netboot/tftp/handlers.go
2016-03-05 15:14:52 -08:00

59 lines
1.7 KiB
Go

// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tftp
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"path/filepath"
)
// FilesystemHandler returns a Handler that serves files in root.
func FilesystemHandler(root string) (Handler, error) {
root, err := filepath.Abs(root)
if err != nil {
return nil, err
}
root = filepath.ToSlash(root)
return func(path string, addr net.Addr) (io.ReadCloser, error) {
// Join with a root, which gets rid of directory traversal
// attempts. Then we join that canonicalized path with the
// actual root, which resolves to the actual on-disk file to
// serve.
path = filepath.Join("/", path)
path = filepath.FromSlash(filepath.Join(root, path))
st, err := os.Stat(path)
if err != nil {
return nil, err
}
if !st.Mode().IsRegular() {
return nil, fmt.Errorf("requested path %q is not a file", path)
}
return os.Open(path)
}, nil
}
// ConstantHandler returns a Handler that serves bs for all requested paths.
func ConstantHandler(bs []byte) Handler {
return func(path string, addr net.Addr) (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewBuffer(bs)), nil
}
}