diff options
Diffstat (limited to 'utility.c')
-rw-r--r-- | utility.c | 341 |
1 files changed, 111 insertions, 230 deletions
@@ -33,102 +33,9 @@ | |||
33 | #include <sys/stat.h> | 33 | #include <sys/stat.h> |
34 | #include <unistd.h> | 34 | #include <unistd.h> |
35 | 35 | ||
36 | #if 0 | ||
37 | |||
38 | extern char *join_paths(char *buffer, const char *a, const char *b) | ||
39 | { | ||
40 | int length = 0; | ||
41 | |||
42 | if (a && *a) { | ||
43 | length = strlen(a); | ||
44 | memcpy(buffer, a, length); | ||
45 | } | ||
46 | if (b && *b) { | ||
47 | if (length > 0 && buffer[length - 1] != '/') | ||
48 | buffer[length++] = '/'; | ||
49 | if (*b == '/') | ||
50 | b++; | ||
51 | strcpy(&buffer[length], b); | ||
52 | } | ||
53 | return buffer; | ||
54 | } | ||
55 | |||
56 | #endif | ||
57 | |||
58 | |||
59 | |||
60 | |||
61 | |||
62 | |||
63 | static CHUNK *chunkList; | ||
64 | |||
65 | |||
66 | /* | ||
67 | * Return the standard ls-like mode string from a file mode. | ||
68 | * This is static and so is overwritten on each call. | ||
69 | */ | ||
70 | const char *modeString(int mode) | ||
71 | { | ||
72 | static char buf[12]; | ||
73 | |||
74 | strcpy(buf, "----------"); | ||
75 | |||
76 | /* | ||
77 | * Fill in the file type. | ||
78 | */ | ||
79 | if (S_ISDIR(mode)) | ||
80 | buf[0] = 'd'; | ||
81 | if (S_ISCHR(mode)) | ||
82 | buf[0] = 'c'; | ||
83 | if (S_ISBLK(mode)) | ||
84 | buf[0] = 'b'; | ||
85 | if (S_ISFIFO(mode)) | ||
86 | buf[0] = 'p'; | ||
87 | #ifdef S_ISLNK | ||
88 | if (S_ISLNK(mode)) | ||
89 | buf[0] = 'l'; | ||
90 | #endif | ||
91 | #ifdef S_ISSOCK | ||
92 | if (S_ISSOCK(mode)) | ||
93 | buf[0] = 's'; | ||
94 | #endif | ||
95 | |||
96 | /* | ||
97 | * Now fill in the normal file permissions. | ||
98 | */ | ||
99 | if (mode & S_IRUSR) | ||
100 | buf[1] = 'r'; | ||
101 | if (mode & S_IWUSR) | ||
102 | buf[2] = 'w'; | ||
103 | if (mode & S_IXUSR) | ||
104 | buf[3] = 'x'; | ||
105 | if (mode & S_IRGRP) | ||
106 | buf[4] = 'r'; | ||
107 | if (mode & S_IWGRP) | ||
108 | buf[5] = 'w'; | ||
109 | if (mode & S_IXGRP) | ||
110 | buf[6] = 'x'; | ||
111 | if (mode & S_IROTH) | ||
112 | buf[7] = 'r'; | ||
113 | if (mode & S_IWOTH) | ||
114 | buf[8] = 'w'; | ||
115 | if (mode & S_IXOTH) | ||
116 | buf[9] = 'x'; | ||
117 | |||
118 | /* | ||
119 | * Finally fill in magic stuff like suid and sticky text. | ||
120 | */ | ||
121 | if (mode & S_ISUID) | ||
122 | buf[3] = ((mode & S_IXUSR) ? 's' : 'S'); | ||
123 | if (mode & S_ISGID) | ||
124 | buf[6] = ((mode & S_IXGRP) ? 's' : 'S'); | ||
125 | if (mode & S_ISVTX) | ||
126 | buf[9] = ((mode & S_IXOTH) ? 't' : 'T'); | ||
127 | |||
128 | return buf; | ||
129 | } | ||
130 | 36 | ||
131 | 37 | ||
38 | #if defined (BB_CP) || defined (BB_MV) | ||
132 | /* | 39 | /* |
133 | * Return TRUE if a fileName is a directory. | 40 | * Return TRUE if a fileName is a directory. |
134 | * Nonexistant files return FALSE. | 41 | * Nonexistant files return FALSE. |
@@ -145,21 +52,6 @@ int isDirectory(const char *name) | |||
145 | 52 | ||
146 | 53 | ||
147 | /* | 54 | /* |
148 | * Return TRUE if a filename is a block or character device. | ||
149 | * Nonexistant files return FALSE. | ||
150 | */ | ||
151 | int isDevice(const char *name) | ||
152 | { | ||
153 | struct stat statBuf; | ||
154 | |||
155 | if (stat(name, &statBuf) < 0) | ||
156 | return FALSE; | ||
157 | |||
158 | return S_ISBLK(statBuf.st_mode) || S_ISCHR(statBuf.st_mode); | ||
159 | } | ||
160 | |||
161 | |||
162 | /* | ||
163 | * Copy one file to another, while possibly preserving its modes, times, | 55 | * Copy one file to another, while possibly preserving its modes, times, |
164 | * and modes. Returns TRUE if successful, or FALSE on a failure with an | 56 | * and modes. Returns TRUE if successful, or FALSE on a failure with an |
165 | * error message output. (Failure is not indicted if the attributes cannot | 57 | * error message output. (Failure is not indicted if the attributes cannot |
@@ -173,47 +65,49 @@ copyFile( | |||
173 | int rfd; | 65 | int rfd; |
174 | int wfd; | 66 | int wfd; |
175 | int rcc; | 67 | int rcc; |
68 | int result; | ||
176 | char buf[BUF_SIZE]; | 69 | char buf[BUF_SIZE]; |
177 | struct stat statBuf1; | 70 | struct stat srcStatBuf; |
178 | struct stat statBuf2; | 71 | struct stat dstStatBuf; |
179 | struct utimbuf times; | 72 | struct utimbuf times; |
180 | 73 | ||
181 | if (stat(srcName, &statBuf1) < 0) { | 74 | if (followLinks == FALSE) |
75 | result = stat(srcName, &srcStatBuf); | ||
76 | else | ||
77 | result = lstat(srcName, &srcStatBuf); | ||
78 | |||
79 | if (result < 0) { | ||
182 | perror(srcName); | 80 | perror(srcName); |
183 | return FALSE; | 81 | return FALSE; |
184 | } | 82 | } |
185 | 83 | ||
186 | if (stat(destName, &statBuf2) < 0) { | 84 | if (followLinks == FALSE) |
187 | statBuf2.st_ino = -1; | 85 | result = stat(destName, &dstStatBuf); |
188 | statBuf2.st_dev = -1; | 86 | else |
87 | result = lstat(destName, &dstStatBuf); | ||
88 | if (result < 0) { | ||
89 | dstStatBuf.st_ino = -1; | ||
90 | dstStatBuf.st_dev = -1; | ||
189 | } | 91 | } |
190 | 92 | ||
191 | if ((statBuf1.st_dev == statBuf2.st_dev) && | 93 | if ((srcStatBuf.st_dev == dstStatBuf.st_dev) && |
192 | (statBuf1.st_ino == statBuf2.st_ino)) { | 94 | (srcStatBuf.st_ino == dstStatBuf.st_ino)) { |
193 | fprintf(stderr, "Copying file \"%s\" to itself\n", srcName); | 95 | fprintf(stderr, "Copying file \"%s\" to itself\n", srcName); |
194 | return FALSE; | 96 | return FALSE; |
195 | } | 97 | } |
196 | 98 | ||
197 | if (S_ISDIR(statBuf1.st_mode)) { | 99 | if (S_ISDIR(srcStatBuf.st_mode)) { |
100 | //fprintf(stderr, "copying directory %s to %s\n", srcName, destName); | ||
198 | /* Make sure the directory is writable */ | 101 | /* Make sure the directory is writable */ |
199 | if (mkdir(destName, 0777777 ^ umask(0))) { | 102 | if (mkdir(destName, 0777777 ^ umask(0))) { |
200 | perror(destName); | 103 | perror(destName); |
201 | return (FALSE); | 104 | return (FALSE); |
202 | } | 105 | } |
203 | } else if (S_ISFIFO(statBuf1.st_mode)) { | 106 | } else if (S_ISLNK(srcStatBuf.st_mode)) { |
204 | if (mkfifo(destName, 644)) { | ||
205 | perror(destName); | ||
206 | return (FALSE); | ||
207 | } | ||
208 | } else if (S_ISBLK(statBuf1.st_mode) || S_ISCHR(statBuf1.st_mode)) { | ||
209 | if (mknod(destName, 644, statBuf1.st_rdev)) { | ||
210 | perror(destName); | ||
211 | return (FALSE); | ||
212 | } | ||
213 | } else if (S_ISLNK(statBuf1.st_mode)) { | ||
214 | char *link_val; | 107 | char *link_val; |
215 | int link_size; | 108 | int link_size; |
216 | 109 | ||
110 | //fprintf(stderr, "copying link %s to %s\n", srcName, destName); | ||
217 | link_val = (char *) alloca(PATH_MAX + 2); | 111 | link_val = (char *) alloca(PATH_MAX + 2); |
218 | link_size = readlink(srcName, link_val, PATH_MAX + 1); | 112 | link_size = readlink(srcName, link_val, PATH_MAX + 1); |
219 | if (link_size < 0) { | 113 | if (link_size < 0) { |
@@ -222,17 +116,31 @@ copyFile( | |||
222 | } | 116 | } |
223 | link_val[link_size] = '\0'; | 117 | link_val[link_size] = '\0'; |
224 | if (symlink(link_val, destName)) { | 118 | if (symlink(link_val, destName)) { |
225 | perror(srcName); | 119 | perror(destName); |
226 | return (FALSE); | 120 | return (FALSE); |
227 | } | 121 | } |
228 | } else { | 122 | } else if (S_ISFIFO(srcStatBuf.st_mode)) { |
123 | //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName); | ||
124 | if (mkfifo(destName, 644)) { | ||
125 | perror(destName); | ||
126 | return (FALSE); | ||
127 | } | ||
128 | } else if (S_ISBLK(srcStatBuf.st_mode) || S_ISCHR(srcStatBuf.st_mode) | ||
129 | || S_ISSOCK (srcStatBuf.st_mode)) { | ||
130 | //fprintf(stderr, "copying soc, blk, or chr %s to %s\n", srcName, destName); | ||
131 | if (mknod(destName, srcStatBuf.st_mode, srcStatBuf.st_rdev)) { | ||
132 | perror(destName); | ||
133 | return (FALSE); | ||
134 | } | ||
135 | } else if (S_ISREG(srcStatBuf.st_mode)) { | ||
136 | //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName); | ||
229 | rfd = open(srcName, O_RDONLY); | 137 | rfd = open(srcName, O_RDONLY); |
230 | if (rfd < 0) { | 138 | if (rfd < 0) { |
231 | perror(srcName); | 139 | perror(srcName); |
232 | return FALSE; | 140 | return FALSE; |
233 | } | 141 | } |
234 | 142 | ||
235 | wfd = creat(destName, statBuf1.st_mode); | 143 | wfd = creat(destName, srcStatBuf.st_mode); |
236 | if (wfd < 0) { | 144 | if (wfd < 0) { |
237 | perror(destName); | 145 | perror(destName); |
238 | close(rfd); | 146 | close(rfd); |
@@ -244,27 +152,25 @@ copyFile( | |||
244 | goto error_exit; | 152 | goto error_exit; |
245 | } | 153 | } |
246 | if (rcc < 0) { | 154 | if (rcc < 0) { |
247 | perror(srcName); | ||
248 | goto error_exit; | 155 | goto error_exit; |
249 | } | 156 | } |
250 | 157 | ||
251 | close(rfd); | 158 | close(rfd); |
252 | |||
253 | if (close(wfd) < 0) { | 159 | if (close(wfd) < 0) { |
254 | perror(destName); | ||
255 | return FALSE; | 160 | return FALSE; |
256 | } | 161 | } |
257 | } | 162 | } |
258 | 163 | ||
259 | if (setModes == TRUE) { | 164 | if (setModes == TRUE) { |
260 | chmod(destName, statBuf1.st_mode); | 165 | //fprintf(stderr, "Setting permissions for %s\n", destName); |
166 | chmod(destName, srcStatBuf.st_mode); | ||
261 | if (followLinks == TRUE) | 167 | if (followLinks == TRUE) |
262 | chown(destName, statBuf1.st_uid, statBuf1.st_gid); | 168 | chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid); |
263 | else | 169 | else |
264 | lchown(destName, statBuf1.st_uid, statBuf1.st_gid); | 170 | lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid); |
265 | 171 | ||
266 | times.actime = statBuf1.st_atime; | 172 | times.actime = srcStatBuf.st_atime; |
267 | times.modtime = statBuf1.st_mtime; | 173 | times.modtime = srcStatBuf.st_mtime; |
268 | 174 | ||
269 | utime(destName, ×); | 175 | utime(destName, ×); |
270 | } | 176 | } |
@@ -273,13 +179,17 @@ copyFile( | |||
273 | 179 | ||
274 | 180 | ||
275 | error_exit: | 181 | error_exit: |
182 | //fprintf(stderr, "choking on %s\n", destName); | ||
183 | perror(destName); | ||
276 | close(rfd); | 184 | close(rfd); |
277 | close(wfd); | 185 | close(wfd); |
278 | 186 | ||
279 | return FALSE; | 187 | return FALSE; |
280 | } | 188 | } |
189 | #endif | ||
281 | 190 | ||
282 | 191 | ||
192 | #ifdef BB_MV | ||
283 | /* | 193 | /* |
284 | * Build a path name from the specified directory name and file name. | 194 | * Build a path name from the specified directory name and file name. |
285 | * If the directory name is NULL, then the original fileName is returned. | 195 | * If the directory name is NULL, then the original fileName is returned. |
@@ -305,106 +215,77 @@ char *buildName(const char *dirName, const char *fileName) | |||
305 | 215 | ||
306 | return buf; | 216 | return buf; |
307 | } | 217 | } |
218 | #endif | ||
308 | 219 | ||
309 | 220 | ||
310 | 221 | ||
311 | /* | 222 | /* |
312 | * Make a NULL-terminated string out of an argc, argv pair. | 223 | * Return the standard ls-like mode string from a file mode. |
313 | * Returns TRUE if successful, or FALSE if the string is too long, | 224 | * This is static and so is overwritten on each call. |
314 | * with an error message given. This does not handle spaces within | ||
315 | * arguments correctly. | ||
316 | */ | ||
317 | int makeString( int argc, const char **argv, char *buf, int bufLen) | ||
318 | { | ||
319 | int len; | ||
320 | |||
321 | while (argc-- > 0) { | ||
322 | len = strlen(*argv); | ||
323 | |||
324 | if (len >= bufLen) { | ||
325 | fprintf(stderr, "Argument string too long\n"); | ||
326 | |||
327 | return FALSE; | ||
328 | } | ||
329 | |||
330 | strcpy(buf, *argv++); | ||
331 | |||
332 | buf += len; | ||
333 | bufLen -= len; | ||
334 | |||
335 | if (argc) | ||
336 | *buf++ = ' '; | ||
337 | |||
338 | bufLen--; | ||
339 | } | ||
340 | |||
341 | *buf = '\0'; | ||
342 | |||
343 | return TRUE; | ||
344 | } | ||
345 | |||
346 | |||
347 | /* | ||
348 | * Allocate a chunk of memory (like malloc). | ||
349 | * The difference, though, is that the memory allocated is put on a | ||
350 | * list of chunks which can be freed all at one time. You CAN NOT free | ||
351 | * an individual chunk. | ||
352 | */ | ||
353 | char *getChunk(int size) | ||
354 | { | ||
355 | CHUNK *chunk; | ||
356 | |||
357 | if (size < CHUNK_INIT_SIZE) | ||
358 | size = CHUNK_INIT_SIZE; | ||
359 | |||
360 | chunk = (CHUNK *) malloc(size + sizeof(CHUNK) - CHUNK_INIT_SIZE); | ||
361 | |||
362 | if (chunk == NULL) | ||
363 | return NULL; | ||
364 | |||
365 | chunk->next = chunkList; | ||
366 | chunkList = chunk; | ||
367 | |||
368 | return chunk->data; | ||
369 | } | ||
370 | |||
371 | |||
372 | /* | ||
373 | * Duplicate a string value using the chunk allocator. | ||
374 | * The returned string cannot be individually freed, but can only be freed | ||
375 | * with other strings when freeChunks is called. Returns NULL on failure. | ||
376 | */ | 225 | */ |
377 | char *chunkstrdup(const char *str) | 226 | const char *modeString(int mode) |
378 | { | 227 | { |
379 | int len; | 228 | static char buf[12]; |
380 | char *newStr; | ||
381 | |||
382 | len = strlen(str) + 1; | ||
383 | newStr = getChunk(len); | ||
384 | 229 | ||
385 | if (newStr) | 230 | strcpy(buf, "----------"); |
386 | memcpy(newStr, str, len); | ||
387 | 231 | ||
388 | return newStr; | 232 | /* |
389 | } | 233 | * Fill in the file type. |
234 | */ | ||
235 | if (S_ISDIR(mode)) | ||
236 | buf[0] = 'd'; | ||
237 | if (S_ISCHR(mode)) | ||
238 | buf[0] = 'c'; | ||
239 | if (S_ISBLK(mode)) | ||
240 | buf[0] = 'b'; | ||
241 | if (S_ISFIFO(mode)) | ||
242 | buf[0] = 'p'; | ||
243 | #ifdef S_ISLNK | ||
244 | if (S_ISLNK(mode)) | ||
245 | buf[0] = 'l'; | ||
246 | #endif | ||
247 | #ifdef S_ISSOCK | ||
248 | if (S_ISSOCK(mode)) | ||
249 | buf[0] = 's'; | ||
250 | #endif | ||
390 | 251 | ||
252 | /* | ||
253 | * Now fill in the normal file permissions. | ||
254 | */ | ||
255 | if (mode & S_IRUSR) | ||
256 | buf[1] = 'r'; | ||
257 | if (mode & S_IWUSR) | ||
258 | buf[2] = 'w'; | ||
259 | if (mode & S_IXUSR) | ||
260 | buf[3] = 'x'; | ||
261 | if (mode & S_IRGRP) | ||
262 | buf[4] = 'r'; | ||
263 | if (mode & S_IWGRP) | ||
264 | buf[5] = 'w'; | ||
265 | if (mode & S_IXGRP) | ||
266 | buf[6] = 'x'; | ||
267 | if (mode & S_IROTH) | ||
268 | buf[7] = 'r'; | ||
269 | if (mode & S_IWOTH) | ||
270 | buf[8] = 'w'; | ||
271 | if (mode & S_IXOTH) | ||
272 | buf[9] = 'x'; | ||
391 | 273 | ||
392 | /* | 274 | /* |
393 | * Free all chunks of memory that had been allocated since the last | 275 | * Finally fill in magic stuff like suid and sticky text. |
394 | * call to this routine. | 276 | */ |
395 | */ | 277 | if (mode & S_ISUID) |
396 | void freeChunks(void) | 278 | buf[3] = ((mode & S_IXUSR) ? 's' : 'S'); |
397 | { | 279 | if (mode & S_ISGID) |
398 | CHUNK *chunk; | 280 | buf[6] = ((mode & S_IXGRP) ? 's' : 'S'); |
281 | if (mode & S_ISVTX) | ||
282 | buf[9] = ((mode & S_IXOTH) ? 't' : 'T'); | ||
399 | 283 | ||
400 | while (chunkList) { | 284 | return buf; |
401 | chunk = chunkList; | ||
402 | chunkList = chunk->next; | ||
403 | free((char *) chunk); | ||
404 | } | ||
405 | } | 285 | } |
406 | 286 | ||
407 | 287 | ||
288 | #ifdef BB_TAR | ||
408 | /* | 289 | /* |
409 | * Get the time string to be used for a file. | 290 | * Get the time string to be used for a file. |
410 | * This is down to the minute for new files, but only the date for old files. | 291 | * This is down to the minute for new files, but only the date for old files. |
@@ -577,8 +458,10 @@ int fullRead(int fd, char *buf, int len) | |||
577 | 458 | ||
578 | return total; | 459 | return total; |
579 | } | 460 | } |
461 | #endif | ||
580 | 462 | ||
581 | 463 | ||
464 | #if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS) | ||
582 | /* | 465 | /* |
583 | * Walk down all the directories under the specified | 466 | * Walk down all the directories under the specified |
584 | * location, and do something (something specified | 467 | * location, and do something (something specified |
@@ -618,7 +501,6 @@ recursiveAction(const char *fileName, int recurse, int followLinks, | |||
618 | 501 | ||
619 | if (S_ISDIR(statbuf.st_mode)) { | 502 | if (S_ISDIR(statbuf.st_mode)) { |
620 | DIR *dir; | 503 | DIR *dir; |
621 | fprintf(stderr, "Dir: %s\n", fileName); | ||
622 | dir = opendir(fileName); | 504 | dir = opendir(fileName); |
623 | if (!dir) { | 505 | if (!dir) { |
624 | perror(fileName); | 506 | perror(fileName); |
@@ -627,7 +509,7 @@ recursiveAction(const char *fileName, int recurse, int followLinks, | |||
627 | if (dirAction != NULL) { | 509 | if (dirAction != NULL) { |
628 | status = dirAction(fileName); | 510 | status = dirAction(fileName); |
629 | if (status == FALSE) { | 511 | if (status == FALSE) { |
630 | perror("cp"); | 512 | perror(fileName); |
631 | return (FALSE); | 513 | return (FALSE); |
632 | } | 514 | } |
633 | } | 515 | } |
@@ -652,7 +534,6 @@ recursiveAction(const char *fileName, int recurse, int followLinks, | |||
652 | return (FALSE); | 534 | return (FALSE); |
653 | } | 535 | } |
654 | } else { | 536 | } else { |
655 | fprintf(stderr, "File: %s\n", fileName); | ||
656 | if (fileAction == NULL) | 537 | if (fileAction == NULL) |
657 | return (TRUE); | 538 | return (TRUE); |
658 | else | 539 | else |
@@ -661,6 +542,6 @@ recursiveAction(const char *fileName, int recurse, int followLinks, | |||
661 | return (TRUE); | 542 | return (TRUE); |
662 | } | 543 | } |
663 | 544 | ||
664 | 545 | #endif | |
665 | 546 | ||
666 | /* END CODE */ | 547 | /* END CODE */ |