Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/get_header_cpio.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (show annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 5495 byte(s)
-updated to busybox-1.13.4
1 /* vi: set sw=4 ts=4: */
2 /* Copyright 2002 Laurence Anderson
3 *
4 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
5 */
6
7 #include "libbb.h"
8 #include "unarchive.h"
9
10 typedef struct hardlinks_t {
11 struct hardlinks_t *next;
12 int inode; /* TODO: must match maj/min too! */
13 int mode ;
14 int mtime; /* These three are useful only in corner case */
15 int uid ; /* of hardlinks with zero size body */
16 int gid ;
17 char name[1];
18 } hardlinks_t;
19
20 char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
21 {
22 file_header_t *file_header = archive_handle->file_header;
23 char cpio_header[110];
24 int namesize;
25 int major, minor, nlink, mode, inode;
26 unsigned size, uid, gid, mtime;
27
28 #define hardlinks_to_create (*(hardlinks_t **)(&archive_handle->ah_priv[0]))
29 #define created_hardlinks (*(hardlinks_t **)(&archive_handle->ah_priv[1]))
30 #define block_count (archive_handle->ah_priv[2])
31 // if (!archive_handle->ah_priv_inited) {
32 // archive_handle->ah_priv_inited = 1;
33 // hardlinks_to_create = NULL;
34 // created_hardlinks = NULL;
35 // }
36
37 /* There can be padding before archive header */
38 data_align(archive_handle, 4);
39
40 size = full_read(archive_handle->src_fd, cpio_header, 110);
41 if (size == 0) {
42 goto create_hardlinks;
43 }
44 if (size != 110) {
45 bb_error_msg_and_die("short read");
46 }
47 archive_handle->offset += 110;
48
49 if (strncmp(&cpio_header[0], "07070", 5) != 0
50 || (cpio_header[5] != '1' && cpio_header[5] != '2')
51 ) {
52 bb_error_msg_and_die("unsupported cpio format, use newc or crc");
53 }
54
55 if (sscanf(cpio_header + 6,
56 "%8x" "%8x" "%8x" "%8x"
57 "%8x" "%8x" "%8x" /*maj,min:*/ "%*16c"
58 /*rmaj,rmin:*/"%8x" "%8x" "%8x" /*chksum: "%*8c"*/,
59 &inode, &mode, &uid, &gid,
60 &nlink, &mtime, &size,
61 &major, &minor, &namesize) != 10)
62 bb_error_msg_and_die("damaged cpio file");
63 file_header->mode = mode;
64 file_header->uid = uid;
65 file_header->gid = gid;
66 file_header->mtime = mtime;
67 file_header->size = size;
68
69 namesize &= 0x1fff; /* paranoia: limit names to 8k chars */
70 file_header->name = xzalloc(namesize + 1);
71 /* Read in filename */
72 xread(archive_handle->src_fd, file_header->name, namesize);
73 archive_handle->offset += namesize;
74
75 /* Update offset amount and skip padding before file contents */
76 data_align(archive_handle, 4);
77
78 if (strcmp(file_header->name, "TRAILER!!!") == 0) {
79 /* Always round up. ">> 9" divides by 512 */
80 block_count = (void*)(ptrdiff_t) ((archive_handle->offset + 511) >> 9);
81 goto create_hardlinks;
82 }
83
84 file_header->link_target = NULL;
85 if (S_ISLNK(file_header->mode)) {
86 file_header->size &= 0x1fff; /* paranoia: limit names to 8k chars */
87 file_header->link_target = xzalloc(file_header->size + 1);
88 xread(archive_handle->src_fd, file_header->link_target, file_header->size);
89 archive_handle->offset += file_header->size;
90 file_header->size = 0; /* Stop possible seeks in future */
91 }
92
93 // TODO: data_extract_all can't deal with hardlinks to non-files...
94 // when fixed, change S_ISREG to !S_ISDIR here
95
96 if (nlink > 1 && S_ISREG(file_header->mode)) {
97 hardlinks_t *new = xmalloc(sizeof(*new) + namesize);
98 new->inode = inode;
99 new->mode = mode ;
100 new->mtime = mtime;
101 new->uid = uid ;
102 new->gid = gid ;
103 strcpy(new->name, file_header->name);
104 /* Put file on a linked list for later */
105 if (size == 0) {
106 new->next = hardlinks_to_create;
107 hardlinks_to_create = new;
108 return EXIT_SUCCESS; /* Skip this one */
109 /* TODO: this breaks cpio -t (it does not show hardlinks) */
110 }
111 new->next = created_hardlinks;
112 created_hardlinks = new;
113 }
114 file_header->device = makedev(major, minor);
115
116 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
117 archive_handle->action_data(archive_handle);
118 archive_handle->action_header(file_header);
119 } else {
120 data_skip(archive_handle);
121 }
122
123 archive_handle->offset += file_header->size;
124
125 free(file_header->link_target);
126 free(file_header->name);
127 file_header->link_target = NULL;
128 file_header->name = NULL;
129
130 return EXIT_SUCCESS;
131
132 create_hardlinks:
133 free(file_header->link_target);
134 free(file_header->name);
135
136 while (hardlinks_to_create) {
137 hardlinks_t *cur;
138 hardlinks_t *make_me = hardlinks_to_create;
139
140 hardlinks_to_create = make_me->next;
141
142 memset(file_header, 0, sizeof(*file_header));
143 file_header->mtime = make_me->mtime;
144 file_header->name = make_me->name;
145 file_header->mode = make_me->mode;
146 file_header->uid = make_me->uid;
147 file_header->gid = make_me->gid;
148 /*file_header->size = 0;*/
149 /*file_header->link_target = NULL;*/
150
151 /* Try to find a file we are hardlinked to */
152 cur = created_hardlinks;
153 while (cur) {
154 /* TODO: must match maj/min too! */
155 if (cur->inode == make_me->inode) {
156 file_header->link_target = cur->name;
157 /* link_target != NULL, size = 0: "I am a hardlink" */
158 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
159 archive_handle->action_data(archive_handle);
160 free(make_me);
161 goto next_link;
162 }
163 cur = cur->next;
164 }
165 /* Oops... no file with such inode was created... do it now
166 * (happens when hardlinked files are empty (zero length)) */
167 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
168 archive_handle->action_data(archive_handle);
169 /* Move to the list of created hardlinked files */
170 make_me->next = created_hardlinks;
171 created_hardlinks = make_me;
172 next_link: ;
173 }
174
175 while (created_hardlinks) {
176 hardlinks_t *p = created_hardlinks;
177 created_hardlinks = p->next;
178 free(p);
179 }
180
181 return EXIT_FAILURE; /* "No more files to process" */
182 }