summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2005-08-11 03:34:03 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2005-08-11 03:34:03 +0000
commitac41194deb402b5611a624be6837e8527a0fd592 (patch)
tree001f2038d707f397b0afc108165f6ef1aa1ac771
parent6407faaf13d62710e524009a5174a5948754ed44 (diff)
downloadrdiff-backup-ac41194deb402b5611a624be6837e8527a0fd592.tar.gz
Added lchown to cmodule so rdiff-backup can preserve symlink uid/gid
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@606 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
-rw-r--r--rdiff-backup/CHANGELOG3
-rw-r--r--rdiff-backup/rdiff_backup/cmodule.c32
-rw-r--r--rdiff-backup/rdiff_backup/rpath.py10
-rw-r--r--rdiff-backup/testing/eas_aclstest.py1
-rw-r--r--rdiff-backup/testing/roottest.py13
5 files changed, 52 insertions, 7 deletions
diff --git a/rdiff-backup/CHANGELOG b/rdiff-backup/CHANGELOG
index 730b483..ae81a47 100644
--- a/rdiff-backup/CHANGELOG
+++ b/rdiff-backup/CHANGELOG
@@ -43,6 +43,9 @@ posix1e module.
bug#13613: Fix for overflow error that could happen when backing up
files with dates far in the future on a 64bit machine to a 32 bit one.
+Symlink ownership should be preserved now. Reported by Naoki
+Takebayashi and others.
+
New in v0.13.6 (2005/04/07)
---------------------------
diff --git a/rdiff-backup/rdiff_backup/cmodule.c b/rdiff-backup/rdiff_backup/cmodule.c
index 6fafde7..f6a44a3 100644
--- a/rdiff-backup/rdiff_backup/cmodule.c
+++ b/rdiff-backup/rdiff_backup/cmodule.c
@@ -368,6 +368,36 @@ static PyObject *acl_unquote(PyObject *self, PyObject *args)
return Py_BuildValue("s", unquote(s));
}
+/* ------------- lchown taken from Python's posixmodule.c -------------- */
+/* duplicate here to avoid v2.3 requirement */
+
+static PyObject *
+posix_error_with_allocated_filename(char* name)
+{
+ PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
+ PyMem_Free(name);
+ return rc;
+}
+
+static PyObject *
+posix_lchown(PyObject *self, PyObject *args)
+{
+ char *path = NULL;
+ int uid, gid;
+ int res;
+ if (!PyArg_ParseTuple(args, "etii:lchown",
+ Py_FileSystemDefaultEncoding, &path,
+ &uid, &gid))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ res = lchown(path, (uid_t) uid, (gid_t) gid);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return posix_error_with_allocated_filename(path);
+ PyMem_Free(path);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
/* ------------- Python export lists -------------------------------- */
@@ -381,6 +411,8 @@ static PyMethodDef CMethods[] = {
"Quote string, escaping non-printables"},
{"acl_unquote", acl_unquote, METH_VARARGS,
"Unquote string, producing original input to quote"},
+ {"lchown", posix_lchown, METH_VARARGS,
+ "Like chown, but don't follow symlinks"},
{NULL, NULL, 0, NULL}
};
diff --git a/rdiff-backup/rdiff_backup/rpath.py b/rdiff-backup/rdiff_backup/rpath.py
index 0b17934..2816c91 100644
--- a/rdiff-backup/rdiff_backup/rpath.py
+++ b/rdiff-backup/rdiff_backup/rpath.py
@@ -152,13 +152,13 @@ def copy_attribs(rpin, rpout):
"""
log.Log("Copying attributes from %s to %s" % (rpin.index, rpout.path), 7)
assert rpin.lstat() == rpout.lstat() or rpin.isspecial()
- if rpin.issym(): return # symlinks have no valid attributes
+ if Globals.change_ownership: rpout.chown(*user_group.map_rpath(rpin))
+ if rpin.issym(): return # symlinks don't have times or perms
if Globals.resource_forks_write and rpin.isreg():
rpout.write_resource_fork(rpin.get_resource_fork())
if Globals.carbonfile_write and rpin.isreg():
rpout.write_carbonfile(rpin.get_carbonfile())
if Globals.eas_write: rpout.write_ea(rpin.get_ea())
- if Globals.change_ownership: rpout.chown(*user_group.map_rpath(rpin))
rpout.chmod(rpin.getperms())
if Globals.acls_write: rpout.write_acl(rpin.get_acl())
if not rpin.isdev(): rpout.setmtime(rpin.getmtime())
@@ -173,13 +173,13 @@ def copy_attribs_inc(rpin, rpout):
"""
log.Log("Copying inc attrs from %s to %s" % (rpin.index, rpout.path), 7)
check_for_files(rpin, rpout)
- if rpin.issym(): return # symlinks have no valid attributes
+ if Globals.change_ownership: apply(rpout.chown, rpin.getuidgid())
+ if rpin.issym(): return # symlinks don't have times or perms
if Globals.resource_forks_write and rpin.isreg() and rpout.isreg():
rpout.write_resource_fork(rpin.get_resource_fork())
if Globals.carbonfile_write and rpin.isreg() and rpout.isreg():
rpout.write_carbonfile(rpin.get_carbonfile())
if Globals.eas_write: rpout.write_ea(rpin.get_ea())
- if Globals.change_ownership: apply(rpout.chown, rpin.getuidgid())
if rpin.isdir() and not rpout.isdir():
rpout.chmod(rpin.getperms() & 0777)
else: rpout.chmod(rpin.getperms())
@@ -775,7 +775,7 @@ class RPath(RORPath):
def chown(self, uid, gid):
"""Set file's uid and gid"""
- self.conn.os.chown(self.path, uid, gid)
+ self.conn.C.lchown(self.path, uid, gid)
self.data['uid'] = uid
self.data['gid'] = gid
diff --git a/rdiff-backup/testing/eas_aclstest.py b/rdiff-backup/testing/eas_aclstest.py
index a595cfe..4d6535f 100644
--- a/rdiff-backup/testing/eas_aclstest.py
+++ b/rdiff-backup/testing/eas_aclstest.py
@@ -245,7 +245,6 @@ other::---""")
new_acl = AccessControlLists(())
tempdir.chmod(0700)
new_acl.read_from_rp(tempdir)
- print "@", new_acl
assert new_acl.is_basic(), str(new_acl)
assert not new_acl == self.sample_acl
assert new_acl != self.sample_acl
diff --git a/rdiff-backup/testing/roottest.py b/rdiff-backup/testing/roottest.py
index 11da994..4950993 100644
--- a/rdiff-backup/testing/roottest.py
+++ b/rdiff-backup/testing/roottest.py
@@ -39,6 +39,9 @@ class RootTest(unittest.TestCase):
This checks for a bug in 0.13.4 where uids and gids would not
be restored correctly.
+ Also test to make sure symlinks get the right ownership.
+ (Earlier symlink ownership was not preserved.)
+
"""
dirrp = rpath.RPath(Globals.local_connection, "testfiles/root_owner")
def make_dir():
@@ -47,17 +50,25 @@ class RootTest(unittest.TestCase):
rp2 = dirrp.append('file2')
rp3 = dirrp.append('file3')
rp4 = dirrp.append('file4')
+ rp5 = dirrp.append('symlink')
rp1.touch()
rp2.touch()
rp3.touch()
rp4.touch()
+ rp5.symlink('foobar')
rp1.chown(2000, 2000)
rp2.chown(2001, 2001)
rp3.chown(2002, 2002)
rp4.chown(2003, 2003)
+ rp5.chown(2004, 2004)
make_dir()
- BackupRestoreSeries(1, 1, ['testfiles/root_owner', 'testfiles/empty'],
+ BackupRestoreSeries(1, 1, ['testfiles/root_owner', 'testfiles/empty',
+ 'testfiles/root_owner'],
compare_ownership = 1)
+ symrp = rpath.RPath(Globals.local_connection,
+ 'testfiles/output/symlink')
+ assert symrp.issym(), symrp
+ assert symrp.getuidgid() == (2004, 2004), symrp.getuidgid()
def test_ownership_mapping(self):
"""Test --user-mapping-file and --group-mapping-file options"""