Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "no follow links" preference #564

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions duplicacy/duplicacy_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,11 @@ func setPreference(context *cli.Context) {
newPreference.DoNotSavePassword = triBool.IsTrue()
}

triBool = context.Generic("no-follow-links").(*TriBool)
if triBool.IsSet() {
newPreference.DoNotFollowLinks = triBool.IsTrue()
}

newPreference.NobackupFile = context.String("nobackup-file")

key := context.String("key")
Expand Down Expand Up @@ -715,7 +720,7 @@ func backupRepository(context *cli.Context) {
uploadRateLimit := context.Int("limit-rate")
enumOnly := context.Bool("enum-only")
storage.SetRateLimits(0, uploadRateLimit)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
Expand Down Expand Up @@ -794,7 +799,7 @@ func restoreRepository(context *cli.Context) {
duplicacy.LOG_INFO("SNAPSHOT_FILTER", "Loaded %d include/exclude pattern(s)", len(patterns))

storage.SetRateLimits(context.Int("limit-rate"), 0)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
Expand Down Expand Up @@ -834,7 +839,7 @@ func listSnapshots(context *cli.Context) {
tag := context.String("t")
revisions := getRevisions(context)

backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

id := preference.SnapshotID
Expand Down Expand Up @@ -882,7 +887,7 @@ func checkSnapshots(context *cli.Context) {
tag := context.String("t")
revisions := getRevisions(context)

backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

id := preference.SnapshotID
Expand Down Expand Up @@ -937,7 +942,7 @@ func printFile(context *cli.Context) {
snapshotID = context.String("id")
}

backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
Expand Down Expand Up @@ -993,11 +998,11 @@ func diff(context *cli.Context) {
}

compareByHash := context.Bool("hash")
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
backupManager.SnapshotManager.Diff(repository, snapshotID, revisions, path, compareByHash, preference.NobackupFile)
backupManager.SnapshotManager.Diff(repository, snapshotID, revisions, path, compareByHash, preference.NobackupFile, preference.DoNotFollowLinks)

runScript(context, preference.Name, "post")
}
Expand Down Expand Up @@ -1036,7 +1041,7 @@ func showHistory(context *cli.Context) {

revisions := getRevisions(context)
showLocalHash := context.Bool("hash")
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
Expand Down Expand Up @@ -1099,7 +1104,7 @@ func pruneSnapshots(context *cli.Context) {
os.Exit(ArgumentExitCode)
}

backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile)
backupManager := duplicacy.CreateBackupManager(preference.SnapshotID, storage, repository, password, preference.NobackupFile, preference.DoNotFollowLinks)
duplicacy.SavePassword(*preference, "password", password)

backupManager.SetupSnapshotCache(preference.Name)
Expand Down Expand Up @@ -1139,7 +1144,7 @@ func copySnapshots(context *cli.Context) {
sourcePassword = duplicacy.GetPassword(*source, "password", "Enter source storage password:", false, false)
}

sourceManager := duplicacy.CreateBackupManager(source.SnapshotID, sourceStorage, repository, sourcePassword, source.NobackupFile)
sourceManager := duplicacy.CreateBackupManager(source.SnapshotID, sourceStorage, repository, sourcePassword, source.NobackupFile, source.DoNotFollowLinks)
sourceManager.SetupSnapshotCache(source.Name)
duplicacy.SavePassword(*source, "password", sourcePassword)

Expand Down Expand Up @@ -1172,7 +1177,7 @@ func copySnapshots(context *cli.Context) {
destinationStorage.SetRateLimits(0, context.Int("upload-limit-rate"))

destinationManager := duplicacy.CreateBackupManager(destination.SnapshotID, destinationStorage, repository,
destinationPassword, destination.NobackupFile)
destinationPassword, destination.NobackupFile, destination.DoNotFollowLinks)
duplicacy.SavePassword(*destination, "password", destinationPassword)
destinationManager.SetupSnapshotCache(destination.Name)

Expand Down
10 changes: 7 additions & 3 deletions src/duplicacy_backupmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type BackupManager struct {
config *Config // contains a number of options

nobackupFile string // don't backup directory when this file name is found

nofollowlinks bool // don't follow symlinks ever (store as symlink only)
}

func (manager *BackupManager) SetDryRun(dryRun bool) {
Expand All @@ -44,7 +46,7 @@ func (manager *BackupManager) SetDryRun(dryRun bool) {
// CreateBackupManager creates a backup manager using the specified 'storage'. 'snapshotID' is a unique id to
// identify snapshots created for this repository. 'top' is the top directory of the repository. 'password' is the
// master key which can be nil if encryption is not enabled.
func CreateBackupManager(snapshotID string, storage Storage, top string, password string, nobackupFile string) *BackupManager {
func CreateBackupManager(snapshotID string, storage Storage, top string, password string, nobackupFile string, nofollowlinks bool) *BackupManager {

config, _, err := DownloadConfig(storage, password)
if err != nil {
Expand All @@ -67,6 +69,8 @@ func CreateBackupManager(snapshotID string, storage Storage, top string, passwor
config: config,

nobackupFile: nobackupFile,

nofollowlinks: nofollowlinks,
}

if IsDebugging() {
Expand Down Expand Up @@ -188,7 +192,7 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
defer DeleteShadowCopy()

LOG_INFO("BACKUP_INDEXING", "Indexing %s", top)
localSnapshot, skippedDirectories, skippedFiles, err := CreateSnapshotFromDirectory(manager.snapshotID, shadowTop, manager.nobackupFile)
localSnapshot, skippedDirectories, skippedFiles, err := CreateSnapshotFromDirectory(manager.snapshotID, shadowTop, manager.nobackupFile, manager.nofollowlinks)
if err != nil {
LOG_ERROR("SNAPSHOT_LIST", "Failed to list the directory %s: %v", top, err)
return false
Expand Down Expand Up @@ -760,7 +764,7 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
remoteSnapshot := manager.SnapshotManager.DownloadSnapshot(manager.snapshotID, revision)
manager.SnapshotManager.DownloadSnapshotContents(remoteSnapshot, patterns, true)

localSnapshot, _, _, err := CreateSnapshotFromDirectory(manager.snapshotID, top, manager.nobackupFile)
localSnapshot, _, _, err := CreateSnapshotFromDirectory(manager.snapshotID, top, manager.nobackupFile, manager.nofollowlinks)
if err != nil {
LOG_ERROR("SNAPSHOT_LIST", "Failed to list the repository: %v", err)
return false
Expand Down
6 changes: 4 additions & 2 deletions src/duplicacy_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,11 @@ func (files FileInfoCompare) Less(i, j int) bool {

// ListEntries returns a list of entries representing file and subdirectories under the directory 'path'. Entry paths
// are normalized as relative to 'top'. 'patterns' are used to exclude or include certain files.
func ListEntries(top string, path string, fileList *[]*Entry, patterns []string, nobackupFile string, discardAttributes bool) (directoryList []*Entry,
func ListEntries(top string, path string, fileList *[]*Entry, patterns []string, nobackupFile string, discardAttributes bool, noFollowLinks bool) (directoryList []*Entry,
skippedFiles []string, err error) {

LOG_DEBUG("LIST_ENTRIES", "noFollowLinks", noFollowLinks)

LOG_DEBUG("LIST_ENTRIES", "Listing %s", path)

fullPath := joinPath(top, path)
Expand Down Expand Up @@ -499,7 +501,7 @@ func ListEntries(top string, path string, fileList *[]*Entry, patterns []string,

if isRegular {
entry.Mode ^= uint32(os.ModeSymlink)
} else if path == "" && (filepath.IsAbs(entry.Link) || filepath.HasPrefix(entry.Link, `\\`)) && !strings.HasPrefix(entry.Link, normalizedTop) {
} else if !noFollowLinks && (path == "" && (filepath.IsAbs(entry.Link) || filepath.HasPrefix(entry.Link, `\\`)) && !strings.HasPrefix(entry.Link, normalizedTop)) {
stat, err := os.Stat(filepath.Join(top, entry.Path))
if err != nil {
LOG_WARN("LIST_LINK", "Failed to read the symlink: %v", err)
Expand Down
1 change: 1 addition & 0 deletions src/duplicacy_preference.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Preference struct {
BackupProhibited bool `json:"no_backup"`
RestoreProhibited bool `json:"no_restore"`
DoNotSavePassword bool `json:"no_save_password"`
DoNotFollowLinks bool `json:"no_follow_links"`
NobackupFile string `json:"nobackup_file"`
Keys map[string]string `json:"keys"`
}
Expand Down
4 changes: 2 additions & 2 deletions src/duplicacy_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func CreateEmptySnapshot(id string) (snapshto *Snapshot) {

// CreateSnapshotFromDirectory creates a snapshot from the local directory 'top'. Only 'Files'
// will be constructed, while 'ChunkHashes' and 'ChunkLengths' can only be populated after uploading.
func CreateSnapshotFromDirectory(id string, top string, nobackupFile string) (snapshot *Snapshot, skippedDirectories []string,
func CreateSnapshotFromDirectory(id string, top string, nobackupFile string, nofollowlinks bool) (snapshot *Snapshot, skippedDirectories []string,
skippedFiles []string, err error) {

snapshot = &Snapshot{
Expand Down Expand Up @@ -86,7 +86,7 @@ func CreateSnapshotFromDirectory(id string, top string, nobackupFile string) (sn
directory := directories[len(directories)-1]
directories = directories[:len(directories)-1]
snapshot.Files = append(snapshot.Files, directory)
subdirectories, skipped, err := ListEntries(top, directory.Path, &snapshot.Files, patterns, nobackupFile, snapshot.discardAttributes)
subdirectories, skipped, err := ListEntries(top, directory.Path, &snapshot.Files, patterns, nobackupFile, snapshot.discardAttributes, nofollowlinks)
if err != nil {
LOG_WARN("LIST_FAILURE", "Failed to list subdirectory: %v", err)
skippedDirectories = append(skippedDirectories, directory.Path)
Expand Down
4 changes: 2 additions & 2 deletions src/duplicacy_snapshotmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1298,7 +1298,7 @@ func (manager *SnapshotManager) PrintFile(snapshotID string, revision int, path

// Diff compares two snapshots, or two revision of a file if the file argument is given.
func (manager *SnapshotManager) Diff(top string, snapshotID string, revisions []int,
filePath string, compareByHash bool, nobackupFile string) bool {
filePath string, compareByHash bool, nobackupFile string, nofollowlinks bool) bool {

LOG_DEBUG("DIFF_PARAMETERS", "top: %s, id: %s, revision: %v, path: %s, compareByHash: %t",
top, snapshotID, revisions, filePath, compareByHash)
Expand All @@ -1311,7 +1311,7 @@ func (manager *SnapshotManager) Diff(top string, snapshotID string, revisions []
if len(revisions) <= 1 {
// Only scan the repository if filePath is not provided
if len(filePath) == 0 {
rightSnapshot, _, _, err = CreateSnapshotFromDirectory(snapshotID, top, nobackupFile)
rightSnapshot, _, _, err = CreateSnapshotFromDirectory(snapshotID, top, nobackupFile, nofollowlinks)
if err != nil {
LOG_ERROR("SNAPSHOT_LIST", "Failed to list the directory %s: %v", top, err)
return false
Expand Down