Mercurial > hg > toybox
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);