ar.c now uses a linked list to process headers, uses getopt, new internal function...
authorGlenn L McGrath <bug1@ihug.co.nz>
Fri, 25 Aug 2000 03:50:10 +0000 (03:50 -0000)
committerGlenn L McGrath <bug1@ihug.co.nz>
Fri, 25 Aug 2000 03:50:10 +0000 (03:50 -0000)
moved copySubFile from ar.c to utilities.c

modified dd.c to use fullWrite

modified copyFile in utilities.c to use copySubFile

applets/usage.c
ar.c
archival/ar.c
coreutils/dd.c
dd.c
internal.h
usage.c
utility.c

index 0dad1ba302abafc5687325cc2c7cedac3ad9e5d9..35f63db8655a3f21ed06aa1f7db29644294b39fd 100644 (file)
@@ -2,15 +2,15 @@
 
 #if defined BB_AR
 const char ar_usage[] =
-       "ar [optxvV] archive [filenames] \n"
+       "ar [[-ov] -tpv archive] filenames \n"
 #ifndef BB_FEATURE_TRIVIAL_HELP
        "\nExtract or list files from an ar archive.\n\n"
        "Options:\n"
-       "\to\t\tpreserve original dates\n"
-       "\tp\t\textract to stdout\n"
-       "\tt\t\tlist\n"
-       "\tx\t\textract\n"
-       "\tv\t\tverbosely list files processed\n"
+       "\t-o\t\tpreserve original dates\n"
+       "\t-p\t\textract to stdout\n"
+       "\t-t\t\tlist\n"
+       "\t-x\t\textract\n"
+       "\t-v\t\tverbosely list files processed\n"
 #endif
        ;
 #endif
diff --git a/ar.c b/ar.c
index b1200b8ae840e19fec23b1ce1b3bbe63863ff17a..1c598fa164654feea3e3d0104d34d99affb57545 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -4,6 +4,12 @@
  *
  * Copyright (C) 2000 by Glenn McGrath
  * Written by Glenn McGrath <bug1@netconnect.com.au> 1 June 2000
+ *             
+ * Modified 8 August 2000 by Glenn McGrath 
+ *  - now uses getopt
+ *  - moved copySubFile function to utilities.c
+ *  - creates linked list of all headers 
+ *  - easily accessable to other busybox functions  
  *
  * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * Last modified 10 June 2000
+ * Last modified 25 August 2000
  */
-
-
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
 #include "internal.h"
 
-#define AR_BLOCK_SIZE 60
-#define AR_PRESERVE_DATE 1     /* preserve original dates */
-#define AR_VERBOSE       2     /* be verbose */
-#define AR_DISPLAY       4     /* display contents */
-#define AR_EXT_TO_FILE   8     /* extract contents of archive */
-#define AR_EXT_TO_STDOUT 16    /* extract to stdout */
+#define BLOCK_SIZE 60
+#define PRESERVE_DATE 1        /* preserve original dates */
+#define VERBOSE       2        /* be verbose */
+#define DISPLAY       4        /* display contents */
+#define EXT_TO_FILE   8        /* extract contents of archive */
+#define EXT_TO_STDOUT 16       /* extract to stdout */
 
 #define BB_DECLARE_EXTERN
 #define bb_need_io_error
 #include "messages.c"
 
-struct ArHeader {                              /* Byte Offset */
-       char ar_name[16];                       /*  0-15 */
-       char ar_date[12];                       /* 16-27 */
-       char ar_uid[6], ar_gid[6];      /* 28-39 */
-       char ar_mode[8];                        /* 40-47 */
-       char ar_size[10];                       /* 48-57 */
-       char ar_fmag[2];                        /* 58-59 */
-};
-typedef struct ArHeader ArHeader;
-
-struct ArInfo {
-       char name[17];                          /* File name */
-       time_t date;                            /* long int, No of seconds since epoch */
-       uid_t uid;                                      /* unsigned int, Numeric UID */
-       gid_t gid;                                      /* unsigned int, Numeric GID */
-       mode_t mode;                            /* unsigned int, Unix mode */
-       size_t size;                            /* int, Size of the file */
-};
-typedef struct ArInfo ArInfo;
+typedef struct rawArHeader {            /* Byte Offset */
+        char name[16];          /*  0-15 */
+        char date[12];          /* 16-27 */
+        char uid[6], gid[6];    /* 28-39 */
+        char mode[8];           /* 40-47 */
+        char size[10];          /* 48-57 */
+        char fmag[2];           /* 58-59 */
+} rawArHeader_t;
+
+typedef struct headerL {
+       char name[16];
+        size_t size;
+        uid_t uid;
+        gid_t gid;
+        mode_t mode;
+        time_t mtime;
+        off_t offset;
+       struct headerL *next;
+} headerL_t;
 
 /*
- * Display details of a file, verbosly if funct=2   
+ * populate linked list with all ar file entries and offset 
  */
