rev |
line source |
pascal@517
|
1 diff -purN busybox-1.10.0/archival/Config.in busybox/archival/Config.in
|
pascal@517
|
2 --- busybox-1.10.0/archival/Config.in 2008-03-29 21:47:37.000000000 +0100
|
pascal@517
|
3 +++ busybox-1.10.0/archival/Config.in 2008-03-29 21:47:37.000000000 +0100
|
pascal@517
|
4 @@ -78,6 +78,14 @@ config CPIO
|
pascal@517
|
5 Unless you have a specific application which requires cpio, you should
|
pascal@517
|
6 probably say N here.
|
pascal@517
|
7
|
pascal@517
|
8 +config FEATURE_CPIO_O
|
pascal@517
|
9 + bool "Support for archive creation"
|
pascal@517
|
10 + default n
|
pascal@517
|
11 + depends on CPIO
|
pascal@517
|
12 + help
|
pascal@517
|
13 + This implementation of cpio can create cpio archives in the "newc"
|
pascal@517
|
14 + format only.
|
pascal@517
|
15 +
|
pascal@517
|
16 config DPKG
|
pascal@517
|
17 bool "dpkg"
|
pascal@517
|
18 default n
|
pascal@517
|
19 diff -purN busybox-1.10.0/archival/cpio.c busybox/archival/cpio.c
|
pascal@517
|
20 --- busybox-1.10.0/archival/cpio.c 2008-03-29 21:47:55.000000000 +0100
|
pascal@517
|
21 +++ busybox-1.10.0/archival/cpio.c 2008-03-29 21:47:55.000000000 +0100
|
pascal@517
|
22 @@ -21,12 +21,146 @@
|
pascal@517
|
23 #define CPIO_OPT_FILE 0x10
|
pascal@517
|
24 #define CPIO_OPT_CREATE_LEADING_DIR 0x20
|
pascal@517
|
25 #define CPIO_OPT_PRESERVE_MTIME 0x40
|
pascal@517
|
26 +#define CPIO_OPT_CREATE 0x80
|
pascal@517
|
27 +#define CPIO_OPT_FORMAT 0x100
|
pascal@517
|
28 +
|
pascal@517
|
29 +#if ENABLE_FEATURE_CPIO_O
|
pascal@517
|
30 +static void cpio_pad(off_t *size, int n)
|
pascal@517
|
31 +{
|
pascal@517
|
32 + int i;
|
pascal@517
|
33 + for (*size += i = (-*size) & n; --i >= 0; bb_putchar(0));
|
pascal@517
|
34 +}
|
pascal@517
|
35 +
|
pascal@517
|
36 +static void cpio_o(void)
|
pascal@517
|
37 +{
|
pascal@517
|
38 + struct name_s {
|
pascal@517
|
39 + struct name_s *next;
|
pascal@517
|
40 + char name[0];
|
pascal@517
|
41 + };
|
pascal@517
|
42 + struct inodes_s {
|
pascal@517
|
43 + struct name_s *names;
|
pascal@517
|
44 + struct inodes_s *next;
|
pascal@517
|
45 + struct stat st;
|
pascal@517
|
46 + } *links = NULL;
|
pascal@517
|
47 + off_t bytes = 0; // output bytes count
|
pascal@517
|
48 +#if CONFIG_FEATURE_COPYBUF_KB < 1
|
pascal@517
|
49 + char buf[1024];
|
pascal@517
|
50 +#else
|
pascal@517
|
51 + char buf[CONFIG_FEATURE_COPYBUF_KB * 1024];
|
pascal@517
|
52 +#endif
|
pascal@517
|
53 +
|
pascal@517
|
54 + while (1) {
|
pascal@517
|
55 + const char *name = "TRAILER!!!";
|
pascal@517
|
56 + char *line = xmalloc_getline(stdin);
|
pascal@517
|
57 + // allocate inode struct each loop to avoid struct stat copy
|
pascal@517
|
58 + struct inodes_s *inode = xzalloc(sizeof(*inode)); // die if fail
|
pascal@649
|
59 + off_t size;
|
pascal@517
|
60 +
|
pascal@517
|
61 + inode->st.st_nlink++; // =1
|
pascal@517
|
62 + if (line) {
|
pascal@517
|
63 + /* Strip leading `./' from the filename. */
|
pascal@517
|
64 + for (name = line; name[0] == '.' && name[1] == '/';) {
|
pascal@517
|
65 + while (*++name == '/');
|
pascal@517
|
66 + }
|
pascal@517
|
67 + if (!*name) goto free_and_continue; // line empty
|
pascal@517
|
68 + if (lstat(name, &inode->st)) {
|
pascal@517
|
69 + abort_cpio_o:
|
pascal@517
|
70 + bb_perror_msg_and_die(name);
|
pascal@517
|
71 + }
|
pascal@595
|
72 + if (!S_ISLNK(inode->st.st_mode) && !S_ISREG(inode->st.st_mode))
|
pascal@596
|
73 + inode->st.st_size = 0;
|
pascal@517
|
74 + }
|
pascal@517
|
75 + // hard links will are stored and will be processed later
|
pascal@517
|
76 + if (!S_ISDIR(inode->st.st_mode) && inode->st.st_nlink > 1) {
|
pascal@517
|
77 + struct name_s *n;
|
pascal@517
|
78 + struct inodes_s *l;
|
pascal@517
|
79 +
|
pascal@517
|
80 + for (l = links; l && l->st.st_ino != inode->st.st_ino; l = l->next);
|
pascal@517
|
81 + if (l == NULL) { // not found: new hard links set
|
pascal@517
|
82 + l = inode; // l->names = NULL; l->st = inode->st
|
pascal@517
|
83 + l->next = links;
|
pascal@517
|
84 + links = l;
|
pascal@517
|
85 + }
|
pascal@517
|
86 + n = xmalloc(sizeof(*n) + strlen(name) + 1); // die if fail
|
pascal@517
|
87 + strcpy(n->name, name);
|
pascal@517
|
88 + n->next = l->names;
|
pascal@517
|
89 + l->names = n; // will not free inode if l == inode
|
pascal@517
|
90 + goto free_and_continue;
|
pascal@517
|
91 + }
|
pascal@649
|
92 + size = inode->st.st_size;
|
pascal@517
|
93 + // no more files ? process hard links
|
pascal@517
|
94 + if (!line && links) {
|
pascal@517
|
95 + struct name_s *n;
|
pascal@517
|
96 +
|
pascal@517
|
97 + free(inode); // trailer pseudo inode
|
pascal@517
|
98 + inode = links;
|
pascal@517
|
99 + n = links->names;
|
pascal@517
|
100 + name = line = xstrdup(n->name); // line will free *name memory
|
pascal@517
|
101 + links->names = n->next;
|
pascal@649
|
102 + if (links->names == NULL) { // inode will free *links memory
|
pascal@649
|
103 + size = links->st.st_size;
|
pascal@517
|
104 + links = links->next;
|
pascal@649
|
105 + }
|
pascal@517
|
106 + free(n);
|
pascal@517
|
107 + }
|
pascal@517
|
108 + bytes += printf("070701%08lx%08lx%08lx%08lx%08lx%08lx%08lx"
|
pascal@517
|
109 + "%08lx%08lx%08lx%08lx%08lx%08lx%s%c",
|
pascal@517
|
110 + (unsigned long) inode->st.st_ino,
|
pascal@517
|
111 + (unsigned long) inode->st.st_mode,
|
pascal@517
|
112 + (unsigned long) inode->st.st_uid,
|
pascal@517
|
113 + (unsigned long) inode->st.st_gid,
|
pascal@517
|
114 + (unsigned long) inode->st.st_nlink,
|
pascal@517
|
115 + (unsigned long) inode->st.st_mtime,
|
pascal@649
|
116 + (unsigned long) size,
|
pascal@517
|
117 + (unsigned long) major(inode->st.st_dev),
|
pascal@517
|
118 + (unsigned long) minor(inode->st.st_dev),
|
pascal@517
|
119 + (unsigned long) major(inode->st.st_rdev),
|
pascal@517
|
120 + (unsigned long) minor(inode->st.st_rdev),
|
pascal@517
|
121 + strlen(name) + 1UL, 0UL, name, 0);
|
pascal@517
|
122 + cpio_pad(&bytes, (line) ? 4-1 : 512-1);
|
pascal@649
|
123 + if (size) {
|
pascal@517
|
124 + if (S_ISLNK(inode->st.st_mode)) {
|
pascal@517
|
125 + char *lpath = xmalloc_readlink_or_warn(name);
|
pascal@517
|
126 +
|
pascal@517
|
127 + if (!lpath) goto abort_cpio_o;
|
pascal@517
|
128 + bytes += printf("%s", lpath);
|
pascal@517
|
129 + free(lpath);
|
pascal@517
|
130 + }
|
pascal@517
|
131 + if (S_ISREG(inode->st.st_mode)) {
|
pascal@517
|
132 + int fd = open_or_warn(name, O_RDONLY);
|
pascal@517
|
133 +
|
pascal@517
|
134 + while (1) {
|
pascal@517
|
135 + int len = full_read(fd, buf, sizeof(buf));
|
pascal@517
|
136 + if (len < 0) goto abort_cpio_o;
|
pascal@517
|
137 + if (len == 0) break;
|
pascal@517
|
138 + bytes += len;
|
pascal@517
|
139 + fwrite(buf, 1, len, stdout);
|
pascal@517
|
140 + }
|
pascal@517
|
141 + close(fd);
|
pascal@517
|
142 + }
|
pascal@517
|
143 + cpio_pad(&bytes, 4-1);
|
pascal@517
|
144 + }
|
pascal@517
|
145 +
|
pascal@618
|
146 + if (!line) {
|
pascal@618
|
147 + fputc('\n', stderr); // GNU cpio do that...
|
pascal@618
|
148 + return; // was trailer
|
pascal@618
|
149 + }
|
pascal@517
|
150 +
|
pascal@517
|
151 + free_and_continue:
|
pascal@517
|
152 + if (!inode->names) free(inode);
|
pascal@517
|
153 + free(line);
|
pascal@517
|
154 + }
|
pascal@517
|
155 +}
|
pascal@517
|
156 +#endif
|
pascal@517
|
157
|
pascal@517
|
158 int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
pascal@517
|
159 int cpio_main(int argc, char **argv)
|
pascal@517
|
160 {
|
pascal@517
|
161 archive_handle_t *archive_handle;
|
pascal@517
|
162 char *cpio_filename = NULL;
|
pascal@517
|
163 +#if ENABLE_FEATURE_CPIO_O
|
pascal@517
|
164 + const char *cpio_fmt = "";
|
pascal@517
|
165 +#endif
|
pascal@517
|
166 unsigned opt;
|
pascal@517
|
167
|
pascal@517
|
168 /* Initialise */
|
pascal@517
|
169 @@ -35,10 +169,26 @@ int cpio_main(int argc, char **argv)
|
pascal@517
|
170 archive_handle->seek = seek_by_read;
|
pascal@517
|
171 archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE;
|
pascal@517
|
172
|
pascal@517
|
173 +#if ENABLE_FEATURE_CPIO_O
|
pascal@517
|
174 + opt = getopt32(argv, "ituvF:dmoH:", &cpio_filename,&cpio_fmt);
|
pascal@517
|
175 +
|
pascal@517
|
176 + if (opt & CPIO_OPT_CREATE) {
|
pascal@517
|
177 + if (*cpio_fmt != 'n')
|
pascal@517
|
178 + goto cpio_show_usage;
|
pascal@517
|
179 + if (cpio_filename) {
|
pascal@517
|
180 + fclose(stdout);
|
pascal@517
|
181 + stdout = fopen(cpio_filename,"w");
|
pascal@517
|
182 + }
|
pascal@517
|
183 + cpio_o();
|
pascal@517
|
184 + return EXIT_SUCCESS;
|
pascal@517
|
185 + }
|
pascal@517
|
186 +#else
|
pascal@517
|
187 opt = getopt32(argv, "ituvF:dm", &cpio_filename);
|
pascal@517
|
188 +#endif
|
pascal@517
|
189
|
pascal@517
|
190 /* One of either extract or test options must be given */
|
pascal@517
|
191 if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
|
pascal@517
|
192 + cpio_show_usage:
|
pascal@517
|
193 bb_show_usage();
|
pascal@517
|
194 }
|
pascal@517
|
195
|
pascal@517
|
196 diff -purN busybox-1.10.0/include/usage.h busybox/include/usage.h
|
pascal@517
|
197 --- busybox-1.10.0/include/usage.h 2008-03-29 21:48:22.000000000 +0100
|
pascal@517
|
198 +++ busybox-1.10.0/include/usage.h 2008-03-29 21:48:22.000000000 +0100
|
pascal@517
|
199 @@ -496,13 +496,19 @@
|
pascal@517
|
200 "\n -l,-s Create (sym)links" \
|
pascal@517
|
201
|
pascal@517
|
202 #define cpio_trivial_usage \
|
pascal@517
|
203 - "-[dimtuv][F cpiofile]"
|
pascal@517
|
204 + "-[dim" USE_FEATURE_CPIO_O("o") "tuv][F cpiofile]" \
|
pascal@517
|
205 + USE_FEATURE_CPIO_O( "[H newc]" )
|
pascal@517
|
206 #define cpio_full_usage \
|
pascal@517
|
207 - "Extract or list files from a cpio archive\n" \
|
pascal@517
|
208 + "Extract or list files from a cpio archive" \
|
pascal@517
|
209 + USE_FEATURE_CPIO_O( ", or create a cpio archive" ) "\n" \
|
pascal@517
|
210 "Main operation mode:" \
|
pascal@517
|
211 "\n d Make leading directories" \
|
pascal@517
|
212 "\n i Extract" \
|
pascal@517
|
213 "\n m Preserve mtime" \
|
pascal@517
|
214 + USE_FEATURE_CPIO_O( \
|
pascal@517
|
215 + "\n o Create" \
|
pascal@517
|
216 + "\n H newc Define format" \
|
pascal@517
|
217 + ) \
|
pascal@517
|
218 "\n t List" \
|
pascal@517
|
219 "\n v Verbose" \
|
pascal@517
|
220 "\n u Unconditional overwrite" \
|