ReadFileFlags on linux minor fix

Add ignoring EINTR to syscall, set O_NOATIME on open, ignore
ENOTTY error (unsupported ioctl) to avoid massive spam for
non-exceptional failure on nonsupporting file systems
This commit is contained in:
2023-10-06 15:26:48 -05:00
parent 95ba772e2d
commit 9046b12f92
2 changed files with 37 additions and 16 deletions

View File

@@ -1,13 +1,13 @@
# Dupluxe # Dupluxe
A Duplicacy derivative with improved support for preserving state on UNIX like systems. Produces snapshots compatible with Duplicacy. An experimental Duplicacy derivative with improved support for preserving state on UNIX like systems. Produces snapshots compatible with Duplicacy.
NOTE: This project/repository is not affiliated with nor endorsed by Duplicacy, Acrosync or their associated rights holders. It is developed and distributed in accordance with the associated LICENSE. Commercial use may require purchase of a license from Acrosync. NOTE: This project/repository is not affiliated with nor endorsed by Duplicacy, Acrosync or their associated rights holders. This project is open source but is not free/libre software. It is developed and distributed in accordance with the associated LICENSE. Commercial use may require purchase of a license from Acrosync, please contact them if you have any doubts.
## Added Features ## Added Features
* Support for hard links. Hard links are tracked during local file listing. All linked entries will reuse the same chunk data, so this can give a time and space saving benefit as hard-linked files only need to be packed once. Hard links are supported to everything (regular files, symlinks, special files) except directories. * Support for hard links. Hard links are tracked during local file listing. All linked entries will reuse the same chunk data, so this can give a time and space saving benefit as hard-linked files only need to be packed once. Hard links are supported to everything (regular files, symlinks, special files) except directories.
* File flags, that is chflags(1) on BSD/Darwin, and ioctl_iflags(2) on Linux. The primary use case is to preserve iflags used by btrfs for no-COW and compression. * Optional File flags, that is chflags(1) on BSD/Darwin, and ioctl_iflags(2) on Linux. The primary use case is to preserve iflags used by btrfs for no-COW and compression.
* Special files (character/block devices, FIFOs, and sockets) are preserved along with associated metadata. * Optional Special files (character/block devices, FIFOs, and sockets) are preserved along with associated metadata.
## Assorted Changes ## Assorted Changes
* The S3 backend uses the newer ListObjectsV2 interface originally because of a bug with some providers with the old, obsolete interface, but now because this API is considerably faster on a number of providers tested. * The S3 backend uses the newer ListObjectsV2 interface originally because of a bug with some providers with the old, obsolete interface, but now because this API is considerably faster on a number of providers tested.

View File

