mirror of
https://github.com/jkl1337/duplicacy.git
synced 2026-01-02 11:44:45 -06:00
Cleanup hardlinking code
This moves special file link data to the chunk fields like symlink hardlinks.
This commit is contained in:
@@ -1198,7 +1198,6 @@ func (manager *BackupManager) UploadSnapshot(chunkOperator *ChunkOperator, top s
|
|||||||
entry.EndChunk -= delta
|
entry.EndChunk -= delta
|
||||||
|
|
||||||
if entry.IsHardlinkRoot() {
|
if entry.IsHardlinkRoot() {
|
||||||
LOG_DEBUG("SNAPSHOT_UPLOAD", "Hard link root %s %v %v", entry.Path, entry.StartChunk, entry.EndChunk)
|
|
||||||
hardLinkTable = append(hardLinkTable, hardLinkEntry{entry, entry.StartChunk})
|
hardLinkTable = append(hardLinkTable, hardLinkEntry{entry, entry.StartChunk})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1206,7 +1205,7 @@ func (manager *BackupManager) UploadSnapshot(chunkOperator *ChunkOperator, top s
|
|||||||
entry.StartChunk -= lastEndChunk
|
entry.StartChunk -= lastEndChunk
|
||||||
lastEndChunk = entry.EndChunk
|
lastEndChunk = entry.EndChunk
|
||||||
entry.EndChunk = delta
|
entry.EndChunk = delta
|
||||||
} else if entry.IsHardlinkedFrom() && !entry.IsLink() {
|
} else if entry.IsHardlinkedFrom() {
|
||||||
i, err := entry.GetHardlinkId()
|
i, err := entry.GetHardlinkId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LOG_ERROR("SNAPSHOT_UPLOAD", "Decode error for hardlinked entry %s, %v", entry.Link, err)
|
LOG_ERROR("SNAPSHOT_UPLOAD", "Decode error for hardlinked entry %s, %v", entry.Link, err)
|
||||||
@@ -1216,17 +1215,13 @@ func (manager *BackupManager) UploadSnapshot(chunkOperator *ChunkOperator, top s
|
|||||||
targetEntry := hardLinkTable[i].entry
|
targetEntry := hardLinkTable[i].entry
|
||||||
var startChunk, endChunk int
|
var startChunk, endChunk int
|
||||||
|
|
||||||
if targetEntry.Size > 0 {
|
if targetEntry.IsFile() && targetEntry.Size > 0 {
|
||||||
startChunk = hardLinkTable[i].startChunk - lastEndChunk
|
startChunk = hardLinkTable[i].startChunk - lastEndChunk
|
||||||
endChunk = targetEntry.EndChunk
|
endChunk = targetEntry.EndChunk
|
||||||
|
lastEndChunk = hardLinkTable[i].startChunk + endChunk
|
||||||
}
|
}
|
||||||
entry = entry.HardLinkTo(targetEntry, startChunk, endChunk)
|
entry = entry.HardLinkTo(targetEntry, startChunk, endChunk)
|
||||||
|
|
||||||
if targetEntry.Size > 0 {
|
|
||||||
lastEndChunk = hardLinkTable[i].startChunk + endChunk
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("SNAPSHOT_UPLOAD", "Uploading cloned hardlink for %s to %s (%v %v)", entry.Path, targetEntry.Path, startChunk, endChunk)
|
|
||||||
} else if entry.IsHardlinkRoot() {
|
} else if entry.IsHardlinkRoot() {
|
||||||
hardLinkTable = append(hardLinkTable, hardLinkEntry{entry, 0})
|
hardLinkTable = append(hardLinkTable, hardLinkEntry{entry, 0})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
entrySymHardLinkRootChunkMarker = -9
|
entryHardLinkRootChunkMarker = -9
|
||||||
entrySymHardLinkTargetChunkMarker = -10
|
entryHardLinkTargetChunkMarker = -10
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the hidden directory in the repository for storing various files.
|
// This is the hidden directory in the repository for storing various files.
|
||||||
@@ -126,6 +126,13 @@ func (entry *Entry) Copy() *Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) HardLinkTo(target *Entry, startChunk int, endChunk int) *Entry {
|
func (entry *Entry) HardLinkTo(target *Entry, startChunk int, endChunk int) *Entry {
|
||||||
|
endOffset := target.EndOffset
|
||||||
|
|
||||||
|
if !target.IsFile() {
|
||||||
|
startChunk = target.StartChunk
|
||||||
|
endChunk = entry.EndChunk
|
||||||
|
endOffset = entry.EndOffset
|
||||||
|
}
|
||||||
return &Entry{
|
return &Entry{
|
||||||
Path: entry.Path,
|
Path: entry.Path,
|
||||||
Size: target.Size,
|
Size: target.Size,
|
||||||
@@ -140,7 +147,7 @@ func (entry *Entry) HardLinkTo(target *Entry, startChunk int, endChunk int) *Ent
|
|||||||
StartChunk: startChunk,
|
StartChunk: startChunk,
|
||||||
StartOffset: target.StartOffset,
|
StartOffset: target.StartOffset,
|
||||||
EndChunk: endChunk,
|
EndChunk: endChunk,
|
||||||
EndOffset: target.EndOffset,
|
EndOffset: endOffset,
|
||||||
|
|
||||||
Attributes: target.Attributes,
|
Attributes: target.Attributes,
|
||||||
}
|
}
|
||||||
@@ -519,31 +526,27 @@ func (entry *Entry) IsSpecial() bool {
|
|||||||
return entry.Mode&uint32(os.ModeNamedPipe|os.ModeDevice|os.ModeCharDevice|os.ModeSocket) != 0
|
return entry.Mode&uint32(os.ModeNamedPipe|os.ModeDevice|os.ModeCharDevice|os.ModeSocket) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) IsFileOrSpecial() bool {
|
|
||||||
return entry.Mode&uint32(os.ModeDir|os.ModeSymlink|os.ModeIrregular) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (entry *Entry) IsComplete() bool {
|
func (entry *Entry) IsComplete() bool {
|
||||||
return entry.Size >= 0
|
return entry.Size >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) IsHardlinkedFrom() bool {
|
func (entry *Entry) IsHardlinkedFrom() bool {
|
||||||
return (entry.IsFileOrSpecial() && len(entry.Link) > 0 && entry.Link != "/") || (entry.IsLink() && entry.StartChunk == entrySymHardLinkTargetChunkMarker)
|
return (entry.IsFile() && len(entry.Link) > 0 && entry.Link != "/") || (!entry.IsDir() && entry.EndChunk == entryHardLinkTargetChunkMarker)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) IsHardlinkRoot() bool {
|
func (entry *Entry) IsHardlinkRoot() bool {
|
||||||
return (entry.IsFileOrSpecial() && entry.Link == "/") || (entry.IsLink() && entry.StartChunk == entrySymHardLinkRootChunkMarker)
|
return (entry.IsFile() && entry.Link == "/") || (!entry.IsDir() && entry.EndChunk == entryHardLinkRootChunkMarker)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) GetHardlinkId() (int, error) {
|
func (entry *Entry) GetHardlinkId() (int, error) {
|
||||||
if entry.IsLink() {
|
if entry.IsFile() {
|
||||||
if entry.StartChunk != entrySymHardLinkTargetChunkMarker {
|
|
||||||
return 0, errors.New("Symlink entry not marked as hardlinked")
|
|
||||||
}
|
|
||||||
return entry.StartOffset, nil
|
|
||||||
} else {
|
|
||||||
i, err := strconv.ParseUint(entry.Link, 16, 64)
|
i, err := strconv.ParseUint(entry.Link, 16, 64)
|
||||||
return int(i), err
|
return int(i), err
|
||||||
|
} else {
|
||||||
|
if entry.EndChunk != entryHardLinkTargetChunkMarker {
|
||||||
|
return 0, errors.New("Symlink entry not marked as hardlinked")
|
||||||
|
}
|
||||||
|
return entry.EndOffset, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -824,17 +827,19 @@ func ListEntries(top string, path string, patterns []string, nobackupFile string
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
entry.Size = 0
|
entry.Size = 0
|
||||||
if entry.IsLink() {
|
if entry.IsFile() {
|
||||||
entry.StartChunk = entrySymHardLinkTargetChunkMarker
|
|
||||||
entry.StartOffset = linkIndex
|
|
||||||
} else {
|
|
||||||
entry.Link = strconv.FormatInt(int64(linkIndex), 16)
|
entry.Link = strconv.FormatInt(int64(linkIndex), 16)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if entry.IsLink() {
|
|
||||||
entry.StartChunk = entrySymHardLinkRootChunkMarker
|
|
||||||
} else {
|
} else {
|
||||||
|
entry.EndChunk = entryHardLinkTargetChunkMarker
|
||||||
|
entry.EndOffset = linkIndex
|
||||||
|
}
|
||||||
|
listingChannel <- entry
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
if entry.IsFile() {
|
||||||
entry.Link = "/"
|
entry.Link = "/"
|
||||||
|
} else {
|
||||||
|
entry.EndChunk = entryHardLinkRootChunkMarker
|
||||||
}
|
}
|
||||||
listingState.linkTable[k] = -1
|
listingState.linkTable[k] = -1
|
||||||
linkKey = &k
|
linkKey = &k
|
||||||
|
|||||||
Reference in New Issue
Block a user