4 * Copyright (C) 1998 by Erik Andersen <andersee@debian.org>
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.
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.
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
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.
37 /* volatile so gcc knows this is the enod of the line */
38 volatile void usage(const char *usage)
40 fprintf(stderr, "Usage: %s\n", usage);
46 #if defined (BB_CP) || defined (BB_MV)
48 * Return TRUE if a fileName is a directory.
49 * Nonexistant files return FALSE.
51 int isDirectory(const char *name)
55 if (stat(name, &statBuf) < 0)
57 if (S_ISDIR(statBuf.st_mode))
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
70 copyFile( const char *srcName, const char *destName,
71 int setModes, int followLinks)
78 struct stat srcStatBuf;
79 struct stat dstStatBuf;
82 if (followLinks == FALSE)
83 result = stat(srcName, &srcStatBuf);
85 result = lstat(srcName, &srcStatBuf);
91 if (followLinks == FALSE)
92 result = stat(destName, &dstStatBuf);
94 result = lstat(destName, &dstStatBuf);
96 dstStatBuf.st_ino = -1;
97 dstStatBuf.st_dev = -1;
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);
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))) {
113 } else if (S_ISLNK(srcStatBuf.st_mode)) {
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);
124 link_val[link_size] = '\0';
125 link_size = symlink(link_val, destName);
126 if (link_size != 0) {
130 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
131 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
132 if (mkfifo(destName, 644)) {
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)) {
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);
151 wfd = creat(destName, srcStatBuf.st_mode);
158 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
159 if (fullWrite(wfd, buf, rcc) < 0)
167 if (close(wfd) < 0) {
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);
178 lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
180 times.actime = srcStatBuf.st_atime;
181 times.modtime = srcStatBuf.st_mtime;
183 utime(destName, ×);
202 * Return the standard ls-like mode string from a file mode.
203 * This is static and so is overwritten on each call.
205 const char *modeString(int mode)
209 strcpy(buf, "----------");
212 * Fill in the file type.
227 * Now fill in the normal file permissions.
249 * Finally fill in magic stuff like suid and sticky text.
252 buf[3] = ((mode & S_IXUSR) ? 's' : 'S');
254 buf[6] = ((mode & S_IXGRP) ? 's' : 'S');
256 buf[9] = ((mode & S_IXOTH) ? 't' : 'T');
263 * 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
268 const char *timeString(time_t timeVal)
276 str = ctime(&timeVal);
278 strcpy(buf, &str[4]);
281 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) {
282 strcpy(&buf[7], &str[20]);
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.
300 int match(const char *text, const char *pattern)
302 const char *retryPat;
303 const char *retryText;
310 while (*text || *pattern) {
322 while ((ch = *pattern++) != ']') {
338 /* fall into next case */
352 /* fall into next case */
379 * 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.
383 int fullWrite(int fd, const char *buf, int len)
391 cc = write(fd, buf, len);
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.
411 int fullRead(int fd, char *buf, int len)
419 cc = read(fd, buf, len);
437 #if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS)
439 * Walk down all the directories under the specified
440 * location, and do something (something specified
441 * by the fileAction and dirAction function pointers).
444 recursiveAction(const char *fileName, int recurse, int followLinks, int delayDirAction,
445 int (*fileAction) (const char *fileName, struct stat* statbuf),
446 int (*dirAction) (const char *fileName, struct stat* statbuf))
452 if (followLinks == FALSE)
453 status = stat(fileName, &statbuf);
455 status = lstat(fileName, &statbuf);
462 if (recurse == FALSE) {
463 if (S_ISDIR(statbuf.st_mode)) {
464 if (dirAction != NULL)
465 return (dirAction(fileName, &statbuf));
471 if (S_ISDIR(statbuf.st_mode)) {
473 dir = opendir(fileName);
478 if (dirAction != NULL && delayDirAction == FALSE) {
479 status = dirAction(fileName, &statbuf);
480 if (status == FALSE) {
485 while ((next = readdir(dir)) != NULL) {
486 char nextFile[NAME_MAX];
487 if ((strcmp(next->d_name, "..") == 0)
488 || (strcmp(next->d_name, ".") == 0)) {
491 sprintf(nextFile, "%s/%s", fileName, next->d_name);
493 recursiveAction(nextFile, TRUE, followLinks, delayDirAction,
494 fileAction, dirAction);
500 status = closedir(dir);
505 if (dirAction != NULL && delayDirAction == TRUE) {
506 status = dirAction(fileName, &statbuf);
507 if (status == FALSE) {
513 if (fileAction == NULL)
516 return (fileAction(fileName, &statbuf));
525 #if defined (BB_TAR) || defined (BB_MKDIR)
527 * Attempt to create the directories along the specified path, except for
528 * the final component. The mode is given for the final directory only,
529 * while all previous ones get default protections. Errors are not reported
530 * here, as failures to restore files can be reported later.
532 extern void createPath (const char *name, int mode)
540 cp = strchr (buf, '/');
544 cp = strchr (cp + 1, '/');
548 if (mkdir (buf, cp ? 0777 : mode) == 0)
549 printf ("Directory \"%s\" created\n", buf);
558 #if defined (BB_CHMOD_CHOWN_CHGRP) || defined (BB_MKDIR)
559 /* [ugoa]{+|-|=}[rwxstl] */
560 extern int parse_mode( const char* s, mode_t* theMode)
565 mode_t groups = S_ISVTX;
571 switch ( c = *s++ ) {
575 groups |= S_ISUID|S_IRWXU;
578 groups |= S_ISGID|S_IRWXG;
584 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
590 if ( groups == S_ISVTX ) /* The default is "all" */
591 groups |= S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
594 if ( c >= '0' && c <= '7' && mode == 0 && groups == S_ISVTX ) {
596 or = strtol(--s, 0, 010);
605 while ( (c = *s++) != '\0' ) {
610 mode |= S_IRUSR|S_IRGRP|S_IROTH;
613 mode |= S_IWUSR|S_IWGRP|S_IWOTH;
616 mode |= S_IXUSR|S_IXGRP|S_IXOTH;
619 mode |= S_IXGRP|S_ISUID|S_ISGID;
637 and &= ~(mode & groups);
641 } while ( c == ',' );