@@ -33,9 +33,6 @@ const (
linux_FS_NOCOW_FL = 0x00800000 /* Do not cow file */ linux_FS_NOCOW_FL = 0x00800000 /* Do not cow file */
linux_FS_PROJINHERIT_FL = 0x20000000 /* Create with parents projid */ linux_FS_PROJINHERIT_FL = 0x20000000 /* Create with parents projid */
linux_FS_IOC_GETFLAGS uintptr = 0x80086601
linux_FS_IOC_SETFLAGS uintptr = 0x40086602
linuxIocFlagsFileEarly = linux_FS_SECRM_FL | linux_FS_UNRM_FL | linux_FS_COMPR_FL | linux_FS_NODUMP_FL | linux_FS_NOATIME_FL | linux_FS_NOCOMP_FL | linux_FS_JOURNAL_DATA_FL | linux_FS_NOTAIL_FL | linux_FS_NOCOW_FL linuxIocFlagsFileEarly = linux_FS_SECRM_FL | linux_FS_UNRM_FL | linux_FS_COMPR_FL | linux_FS_NODUMP_FL | linux_FS_NOATIME_FL | linux_FS_NOCOMP_FL | linux_FS_JOURNAL_DATA_FL | linux_FS_NOTAIL_FL | linux_FS_NOCOW_FL
linuxIocFlagsDirEarly = linux_FS_TOPDIR_FL | linux_FS_PROJINHERIT_FL linuxIocFlagsDirEarly = linux_FS_TOPDIR_FL | linux_FS_PROJINHERIT_FL
linuxIocFlagsLate = linux_FS_SYNC_FL | linux_FS_IMMUTABLE_FL | linux_FS_APPEND_FL | linux_FS_DIRSYNC_FL linuxIocFlagsLate = linux_FS_SYNC_FL | linux_FS_IMMUTABLE_FL | linux_FS_APPEND_FL | linux_FS_DIRSYNC_FL
@@ -43,13 +40,32 @@ const (
linuxFileFlagsKey = "\x00lf" linuxFileFlagsKey = "\x00lf"
) )
func ioctl(f *os.File, request uintptr, attrp *uint32) error { var (
argp := uintptr(unsafe.Pointer(attrp)) errENOTTY error = unix.ENOTTY
)
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), request, argp); errno != 0 { func ignoringEINTR(fn func() error) (err error) {
return os.NewSyscallError("ioctl", errno) for {
err = fn()
if err != unix.EINTR {
break
}
} }
return nil return err
}
func ioctl(f *os.File, request uintptr, attrp *uint32) error {
return ignoringEINTR(func() error {
argp := uintptr(unsafe.Pointer(attrp))
_, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), request, argp)
if errno == 0 {
return nil
} else if errno == unix.ENOTTY {
return errENOTTY
}
return errno
})
} }
func (entry *Entry) ReadAttributes(fullPath string, fi os.FileInfo) error { func (entry *Entry) ReadAttributes(fullPath string, fi os.FileInfo) error {
@@ -75,20 +91,25 @@ func (entry *Entry) ReadAttributes(fullPath string, fi os.FileInfo) error {
} }
func (entry *Entry) ReadFileFlags(fullPath string, fileInfo os.FileInfo) error { func (entry *Entry) ReadFileFlags(fullPath string, fileInfo os.FileInfo) error {
// the linux file flags interface is quite depressing. The half assed attempt at statx
// doesn't even cover the flags we're interested in
if !(entry.IsFile() || entry.IsDir()) { if !(entry.IsFile() || entry.IsDir()) {
return nil return nil
} }
f, err := os.OpenFile(fullPath, os.O_RDONLY|unix.O_NOFOLLOW, 0) f, err := os.OpenFile(fullPath, os.O_RDONLY|unix.O_NOATIME|unix.O_NOFOLLOW, 0)
if err != nil { if err != nil {
return err return err
} }
var flags uint32 var flags uint32
err = ioctl(f, linux_FS_IOC_GETFLAGS, &flags) err = ioctl(f, unix.FS_IOC_GETFLAGS, &flags)
f.Close() f.Close()
if err != nil { if err != nil {
if err == unix.ENOTTY {
return nil
}
return err return err
} }
@@ -154,7 +175,7 @@ func (entry *Entry) RestoreEarlyDirFlags(fullPath string, mask uint32) error {
if err != nil { if err != nil {
return err return err
} }
err = ioctl(f, linux_FS_IOC_SETFLAGS, &flags) err = ioctl(f, unix.FS_IOC_SETFLAGS, &flags)
f.Close() f.Close()
if err != nil { if err != nil {
return fmt.Errorf("Set flags 0x%.8x failed: %w", flags, err) return fmt.Errorf("Set flags 0x%.8x failed: %w", flags, err)
@@ -174,7 +195,7 @@ func (entry *Entry) RestoreEarlyFileFlags(f *os.File, mask uint32) error {
} }
if flags != 0 { if flags != 0 {
err := ioctl(f, linux_FS_IOC_SETFLAGS, &flags) err := ioctl(f, unix.FS_IOC_SETFLAGS, &flags)
if err != nil { if err != nil {
return fmt.Errorf("Set flags 0x%.8x failed: %w", flags, err) return fmt.Errorf("Set flags 0x%.8x failed: %w", flags, err)
} }