- related to trac#927

Signed-off-by: Jakub Filak <[email protected]>
---
 src/include/dump_dir.h |  9 +++++++++
 src/lib/dump_dir.c     | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h
index 89c7ff7..0a6a1b0 100644
--- a/src/include/dump_dir.h
+++ b/src/include/dump_dir.h
@@ -83,6 +83,15 @@ int dd_delete_item(struct dump_dir *dd, const char *name);
 /* Returns 0 if directory is deleted or not found */
 int dd_delete(struct dump_dir *dd);
 int dd_rename(struct dump_dir *dd, const char *new_path);
+/* Changes owner of dump dir
+ * Uses two different strategies selected at build time by
+ * DUMP_DIR_OWNED_BY_USER configuration:
+ *  <= 0 : owner = abrt user's uid,  group = new_uid's gid
+ *   > 0 : owner = new_uid,          group = abrt group's gid
+ *
+ * On success, zero is returned. On error, -1 is returned.
+ */
+int dd_chown(struct dump_dir *dd, uid_t new_uid);
 
 
 /* reported_to handling */
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
index dfa19aa..f815848 100644
--- a/src/lib/dump_dir.c
+++ b/src/lib/dump_dir.c
@@ -760,6 +760,58 @@ int dd_delete(struct dump_dir *dd)
     return r;
 }
 
+int dd_chown(struct dump_dir *dd, uid_t new_uid)
+{
+    if (!dd->locked)
+        error_msg_and_die("dump_dir is not opened"); /* bug */
+
+    errno = 0;
+    struct stat statbuf;
+    if (!(stat(dd->dd_dirname, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)))
+    {
+        perror_msg("stat");
+        errno = 0;
+        return 1;
+    }
+
+    struct passwd *pw = getpwuid(new_uid);
+    if (!pw)
+    {
+        error_msg("UID %ld is not found in user database", (long)new_uid);
+        return 1;
+    }
+
+#if DUMP_DIR_OWNED_BY_USER > 0
+    uid_t owners_uid = pw->pw_uid;
+    gid_t groups_gid = statbuf.st_gid;
+#else
+    uid_t owners_uid = statbuf.st_uid;
+    gid_t groups_gid = pw->pw_gid;
+#endif
+
+    int chown_res = lchown(dd->dd_dirname, owners_uid, groups_gid);
+    int chown_errno = errno;
+    dd_init_next_file(dd);
+    char *full_name;
+    while (chown_res == 0 && dd_get_next_file(dd, /*short_name*/ NULL, 
&full_name))
+    {
+        VERB3 log("chowning %s", full_name);
+        chown_res = lchown(full_name, owners_uid, groups_gid);
+        chown_errno = errno;
+        free(full_name);
+    }
+
+    if (chown_res != 0)
+    {
+        errno = chown_errno;
+        perror_msg("chown");
+        errno = 0;
+        return 1;
+    }
+
+    return 0;
+}
+
 static char *load_text_file(const char *path, unsigned flags)
 {
     int fd = open(path, O_RDONLY | ((flags & DD_OPEN_FOLLOW) ? 0 : 
O_NOFOLLOW));
-- 
1.7.11.7

Reply via email to