go_sysutils/fsutils/funcs_linux.go
brent saner eefe02afaf
v1.11.0
ADDED:
* fsutils: better/additional fsattrs functionality
* paths: highly filterable filesystem searching
2024-11-16 01:28:24 -05:00

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
}