diff options
author | Eric Andersen | 1999-10-05 22:58:32 +0000 |
---|---|---|
committer | Eric Andersen | 1999-10-05 22:58:32 +0000 |
commit | 2b69c40e8060934c115922c012737bd471956f09 (patch) | |
tree | c92657a42b94419ab9579e8c52639c301764ec40 /utility.c | |
parent | cc8ed39b240180b58810784f844e253263594ac3 (diff) | |
download | busybox-2b69c40e8060934c115922c012737bd471956f09.zip busybox-2b69c40e8060934c115922c012737bd471956f09.tar.gz |
More stuff works.
-Erik
Diffstat (limited to 'utility.c')
-rw-r--r-- | utility.c | 744 |
1 files changed, 48 insertions, 696 deletions
@@ -22,7 +22,16 @@ * */ -#include "utility.h" +#include "internal.h" +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +//#include <sys/types.h> +//#include <sys/stat.h> +#include <dirent.h> +#include <time.h> +#include <utime.h> #if 0 @@ -54,13 +63,6 @@ join_paths(char * buffer, const char * a, const char * b) static CHUNK * chunkList; -extern void -name_and_error(const char * name) -{ - fprintf(stderr, "%s: %s\n", name, strerror(errno)); -} - - /* * Return the standard ls-like mode string from a file mode. @@ -130,36 +132,6 @@ modeString(int mode) /* - * Get the time string to be used for a file. - * This is down to the minute for new files, but only the date for old files. - * The string is returned from a static buffer, and so is overwritten for - * each call. - */ -const char * -timeString(time_t timeVal) -{ - time_t now; - char * str; - static char buf[26]; - - time(&now); - - str = ctime(&timeVal); - - strcpy(buf, &str[4]); - buf[12] = '\0'; - - if ((timeVal > now) || (timeVal < now - 365*24*60*60L)) - { - strcpy(&buf[7], &str[20]); - buf[11] = '\0'; - } - - return buf; -} - - -/* * Return TRUE if a fileName is a directory. * Nonexistant files return FALSE. */ @@ -325,624 +297,6 @@ buildName(const char * dirName, const char * fileName) /* - * Expand the wildcards in a fileName wildcard pattern, if any. - * Returns an argument list with matching fileNames in sorted order. - * The expanded names are stored in memory chunks which can later all - * be freed at once. The returned list is only valid until the next - * call or until the next command. Returns zero if the name is not a - * wildcard, or returns the count of matched files if the name is a - * wildcard and there was at least one match, or returns -1 if either - * no fileNames matched or there was an allocation error. - */ -int -expandWildCards(const char * fileNamePattern, const char *** retFileTable) -{ - const char * last; - const char * cp1; - const char * cp2; - const char * cp3; - char * str; - DIR * dirp; - struct dirent * dp; - int dirLen; - int newFileTableSize; - char ** newFileTable; - char dirName[PATH_LEN]; - - static int fileCount; - static int fileTableSize; - static char ** fileTable; - - /* - * Clear the return values until we know their final values. - */ - fileCount = 0; - *retFileTable = NULL; - - /* - * Scan the file name pattern for any wildcard characters. - */ - cp1 = strchr(fileNamePattern, '*'); - cp2 = strchr(fileNamePattern, '?'); - cp3 = strchr(fileNamePattern, '['); - - /* - * If there are no wildcard characters then return zero to - * indicate that there was actually no wildcard pattern. - */ - if ((cp1 == NULL) && (cp2 == NULL) && (cp3 == NULL)) - return 0; - - /* - * There are wildcards in the specified filename. - * Get the last component of the file name. - */ - last = strrchr(fileNamePattern, '/'); - - if (last) - last++; - else - last = fileNamePattern; - - /* - * If any wildcards were found before the last filename component - * then return an error. - */ - if ((cp1 && (cp1 < last)) || (cp2 && (cp2 < last)) || - (cp3 && (cp3 < last))) - { - fprintf(stderr, - "Wildcards only implemented for last file name component\n"); - - return -1; - } - - /* - * Assume at first that we are scanning the current directory. - */ - dirName[0] = '.'; - dirName[1] = '\0'; - - /* - * If there was a directory given as part of the file name then - * copy it and null terminate it. - */ - if (last != fileNamePattern) - { - memcpy(dirName, fileNamePattern, last - fileNamePattern); - dirName[last - fileNamePattern - 1] = '\0'; - - if (dirName[0] == '\0') - { - dirName[0] = '/'; - dirName[1] = '\0'; - } - } - - /* - * Open the directory containing the files to be checked. - */ - dirp = opendir(dirName); - - if (dirp == NULL) - { - perror(dirName); - - return -1; - } - - /* - * Prepare the directory name for use in making full path names. - */ - dirLen = strlen(dirName); - - if (last == fileNamePattern) - { - dirLen = 0; - dirName[0] = '\0'; - } - else if (dirName[dirLen - 1] != '/') - { - dirName[dirLen++] = '/'; - dirName[dirLen] = '\0'; - } - - /* - * Find all of the files in the directory and check them against - * the wildcard pattern. - */ - while ((dp = readdir(dirp)) != NULL) - { - /* - * Skip the current and parent directories. - */ - if ((strcmp(dp->d_name, ".") == 0) || - (strcmp(dp->d_name, "..") == 0)) - { - continue; - } - - /* - * If the file name doesn't match the pattern then skip it. - */ - if (!match(dp->d_name, last)) - continue; - - /* - * This file name is selected. - * See if we need to reallocate the file name table. - */ - if (fileCount >= fileTableSize) - { - /* - * Increment the file table size and reallocate it. - */ - newFileTableSize = fileTableSize + EXPAND_ALLOC; - - newFileTable = (char **) realloc((char *) fileTable, - (newFileTableSize * sizeof(char *))); - - if (newFileTable == NULL) - { - fprintf(stderr, "Cannot allocate file list\n"); - closedir(dirp); - - return -1; - } - - fileTable = newFileTable; - fileTableSize = newFileTableSize; - } - - /* - * Allocate space for storing the file name in a chunk. - */ - str = getChunk(dirLen + strlen(dp->d_name) + 1); - - if (str == NULL) - { - fprintf(stderr, "No memory for file name\n"); - closedir(dirp); - - return -1; - } - - /* - * Save the file name in the chunk. - */ - if (dirLen) - memcpy(str, dirName, dirLen); - - strcpy(str + dirLen, dp->d_name); - - /* - * Save the allocated file name into the file table. - */ - fileTable[fileCount++] = str; - } - - /* - * Close the directory and check for any matches. - */ - closedir(dirp); - - if (fileCount == 0) - { - fprintf(stderr, "No matches\n"); - - return -1; - } - - /* - * Sort the list of file names. - */ - qsort((void *) fileTable, fileCount, sizeof(char *), nameSort); - - /* - * Return the file list and count. - */ - *retFileTable = (const char **) fileTable; - - return fileCount; -} - - -/* - * Sort routine for list of fileNames. - */ -int -nameSort(const void * p1, const void * p2) -{ - const char ** s1; - const char ** s2; - - s1 = (const char **) p1; - s2 = (const char **) p2; - - return strcmp(*s1, *s2); -} - - - -/* - * Routine to see if a text string is matched by a wildcard pattern. - * Returns TRUE if the text is matched, or FALSE if it is not matched - * or if the pattern is invalid. - * * matches zero or more characters - * ? matches a single character - * [abc] matches 'a', 'b' or 'c' - * \c quotes character c - * Adapted from code written by Ingo Wilken. - */ -BOOL -match(const char * text, const char * pattern) -{ - const char * retryPat; - const char * retryText; - int ch; - BOOL found; - - retryPat = NULL; - retryText = NULL; - - while (*text || *pattern) - { - ch = *pattern++; - - switch (ch) - { - case '*': - retryPat = pattern; - retryText = text; - break; - - case '[': - found = FALSE; - - while ((ch = *pattern++) != ']') - { - if (ch == '\\') - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - if (*text == ch) - found = TRUE; - } - - if (!found) - { - pattern = retryPat; - text = ++retryText; - } - - /* fall into next case */ - - case '?': - if (*text++ == '\0') - return FALSE; - - break; - - case '\\': - ch = *pattern++; - - if (ch == '\0') - return FALSE; - - /* fall into next case */ - - default: - if (*text == ch) - { - if (*text) - text++; - break; - } - - if (*text) - { - pattern = retryPat; - text = ++retryText; - break; - } - - return FALSE; - } - - if (pattern == NULL) - return FALSE; - } - - return TRUE; -} - - -/* - * Take a command string and break it up into an argc, argv list while - * handling quoting and wildcards. The returned argument list and - * strings are in static memory, and so are overwritten on each call. - * The argument list is ended with a NULL pointer for convenience. - * Returns TRUE if successful, or FALSE on an error with a message - * already output. - */ -BOOL -makeArgs(const char * cmd, int * retArgc, const char *** retArgv) -{ - const char * argument; - char * cp; - char * cpOut; - char * newStrings; - const char ** fileTable; - const char ** newArgTable; - int newArgTableSize; - int fileCount; - int len; - int ch; - int quote; - BOOL quotedWildCards; - BOOL unquotedWildCards; - - static int stringsLength; - static char * strings; - static int argCount; - static int argTableSize; - static const char ** argTable; - - /* - * Clear the returned values until we know them. - */ - argCount = 0; - *retArgc = 0; - *retArgv = NULL; - - /* - * Copy the command string into a buffer that we can modify, - * reallocating it if necessary. - */ - len = strlen(cmd) + 1; - - if (len > stringsLength) - { - newStrings = realloc(strings, len); - - if (newStrings == NULL) - { - fprintf(stderr, "Cannot allocate string\n"); - - return FALSE; - } - - strings = newStrings; - stringsLength = len; - } - - memcpy(strings, cmd, len); - cp = strings; - - /* - * Keep parsing the command string as long as there are any - * arguments left. - */ - while (*cp) - { - /* - * Save the beginning of this argument. - */ - argument = cp; - cpOut = cp; - - /* - * Reset quoting and wildcarding for this argument. - */ - quote = '\0'; - quotedWildCards = FALSE; - unquotedWildCards = FALSE; - - /* - * Loop over the string collecting the next argument while - * looking for quoted strings or quoted characters, and - * remembering whether there are any wildcard characters - * in the argument. - */ - while (*cp) - { - ch = *cp++; - - /* - * If we are not in a quote and we see a blank then - * this argument is done. - */ - if (isBlank(ch) && (quote == '\0')) - break; - - /* - * If we see a backslash then accept the next - * character no matter what it is. - */ - if (ch == '\\') - { - ch = *cp++; - - /* - * Make sure there is a next character. - */ - if (ch == '\0') - { - fprintf(stderr, - "Bad quoted character\n"); - - return FALSE; - } - - /* - * Remember whether the quoted character - * is a wildcard. - */ - if (isWildCard(ch)) - quotedWildCards = TRUE; - - *cpOut++ = ch; - - continue; - } - - /* - * If we see one of the wildcard characters then - * remember whether it was seen inside or outside - * of quotes. - */ - if (isWildCard(ch)) - { - if (quote) - quotedWildCards = TRUE; - else - unquotedWildCards = TRUE; - } - - /* - * If we were in a quote and we saw the same quote - * character again then the quote is done. - */ - if (ch == quote) - { - quote = '\0'; - - continue; - } - - /* - * If we weren't in a quote and we see either type - * of quote character, then remember that we are - * now inside of a quote. - */ - if ((quote == '\0') && ((ch == '\'') || (ch == '"'))) - { - quote = ch; - - continue; - } - - /* - * Store the character. - */ - *cpOut++ = ch; - } - - /* - * Make sure that quoting is terminated properly. - */ - if (quote) - { - fprintf(stderr, "Unmatched quote character\n"); - - return FALSE; - } - - /* - * Null terminate the argument if it had shrunk, and then - * skip over all blanks to the next argument, nulling them - * out too. - */ - if (cp != cpOut) - *cpOut = '\0'; - - while (isBlank(*cp)) - *cp++ = '\0'; - - /* - * If both quoted and unquoted wildcards were used then - * complain since we don't handle them properly. - */ - if (quotedWildCards && unquotedWildCards) - { - fprintf(stderr, - "Cannot use quoted and unquoted wildcards\n"); - - return FALSE; - } - - /* - * Expand the argument into the matching filenames or accept - * it as is depending on whether there were any unquoted - * wildcard characters in it. - */ - if (unquotedWildCards) - { - /* - * Expand the argument into the matching filenames. - */ - fileCount = expandWildCards(argument, &fileTable); - - /* - * Return an error if the wildcards failed to match. - */ - if (fileCount < 0) - return FALSE; - - if (fileCount == 0) - { - fprintf(stderr, "Wildcard expansion error\n"); - - return FALSE; - } - } - else - { - /* - * Set up to only store the argument itself. - */ - fileTable = &argument; - fileCount = 1; - } - - /* - * Now reallocate the argument table to hold the file name. - */ - if (argCount + fileCount >= argTableSize) - { - newArgTableSize = argCount + fileCount + 1; - - newArgTable = (const char **) realloc(argTable, - (sizeof(const char *) * newArgTableSize)); - - if (newArgTable == NULL) - { - fprintf(stderr, "No memory for arg list\n"); - - return FALSE; - } - - argTable = newArgTable; - argTableSize = newArgTableSize; - } - - /* - * Copy the new arguments to the end of the old ones. - */ - memcpy((void *) &argTable[argCount], (const void *) fileTable, - (sizeof(const char **) * fileCount)); - - /* - * Add to the argument count. - */ - argCount += fileCount; - } - - /* - * Null terminate the argument list and return it. - */ - argTable[argCount] = NULL; - - *retArgc = argCount; - *retArgv = argTable; - - return TRUE; -} - - -/* * Make a NULL-terminated string out of an argc, argv pair. * Returns TRUE if successful, or FALSE if the string is too long, * with an error message given. This does not handle spaces within @@ -1114,15 +468,14 @@ fullRead(int fd, char * buf, int len) /* - * Read all of the supplied buffer from a file. - * This does multiple reads as necessary. - * Returns the amount read, or -1 on an error. - * A short read is returned on an end of file. + * Walk down all the directories under the specified + * location, and do something (something specified + * by the fileAction and dirAction function pointers). */ int -recursive( const char *fileName, BOOL followLinks, const char* pattern, - int (*fileAction)(const char* fileName, const struct stat* statbuf), - int (*dirAction)(const char* fileName, const struct stat* statbuf)) +recursiveAction( const char *fileName, BOOL followLinks, + int (*fileAction)(const char* fileName), + int (*dirAction)(const char* fileName)) { int status; struct stat statbuf; @@ -1135,45 +488,44 @@ recursive( const char *fileName, BOOL followLinks, const char* pattern, if (status < 0) { perror(fileName); - return( -1); + return( FALSE); } - if (S_ISREG(statbuf.st_mode)) { - if (match(fileName, pattern)) { - if (fileAction==NULL) - fprintf( stdout, "%s\n", fileName); - else - return(fileAction(fileName, &statbuf)); + if (S_ISDIR(statbuf.st_mode)) { + DIR *dir; + dir = opendir(fileName); + if (!dir) { + perror(fileName); + return(FALSE); } - } - else if (S_ISDIR(statbuf.st_mode)) { - if (dirAction==NULL) { - DIR *dir; - if (! match(fileName, pattern)) - return 1; - dir = opendir(fileName); - if (!dir) { - perror(fileName); - return( -1); - } - while ((next = readdir (dir)) != NULL) { - status = recursive(fileName, followLinks, pattern, fileAction, dirAction); - if (status < 0) { - closedir(dir); - return(status); - } - } - status = closedir (dir); - if (status < 0) { - perror(fileName); - return( -1); - } + while ((next = readdir (dir)) != NULL) { + char nextFile[NAME_MAX]; + if ( (strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0) ) { + continue; + } + sprintf(nextFile, "%s/%s", fileName, next->d_name); + status = recursiveAction(nextFile, followLinks, fileAction, dirAction); + if (status < 0) { + closedir(dir); + return(FALSE); + } + } + status = closedir (dir); + if (status < 0) { + perror(fileName); + return( FALSE); } + if (dirAction==NULL) + return(TRUE); else - return(dirAction(fileName, &statbuf)); + return(dirAction(fileName)); + } + else { + if (fileAction==NULL) + return(TRUE); + else + return(fileAction(fileName)); } - return( 1); - } |