aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-11-29 07:45:33 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2009-11-29 07:45:33 +0100
commitf94c9bf288290c9f4e5a7c2745922abd600e88ca (patch)
tree57289568fb310466798ae6b297fe46d6e3d2bfcf /libbb
parent2ce42e98d799de4c3389d9c4ce0a6b0d42dac7cc (diff)
downloadbusybox-w32-f94c9bf288290c9f4e5a7c2745922abd600e88ca.tar.gz
busybox-w32-f94c9bf288290c9f4e5a7c2745922abd600e88ca.tar.bz2
busybox-w32-f94c9bf288290c9f4e5a7c2745922abd600e88ca.zip
tar: fix bug 673 (misdetection of repeated dir as hardlink). +92 bytes
While at it, remove many superfluous ops on unpack: mkdir("."), lots of umask() calls. Can remove more by caching username->uid. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb')
-rw-r--r--libbb/make_directory.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index a4ad59975..4486eb1ed 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -28,53 +28,76 @@
28 28
29int FAST_FUNC bb_make_directory(char *path, long mode, int flags) 29int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
30{ 30{
31 mode_t mask; 31 mode_t cur_mask;
32 mode_t org_mask;
32 const char *fail_msg; 33 const char *fail_msg;
33 char *s = path; 34 char *s;
34 char c; 35 char c;
35 struct stat st; 36 struct stat st;
36 37
37 mask = umask(0); 38 /* Happens on bb_make_directory(dirname("no_slashes"),...) */
38 umask(mask & ~0300); /* Ensure intermediate dirs are wx */ 39 if (LONE_CHAR(path, '.'))
40 return 0;
39 41
42 org_mask = cur_mask = (mode_t)-1L;
43 s = path;
40 while (1) { 44 while (1) {
41 c = '\0'; 45 c = '\0';
42 46
43 if (flags & FILEUTILS_RECUR) { /* Get the parent. */ 47 if (flags & FILEUTILS_RECUR) { /* Get the parent */
44 /* Bypass leading non-'/'s and then subsequent '/'s. */ 48 /* Bypass leading non-'/'s and then subsequent '/'s */
45 while (*s) { 49 while (*s) {
46 if (*s == '/') { 50 if (*s == '/') {
47 do { 51 do {
48 ++s; 52 ++s;
49 } while (*s == '/'); 53 } while (*s == '/');
50 c = *s; /* Save the current char */ 54 c = *s; /* Save the current char */
51 *s = '\0'; /* and replace it with nul. */ 55 *s = '\0'; /* and replace it with nul */
52 break; 56 break;
53 } 57 }
54 ++s; 58 ++s;
55 } 59 }
56 } 60 }
57 61
58 if (!c) /* Last component uses orig umask */ 62 if (c != '\0') {
59 umask(mask); 63 /* Intermediate dirs: must have wx for user */
64 if (cur_mask == (mode_t)-1L) { /* wasn't done yet? */
65 mode_t new_mask;
66 org_mask = umask(0);
67 cur_mask = 0;
68 /* Clear u=wx in umask - this ensures
69 * they won't be cleared on mkdir */
70 new_mask = (org_mask & ~(mode_t)0300);
71 //bb_error_msg("org_mask:%o cur_mask:%o", org_mask, new_mask);
72 if (new_mask != cur_mask) {
73 cur_mask = new_mask;
74 umask(new_mask);
75 }
76 }
77 } else {
78 /* Last component: uses original umask */
79 //bb_error_msg("1 org_mask:%o", org_mask);
80 if (org_mask != cur_mask) {
81 cur_mask = org_mask;
82 umask(org_mask);
83 }
84 }
60 85
61 if (mkdir(path, 0777) < 0) { 86 if (mkdir(path, 0777) < 0) {
62 /* If we failed for any other reason than the directory 87 /* If we failed for any other reason than the directory
63 * already exists, output a diagnostic and return -1. */ 88 * already exists, output a diagnostic and return -1 */
64 if (errno != EEXIST 89 if (errno != EEXIST
65 || !(flags & FILEUTILS_RECUR) 90 || !(flags & FILEUTILS_RECUR)
66 || ((stat(path, &st) < 0) || !S_ISDIR(st.st_mode)) 91 || ((stat(path, &st) < 0) || !S_ISDIR(st.st_mode))
67 ) { 92 ) {
68 fail_msg = "create"; 93 fail_msg = "create";
69 umask(mask);
70 break; 94 break;
71 } 95 }
72 /* Since the directory exists, don't attempt to change 96 /* Since the directory exists, don't attempt to change
73 * permissions if it was the full target. Note that 97 * permissions if it was the full target. Note that
74 * this is not an error condition. */ 98 * this is not an error condition. */
75 if (!c) { 99 if (!c) {
76 umask(mask); 100 goto ret0;
77 return 0;
78 } 101 }
79 } 102 }
80 103
@@ -86,13 +109,21 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
86 fail_msg = "set permissions of"; 109 fail_msg = "set permissions of";
87 break; 110 break;
88 } 111 }
89 return 0; 112 goto ret0;
90 } 113 }
91 114
92 /* Remove any inserted nul from the path (recursive mode). */ 115 /* Remove any inserted nul from the path (recursive mode) */
93 *s = c; 116 *s = c;
94 } /* while (1) */ 117 } /* while (1) */
95 118
96 bb_perror_msg("can't %s directory '%s'", fail_msg, path); 119 bb_perror_msg("can't %s directory '%s'", fail_msg, path);
97 return -1; 120 flags = -1;
121 goto ret;
122 ret0:
123 flags = 0;
124 ret:
125 //bb_error_msg("2 org_mask:%o", org_mask);
126 if (org_mask != cur_mask)
127 umask(org_mask);
128 return flags;
98} 129}