X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ar.c;h=88cdd4f9fe18c41a1f379a319d78fd747439dac1;hb=f3b2b52b589bccae28b1740c155733028f2b8fd5;hp=5803ad1a7096f7a2cd46858fec6f54983434e234;hpb=e2b345a6d8269048e2a310de70234b28745c42c1;p=oweals%2Fbusybox.git diff --git a/ar.c b/ar.c index 5803ad1a7..88cdd4f9f 100644 --- a/ar.c +++ b/ar.c @@ -21,7 +21,7 @@ * 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 9 September 2000 + * Last modified 20 September 2000 */ #include #include @@ -35,7 +35,7 @@ #include #include #include -#include "internal.h" +#include "busybox.h" #define BLOCK_SIZE 60 #define PRESERVE_DATE 1 /* preserve original dates */ @@ -51,6 +51,30 @@ //#define bb_need_io_error //#include "messages.c" +//#define BB_AR_EXPERIMENTAL_UNTAR + +#if defined BB_AR_EXPERIMENTAL_UNTAR +typedef struct rawTarHeader { + char name[100]; /* 0-99 */ + char mode[8]; /* 100-107 */ + char uid[8]; /* 108-115 */ + char gid[8]; /* 116-123 */ + char size[12]; /* 124-135 */ + char mtime[12]; /* 136-147 */ + char chksum[8]; /* 148-155 */ + char typeflag; /* 156-156 */ + char linkname[100]; /* 157-256 */ + char magic[6]; /* 257-262 */ + char version[2]; /* 263-264 */ + char uname[32]; /* 265-296 */ + char gname[32]; /* 297-328 */ + char devmajor[8]; /* 329-336 */ + char devminor[8]; /* 337-344 */ + char prefix[155]; /* 345-499 */ + char padding[12]; /* 500-512 */ +} rawTarHeader_t; +#endif + typedef struct rawArHeader { /* Byte Offset */ char name[16]; /* 0-15 */ char date[12]; /* 16-27 */ @@ -71,94 +95,138 @@ typedef struct headerL { struct headerL *next; } headerL_t; +#if defined BB_AR_EXPERIMENTAL_UNTAR /* - * identify Ar header (magic) and set srcFd to first header entry + * identify Tar header (magic field) and reset srcFd to entry position */ -static int checkArMagic(int srcFd) +static int checkTarMagic(int srcFd) { - char arMagic[8]; - if (fullRead(srcFd, arMagic, 8) != 8) - return (FALSE); - - if (strncmp(arMagic,"!",7) != 0) + off_t headerStart; + char magic[6]; + + headerStart = lseek(srcFd, 0, SEEK_CUR); + lseek(srcFd, (off_t) 257, SEEK_CUR); + full_read(srcFd, magic, 6); + lseek(srcFd, headerStart, SEEK_SET); + if (strncmp(magic, "ustar", 5)!=0) return(FALSE); - return(TRUE); + return(TRUE); +} + + +static int readTarHeader(int srcFd, headerL_t *current) +{ + rawTarHeader_t rawTarHeader; + unsigned char *temp = (unsigned char *) &rawTarHeader; + long sum = 0; + int i; + off_t initialOffset; + + initialOffset = lseek(srcFd, 0, SEEK_CUR); + if (full_read(srcFd, (char *) &rawTarHeader, 512) != 512) { + lseek(srcFd, initialOffset, SEEK_SET); + return(FALSE); + } + for (i = 0; i < 148 ; i++) + sum += temp[i]; + sum += ' ' * 8; + for (i = 156; i < 512 ; i++) + sum += temp[i]; + if (sum!= strtol(rawTarHeader.chksum, NULL, 8)) + return(FALSE); + sscanf(rawTarHeader.name, "%s", current->name); + current->size = strtol(rawTarHeader.size, NULL, 8); + current->uid = strtol(rawTarHeader.uid, NULL, 8); + current->gid = strtol(rawTarHeader.gid, NULL, 8); + current->mode = strtol(rawTarHeader.mode, NULL, 8); + current->mtime = strtol(rawTarHeader.mtime, NULL, 8); + current->offset = lseek(srcFd, 0 , SEEK_CUR); + + current->next = (headerL_t *) xmalloc(sizeof(headerL_t)); + current = current->next; + return(TRUE); } +#endif /* - * read, convert and check the raw ar header - * srcFd should be pointing to the start of header prior to entry - * srcFd will be pointing at the start of data after successful exit - * if returns FALSE srcFd is reset to initial position + * identify Ar header (magic) and reset srcFd to entry position */ -static int readRawArHeader(int srcFd, headerL_t *header) +static int checkArMagic(int srcFd) { - rawArHeader_t rawArHeader; - off_t initialOffset; - size_t nameLength; - - initialOffset = lseek(srcFd, 0, SEEK_CUR); - if (fullRead(srcFd, (char *) &rawArHeader, 60) != 60) { - lseek(srcFd, initialOffset, SEEK_SET); - return(FALSE); - } - if ((rawArHeader.fmag[0]!='`') || (rawArHeader.fmag[1]!='\n')) { - lseek(srcFd, initialOffset, SEEK_SET); - return(FALSE); - } + off_t headerStart; + char arMagic[8]; - strncpy(header->name, rawArHeader.name, 16); - nameLength=strcspn(header->name, " \\"); - header->name[nameLength]='\0'; - parse_mode(rawArHeader.mode, &header->mode); - header->mtime = atoi(rawArHeader.date); - header->uid = atoi(rawArHeader.uid); - header->gid = atoi(rawArHeader.gid); - header->size = (size_t) atoi(rawArHeader.size); - header->offset = initialOffset + (off_t) 60; - return(TRUE); + headerStart = lseek(srcFd, 0, SEEK_CUR); + if (full_read(srcFd, arMagic, 8) != 8) { + error_msg("fatal error\n"); + return (FALSE); + } + lseek(srcFd, headerStart, SEEK_SET); + + if (strncmp(arMagic,"!",7) != 0) + return(FALSE); + return(TRUE); } /* * get, check and correct the converted header */ -static int readArEntry(int srcFd, headerL_t *newEntry) +static int readArEntry(int srcFd, headerL_t *entry) { size_t nameLength; + rawArHeader_t rawArHeader; + off_t initialOffset; - if(readRawArHeader(srcFd, newEntry)==FALSE) - return(FALSE); - - nameLength = strcspn(newEntry->name, "/"); + initialOffset = lseek(srcFd, 0, SEEK_CUR); + if (full_read(srcFd, (char *) &rawArHeader, 60) != 60) { + lseek(srcFd, initialOffset, SEEK_SET); + return(FALSE); + } + if ((rawArHeader.fmag[0]!='`') || (rawArHeader.fmag[1]!='\n')) { + lseek(srcFd, initialOffset, SEEK_SET); + return(FALSE); + } + + strncpy(entry->name, rawArHeader.name, 16); + nameLength=strcspn(entry->name, " \\"); + entry->name[nameLength]='\0'; + parse_mode(rawArHeader.mode, &entry->mode); + entry->mtime = atoi(rawArHeader.date); + entry->uid = atoi(rawArHeader.uid); + entry->gid = atoi(rawArHeader.gid); + entry->size = (size_t) atoi(rawArHeader.size); + entry->offset = initialOffset + (off_t) 60; + + nameLength = strcspn(entry->name, "/"); /* handle GNU style short filenames, strip trailing '/' */ if (nameLength > 0) - newEntry->name[nameLength]='\0'; + entry->name[nameLength]='\0'; /* handle GNU style long filenames */ if (nameLength == 0) { /* escape from recursive call */ - if (newEntry->name[1]=='0') + if (entry->name[1]=='0') return(TRUE); /* the data section contains the real filename */ - if (newEntry->name[1]=='/') { + if (entry->name[1]=='/') { char tempName[MAX_NAME_LENGTH]; - if (newEntry->size > MAX_NAME_LENGTH) - newEntry->size = MAX_NAME_LENGTH; - fullRead(srcFd, tempName, newEntry->size); - tempName[newEntry->size-3]='\0'; + if (entry->size > MAX_NAME_LENGTH) + entry->size = MAX_NAME_LENGTH; + full_read(srcFd, tempName, entry->size); + tempName[entry->size-3]='\0'; /* read the second header for this entry */ /* be carefull, this is recursive */ - if (readArEntry(srcFd, newEntry)==FALSE) + if (readArEntry(srcFd, entry)==FALSE) return(FALSE); - if ((newEntry->name[0]='/') && (newEntry->name[1]='0')) - strcpy(newEntry->name, tempName); + if ((entry->name[0]='/') && (entry->name[1]='0')) + strcpy(entry->name, tempName); else { - errorMsg("Invalid long filename\n"); + error_msg("Invalid long filename\n"); return(FALSE); } } @@ -171,24 +239,58 @@ static int readArEntry(int srcFd, headerL_t *newEntry) */ static headerL_t *getHeaders(int srcFd, headerL_t *head, int funct) { +#if defined BB_AR_EXPERIMENTAL_UNTAR + int tar=FALSE; +#endif + int ar=FALSE; headerL_t *list; - list = (headerL_t *) malloc(sizeof(headerL_t)); + off_t initialOffset; + + list = (headerL_t *) xmalloc(sizeof(headerL_t)); + initialOffset=lseek(srcFd, 0, SEEK_CUR); + if (checkArMagic(srcFd)==TRUE) + ar=TRUE; + +#if defined BB_AR_EXPERIMENTAL_UNTAR + if (checkTarMagic(srcFd)==TRUE) + tar=TRUE; + + if (tar==TRUE) { + while(readTarHeader(srcFd, list)==TRUE) { + off_t tarOffset; + list->next = (headerL_t *) xmalloc(sizeof(headerL_t)); + *list->next = *head; + *head = *list; - if (checkArMagic(srcFd)==TRUE) { - printf("found ar header "); - while(readArEntry(srcFd, list) == TRUE) { - list->next = (headerL_t *) malloc(sizeof(headerL_t)); + /* recursive check for sub-archives */ + if ((funct & RECURSIVE) == RECURSIVE) + head = getHeaders(srcFd, head, funct); + tarOffset = (off_t) head->size/512; + if ( head->size % 512 > 0) + tarOffset++; + tarOffset=tarOffset*512; + lseek(srcFd, head->offset + tarOffset, SEEK_SET); + } + } +#endif + + if (ar==TRUE) { + lseek(srcFd, 8, SEEK_CUR); + while(1) { + if (readArEntry(srcFd, list) == FALSE) { + lseek(srcFd, ++initialOffset, SEEK_CUR); + if (readArEntry(srcFd, list) == FALSE) + return(head); + } + list->next = (headerL_t *) xmalloc(sizeof(headerL_t)); *list->next = *head; *head = *list; - /* recursive check for sub-archives */ - if ((funct & RECURSIVE) == RECURSIVE) + if (funct & RECURSIVE) head = getHeaders(srcFd, head, funct); lseek(srcFd, head->offset + head->size, SEEK_SET); } } - else - printf("not an ar header\n"); return(head); } @@ -205,27 +307,6 @@ static headerL_t *findEntry(headerL_t *head, const char *filename) return(NULL); } -/* - * populate linked list with all ar file entries and offset - */ -static int displayEntry(headerL_t *head, int funct) -{ - if ((funct & VERBOSE) == VERBOSE) { - printf("%s %d/%d %8d %s ", modeString(head->mode), head->uid, head->gid, head->size, timeString(head->mtime)); - } - printf("%s\n", head->name); - head = head->next; - return(TRUE); -} - -static int extractAr(int srcFd, int dstFd, headerL_t *file) -{ - 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, opt=0; @@ -235,72 +316,76 @@ extern int ar_main(int argc, char **argv) while ((opt = getopt(argc, argv, "ovtpxR")) != -1) { switch (opt) { case 'o': - funct = funct | PRESERVE_DATE; + funct |= PRESERVE_DATE; break; case 'v': - funct = funct | VERBOSE; + funct |= VERBOSE; break; case 't': - funct = funct | DISPLAY; + funct |= DISPLAY; break; case 'x': - funct = funct | EXT_TO_FILE; + funct |= EXT_TO_FILE; break; case 'p': - funct = funct | EXT_TO_STDOUT; + funct |= EXT_TO_STDOUT; break; case 'R': - funct = funct | RECURSIVE; + funct |= RECURSIVE; break; default: usage(ar_usage); } } - /* check the src filename was specified */ - if (optind == argc) { - usage(ar_usage); - return(FALSE); - } + /* check the src filename was specified */ + if (optind == argc) + usage(ar_usage); - if ( (srcFd = open(argv[optind], O_RDONLY)) < 0) { - errorMsg("Cannot read %s\n", optarg); - return (FALSE); - } + if ( (srcFd = open(argv[optind], O_RDONLY)) < 0) + error_msg_and_die("Cannot read %s\n", argv[optind]); + optind++; - entry = (headerL_t *) malloc(sizeof(headerL_t)); - header = (headerL_t *) malloc(sizeof(headerL_t)); - extractList = (headerL_t *) malloc(sizeof(headerL_t)); + entry = (headerL_t *) xmalloc(sizeof(headerL_t)); + header = (headerL_t *) xmalloc(sizeof(headerL_t)); + extractList = (headerL_t *) xmalloc(sizeof(headerL_t)); header = getHeaders(srcFd, header, funct); - /* find files to extract or display */ if (optindnext = (headerL_t *) malloc(sizeof(headerL_t)); + entry->next = (headerL_t *) xmalloc(sizeof(headerL_t)); *entry->next = *extractList; *extractList = *entry; } optind++; } } - else - /* extract everything */ + else extractList = header; - while(extractList->next != NULL) { - if ( (funct & EXT_TO_FILE) == EXT_TO_FILE) { + while(extractList->next != NULL) { + if (funct & EXT_TO_FILE) { + if (is_directory(extractList->name, TRUE, NULL)==FALSE) + create_path(extractList->name, 0666); dstFd = open(extractList->name, O_WRONLY | O_CREAT, extractList->mode); - - extractAr(srcFd, dstFd, extractList); + lseek(srcFd, extractList->offset, SEEK_SET); + copy_file_chunk(srcFd, dstFd, (size_t) extractList->size); + } + if (funct & EXT_TO_STDOUT) { + lseek(srcFd, extractList->offset, SEEK_SET); + copy_file_chunk(srcFd, fileno(stdout), (size_t) extractList->size); + } + if ( (funct & DISPLAY) || (funct & VERBOSE)) { + if (funct & VERBOSE) + printf("%s %d/%d %8d %s ", mode_string(extractList->mode), + extractList->uid, extractList->gid, + extractList->size, time_string(extractList->mtime)); + printf("%s\n", extractList->name); } - if ( (funct & EXT_TO_STDOUT) == EXT_TO_STDOUT) - extractAr(srcFd, fileno(stdout), extractList); - if ( (funct & DISPLAY) == DISPLAY) - displayEntry(extractList, funct); extractList=extractList->next; } - return (TRUE); + return EXIT_SUCCESS; }