aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-21 00:55:46 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-21 00:55:46 +0000
commit3eb91c2e3594f379f357bfcc85105b6b76a11781 (patch)
tree1c53c50828d9d75945eaeaad00be45999c7a17e0
parent5d148e2646874a6f460402f2dd70ea2fb6be08dd (diff)
downloadbusybox-w32-3eb91c2e3594f379f357bfcc85105b6b76a11781.tar.gz
busybox-w32-3eb91c2e3594f379f357bfcc85105b6b76a11781.tar.bz2
busybox-w32-3eb91c2e3594f379f357bfcc85105b6b76a11781.zip
cpio: (allegedly) fix bug 0001095:
"cpio hardlink support and possible memory leak fix"
-rw-r--r--archival/libunarchive/get_header_cpio.c93
-rw-r--r--archival/libunarchive/init_handle.c2
2 files changed, 55 insertions, 40 deletions
diff --git a/archival/libunarchive/get_header_cpio.c b/archival/libunarchive/get_header_cpio.c
index dd48cb09b..f0b07b56c 100644
--- a/archival/libunarchive/get_header_cpio.c
+++ b/archival/libunarchive/get_header_cpio.c
@@ -8,7 +8,7 @@
8#include "unarchive.h" 8#include "unarchive.h"
9 9
10typedef struct hardlinks_s { 10typedef struct hardlinks_s {
11 file_header_t *entry; 11 char *name;
12 int inode; 12 int inode;
13 struct hardlinks_s *next; 13 struct hardlinks_s *next;
14} hardlinks_t; 14} hardlinks_t;
@@ -17,46 +17,66 @@ char get_header_cpio(archive_handle_t *archive_handle)
17{ 17{
18 static hardlinks_t *saved_hardlinks = NULL; 18 static hardlinks_t *saved_hardlinks = NULL;
19 static unsigned short pending_hardlinks = 0; 19 static unsigned short pending_hardlinks = 0;
20 static int inode;
20 file_header_t *file_header = archive_handle->file_header; 21 file_header_t *file_header = archive_handle->file_header;
21 char cpio_header[110]; 22 char cpio_header[110];
22 int namesize; 23 int namesize;
23 char dummy[16]; 24 char dummy[16];
24 int major, minor, nlink, inode; 25 int major, minor, nlink;
25 26
26 if (pending_hardlinks) { /* Deal with any pending hardlinks */ 27 if (pending_hardlinks) { /* Deal with any pending hardlinks */
27 hardlinks_t *tmp; 28 hardlinks_t *tmp, *oldtmp;
28 hardlinks_t *oldtmp;
29 29
30 tmp = saved_hardlinks; 30 tmp = saved_hardlinks;
31 oldtmp = NULL; 31 oldtmp = NULL;
32 32
33 file_header->link_name = file_header->name;
34 file_header->size = 0;
35
33 while (tmp) { 36 while (tmp) {
34 bb_error_msg_and_die("need to fix this"); 37 if (tmp->inode != inode) {
35 if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */ 38 tmp = tmp->next;
36 file_header = tmp->entry;
37 if (oldtmp) {
38 oldtmp->next = tmp->next; /* Remove item from linked list */
39 } else {
40 saved_hardlinks = tmp->next;
41 }
42 free(tmp);
43 continue; 39 continue;
44 } 40 }
41
42 file_header->name = tmp->name;
43
44 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
45 archive_handle->action_data(archive_handle);
46 archive_handle->action_header(archive_handle->file_header);
47 }
48
49 pending_hardlinks--;
50
45 oldtmp = tmp; 51 oldtmp = tmp;
46 tmp = tmp->next; 52 tmp = tmp->next;
53 free(oldtmp->name);
54 free(oldtmp);
55 if (oldtmp == saved_hardlinks)
56 saved_hardlinks = tmp;
57 }
58
59 file_header->name = file_header->link_name;
60
61 if (pending_hardlinks > 1) {
62 bb_error_msg("error resolving hardlink: archive made by GNU cpio 2.0-2.2?");
47 } 63 }
48 pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */ 64
65 /* No more pending hardlinks, read next file entry */
66 pending_hardlinks = 0;
49 } 67 }
50 68
51 /* There can be padding before archive header */ 69 /* There can be padding before archive header */
52 data_align(archive_handle, 4); 70 data_align(archive_handle, 4);
53 71
54 if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) { 72 if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {
55 return(EXIT_FAILURE); 73 return EXIT_FAILURE;
56 } 74 }
57 archive_handle->offset += 110; 75 archive_handle->offset += 110;
58 76
59 if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) { 77 if (strncmp(&cpio_header[0], "07070", 5) != 0
78 || (cpio_header[5] != '1' && cpio_header[5] != '2')
79 ) {
60 bb_error_msg_and_die("unsupported cpio format, use newc or crc"); 80 bb_error_msg_and_die("unsupported cpio format, use newc or crc");
61 } 81 }
62 82
@@ -70,7 +90,8 @@ char get_header_cpio(archive_handle_t *archive_handle)
70 file_header->size = tmpsize; 90 file_header->size = tmpsize;
71 } 91 }
72 92
73 file_header->name = (char *) xzalloc(namesize + 1); 93 free(file_header->name);
94 file_header->name = xzalloc(namesize + 1);
74 /* Read in filename */ 95 /* Read in filename */
75 xread(archive_handle->src_fd, file_header->name, namesize); 96 xread(archive_handle->src_fd, file_header->name, namesize);
76 archive_handle->offset += namesize; 97 archive_handle->offset += namesize;
@@ -79,26 +100,29 @@ char get_header_cpio(archive_handle_t *archive_handle)
79 data_align(archive_handle, 4); 100 data_align(archive_handle, 4);
80 101
81 if (strcmp(file_header->name, "TRAILER!!!") == 0) { 102 if (strcmp(file_header->name, "TRAILER!!!") == 0) {
82 printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */ 103 /* Always round up */
104 printf("%d blocks\n", (int) (archive_handle->offset % 512 ?
105 archive_handle->offset / 512 + 1 :
106 archive_handle->offset / 512
107 ));
83 if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */ 108 if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
84 hardlinks_t *tmp = saved_hardlinks; 109 hardlinks_t *tmp = saved_hardlinks;
85 hardlinks_t *oldtmp = NULL; 110 hardlinks_t *oldtmp = NULL;
86 while (tmp) { 111 while (tmp) {
87 bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name); 112 bb_error_msg("%s not created: cannot resolve hardlink", tmp->name);
88 oldtmp = tmp; 113 oldtmp = tmp;
89 tmp = tmp->next; 114 tmp = tmp->next;
90 free (oldtmp->entry->name); 115 free(oldtmp->name);
91 free (oldtmp->entry); 116 free(oldtmp);
92 free (oldtmp);
93 } 117 }
94 saved_hardlinks = NULL; 118 saved_hardlinks = NULL;
95 pending_hardlinks = 0; 119 pending_hardlinks = 0;
96 } 120 }
97 return(EXIT_FAILURE); 121 return EXIT_FAILURE;
98 } 122 }
99 123
100 if (S_ISLNK(file_header->mode)) { 124 if (S_ISLNK(file_header->mode)) {
101 file_header->link_name = (char *) xzalloc(file_header->size + 1); 125 file_header->link_name = xzalloc(file_header->size + 1);
102 xread(archive_handle->src_fd, file_header->link_name, file_header->size); 126 xread(archive_handle->src_fd, file_header->link_name, file_header->size);
103 archive_handle->offset += file_header->size; 127 archive_handle->offset += file_header->size;
104 file_header->size = 0; /* Stop possible seeks in future */ 128 file_header->size = 0; /* Stop possible seeks in future */
@@ -110,23 +134,14 @@ char get_header_cpio(archive_handle_t *archive_handle)
110 hardlinks_t *new = xmalloc(sizeof(hardlinks_t)); 134 hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
111 new->next = saved_hardlinks; 135 new->next = saved_hardlinks;
112 new->inode = inode; 136 new->inode = inode;
113 new->entry = file_header; 137 /* name current allocated, freed later */
138 new->name = file_header->name;
139 file_header->name = NULL;
114 saved_hardlinks = new; 140 saved_hardlinks = new;
115 return(EXIT_SUCCESS); // Skip this one 141 return EXIT_SUCCESS; /* Skip this one */
116 } else { /* Found the file with data in */
117 hardlinks_t *tmp = saved_hardlinks;
118 pending_hardlinks = 1;
119 while (tmp) {
120 if (tmp->inode == inode) {
121 tmp->entry->link_name = xstrdup(file_header->name);
122 nlink--;
123 }
124 tmp = tmp->next;
125 }
126 if (nlink > 1) {
127 bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
128 }
129 } 142 }
143 /* Found the file with data in */
144 pending_hardlinks = nlink;
130 } 145 }
131 file_header->device = makedev(major, minor); 146 file_header->device = makedev(major, minor);
132 147
diff --git a/archival/libunarchive/init_handle.c b/archival/libunarchive/init_handle.c
index 06e8d1fab..309d329ea 100644
--- a/archival/libunarchive/init_handle.c
+++ b/archival/libunarchive/init_handle.c
@@ -12,7 +12,7 @@ archive_handle_t *init_handle(void)
12 12
13 /* Initialize default values */ 13 /* Initialize default values */
14 archive_handle = xzalloc(sizeof(archive_handle_t)); 14 archive_handle = xzalloc(sizeof(archive_handle_t));
15 archive_handle->file_header = xmalloc(sizeof(file_header_t)); 15 archive_handle->file_header = xzalloc(sizeof(file_header_t));
16 archive_handle->action_header = header_skip; 16 archive_handle->action_header = header_skip;
17 archive_handle->action_data = data_skip; 17 archive_handle->action_data = data_skip;
18 archive_handle->filter = filter_accept_all; 18 archive_handle->filter = filter_accept_all;