| @@ -21,26 +21,28 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| { |
| file_header_t *file_header = archive_handle->file_header; |
| char cpio_header[110]; |
| - | char dummy[16]; |
| int namesize; |
| int major, minor, nlink, mode, inode; |
| unsigned size, uid, gid, mtime; |
| |
| - | #define saved_hardlinks (*(hardlinks_t **)(&archive_handle->ah_priv[0])) |
| - | #define saved_hardlinks_created (*(hardlinks_t **)(&archive_handle->ah_priv[1])) |
| + | #define hardlinks_to_create (*(hardlinks_t **)(&archive_handle->ah_priv[0])) |
| + | #define created_hardlinks (*(hardlinks_t **)(&archive_handle->ah_priv[1])) |
| // if (!archive_handle->ah_priv_inited) { |
| // archive_handle->ah_priv_inited = 1; |
| - | // saved_hardlinks = NULL; |
| - | // saved_hardlinks_created = NULL; |
| + | // hardlinks_to_create = NULL; |
| + | // created_hardlinks = NULL; |
| // } |
| |
| /* There can be padding before archive header */ |
| data_align(archive_handle, 4); |
| |
| - | //TODO: this function is used only here, make it static? |
| - | if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) { |
| + | size = full_read(archive_handle->src_fd, cpio_header, 110); |
| + | if (size == 0) { |
| goto create_hardlinks; |
| } |
| + | if (size != 110) { |
| + | bb_error_msg_and_die("short read"); |
| + | } |
| archive_handle->offset += 110; |
| |
| if (strncmp(&cpio_header[0], "07070", 5) != 0 |
| @@ -49,20 +51,21 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| bb_error_msg_and_die("unsupported cpio format, use newc or crc"); |
| } |
| |
| - | sscanf(cpio_header + 6, |
| + | if (sscanf(cpio_header + 6, |
| "%8x" "%8x" "%8x" "%8x" |
| - | "%8x" "%8x" "%8x" /*maj,min:*/ "%16c" |
| - | /*rmaj,rmin:*/"%8x" "%8x" "%8x" /*chksum:*/ "%8c", |
| + | "%8x" "%8x" "%8x" /*maj,min:*/ "%*16c" |
| + | /*rmaj,rmin:*/"%8x" "%8x" "%8x" /*chksum: "%*8c"*/, |
| &inode, &mode, &uid, &gid, |
| - | &nlink, &mtime, &size, dummy, |
| - | &major, &minor, &namesize, dummy); |
| + | &nlink, &mtime, &size, |
| + | &major, &minor, &namesize) != 10) |
| + | bb_error_msg_and_die("damaged cpio file"); |
| file_header->mode = mode; |
| file_header->uid = uid; |
| file_header->gid = gid; |
| file_header->mtime = mtime; |
| file_header->size = size; |
| |
| - | namesize &= 0x1fff; /* paranoia: names can't be that long */ |
| + | namesize &= 0x1fff; /* paranoia: limit names to 8k chars */ |
| file_header->name = xzalloc(namesize + 1); |
| /* Read in filename */ |
| xread(archive_handle->src_fd, file_header->name, namesize); |
| @@ -77,17 +80,17 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| goto create_hardlinks; |
| } |
| |
| + | file_header->link_target = NULL; |
| if (S_ISLNK(file_header->mode)) { |
| + | file_header->size &= 0x1fff; /* paranoia: limit names to 8k chars */ |
| file_header->link_target = xzalloc(file_header->size + 1); |
| xread(archive_handle->src_fd, file_header->link_target, file_header->size); |
| archive_handle->offset += file_header->size; |
| file_header->size = 0; /* Stop possible seeks in future */ |
| - | } else { |
| - | file_header->link_target = NULL; |
| } |
| |
| // TODO: data_extract_all can't deal with hardlinks to non-files... |
| - | // (should be !S_ISDIR instead of S_ISREG here) |
| + | // when fixed, change S_ISREG to !S_ISDIR here |
| |
| if (nlink > 1 && S_ISREG(file_header->mode)) { |
| hardlinks_t *new = xmalloc(sizeof(*new) + namesize); |
| @@ -99,13 +102,13 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| strcpy(new->name, file_header->name); |
| /* Put file on a linked list for later */ |
| if (size == 0) { |
| - | new->next = saved_hardlinks; |
| - | saved_hardlinks = new; |
| + | new->next = hardlinks_to_create; |
| + | hardlinks_to_create = new; |
| return EXIT_SUCCESS; /* Skip this one */ |
| /* TODO: this breaks cpio -t (it does not show hardlinks) */ |
| } |
| - | new->next = saved_hardlinks_created; |
| - | saved_hardlinks_created = new; |
| + | new->next = created_hardlinks; |
| + | created_hardlinks = new; |
| } |
| file_header->device = makedev(major, minor); |
| |
| @@ -129,18 +132,23 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| free(file_header->link_target); |
| free(file_header->name); |
| |
| - | while (saved_hardlinks) { |
| + | while (hardlinks_to_create) { |
| hardlinks_t *cur; |
| - | hardlinks_t *make_me = saved_hardlinks; |
| - | saved_hardlinks = make_me->next; |
| + | hardlinks_t *make_me = hardlinks_to_create; |
| + | |
| + | hardlinks_to_create = make_me->next; |
| |
| memset(file_header, 0, sizeof(*file_header)); |
| + | file_header->mtime = make_me->mtime; |
| file_header->name = make_me->name; |
| file_header->mode = make_me->mode; |
| + | file_header->uid = make_me->uid; |
| + | file_header->gid = make_me->gid; |
| /*file_header->size = 0;*/ |
| + | /*file_header->link_target = NULL;*/ |
| |
| /* Try to find a file we are hardlinked to */ |
| - | cur = saved_hardlinks_created; |
| + | cur = created_hardlinks; |
| while (cur) { |
| /* TODO: must match maj/min too! */ |
| if (cur->inode == make_me->inode) { |
| @@ -155,20 +163,17 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) |
| } |
| /* Oops... no file with such inode was created... do it now |
| * (happens when hardlinked files are empty (zero length)) */ |
| - | file_header->mtime = make_me->mtime; |
| - | file_header->uid = make_me->uid ; |
| - | file_header->gid = make_me->gid ; |
| if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) |
| archive_handle->action_data(archive_handle); |
| /* Move to the list of created hardlinked files */ |
| - | make_me->next = saved_hardlinks_created; |
| - | saved_hardlinks_created = make_me; |
| + | make_me->next = created_hardlinks; |
| + | created_hardlinks = make_me; |
| next_link: ; |
| } |
| |
| - | while (saved_hardlinks_created) { |
| - | hardlinks_t *p = saved_hardlinks_created; |
| - | saved_hardlinks_created = p->next; |
| + | while (created_hardlinks) { |
| + | hardlinks_t *p = created_hardlinks; |
| + | created_hardlinks = p->next; |
| free(p); |
| } |
| |