[libgsystem] fileutils: Add gs_file_create_with_uidgid()



commit f56702ef40a5df056097d2e14ee0dac3614b744c
Author: Colin Walters <walters verbum org>
Date:   Thu Jul 18 14:19:57 2013 -0400

    fileutils: Add gs_file_create_with_uidgid()
    
    If the provided mode includes S_ISUID or S_ISGID, we will successfully
    invoke fchmod(), but then a subsequent chown() will undo any setuid
    bits, even if we're just calling chown for the already extant uid.
    
    This API can reliably create a file with the provided mode and owner.

 gsystem-file-utils.c |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gsystem-file-utils.h |    8 +++++
 2 files changed, 84 insertions(+), 0 deletions(-)
---
diff --git a/gsystem-file-utils.c b/gsystem-file-utils.c
index 31e7331..5510948 100644
--- a/gsystem-file-utils.c
+++ b/gsystem-file-utils.c
@@ -252,6 +252,82 @@ gs_file_sync_data (GFile          *file,
 }
 
 /**
+ * gs_file_create_with_uidgid:
+ * @file: Path of file to create
+ * @mode: Unix mode
+ * @uid: Unix uid
+ * @gid: Unix gid
+ * @out_stream: (out) (transfer full) (allow-none): Output stream connected to file descriptor
+ * @cancellable: a #GCancellable
+ * @error: a #GError
+ *
+ * Create @file exclusively; it must not exist already.  Ensure the
+ * returned file has mode @mode and has Unix owners corresponding to
+ * the parameters @uid and @gid.
+ *
+ * The parameter @out_stream if provided, will be filled in with a
+ * #GOutputStream connected to the file.
+ *
+ * Returns: %TRUE on success, %FALSE on error.
+ */
+gboolean
+gs_file_create_with_uidgid (GFile          *file,
+                            int             mode,
+                            uid_t           uid,
+                            gid_t           gid,
+                            GOutputStream **out_stream,
+                            GCancellable   *cancellable,
+                            GError        **error)
+{
+  gboolean ret = FALSE;
+  int fd;
+  GOutputStream *ret_stream = NULL;
+  static gsize uidgid_cached;
+  static uid_t myuid;
+  static uid_t mygid;
+
+  /* Ok yes this is lame, but calling these two over and over shows up
+   * in strace.  I like my straces to be clean, shoot me.
+   */
+  if (g_once_init_enter (&uidgid_cached))
+    {
+      myuid = getuid ();
+      mygid = getgid ();
+      g_once_init_leave (&uidgid_cached, 1);
+    }
+
+  fd = open_nointr (gs_file_get_path_cached (file), O_WRONLY | O_CREAT | O_EXCL, mode);
+  if (fd < 0)
+    {
+      _set_error_from_errno (error);
+      goto out;
+    }
+
+  if (uid != myuid || gid != mygid)
+    {
+      if (fchown (fd, uid, gid) < 0)
+        {
+          _set_error_from_errno (error);
+          goto out;
+        }
+    }
+
+  if (fchmod (fd, mode) < 0)
+    {
+      _set_error_from_errno (error);
+      goto out;
+    }
+  
+  ret_stream = g_unix_output_stream_new (fd, TRUE);
+  
+  ret = TRUE;
+  gs_transfer_out_value (out_stream, &ret_stream);
+ out:
+  g_clear_object (&ret_stream);
+  return ret;
+}
+
+/**
  * gs_file_create:
  * @file: Path to non-existent file
  * @mode: Unix access permissions
diff --git a/gsystem-file-utils.h b/gsystem-file-utils.h
index 26ee878..d8cd73d 100644
--- a/gsystem-file-utils.h
+++ b/gsystem-file-utils.h
@@ -61,6 +61,14 @@ gboolean gs_file_create (GFile          *file,
                          GCancellable   *cancellable,
                          GError        **error);
 
+gboolean gs_file_create_with_uidgid (GFile          *file,
+                                     int             mode,
+                                     uid_t           uid,
+                                     gid_t           gid,
+                                     GOutputStream **out_stream,
+                                     GCancellable   *cancellable,
+                                     GError        **error);
+
 gboolean gs_file_linkcopy (GFile          *src,
                            GFile          *dest,
                            GFileCopyFlags  flags,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]