mirror of
https://github.com/jkl1337/duplicacy.git
synced 2026-01-02 11:44:45 -06:00
Compare commits
1 Commits
wip-hardli
...
96e7c93a2c
| Author | SHA1 | Date | |
|---|---|---|---|
| 96e7c93a2c |
@@ -797,6 +797,21 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
||||
}
|
||||
remoteEntry.RestoreEarlyDirFlags(fullPath)
|
||||
directoryEntries = append(directoryEntries, remoteEntry)
|
||||
} else if remoteEntry.IsSpecial() {
|
||||
if stat, _ := os.Lstat(fullPath); stat != nil {
|
||||
if !overwrite {
|
||||
LOG_WERROR(allowFailures, "DOWNLOAD_OVERWRITE",
|
||||
"File %s already exists. Please specify the -overwrite option to overwrite", remoteEntry.Path)
|
||||
continue
|
||||
}
|
||||
os.Remove(fullPath)
|
||||
}
|
||||
|
||||
if err := remoteEntry.RestoreSpecial(fullPath); err != nil {
|
||||
LOG_ERROR("RESTORE_SPECIAL", "Unable to restore special file %s: %v", remoteEntry.Path, err)
|
||||
return 0
|
||||
}
|
||||
remoteEntry.RestoreMetadata(fullPath, nil, setOwner)
|
||||
} else {
|
||||
if remoteEntry.IsHardlinkRoot() {
|
||||
hardLinkTable[len(hardLinkTable)-1] = hardLinkEntry{remoteEntry, true}
|
||||
|
||||
@@ -509,6 +509,10 @@ func (entry *Entry) IsLink() bool {
|
||||
return entry.Mode&uint32(os.ModeSymlink) != 0
|
||||
}
|
||||
|
||||
func (entry *Entry) IsSpecial() bool {
|
||||
return entry.Mode&uint32(os.ModeNamedPipe|os.ModeDevice|os.ModeCharDevice) != 0
|
||||
}
|
||||
|
||||
func (entry *Entry) IsComplete() bool {
|
||||
return entry.Size >= 0
|
||||
}
|
||||
@@ -815,12 +819,15 @@ func ListEntries(top string, path string, patterns []string, nobackupFile string
|
||||
}
|
||||
entry = newEntry
|
||||
}
|
||||
}
|
||||
|
||||
if f.Mode()&(os.ModeNamedPipe|os.ModeSocket|os.ModeDevice) != 0 {
|
||||
LOG_WARN("LIST_SKIP", "Skipped non-regular file %s", entry.Path)
|
||||
skippedFiles = append(skippedFiles, entry.Path)
|
||||
} else if entry.Mode & uint32(os.ModeSocket) != 0 {
|
||||
// no reason to issue a warning for what should always be a transient file anyways
|
||||
continue
|
||||
} else if entry.IsSpecial() {
|
||||
if !entry.ReadSpecial(f) {
|
||||
LOG_WARN("LIST_DEV", "Failed to save device node %s", entry.Path)
|
||||
skippedFiles = append(skippedFiles, entry.Path)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var linkKey *listEntryLinkKey
|
||||
|
||||
@@ -111,12 +111,12 @@ func (entryList *EntryList)createOnDiskFile() error {
|
||||
// Add an entry to the entry list
|
||||
func (entryList *EntryList)AddEntry(entry *Entry) error {
|
||||
|
||||
if !entry.IsDir() && !entry.IsLink() {
|
||||
if entry.IsFile() {
|
||||
entryList.NumberOfEntries++
|
||||
}
|
||||
|
||||
if !entry.IsComplete() {
|
||||
if entry.IsDir() || entry.IsLink() {
|
||||
if !entry.IsFile() {
|
||||
entry.Size = 0
|
||||
} else {
|
||||
modifiedEntry := ModifiedEntry {
|
||||
|
||||
@@ -48,6 +48,9 @@ func ioctl(f *os.File, request uintptr, attrp *uint32) error {
|
||||
}
|
||||
|
||||
func (entry *Entry) ReadFileFlags(f *os.File) error {
|
||||
if entry.IsSpecial() {
|
||||
return nil
|
||||
}
|
||||
var flags uint32
|
||||
if err := ioctl(f, linux_FS_IOC_GETFLAGS, &flags); err != nil {
|
||||
return err
|
||||
|
||||
@@ -49,7 +49,7 @@ func SetOwner(fullPath string, entry *Entry, fileInfo *os.FileInfo) bool {
|
||||
|
||||
func (entry *Entry) ReadAttributes(top string) {
|
||||
fullPath := filepath.Join(top, entry.Path)
|
||||
f, err := os.OpenFile(fullPath, os.O_RDONLY|syscall.O_NOFOLLOW, 0)
|
||||
f, err := os.OpenFile(fullPath, os.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_NONBLOCK, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -101,6 +101,37 @@ func (entry *Entry) SetAttributesToFile(fullPath string) {
|
||||
f.Close()
|
||||
}
|
||||
|
||||
func (entry *Entry) ReadSpecial(fileInfo os.FileInfo) bool {
|
||||
if fileInfo.Mode() & (os.ModeDevice | os.ModeCharDevice) == 0 {
|
||||
return true
|
||||
}
|
||||
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
|
||||
if !ok || stat == nil {
|
||||
return false
|
||||
}
|
||||
entry.Size = 0
|
||||
rdev := uint64(stat.Rdev)
|
||||
entry.StartChunk = int(rdev & 0xFFFFFFFF)
|
||||
entry.StartOffset = int(rdev >> 32)
|
||||
return true
|
||||
}
|
||||
|
||||
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
||||
if entry.Mode & uint32(os.ModeDevice | os.ModeCharDevice) != 0 {
|
||||
mode := entry.Mode & uint32(fileModeMask)
|
||||
if entry.Mode & uint32(os.ModeCharDevice) != 0 {
|
||||
mode |= syscall.S_IFCHR
|
||||
} else {
|
||||
mode |= syscall.S_IFBLK
|
||||
}
|
||||
rdev := uint64(entry.StartChunk) | uint64(entry.StartOffset) << 32
|
||||
return syscall.Mknod(fullPath, mode, int(rdev))
|
||||
} else if entry.Mode & uint32(os.ModeNamedPipe) != 0 {
|
||||
return syscall.Mkfifo(fullPath, uint32(entry.Mode))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func joinPath(components ...string) string {
|
||||
return path.Join(components...)
|
||||
}
|
||||
|
||||
@@ -117,6 +117,14 @@ func (entry *Entry) SetAttributesToFile(fullPath string) {
|
||||
|
||||
}
|
||||
|
||||
func (entry *Entry) ReadDeviceNode(fileInfo os.FileInfo) bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (entry *Entry) RestoreSpecial(fullPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func joinPath(components ...string) string {
|
||||
|
||||
combinedPath := `\\?\` + filepath.Join(components...)
|
||||
|
||||
Reference in New Issue
Block a user