duplicacy icon indicating copy to clipboard operation
duplicacy copied to clipboard

Ownerships and permissions of parent directories are wrong when restoring a subset of files

Open freakyjoe8 opened this issue 8 years ago • 13 comments

Hi,

I just restored a couple of files from my cloud backup. The restored files are now all owned by root instead of the original files owner. Is this behavior by design? File permissions are correct though.

freakyjoe8 avatar Jun 23 '17 07:06 freakyjoe8

This could be a bug. I'll take a look.

gilbertchen avatar Jun 23 '17 20:06 gilbertchen

Can you make sure it doesn't set the owner correctly? Which OS are you running on?

I ran a test and it restored the original owner despite of being run as root.

gilbertchen avatar Jul 08 '17 00:07 gilbertchen

I just tried it again and had a deeper look at the restored files and directories. The structure looks like this:

user1/domains/test.com/htdocs/index.php

The directory "test.com" and anything below has the correct ownerships. User and group are "user1". But both the directory "user1" and "domains" are owned by root after a restore instead of user1. Same for group ownership. So only certain parts are restored 100% correct. I must admit that the userid /groupid is >5000 and both are stored in MySQL via libnss. The passwd/groups file is not used. Don't know if that makes any difference.

OS: Ubuntu 16.04 LTS 64bit Command used: duplicacy -log -background restore -threads 4 -stats -r 404 user1/domains/test.com/* Cloud Service: Google Storage

freakyjoe8 avatar Jul 09 '17 15:07 freakyjoe8

I guess if you include user1/ and user1/domains in the file list their ownership should be restored correctly:

duplicacy -log -background restore -threads 4 -stats -r 404 user1/ user1/domains/ user1/domains/test.com/*

Without them being included, Duplicacy would create user1 and user1/domains as new directories just to store /user1/domains/test.com and therefore would not restore their ownership and permissions from the backup.

gilbertchen avatar Jul 11 '17 00:07 gilbertchen

That works. But the behavior is from my point of view not as it should be. I expect from a backup solution to restore all files and directories with the original permissions and ownerships if I don't set anything differently. What's the sense of restoring with wildcards if certain things are restored in a different way? I really like duplicacy but that behavior makes it unfortunately unusable for my use cases.

freakyjoe8 avatar Jul 11 '17 07:07 freakyjoe8

I think the fix is to automatically add parent directories if they are not specified.

gilbertchen avatar Jul 12 '17 03:07 gilbertchen

The fix of specifying the intermediate directories isn't working for me. For example, running:

sudo duplicacy restore -r 3 -stats 2015 2015/01 2015/01/25 2015/01/25/P1050608.JPG

still gives me all of the directories owned by the user running the restore (root), and only the file itself having the correct owner and group.

deviantintegral avatar Sep 04 '17 14:09 deviantintegral

Also:

sudo duplicacy restore -r 3 -stats 2015 2015/01/\*

gave incorrect ownership on 2015, but not 2015/01 or any of the subdirectories or files.

deviantintegral avatar Sep 04 '17 14:09 deviantintegral

I'll take a look at this.

gilbertchen avatar Sep 05 '17 03:09 gilbertchen

This is still a problem for me. Running 2.2.3 on Arch Linux, created the backup as root.

averms avatar Jun 29 '19 17:06 averms

The permission are messed up too, 744 instead of what they actually were when backing up.

averms avatar Jun 29 '19 17:06 averms

Tried a test restore to /tmp from a backup as root; still have this issue. I agree that having to include the root directory in the filters is a little silly, particularly because filter documentation explicitly states that unless all filter lines are include statements, everything is included by default.

meersjo avatar Jul 16 '19 10:07 meersjo

Here's a Bash snippet that parses Duplicacy include patterns and generates include patterns for any parent directories:

patterns=()
# shellcheck disable=SC2167
for pattern in "${patterns[@]}"; do
	if [[ $pattern != +* ]]; then
		continue
	fi

	dir_patterns=()
	IFS=/ read -r -a pattern_items <<<"${pattern:1}"
	for pattern_item in "${pattern_items[@]::${#pattern_items[@]}-1}"; do
		if [[ ${#dir_patterns[@]} -eq 0 ]]; then
			dir_patterns+=("+$pattern_item/")
		else
			dir_patterns+=("${dir_patterns[-1]}$pattern_item/")
		fi
	done

	for dir_pattern in "${dir_patterns[@]}"; do
		# shellcheck disable=SC2165
		for pattern in "${patterns[@]}"; do
			if [[ $dir_pattern = "$pattern" ]]; then
				continue 2
			fi
		done

		patterns+=("$dir_pattern")
	done
done

$patterns needs to be initialized with include/exclude patterns (first line), and once processing is done, will contain the initial set of patterns and include patterns for any parent directories.

TobyGiacometti avatar Jun 08 '24 13:06 TobyGiacometti