1
2
3
4
5
6
7#include "libbb.h"
8#include "bb_archive.h"
9
10typedef struct hardlinks_t {
11 struct hardlinks_t *next;
12 int inode;
13 int mode ;
14 int mtime;
15 int uid ;
16 int gid ;
17 char name[1];
18} hardlinks_t;
19
20char 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
29 data_align(archive_handle, 4);
30
31 size = full_read(archive_handle->src_fd, cpio_header, 110);
32 if (size == 0) {
33 goto create_hardlinks;
34 }
35 if (size != 110) {
36 bb_error_msg_and_die("short read");
37 }
38 archive_handle->offset += 110;
39
40 if (!is_prefixed_with(&cpio_header[0], "07070")
41 || (cpio_header[5] != '1' && cpio_header[5] != '2')
42 ) {
43 bb_error_msg_and_die("unsupported cpio format, use newc or crc");
44 }
45
46 if (sscanf(cpio_header + 6,
47 "%8x" "%8x" "%8x" "%8x"
48 "%8x" "%8x" "%8x" "%*16c"
49 "%8x" "%8x" "%8x" ,
50 &inode, &mode, &uid, &gid,
51 &nlink, &mtime, &size,
52 &major, &minor, &namesize) != 10)
53 bb_error_msg_and_die("damaged cpio file");
54 file_header->mode = mode;
55
56 if (archive_handle->cpio__owner.uid != (uid_t)-1L)
57 uid = archive_handle->cpio__owner.uid;
58 if (archive_handle->cpio__owner.gid != (gid_t)-1L)
59 gid = archive_handle->cpio__owner.gid;
60 file_header->uid = uid;
61 file_header->gid = gid;
62 file_header->mtime = mtime;
63 file_header->size = size;
64
65 namesize &= 0x1fff;
66 file_header->name = xzalloc(namesize + 1);
67
68 xread(archive_handle->src_fd, file_header->name, namesize);
69 if (file_header->name[0] == '/') {
70
71
72
73
74 char *p = file_header->name;
75 do p++; while (*p == '/');
76 overlapping_strcpy(file_header->name, p);
77 }
78 archive_handle->offset += namesize;
79
80
81 data_align(archive_handle, 4);
82
83 if (strcmp(file_header->name, cpio_TRAILER) == 0) {
84
85 archive_handle->cpio__blocks = (uoff_t)(archive_handle->offset + 511) >> 9;
86 goto create_hardlinks;
87 }
88
89 file_header->link_target = NULL;
90 if (S_ISLNK(file_header->mode)) {
91 file_header->size &= 0x1fff;
92 file_header->link_target = xzalloc(file_header->size + 1);
93 xread(archive_handle->src_fd, file_header->link_target, file_header->size);
94 archive_handle->offset += file_header->size;
95 file_header->size = 0;
96 }
97
98
99
100
101 if (nlink > 1 && S_ISREG(file_header->mode)) {
102 hardlinks_t *new = xmalloc(sizeof(*new) + namesize);
103 new->inode = inode;
104 new->mode = mode ;
105 new->mtime = mtime;
106 new->uid = uid ;
107 new->gid = gid ;
108 strcpy(new->name, file_header->name);
109
110 if (size == 0) {
111 new->next = archive_handle->cpio__hardlinks_to_create;
112 archive_handle->cpio__hardlinks_to_create = new;
113 return EXIT_SUCCESS;
114
115 }
116 new->next = archive_handle->cpio__created_hardlinks;
117 archive_handle->cpio__created_hardlinks = new;
118 }
119 file_header->device = makedev(major, minor);
120
121 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
122 archive_handle->action_data(archive_handle);
123
124
125
126
127 archive_handle->action_header(file_header);
128 } else {
129 data_skip(archive_handle);
130 }
131
132 archive_handle->offset += file_header->size;
133
134 free(file_header->link_target);
135 free(file_header->name);
136 file_header->link_target = NULL;
137 file_header->name = NULL;
138
139 return EXIT_SUCCESS;
140
141 create_hardlinks:
142 free(file_header->link_target);
143 free(file_header->name);
144
145 while (archive_handle->cpio__hardlinks_to_create) {
146 hardlinks_t *cur;
147 hardlinks_t *make_me = archive_handle->cpio__hardlinks_to_create;
148
149 archive_handle->cpio__hardlinks_to_create = make_me->next;
150
151 memset(file_header, 0, sizeof(*file_header));
152 file_header->mtime = make_me->mtime;
153 file_header->name = make_me->name;
154 file_header->mode = make_me->mode;
155 file_header->uid = make_me->uid;
156 file_header->gid = make_me->gid;
157
158
159
160
161 cur = archive_handle->cpio__created_hardlinks;
162 while (cur) {
163
164 if (cur->inode == make_me->inode) {
165 file_header->link_target = cur->name;
166
167 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
168 archive_handle->action_data(archive_handle);
169 free(make_me);
170 goto next_link;
171 }
172 cur = cur->next;
173 }
174
175
176 if (archive_handle->filter(archive_handle) == EXIT_SUCCESS)
177 archive_handle->action_data(archive_handle);
178
179 make_me->next = archive_handle->cpio__created_hardlinks;
180 archive_handle->cpio__created_hardlinks = make_me;
181 next_link: ;
182 }
183
184 while (archive_handle->cpio__created_hardlinks) {
185 hardlinks_t *p = archive_handle->cpio__created_hardlinks;
186 archive_handle->cpio__created_hardlinks = p->next;
187 free(p);
188 }
189
190 return EXIT_FAILURE;
191}
192