1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

samba.xattr: Massively simplify copytree_with_xattrs.

This commit is contained in:
Jelmer Vernooij 2012-02-27 02:46:31 +01:00
parent 2c9ff8a4d7
commit 8008228b94
3 changed files with 60 additions and 67 deletions

View File

@ -1471,7 +1471,7 @@ def backup_provision(paths, dir):
:param paths: Paths to different objects
:param dir: Directory where to store the backup
"""
if paths.sysvol is not None:
if paths.sysvol:
copytree_with_xattrs(paths.sysvol, os.path.join(dir, "sysvol"))
shutil.copy2(paths.samdb, dir)
shutil.copy2(paths.secrets, dir)

View File

@ -20,10 +20,16 @@
"""Tests for samba.xattr_native and samba.xattr_tdb."""
import samba.xattr_native, samba.xattr_tdb
from samba.xattr import copytree_with_xattrs
from samba.dcerpc import xattr
from samba.ndr import ndr_pack
from samba.tests import TestCase, TestSkipped
from samba.tests import (
TestCase,
TestCaseInTempDir,
TestSkipped,
)
import random
import shutil
import os
class XattrTests(TestCase):
@ -103,3 +109,20 @@ class XattrTests(TestCase):
finally:
os.unlink(tempf)
os.unlink(eadb_path)
class TestCopyTreeWithXattrs(TestCaseInTempDir):
def test_simple(self):
os.chdir(self.tempdir)
os.mkdir("a")
os.mkdir("a/b")
os.mkdir("a/b/c")
f = open('a/b/c/d', 'w')
try:
f.write("foo")
finally:
f.close()
copytree_with_xattrs("a", "b")
shutil.rmtree("a")
shutil.rmtree("b")

View File

@ -3,7 +3,6 @@
#
# Utility code for dealing with POSIX extended attributes
#
# Copyright (C) Matthieu Patou <mat@matws.net> 2009 - 2010
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2012
#
# This program is free software; you can redistribute it and/or modify
@ -25,70 +24,41 @@ import samba.xattr_native
import shutil
def copytree_with_xattrs(source, target):
"""Copy a tree but preserve extended attributes.
def copyattrs(frompath, topath):
"""Copy ACL related attributes from a path to another path."""
for attr_name in (xattr.XATTR_NTACL_NAME, "system.posix_acl_access"):
# Get the xattr attributes if any
try:
attribute = samba.xattr_native.wrap_getxattr(frompath,
xattr.XATTR_NTACL_NAME)
samba.xattr_native.wrap_setxattr(topath,
xattr.XATTR_NTACL_NAME,
attribute)
except Exception:
pass
# FIXME:Catch a specific exception
:param source: Source tree path
:param target: Target path
def copytree_with_xattrs(src, dst):
"""Recursively copy a directory tree using shutil.copy2(), preserving xattrs.
The destination directory must not already exist.
If exception(s) occur, an Error is raised with a list of reasons.
"""
shutil.copytree(source, target)
copyxattrs(target, source)
names = os.listdir(src)
def copyxattrs(dir, refdir):
"""Copy extended attributes from a reference dir to a destination dir
Both dir are supposed to hold the same files
:param dir: Destination dir
:param refdir: Reference directory"""
for root, dirs, files in os.walk(dir, topdown=True):
for name in files:
subdir = root[len(dir):]
ref = os.path.join(refdir, subdir, name)
statsinfo = os.stat(ref)
tgt = os.path.join(root, name)
try:
os.chown(tgt, statsinfo.st_uid, statsinfo.st_gid)
# Get the xattr attributes if any
try:
attribute = samba.xattr_native.wrap_getxattr(ref,
xattr.XATTR_NTACL_NAME)
samba.xattr_native.wrap_setxattr(tgt,
xattr.XATTR_NTACL_NAME,
attribute)
except Exception:
pass
# FIXME:Catch a specific exception
attribute = samba.xattr_native.wrap_getxattr(ref,
"system.posix_acl_access")
samba.xattr_native.wrap_setxattr(tgt,
"system.posix_acl_access",
attribute)
except Exception:
# FIXME: Catch a specific exception
continue
for name in dirs:
subdir = root[len(dir):]
ref = os.path.join(refdir, subdir, name)
statsinfo = os.stat(ref)
tgt = os.path.join(root, name)
try:
os.chown(os.path.join(root, name), statsinfo.st_uid,
statsinfo.st_gid)
try:
attribute = samba.xattr_native.wrap_getxattr(ref,
xattr.XATTR_NTACL_NAME)
samba.xattr_native.wrap_setxattr(tgt,
xattr.XATTR_NTACL_NAME,
attribute)
except Exception:
pass # FIXME: Catch a specific exception
attribute = samba.xattr_native.wrap_getxattr(ref,
"system.posix_acl_access")
samba.xattr_native.wrap_setxattr(tgt,
"system.posix_acl_access",
attribute)
except Exception:
continue
os.makedirs(dst)
errors = []
for name in names:
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
if os.path.islink(srcname):
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree_with_xattrs(srcname, dstname)
else:
# Will raise a SpecialFileError for unsupported file types
shutil.copy2(srcname, dstname)
shutil.copystat(src, dst)
copyattrs(src, dst)