aboutsummaryrefslogtreecommitdiff
path: root/archival/libunarchive
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-12-10 00:17:22 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-12-10 00:17:22 +0000
commitb72a735a320eb60d29bc1580138c06ae7c9d321c (patch)
tree4923918fadcaac4fdaa5d4197a4e5bafd22b9b2e /archival/libunarchive
parent62fae308a3d92d987711d08f3d36b0ad753c2e18 (diff)
downloadbusybox-w32-b72a735a320eb60d29bc1580138c06ae7c9d321c.tar.gz
busybox-w32-b72a735a320eb60d29bc1580138c06ae7c9d321c.tar.bz2
busybox-w32-b72a735a320eb60d29bc1580138c06ae7c9d321c.zip
rpm applet by Laurence Anderson
Diffstat (limited to 'archival/libunarchive')
-rw-r--r--archival/libunarchive/Makefile.in1
-rw-r--r--archival/libunarchive/data_extract_all.c2
-rw-r--r--archival/libunarchive/get_header_cpio.c185
3 files changed, 187 insertions, 1 deletions
diff --git a/archival/libunarchive/Makefile.in b/archival/libunarchive/Makefile.in
index 28e2955b9..b59048612 100644
--- a/archival/libunarchive/Makefile.in
+++ b/archival/libunarchive/Makefile.in
@@ -35,6 +35,7 @@ LIBUNARCHIVE-y:= \
35 filter_accept_reject_list.o \ 35 filter_accept_reject_list.o \
36\ 36\
37 get_header_ar.o \ 37 get_header_ar.o \
38 get_header_cpio.o \
38 get_header_tar.o \ 39 get_header_tar.o \
39 get_header_tar_bz2.o \ 40 get_header_tar_bz2.o \
40 get_header_tar_gz.o \ 41 get_header_tar_gz.o \
diff --git a/archival/libunarchive/data_extract_all.c b/archival/libunarchive/data_extract_all.c
index 7ab87e73e..9c4510e6b 100644
--- a/archival/libunarchive/data_extract_all.c
+++ b/archival/libunarchive/data_extract_all.c
@@ -43,7 +43,7 @@ extern void data_extract_all(archive_handle_t *archive_handle)
43 switch(file_header->mode & S_IFMT) { 43 switch(file_header->mode & S_IFMT) {
44 case S_IFREG: { 44 case S_IFREG: {
45#ifdef CONFIG_CPIO 45#ifdef CONFIG_CPIO
46 if (file_header->link_name) { 46 if (file_header->link_name && file_header->size == 0) {
47 /* hard link */ 47 /* hard link */
48 res = link(file_header->link_name, file_header->name); 48 res = link(file_header->link_name, file_header->name);
49 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) { 49 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
diff --git a/archival/libunarchive/get_header_cpio.c b/archival/libunarchive/get_header_cpio.c
new file mode 100644
index 000000000..87e971588
--- /dev/null
+++ b/archival/libunarchive/get_header_cpio.c
@@ -0,0 +1,185 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include "unarchive.h"
22#include "libbb.h"
23
24typedef struct hardlinks_s {
25 file_header_t *entry;
26 int inode;
27 struct hardlinks_s *next;
28} hardlinks_t;
29
30extern char get_header_cpio(archive_handle_t *archive_handle)
31{
32 static hardlinks_t *saved_hardlinks = NULL;
33 static unsigned short pending_hardlinks = 0;
34 file_header_t *file_header = archive_handle->file_header;
35 char cpio_header[110];
36 int namesize;
37 char dummy[16];
38 int major, minor, nlink, inode;
39 char extract_flag;
40
41 if (pending_hardlinks) { /* Deal with any pending hardlinks */
42 hardlinks_t *tmp;
43 hardlinks_t *oldtmp;
44
45 tmp = saved_hardlinks;
46 oldtmp = NULL;
47
48 while (tmp) {
49 error_msg_and_die("need to fix this\n");
50 if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
51 file_header = tmp->entry;
52 if (oldtmp) {
53 oldtmp->next = tmp->next; /* Remove item from linked list */
54 } else {
55 saved_hardlinks = tmp->next;
56 }
57 free(tmp);
58 continue;
59 }
60 oldtmp = tmp;
61 tmp = tmp->next;
62 }
63 pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
64 }
65
66 /* There can be padding before archive header */
67 data_align(archive_handle, 4);
68
69 if (archive_xread_all_eof(archive_handle, cpio_header, 110) == 0) {
70 return(EXIT_FAILURE);
71 }
72 archive_handle->offset += 110;
73
74 if (strncmp(&cpio_header[0], "07070", 5) != 0) {
75 printf("cpio header is %x-%x-%x-%x-%x\n",
76 cpio_header[0],
77 cpio_header[1],
78 cpio_header[2],
79 cpio_header[3],
80 cpio_header[4]);
81 error_msg_and_die("Unsupported cpio format");
82 }
83
84 if ((cpio_header[5] != '1') && (cpio_header[5] != '2')) {
85 error_msg_and_die("Unsupported cpio format, use newc or crc");
86 }
87
88 sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
89 dummy, &inode, (unsigned int*)&file_header->mode,
90 (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
91 &nlink, &file_header->mtime, &file_header->size,
92 dummy, &major, &minor, &namesize, dummy);
93
94 file_header->name = (char *) xmalloc(namesize + 1);
95 archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */
96 file_header->name[namesize] = '\0';
97 archive_handle->offset += namesize;
98
99 /* Update offset amount and skip padding before file contents */
100 data_align(archive_handle, 4);
101
102 if (strcmp(file_header->name, "TRAILER!!!") == 0) {
103 printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
104 if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
105 hardlinks_t *tmp = saved_hardlinks;
106 hardlinks_t *oldtmp = NULL;
107 while (tmp) {
108 error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
109 oldtmp = tmp;
110 tmp = tmp->next;
111 free (oldtmp->entry->name);
112 free (oldtmp->entry);
113 free (oldtmp);
114 }
115 saved_hardlinks = NULL;
116 pending_hardlinks = 0;
117 }
118 return(EXIT_FAILURE);
119 }
120
121 if (S_ISLNK(file_header->mode)) {
122 file_header->link_name = (char *) xmalloc(file_header->size + 1);
123 archive_xread_all(archive_handle, file_header->link_name, file_header->size);
124 file_header->link_name[file_header->size] = '\0';
125 archive_handle->offset += file_header->size;
126 file_header->size = 0; /* Stop possible seeks in future */
127 }
128 if (nlink > 1 && !S_ISDIR(file_header->mode)) {
129 if (file_header->size == 0) { /* Put file on a linked list for later */
130 hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
131 new->next = saved_hardlinks;
132 new->inode = inode;
133 new->entry = file_header;
134 saved_hardlinks = new;
135 return(EXIT_SUCCESS); // Skip this one
136 } else { /* Found the file with data in */
137 hardlinks_t *tmp = saved_hardlinks;
138 pending_hardlinks = 1;
139 while (tmp) {
140 if (tmp->inode == inode) {
141 tmp->entry->link_name = xstrdup(file_header->name);
142 nlink--;
143 }
144 tmp = tmp->next;
145 }
146 if (nlink > 1) {
147 error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
148 }
149 }
150 }
151 file_header->device = (major << 8) | minor;
152
153 extract_flag = FALSE;
154 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
155 struct stat statbuf;
156
157 extract_flag = TRUE;
158
159 /* Check if the file already exists */
160 if (lstat (file_header->name, &statbuf) == 0) {
161 if ((archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) || (statbuf.st_mtime < file_header->mtime)) {
162 /* Remove file if flag set or its older than the file to be extracted */
163 if (unlink(file_header->name) == -1) {
164 perror_msg_and_die("Couldnt remove old file");
165 }
166 } else {
167 if (! archive_handle->flags & ARCHIVE_EXTRACT_QUIET) {
168 error_msg("%s not created: newer or same age file exists", file_header->name);
169 }
170 extract_flag = FALSE;
171 }
172 }
173 archive_handle->action_header(file_header);
174 }
175
176 archive_handle->action_header(file_header);
177 if (extract_flag) {
178 archive_handle->action_data(archive_handle);
179 } else {
180 data_skip(archive_handle);
181 }
182 archive_handle->offset += file_header->size;
183 return (EXIT_SUCCESS);
184}
185