-static void displayEntry(struct ArInfo *entry, int funct)
+static int parseArArchive(int srcFd, headerL_t *current)
 {
-       /* TODO convert mode to string */
-       if ((funct & AR_VERBOSE) == AR_VERBOSE)
-               printf("%i %i/%i %8i %s ", entry->mode, entry->uid, entry->gid,
-                          entry->size, timeString(entry->date));
-       printf("%s\n", entry->name);
-}
-
-/* this is from tar.c remove later*/
-static long getOctal(const char *cp, int size)
-{
-        long val = 0;
-
-        for(;(size > 0) && (*cp == ' '); cp++, size--);
-        if ((size == 0) || !isOctal(*cp))
-                return -1;
-        for(; (size > 0) && isOctal(*cp); size--) {
-                val = val * 8 + *cp++ - '0';
+        off_t lastOffset=0, thisOffset=0;
+        char arVersion[8];
+        rawArHeader_t rawArHeader;
+       
+       lseek(srcFd, 0, SEEK_SET);
+        if (fullRead(srcFd, arVersion, 8) <= 0) {
+                errorMsg("Invalid header magic\n");
+                return (FALSE);
         }
-        for (;(size > 0) && (*cp == ' '); cp++, size--);
-        if ((size > 0) && *cp)
-                return -1;
-        return val;
-}
-
-/*
- * Converts from the char based struct to a new struct with stricter types
- */
-static int processArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
-{
-       int count2;
-       int count;
-       
-       /* check end of header marker is valid */
-       if ((rawHeader->ar_fmag[0]!='`') || (rawHeader->ar_fmag[1]!='\n')) 
-               return(FALSE); 
-
-       /* convert filename */ 
-       for (count = 0; count < 16; count++) {
-               /* allow spaces in filename except at the end */
-               if (rawHeader->ar_name[count] == ' ') {
-                       for (count2 = count; count2 < 16; count2++)
-                               if (!isspace(rawHeader->ar_name[count2]))
-                                       break;
-                       if (count2 >= 16)
-                               break;
-               }
-               /* GNU ar uses '/' as an end of filename marker */
-               if (rawHeader->ar_name[count] == '/')
-                       break;
-               header->name[count] = rawHeader->ar_name[count];
-       }
-       header->name[count] = '\0';
-       header->date = atoi(rawHeader->ar_date);
-       header->uid = atoi(rawHeader->ar_uid);
-       header->gid = atoi(rawHeader->ar_gid);
-       header->mode = getOctal(rawHeader->ar_mode, sizeof(rawHeader->ar_mode));
-       header->size = atoi(rawHeader->ar_size);
-       return (TRUE);
-}
-
-/*
- * Copy size bytes from current position if srcFd to current position in dstFd
- * taken from tarExtractRegularFile in tar.c, remove later
- */
-static int copySubFile(int srcFd, int dstFd, int copySize)
-{
-       int readSize, writeSize, doneSize;
-       char buffer[BUFSIZ];
-
-       while (copySize > 0) {
-               if (copySize > BUFSIZ)
-                       readSize = BUFSIZ;
-               else
-                       readSize = copySize;
-               writeSize = fullRead(srcFd, buffer, readSize);
-               if (writeSize <= 0) {
-                       errorMsg(io_error, "copySubFile", strerror(errno));
-                       return (FALSE);
-               }
-               doneSize = fullWrite(dstFd, buffer, writeSize);
-               if (doneSize <= 0) {
-                       errorMsg(io_error, "copySubFile", strerror(errno));
-                       return (FALSE);
-               }
-               copySize -= doneSize;
-       }
-       return (TRUE);
+        if (strncmp(arVersion,"!<arch>",7) != 0) {
+                errorMsg("This doesnt appear to be an ar archive\n");
+                return(FALSE);
+        }
+        while (fullRead(srcFd, (char *) &rawArHeader, 60) == 60) {
+              if ( (rawArHeader.fmag[0] == '`') &&
+                        (rawArHeader.fmag[1] == '\n')) {
+                        sscanf(rawArHeader.name, "%s", current->name);
+                        parse_mode(rawArHeader.mode, &current->mode);
+                        current->mtime = atoi(rawArHeader.date);
+                        current->uid = atoi(rawArHeader.uid);
+                        current->gid = atoi(rawArHeader.gid);
+                        current->size = (size_t) atoi(rawArHeader.size);
+                        current->offset = lseek(srcFd, 0 , SEEK_CUR);
+                       current->next = (headerL_t *) xmalloc(sizeof(headerL_t));
+                       lastOffset = lseek(srcFd, (off_t) current->size, SEEK_CUR);
+                       current = current->next;
+                }
+                else {  /* GNU ar has an extra char after data */
+                       thisOffset=lseek(srcFd, 0, SEEK_CUR);
+                        if ( (thisOffset - lastOffset) > ((off_t) 61) ) 
+                                return(FALSE);
+                       lseek(srcFd, thisOffset - 59, SEEK_SET);
+                }
+        }
+        return(FALSE);
 }
 
 /*
- * Extract the file described in ArInfo to the specified path 
- * set the new files uid, gid and mode 
+ * return the headerL_t struct for the specified filename
  */
-static int extractToFile(struct ArInfo *file, int funct, int srcFd, const char *path)
+static headerL_t *getSubFileHeader(int srcFd, const char filename[16])
 {
-       int dstFd, temp;
-       struct stat tmpStat;
-       char *pathname = NULL;
-       struct utimbuf newtime;
-       
-       if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) {
-               if (!createPath(path, 0777)) {
-                       fatalError("Cannot extract to specified path");
-                       return (FALSE);
-               }
-       }
-       temp = (strlen(path) + 16);
-       pathname = (char *) xmalloc(temp);
-       pathname = strcpy(pathname, path);
-       pathname = strcat(pathname, file->name);
-       dstFd = device_open(pathname, O_WRONLY | O_CREAT);
-       temp = copySubFile(srcFd, dstFd, file->size);
-       fchown(dstFd, file->uid, file->gid);
-       fchmod(dstFd, file->mode);
-       close(dstFd);
-       if ((funct&AR_PRESERVE_DATE)==AR_PRESERVE_DATE) 
-               newtime.modtime=file->date;
-       else
-               newtime.modtime=time(0);
-       newtime.actime=time(0);
-       temp = utime(pathname, &newtime);
-       return (TRUE);
+        headerL_t *list;
+       list = xmalloc(sizeof(headerL_t)); 
+
+        parseArArchive(srcFd, list);
+        while (list->next != NULL) {
+                if (strncmp(list->name, filename, strlen(filename))==0)
+                        return(list);
+                list=list->next;
+        }
+        return(NULL);
 }
 
 /*
- * Return a file descriptor for the specified file and do error checks
+ * populate linked list with all ar file entries and offset 
  */
