eefe02afaf
ADDED: * fsutils: better/additional fsattrs functionality * paths: highly filterable filesystem searching
135 lines
2.6 KiB
Go
135 lines
2.6 KiB
Go
//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
|
|
}
|
|
|
|
// 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
|
|
}
|