mirror of
https://github.com/jkl1337/duplicacy.git
synced 2026-01-02 11:44:45 -06:00
Fix and reorganize for build for FreeBSD
- the xattr handling of namespaces is different on BSD with the xattr package, the user namespace is implicit - Don't backup/exclude files with flag nodump on BSD/Darwin
This commit is contained in:
@@ -608,10 +608,6 @@ func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo, setO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Attributes != nil && len(*entry.Attributes) > 0 {
|
|
||||||
entry.SetAttributesToFile(fullPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only set the time if the file is not a symlink
|
// Only set the time if the file is not a symlink
|
||||||
if !entry.IsLink() && (*fileInfo).ModTime().Unix() != entry.Time {
|
if !entry.IsLink() && (*fileInfo).ModTime().Unix() != entry.Time {
|
||||||
modifiedTime := time.Unix(entry.Time, 0)
|
modifiedTime := time.Unix(entry.Time, 0)
|
||||||
@@ -622,6 +618,10 @@ func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo, setO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if entry.Attributes != nil && len(*entry.Attributes) > 0 {
|
||||||
|
entry.SetAttributesToFile(fullPath)
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,10 +242,12 @@ func TestEntryExcludeByAttribute(t *testing.T) {
|
|||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
excludeAttrName = "com.apple.metadata:com_apple_backup_excludeItem"
|
excludeAttrName = "com.apple.metadata:com_apple_backup_excludeItem"
|
||||||
excludeAttrValue = []byte("com.apple.backupd")
|
excludeAttrValue = []byte("com.apple.backupd")
|
||||||
} else if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" || runtime.GOOS == "solaris" {
|
} else if runtime.GOOS == "linux" {
|
||||||
excludeAttrName = "user.duplicacy_exclude"
|
excludeAttrName = "user.duplicacy_exclude"
|
||||||
|
} else if runtime.GOOS == "freebsd" || runtime.GOOS == "netbsd" {
|
||||||
|
excludeAttrName = "duplicacy_exclude"
|
||||||
} else {
|
} else {
|
||||||
t.Skip("skipping test, not darwin, linux, freebsd, netbsd, or solaris")
|
t.Skip("skipping test, not darwin, linux, freebsd, or netbsd")
|
||||||
}
|
}
|
||||||
|
|
||||||
testDir := filepath.Join(os.TempDir(), "duplicacy_test")
|
testDir := filepath.Join(os.TempDir(), "duplicacy_test")
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
// Copyright (c) Acrosync LLC. All rights reserved.
|
|
||||||
// Free for personal use and commercial trial
|
|
||||||
// Commercial use requires per-user licenses available from https://duplicacy.com
|
|
||||||
|
|
||||||
//go:build freebsd || netbsd || darwin
|
|
||||||
// +build freebsd netbsd darwin
|
|
||||||
|
|
||||||
package duplicacy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/pkg/xattr"
|
|
||||||
)
|
|
||||||
|
|
||||||
const bsdFileFlagsKey = "\x00bf"
|
|
||||||
|
|
||||||
func (entry *Entry) ReadAttributes(top string) {
|
|
||||||
fullPath := filepath.Join(top, entry.Path)
|
|
||||||
fileInfo, err := os.Lstat(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !entry.IsSpecial() {
|
|
||||||
attributes, _ := xattr.LList(fullPath)
|
|
||||||
if len(attributes) > 0 {
|
|
||||||
entry.Attributes = &map[string][]byte{}
|
|
||||||
for _, name := range attributes {
|
|
||||||
attribute, err := xattr.LGet(fullPath, name)
|
|
||||||
if err == nil {
|
|
||||||
(*entry.Attributes)[name] = attribute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := entry.readFileFlags(fileInfo); err != nil {
|
|
||||||
LOG_INFO("ATTR_BACKUP", "Could not backup flags for file %s: %v", fullPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) SetAttributesToFile(fullPath string) {
|
|
||||||
if !entry.IsSpecial() {
|
|
||||||
names, _ := xattr.LList(fullPath)
|
|
||||||
for _, name := range names {
|
|
||||||
newAttribute, found := (*entry.Attributes)[name]
|
|
||||||
if found {
|
|
||||||
oldAttribute, _ := xattr.LGet(fullPath, name)
|
|
||||||
if !bytes.Equal(oldAttribute, newAttribute) {
|
|
||||||
xattr.LSet(fullPath, name, newAttribute)
|
|
||||||
}
|
|
||||||
delete(*entry.Attributes, name)
|
|
||||||
} else {
|
|
||||||
xattr.LRemove(fullPath, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, attribute := range *entry.Attributes {
|
|
||||||
if len(name) > 0 && name[0] == '\x00' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
xattr.LSet(fullPath, name, attribute)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := entry.restoreLateFileFlags(fullPath); err != nil {
|
|
||||||
LOG_DEBUG("ATTR_RESTORE", "Could not restore flags for file %s: %v", fullPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) readFileFlags(fileInfo os.FileInfo) error {
|
|
||||||
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
|
|
||||||
if ok && stat.Flags != 0 {
|
|
||||||
if entry.Attributes == nil {
|
|
||||||
entry.Attributes = &map[string][]byte{}
|
|
||||||
}
|
|
||||||
v := make([]byte, 4)
|
|
||||||
binary.LittleEndian.PutUint32(v, stat.Flags)
|
|
||||||
(*entry.Attributes)[bsdFileFlagsKey] = v
|
|
||||||
LOG_DEBUG("ATTR_READ", "Read flags 0x%x for %s", stat.Flags, entry.Path)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) RestoreEarlyFileFlags(f *os.File) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
|
||||||
mode := entry.Mode & uint32(fileModeMask)
|
|
||||||
|
|
||||||
if entry.Mode&uint32(os.ModeNamedPipe) != 0 {
|
|
||||||
mode |= syscall.S_IFIFO
|
|
||||||
} else if entry.Mode&uint32(os.ModeCharDevice) != 0 {
|
|
||||||
mode |= syscall.S_IFCHR
|
|
||||||
} else if entry.Mode&uint32(os.ModeDevice) != 0 {
|
|
||||||
mode |= syscall.S_IFBLK
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return syscall.Mknod(fullPath, mode, int(entry.GetRdev()))
|
|
||||||
}
|
|
||||||
@@ -5,22 +5,109 @@
|
|||||||
package duplicacy
|
package duplicacy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/pkg/xattr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const darwin_UF_NODUMP = 0x1
|
||||||
|
|
||||||
|
const darwinFileFlagsKey = "\x00bf"
|
||||||
|
|
||||||
func excludedByAttribute(attributes map[string][]byte) bool {
|
func excludedByAttribute(attributes map[string][]byte) bool {
|
||||||
value, ok := attributes["com.apple.metadata:com_apple_backup_excludeItem"]
|
value, ok := attributes["com.apple.metadata:com_apple_backup_excludeItem"]
|
||||||
return ok && strings.Contains(string(value), "com.apple.backupd")
|
excluded := ok && strings.Contains(string(value), "com.apple.backupd")
|
||||||
|
if !excluded {
|
||||||
|
value, ok := attributes[darwinFileFlagsKey]
|
||||||
|
excluded = ok && (binary.LittleEndian.Uint32(value) & darwin_UF_NODUMP) != 0
|
||||||
|
}
|
||||||
|
return excluded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) ReadAttributes(top string) {
|
||||||
|
fullPath := filepath.Join(top, entry.Path)
|
||||||
|
fileInfo, err := os.Lstat(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !entry.IsSpecial() {
|
||||||
|
attributes, _ := xattr.LList(fullPath)
|
||||||
|
if len(attributes) > 0 {
|
||||||
|
entry.Attributes = &map[string][]byte{}
|
||||||
|
for _, name := range attributes {
|
||||||
|
attribute, err := xattr.LGet(fullPath, name)
|
||||||
|
if err == nil {
|
||||||
|
(*entry.Attributes)[name] = attribute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := entry.readFileFlags(fileInfo); err != nil {
|
||||||
|
LOG_INFO("ATTR_BACKUP", "Could not backup flags for file %s: %v", fullPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) SetAttributesToFile(fullPath string) {
|
||||||
|
if !entry.IsSpecial() {
|
||||||
|
names, _ := xattr.LList(fullPath)
|
||||||
|
for _, name := range names {
|
||||||
|
newAttribute, found := (*entry.Attributes)[name]
|
||||||
|
if found {
|
||||||
|
oldAttribute, _ := xattr.LGet(fullPath, name)
|
||||||
|
if !bytes.Equal(oldAttribute, newAttribute) {
|
||||||
|
xattr.LSet(fullPath, name, newAttribute)
|
||||||
|
}
|
||||||
|
delete(*entry.Attributes, name)
|
||||||
|
} else {
|
||||||
|
xattr.LRemove(fullPath, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, attribute := range *entry.Attributes {
|
||||||
|
if len(name) > 0 && name[0] == '\x00' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
xattr.LSet(fullPath, name, attribute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := entry.restoreLateFileFlags(fullPath); err != nil {
|
||||||
|
LOG_DEBUG("ATTR_RESTORE", "Could not restore flags for file %s: %v", fullPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreEarlyFileFlags(f *os.File) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) readFileFlags(fileInfo os.FileInfo) error {
|
||||||
|
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
|
||||||
|
if ok && stat.Flags != 0 {
|
||||||
|
if entry.Attributes == nil {
|
||||||
|
entry.Attributes = &map[string][]byte{}
|
||||||
|
}
|
||||||
|
v := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(v, stat.Flags)
|
||||||
|
(*entry.Attributes)[darwinFileFlagsKey] = v
|
||||||
|
LOG_DEBUG("ATTR_READ", "Read flags 0x%x for %s", stat.Flags, entry.Path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) restoreLateFileFlags(path string) error {
|
func (entry *Entry) restoreLateFileFlags(path string) error {
|
||||||
if entry.Attributes == nil {
|
if entry.Attributes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if v, have := (*entry.Attributes)[bsdFileFlagsKey]; have {
|
if v, have := (*entry.Attributes)[darwinFileFlagsKey]; have {
|
||||||
f, err := os.OpenFile(path, os.O_RDONLY|syscall.O_SYMLINK, 0)
|
f, err := os.OpenFile(path, os.O_RDONLY|syscall.O_SYMLINK, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -31,3 +118,18 @@ func (entry *Entry) restoreLateFileFlags(path string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
||||||
|
mode := entry.Mode & uint32(fileModeMask)
|
||||||
|
|
||||||
|
if entry.Mode&uint32(os.ModeNamedPipe) != 0 {
|
||||||
|
mode |= syscall.S_IFIFO
|
||||||
|
} else if entry.Mode&uint32(os.ModeCharDevice) != 0 {
|
||||||
|
mode |= syscall.S_IFCHR
|
||||||
|
} else if entry.Mode&uint32(os.ModeDevice) != 0 {
|
||||||
|
mode |= syscall.S_IFBLK
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return syscall.Mknod(fullPath, mode, int(entry.GetRdev()))
|
||||||
|
}
|
||||||
|
|||||||
@@ -121,6 +121,11 @@ func (entry *Entry) ReadAttributes(top string) {
|
|||||||
x.f.Close()
|
x.f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func excludedByAttribute(attributes map[string][]byte) bool {
|
||||||
|
_, ok := attributes["user.duplicacy_exclude"]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func (entry *Entry) SetAttributesToFile(fullPath string) {
|
func (entry *Entry) SetAttributesToFile(fullPath string) {
|
||||||
x := xattrHandle{nil, fullPath}
|
x := xattrHandle{nil, fullPath}
|
||||||
if !entry.IsLink() {
|
if !entry.IsLink() {
|
||||||
@@ -235,8 +240,3 @@ func (entry *Entry) RestoreSpecial(fullPath string) error {
|
|||||||
}
|
}
|
||||||
return syscall.Mknod(fullPath, mode, int(entry.GetRdev()))
|
return syscall.Mknod(fullPath, mode, int(entry.GetRdev()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func excludedByAttribute(attributes map[string][]byte) bool {
|
|
||||||
_, ok := attributes["user.duplicacy_exclude"]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) Acrosync LLC. All rights reserved.
|
|
||||||
// Free for personal use and commercial trial
|
|
||||||
// Commercial use requires per-user licenses available from https://duplicacy.com
|
|
||||||
|
|
||||||
//go:build freebsd || netbsd || solaris
|
|
||||||
// +build freebsd netbsd solaris
|
|
||||||
|
|
||||||
package duplicacy
|
|
||||||
|
|
||||||
func excludedByAttribute(attributes map[string][]byte) bool {
|
|
||||||
_, ok := attributes["user.duplicacy_exclude"]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
@@ -117,8 +117,12 @@ func (entry *Entry) SetAttributesToFile(fullPath string) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) ReadDeviceNode(fileInfo os.FileInfo) bool {
|
func (entry *Entry) ReadSpecial(fileInfo os.FileInfo) bool {
|
||||||
return nil
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) IsSameSpecial(fileInfo os.FileInfo) bool {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
||||||
@@ -148,8 +152,8 @@ func SplitDir(fullPath string) (dir string, file string) {
|
|||||||
return fullPath[:i+1], fullPath[i+1:]
|
return fullPath[:i+1], fullPath[i+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) ReadFileFlags(f *os.File) error {
|
func excludedByAttribute(attributes map[string][]byte) bool {
|
||||||
return nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
||||||
@@ -159,7 +163,3 @@ func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
|||||||
func (entry *Entry) RestoreEarlyFileFlags(f *os.File) error {
|
func (entry *Entry) RestoreEarlyFileFlags(f *os.File) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) RestoreLateFileFlags(f *os.File) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,18 +13,124 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/pkg/xattr"
|
"github.com/pkg/xattr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const bsd_UF_NODUMP = 0x1
|
||||||
|
|
||||||
|
const bsdFileFlagsKey = "\x00bf"
|
||||||
|
|
||||||
|
func excludedByAttribute(attributes map[string][]byte) bool {
|
||||||
|
_, excluded := attributes["duplicacy_exclude"]
|
||||||
|
if !excluded {
|
||||||
|
value, ok := attributes[bsdFileFlagsKey]
|
||||||
|
excluded = ok && (binary.LittleEndian.Uint32(value) & bsd_UF_NODUMP) != 0
|
||||||
|
}
|
||||||
|
return excluded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) ReadAttributes(top string) {
|
||||||
|
fullPath := filepath.Join(top, entry.Path)
|
||||||
|
fileInfo, err := os.Lstat(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !entry.IsSpecial() {
|
||||||
|
attributes, _ := xattr.LList(fullPath)
|
||||||
|
|
||||||
|
if len(attributes) > 0 {
|
||||||
|
entry.Attributes = &map[string][]byte{}
|
||||||
|
for _, name := range attributes {
|
||||||
|
attribute, err := xattr.LGet(fullPath, name)
|
||||||
|
if err == nil {
|
||||||
|
(*entry.Attributes)[name] = attribute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := entry.readFileFlags(fileInfo); err != nil {
|
||||||
|
LOG_INFO("ATTR_BACKUP", "Could not backup flags for file %s: %v", fullPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) SetAttributesToFile(fullPath string) {
|
||||||
|
if !entry.IsSpecial() {
|
||||||
|
names, _ := xattr.LList(fullPath)
|
||||||
|
for _, name := range names {
|
||||||
|
newAttribute, found := (*entry.Attributes)[name]
|
||||||
|
if found {
|
||||||
|
oldAttribute, _ := xattr.LGet(fullPath, name)
|
||||||
|
if !bytes.Equal(oldAttribute, newAttribute) {
|
||||||
|
xattr.LSet(fullPath, name, newAttribute)
|
||||||
|
}
|
||||||
|
delete(*entry.Attributes, name)
|
||||||
|
} else {
|
||||||
|
xattr.LRemove(fullPath, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, attribute := range *entry.Attributes {
|
||||||
|
if len(name) > 0 && name[0] == '\x00' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
xattr.LSet(fullPath, name, attribute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := entry.restoreLateFileFlags(fullPath); err != nil {
|
||||||
|
LOG_DEBUG("ATTR_RESTORE", "Could not restore flags for file %s: %v", fullPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreEarlyDirFlags(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreEarlyFileFlags(f *os.File) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) readFileFlags(fileInfo os.FileInfo) error {
|
||||||
|
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
|
||||||
|
if ok && stat.Flags != 0 {
|
||||||
|
if entry.Attributes == nil {
|
||||||
|
entry.Attributes = &map[string][]byte{}
|
||||||
|
}
|
||||||
|
v := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(v, stat.Flags)
|
||||||
|
(*entry.Attributes)[bsdFileFlagsKey] = v
|
||||||
|
LOG_DEBUG("ATTR_READ", "Read flags 0x%x for %s", stat.Flags, entry.Path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (entry *Entry) restoreLateFileFlags(path string) error {
|
func (entry *Entry) restoreLateFileFlags(path string) error {
|
||||||
if entry.Attributes == nil {
|
if entry.Attributes == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if v, have := (*entry.Attributes)[bsdFileFlagsKey]; have {
|
if v, have := (*entry.Attributes)[bsdFileFlagsKey]; have {
|
||||||
if _, _, errno := syscall.Syscall(syscall.SYS_LCHFLAGS, uintptr(unsafe.Pointer(syscall.StringBytePtr(path))), uintptr(v), 0); errno != 0 {
|
if _, _, errno := syscall.Syscall(syscall.SYS_LCHFLAGS,
|
||||||
|
uintptr(unsafe.Pointer(syscall.StringBytePtr(path))),
|
||||||
|
uintptr(binary.LittleEndian.Uint32((v))), 0); errno != 0 {
|
||||||
return os.NewSyscallError("lchflags", errno)
|
return os.NewSyscallError("lchflags", errno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
||||||
|
mode := entry.Mode & uint32(fileModeMask)
|
||||||
|
|
||||||
|
if entry.Mode&uint32(os.ModeNamedPipe) != 0 {
|
||||||
|
mode |= syscall.S_IFIFO
|
||||||
|
} else if entry.Mode&uint32(os.ModeCharDevice) != 0 {
|
||||||
|
mode |= syscall.S_IFCHR
|
||||||
|
} else if entry.Mode&uint32(os.ModeDevice) != 0 {
|
||||||
|
mode |= syscall.S_IFBLK
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return syscall.Mknod(fullPath, mode, entry.GetRdev())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user