[PATCH 1/3] Add a function to recursively change owner of a directory

Vratislav Podzimek vpodzime at redhat.com
Wed Jun 5 12:17:19 UTC 2013


Implemented by using a universal function for mapping a function on the
directory tree.

Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
 pyanaconda/iutil.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 7020da5..ff36405 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -628,3 +628,79 @@ def cmp_obj_attrs(obj1, obj2, attr_list):
         else:
             return False
     return True
+
+def dir_tree_map(root, func, files=True, dirs=True):
+    """
+    Apply the given function to all files and directories in the directory tree
+    under the given root directory.
+
+    :param root: root of the directory tree the function should be mapped to
+    :type root: str
+    :param func: a function taking the directory/file path
+    :type func: path -> None
+    :param files: whether to apply the function to the files in the dir. tree
+    :type files: bool
+    :param dirs: whether to apply the function to the directories in the dir. tree
+    :type dirs: bool
+
+    TODO: allow using globs and thus more trees?
+
+    """
+
+    for (dir_ent, dir_items, file_items) in os.walk(root):
+        if dirs:
+            # try to call the function on the directory entry
+            try:
+                func(dir_ent)
+            except:
+                pass
+
+        if files:
+            # try to call the function on the files in the directory entry
+            for file_ent in (os.path.join(dir_ent, f) for f in file_items):
+                try:
+                    func(file_ent)
+                except:
+                    pass
+
+        # directories under the directory entry will appear as directory entries
+        # in the loop
+
+def chown_dir_tree(root, uid, gid, from_uid_only=None, from_gid_only=None):
+    """
+    Change owner (uid and gid) of the files and directories under the given
+    directory tree (recursively).
+
+    :param root: root of the directory tree that should be chown'ed
+    :type root: str
+    :param uid: UID that should be set as the owner
+    :type uid: int
+    :param gid: GID that should be set as the owner
+    :type gid: int
+    :param from_uid_only: if given, the owner is changed only for the files and
+                          directories owned by that UID
+    :type from_uid_only: int or None
+    :param from_gid_only: if given, the owner is changed only for the files and
+                          directories owned by that GID
+    :type from_gid_only: int or None
+
+    """
+
+    def conditional_chown(path, uid, gid, from_uid=None, from_gid=None):
+        stats = os.stat(path)
+        if (from_uid and stats.st_uid != from_uid) or \
+                (from_gid and stats.st_gid != from_gid):
+            # owner UID or GID not matching, do nothing
+            return
+
+        # UID and GID matching or not required
+        os.chown(path, uid, gid)
+
+    if not from_uid_only and not from_gid_only:
+        # the easy way
+        dir_tree_map(root, lambda path: os.chown(path, uid, gid))
+    else:
+        # conditional chown
+        dir_tree_map(root, lambda path: conditional_chown(path, uid, gid,
+                                                          from_uid_only,
+                                                          from_gid_only))
-- 
1.7.11.7



More information about the anaconda-patches mailing list