//go:build linux package fsutils import ( `os` `reflect` `unsafe` `golang.org/x/sys/unix` `r00t2.io/goutils/bitmask` `r00t2.io/sysutils/paths` ) func GetAttrs(path string) (attrs *FsAttrs, err error) { var f *os.File var evalAttrs FsAttrs var attrVal fsAttr var attrValBit bitmask.MaskBit var reflectVal reflect.Value var field reflect.Value var myPath string = path if err = paths.RealPath(&myPath); err != nil { return } if f, err = os.Open(myPath); err != nil { return } defer f.Close() reflectVal = reflect.ValueOf(&evalAttrs).Elem() if attrVal, err = getAttrs(f); err != nil { return } attrValBit = bitmask.MaskBit(attrVal) for attrNm, attrInt := range AttrNameValueMap { field = reflectVal.FieldByName(attrNm) field.SetBool(attrValBit.HasFlag(bitmask.MaskBit(attrInt))) } attrs = new(FsAttrs) *attrs = evalAttrs return } // getAttrs is the unexported low-level syscall to get attributes. func getAttrs(f *os.File) (attrVal fsAttr, err error) { var u uint var curFlags int // var errNo syscall.Errno /* if _, _, errNo = unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.FS_IOC_GETFLAGS, uintptr(unsafe.Pointer(&curFlags))); errNo != 0 { err = os.NewSyscallError("ioctl: FS_IOC_GETFLAGS", errNo) return } */ if curFlags, err = unix.IoctlGetInt(int(f.Fd()), unix.FS_IOC_GETFLAGS); err != nil { return } u = uint(curFlags) attrVal = fsAttr(u) return } // invertMap returns some handy consts remapping for easier lookups. func invertMap(origMap map[string]fsAttr) (newMap map[fsAttr]string) { if origMap == nil { return } newMap = make(map[fsAttr]string) for k, v := range origMap { newMap[v] = k } return } // setAttrs is the unexported low-level syscall to set attributes. attrs may be OR'd. func setAttrs(f *os.File, attrs fsAttr) (err error) { var curAttrs fsAttr var ab bitmask.MaskBit var errNo unix.Errno var val uint if curAttrs, err = getAttrs(f); err != nil { return } ab = bitmask.MaskBit(curAttrs) if ab.HasFlag(bitmask.MaskBit(attrs)) { return } ab.AddFlag(bitmask.MaskBit(attrs)) val = ab.Value() /* if err = unix.IoctlSetInt(int(f.Fd()), unix.FS_IOC_SETFLAGS, int(ab.Value())); err != nil { return } */ if _, _, errNo = unix.Syscall(unix.SYS_IOCTL, f.Fd(), unix.FS_IOC_SETFLAGS, uintptr(unsafe.Pointer(&val))); errNo != 0 { err = os.NewSyscallError("ioctl: SYS_IOCTL", errNo) return } return } // unsetAttrs is the unexported low-level syscall to remove attributes. attrs may be OR'd. func unsetAttrs(f *os.File, attrs fsAttr) (err error) { var curAttrs fsAttr var ab bitmask.MaskBit if curAttrs, err = getAttrs(f); err != nil { return } ab = bitmask.MaskBit(curAttrs) if !ab.HasFlag(bitmask.MaskBit(attrs)) { return } ab.ClearFlag(bitmask.MaskBit(attrs)) /* if err = unix.IoctlSetInt(int(f.Fd()), unix.FS_IOC_SETFLAGS, int(ab.Value())); err != nil { return } */ return }