aboutsummaryrefslogtreecommitdiff
path: root/filesystem/path.go
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem/path.go')
-rw-r--r--filesystem/path.go83
1 files changed, 60 insertions, 23 deletions
diff --git a/filesystem/path.go b/filesystem/path.go
index d788a6b..8cfb235 100644
--- a/filesystem/path.go
+++ b/filesystem/path.go
@@ -20,18 +20,26 @@
package filesystem
import (
+ "fmt"
"log"
"os"
"path/filepath"
+ "golang.org/x/sys/unix"
+
"github.com/pkg/errors"
)
-// We only check the unix permissions and the sticky bit
-const permMask = os.ModeSticky | os.ModePerm
+// OpenFileOverridingUmask calls os.OpenFile but with the umask overridden so
+// that no permission bits are masked out if the file is created.
+func OpenFileOverridingUmask(name string, flag int, perm os.FileMode) (*os.File, error) {
+ oldMask := unix.Umask(0)
+ defer unix.Umask(oldMask)
+ return os.OpenFile(name, flag, perm)
+}
-// cannonicalizePath turns path into an absolute path without symlinks.
-func cannonicalizePath(path string) (string, error) {
+// canonicalizePath turns path into an absolute path without symlinks.
+func canonicalizePath(path string) (string, error) {
path, err := filepath.Abs(path)
if err != nil {
return "", err
@@ -56,36 +64,65 @@ func loggedStat(name string) (os.FileInfo, error) {
return info, err
}
+// loggedLstat runs os.Lstat (doesn't dereference trailing symlink), but it logs
+// the error if lstat returns any error other than nil or IsNotExist.
+func loggedLstat(name string) (os.FileInfo, error) {
+ info, err := os.Lstat(name)
+ if err != nil && !os.IsNotExist(err) {
+ log.Print(err)
+ }
+ return info, err
+}
+
// isDir returns true if the path exists and is that of a directory.
func isDir(path string) bool {
info, err := loggedStat(path)
return err == nil && info.IsDir()
}
-// isDevice returns true if the path exists and is that of a directory.
-func isDevice(path string) bool {
+// isRegularFile returns true if the path exists and is that of a regular file.
+func isRegularFile(path string) bool {
info, err := loggedStat(path)
- return err == nil && info.Mode()&os.ModeDevice != 0
+ return err == nil && info.Mode().IsRegular()
}
-// isDirCheckPerm returns true if the path exists and is a directory. If the
-// specified permissions and sticky bit of mode do not match the path, and error
-// is logged.
-func isDirCheckPerm(path string, mode os.FileMode) bool {
- info, err := loggedStat(path)
- // Check if directory
- if err != nil || !info.IsDir() {
- return false
+// HaveReadAccessTo returns true if the process has read access to a file or
+// directory, without actually opening it.
+func HaveReadAccessTo(path string) bool {
+ return unix.Access(path, unix.R_OK) == nil
+}
+
+// DeviceNumber represents a combined major:minor device number.
+type DeviceNumber uint64
+
+func (num DeviceNumber) String() string {
+ return fmt.Sprintf("%d:%d", unix.Major(uint64(num)), unix.Minor(uint64(num)))
+}
+
+func newDeviceNumberFromString(str string) (DeviceNumber, error) {
+ var major, minor uint32
+ if count, _ := fmt.Sscanf(str, "%d:%d", &major, &minor); count != 2 {
+ return 0, errors.Errorf("invalid device number string %q", str)
}
- // Check for bad permissions
- if info.Mode()&permMask != mode&permMask {
- log.Printf("directory %s has incorrect permissions", path)
+ return DeviceNumber(unix.Mkdev(major, minor)), nil
+}
+
+// getDeviceNumber returns the device number of the device node at the given
+// path. If there is a symlink at the path, it is dereferenced.
+func getDeviceNumber(path string) (DeviceNumber, error) {
+ var stat unix.Stat_t
+ if err := unix.Stat(path, &stat); err != nil {
+ return 0, err
}
- return true
+ return DeviceNumber(stat.Rdev), nil
}
-// isRegularFile returns true if the path exists and is that of a regular file.
-func isRegularFile(path string) bool {
- info, err := loggedStat(path)
- return err == nil && info.Mode().IsRegular()
+// getNumberOfContainingDevice returns the device number of the filesystem which
+// contains the given file. If the file is a symlink, it is not dereferenced.
+func getNumberOfContainingDevice(path string) (DeviceNumber, error) {
+ var stat unix.Stat_t
+ if err := unix.Lstat(path, &stat); err != nil {
+ return 0, err
+ }
+ return DeviceNumber(stat.Dev), nil
}