]> git.saurik.com Git - apple/libc.git/blobdiff - darwin/_dirhelper.c
Libc-583.tar.gz
[apple/libc.git] / darwin / _dirhelper.c
index c28a0cc86fd3f814cf2dd742117b3315c9632281..c25abd101eccea0c7d7731b93b1ec84aeeddc25a 100644 (file)
@@ -136,6 +136,23 @@ __user_local_dirname(uid_t uid, dirhelper_which_t which, char *path, size_t path
     return path;
 }
 
+char *
+__user_local_mkdir_p(char *path)
+{
+    char *next;
+    int res;
+    
+    next = path + strlen(VAR_FOLDERS_PATH);
+    while ((next = strchr(next, '/')) != NULL) {
+       *next = 0; // temporarily truncate
+       res = mkdir(path, 0755);
+       if (res != 0 && errno != EEXIST)
+           return NULL;
+       *next++ = '/'; // restore the slash and increment
+    }
+    return path;
+}
+
 __private_extern__ char *
 _dirhelper(dirhelper_which_t which, char *path, size_t pathlen)
 {
@@ -151,42 +168,54 @@ _dirhelper(dirhelper_which_t which, char *path, size_t pathlen)
 
     if(!*userdir) {
        MUTEX_LOCK(&lock);
-       if(!*userdir) {
-           mach_port_t mp;
-
-           if(bootstrap_look_up(bootstrap_port, DIRHELPER_BOOTSTRAP_NAME, &mp) != KERN_SUCCESS) {
-               errno = EPERM;
-               MUTEX_UNLOCK(&lock);
-               return NULL;
-           }
+       if (!*userdir) {
+           
            if(__user_local_dirname(geteuid(), DIRHELPER_USER_LOCAL, userdir, sizeof(userdir)) == NULL) {
-server_error:
-               mach_port_deallocate(mach_task_self(), mp);
                MUTEX_UNLOCK(&lock);
                return NULL;
            }
            /*
-            * check if userdir exists, and if not, call
-            * __dirhelper_create_user_local to create it
-            * (we have to check again afterwards).
+            * check if userdir exists, and if not, either do the work
+            * ourself if we are root, or call
+            * __dirhelper_create_user_local to create it (we have to
+            * check again afterwards).
             */
            if(stat(userdir, &sb) < 0) {
+               mach_port_t mp;
+               
                if(errno != ENOENT) { /* some unknown error */
                    *userdir = 0;
-                   goto server_error;
-               }
-               if(__dirhelper_create_user_local(mp) != KERN_SUCCESS) {
-                   errno = EPERM;
-                   *userdir = 0;
-                   goto server_error;
+                   MUTEX_UNLOCK(&lock);
+                   return NULL;
                }
-               /* double check that the directory really got created */
-               if(stat(userdir, &sb) < 0) {
-                   *userdir = 0;
-                   goto server_error;
+               /*
+                * If we are root, lets do what dirhelper does for us.
+                */
+               if (geteuid() == 0) {
+                   if (__user_local_mkdir_p(userdir) == NULL) {
+                       *userdir = 0;
+                       MUTEX_UNLOCK(&lock);
+                       return NULL;
+                   }
+               } else {
+                   if(bootstrap_look_up(bootstrap_port, DIRHELPER_BOOTSTRAP_NAME, &mp) != KERN_SUCCESS) {
+                       errno = EPERM;
+                   server_error:
+                       mach_port_deallocate(mach_task_self(), mp);
+                       MUTEX_UNLOCK(&lock);
+                       return NULL;
+                   }
+                   if(__dirhelper_create_user_local(mp) != KERN_SUCCESS) {
+                       errno = EPERM;
+                       goto server_error;
+                   }
+                   /* double check that the directory really got created */
+                   if(stat(userdir, &sb) < 0) {
+                       goto server_error;
+                   }
+                   mach_port_deallocate(mach_task_self(), mp);
                }
            }
-           mach_port_deallocate(mach_task_self(), mp);
        }
        MUTEX_UNLOCK(&lock);
     }