]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: Create virFileAccessibleAs function
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 17 Oct 2011 16:00:28 +0000 (18:00 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 25 Oct 2011 07:27:02 +0000 (09:27 +0200)
This function checks if a given path is accessible under
given uid and gid.

src/util/util.c
src/util/util.h

index af2734486e0d30e79fd49c4c3217e232299ff164..bf170f249668bb2d1019479e90f029508daa7c4b 100644 (file)
@@ -671,6 +671,67 @@ virFileIsExecutable(const char *file)
 }
 
 #ifndef WIN32
+/* Check that a file is accessible under certain
+ * user & gid.
+ * @mode can be F_OK, or a bitwise combination of R_OK, W_OK, and X_OK.
+ * see 'man access' for more details.
+ * Returns 0 on success, -1 on fail with errno set.
+ */
+int
+virFileAccessibleAs(const char *path, int mode,
+                    uid_t uid, gid_t gid)
+{
+    pid_t pid = 0;
+    int status, ret = 0;
+    int forkRet = 0;
+
+    if (uid == getuid() &&
+        gid == getgid())
+        return access(path, mode);
+
+    forkRet = virFork(&pid);
+
+    if (pid < 0) {
+        return -1;
+    }
+
+    if (pid) { /* parent */
+        if (virPidWait(pid, &status) < 0) {
+            /* virPidWait() already
+             * reported error */
+                return -1;
+        }
+
+        errno = status;
+        return -1;
+    }
+
+    /* child.
+     * Return positive value here. Parent
+     * will change it to negative one. */
+
+    if (forkRet < 0) {
+        ret = errno;
+        goto childerror;
+    }
+
+    if (virSetUIDGID(uid, gid) < 0) {
+        ret = errno;
+        goto childerror;
+    }
+
+    if (access(path, mode) < 0)
+        ret = errno;
+
+childerror:
+    if ((ret & 0xFF) != ret) {
+        VIR_WARN("unable to pass desired return value %d", ret);
+        ret = 0xFF;
+    }
+
+    _exit(ret);
+}
+
 /* return -errno on failure, or 0 on success */
 static int
 virFileOpenAsNoFork(const char *path, int openflags, mode_t mode,
@@ -993,6 +1054,18 @@ childerror:
 
 #else /* WIN32 */
 
+int
+virFileAccessibleAs(const char *path,
+                    int mode,
+                    uid_t uid ATTRIBUTE_UNUSED,
+                    git_t gid ATTRIBUTE_UNUSED)
+{
+
+    VIR_WARN("Ignoring uid/gid due to WIN32");
+
+    return access(path, mode);
+}
+
 /* return -errno on failure, or 0 on success */
 int virFileOpenAs(const char *path ATTRIBUTE_UNUSED,
                   int openflags ATTRIBUTE_UNUSED,
index c55e85279f26ff99f52d0f32be5e84b0af95d2d4..e869f1bfa823c4e7d5a0f4683a195b2189be894e 100644 (file)
@@ -93,6 +93,9 @@ enum {
     VIR_FILE_OPEN_AS_UID      = (1 << 0),
     VIR_FILE_OPEN_FORCE_PERMS = (1 << 1),
 };
+int virFileAccessibleAs(const char *path, int mode,
+                        uid_t uid, gid_t gid)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
 int virFileOpenAs(const char *path, int openflags, mode_t mode,
                   uid_t uid, gid_t gid,
                   unsigned int flags)