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.
38 #if defined (BB_CP) || defined (BB_MV)
40 * Return TRUE if a fileName is a directory.
41 * Nonexistant files return FALSE.
43 int isDirectory(const char *name)
47 if (stat(name, &statBuf) < 0)
50 return S_ISDIR(statBuf.st_mode);
55 * Copy one file to another, while possibly preserving its modes, times,
56 * and modes. Returns TRUE if successful, or FALSE on a failure with an
57 * error message output. (Failure is not indicted if the attributes cannot
63 const char *destName, int setModes, int followLinks)
70 struct stat srcStatBuf;
71 struct stat dstStatBuf;
74 if (followLinks == FALSE)
75 result = stat(srcName, &srcStatBuf);
77 result = lstat(srcName, &srcStatBuf);
84 if (followLinks == FALSE)
85 result = stat(destName, &dstStatBuf);
87 result = lstat(destName, &dstStatBuf);
89 dstStatBuf.st_ino = -1;
90 dstStatBuf.st_dev = -1;
93 if ((srcStatBuf.st_dev == dstStatBuf.st_dev) &&
94 (srcStatBuf.st_ino == dstStatBuf.st_ino)) {
95 fprintf(stderr, "Copying file \"%s\" to itself\n", srcName);
99 if (S_ISDIR(srcStatBuf.st_mode)) {
100 //fprintf(stderr, "copying directory %s to %s\n", srcName, destName);
101 /* Make sure the directory is writable */
102 if (mkdir(destName, 0777777 ^ umask(0))) {
106 } else if (S_ISLNK(srcStatBuf.st_mode)) {
110 //fprintf(stderr, "copying link %s to %s\n", srcName, destName);
111 link_val = (char *) alloca(PATH_MAX + 2);
112 link_size = readlink(srcName, link_val, PATH_MAX + 1);
117 link_val[link_size] = '\0';
118 if (symlink(link_val, destName)) {
122 } else if (S_ISFIFO(srcStatBuf.st_mode)) {
123 //fprintf(stderr, "copying fifo %s to %s\n", srcName, destName);
124 if (mkfifo(destName, 644)) {
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)) {
135 } else if (S_ISREG(srcStatBuf.st_mode)) {
136 //fprintf(stderr, "copying regular file %s to %s\n", srcName, destName);
137 rfd = open(srcName, O_RDONLY);
143 wfd = creat(destName, srcStatBuf.st_mode);
150 while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
151 if (fullWrite(wfd, buf, rcc) < 0)
159 if (close(wfd) < 0) {
164 if (setModes == TRUE) {
165 //fprintf(stderr, "Setting permissions for %s\n", destName);
166 chmod(destName, srcStatBuf.st_mode);
167 if (followLinks == TRUE)
168 chown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
170 lchown(destName, srcStatBuf.st_uid, srcStatBuf.st_gid);
172 times.actime = srcStatBuf.st_atime;
173 times.modtime = srcStatBuf.st_mtime;
175 utime(destName, ×);
182 //fprintf(stderr, "choking on %s\n", destName);
194 * Build a path name from the specified directory name and file name.
195 * If the directory name is NULL, then the original fileName is returned.
196 * The built path is in a static area, and is overwritten for each call.
198 char *buildName(const char *dirName, const char *fileName)
201 static char buf[PATH_LEN];
203 if ((dirName == NULL) || (*dirName == '\0')) {
204 strcpy(buf, fileName);
208 cp = strrchr(fileName, '/');
213 strcpy(buf, dirName);
223 * Return the standard ls-like mode string from a file mode.
224 * This is static and so is overwritten on each call.
226 const char *modeString(int mode)
230 strcpy(buf, "----------");
233 * Fill in the file type.
253 * Now fill in the normal file permissions.
275 * Finally fill in magic stuff like suid and sticky text.
278 buf[3] = ((mode & S_IXUSR) ? 's' : 'S');
280 buf[6] = ((mode & S_IXGRP) ? 's' : 'S');
282 buf[9] = ((mode & S_IXOTH) ? 't' : 'T');
290 * Get the time string to be used for a file.
291 * This is down to the minute for new files, but only the date for old files.
292 * The string is returned from a static buffer, and so is overwritten for
295 const char *timeString(time_t timeVal)
303 str = ctime(&timeVal);
305 strcpy(buf, &str[4]);
308 if ((timeVal > now) || (timeVal < now - 365 * 24 * 60 * 60L)) {
309 strcpy(&buf[7], &str[20]);
318 * Routine to see if a text string is matched by a wildcard pattern.
319 * Returns TRUE if the text is matched, or FALSE if it is not matched
320 * or if the pattern is invalid.
321 * * matches zero or more characters
322 * ? matches a single character
323 * [abc] matches 'a', 'b' or 'c'
324 * \c quotes character c
325 * Adapted from code written by Ingo Wilken.
327 int match(const char *text, const char *pattern)
329 const char *retryPat;
330 const char *retryText;
337 while (*text || *pattern) {
349 while ((ch = *pattern++) != ']') {
365 /* fall into next case */
379 /* fall into next case */
406 * Write all of the supplied buffer out to a file.
407 * This does multiple writes as necessary.
408 * Returns the amount written, or -1 on an error.
410 int fullWrite(int fd, const char *buf, int len)
418 cc = write(fd, buf, len);
433 * Read all of the supplied buffer from a file.
434 * This does multiple reads as necessary.
435 * Returns the amount read, or -1 on an error.
436 * A short read is returned on an end of file.
438 int fullRead(int fd, char *buf, int len)
446 cc = read(fd, buf, len);
464 #if defined (BB_CHOWN) || defined (BB_CP) || defined (BB_FIND) || defined (BB_LS)
466 * Walk down all the directories under the specified
467 * location, and do something (something specified
468 * by the fileAction and dirAction function pointers).
471 recursiveAction(const char *fileName, int recurse, int followLinks,
472 int (*fileAction) (const char *fileName),
473 int (*dirAction) (const char *fileName))
480 status = lstat(fileName, &statbuf);
482 status = stat(fileName, &statbuf);
488 if (recurse == FALSE) {
489 if (S_ISDIR(statbuf.st_mode)) {
490 if (dirAction == NULL)
493 return (dirAction(fileName));
495 if (fileAction == NULL)
498 return (fileAction(fileName));
502 if (S_ISDIR(statbuf.st_mode)) {
504 dir = opendir(fileName);
509 if (dirAction != NULL) {
510 status = dirAction(fileName);
511 if (status == FALSE) {
516 while ((next = readdir(dir)) != NULL) {
517 char nextFile[NAME_MAX];
518 if ((strcmp(next->d_name, "..") == 0)
519 || (strcmp(next->d_name, ".") == 0)) {
522 sprintf(nextFile, "%s/%s", fileName, next->d_name);
524 recursiveAction(nextFile, TRUE, followLinks, fileAction,
531 status = closedir(dir);
537 if (fileAction == NULL)
540 return (fileAction(fileName));