// Equal determines if two network handles refer to the same network // namespace. This is done by comparing the device and inode that the // file descripors point to. func (ns NsHandle) Equal(other NsHandle) bool { var s1, s2 syscall.Stat_t if err := syscall.Fstat(int(ns), &s1); err != nil { return false } if err := syscall.Fstat(int(other), &s2); err != nil { return false } return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino) }
func getHandle(fn string) (*handle, error) { f, err := os.OpenFile(fn, O_PATH, 0) if err != nil { return nil, errors.Wrapf(err, "failed to open %v with O_PATH", fn) } var stat syscall.Stat_t if err := syscall.Fstat(int(f.Fd()), &stat); err != nil { f.Close() return nil, errors.Wrapf(err, "failed to stat handle %v", f.Fd()) } h := &handle{ f: f, name: fn, dev: stat.Dev, ino: stat.Ino, } // check /proc just in case if _, err := os.Stat(h.procPath()); err != nil { f.Close() return nil, errors.Wrapf(err, "couldn't stat %v", h.procPath()) } return h, nil }
func NewNetNSProbe(g *graph.Graph, n *graph.Node, runPath ...string) (*NetNSProbe, error) { if uid := os.Geteuid(); uid != 0 { return nil, errors.New("NetNS probe has to be run as root") } path := "/var/run/netns" if len(runPath) > 0 && runPath[0] != "" { path = runPath[0] } rootNs, err := netns.Get() if err != nil { return nil, errors.New("Failed to get root namespace") } defer rootNs.Close() var stats syscall.Stat_t if err := syscall.Fstat(int(rootNs), &stats); err != nil { return nil, errors.New("Failed to stat root namespace") } return &NetNSProbe{ Graph: g, Root: n, nsnlProbes: make(map[string]*NetNsNetLinkTopoUpdater), pathToNetNS: make(map[string]*NetNs), runPath: path, rootNsDev: stats.Dev, }, nil }
func (h *Handle) getFileSize() (uint64, error) { var stat syscall.Stat_t if err := syscall.Fstat(int(h.file.Fd()), &stat); err != nil { return 0, osErrorToFuseError(err) } return uint64(stat.Size), nil }
func getBlkSize(f *os.File) (uint32, error) { var stat syscall.Stat_t if err := syscall.Fstat(int(f.Fd()), &stat); err != nil { return 0, osErrorToFuseError(err) } return uint32(stat.Blksize), nil }
// String shows the file descriptor number and its dev and inode. func (ns NsHandle) String() string { var s syscall.Stat_t if err := syscall.Fstat(int(ns), &s); err != nil { return fmt.Sprintf("NS(%d: unknown)", ns) } return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino) }
// fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user. // The ownership needs to match because it is created outside of the container and needs to be // localized. func fixStdioPermissions(u *user.ExecUser) error { var null syscall.Stat_t if err := syscall.Stat("/dev/null", &null); err != nil { return err } for _, fd := range []uintptr{ os.Stdin.Fd(), os.Stderr.Fd(), os.Stdout.Fd(), } { var s syscall.Stat_t if err := syscall.Fstat(int(fd), &s); err != nil { return err } // skip chown of /dev/null if it was used as one of the STDIO fds. if s.Rdev == null.Rdev { continue } // Operation not permitted error on unprivileged container //if err := syscall.Fchown(int(fd), u.Uid, u.Gid); err != nil { // return err //} } return nil }
// NewLock opens a new lock on a file without acquisition func NewLock(path string, lockType LockType) (*FileLock, error) { l := &FileLock{path: path, fd: -1} mode := syscall.O_RDONLY | syscall.O_CLOEXEC if lockType == Dir { mode |= syscall.O_DIRECTORY } lfd, err := syscall.Open(l.path, mode, 0) if err != nil { if err == syscall.ENOENT { err = ErrNotExist } else if err == syscall.EACCES { err = ErrPermission } return nil, err } l.fd = lfd var stat syscall.Stat_t err = syscall.Fstat(lfd, &stat) if err != nil { return nil, err } // Check if the file is a regular file if lockType == RegFile && !(stat.Mode&syscall.S_IFMT == syscall.S_IFREG) { return nil, ErrNotRegular } return l, nil }
// fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user. // The ownership needs to match because it is created outside of the container and needs to be // localized. func fixStdioPermissions(u *user.ExecUser) error { var null syscall.Stat_t if err := syscall.Stat("/dev/null", &null); err != nil { return err } for _, fd := range []uintptr{ os.Stdin.Fd(), os.Stderr.Fd(), os.Stdout.Fd(), } { var s syscall.Stat_t if err := syscall.Fstat(int(fd), &s); err != nil { return err } // Skip chown of /dev/null if it was used as one of the STDIO fds. if s.Rdev == null.Rdev { continue } // We only change the uid owner (as it is possible for the mount to // prefer a different gid, and there's no reason for us to change it). // The reason why we don't just leave the default uid=X mount setup is // that users expect to be able to actually use their console. Without // this code, you couldn't effectively run as a non-root user inside a // container and also have a console set up. if err := syscall.Fchown(int(fd), u.Uid, int(s.Gid)); err != nil { return err } } return nil }
func touch(filename string, nacc, nmod int64) (errcnt int) { var st syscall.Stat_t var ut syscall.Utimbuf if e := syscall.Stat(filename, &st); e != 0 { if e == syscall.ENOENT { if *cflag { errcnt++ return } var fd int defer syscall.Close(fd) if fd, e = syscall.Creat(filename, 0666); e != 0 { fmt.Fprintf(os.Stderr, "touch: can not create %s\n", filename) errcnt += 1 return } if e = syscall.Fstat(fd, &st); e != 0 { fmt.Fprintf(os.Stderr, "touch: can't stat %s\n", filename) errcnt += 1 return } } else { fmt.Fprintf(os.Stderr, "touch: can't stat %s\n", filename) errcnt += 1 return } } if *aflag { ut.Actime = nacc } else { ut.Actime = st.Atim.Sec } if *mflag { ut.Modtime = nmod } else { ut.Modtime = st.Mtim.Sec } if nulltime { if e := syscall.Utime(filename, nil); e != 0 { fmt.Fprintf(os.Stderr, "touch: unable to touch %s", filename) errcnt += 1 } } else { if e := syscall.Utime(filename, &ut); e != 0 { fmt.Fprintf(os.Stderr, "touch: unable to touch %s", filename) errcnt += 1 } } return }
// Stat returns the Dir structure describing file. // It returns the Dir and an error, if any. func (file *File) Stat() (dir *Dir, err Error) { var stat syscall.Stat_t e := syscall.Fstat(file.fd, &stat) if e != 0 { return nil, &PathError{"stat", file.name, Errno(e)} } return dirFromStat(file.name, new(Dir), &stat, &stat), nil }
// isatty reports whether fd is a tty. // Actually it reports whether fd is a character device, which is close enough. func isatty(fd int) bool { var st syscall.Stat_t err := syscall.Fstat(fd, &st) if err != nil { return false } return st.Mode&syscall.S_IFMT == syscall.S_IFCHR }
// Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (f *File) Stat() (fi FileInfo, err error) { var stat syscall.Stat_t err = syscall.Fstat(f.fd, &stat) if err != nil { return nil, &PathError{"stat", f.name, err} } return fileInfoFromStat(&stat, f.name), nil }
// Stat returns the FileInfo structure describing file. // It returns the FileInfo and an error, if any. func (file *File) Stat() (fi *FileInfo, err Error) { var stat syscall.Stat_t e := syscall.Fstat(file.fd, &stat) if e != 0 { return nil, &PathError{"stat", file.name, Errno(e)} } return fileInfoFromStat(file.name, new(FileInfo), &stat, &stat), nil }
func open(path string) (*os.File, error) { var f *os.File var err error for { f, err = os.OpenFile(path, syscall.O_RDWR|syscall.O_CREAT|syscall.O_EXCL, 0644) if err != nil { if !os.IsExist(err) { return nil, err } f, err = os.OpenFile(path, syscall.O_RDWR, 0644) if err != nil { if os.IsNotExist(err) { continue } return nil, err } } err = syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &syscall.Flock_t{ Type: syscall.F_WRLCK, }) if err != nil { f.Close() return nil, err } st1 := syscall.Stat_t{} err = syscall.Fstat(int(f.Fd()), &st1) // ffs if err != nil { f.Close() return nil, err } st2 := syscall.Stat_t{} err = syscall.Stat(path, &st2) if err != nil { f.Close() if os.IsNotExist(err) { continue } return nil, err } if st1.Ino != st2.Ino { f.Close() continue } break } return f, nil }
// Du returns the disk usage of the file "fd" points to, in bytes. // Same as "du --block-size=1". func Du(t *testing.T, fd int) (nBytes int64) { var st syscall.Stat_t err := syscall.Fstat(fd, &st) if err != nil { t.Fatal(err) } // st.Blocks = number of 512-byte blocks return st.Blocks * 512 }
func (f *LoopbackFile) GetAttr(a *Attr) Status { st := syscall.Stat_t{} err := syscall.Fstat(int(f.File.Fd()), &st) if err != nil { return ToStatus(err) } a.FromStat(&st) return OK }
func ext۰syscall۰Fstat(fr *Frame, args []Value) Value { // func Fstat(fd int, stat *Stat_t) (err error) fd := args[0].(int) stat := (*args[1].(*Value)).(Structure) var st syscall.Stat_t err := syscall.Fstat(fd, &st) fillStat(&st, stat) return wrapError(err) }
func ext۰syscall۰Fstat(fn *ssa.Function, args []value) value { // func Fstat(fd int, stat *Stat_t) (err error) fd := args[0].(int) stat := (*args[1].(*value)).(structure) var st syscall.Stat_t err := syscall.Fstat(fd, &st) fillStat(&st, stat) return wrapError(err) }
func (me *LoopbackFile) GetAttr() (*Attr, Status) { st := syscall.Stat_t{} err := syscall.Fstat(int(me.File.Fd()), &st) if err != nil { return nil, ToStatus(err) } a := &Attr{} a.FromStat(&st) return a, OK }
// UniqueId returns a string which uniquely identifies the namespace // associated with the network handle. func (ns NsHandle) UniqueId() string { var s syscall.Stat_t if ns == -1 { return "NS(none)" } if err := syscall.Fstat(int(ns), &s); err != nil { return "NS(unknown)" } return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino) }
func (f *AzukiFile) GetAttr(a *fuse.Attr) fuse.Status { st := syscall.Stat_t{} f.lock.Lock() err := syscall.Fstat(int(f.File.Fd()), &st) f.lock.Unlock() if err != nil { return fuse.ToStatus(err) } a.FromStat(&st) return fuse.OK }
func fstat(u U, a []uint64) uint64 { fd, buf := int(a[0]), a[1] var stat syscall.Stat_t if err := syscall.Fstat(fd, &stat); err != nil { return errno(err) } if err := struc.Pack(u.Mem().StreamAt(buf), &stat); err != nil { panic(err) } return 0 }
func (k *PosixKernel) Fstat(fd co.Fd, buf co.Obuf) uint64 { var stat syscall.Stat_t if err := syscall.Fstat(int(fd), &stat); err != nil { return Errno(err) } targetStat := NewTargetStat(&stat, k.U.OS(), k.U.Bits()) if err := buf.Pack(targetStat); err != nil { panic(err) } return 0 }
func NewFile(fd *os.File, writeOnly bool, cfs *cryptfs.CryptFS) nodefs.File { var st syscall.Stat_t syscall.Fstat(int(fd.Fd()), &st) return &file{ fd: fd, writeOnly: writeOnly, cfs: cfs, ino: st.Ino, } }
// Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (f *File) Stat() (FileInfo, error) { if f == nil { return nil, ErrInvalid } var stat syscall.Stat_t err := syscall.Fstat(f.fd, &stat) if err != nil { return nil, &PathError{"stat", f.name, err} } return fileInfoFromStat(&stat, f.name), nil }
// Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (f *File) Stat() (FileInfo, error) { if f == nil { return nil, ErrInvalid } var fs fileStat err := syscall.Fstat(f.fd, &fs.sys) if err != nil { return nil, &PathError{"stat", f.name, err} } fillFileStatFromSys(&fs, f.name) return &fs, nil }
func isCtty(fd int) bool { // One would hope there was a simple way to figure out what our controlling // tty is. Or at least check if stdin is coming from our controlling tty (as // opposed to just any old terminal). Alas, the infuriating morass that // passes for job control provides no such ability. Of no help: // stat(/dev/tty), readlink(/dev/fd/0), open(/dev/stdin), open(/dev/tty), // cat(/proc/self/fdinfo/0), stat(/proc/self/fd/0), ioctl, tty_ioctl, TIOC*, // anything to do with sid, pgrp, pgid, /dev/console, the tty command, $TTY, // $SSH_TTY. Since I am on a mission, I delved into the source for /bin/ps // to discover /proc/self/stat contains the major/minor numbers for the // controlling tty. And stat(stdin).Rdev provides the same info. If they // differ, I'm going to conclude -- oh so tentatively -- that stdin is NOT // our controlling tty. If they match, or anything goes wrong, we will // assume that stdin, if it is a terminal, is our ctty. if !terminal.IsTerminal(fd) { return false } var s syscall.Stat_t err := syscall.Fstat(fd, &s) if err != nil { fmt.Fprintf(noise, "[warning: fstat(%d) failed: %v]\n", fd, err) return true } name := "/proc/self/stat" f, err := os.Open(name) if err != nil { fmt.Fprintf(noise, "[warning: open(%q) failed: %v]\n", name, err) return true } b, err := ioutil.ReadAll(f) if err != nil { fmt.Fprintf(noise, "[warning: read(%q) failed: %v]\n", name, err) return true } a := strings.Split(string(b), " ") tty_nr := 6 if len(a) <= tty_nr { fmt.Fprintf(noise, "[warning: read(%q) borked: only %d fields]\n", name, len(a)) return true } ctty, err := strconv.Atoi(a[tty_nr]) if err != nil { fmt.Fprintf(noise, "[warning: read(%q) borked: tty_nr = %v]\n", name, a[tty_nr]) return true } if uint64(ctty) != s.Rdev { fmt.Fprintf(noise, "[warning: stdin is a tty, but not ctty]\n") return false } return true }
// If stdin, stdout, and/or stderr are pointing to `/dev/null` in the parent's rootfs // this method will make them point to `/dev/null` in this container's rootfs. This // needs to be called after we chroot/pivot into the container's rootfs so that any // symlinks are resolved locally. func reOpenDevNull(rootfs string) error { var stat, devNullStat syscall.Stat_t file, err := os.Open("/dev/null") if err != nil { return fmt.Errorf("Failed to open /dev/null - %s", err) } defer file.Close() if err := syscall.Fstat(int(file.Fd()), &devNullStat); err != nil { return err } for fd := 0; fd < 3; fd++ { if err := syscall.Fstat(fd, &stat); err != nil { return err } if stat.Rdev == devNullStat.Rdev { // Close and re-open the fd. if err := syscall.Dup3(int(file.Fd()), fd, 0); err != nil { return err } } } return nil }
// Is stdin, stdout or stderr were to be pointing to '/dev/null', // this method will make them point to '/dev/null' from within this namespace. func reOpenDevNull(rootfs string) error { var stat, devNullStat syscall.Stat_t file, err := os.Open(filepath.Join(rootfs, "/dev/null")) if err != nil { return fmt.Errorf("Failed to open /dev/null - %s", err) } defer file.Close() if err = syscall.Fstat(int(file.Fd()), &devNullStat); err != nil { return fmt.Errorf("Failed to stat /dev/null - %s", err) } for fd := 0; fd < 3; fd++ { if err = syscall.Fstat(fd, &stat); err != nil { return fmt.Errorf("Failed to stat fd %d - %s", fd, err) } if stat.Rdev == devNullStat.Rdev { // Close and re-open the fd. if err = syscall.Dup2(int(file.Fd()), fd); err != nil { return fmt.Errorf("Failed to dup fd %d to fd %d - %s", file.Fd(), fd, err) } } } return nil }