changeset 1219:468444e5c7c5 draft

Move mkpathat to lib, remove redundant function used by patch.
author Rob Landley <rob@landley.net>
date Tue, 11 Mar 2014 20:44:55 -0500
parents fba5d8d3905c
children 10d4dd6621cb
files lib/lib.c lib/lib.h lib/xwrap.c toys/posix/mkdir.c toys/posix/patch.c
diffstat 5 files changed, 52 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/lib/lib.c	Tue Mar 11 18:11:12 2014 -0500
+++ b/lib/lib.c	Tue Mar 11 20:44:55 2014 -0500
@@ -116,6 +116,55 @@
   return offset;
 }
 
+// flags: 1=make last dir (with mode lastmode, otherwise skips last component)
+//        2=make path (already exists is ok)
+//        4=verbose
+// returns 0 = path ok, 1 = error
+int mkpathat(int atfd, char *dir, mode_t lastmode, int flags)
+{
+  struct stat buf;
+  char *s;
+
+  // mkdir -p one/two/three is not an error if the path already exists,
+  // but is if "three" is a file. The others we dereference and catch
+  // not-a-directory along the way, but the last one we must explicitly
+  // test for. Might as well do it up front.
+
+  if (!fstatat(atfd, dir, &buf, 0) && !S_ISDIR(buf.st_mode)) {
+    errno = EEXIST;
+    return 1;
+  }
+
+  // Skip leading / of absolute paths
+  while (*dir == '/') dir++;
+
+  for (s=dir; ;s++) {
+    char save = 0;
+    mode_t mode = (0777&~toys.old_umask)|0300;
+
+    // Skip leading / of absolute paths.
+    if (*s == '/' && (flags&2)) {
+      save = *s;
+      *s = 0;
+    } else if (*s) continue;
+
+    // Use the mode from the -m option only for the last directory.
+    if (!save) {
+      if (flags&1) mode = lastmode;
+      else break;
+    }
+
+    if (mkdirat(atfd, dir, mode)) {
+      if (!(flags&2) || errno != EEXIST) return 1;
+    } else if (flags&4)
+      fprintf(stderr, "%s: created directory '%s'\n", toys.which->name, dir);
+    
+    if (!(*s = save)) break;
+  }
+
+  return 0;
+}
+
 // Split a path into linked list of components, tracking head and tail of list.
 // Filters out // entries with no contents.
 struct string_list **splitpath(char *path, struct string_list **list)
--- a/lib/lib.h	Tue Mar 11 18:11:12 2014 -0500
+++ b/lib/lib.h	Tue Mar 11 20:44:55 2014 -0500
@@ -110,7 +110,6 @@
 char *xrealpath(char *path);
 void xchdir(char *path);
 void xchroot(char *path);
-void xmkpath(char *path, int mode);
 struct passwd *xgetpwuid(uid_t uid);
 struct group *xgetgrgid(gid_t gid);
 struct passwd *xgetpwnam(char *name);
@@ -128,6 +127,7 @@
 ssize_t readall(int fd, void *buf, size_t len);
 ssize_t writeall(int fd, void *buf, size_t len);
 off_t lskip(int fd, off_t offset);
+int mkpathat(int atfd, char *dir, mode_t lastmode, int flags);
 struct string_list **splitpath(char *path, struct string_list **list);
 char *readfile(char *name, char *buf, off_t len);
 void msleep(long miliseconds);
--- a/lib/xwrap.c	Tue Mar 11 18:11:12 2014 -0500
+++ b/lib/xwrap.c	Tue Mar 11 20:44:55 2014 -0500
@@ -369,34 +369,6 @@
   xchdir("/");
 }
 
-// Ensure entire path exists.
-// If mode != -1 set permissions on newly created dirs.
-// Requires that path string be writable (for temporary null terminators).
-void xmkpath(char *path, int mode)
-{
-  char *p, old;
-  mode_t mask;
-  int rc;
-  struct stat st;
-
-  for (p = path; ; p++) {
-    if (!*p || *p == '/') {
-      old = *p;
-      *p = rc = 0;
-      if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
-        if (mode != -1) {
-          mask=umask(0);
-          rc = mkdir(path, mode);
-          umask(mask);
-        } else rc = mkdir(path, 0777);
-      }
-      *p = old;
-      if(rc) perror_exit("mkpath '%s'", path);
-    }
-    if (!*p) break;
-  }
-}
-
 struct passwd *xgetpwuid(uid_t uid)
 {
   struct passwd *pwd = getpwuid(uid);
--- a/toys/posix/mkdir.c	Tue Mar 11 18:11:12 2014 -0500
+++ b/toys/posix/mkdir.c	Tue Mar 11 20:44:55 2014 -0500
@@ -25,55 +25,6 @@
   char *arg_mode;
 )
 
-// flags: 1=make last dir (with mode lastmode, otherwise skips last component)
-//        2=make path (already exists is ok)
-//        4=verbose
-// returns 0 = path ok, 1 = error
-int mkpathat(int atfd, char *dir, mode_t lastmode, int flags)
-{
-  struct stat buf;
-  char *s;
-
-  // mkdir -p one/two/three is not an error if the path already exists,
-  // but is if "three" is a file. The others we dereference and catch
-  // not-a-directory along the way, but the last one we must explicitly
-  // test for. Might as well do it up front.
-
-  if (!fstatat(atfd, dir, &buf, 0) && !S_ISDIR(buf.st_mode)) {
-    errno = EEXIST;
-    return 1;
-  }
-
-  // Skip leading / of absolute paths
-  while (*dir == '/') dir++;
-
-  for (s=dir; ;s++) {
-    char save = 0;
-    mode_t mode = (0777&~toys.old_umask)|0300;
-
-    // Skip leading / of absolute paths.
-    if (*s == '/' && (flags&2)) {
-      save = *s;
-      *s = 0;
-    } else if (*s) continue;
-
-    // Use the mode from the -m option only for the last directory.
-    if (!save) {
-      if (flags&1) mode = lastmode;
-      else break;
-    }
-
-    if (mkdirat(atfd, dir, mode)) {
-      if (!(flags&2) || errno != EEXIST) return 1;
-    } else if (flags&4)
-      fprintf(stderr, "%s: created directory '%s'\n", toys.which->name, dir);
-    
-    if (!(*s = save)) break;
-  }
-
-  return 0;
-}
-
 void mkdir_main(void)
 {
   char **s;
--- a/toys/posix/patch.c	Tue Mar 11 18:11:12 2014 -0500
+++ b/toys/posix/patch.c	Tue Mar 11 20:44:55 2014 -0500
@@ -385,12 +385,8 @@
           if ((!strcmp(oldname, "/dev/null") || !oldsum) && access(name, F_OK))
           {
             printf("creating %s\n", name);
-            s = strrchr(name, '/');
-            if (s) {
-              *s = 0;
-              xmkpath(name, -1);
-              *s = '/';
-            }
+            if (mkpathat(AT_FDCWD, name, 0, 2))
+              perror_exit("mkpath %s", name);
             TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666);
           } else {
             printf("patching %s\n", name);