diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2003-03-19 09:13:01 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2003-03-19 09:13:01 +0000 |
commit | cad5364599eb5062d59e0c397ed638ddd61a8d5d (patch) | |
tree | a318d0f03aa076c74b576ea45dc543a5669e8e91 /libbb/make_directory.c | |
parent | e01f9662a5bd5d91be4f6b3941b57fff73cd5af1 (diff) | |
download | busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.tar.gz busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.tar.bz2 busybox-w32-cad5364599eb5062d59e0c397ed638ddd61a8d5d.zip |
Major coreutils update.
Diffstat (limited to 'libbb/make_directory.c')
-rw-r--r-- | libbb/make_directory.c | 118 |
1 files changed, 72 insertions, 46 deletions
diff --git a/libbb/make_directory.c b/libbb/make_directory.c index 65be397bf..e3d2c52b1 100644 --- a/libbb/make_directory.c +++ b/libbb/make_directory.c | |||
@@ -1,12 +1,8 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /* | 2 | /* |
3 | * Mini make_directory implementation for busybox | 3 | * parse_mode implementation for busybox |
4 | * | 4 | * |
5 | * Copyright (C) 2001 Matt Kraai. | 5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> |
6 | * | ||
7 | * Rewriten in 2002 | ||
8 | * Copyright (C) 2002 Glenn McGrath | ||
9 | * Copyright (C) 2002 Vladimir N. Oleynik | ||
10 | * | 6 | * |
11 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -24,57 +20,87 @@ | |||
24 | * | 20 | * |
25 | */ | 21 | */ |
26 | 22 | ||
23 | /* Mar 5, 2003 Manuel Novoa III | ||
24 | * | ||
25 | * This is the main work function for the 'mkdir' applet. As such, it | ||
26 | * strives to be SUSv3 compliant in it's behaviour when recursively | ||
27 | * making missing parent dirs, and in it's mode setting of the final | ||
28 | * directory 'path'. | ||
29 | * | ||
30 | * To recursively build all missing intermediate directories, make | ||
31 | * sure that (flags & FILEUTILS_RECUR) is non-zero. Newly created | ||
32 | * intermediate directories will have at least u+wx perms. | ||
33 | * | ||
34 | * To set specific permisions on 'path', pass the appropriate 'mode' | ||
35 | * val. Otherwise, pass -1 to get default permisions. | ||
36 | */ | ||
37 | |||
27 | #include <errno.h> | 38 | #include <errno.h> |
28 | #include <fcntl.h> | ||
29 | #include <string.h> | ||
30 | #include <sys/stat.h> | ||
31 | #include <sys/types.h> | ||
32 | #include <unistd.h> | 39 | #include <unistd.h> |
33 | #include <stdlib.h> | ||
34 | |||
35 | #include "libbb.h" | 40 | #include "libbb.h" |
36 | 41 | ||
37 | /* Create the directory PATH with mode MODE, or the default if MODE is -1. | 42 | int bb_make_directory (char *path, long mode, int flags) |
38 | * Also create parent directories as necessary if flags contains | ||
39 | * FILEUTILS_RECUR. */ | ||
40 | |||
41 | int make_directory (char *path, long mode, int flags) | ||
42 | { | 43 | { |
43 | int ret; | 44 | mode_t mask; |
44 | 45 | const char *fail_msg; | |
45 | if (flags == FILEUTILS_RECUR) { | 46 | char *s = path; |
46 | char *pp = strrchr(path, '/'); | 47 | char c; |
47 | if ((pp) && (pp != path)) { | ||
48 | *pp = '\0'; | ||
49 | make_directory(path, -1, flags); | ||
50 | *pp = '/'; | ||
51 | } | ||
52 | } | ||
53 | 48 | ||
54 | if (mode == -1) { | 49 | mask = umask(0); |
55 | struct stat statbuf; | 50 | umask(mask & ~0300); |
56 | char *pp = strrchr(path, '/'); | ||
57 | 51 | ||
58 | statbuf.st_mode = 0777; | 52 | do { |
53 | c = 0; | ||
59 | 54 | ||
60 | /* stat the directory */ | 55 | if (flags & FILEUTILS_RECUR) { /* Get the parent. */ |
61 | if ((pp) && (pp != path)) { | 56 | /* Bypass leading non-'/'s and then subsequent '/'s. */ |
62 | *pp = '\0'; | 57 | while (*s) { |
63 | stat(path, &statbuf); | 58 | if (*s == '/') { |
64 | *pp = '/'; | 59 | do { |
60 | ++s; | ||
61 | } while (*s == '/'); | ||
62 | c = *s; /* Save the current char */ | ||
63 | *s = 0; /* and replace it with nul. */ | ||
64 | break; | ||
65 | } | ||
66 | ++s; | ||
67 | } | ||
65 | } | 68 | } |
66 | 69 | ||
67 | mode = statbuf.st_mode; | 70 | if (mkdir(path, 0777) < 0) { |
68 | } | 71 | /* If we failed for any other reason than the directory |
72 | * already exists, output a diagnostic and return -1.*/ | ||
73 | if (errno != EEXIST) { | ||
74 | fail_msg = "create"; | ||
75 | umask(mask); | ||
76 | break; | ||
77 | } | ||
78 | /* Since the directory exists, don't attempt to change | ||
79 | * permissions if it was the full target. Note that | ||
80 | * this is not an error conditon. */ | ||
81 | if (!c) { | ||
82 | umask(mask); | ||
83 | return 0; | ||
84 | } | ||
85 | } | ||
69 | 86 | ||
70 | ret = mkdir(path, mode); | 87 | if (!c) { |
71 | if (ret == -1) { | 88 | /* Done. If necessary, updated perms on the newly |
72 | if ((flags == FILEUTILS_RECUR) && (errno == EEXIST)) { | 89 | * created directory. Failure to update here _is_ |
73 | ret = 0; | 90 | * an error.*/ |
74 | } else { | 91 | umask(mask); |
75 | perror_msg_and_die("Cannot create directory '%s'", path); | 92 | if ((mode != -1) && (chmod(path, mode) < 0)){ |
93 | fail_msg = "set permissions of"; | ||
94 | break; | ||
95 | } | ||
96 | return 0; | ||
76 | } | 97 | } |
77 | } | ||
78 | 98 | ||
79 | return(ret); | 99 | /* Remove any inserted nul from the path (recursive mode). */ |
100 | *s = c; | ||
101 | |||
102 | } while (1); | ||
103 | |||
104 | bb_perror_msg ("Cannot %s directory `%s'", fail_msg, path); | ||
105 | return -1; | ||
80 | } | 106 | } |