diff options
author | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-06-22 09:22:06 +0000 |
---|---|---|
committer | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-06-22 09:22:06 +0000 |
commit | e1886edd0ca3ea6f622c70d687a27f2b7eef52a7 (patch) | |
tree | 5a1924092009892cc80f0b0947ec1bae17ca3b1c /libbb | |
parent | db3c0c3742717789043407a05c90c8c8eef0dd5e (diff) | |
download | busybox-w32-e1886edd0ca3ea6f622c70d687a27f2b7eef52a7.tar.gz busybox-w32-e1886edd0ca3ea6f622c70d687a27f2b7eef52a7.tar.bz2 busybox-w32-e1886edd0ca3ea6f622c70d687a27f2b7eef52a7.zip |
cpio applet, and changes to associated code
git-svn-id: svn://busybox.net/trunk/busybox@2887 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/unarchive.c | 85 |
1 files changed, 70 insertions, 15 deletions
diff --git a/libbb/unarchive.c b/libbb/unarchive.c index 635dcae35..20609ded7 100644 --- a/libbb/unarchive.c +++ b/libbb/unarchive.c | |||
@@ -119,10 +119,11 @@ char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *f | |||
119 | } | 119 | } |
120 | } | 120 | } |
121 | else if (function & extract_all_to_fs) { | 121 | else if (function & extract_all_to_fs) { |
122 | #if 0 | ||
123 | struct stat oldfile; | 122 | struct stat oldfile; |
124 | if ( (S_ISLNK(file_entry->mode) ? lstat (full_name, &oldfile) : stat (full_name, &oldfile)) == 0) { /* The file already exists */ | 123 | int stat_res; |
125 | if (function & extract_unconditional || oldfile.st_mtime < file_entry->mtime) { | 124 | stat_res = lstat (full_name, &oldfile); |
125 | if (stat_res == 0) { /* The file already exists */ | ||
126 | if ((function & extract_unconditional) || (oldfile.st_mtime < file_entry->mtime)) { | ||
126 | if (!S_ISDIR(oldfile.st_mode)) { | 127 | if (!S_ISDIR(oldfile.st_mode)) { |
127 | unlink(full_name); /* Directories might not be empty etc */ | 128 | unlink(full_name); /* Directories might not be empty etc */ |
128 | } | 129 | } |
@@ -134,7 +135,6 @@ char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *f | |||
134 | return (NULL); | 135 | return (NULL); |
135 | } | 136 | } |
136 | } | 137 | } |
137 | #endif | ||
138 | switch(file_entry->mode & S_IFMT) { | 138 | switch(file_entry->mode & S_IFMT) { |
139 | case S_IFREG: | 139 | case S_IFREG: |
140 | if (file_entry->link_name) { /* Found a cpio hard link */ | 140 | if (file_entry->link_name) { /* Found a cpio hard link */ |
@@ -153,10 +153,11 @@ char *extract_archive(FILE *src_stream, FILE *out_stream, const file_header_t *f | |||
153 | } | 153 | } |
154 | break; | 154 | break; |
155 | case S_IFDIR: | 155 | case S_IFDIR: |
156 | /* Use make_directory instead of mkdir in case prefix path hasn't been created */ | 156 | if ((function & extract_create_dirs) && (stat_res != 0)) { |
157 | if (function & extract_create_dirs) { | 157 | /* Make sure the prefix component of full_name was create |
158 | if (make_directory(full_name, file_entry->mode, FILEUTILS_RECUR) < 0) { | 158 | * in applet before getting here*/ |
159 | return NULL; | 159 | if (mkdir(full_name, file_entry->mode) < 0) { |
160 | perror_msg("extract_archive: "); | ||
160 | } | 161 | } |
161 | } | 162 | } |
162 | break; | 163 | break; |
@@ -335,14 +336,38 @@ void *get_header_ar(FILE *src_stream) | |||
335 | #endif | 336 | #endif |
336 | 337 | ||
337 | #ifdef L_get_header_cpio | 338 | #ifdef L_get_header_cpio |
339 | struct hardlinks { | ||
340 | file_header_t *entry; | ||
341 | int inode; | ||
342 | struct hardlinks *next; | ||
343 | }; | ||
344 | |||
338 | void *get_header_cpio(FILE *src_stream) | 345 | void *get_header_cpio(FILE *src_stream) |
339 | { | 346 | { |
340 | file_header_t *cpio_entry = NULL; | 347 | file_header_t *cpio_entry = NULL; |
341 | char cpio_header[110]; | 348 | char cpio_header[110]; |
342 | char dummy[14]; | ||
343 | int namesize; | 349 | int namesize; |
344 | int major, minor, nlink; | 350 | char dummy[16]; |
345 | 351 | int major, minor, nlink, inode; | |
352 | static struct hardlinks *saved_hardlinks = NULL; | ||
353 | static int pending_hardlinks = 0; | ||
354 | |||
355 | if (pending_hardlinks) { /* Deal with any pending hardlinks */ | ||
356 | struct hardlinks *tmp = saved_hardlinks, *oldtmp = NULL; | ||
357 | while (tmp) { | ||
358 | if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */ | ||
359 | cpio_entry = tmp->entry; | ||
360 | if (oldtmp) oldtmp->next = tmp->next; /* Remove item from linked list */ | ||
361 | else saved_hardlinks = tmp->next; | ||
362 | free(tmp); | ||
363 | return (cpio_entry); | ||
364 | } | ||
365 | oldtmp = tmp; | ||
366 | tmp = tmp->next; | ||
367 | } | ||
368 | pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */ | ||
369 | } | ||
370 | |||
346 | /* There can be padding before archive header */ | 371 | /* There can be padding before archive header */ |
347 | seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); | 372 | seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); |
348 | if (fread(cpio_header, 1, 110, src_stream) == 110) { | 373 | if (fread(cpio_header, 1, 110, src_stream) == 110) { |
@@ -356,8 +381,8 @@ void *get_header_cpio(FILE *src_stream) | |||
356 | /* Doesnt do the crc check yet */ | 381 | /* Doesnt do the crc check yet */ |
357 | case '1': /* "newc" header format */ | 382 | case '1': /* "newc" header format */ |
358 | cpio_entry = (file_header_t *) xcalloc(1, sizeof(file_header_t)); | 383 | cpio_entry = (file_header_t *) xcalloc(1, sizeof(file_header_t)); |
359 | sscanf(cpio_header, "%14c%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c", | 384 | sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c", |
360 | dummy, &cpio_entry->mode, &cpio_entry->uid, &cpio_entry->gid, | 385 | dummy, &inode, &cpio_entry->mode, &cpio_entry->uid, &cpio_entry->gid, |
361 | &nlink, &cpio_entry->mtime, &cpio_entry->size, | 386 | &nlink, &cpio_entry->mtime, &cpio_entry->size, |
362 | dummy, &major, &minor, &namesize, dummy); | 387 | dummy, &major, &minor, &namesize, dummy); |
363 | 388 | ||
@@ -368,6 +393,19 @@ void *get_header_cpio(FILE *src_stream) | |||
368 | seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); | 393 | seek_sub_file(src_stream, (4 - (archive_offset % 4)) % 4); |
369 | if (strcmp(cpio_entry->name, "TRAILER!!!") == 0) { | 394 | if (strcmp(cpio_entry->name, "TRAILER!!!") == 0) { |
370 | printf("%d blocks\n", (int) (archive_offset % 512 ? (archive_offset / 512) + 1 : archive_offset / 512)); /* Always round up */ | 395 | printf("%d blocks\n", (int) (archive_offset % 512 ? (archive_offset / 512) + 1 : archive_offset / 512)); /* Always round up */ |
396 | if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */ | ||
397 | struct hardlinks *tmp = saved_hardlinks, *oldtmp = NULL; | ||
398 | while (tmp) { | ||
399 | error_msg("%s not created: cannot resolve hardlink", tmp->entry->name); | ||
400 | oldtmp = tmp; | ||
401 | tmp = tmp->next; | ||
402 | free (oldtmp->entry->name); | ||
403 | free (oldtmp->entry); | ||
404 | free (oldtmp); | ||
405 | } | ||
406 | saved_hardlinks = NULL; | ||
407 | pending_hardlinks = 0; | ||
408 | } | ||
371 | return(NULL); | 409 | return(NULL); |
372 | } | 410 | } |
373 | 411 | ||
@@ -376,9 +414,26 @@ void *get_header_cpio(FILE *src_stream) | |||
376 | fread(cpio_entry->link_name, 1, cpio_entry->size, src_stream); | 414 | fread(cpio_entry->link_name, 1, cpio_entry->size, src_stream); |
377 | archive_offset += cpio_entry->size; | 415 | archive_offset += cpio_entry->size; |
378 | } | 416 | } |
379 | if (nlink > 1 && !S_ISDIR(cpio_entry->mode) && cpio_entry->size == 0) { | 417 | if (nlink > 1 && !S_ISDIR(cpio_entry->mode)) { |
380 | error_msg("%s not extracted: Cannot handle hard links yet", cpio_entry->name); | 418 | if (cpio_entry->size == 0) { /* Put file on a linked list for later */ |
419 | struct hardlinks *new = xmalloc(sizeof(struct hardlinks)); | ||
420 | new->next = saved_hardlinks; | ||
421 | new->inode = inode; | ||
422 | new->entry = cpio_entry; | ||
423 | saved_hardlinks = new; | ||
381 | return(get_header_cpio(src_stream)); /* Recurse to next file */ | 424 | return(get_header_cpio(src_stream)); /* Recurse to next file */ |
425 | } else { /* Found the file with data in */ | ||
426 | struct hardlinks *tmp = saved_hardlinks; | ||
427 | pending_hardlinks = 1; | ||
428 | while (tmp) { | ||
429 | if (tmp->inode == inode) { | ||
430 | tmp->entry->link_name = xstrdup(cpio_entry->name); | ||
431 | nlink--; | ||
432 | } | ||
433 | tmp = tmp->next; | ||
434 | } | ||
435 | if (nlink > 1) error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?"); | ||
436 | } | ||
382 | } | 437 | } |
383 | cpio_entry->device = (major << 8) | minor; | 438 | cpio_entry->device = (major << 8) | minor; |
384 | break; | 439 | break; |