cpio: (allegedly) fix bug 0001095: "cpio hardlink support and possible memory leak fix"
No binary (build failed)
—
(log yok)
| @@ -8,7 +8,7 @@ | |
| #include "unarchive.h" | |
| typedef struct hardlinks_s { | |
| - | file_header_t *entry; |
| + | char *name; |
| int inode; | |
| struct hardlinks_s *next; | |
| } hardlinks_t; | |
| @@ -17,46 +17,66 @@ char get_header_cpio(archive_handle_t *archive_handle) | |
| { | |
| static hardlinks_t *saved_hardlinks = NULL; | |
| static unsigned short pending_hardlinks = 0; | |
| + | static int inode; |
| file_header_t *file_header = archive_handle->file_header; | |
| char cpio_header[110]; | |
| int namesize; | |
| char dummy[16]; | |
| - | int major, minor, nlink, inode; |
| + | int major, minor, nlink; |
| if (pending_hardlinks) { /* Deal with any pending hardlinks */ | |
| - | hardlinks_t *tmp; |
| - | hardlinks_t *oldtmp; |
| + | hardlinks_t *tmp, *oldtmp; |
| tmp = saved_hardlinks; | |
| oldtmp = NULL; | |
| + | file_header->link_name = file_header->name; |
| + | file_header->size = 0; |
| + | |
| while (tmp) { | |
| - | bb_error_msg_and_die("need to fix this"); |
| - | if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */ |
| - | file_header = tmp->entry; |
| - | if (oldtmp) { |
| - | oldtmp->next = tmp->next; /* Remove item from linked list */ |
| - | } else { |
| - | saved_hardlinks = tmp->next; |
| - | } |
| - | free(tmp); |
| + | if (tmp->inode != inode) { |
| + | tmp = tmp->next; |
| continue; | |
| } | |
| + | |
| + | file_header->name = tmp->name; |
| + | |
| + | if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { |
| + | archive_handle->action_data(archive_handle); |
| + | archive_handle->action_header(archive_handle->file_header); |
| + | } |
| + | |
| + | pending_hardlinks--; |
| + | |
| oldtmp = tmp; | |
| tmp = tmp->next; | |
| + | free(oldtmp->name); |
| + | free(oldtmp); |
| + | if (oldtmp == saved_hardlinks) |
| + | saved_hardlinks = tmp; |
| + | } |
| + | |
| + | file_header->name = file_header->link_name; |
| + | |
| + | if (pending_hardlinks > 1) { |
| + | bb_error_msg("error resolving hardlink: archive made by GNU cpio 2.0-2.2?"); |
| } | |
| - | pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */ |
| + | |
| + | /* No more pending hardlinks, read next file entry */ |
| + | pending_hardlinks = 0; |
| } | |
| /* There can be padding before archive header */ | |
| data_align(archive_handle, 4); | |
| if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) { | |
| - | return(EXIT_FAILURE); |
| + | return EXIT_FAILURE; |
| } | |
| archive_handle->offset += 110; | |
| - | if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) { |
| + | if (strncmp(&cpio_header[0], "07070", 5) != 0 |
| + | || (cpio_header[5] != '1' && cpio_header[5] != '2') |
| + | ) { |
| bb_error_msg_and_die("unsupported cpio format, use newc or crc"); | |
| } | |
| @@ -70,7 +90,8 @@ char get_header_cpio(archive_handle_t *archive_handle) | |
| file_header->size = tmpsize; | |
| } | |
| - | file_header->name = (char *) xzalloc(namesize + 1); |
| + | free(file_header->name); |
| + | file_header->name = xzalloc(namesize + 1); |
| /* Read in filename */ | |
| xread(archive_handle->src_fd, file_header->name, namesize); | |
| archive_handle->offset += namesize; | |
| @@ -79,26 +100,29 @@ char get_header_cpio(archive_handle_t *archive_handle) | |
| data_align(archive_handle, 4); | |
| if (strcmp(file_header->name, "TRAILER!!!") == 0) { | |
| - | printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */ |
| + | /* Always round up */ |
| + | printf("%d blocks\n", (int) (archive_handle->offset % 512 ? |
| + | archive_handle->offset / 512 + 1 : |
| + | archive_handle->offset / 512 |
| + | )); |
| if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */ | |
| hardlinks_t *tmp = saved_hardlinks; | |
| hardlinks_t *oldtmp = NULL; | |
| while (tmp) { | |
| - | bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name); |
| + | bb_error_msg("%s not created: cannot resolve hardlink", tmp->name); |
| oldtmp = tmp; | |
| tmp = tmp->next; | |
| - | free (oldtmp->entry->name); |
| - | free (oldtmp->entry); |
| - | free (oldtmp); |
| + | free(oldtmp->name); |
| + | free(oldtmp); |
| } | |
| saved_hardlinks = NULL; | |
| pending_hardlinks = 0; | |
| } | |
| - | return(EXIT_FAILURE); |
| + | return EXIT_FAILURE; |
| } | |
| if (S_ISLNK(file_header->mode)) { | |
| - | file_header->link_name = (char *) xzalloc(file_header->size + 1); |
| + | file_header->link_name = xzalloc(file_header->size + 1); |
| xread(archive_handle->src_fd, file_header->link_name, file_header->size); | |
| archive_handle->offset += file_header->size; | |
| file_header->size = 0; /* Stop possible seeks in future */ | |
| @@ -110,23 +134,14 @@ char get_header_cpio(archive_handle_t *archive_handle) | |
| hardlinks_t *new = xmalloc(sizeof(hardlinks_t)); | |
| new->next = saved_hardlinks; | |
| new->inode = inode; | |
| - | new->entry = file_header; |
| + | /* name current allocated, freed later */ |
| + | new->name = file_header->name; |
| + | file_header->name = NULL; |
| saved_hardlinks = new; | |
| - | return(EXIT_SUCCESS); // Skip this one |
| - | } else { /* Found the file with data in */ |
| - | hardlinks_t *tmp = saved_hardlinks; |
| - | pending_hardlinks = 1; |
| - | while (tmp) { |
| - | if (tmp->inode == inode) { |
| - | tmp->entry->link_name = xstrdup(file_header->name); |
| - | nlink--; |
| - | } |
| - | tmp = tmp->next; |
| - | } |
| - | if (nlink > 1) { |
| - | bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?"); |
| - | } |
| + | return EXIT_SUCCESS; /* Skip this one */ |
| } | |
| + | /* Found the file with data in */ |
| + | pending_hardlinks = nlink; |
| } | |
| file_header->device = makedev(major, minor); | |
| @@ -12,7 +12,7 @@ archive_handle_t *init_handle(void) | |
| /* Initialize default values */ | |
| archive_handle = xzalloc(sizeof(archive_handle_t)); | |
| - | archive_handle->file_header = xmalloc(sizeof(file_header_t)); |
| + | archive_handle->file_header = xzalloc(sizeof(file_header_t)); |
| archive_handle->action_header = header_skip; | |
| archive_handle->action_data = data_skip; | |
| archive_handle->filter = filter_accept_all; | |