Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide 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 niro 532 /* 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 niro 816 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 niro 532 } hardlinks_t;
19    
20 niro 816 char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
21 niro 532 {
22     file_header_t *file_header = archive_handle->file_header;
23     char cpio_header[110];
24     int namesize;
25 niro 816 int major, minor, nlink, mode, inode;
26     unsigned size, uid, gid, mtime;
27 niro 532
28 niro 816 #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 niro 532
37     /* There can be padding before archive header */
38     data_align(archive_handle, 4);
39    
40 niro 816 size = full_read(archive_handle->src_fd, cpio_header, 110);
41     if (size == 0) {
42     goto create_hardlinks;
43 niro 532 }
44 niro 816 if (size != 110) {
45     bb_error_msg_and_die("short read");
46     }
47 niro 532 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 niro 816 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 niro 532
69 niro 816 namesize &= 0x1fff; /* paranoia: limit names to 8k chars */
70 niro 532 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 niro 816 /* Always round up. ">> 9" divides by 512 */
80     block_count = (void*)(ptrdiff_t) ((archive_handle->offset + 511) >> 9);
81     goto create_hardlinks;
82 niro 532 }
83    
84 niro 816 file_header->link_target = NULL;
85 niro 532 if (S_ISLNK(file_header->mode)) {
86 niro 816 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 niro 532 archive_handle->offset += file_header->size;
90     file_header->size = 0; /* Stop possible seeks in future */
91     }
92 niro 816
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 niro 532 return EXIT_SUCCESS; /* Skip this one */
109 niro 816 /* TODO: this breaks cpio -t (it does not show hardlinks) */
110 niro 532 }
111 niro 816 new->next = created_hardlinks;
112     created_hardlinks = new;
113 niro 532 }
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 niro 816 archive_handle->action_header(file_header);
119 niro 532 } else {
120     data_skip(archive_handle);
121     }
122    
123     archive_handle->offset += file_header->size;
124    
125 niro 816 free(file_header->link_target);
126     free(file_header->name);
127     file_header->link_target = NULL;
128     file_header->name = NULL;
129 niro 532
130     return EXIT_SUCCESS;
131 niro 816
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 niro 532 }