It turns out that Cygwin won't allow you to chown() a path to an
unknown uid or gid, even when "root".
For now, make that a deferred error on Cygwin, rework the tests to
avoid it when possible, and disable the tests (on Cygwin) that require
it.
For the record, it appears that tar doesn't normally hit this problem
on Cygwin because it uses "geteuid() == 0" to detect super-user
status, which won't be true in the normal case, even if the user is an
administrator.
Signed-off-by: Rob Browning <rlb@defaultvalue.org>
current system. The use of user and group names can be disabled via
`--numeric-ids` (which can be important when restoring a chroot, for
example), and as a special case, a uid or gid of 0 will never be
current system. The use of user and group names can be disabled via
`--numeric-ids` (which can be important when restoring a chroot, for
example), and as a special case, a uid or gid of 0 will never be
+remapped by name. Additionally, some systems don't allow setting a
+uid/gid that doesn't correspond with a known user/group. On those
+systems, bup will log an error for each relevant path.
Hardlinks will also be restored when possible, but at least currently,
no links will be made to targets outside the restore tree, and if the
Hardlinks will also be restored when possible, but at least currently,
no links will be made to targets outside the restore tree, and if the
except OSError, e:
if e.errno == errno.EPERM:
add_error('lchown: %s' % e)
except OSError, e:
if e.errno == errno.EPERM:
add_error('lchown: %s' % e)
+ elif sys.platform.startswith('cygwin') \
+ and e.errno == errno.EINVAL:
+ add_error('lchown: unknown uid/gid (%d/%d) for %s'
+ % (uid, gid, path))
--- /dev/null
+#!/usr/bin/env python
+
+import grp
+import pwd
+import sys
+
+def usage():
+ print >> sys.stderr, "Usage: id-other-than ID [ID ...]"
+
+if len(sys.argv) < 2:
+ usage()
+ sys.exit(1)
+
+def is_integer(x):
+ try:
+ int(x)
+ return True
+ except ValueError, e:
+ return False
+
+excluded_ids = frozenset(int(x) for x in sys.argv[2:] if is_integer(x))
+excluded_names = frozenset(x for x in sys.argv[2:] if not is_integer(x))
+
+if sys.argv[1] == '--user':
+ for x in pwd.getpwall():
+ if x.pw_name not in excluded_names and x.pw_uid not in excluded_ids:
+ print x.pw_name + ':' + str(x.pw_uid)
+ sys.exit(0)
+elif sys.argv[1] == '--group':
+ for x in grp.getgrall():
+ if x.gr_name not in excluded_names and x.gr_gid not in excluded_ids:
+ print x.gr_name + ':' + str(x.gr_gid)
+ sys.exit(0)
+else:
+ usage()
+ sys.exit(1)
+++ /dev/null
-#!/usr/bin/env python
-
-import grp
-import pwd
-import sys
-
-def usage():
- print >> sys.stderr, "Usage: some-owners (--user | --group)"
-
-if len(sys.argv) != 2:
- usage()
- sys.exit(1)
-
-if sys.argv[1] == '--user':
- non_root_users = [x.pw_name for x in pwd.getpwall() if x.pw_name != 'root']
- print non_root_users[0]
-elif sys.argv[1] == '--group':
- non_root_groups = [x.gr_name for x in grp.getgrall() if x.gr_name != 'root']
- print non_root_groups[0]
-else:
- usage()
- sys.exit(1)
"$TOP/t/hardlink-sets" "$@"
}
"$TOP/t/hardlink-sets" "$@"
}
+id-other-than()
+{
+ "$TOP/t/id-other-than" "$@"
+}
+
# Very simple metadata tests -- create a test tree then check that bup
# meta can reproduce the metadata correctly (according to bup xstat)
# via create, extract, start-extract, and finish-extract. The current
# Very simple metadata tests -- create a test tree then check that bup
# meta can reproduce the metadata correctly (according to bup xstat)
# via create, extract, start-extract, and finish-extract. The current
chmod 700 dest # so we can't accidentally do something insecure
cd dest
chmod 700 dest # so we can't accidentally do something insecure
cd dest
- # Make sure we can restore a uid.
- WVPASS bup meta --edit --unset-user --set-uid 42 ../src.meta \
+ other_uinfo="$(id-other-than --user "$(id -un)")"
+ other_user="${other_uinfo%%:*}"
+ other_uid="${other_uinfo##*:}"
+
+ other_ginfo="$(id-other-than --group "$(id -gn)")"
+ other_group="${other_ginfo%%:*}"
+ other_gid="${other_ginfo##*:}"
+
+ # Make sure we can restore a uid (must be in /etc/passwd b/c cygwin).
+ WVPASS bup meta --edit --unset-user --set-uid "$other_uid" ../src.meta \
- WVPASS bup xstat src | WVPASS grep -qE '^uid: 42'
+ WVPASS bup xstat src | WVPASS grep -qE "^uid: $other_uid"
- # Make sure we can restore a gid.
- WVPASS bup meta --edit --unset-group --set-gid 42 ../src.meta \
+ # Make sure we can restore a gid (must be in /etc/group b/c cygwin).
+ WVPASS bup meta --edit --unset-group --set-gid "$other_gid" ../src.meta \
- WVPASS bup xstat src | WVPASS grep -qE '^gid: 42'
+ WVPASS bup xstat src | WVPASS grep -qE "^gid: $other_gid"
+
+ other_uinfo2="$(id-other-than --user "$(id -un)" "$other_user")"
+ other_user2="${other_uinfo2%%:*}"
+ other_uid2="${other_uinfo2##*:}"
- some_user=$("$TOP"/t/some-owner --user)
- some_group=$("$TOP"/t/some-owner --group)
+ other_ginfo2="$(id-other-than --group "$(id -gn)" "$other_group")"
+ other_group2="${other_ginfo2%%:*}"
+ other_gid2="${other_ginfo2##*:}"
# Try to restore a user (and see that user trumps uid when uid is not 0).
# Try to restore a user (and see that user trumps uid when uid is not 0).
- WVPASS bup meta --edit --set-uid 42 --set-user "$some_user" ../src.meta \
+ WVPASS bup meta --edit \
+ --set-uid "$other_uid2" --set-user "$some_user" ../src.meta \
| WVPASS bup meta -x
WVPASS bup xstat src | WVPASS grep -qE "^user: $some_user"
# Try to restore a group (and see that group trumps gid when gid is not 0).
| WVPASS bup meta -x
WVPASS bup xstat src | WVPASS grep -qE "^user: $some_user"
# Try to restore a group (and see that group trumps gid when gid is not 0).
- WVPASS bup meta --edit --set-gid 42 --set-group "$some_group" ../src.meta \
+ WVPASS bup meta --edit \
+ --set-gid "$other_gid2" --set-group "$some_group" ../src.meta \
| WVPASS bup meta -x
WVPASS bup xstat src | WVPASS grep -qE "^group: $some_user"
| WVPASS bup meta -x
WVPASS bup xstat src | WVPASS grep -qE "^group: $some_user"
- # Make sure a uid of 0 trumps a non-root user.
- WVPASS bup meta --edit --set-user "$some_user" ../src.meta \
- | WVPASS bup meta -x
- WVPASS bup xstat src | WVPASS grep -qvE "^user: $some_user"
- WVPASS bup xstat src | WVPASS grep -qE "^uid: 0"
-
- # Make sure a gid of 0 trumps a non-root group.
- WVPASS bup meta --edit --set-group "$some_user" ../src.meta \
- | WVPASS bup meta -x
- WVPASS bup xstat src | WVPASS grep -qvE "^group: $some_group"
- WVPASS bup xstat src | WVPASS grep -qE "^gid: 0"
+ # Test --numeric-ids (uid). Note the name 'root' is not handled
+ # specially, so we use that here as the test user name. We assume
+ # that the root user's uid is never 42.
+ rm -rf src
+ WVPASS bup meta --edit --set-user root --set-uid "$other_uid" ../src.meta \
+ | WVPASS bup meta -x --numeric-ids
+ new_uidx=$(bup xstat src | grep -e '^uid:')
+ WVPASSEQ "$new_uidx" "uid: $other_uid"
# Test --numeric-ids (gid). Note the name 'root' is not handled
# specially, so we use that here as the test group name. We
# assume that the root group's gid is never 42.
rm -rf src
# Test --numeric-ids (gid). Note the name 'root' is not handled
# specially, so we use that here as the test group name. We
# assume that the root group's gid is never 42.
rm -rf src
- WVPASS bup meta --edit --set-group root --set-gid 42 ../src.meta \
+ WVPASS bup meta --edit --set-group root --set-gid "$other_gid" ../src.meta \
| WVPASS bup meta -x --numeric-ids
new_gidx=$(bup xstat src | grep -e '^gid:')
| WVPASS bup meta -x --numeric-ids
new_gidx=$(bup xstat src | grep -e '^gid:')
- WVPASSEQ "$new_gidx" 'gid: 42'
-
- # Test --numeric-ids (uid). Note the name 'root' is not handled
- # specially, so we use that here as the test user name. We assume
- # that the root user's uid is never 42.
- rm -rf src
- WVPASS bup meta --edit --set-user root --set-uid 42 ../src.meta \
- | WVPASS bup meta -x --numeric-ids
- new_uidx=$(bup xstat src | grep -e '^uid:')
- WVPASSEQ "$new_uidx" 'uid: 42'
+ WVPASSEQ "$new_gidx" "gid: $other_gid"
# Test that restoring an unknown user works.
unknown_user=$("$TOP"/t/unknown-owners --user)
rm -rf src
# Test that restoring an unknown user works.
unknown_user=$("$TOP"/t/unknown-owners --user)
rm -rf src
- WVPASS bup meta --edit --set-uid 42 --set-user "$unknown_user" ../src.meta \
+ WVPASS bup meta --edit \
+ --set-uid "$other_uid" --set-user "$unknown_user" ../src.meta \
| WVPASS bup meta -x
new_uidx=$(bup xstat src | grep -e '^uid:')
| WVPASS bup meta -x
new_uidx=$(bup xstat src | grep -e '^uid:')
- WVPASSEQ "$new_uidx" 'uid: 42'
+ WVPASSEQ "$new_uidx" "uid: $other_uid"
# Test that restoring an unknown group works.
unknown_group=$("$TOP"/t/unknown-owners --group)
rm -rf src
WVPASS bup meta --edit \
# Test that restoring an unknown group works.
unknown_group=$("$TOP"/t/unknown-owners --group)
rm -rf src
WVPASS bup meta --edit \
- --set-gid 42 --set-group "$unknown_group" ../src.meta \
+ --set-gid "$other_gid" --set-group "$unknown_group" ../src.meta \
| WVPASS bup meta -x
new_gidx=$(bup xstat src | grep -e '^gid:')
| WVPASS bup meta -x
new_gidx=$(bup xstat src | grep -e '^gid:')
- WVPASSEQ "$new_gidx" 'gid: 42'
+ WVPASSEQ "$new_gidx" "gid: $other_gid"
+
+ if ! [[ $(uname) =~ CYGWIN ]]; then
+ # For now, skip these on Cygwin because it doesn't allow
+ # restoring an unknown uid/gid.
+
+ # Make sure a uid of 0 trumps a non-root user.
+ WVPASS bup meta --edit --set-user "$some_user" ../src.meta \
+ | WVPASS bup meta -x
+ WVPASS bup xstat src | WVPASS grep -qvE "^user: $some_user"
+ WVPASS bup xstat src | WVPASS grep -qE "^uid: 0"
+
+ # Make sure a gid of 0 trumps a non-root group.
+ WVPASS bup meta --edit --set-group "$some_user" ../src.meta \
+ | WVPASS bup meta -x
+ WVPASS bup xstat src | WVPASS grep -qvE "^group: $some_group"
+ WVPASS bup xstat src | WVPASS grep -qE "^gid: 0"
+ fi
)
# Root-only tests that require an FS with all the trimmings: ACLs,
)
# Root-only tests that require an FS with all the trimmings: ACLs,