-static int getArFd(char *filename)
+static int displayEntry(int srcFd, const char filename[16], int funct)
 {
-        int arFd;
-        char arVersion[8];
+       headerL_t *file;
 
-        arFd = open(filename, O_RDONLY);
-        if (arFd < 0) { 
-                errorMsg("Error opening '%s': %s\n", filename, strerror(errno));
-               return (FALSE);
+       if ((file = getSubFileHeader(srcFd, filename)) == NULL)
+               return(FALSE);
+       if ((funct & VERBOSE) == VERBOSE) {
+               printf("%s %d/%d %8d %s ", modeString(file->mode), file->uid, file->gid, file->size, timeString(file->mtime));
        }
-        if (fullRead(arFd, arVersion, 8) <= 0) {
-                errorMsg( "Unexpected EOF in archive\n");
-                return (FALSE);
-        }
-        if (strncmp(arVersion,"!<arch>",7) != 0) {
-                errorMsg("ar header fails check ");
-                return(FALSE);
-        }
-        return arFd;
+       printf("%s\n", file->name);
+       return(TRUE);
 }
 
-/*
- * Step through the ar file and process it one entry at a time
- * fileList[0] is the name of the ar archive
- * fileList[1] and up are filenames to extract from the archive
- * funct contains flags to specify the actions to be performed 
- */
-static int readArFile(char *fileList[16], int fileListSize, int funct)
+static int extractAr(int srcFd, int dstFd, const char filename[16])
 {
-       int arFd, status, extFileFlag, i, lastOffset=0;
-       ArHeader rawArHeader;
-       ArInfo arEntry;
-
-       /* open the ar archive */
-       arFd=getArFd(fileList[0]);
-
-       /* read the first header, then loop until ono more headers */ 
-       while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE))
-                  == AR_BLOCK_SIZE) {
-
-               /* check the header is valid, if not try reading the header
-                  agian with an offset of 1, needed as some ar archive end
-                   with a '\n' which isnt counted in specified file size */
-               if ((status=processArHeader(&rawArHeader, &arEntry))==FALSE ) {
-                       if ((i=lseek(arFd, 0, SEEK_CUR))==(lastOffset+60)) 
-                               lseek(arFd, lastOffset+1, SEEK_SET);
-                       else 
-                               return(FALSE);
-                       }
-               else {  
-                       extFileFlag=0;
-                       
-                       if ((funct&AR_DISPLAY) || (funct&AR_VERBOSE))
-                               displayEntry(&arEntry, funct);
-
-                       /* check file was specified to be extracted only if 
-                          some file were specified */
-                       if ((funct&AR_EXT_TO_FILE) || (funct&AR_EXT_TO_STDOUT)){
-                               if (fileListSize==1)
-                                       extFileFlag=1;
-                               else {
-                                       for( i=1; i<=fileListSize; i++)
-                                               if ((status=(strcmp(fileList[i],arEntry.name)))==0)
-                                                       extFileFlag=1;
-                               }
-                       }
-                       if (extFileFlag==1) { 
-                               if (funct&AR_EXT_TO_FILE)
-                                               extractToFile(&arEntry, funct, arFd, "./");
-                               else    
-                                               copySubFile(arFd,fileno(stdout),arEntry.size);
-                       }
-                       else
-                               lseek(arFd, arEntry.size, SEEK_CUR);
-                       lastOffset=lseek(arFd, 0, SEEK_CUR);
-               } /* if processArHeader */
-       }  /* while */
-       return (TRUE);
+        headerL_t *file;
+        if ( (file = getSubFileHeader(srcFd, filename)) == NULL)
+               return(FALSE);
+       lseek(srcFd, file->offset, SEEK_SET);
+       if (copySubFile(srcFd, dstFd, (size_t) file->size) == TRUE)
+               return(TRUE);   
+       return(FALSE);
 }
 
 extern int ar_main(int argc, char **argv)
 {
-        int funct = 0, ret=0, i=0;
-        char *fileList[16], c, *opt_ptr;
-
-       if (argc < 2)
-               usage(ar_usage);
-
-       opt_ptr = argv[1];
-       if (*opt_ptr == '-')
-               ++opt_ptr;
-       while ((c = *opt_ptr++) != '\0') {
-               switch (c) {
+        int funct = 0, opt=0;
+       int srcFd=0, dstFd=0;
+       while ((opt = getopt(argc, argv, "ovt:p:x:")) != -1) {
+               switch (opt) {
                case 'o':
-                       funct = funct | AR_PRESERVE_DATE;
+                       funct = funct | PRESERVE_DATE;
                        break;
                case 'v':
-                       funct = funct | AR_VERBOSE;
+                       funct = funct | VERBOSE;
                        break;
                case 't':
-                       funct = funct | AR_DISPLAY;
-                       break;
+                       funct = funct | DISPLAY;
                case 'x':
-                       funct = funct | AR_EXT_TO_FILE;
-                       break;
+                       if (opt=='x') {
+                               funct = funct | EXT_TO_FILE;
+                        }
                case 'p':
-                       funct = funct | AR_EXT_TO_STDOUT;
+                       if (opt=='p') {
+                               funct = funct | EXT_TO_STDOUT;
+                       }
+                       /* following is common to 't','x' and 'p' */
+                        if (optarg == NULL) {
+                                printf("expected a filename\n");
+                                return(FALSE);
+                        }
+                       if ( (srcFd = open(optarg, O_RDONLY)) < 0) {
+                               errorMsg("Cannot read %s\n", optarg);
+                               return (FALSE);
+                       }
                        break;
                default:
                        usage(ar_usage);
                }
        }
-
-        for(i=0; i<(argc-2); i++) 
-                fileList[i]=argv[i+2];
-       
-       if (funct > 3)
-               ret = readArFile(fileList, (argc-2), funct);
+        /* check options not just preserve_dates and/or verbose */  
+       if (funct < 4) {
+                usage(ar_usage);
+                return(FALSE);
+        }
        
-       return (ret);
+       /* find files to extract */
+       if (optind<argc)
+               for(; optind < argc; optind++) {
+                       if ( (funct & EXT_TO_FILE) == EXT_TO_FILE) {
+                               dstFd = open(argv[optind], O_WRONLY | O_CREAT);
+                               extractAr(srcFd, dstFd, argv[optind]);
+                       }
+                       if ( (funct & EXT_TO_STDOUT) == EXT_TO_STDOUT)  
+                               extractAr(srcFd, fileno(stdout), argv[optind]); 
+                       if ( (funct & DISPLAY) == DISPLAY)
+                               displayEntry(srcFd, argv[optind], funct);
+               }
+       return (TRUE);
 }
index b1200b8ae840e19fec23b1ce1b3bbe63863ff17a..1c598fa164654feea3e3d0104d34d99affb57545 100644 (file)
@@ -4,6 +4,12 @@
  *
  * Copyright (C) 2000 by Glenn McGrath
  * Written by Glenn McGrath <bug1@netconnect.com.au> 1 June 2000
+ *             
+ * Modified 8 August 2000 by Glenn McGrath 
+ *  - now uses getopt
+ *  - moved copySubFile function to utilities.c
+ *  - creates linked list of all headers 
+ *  - easily accessable to other busybox functions  
  *
  * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * Last modified 10 June 2000
+ * Last modified 25 August 2000
  */
-
-
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
 #include "internal.h"
 
-#define AR_BLOCK_SIZE 60
-#define AR_PRESERVE_DATE 1     /* preserve original dates */
-#define AR_VERBOSE       2     /* be verbose */
-#define AR_DISPLAY       4     /* display contents */
-#define AR_EXT_TO_FILE   8     /* extract contents of archive */
-#define AR_EXT_TO_STDOUT 16    /* extract to stdout */
+#define BLOCK_SIZE 60
+#define PRESERVE_DATE 1        /* preserve original dates */
+#define VERBOSE       2        /* be verbose */
+#define DISPLAY       4        /* display contents */
+#define EXT_TO_FILE   8        /* extract contents of archive */
+#define EXT_TO_STDOUT 16       /* extract to stdout */
 
 #define BB_DECLARE_EXTERN
 #define bb_need_io_error
 #include "messages.c"
 
-struct ArHeader {                              /* Byte Offset */
-       char ar_name[16];                       /*  0-15 */
-       char ar_date[12];                       /* 16-27 */
-       char ar_uid[6], ar_gid[6];      /* 28-39 */
-       char ar_mode[8];                        /* 40-47 */
-       char ar_size[10];                       /* 48-57 */
-       char ar_fmag[2];                        /* 58-59 */
-};
-typedef struct ArHeader ArHeader;
-
-struct ArInfo {
-       char name[17];                          /* File name */
-       time_t date;                            /* long int, No of seconds since epoch */
-       uid_t uid;                                      /* unsigned int, Numeric UID */
-       gid_t gid;                                      /* unsigned int, Numeric GID */
-       mode_t mode;                            /* unsigned int, Unix mode */
-       size_t size;                            /* int, Size of the file */
-};
-typedef struct ArInfo ArInfo;
+typedef struct rawArHeader {            /* Byte Offset */
+        char name[16];          /*  0-15 */
+        char date[12];          /* 16-27 */
+        char uid[6], gid[6];    /* 28-39 */
+        char mode[8];           /* 40-47 */
+        char size[10];          /* 48-57 */
+        char fmag[2];           /* 58-59 */
+} rawArHeader_t;
+
+typedef struct headerL {
+       char name[16];
+        size_t size;
+        uid_t uid;
+        gid_t gid;
+        mode_t mode;
+        time_t mtime;
+        off_t offset;
+       struct headerL *next;
+} headerL_t;
 
 /*
- * Display details of a file, verbosly if funct=2   
+ * populate linked list with all ar file entries and offset 
  */
-static void displayEntry(struct ArInfo *entry, int funct)
+static int parseArArchive(int srcFd, headerL_t *current)
 {
-       /* TODO convert mode to string */
-       if ((funct & AR_VERBOSE) == AR_VERBOSE)
-               printf("%i %i/%i %8i %s ", entry->mode, entry->uid, entry->gid,
-                          entry->size, timeString(entry->date));
-       printf("%s\n", entry->name);
-}
-
-/* this is from tar.c remove later*/
-static long getOctal(const char *cp, int size)
-{
-        long val = 0;
-
-        for(;(size > 0) && (*cp == ' '); cp++, size--);
-        if ((size == 0) || !isOctal(*cp))
-                return -1;
-        for(; (size > 0) && isOctal(*cp); size--) {
-                val = val * 8 + *cp++ - '0';
+        off_t lastOffset=0, thisOffset=0;
+        char arVersion[8];
+        rawArHeader_t rawArHeader;
+       
+       lseek(srcFd, 0, SEEK_SET);
+        if (fullRead(srcFd, arVersion, 8) <= 0) {
+                errorMsg("Invalid header magic\n");
+                return (FALSE);
         }
-        for (;(size > 0) && (*cp == ' '); cp++, size--);
-        if ((size > 0) && *cp)
-                return -1;
-        return val;
-}
-
-/*
- * Converts from the char based struct to a new struct with stricter types
- */
-static int processArHeader(struct ArHeader *rawHeader, struct ArInfo *header)
-{
-       int count2;
-       int count;
-       
-       /* check end of header marker is valid */
-       if ((rawHeader->ar_fmag[0]!='`') || (rawHeader->ar_fmag[1]!='\n')) 
-               return(FALSE); 
-
-       /* convert filename */ 
-       for (count = 0; count < 16; count++) {
-               /* allow spaces in filename except at the end */
-               if (rawHeader->ar_name[count] == ' ') {
-                       for (count2 = count; count2 < 16; count2++)
-                               if (!isspace(rawHeader->ar_name[count2]))
-                                       break;
-                       if (count2 >= 16)
-                               break;
-               }
-               /* GNU ar uses '/' as an end of filename marker */
-               if (rawHeader->ar_name[count] == '/')
-                       break;
-               header->name[count] = rawHeader->ar_name[count];
-       }
-       header->name[count] = '\0';
-       header->date = atoi(rawHeader->ar_date);
-       header->uid = atoi(rawHeader->ar_uid);
-       header->gid = atoi(rawHeader->ar_gid);
-       header->mode = getOctal(rawHeader->ar_mode, sizeof(rawHeader->ar_mode));
-       header->size = atoi(rawHeader->ar_size);
-       return (TRUE);
-}
-
-/*
- * Copy size bytes from current position if srcFd to current position in dstFd
- * taken from tarExtractRegularFile in tar.c, remove later
- */
-static int copySubFile(int srcFd, int dstFd, int copySize)
-{
-       int readSize, writeSize, doneSize;
-       char buffer[BUFSIZ];
-
-       while (copySize > 0) {
-               if (copySize > BUFSIZ)
-                       readSize = BUFSIZ;
-               else
-                       readSize = copySize;
-               writeSize = fullRead(srcFd, buffer, readSize);
-               if (writeSize <= 0) {
-                       errorMsg(io_error, "copySubFile", strerror(errno));
-                       return (FALSE);
-               }
-               doneSize = fullWrite(dstFd, buffer, writeSize);
-               if (doneSize <= 0) {
-                       errorMsg(io_error, "copySubFile", strerror(errno));
-                       return (FALSE);
-               }
-               copySize -= doneSize;
-       }
-       return (TRUE);
+        if (strncmp(arVersion,"!<arch>",7) != 0) {
+                errorMsg("This doesnt appear to be an ar archive\n");
+                return(FALSE);
+        }
+        while (fullRead(srcFd, (char *) &rawArHeader, 60) == 60) {
+              if ( (rawArHeader.fmag[0] == '`') &&
+                        (rawArHeader.fmag[1] == '\n')) {
+                        sscanf(rawArHeader.name, "%s", current->name);
+                        parse_mode(rawArHeader.mode, &current->mode);
+                        current->mtime = atoi(rawArHeader.date);
+                        current->uid = atoi(rawArHeader.uid);
+                        current->gid = atoi(rawArHeader.gid);
+                        current->size = (size_t) atoi(rawArHeader.size);
+                        current->offset = lseek(srcFd, 0 , SEEK_CUR);
+                       current->next = (headerL_t *) xmalloc(sizeof(headerL_t));
+                       lastOffset = lseek(srcFd, (off_t) current->size, SEEK_CUR);
+                       current = current->next;
+                }
+                else {  /* GNU ar has an extra char after data */
+                       thisOffset=lseek(srcFd, 0, SEEK_CUR);
+                        if ( (thisOffset - lastOffset) > ((off_t) 61) ) 
+                                return(FALSE);
+                       lseek(srcFd, thisOffset - 59, SEEK_SET);
+                }
+        }
+        return(FALSE);
 }
 
 /*
- * Extract the file described in ArInfo to the specified path 
- * set the new files uid, gid and mode 
+ * return the headerL_t struct for the specified filename
  */
-static int extractToFile(struct ArInfo *file, int funct, int srcFd, const char *path)
+static headerL_t *getSubFileHeader(int srcFd, const char filename[16])
 {
-       int dstFd, temp;
-       struct stat tmpStat;
-       char *pathname = NULL;
-       struct utimbuf newtime;
-       
-       if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) {
-               if (!createPath(path, 0777)) {
-                       fatalError("Cannot extract to specified path");
-                       return (FALSE);
-               }
-       }
-       temp = (strlen(path) + 16);
-       pathname = (char *) xmalloc(temp);
-       pathname = strcpy(pathname, path);
-       pathname = strcat(pathname, file->name);
-       dstFd = device_open(pathname, O_WRONLY | O_CREAT);
-       temp = copySubFile(srcFd, dstFd, file->size);
-       fchown(dstFd, file->uid, file->gid);
-       fchmod(dstFd, file->mode);
-       close(dstFd);
-       if ((funct&AR_PRESERVE_DATE)==AR_PRESERVE_DATE) 
-               newtime.modtime=file->date;
-       else
-               newtime.modtime=time(0);
-       newtime.actime=time(0);
-       temp = utime(pathname, &newtime);
-       return (TRUE);
+        headerL_t *list;
+       list = xmalloc(sizeof(headerL_t)); 
+
+        parseArArchive(srcFd, list);
+        while (list->next != NULL) {
+                if (strncmp(list->name, filename, strlen(filename))==0)
+                        return(list);
+                list=list->next;
+        }
+        return(NULL);
 }
 
 /*
- * Return a file descriptor for the specified file and do error checks
+ * populate linked list with all ar file entries and offset 
  */
-static int getArFd(char *filename)
+static int displayEntry(int srcFd, const char filename[16], int funct)
 {
-        int arFd;
-        char arVersion[8];
+       headerL_t *file;
 
-        arFd = open(filename, O_RDONLY);
-        if (arFd < 0) { 
-                errorMsg("Error opening '%s': %s\n", filename, strerror(errno));
-               return (FALSE);
+       if ((file = getSubFileHeader(srcFd, filename)) == NULL)
+               return(FALSE);
+       if ((funct & VERBOSE) == VERBOSE) {
+               printf("%s %d/%d %8d %s ", modeString(file->mode), file->uid, file->gid, file->size, timeString(file->mtime));
        }
-        if (fullRead(arFd, arVersion, 8) <= 0) {
-                errorMsg( "Unexpected EOF in archive\n");
-                return (FALSE);
-        }
-        if (strncmp(arVersion,"!<arch>",7) != 0) {
-                errorMsg("ar header fails check ");
-                return(FALSE);
-        }
-        return arFd;
+       printf("%s\n", file->name);
+       return(TRUE);
 }
 
-/*
- * Step through the ar file and process it one entry at a time
- * fileList[0] is the name of the ar archive
- * fileList[1] and up are filenames to extract from the archive
- * funct contains flags to specify the actions to be performed 
- */
-static int readArFile(char *fileList[16], int fileListSize, int funct)
+static int extractAr(int srcFd, int dstFd, const char filename[16])
 {
-       int arFd, status, extFileFlag, i, lastOffset=0;
-       ArHeader rawArHeader;
-       ArInfo arEntry;
-
-       /* open the ar archive */
-       arFd=getArFd(fileList[0]);
-
-       /* read the first header, then loop until ono more headers */ 
-       while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE))
-                  == AR_BLOCK_SIZE) {
-
-               /* check the header is valid, if not try reading the header
-                  agian with an offset of 1, needed as some ar archive end
-                   with a '\n' which isnt counted in specified file size */
-               if ((status=processArHeader(&rawArHeader, &arEntry))==FALSE ) {
-                       if ((i=lseek(arFd, 0, SEEK_CUR))==(lastOffset+60)) 
-                               lseek(arFd, lastOffset+1, SEEK_SET);
-                       else 
-                               return(FALSE);
-                       }
-               else {  
-                       extFileFlag=0;
-                       
-                       if ((funct&AR_DISPLAY) || (funct&AR_VERBOSE))
-                               displayEntry(&arEntry, funct);
-
-                       /* check file was specified to be extracted only if 
-                          some file were specified */
-                       if ((funct&AR_EXT_TO_FILE) || (funct&AR_EXT_TO_STDOUT)){
-                               if (fileListSize==1)
-                                       extFileFlag=1;
-                               else {
-                                       for( i=1; i<=fileListSize; i++)
-                                               if ((status=(strcmp(fileList[i],arEntry.name)))==0)
-                                                       extFileFlag=1;
-                               }
-                       }
-                       if (extFileFlag==1) { 
-                               if (funct&AR_EXT_TO_FILE)
-                                               extractToFile(&arEntry, funct, arFd, "./");
-                               else    
-                                               copySubFile(arFd,fileno(stdout),arEntry.size);
-                       }
-                       else
-                               lseek(arFd, arEntry.size, SEEK_CUR);
-                       lastOffset=lseek(arFd, 0, SEEK_CUR);
-               } /* if processArHeader */
-       }  /* while */
-       return (TRUE);
+        headerL_t *file;
+        if ( (file = getSubFileHeader(srcFd, filename)) == NULL)
+               return(FALSE);
+       lseek(srcFd, file->offset, SEEK_SET);
+       if (copySubFile(srcFd, dstFd, (size_t) file->size) == TRUE)
+               return(TRUE);   
+       return(FALSE);
 }
 
 extern int ar_main(int argc, char **argv)
 {
-        int funct = 0, ret=0, i=0;
-        char *fileList[16], c, *opt_ptr;
-
-       if (argc < 2)
-               usage(ar_usage);
-
-       opt_ptr = argv[1];
-       if (*opt_ptr == '-')
-               ++opt_ptr;
-       while ((c = *opt_ptr++) != '\0') {
-               switch (c) {
+        int funct = 0, opt=0;
+       int srcFd=0, dstFd=0;
+       while ((opt = getopt(argc, argv, "ovt:p:x:")) != -1) {
+               switch (opt) {
                case 'o':
-                       funct = funct | AR_PRESERVE_DATE;
+                       funct = funct | PRESERVE_DATE;
                        break;
                case 'v':
-                       funct = funct | AR_VERBOSE;
+                       funct = funct | VERBOSE;
                        break;
                case 't':
-                       funct = funct | AR_DISPLAY;
-                       break;
+                       funct = funct | DISPLAY;
                case 'x':
-                       funct = funct | AR_EXT_TO_FILE;
-                       break;
+                       if (opt=='x') {
+                               funct = funct | EXT_TO_FILE;
+                        }
                case 'p':
-                       funct = funct | AR_EXT_TO_STDOUT;
+                       if (opt=='p') {
+                               funct = funct | EXT_TO_STDOUT;
+                       }
+                       /* following is common to 't','x' and 'p' */
+                        if (optarg == NULL) {
+                                printf("expected a filename\n");
+                                return(FALSE);
+                        }
+                       if ( (srcFd = open(optarg, O_RDONLY)) < 0) {
+                               errorMsg("Cannot read %s\n", optarg);
+                               return (FALSE);
+                       }
                        break;
                default:
                        usage(ar_usage);
                }
        }
-
-        for(i=0; i<(argc-2); i++) 
-                fileList[i]=argv[i+2];
-       
-       if (funct > 3)
-               ret = readArFile(fileList, (argc-2), funct);
+        /* check options not just preserve_dates and/or verbose */  
+       if (funct < 4) {
+                usage(ar_usage);
+                return(FALSE);
+        }
        
-       return (ret);
+       /* find files to extract */
+       if (optind<argc)
+               for(; optind < argc; optind++) {
+                       if ( (funct & EXT_TO_FILE) == EXT_TO_FILE) {
+                               dstFd = open(argv[optind], O_WRONLY | O_CREAT);
+                               extractAr(srcFd, dstFd, argv[optind]);
+                       }
+                       if ( (funct & EXT_TO_STDOUT) == EXT_TO_STDOUT)  
+                               extractAr(srcFd, fileno(stdout), argv[optind]); 
+                       if ( (funct & DISPLAY) == DISPLAY)
+                               displayEntry(srcFd, argv[optind], funct);
+               }
+       return (TRUE);
 }
index 6df2588ca43238bcbff4e216bbc42a123d2939e8..787e5da9572ddb0a7da975bc37fb3d62e99185bb 100644 (file)
@@ -44,7 +44,6 @@ extern int dd_main(int argc, char **argv)
 {
        char *inFile = NULL;
        char *outFile = NULL;
-       char *cp;
        int inFd;
        int outFd;
        int inCc = 0;
@@ -135,42 +134,14 @@ extern int dd_main(int argc, char **argv)
 
        lseek(inFd, skipBlocks * blockSize, SEEK_SET);
        lseek(outFd, seekBlocks * blockSize, SEEK_SET);
-       //
-       //TODO: Convert to using fullRead & fullWrite
-       // from utility.c
-       //  -Erik
-       while (outTotal < count * blockSize) {
-               inCc = read(inFd, buf, blockSize);
-               if (inCc < 0) {
-                       perror(inFile);
-                       goto cleanup;
-               } else if (inCc == 0) {
-                       goto cleanup;
-               }
-               intotal += inCc;
-               cp = buf;
-
-               while (intotal > outTotal) {
-                       if (outTotal + inCc > count * blockSize)
-                               inCc = count * blockSize - outTotal;
-                       outCc = write(outFd, cp, inCc);
-                       if (outCc < 0) {
-                               perror(outFile);
-                               goto cleanup;
-                       } else if (outCc == 0) {
-                               goto cleanup;
-                       }
-
-                       inCc -= outCc;
-                       cp += outCc;
-                       outTotal += outCc;
-               }
-       }
 
-       if (inCc < 0)
-               perror(inFile);
+       while ((inCc = read(inFd, buf, sizeof(buf))) > 0) {
+               intotal +=inCc;
+               if ((outCc = fullWrite(outFd, buf, inCc)) < 0)
+                       break;
+               outTotal += outCc;
+        }
 
-  cleanup:
        /* Note that we are not freeing memory or closing
         * files here, to save a few bytes. */
 #ifdef BB_FEATURE_CLEAN_UP
diff --git a/dd.c b/dd.c
index 6df2588ca43238bcbff4e216bbc42a123d2939e8..787e5da9572ddb0a7da975bc37fb3d62e99185bb 100644 (file)
--- a/dd.c
+++ b/dd.c
@@ -44,7 +44,6 @@ extern int dd_main(int argc, char **argv)
 {
        char *inFile = NULL;
        char *outFile = NULL;
-       char *cp;
        int inFd;
        int outFd;
        int inCc = 0;
@@ -135,42 +134,14 @@ extern int dd_main(int argc, char **argv)
 
        lseek(inFd, skipBlocks * blockSize, SEEK_SET);
        lseek(outFd, seekBlocks * blockSize, SEEK_SET);
-       //
-       //TODO: Convert to using fullRead & fullWrite
-       // from utility.c
-       //  -Erik
-       while (outTotal < count * blockSize) {
-               inCc = read(inFd, buf, blockSize);
-               if (inCc < 0) {
-                       perror(inFile);
-                       goto cleanup;
-               } else if (inCc == 0) {
-                       goto cleanup;
-               }
-               intotal += inCc;
-               cp = buf;
-
-               while (intotal > outTotal) {
-                       if (outTotal + inCc > count * blockSize)
-                               inCc = count * blockSize - outTotal;
-                       outCc = write(outFd, cp, inCc);
-                       if (outCc < 0) {
-                               perror(outFile);
-                               goto cleanup;
-                       } else if (outCc == 0) {
-                               goto cleanup;
-                       }
-
-                       inCc -= outCc;
-                       cp += outCc;
-                       outTotal += outCc;
-               }
-       }
 
-       if (inCc < 0)
-               perror(inFile);
+       while ((inCc = read(inFd, buf, sizeof(buf))) > 0) {
+               intotal +=inCc;
+               if ((outCc = fullWrite(outFd, buf, inCc)) < 0)
+                       break;
+               outTotal += outCc;
+        }
 
-  cleanup:
        /* Note that we are not freeing memory or closing
         * files here, to save a few bytes. */
 #ifdef BB_FEATURE_CLEAN_UP
index ab0d94fb82e1d414cb7a28c50d4ee730851c5ee3..f6edb1666b921995df0f2aad1eed53fd39606a08 100644 (file)
@@ -345,6 +345,7 @@ void reset_ino_dev_hashtable(void);
 
 int copyFile(const char *srcName, const char *destName,
                 int setModes, int followLinks, int forceFlag);
+int copySubFile(int srcFd, int dstFd, size_t remaining);
 char *buildName(const char *dirName, const char *fileName);
 int makeString(int argc, const char **argv, char *buf, int bufLen);
 char *getChunk(int size);
diff --git a/usage.c b/usage.c
index 0dad1ba302abafc5687325cc2c7cedac3ad9e5d9..35f63db8655a3f21ed06aa1f7db29644294b39fd 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -2,15 +2,15 @@
 
 #if defined BB_AR
 const char ar_usage[] =
-       "ar [optxvV] archive [filenames] \n"
+       "ar [[-ov] -tpv archive] filenames \n"
 #ifndef BB_FEATURE_TRIVIAL_HELP
        "\nExtract or list files from an ar archive.\n\n"
        "Options:\n"
-       "\to\t\tpreserve original dates\n"
-       "\tp\t\textract to stdout\n"
-       "\tt\t\tlist\n"
-       "\tx\t\textract\n"
-       "\tv\t\tverbosely list files processed\n"
+       "\t-o\t\tpreserve original dates\n"
+       "\t-p\t\textract to stdout\n"
+       "\t-t\t\tlist\n"
+       "\t-x\t\textract\n"
+       "\t-v\t\tverbosely list files processed\n"
 #endif
        ;
 #endif
index de0311d176cebe096ca4a712a3ace430b101927a..2851dd20dbe9575cd2dd2810c74f9f3640b0b9e8 100644 (file)
--- a/utility.c
+++ b/utility.c
@@ -231,7 +231,7 @@ void reset_ino_dev_hashtable(void)
 
 #endif /* BB_CP_MV || BB_DU */
 
-#if defined (BB_CP_MV) || defined (BB_DU) || defined (BB_LN) || defined (BB_AR)
+#if defined (BB_CP_MV) || defined (BB_DU) || defined (BB_LN)
 /*
  * Return TRUE if a fileName is a directory.
  * Nonexistant files return FALSE.
@@ -264,6 +264,29 @@ int isDirectory(const char *fileName, const int followLinks, struct stat *statBu
 }
 #endif
 
+#if defined (BB_AR)
+/*
+ * Copy readSize bytes between two file descriptors
+ */
+int copySubFile(int srcFd, int dstFd, size_t remaining)
+{
+        size_t size;
+        char buffer[BUFSIZ];
+
+        while (remaining > 0) {
+                if (remaining > BUFSIZ)
+                        size = BUFSIZ;
+                else
+                        size = remaining;
+                if (fullWrite(dstFd, buffer, fullRead(srcFd, buffer, size)) < size)
+                        return(FALSE);
+                remaining -= size;
+        }
+        return (TRUE);
+}
+#endif
+
+
 #if defined (BB_CP_MV)
 /*
  * Copy one file to another, while possibly preserving its modes, times, and
@@ -277,9 +300,7 @@ copyFile(const char *srcName, const char *destName,
 {
        int rfd;
        int wfd;
-       int rcc;
        int status;
-       char buf[BUF_SIZE];
        struct stat srcStatBuf;
        struct stat dstStatBuf;
        struct utimbuf times;
@@ -364,8 +385,7 @@ copyFile(const char *srcName, const char *destName,
                        return FALSE;
                }
 
-               wfd =
-                       open(destName, O_WRONLY | O_CREAT | O_TRUNC,
+               wfd = open(destName, O_WRONLY | O_CREAT | O_TRUNC,
                                 srcStatBuf.st_mode);
                if (wfd < 0) {
                        perror(destName);
@@ -373,14 +393,9 @@ copyFile(const char *srcName, const char *destName,
                        return FALSE;
                }
 
-               while ((rcc = read(rfd, buf, sizeof(buf))) > 0) {
-                       if (fullWrite(wfd, buf, rcc) < 0)
-                               goto error_exit;
-               }
-               if (rcc < 0) {
-                       goto error_exit;
-               }
-
+               if (copySubFile(rfd, wfd, srcStatBuf.st_size)==FALSE)
+                       goto error_exit;        
+               
                close(rfd);
                if (close(wfd) < 0) {
                        return FALSE;
@@ -677,7 +692,7 @@ int recursiveAction(const char *fileName,
 
 
 
-#if defined (BB_TAR) || defined (BB_MKDIR) || defined (BB_AR)
+#if defined (BB_TAR) || defined (BB_MKDIR)
 /*
  * Attempt to create the directories along the specified path, except for
  * the final component.  The mode is given for the final directory only,
@@ -1292,7 +1307,7 @@ extern long getNum(const char *cp)
 #endif                                                 /* BB_DD || BB_TAIL */
 
 
-#if defined BB_INIT || defined BB_SYSLOGD || defined BB_AR
+#if defined BB_INIT || defined BB_SYSLOGD 
 /* try to open up the specified device */
 extern int device_open(char *device, int mode)
 {