Skip to content

Commit

Permalink
fileutils: Use ModeType as the mask for mode checks
Browse files Browse the repository at this point in the history
POSIX provides S_IS*(m) macros to portably interpret the mode type,
but does not define values for each type [1].  Alban pointed out that
st_mode is not a bitfield on Linux [2].  For example, Linux defines
[3]:

  S_IFBLK 060000
  S_IFDIR 040000
  S_IFCHR 020000

So 'm&S_IFCHR == S_IFCHR', for example, would succeed for both
character and block devices.  Go translates the system values to a
platform-agnostic bitfield [4], so the previous approach works on Go.
But it may be confusing for people used to the native non-bitfield
mode, so this commit moves us to an approach that does not rely on
Go's using a bitfield.

I've also dropped the 07000 portion of the previous 07777 mask in
favor of the cross-platform ModePerm mask.  This avoids an internal
magic number, and the sticky, suid, and sgid bits don't make sense for
device nodes.  And I'm using some contants from os instead of their
syscall analogs.  We can't drop the syscall dependency, because we're
still using syscall to construct the Mknod arguments, but with this
commit we're no longer using it to inspect the source file type.

[1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html
[2]: opencontainers/runtime-tools#308 (comment)
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h?h=v4.16#n9
[4]: https://github.com/golang/go/blob/b0d437f866eb8987cde7e6550cacd77876f36d4b/src/os/types.go#L45
  • Loading branch information
wking committed Apr 6, 2018
1 parent 7d4729f commit 8bad3ca
Showing 1 changed file with 8 additions and 8 deletions.
16 changes: 8 additions & 8 deletions fileutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ func CopyFile(source string, dest string) error {

uid := int(st.Uid)
gid := int(st.Gid)
modeType := si.Mode()&os.ModeType

// Handle symlinks
if si.Mode()&os.ModeSymlink != 0 {
if modeType == os.ModeSymlink {
target, err := os.Readlink(source)
if err != nil {
return err
Expand All @@ -35,15 +36,14 @@ func CopyFile(source string, dest string) error {
}

// Handle device files
if st.Mode&syscall.S_IFMT == syscall.S_IFBLK || st.Mode&syscall.S_IFMT == syscall.S_IFCHR {
if modeType == os.ModeDevice {
devMajor := int64(major(uint64(st.Rdev)))
devMinor := int64(minor(uint64(st.Rdev)))
mode := uint32(si.Mode() & 07777)
if st.Mode&syscall.S_IFMT == syscall.S_IFBLK {
mode |= syscall.S_IFBLK
}
if st.Mode&syscall.S_IFMT == syscall.S_IFCHR {
mode := uint32(si.Mode() & os.ModePerm)
if si.Mode()&os.ModeCharDevice != 0 {
mode |= syscall.S_IFCHR
} else {
mode |= syscall.S_IFBLK
}
if err := syscall.Mknod(dest, mode, int(mkdev(devMajor, devMinor))); err != nil {
return err
Expand Down Expand Up @@ -76,7 +76,7 @@ func CopyFile(source string, dest string) error {
}

// Chmod the file
if !(si.Mode()&os.ModeSymlink == os.ModeSymlink) {
if !(modeType == os.ModeSymlink) {
if err := os.Chmod(dest, si.Mode()); err != nil {
return err
}
Expand Down

0 comments on commit 8bad3ca

Please sign in to comment.