Files
debos/filesystem.go
Arnaud Rebillout 0f2b35e7af Abort on various error cases that were silently ignored
Various filesystem operations here and there are done without checking
the return value, so when it fails nobody knows and the user waste his
time understanding what's going on. Checking return values is useful.

Signed-off-by: Arnaud Rebillout <arnaud.rebillout@collabora.com>
2018-06-14 10:30:43 +02:00

115 lines
2.2 KiB
Go

package debos
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strings"
)
func CleanPathAt(path, at string) string {
if filepath.IsAbs(path) {
return filepath.Clean(path)
}
return filepath.Join(at, path)
}
func CleanPath(path string) string {
cwd, _ := os.Getwd()
return CleanPathAt(path, cwd)
}
func CopyFile(src, dst string, mode os.FileMode) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
tmp, err := ioutil.TempFile(filepath.Dir(dst), "")
if err != nil {
return err
}
_, err = io.Copy(tmp, in)
if err != nil {
tmp.Close()
os.Remove(tmp.Name())
return err
}
if err = tmp.Close(); err != nil {
os.Remove(tmp.Name())
return err
}
if err = os.Chmod(tmp.Name(), mode); err != nil {
os.Remove(tmp.Name())
return err
}
if err = os.Rename(tmp.Name(), dst); err != nil {
os.Remove(tmp.Name())
return err
}
return nil
}
func CopyTree(sourcetree, desttree string) error {
fmt.Printf("Overlaying %s on %s\n", sourcetree, desttree)
walker := func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
suffix, _ := filepath.Rel(sourcetree, p)
target := path.Join(desttree, suffix)
switch info.Mode() & os.ModeType {
case 0:
err := CopyFile(p, target, info.Mode())
if err != nil {
log.Panicf("Failed to copy file %s: %v", p, err)
}
case os.ModeDir:
os.Mkdir(target, info.Mode())
case os.ModeSymlink:
link, err := os.Readlink(p)
if err != nil {
log.Panicf("Failed to read symlink %s: %v", suffix, err)
}
os.Symlink(link, target)
default:
log.Panicf("Not handled /%s %v", suffix, info.Mode())
}
return nil
}
return filepath.Walk(sourcetree, walker)
}
func RealPath(path string) (string, error) {
p, err := filepath.EvalSymlinks(path)
if err != nil {
return "", err
}
return filepath.Abs(p)
}
func RestrictedPath(prefix, dest string) (string, error) {
var err error
destination := path.Join(prefix, dest)
destination, err = filepath.Abs(destination)
if err != nil {
return "", err
}
if !strings.HasPrefix(destination, prefix) {
return "", fmt.Errorf("The resulting path points outside of prefix '%s': '%s'\n", prefix, destination)
}
return destination, nil
}