blob: fa9849160effc1f4207cf4cce4f945eca4af167e [file] [log] [blame]
Eric Andersencc8ed391999-10-05 16:24:54 +00001/*
2 * Utility routines.
3 *
4 * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Based in part on code from sash, Copyright (c) 1999 by David I. Bell
21 * Permission has been granted to redistribute this code under the GPL.
22 *
23 */
24
Eric Andersen2b69c401999-10-05 22:58:32 +000025#include "internal.h"
26#include <stdio.h>
27#include <string.h>
28#include <errno.h>
29#include <fcntl.h>
Eric Andersen2b69c401999-10-05 22:58:32 +000030#include <dirent.h>
31#include <time.h>
32#include <utime.h>
Eric Andersenf811e071999-10-09 00:25:00 +000033#include <sys/stat.h>
34#include <unistd.h>
Eric Andersence8f3b91999-10-20 07:03:36 +000035#include <ctype.h>
Eric Andersencc8ed391999-10-05 16:24:54 +000036
Eric Andersenb0e9a701999-10-18 22:28:26 +000037/* volatile so gcc knows this is the enod of the line */
38volatile void usage(const char *usage)
39{
40 fprintf(stderr, "Usage: %s\n", usage);
41 exit(FALSE);
42}
43
44
Eric Andersenc6cb79d1999-10-13 18:01:10 +000045
46#if defined (BB_CP) || defined (BB_MV)
47/*
48 * Return TRUE if a fileName is a directory.
49 * Nonexistant files return FALSE.
50 */
51int isDirectory(const char *name)
Eric Andersencc8ed391999-10-05 16:24:54 +000052{
Eric Andersenc6cb79d1999-10-13 18:01:10 +000053 struct stat statBuf;
Eric Andersencc8ed391999-10-05 16:24:54 +000054
Eric Andersenc6cb79d1999-10-13 18:01:10 +000055 if (stat(name, &statBuf) < 0)
56 return FALSE;
Eric Andersen9b587181999-10-17 05:43:39 +000057 if (S_ISDIR(statBuf.st_mode))
58 return TRUE;
59 return(FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +000060}
61
Eric Andersenc6cb79d1999-10-13 18:01:10 +000062
63/*
64 * Copy one file to another, while possibly preserving its modes, times,
65 * and modes. Returns TRUE if successful, or FALSE on a failure with an
66 * error message output. (Failure is not indicted if the attributes cannot
67 * be set.)
68 */
69int
Eric Andersen3c163821999-10-14 22:16:57 +000070copyFile( const char *srcName, const char *destName,
71 int setModes, int followLinks)
Eric Andersenc6cb79d1999-10-13 18:01:10 +000072{
73 int rfd;
74 int wfd;
75 int rcc;
76 int result;
77 char buf[BUF_SIZE];
78 struct stat srcStatBuf;
79 struct stat dstStatBuf;
80 struct utimbuf times;
81
82 if (followLinks == FALSE)
83 result = stat(srcName, &srcStatBuf);
84 else
85 result = lstat(srcName, &srcStatBuf);
Eric Andersenc6cb79d1999-10-13 18:01:10 +000086 if (result < 0) {
87 perror(srcName);
88 return FALSE;
89 }
90
91 if (followLinks == FALSE)
92 result = stat(destName, &dstStatBuf);
93 else
94 result = lstat(destName, &dstStatBuf);
95 if (result < 0) {
96 dstStatBuf.st_ino = -1;
97 dstStatBuf.st_dev = -1;
98 }
99
100 if ((srcStatBuf.st_dev == dstStatBuf.st_dev) &&
101 (srcStatBuf.st_ino == dstStatBuf.st_ino)) {
102 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName);
103 return FALSE;
104 }
105
106 if (S_ISDIR(srcStatBuf.st_mode)) {
107 //fprintf(stderr, "copying directory %s to %s\n", srcName, destName);
108 /* Make sure the directory is writable */
109 if (mkdir(destName, 0777777 ^ umask(0))) {
110 perror(destName);
111 return (FALSE);
112 }
113 } else if (S_ISLNK(srcStatBuf.st_mode)) {
114 char *link_val;
115 int link_size;
116
117 //fprintf(stderr, "copying link %s to %s\n", srcName, destName);
118 link_val = (char *) alloca(PATH_MAX + 2);
119 link_size = readlink(srcName, link_val, PATH_MAX + 1);
120 if (link_size < 0) {
121 perror(srcName);
122 return (FALSE);
123 }
124 link_val[link_size] = '\0';
Eric Andersen3c163821999-10-14 22:16:57 +0000125 link_size = symlink(link_val, destName);
126 if (link_size != 0) {
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000127 perror(destName);
128 return (FALSE);
129 }
130 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
131 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
132 if (mkfifo(destName, 644)) {
133 perror(destName);
134 return (FALSE);
135 }
136 } else if (S_ISBLK(srcStatBuf.st_mode) || S_ISCHR(srcStatBuf.st_mode)
137 || S_ISSOCK (srcStatBuf.st_mode)) {
138 //fprintf(stderr, "copying soc, blk, or chr %s to %s\n", srcName, destName);
139 if (mknod(destName, srcStatBuf.st_mode, srcStatBuf.st_rdev)) {
140 perror(destName);
141 return (FALSE);
142 }
143 } else if (S_ISREG(srcStatBuf.st_mode)) {
144 //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName);
145 rfd = open(srcName, O_RDONLY);
146 if (rfd < 0) {
147 perror(srcName);
148 return FALSE;
149 }
150
151 wfd = creat(destName, srcStatBuf.st_mode);
152 if (wfd < 0) {
153 perror(destName);
154 close(rfd);
155 return FALSE;
156 }
157
158 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
159 if (fullWrite(wfd, buf, rcc) < 0)
160 goto error_exit;
161 }
162 if (rcc < 0) {
163 goto error_exit;
164 }
165
166 close(rfd);
167 if (close(wfd) < 0) {
168 return FALSE;
169 }
170 }
171
172 if (setModes == TRUE) {
173 //fprintf(stderr, "Setting permissions for %s\n", destName);
174 chmod(destName, srcStatBuf.st_mode);
175 if (followLinks == TRUE)
176 chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
177 else
178 lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
179
180 times.actime = srcStatBuf.st_atime;
181 times.modtime = srcStatBuf.st_mtime;
182
183 utime(destName, &times);
184 }
185
186 return TRUE;
187
188
189 error_exit:
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000190 perror(destName);
191 close(rfd);
192 close(wfd);
193
194 return FALSE;
195}
Eric Andersencc8ed391999-10-05 16:24:54 +0000196#endif
197
198
199
Eric Andersenbed30e91999-10-18 19:02:32 +0000200#ifdef BB_TAR
Eric Andersencc8ed391999-10-05 16:24:54 +0000201/*
202 * Return the standard ls-like mode string from a file mode.
203 * This is static and so is overwritten on each call.
204 */
Eric Andersenf811e071999-10-09 00:25:00 +0000205const char *modeString(int mode)
Eric Andersencc8ed391999-10-05 16:24:54 +0000206{
Eric Andersenf811e071999-10-09 00:25:00 +0000207 static char buf[12];
Eric Andersencc8ed391999-10-05 16:24:54 +0000208
Eric Andersenf811e071999-10-09 00:25:00 +0000209 strcpy(buf, "----------");
Eric Andersencc8ed391999-10-05 16:24:54 +0000210
Eric Andersenf811e071999-10-09 00:25:00 +0000211 /*
212 * Fill in the file type.
213 */
214 if (S_ISDIR(mode))
215 buf[0] = 'd';
216 if (S_ISCHR(mode))
217 buf[0] = 'c';
218 if (S_ISBLK(mode))
219 buf[0] = 'b';
220 if (S_ISFIFO(mode))
221 buf[0] = 'p';
Eric Andersenf811e071999-10-09 00:25:00 +0000222 if (S_ISLNK(mode))
223 buf[0] = 'l';
Eric Andersenf811e071999-10-09 00:25:00 +0000224 if (S_ISSOCK(mode))
225 buf[0] = 's';
Eric Andersenf811e071999-10-09 00:25:00 +0000226 /*
227 * Now fill in the normal file permissions.
228 */
229 if (mode & S_IRUSR)
230 buf[1] = 'r';
231 if (mode & S_IWUSR)
232 buf[2] = 'w';
233 if (mode & S_IXUSR)
234 buf[3] = 'x';
235 if (mode & S_IRGRP)
236 buf[4] = 'r';
237 if (mode & S_IWGRP)
238 buf[5] = 'w';
239 if (mode & S_IXGRP)
240 buf[6] = 'x';
241 if (mode & S_IROTH)
242 buf[7] = 'r';
243 if (mode & S_IWOTH)
244 buf[8] = 'w';
245 if (mode & S_IXOTH)
246 buf[9] = 'x';
Eric Andersencc8ed391999-10-05 16:24:54 +0000247
Eric Andersenf811e071999-10-09 00:25:00 +0000248 /*
249 * Finally fill in magic stuff like suid and sticky text.
250 */
251 if (mode & S_ISUID)
252 buf[3] = ((mode & S_IXUSR) ? 's' : 'S');
253 if (mode & S_ISGID)
254 buf[6] = ((mode & S_IXGRP) ? 's' : 'S');
255 if (mode & S_ISVTX)
256 buf[9] = ((mode & S_IXOTH) ? 't' : 'T');
Eric Andersencc8ed391999-10-05 16:24:54 +0000257
Eric Andersenf811e071999-10-09 00:25:00 +0000258 return buf;
Eric Andersencc8ed391999-10-05 16:24:54 +0000259}
260
261
Eric Andersencc8ed391999-10-05 16:24:54 +0000262/*
Eric Andersen17d49ef1999-10-06 20:25:32 +0000263 * Get the time string to be used for a file.
264 * This is down to the minute for new files, but only the date for old files.
265 * The string is returned from a static buffer, and so is overwritten for
266 * each call.
267 */
Eric Andersenf811e071999-10-09 00:25:00 +0000268const char *timeString(time_t timeVal)
Eric Andersen17d49ef1999-10-06 20:25:32 +0000269{
Eric Andersenf811e071999-10-09 00:25:00 +0000270 time_t now;
271 char *str;
272 static char buf[26];
Eric Andersen17d49ef1999-10-06 20:25:32 +0000273
Eric Andersenf811e071999-10-09 00:25:00 +0000274 time(&now);
Eric Andersen17d49ef1999-10-06 20:25:32 +0000275
Eric Andersenf811e071999-10-09 00:25:00 +0000276 str = ctime(&timeVal);
Eric Andersen17d49ef1999-10-06 20:25:32 +0000277
Eric Andersenf811e071999-10-09 00:25:00 +0000278 strcpy(buf, &str[4]);
279 buf[12] = '\0';
Eric Andersen17d49ef1999-10-06 20:25:32 +0000280
Eric Andersenf811e071999-10-09 00:25:00 +0000281 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) {
282 strcpy(&buf[7], &str[20]);
283 buf[11] = '\0';
284 }
Eric Andersen17d49ef1999-10-06 20:25:32 +0000285
Eric Andersenf811e071999-10-09 00:25:00 +0000286 return buf;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000287}
288
289
290/*
291 * Routine to see if a text string is matched by a wildcard pattern.
292 * Returns TRUE if the text is matched, or FALSE if it is not matched
293 * or if the pattern is invalid.
294 * * matches zero or more characters
295 * ? matches a single character
296 * [abc] matches 'a', 'b' or 'c'
297 * \c quotes character c
298 * Adapted from code written by Ingo Wilken.
299 */
Eric Andersenf811e071999-10-09 00:25:00 +0000300int match(const char *text, const char *pattern)
Eric Andersen17d49ef1999-10-06 20:25:32 +0000301{
Eric Andersenf811e071999-10-09 00:25:00 +0000302 const char *retryPat;
303 const char *retryText;
304 int ch;
305 int found;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000306
Eric Andersenf811e071999-10-09 00:25:00 +0000307 retryPat = NULL;
308 retryText = NULL;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000309
Eric Andersenf811e071999-10-09 00:25:00 +0000310 while (*text || *pattern) {
311 ch = *pattern++;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000312
Eric Andersenf811e071999-10-09 00:25:00 +0000313 switch (ch) {
314 case '*':
315 retryPat = pattern;
316 retryText = text;
317 break;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000318
Eric Andersenf811e071999-10-09 00:25:00 +0000319 case '[':
320 found = FALSE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000321
Eric Andersenf811e071999-10-09 00:25:00 +0000322 while ((ch = *pattern++) != ']') {
323 if (ch == '\\')
324 ch = *pattern++;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000325
Eric Andersenf811e071999-10-09 00:25:00 +0000326 if (ch == '\0')
327 return FALSE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000328
Eric Andersenf811e071999-10-09 00:25:00 +0000329 if (*text == ch)
330 found = TRUE;
331 }
Eric Andersen17d49ef1999-10-06 20:25:32 +0000332
Eric Andersenf811e071999-10-09 00:25:00 +0000333 if (!found) {
334 pattern = retryPat;
335 text = ++retryText;
336 }
Eric Andersen17d49ef1999-10-06 20:25:32 +0000337
Eric Andersenf811e071999-10-09 00:25:00 +0000338 /* fall into next case */
Eric Andersen17d49ef1999-10-06 20:25:32 +0000339
Eric Andersenf811e071999-10-09 00:25:00 +0000340 case '?':
341 if (*text++ == '\0')
342 return FALSE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000343
Eric Andersenf811e071999-10-09 00:25:00 +0000344 break;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000345
Eric Andersenf811e071999-10-09 00:25:00 +0000346 case '\\':
347 ch = *pattern++;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000348
Eric Andersenf811e071999-10-09 00:25:00 +0000349 if (ch == '\0')
350 return FALSE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000351
Eric Andersenf811e071999-10-09 00:25:00 +0000352 /* fall into next case */
Eric Andersen17d49ef1999-10-06 20:25:32 +0000353
Eric Andersenf811e071999-10-09 00:25:00 +0000354 default:
355 if (*text == ch) {
356 if (*text)
357 text++;
358 break;
359 }
Eric Andersen17d49ef1999-10-06 20:25:32 +0000360
Eric Andersenf811e071999-10-09 00:25:00 +0000361 if (*text) {
362 pattern = retryPat;
363 text = ++retryText;
364 break;
365 }
Eric Andersen17d49ef1999-10-06 20:25:32 +0000366
Eric Andersenf811e071999-10-09 00:25:00 +0000367 return FALSE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000368 }
369
Eric Andersenf811e071999-10-09 00:25:00 +0000370 if (pattern == NULL)
371 return FALSE;
372 }
373
374 return TRUE;
Eric Andersen17d49ef1999-10-06 20:25:32 +0000375}
376
377
378/*
Eric Andersencc8ed391999-10-05 16:24:54 +0000379 * Write all of the supplied buffer out to a file.
380 * This does multiple writes as necessary.
381 * Returns the amount written, or -1 on an error.
382 */
Eric Andersenf811e071999-10-09 00:25:00 +0000383int fullWrite(int fd, const char *buf, int len)
Eric Andersencc8ed391999-10-05 16:24:54 +0000384{
Eric Andersenf811e071999-10-09 00:25:00 +0000385 int cc;
386 int total;
Eric Andersencc8ed391999-10-05 16:24:54 +0000387
Eric Andersenf811e071999-10-09 00:25:00 +0000388 total = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000389
Eric Andersenf811e071999-10-09 00:25:00 +0000390 while (len > 0) {
391 cc = write(fd, buf, len);
Eric Andersencc8ed391999-10-05 16:24:54 +0000392
Eric Andersenf811e071999-10-09 00:25:00 +0000393 if (cc < 0)
394 return -1;
Eric Andersencc8ed391999-10-05 16:24:54 +0000395
Eric Andersenf811e071999-10-09 00:25:00 +0000396 buf += cc;
397 total += cc;
398 len -= cc;
399 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000400
Eric Andersenf811e071999-10-09 00:25:00 +0000401 return total;
Eric Andersencc8ed391999-10-05 16:24:54 +0000402}
403
404
405/*
406 * Read all of the supplied buffer from a file.
407 * This does multiple reads as necessary.
408 * Returns the amount read, or -1 on an error.
409 * A short read is returned on an end of file.
410 */
Eric Andersenf811e071999-10-09 00:25:00 +0000411int fullRead(int fd, char *buf, int len)
Eric Andersencc8ed391999-10-05 16:24:54 +0000412{
Eric Andersenf811e071999-10-09 00:25:00 +0000413 int cc;
414 int total;
Eric Andersencc8ed391999-10-05 16:24:54 +0000415
Eric Andersenf811e071999-10-09 00:25:00 +0000416 total = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000417
Eric Andersenf811e071999-10-09 00:25:00 +0000418 while (len > 0) {
419 cc = read(fd, buf, len);
Eric Andersencc8ed391999-10-05 16:24:54 +0000420
Eric Andersenf811e071999-10-09 00:25:00 +0000421 if (cc < 0)
422 return -1;
Eric Andersencc8ed391999-10-05 16:24:54 +0000423
Eric Andersenf811e071999-10-09 00:25:00 +0000424 if (cc == 0)
425 break;
Eric Andersencc8ed391999-10-05 16:24:54 +0000426
Eric Andersenf811e071999-10-09 00:25:00 +0000427 buf += cc;
428 total += cc;
429 len -= cc;
430 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000431
Eric Andersenf811e071999-10-09 00:25:00 +0000432 return total;
Eric Andersencc8ed391999-10-05 16:24:54 +0000433}
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000434#endif
Eric Andersencc8ed391999-10-05 16:24:54 +0000435
436
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000437#if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS)
Eric Andersencc8ed391999-10-05 16:24:54 +0000438/*
Eric Andersen2b69c401999-10-05 22:58:32 +0000439 * Walk down all the directories under the specified
440 * location, and do something (something specified
441 * by the fileAction and dirAction function pointers).
Eric Andersenb7a1a751999-10-19 23:37:14 +0000442 *
443 * TODO: check if ftw(3) can replace this to reduce code size...
Eric Andersencc8ed391999-10-05 16:24:54 +0000444 */
445int
Eric Andersenbed30e91999-10-18 19:02:32 +0000446recursiveAction(const char *fileName, int recurse, int followLinks, int delayDirAction,
Eric Andersen9b587181999-10-17 05:43:39 +0000447 int (*fileAction) (const char *fileName, struct stat* statbuf),
448 int (*dirAction) (const char *fileName, struct stat* statbuf))
Eric Andersencc8ed391999-10-05 16:24:54 +0000449{
Eric Andersenf811e071999-10-09 00:25:00 +0000450 int status;
451 struct stat statbuf;
452 struct dirent *next;
Eric Andersen9d3aba71999-10-06 09:04:55 +0000453
Eric Andersen3c163821999-10-14 22:16:57 +0000454 if (followLinks == FALSE)
Eric Andersenf811e071999-10-09 00:25:00 +0000455 status = stat(fileName, &statbuf);
Eric Andersen3c163821999-10-14 22:16:57 +0000456 else
457 status = lstat(fileName, &statbuf);
458
Eric Andersencc8ed391999-10-05 16:24:54 +0000459 if (status < 0) {
460 perror(fileName);
Eric Andersenf811e071999-10-09 00:25:00 +0000461 return (FALSE);
462 }
463
464 if (recurse == FALSE) {
465 if (S_ISDIR(statbuf.st_mode)) {
Eric Andersen3c163821999-10-14 22:16:57 +0000466 if (dirAction != NULL)
Eric Andersen9b587181999-10-17 05:43:39 +0000467 return (dirAction(fileName, &statbuf));
Eric Andersenf811e071999-10-09 00:25:00 +0000468 else
Eric Andersen3c163821999-10-14 22:16:57 +0000469 return (TRUE);
470 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000471 }
472
Eric Andersen2b69c401999-10-05 22:58:32 +0000473 if (S_ISDIR(statbuf.st_mode)) {
474 DIR *dir;
475 dir = opendir(fileName);
476 if (!dir) {
477 perror(fileName);
Eric Andersenf811e071999-10-09 00:25:00 +0000478 return (FALSE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000479 }
Eric Andersenbed30e91999-10-18 19:02:32 +0000480 if (dirAction != NULL && delayDirAction == FALSE) {
Eric Andersen9b587181999-10-17 05:43:39 +0000481 status = dirAction(fileName, &statbuf);
Eric Andersenf811e071999-10-09 00:25:00 +0000482 if (status == FALSE) {
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000483 perror(fileName);
Eric Andersenf811e071999-10-09 00:25:00 +0000484 return (FALSE);
485 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000486 }
Eric Andersenf811e071999-10-09 00:25:00 +0000487 while ((next = readdir(dir)) != NULL) {
488 char nextFile[NAME_MAX];
489 if ((strcmp(next->d_name, "..") == 0)
490 || (strcmp(next->d_name, ".") == 0)) {
491 continue;
492 }
493 sprintf(nextFile, "%s/%s", fileName, next->d_name);
494 status =
Eric Andersenbed30e91999-10-18 19:02:32 +0000495 recursiveAction(nextFile, TRUE, followLinks, delayDirAction,
496 fileAction, dirAction);
Eric Andersenf811e071999-10-09 00:25:00 +0000497 if (status < 0) {
498 closedir(dir);
499 return (FALSE);
500 }
501 }
502 status = closedir(dir);
Eric Andersen2b69c401999-10-05 22:58:32 +0000503 if (status < 0) {
504 perror(fileName);
Eric Andersenf811e071999-10-09 00:25:00 +0000505 return (FALSE);
Eric Andersen2b69c401999-10-05 22:58:32 +0000506 }
Eric Andersenbed30e91999-10-18 19:02:32 +0000507 if (dirAction != NULL && delayDirAction == TRUE) {
508 status = dirAction(fileName, &statbuf);
509 if (status == FALSE) {
510 perror(fileName);
511 return (FALSE);
512 }
513 }
Eric Andersenf811e071999-10-09 00:25:00 +0000514 } else {
Eric Andersenf811e071999-10-09 00:25:00 +0000515 if (fileAction == NULL)
516 return (TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000517 else
Eric Andersen9b587181999-10-17 05:43:39 +0000518 return (fileAction(fileName, &statbuf));
Eric Andersencc8ed391999-10-05 16:24:54 +0000519 }
Eric Andersenf811e071999-10-09 00:25:00 +0000520 return (TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000521}
522
Eric Andersenc6cb79d1999-10-13 18:01:10 +0000523#endif
Eric Andersencc8ed391999-10-05 16:24:54 +0000524
Eric Andersenf6be9441999-10-13 21:12:06 +0000525
526
527#if defined (BB_TAR) || defined (BB_MKDIR)
528/*
529 * Attempt to create the directories along the specified path, except for
530 * the final component. The mode is given for the final directory only,
531 * while all previous ones get default protections. Errors are not reported
532 * here, as failures to restore files can be reported later.
533 */
534extern void createPath (const char *name, int mode)
535{
536 char *cp;
537 char *cpOld;
538 char buf[NAME_MAX];
539
540 strcpy (buf, name);
541
542 cp = strchr (buf, '/');
543
544 while (cp) {
545 cpOld = cp;
546 cp = strchr (cp + 1, '/');
547
548 *cpOld = '\0';
549
550 if (mkdir (buf, cp ? 0777 : mode) == 0)
551 printf ("Directory \"%s\" created\n", buf);
552
553 *cpOld = '/';
554 }
555}
556#endif
557
558
559
560#if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_MKDIR)
Eric Andersence8f3b91999-10-20 07:03:36 +0000561/* [ugoa]{+|-|=}[rwxst] */
562
563
564
565extern int
566parse_mode( const char* s, mode_t* theMode)
Eric Andersenf6be9441999-10-13 21:12:06 +0000567{
Eric Andersence8f3b91999-10-20 07:03:36 +0000568 mode_t andMode = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
569 mode_t orMode = 0;
Eric Andersenf6be9441999-10-13 21:12:06 +0000570 mode_t mode = 0;
Eric Andersence8f3b91999-10-20 07:03:36 +0000571 mode_t groups = 0;
Eric Andersenf6be9441999-10-13 21:12:06 +0000572 char type;
573 char c;
574
575 do {
576 for ( ; ; ) {
577 switch ( c = *s++ ) {
578 case '\0':
Eric Andersence8f3b91999-10-20 07:03:36 +0000579 return -1;
Eric Andersenf6be9441999-10-13 21:12:06 +0000580 case 'u':
581 groups |= S_ISUID|S_IRWXU;
582 continue;
583 case 'g':
584 groups |= S_ISGID|S_IRWXG;
585 continue;
586 case 'o':
587 groups |= S_IRWXO;
588 continue;
589 case 'a':
590 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
591 continue;
592 case '+':
593 case '=':
594 case '-':
595 type = c;
Eric Andersence8f3b91999-10-20 07:03:36 +0000596 if ( groups == 0 ) /* The default is "all" */
Eric Andersenf6be9441999-10-13 21:12:06 +0000597 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
598 break;
599 default:
Eric Andersence8f3b91999-10-20 07:03:36 +0000600 if ( isdigit(c) && c >= '0' && c <= '7' && mode == 0 && groups == 0 ) {
601 andMode = 0;
602 orMode = strtol(--s, NULL, 8);
603 *theMode &= andMode;
604 *theMode |= orMode;
Eric Andersenf6be9441999-10-13 21:12:06 +0000605 return (TRUE);
606 }
607 else
608 return (FALSE);
609 }
610 break;
611 }
612
613 while ( (c = *s++) != '\0' ) {
614 switch ( c ) {
615 case ',':
616 break;
617 case 'r':
618 mode |= S_IRUSR|S_IRGRP|S_IROTH;
619 continue;
620 case 'w':
621 mode |= S_IWUSR|S_IWGRP|S_IWOTH;
622 continue;
623 case 'x':
624 mode |= S_IXUSR|S_IXGRP|S_IXOTH;
625 continue;
626 case 's':
627 mode |= S_IXGRP|S_ISUID|S_ISGID;
628 continue;
629 case 't':
Eric Andersence8f3b91999-10-20 07:03:36 +0000630 mode |= 0;
Eric Andersenf6be9441999-10-13 21:12:06 +0000631 continue;
632 default:
Eric Andersence8f3b91999-10-20 07:03:36 +0000633 *theMode &= andMode;
634 *theMode |= orMode;
635 return( TRUE);
Eric Andersenf6be9441999-10-13 21:12:06 +0000636 }
637 break;
638 }
639 switch ( type ) {
640 case '=':
Eric Andersence8f3b91999-10-20 07:03:36 +0000641 andMode &= ~(groups);
Eric Andersenf6be9441999-10-13 21:12:06 +0000642 /* fall through */
643 case '+':
Eric Andersence8f3b91999-10-20 07:03:36 +0000644 orMode |= mode & groups;
Eric Andersenf6be9441999-10-13 21:12:06 +0000645 break;
646 case '-':
Eric Andersence8f3b91999-10-20 07:03:36 +0000647 andMode &= ~(mode & groups);
648 orMode &= andMode;
Eric Andersenf6be9441999-10-13 21:12:06 +0000649 break;
650 }
651 } while ( c == ',' );
Eric Andersence8f3b91999-10-20 07:03:36 +0000652 *theMode &= andMode;
653 *theMode |= orMode;
Eric Andersenf6be9441999-10-13 21:12:06 +0000654 return (TRUE);
655}
Eric Andersence8f3b91999-10-20 07:03:36 +0000656
657
Eric Andersenf6be9441999-10-13 21:12:06 +0000658#endif
659
Eric Andersene674eb71999-10-19 20:52:57 +0000660
661
Eric Andersencc8ed391999-10-05 16:24:54 +0000662/* END CODE */