Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/utils/cpio.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1297 - (show annotations) (download)
Fri May 27 15:12:11 2011 UTC (12 years, 11 months ago) by niro
File MIME type: text/plain
File size: 31859 byte(s)
-updated to klibc-1.5.22 with mntproc definitions patch included
1 /* copyin.c - extract or list a cpio archive
2 Copyright (C) 1990,1991,1992,2001,2002,2003,2004 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <malloc.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <utime.h>
30 #ifndef FNM_PATHNAME
31 #include <fnmatch.h>
32 #endif
33
34 #ifndef O_BINARY
35 # define O_BINARY 0
36 #endif
37
38 # ifndef DIRECTORY_SEPARATOR
39 # define DIRECTORY_SEPARATOR '/'
40 # endif
41
42 # ifndef ISSLASH
43 # define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
44 # endif
45
46 /* Return 1 if an array of N objects, each of size S, cannot exist due
47 to size arithmetic overflow. S must be positive and N must be
48 nonnegative. This is a macro, not an inline function, so that it
49 works correctly even when SIZE_MAX < N.
50
51 By gnulib convention, SIZE_MAX represents overflow in size
52 calculations, so the conservative dividend to use here is
53 SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
54 However, malloc (SIZE_MAX) fails on all known hosts where
55 sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
56 exactly-SIZE_MAX allocations on such hosts; this avoids a test and
57 branch when S is known to be 1. */
58 # define xalloc_oversized(n, s) \
59 ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
60
61 #define DISK_IO_BLOCK_SIZE (512)
62
63 char *progname = NULL;
64
65 /* If true, print a . for each file processed. (-V) */
66 char dot_flag = false;
67
68 /* Input and output buffers. */
69 char *input_buffer, *output_buffer;
70
71 /* The size of the input buffer. */
72 long input_buffer_size;
73
74 /* Current locations in `input_buffer' and `output_buffer'. */
75 char *in_buff, *out_buff;
76
77 /* Current number of bytes stored at `input_buff' and `output_buff'. */
78 long input_size, output_size;
79
80 /* Block size value, initially 512. -B sets to 5120. */
81 int io_block_size = 512;
82
83 struct new_cpio_header {
84 unsigned short c_magic;
85 union {
86 struct {
87 unsigned long c_ino;
88 unsigned long c_mode;
89 unsigned long c_uid;
90 unsigned long c_gid;
91 unsigned long c_nlink;
92 unsigned long c_mtime;
93 unsigned long c_filesize;
94 long c_dev_maj;
95 long c_dev_min;
96 long c_rdev_maj;
97 long c_rdev_min;
98 unsigned long c_namesize;
99 unsigned long c_chksum;
100 };
101 unsigned long c_hdr[13];
102 };
103 char *c_name;
104 char *c_tar_linkname;
105 };
106
107 /* Total number of bytes read and written for all files.
108 * Now that many tape drives hold more than 4Gb we need more than 32
109 * bits to hold input_bytes and output_bytes.
110 */
111 long long input_bytes, output_bytes;
112
113 /* Allocate N bytes of memory dynamically, with error checking. */
114
115 static void *xmalloc(size_t n)
116 {
117 void *p;
118 if (xalloc_oversized(n, 1) || (!(p = malloc(n)) && n != 0)) {
119 fprintf(stderr, "%s: memory exhausted\n", progname);
120 exit(1);
121 }
122 return p;
123 /* return xnmalloc_inline (n, 1); */
124 }
125
126 /* Clone STRING. */
127
128 static char *xstrdup(char const *string)
129 {
130 size_t s = strlen(string) + 1;
131 return memcpy(xmalloc(s), string, s);
132 /* return xmemdup_inline (string, strlen (string) + 1); */
133 }
134
135 /* Copy NUM_BYTES of buffer `in_buff' into IN_BUF.
136 `in_buff' may be partly full.
137 When `in_buff' is exhausted, refill it from file descriptor IN_DES. */
138
139 static void tape_fill_input_buffer(int in_des, int num_bytes)
140 {
141 in_buff = input_buffer;
142 num_bytes = (num_bytes < io_block_size) ? num_bytes : io_block_size;
143 input_size = read(in_des, input_buffer, num_bytes);
144 if (input_size < 0) {
145 fprintf(stderr, "%s: read error: %s\n", progname,
146 strerror(errno));
147 exit(1);
148 }
149 if (input_size == 0) {
150 fprintf(stderr, "%s: premature end of file\n", progname);
151 exit(1);
152 }
153 input_bytes += input_size;
154 }
155
156 /* Write `output_size' bytes of `output_buffer' to file
157 descriptor OUT_DES and reset `output_size' and `out_buff'.
158 If `swapping_halfwords' or `swapping_bytes' is set,
159 do the appropriate swapping first. Our callers have
160 to make sure to only set these flags if `output_size'
161 is appropriate (a multiple of 4 for `swapping_halfwords',
162 2 for `swapping_bytes'). The fact that DISK_IO_BLOCK_SIZE
163 must always be a multiple of 4 helps us (and our callers)
164 insure this. */
165
166 static void disk_empty_output_buffer(int out_des)
167 {
168 int bytes_written;
169
170 bytes_written = write(out_des, output_buffer, output_size);
171
172 if (bytes_written != output_size) {
173 fprintf(stderr, "%s: write error: %s\n",
174 progname, strerror(errno));
175 exit(1);
176 }
177 output_bytes += output_size;
178 out_buff = output_buffer;
179 output_size = 0;
180 }
181
182 /* Copy NUM_BYTES of buffer IN_BUF to `out_buff', which may be partly full.
183 When `out_buff' fills up, flush it to file descriptor OUT_DES. */
184
185 static void disk_buffered_write(char *in_buf, int out_des, long num_bytes)
186 {
187 register long bytes_left = num_bytes; /* Bytes needing to be copied. */
188 register long space_left; /* Room left in output buffer. */
189
190 while (bytes_left > 0) {
191 space_left = DISK_IO_BLOCK_SIZE - output_size;
192 if (space_left == 0)
193 disk_empty_output_buffer(out_des);
194 else {
195 if (bytes_left < space_left)
196 space_left = bytes_left;
197 memmove(out_buff, in_buf, (unsigned)space_left);
198 out_buff += space_left;
199 output_size += space_left;
200 in_buf += space_left;
201 bytes_left -= space_left;
202 }
203 }
204 }
205
206 /* Copy a file using the input and output buffers, which may start out
207 partly full. After the copy, the files are not closed nor the last
208 block flushed to output, and the input buffer may still be partly
209 full. If `crc_i_flag' is set, add each byte to `crc'.
210 IN_DES is the file descriptor for input;
211 OUT_DES is the file descriptor for output;
212 NUM_BYTES is the number of bytes to copy. */
213
214 static void copy_files_tape_to_disk(int in_des, int out_des, long num_bytes)
215 {
216 long size;
217
218 while (num_bytes > 0) {
219 if (input_size == 0)
220 tape_fill_input_buffer(in_des, io_block_size);
221 size = (input_size < num_bytes) ? input_size : num_bytes;
222 disk_buffered_write(in_buff, out_des, size);
223 num_bytes -= size;
224 input_size -= size;
225 in_buff += size;
226 }
227 }
228
229 /* if IN_BUF is NULL, Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
230 static void tape_buffered_read(char *in_buf, int in_des, long num_bytes)
231 {
232 register long bytes_left = num_bytes; /* Bytes needing to be copied. */
233 register long space_left; /* Bytes to copy from input buffer. */
234
235 while (bytes_left > 0) {
236 if (input_size == 0)
237 tape_fill_input_buffer(in_des, io_block_size);
238 if (bytes_left < input_size)
239 space_left = bytes_left;
240 else
241 space_left = input_size;
242 if (in_buf != NULL) {
243 memmove(in_buf, in_buff, (unsigned)space_left);
244 in_buf += space_left;
245 }
246 in_buff += space_left;
247 input_size -= space_left;
248 bytes_left -= space_left;
249 }
250 }
251
252 /* Skip the next NUM_BYTES bytes of file descriptor IN_DES. */
253 #define tape_toss_input(in_des,num_bytes) \
254 (tape_buffered_read(NULL,(in_des),(num_bytes)))
255
256 struct deferment {
257 struct deferment *next;
258 struct new_cpio_header header;
259 };
260
261 static struct deferment *create_deferment(struct new_cpio_header *file_hdr)
262 {
263 struct deferment *d;
264 d = (struct deferment *)xmalloc(sizeof(struct deferment));
265 d->header = *file_hdr;
266 d->header.c_name = (char *)xmalloc(strlen(file_hdr->c_name) + 1);
267 strcpy(d->header.c_name, file_hdr->c_name);
268 return d;
269 }
270
271 static void free_deferment(struct deferment *d)
272 {
273 free(d->header.c_name);
274 free(d);
275 }
276
277 static int link_to_name(char *link_name, char *link_target)
278 {
279 int res = link(link_target, link_name);
280 return res;
281 }
282
283 struct inode_val {
284 unsigned long inode;
285 unsigned long major_num;
286 unsigned long minor_num;
287 char *file_name;
288 };
289
290 /* Inode hash table. Allocated by first call to add_inode. */
291 static struct inode_val **hash_table = NULL;
292
293 /* Size of current hash table. Initial size is 47. (47 = 2*22 + 3) */
294 static int hash_size = 22;
295
296 /* Number of elements in current hash table. */
297 static int hash_num;
298
299 /* Do the hash insert. Used in normal inserts and resizing the hash
300 table. It is guaranteed that there is room to insert the item.
301 NEW_VALUE is the pointer to the previously allocated inode, file
302 name association record. */
303
304 static void hash_insert(struct inode_val *new_value)
305 {
306 int start; /* Home position for the value. */
307 int temp; /* Used for rehashing. */
308
309 /* Hash function is node number modulo the table size. */
310 start = new_value->inode % hash_size;
311
312 /* Do the initial look into the table. */
313 if (hash_table[start] == NULL) {
314 hash_table[start] = new_value;
315 return;
316 }
317
318 /* If we get to here, the home position is full with a different inode
319 record. Do a linear search for the first NULL pointer and insert
320 the new item there. */
321 temp = (start + 1) % hash_size;
322 while (hash_table[temp] != NULL)
323 temp = (temp + 1) % hash_size;
324
325 /* Insert at the NULL. */
326 hash_table[temp] = new_value;
327 }
328
329 /* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */
330
331 static void
332 add_inode(unsigned long node_num, char *file_name, unsigned long major_num,
333 unsigned long minor_num)
334 {
335 struct inode_val *temp;
336
337 /* Create new inode record. */
338 temp = (struct inode_val *)xmalloc(sizeof(struct inode_val));
339 temp->inode = node_num;
340 temp->major_num = major_num;
341 temp->minor_num = minor_num;
342 temp->file_name = xstrdup(file_name);
343
344 /* Do we have to increase the size of (or initially allocate)
345 the hash table? */
346 if (hash_num == hash_size || hash_table == NULL) {
347 struct inode_val **old_table; /* Pointer to old table. */
348 int i; /* Index for re-insert loop. */
349
350 /* Save old table. */
351 old_table = hash_table;
352 if (old_table == NULL)
353 hash_num = 0;
354
355 /* Calculate new size of table and allocate it.
356 Sequence of table sizes is 47, 97, 197, 397, 797, 1597, 3197, 6397 ...
357 where 3197 and most of the sizes after 6397 are not prime. The other
358 numbers listed are prime. */
359 hash_size = 2 * hash_size + 3;
360 hash_table = (struct inode_val **)
361 xmalloc(hash_size * sizeof(struct inode_val *));
362 memset(hash_table, 0, hash_size * sizeof(struct inode_val *));
363
364 /* Insert the values from the old table into the new table. */
365 for (i = 0; i < hash_num; i++)
366 hash_insert(old_table[i]);
367
368 free(old_table);
369 }
370
371 /* Insert the new record and increment the count of elements in the
372 hash table. */
373 hash_insert(temp);
374 hash_num++;
375 }
376
377 static char *find_inode_file(unsigned long node_num, unsigned long major_num,
378 unsigned long minor_num)
379 {
380 int start; /* Initial hash location. */
381 int temp; /* Rehash search variable. */
382
383 if (hash_table != NULL) {
384 /* Hash function is node number modulo the table size. */
385 start = node_num % hash_size;
386
387 /* Initial look into the table. */
388 if (hash_table[start] == NULL)
389 return NULL;
390 if (hash_table[start]->inode == node_num
391 && hash_table[start]->major_num == major_num
392 && hash_table[start]->minor_num == minor_num)
393 return hash_table[start]->file_name;
394
395 /* The home position is full with a different inode record.
396 Do a linear search terminated by a NULL pointer. */
397 for (temp = (start + 1) % hash_size;
398 hash_table[temp] != NULL && temp != start;
399 temp = (temp + 1) % hash_size) {
400 if (hash_table[temp]->inode == node_num
401 && hash_table[start]->major_num == major_num
402 && hash_table[start]->minor_num == minor_num)
403 return hash_table[temp]->file_name;
404 }
405 }
406 return NULL;
407 }
408
409 /* Try and create a hard link from FILE_NAME to another file
410 with the given major/minor device number and inode. If no other
411 file with the same major/minor/inode numbers is known, add this file
412 to the list of known files and associated major/minor/inode numbers
413 and return -1. If another file with the same major/minor/inode
414 numbers is found, try and create another link to it using
415 link_to_name, and return 0 for success and -1 for failure. */
416
417 static int
418 link_to_maj_min_ino(char *file_name, int st_dev_maj, int st_dev_min, int st_ino)
419 {
420 int link_res;
421 char *link_name;
422 link_res = -1;
423 /* Is the file a link to a previously copied file? */
424 link_name = find_inode_file(st_ino, st_dev_maj, st_dev_min);
425 if (link_name == NULL)
426 add_inode(st_ino, file_name, st_dev_maj, st_dev_min);
427 else
428 link_res = link_to_name(file_name, link_name);
429 return link_res;
430 }
431
432 static void copyin_regular_file(struct new_cpio_header *file_hdr,
433 int in_file_des);
434
435 static void warn_junk_bytes(long bytes_skipped)
436 {
437 fprintf(stderr, "%s: warning: skipped %ld byte(s) of junk\n",
438 progname, bytes_skipped);
439 }
440
441 /* Skip the padding on IN_FILE_DES after a header or file,
442 up to the next header.
443 The number of bytes skipped is based on OFFSET -- the current offset
444 from the last start of a header (or file) -- and the current
445 header type. */
446
447 static void tape_skip_padding(int in_file_des, int offset)
448 {
449 int pad;
450 pad = (4 - (offset % 4)) % 4;
451
452 if (pad != 0)
453 tape_toss_input(in_file_des, pad);
454 }
455
456 static int
457 try_existing_file(struct new_cpio_header *file_hdr, int in_file_des,
458 int *existing_dir)
459 {
460 struct stat file_stat;
461
462 *existing_dir = false;
463 if (lstat(file_hdr->c_name, &file_stat) == 0) {
464 if (S_ISDIR(file_stat.st_mode)
465 && ((file_hdr->c_mode & S_IFMT) == S_IFDIR)) {
466 /* If there is already a directory there that
467 we are trying to create, don't complain about
468 it. */
469 *existing_dir = true;
470 return 0;
471 } else if (S_ISDIR(file_stat.st_mode)
472 ? rmdir(file_hdr->c_name)
473 : unlink(file_hdr->c_name)) {
474 fprintf(stderr, "%s: cannot remove current %s: %s\n",
475 progname, file_hdr->c_name, strerror(errno));
476 tape_toss_input(in_file_des, file_hdr->c_filesize);
477 tape_skip_padding(in_file_des, file_hdr->c_filesize);
478 return -1; /* Go to the next file. */
479 }
480 }
481 return 0;
482 }
483
484 /* The newc and crc formats store multiply linked copies of the same file
485 in the archive only once. The actual data is attached to the last link
486 in the archive, and the other links all have a filesize of 0. When a
487 file in the archive has multiple links and a filesize of 0, its data is
488 probably "attatched" to another file in the archive, so we can't create
489 it right away. We have to "defer" creating it until we have created
490 the file that has the data "attatched" to it. We keep a list of the
491 "defered" links on deferments. */
492
493 struct deferment *deferments = NULL;
494
495 /* Add a file header to the deferments list. For now they all just
496 go on one list, although we could optimize this if necessary. */
497
498 static void defer_copyin(struct new_cpio_header *file_hdr)
499 {
500 struct deferment *d;
501 d = create_deferment(file_hdr);
502 d->next = deferments;
503 deferments = d;
504 return;
505 }
506
507 /* We just created a file that (probably) has some other links to it
508 which have been defered. Go through all of the links on the deferments
509 list and create any which are links to this file. */
510
511 static void create_defered_links(struct new_cpio_header *file_hdr)
512 {
513 struct deferment *d;
514 struct deferment *d_prev;
515 int ino;
516 int maj;
517 int min;
518 int link_res;
519 ino = file_hdr->c_ino;
520 maj = file_hdr->c_dev_maj;
521 min = file_hdr->c_dev_min;
522 d = deferments;
523 d_prev = NULL;
524 while (d != NULL) {
525 if ((d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
526 && (d->header.c_dev_min == min)) {
527 struct deferment *d_free;
528 link_res =
529 link_to_name(d->header.c_name, file_hdr->c_name);
530 if (link_res < 0) {
531 fprintf(stderr,
532 "%s: cannot link %s to %s: %s\n",
533 progname, d->header.c_name,
534 file_hdr->c_name, strerror(errno));
535 }
536 if (d_prev != NULL)
537 d_prev->next = d->next;
538 else
539 deferments = d->next;
540 d_free = d;
541 d = d->next;
542 free_deferment(d_free);
543 } else {
544 d_prev = d;
545 d = d->next;
546 }
547 }
548 }
549
550 /* If we had a multiply linked file that really was empty then we would
551 have defered all of its links, since we never found any with data
552 "attached", and they will still be on the deferment list even when
553 we are done reading the whole archive. Write out all of these
554 empty links that are still on the deferments list. */
555
556 static void create_final_defers(void)
557 {
558 struct deferment *d;
559 int link_res;
560 int out_file_des;
561 struct utimbuf times; /* For setting file times. */
562 /* Initialize this in case it has members we don't know to set. */
563 memset(&times, 0, sizeof(struct utimbuf));
564
565 for (d = deferments; d != NULL; d = d->next) {
566 /* Debian hack: A line, which could cause an endless loop, was
567 removed (97/1/2). It was reported by Ronald F. Guilmette to
568 the upstream maintainers. -BEM */
569 /* Debian hack: This was reported by Horst Knobloch. This bug has
570 been reported to "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM
571 */
572 link_res = link_to_maj_min_ino(d->header.c_name,
573 d->header.c_dev_maj,
574 d->header.c_dev_min,
575 d->header.c_ino);
576 if (link_res == 0) {
577 continue;
578 }
579 out_file_des = open(d->header.c_name,
580 O_CREAT | O_WRONLY | O_BINARY, 0600);
581 if (out_file_des < 0) {
582 fprintf(stderr, "%s: open %s: %s\n",
583 progname, d->header.c_name, strerror(errno));
584 continue;
585 }
586
587 /* File is now copied; set attributes. */
588 if ((fchown(out_file_des, d->header.c_uid, d->header.c_gid) < 0)
589 && errno != EPERM)
590 fprintf(stderr, "%s: fchown %s: %s\n",
591 progname, d->header.c_name, strerror(errno));
592 /* chown may have turned off some permissions we wanted. */
593 if (fchmod(out_file_des, (int)d->header.c_mode) < 0)
594 fprintf(stderr, "%s: fchmod %s: %s\n",
595 progname, d->header.c_name, strerror(errno));
596
597 if (close(out_file_des) < 0)
598 fprintf(stderr, "%s: close %s: %s\n",
599 progname, d->header.c_name, strerror(errno));
600
601 }
602 }
603
604 static void
605 copyin_regular_file(struct new_cpio_header *file_hdr, int in_file_des)
606 {
607 int out_file_des; /* Output file descriptor. */
608
609 /* Can the current file be linked to a previously copied file? */
610 if (file_hdr->c_nlink > 1) {
611 int link_res;
612 if (file_hdr->c_filesize == 0) {
613 /* The newc and crc formats store multiply linked copies
614 of the same file in the archive only once. The
615 actual data is attached to the last link in the
616 archive, and the other links all have a filesize
617 of 0. Since this file has multiple links and a
618 filesize of 0, its data is probably attatched to
619 another file in the archive. Save the link, and
620 process it later when we get the actual data. We
621 can't just create it with length 0 and add the
622 data later, in case the file is readonly. We still
623 lose if its parent directory is readonly (and we aren't
624 running as root), but there's nothing we can do about
625 that. */
626 defer_copyin(file_hdr);
627 tape_toss_input(in_file_des, file_hdr->c_filesize);
628 tape_skip_padding(in_file_des, file_hdr->c_filesize);
629 return;
630 }
631 /* If the file has data (filesize != 0), then presumably
632 any other links have already been defer_copyin'ed(),
633 but GNU cpio version 2.0-2.2 didn't do that, so we
634 still have to check for links here (and also in case
635 the archive was created and later appeneded to). */
636 /* Debian hack: (97/1/2) This was reported by Ronald
637 F. Guilmette to the upstream maintainers. -BEM */
638 link_res = link_to_maj_min_ino(file_hdr->c_name,
639 file_hdr->c_dev_maj,
640 file_hdr->c_dev_min,
641 file_hdr->c_ino);
642 if (link_res == 0) {
643 tape_toss_input(in_file_des, file_hdr->c_filesize);
644 tape_skip_padding(in_file_des, file_hdr->c_filesize);
645 return;
646 }
647 }
648
649 /* If not linked, copy the contents of the file. */
650 out_file_des = open(file_hdr->c_name,
651 O_CREAT | O_WRONLY | O_BINARY, 0600);
652
653 if (out_file_des < 0) {
654 fprintf(stderr, "%s: open %s: %s\n",
655 progname, file_hdr->c_name, strerror(errno));
656 tape_toss_input(in_file_des, file_hdr->c_filesize);
657 tape_skip_padding(in_file_des, file_hdr->c_filesize);
658 return;
659 }
660
661 copy_files_tape_to_disk(in_file_des, out_file_des,
662 file_hdr->c_filesize);
663 disk_empty_output_buffer(out_file_des);
664
665 if (close(out_file_des) < 0)
666 fprintf(stderr, "%s: close %s: %s\n",
667 progname, file_hdr->c_name, strerror(errno));
668
669 /* File is now copied; set attributes. */
670 if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0)
671 && errno != EPERM)
672 fprintf(stderr, "%s: chown %s: %s\n",
673 progname, file_hdr->c_name, strerror(errno));
674
675 /* chown may have turned off some permissions we wanted. */
676 if (chmod(file_hdr->c_name, (int)file_hdr->c_mode) < 0)
677 fprintf(stderr, "%s: chmod %s: %s\n",
678 progname, file_hdr->c_name, strerror(errno));
679
680 tape_skip_padding(in_file_des, file_hdr->c_filesize);
681 if (file_hdr->c_nlink > 1) {
682 /* (see comment above for how the newc and crc formats
683 store multiple links). Now that we have the data
684 for this file, create any other links to it which
685 we defered. */
686 create_defered_links(file_hdr);
687 }
688 }
689
690 /* In general, we can't use the builtin `basename' function if available,
691 since it has different meanings in different environments.
692 In some environments the builtin `basename' modifies its argument.
693
694 Return the address of the last file name component of NAME. If
695 NAME has no file name components because it is all slashes, return
696 NAME if it is empty, the address of its last slash otherwise. */
697
698 static char *base_name(char const *name)
699 {
700 char const *base = name;
701 char const *p;
702
703 for (p = base; *p; p++) {
704 if (ISSLASH(*p)) {
705 /* Treat multiple adjacent slashes like a single slash. */
706 do
707 p++;
708 while (ISSLASH(*p));
709
710 /* If the file name ends in slash, use the trailing slash as
711 the basename if no non-slashes have been found. */
712 if (!*p) {
713 if (ISSLASH(*base))
714 base = p - 1;
715 break;
716 }
717
718 /* *P is a non-slash preceded by a slash. */
719 base = p;
720 }
721 }
722
723 return (char *)base;
724 }
725
726 /* Return the length of of the basename NAME. Typically NAME is the
727 value returned by base_name. Act like strlen (NAME), except omit
728 redundant trailing slashes. */
729
730 static size_t base_len(char const *name)
731 {
732 size_t len;
733
734 for (len = strlen(name); 1 < len && ISSLASH(name[len - 1]); len--)
735 continue;
736
737 return len;
738 }
739
740 /* Remove trailing slashes from PATH.
741 Return true if a trailing slash was removed.
742 This is useful when using filename completion from a shell that
743 adds a "/" after directory names (such as tcsh and bash), because
744 the Unix rename and rmdir system calls return an "Invalid argument" error
745 when given a path that ends in "/" (except for the root directory). */
746
747 static bool strip_trailing_slashes(char *path)
748 {
749 char *base = base_name(path);
750 char *base_lim = base + base_len(base);
751 bool had_slash = (*base_lim != '\0');
752 *base_lim = '\0';
753 return had_slash;
754 }
755
756 static void copyin_directory(struct new_cpio_header *file_hdr, int existing_dir)
757 {
758 int res; /* Result of various function calls. */
759
760 /* Strip any trailing `/'s off the filename; tar puts
761 them on. We might as well do it here in case anybody
762 else does too, since they cause strange things to happen. */
763 strip_trailing_slashes(file_hdr->c_name);
764
765 /* Ignore the current directory. It must already exist,
766 and we don't want to change its permission, ownership
767 or time. */
768 if (file_hdr->c_name[0] == '.' && file_hdr->c_name[1] == '\0') {
769 return;
770 }
771
772 if (!existing_dir)
773 {
774 res = mkdir(file_hdr->c_name, file_hdr->c_mode);
775 } else
776 res = 0;
777 if (res < 0) {
778 /* In some odd cases where the file_hdr->c_name includes `.',
779 the directory may have actually been created by
780 create_all_directories(), so the mkdir will fail
781 because the directory exists. If that's the case,
782 don't complain about it. */
783 struct stat file_stat;
784 if ((errno != EEXIST) ||
785 (lstat(file_hdr->c_name, &file_stat) != 0) ||
786 !(S_ISDIR(file_stat.st_mode))) {
787 fprintf(stderr, "%s: lstat %s: %s\n",
788 progname, file_hdr->c_name, strerror(errno));
789 return;
790 }
791 }
792 if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0)
793 && errno != EPERM)
794 fprintf(stderr, "%s: chown %s: %s\n",
795 progname, file_hdr->c_name, strerror(errno));
796 /* chown may have turned off some permissions we wanted. */
797 if (chmod(file_hdr->c_name, (int)file_hdr->c_mode) < 0)
798 fprintf(stderr, "%s: chmod %s: %s\n",
799 progname, file_hdr->c_name, strerror(errno));
800 }
801
802 static void copyin_device(struct new_cpio_header *file_hdr)
803 {
804 int res; /* Result of various function calls. */
805
806 if (file_hdr->c_nlink > 1) {
807 int link_res;
808 /* Debian hack: This was reported by Horst
809 Knobloch. This bug has been reported to
810 "bug-gnu-utils@prep.ai.mit.edu". (99/1/6) -BEM */
811 link_res = link_to_maj_min_ino(file_hdr->c_name,
812 file_hdr->c_dev_maj,
813 file_hdr->c_dev_min,
814 file_hdr->c_ino);
815 if (link_res == 0) {
816 return;
817 }
818 }
819
820 res = mknod(file_hdr->c_name, file_hdr->c_mode,
821 makedev(file_hdr->c_rdev_maj, file_hdr->c_rdev_min));
822 if (res < 0) {
823 fprintf(stderr, "%s: mknod %s: %s\n", progname,
824 file_hdr->c_name, strerror(errno));
825 return;
826 }
827 if ((chown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0)
828 && errno != EPERM)
829 fprintf(stderr, "%s: chown %s: %s\n", progname,
830 file_hdr->c_name, strerror(errno));
831 /* chown may have turned off some permissions we wanted. */
832 if (chmod(file_hdr->c_name, file_hdr->c_mode) < 0)
833 fprintf(stderr, "%s: chmod %s: %s\n", progname,
834 file_hdr->c_name, strerror(errno));
835 }
836
837 static void copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
838 {
839 char *link_name = NULL; /* Name of hard and symbolic links. */
840 int res; /* Result of various function calls. */
841
842 link_name = (char *)xmalloc((unsigned int)file_hdr->c_filesize + 1);
843 link_name[file_hdr->c_filesize] = '\0';
844 tape_buffered_read(link_name, in_file_des, file_hdr->c_filesize);
845 tape_skip_padding(in_file_des, file_hdr->c_filesize);
846
847 res = symlink(link_name, file_hdr->c_name);
848 if (res < 0) {
849 fprintf(stderr, "%s: symlink %s: %s\n",
850 progname, file_hdr->c_name, strerror(errno));
851 free(link_name);
852 return;
853 }
854 if ((lchown(file_hdr->c_name, file_hdr->c_uid, file_hdr->c_gid) < 0)
855 && errno != EPERM) {
856 fprintf(stderr, "%s: lchown %s: %s\n",
857 progname, file_hdr->c_name, strerror(errno));
858 }
859 free(link_name);
860 }
861
862 static void copyin_file(struct new_cpio_header *file_hdr, int in_file_des)
863 {
864 int existing_dir;
865
866 if (try_existing_file(file_hdr, in_file_des, &existing_dir) < 0)
867 return;
868
869 /* Do the real copy or link. */
870 switch (file_hdr->c_mode & S_IFMT) {
871 case S_IFREG:
872 copyin_regular_file(file_hdr, in_file_des);
873 break;
874
875 case S_IFDIR:
876 copyin_directory(file_hdr, existing_dir);
877 break;
878
879 case S_IFCHR:
880 case S_IFBLK:
881 case S_IFSOCK:
882 case S_IFIFO:
883 copyin_device(file_hdr);
884 break;
885
886 case S_IFLNK:
887 copyin_link(file_hdr, in_file_des);
888 break;
889
890 default:
891 fprintf(stderr, "%s: %s: unknown file type\n",
892 progname, file_hdr->c_name);
893 tape_toss_input(in_file_des, file_hdr->c_filesize);
894 tape_skip_padding(in_file_des, file_hdr->c_filesize);
895 }
896 }
897
898 /* Fill in FILE_HDR by reading a new-format ASCII format cpio header from
899 file descriptor IN_DES, except for the magic number, which is
900 already filled in. */
901
902 static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des)
903 {
904 char ascii_header[13*8], *ah, hexbuf[9];
905 int i;
906
907 tape_buffered_read(ascii_header, in_des, 13*8);
908 ah = ascii_header;
909 hexbuf[8] = '\0';
910 for (i = 0; i < 13; i++) {
911 memcpy(hexbuf, ah, 8);
912 file_hdr->c_hdr[i] = strtoul(hexbuf, NULL, 16);
913 ah += 8;
914 }
915 /* Read file name from input. */
916 free(file_hdr->c_name);
917 file_hdr->c_name = (char *)xmalloc(file_hdr->c_namesize);
918 tape_buffered_read(file_hdr->c_name, in_des,
919 (long)file_hdr->c_namesize);
920
921 /* In SVR4 ASCII format, the amount of space allocated for the header
922 is rounded up to the next long-word, so we might need to drop
923 1-3 bytes. */
924 tape_skip_padding(in_des, file_hdr->c_namesize + 110);
925 }
926
927 /* Return 16-bit integer I with the bytes swapped. */
928 #define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
929
930 /* Read the header, including the name of the file, from file
931 descriptor IN_DES into FILE_HDR. */
932
933 static void read_in_header(struct new_cpio_header *file_hdr, int in_des)
934 {
935 long bytes_skipped = 0; /* Bytes of junk found before magic number. */
936
937 /* Search for a valid magic number. */
938
939 file_hdr->c_tar_linkname = NULL;
940
941 tape_buffered_read((char *)file_hdr, in_des, 6L);
942 while (1) {
943 if (!strncmp((char *)file_hdr, "070702", 6)
944 || !strncmp((char *)file_hdr, "070701", 6))
945 {
946 if (bytes_skipped > 0)
947 warn_junk_bytes(bytes_skipped);
948
949 read_in_new_ascii(file_hdr, in_des);
950 break;
951 }
952 bytes_skipped++;
953 memmove((char *)file_hdr, (char *)file_hdr + 1, 5);
954 tape_buffered_read((char *)file_hdr + 5, in_des, 1L);
955 }
956 }
957
958 /* Read the collection from standard input and create files
959 in the file system. */
960
961 static void process_copy_in(void)
962 {
963 char done = false; /* True if trailer reached. */
964 struct new_cpio_header file_hdr; /* Output header information. */
965 int in_file_des; /* Input file descriptor. */
966
967 /* Initialize the copy in. */
968 file_hdr.c_name = NULL;
969
970 /* only from stdin */
971 in_file_des = 0;
972
973 /* While there is more input in the collection, process the input. */
974 while (!done) {
975 /* Start processing the next file by reading the header. */
976 read_in_header(&file_hdr, in_file_des);
977
978 /* Is this the header for the TRAILER file? */
979 if (strcmp("TRAILER!!!", file_hdr.c_name) == 0) {
980 done = true;
981 break;
982 }
983
984 /* Copy the input file into the directory structure. */
985
986 copyin_file(&file_hdr, in_file_des);
987
988 if (dot_flag)
989 fputc('.', stderr);
990 }
991
992 if (dot_flag)
993 fputc('\n', stderr);
994
995 create_final_defers();
996
997 }
998
999 /* Initialize the input and output buffers to their proper size and
1000 initialize all variables associated with the input and output
1001 buffers. */
1002
1003 static void initialize_buffers(void)
1004 {
1005 int in_buf_size, out_buf_size;
1006
1007 /* Make sure the input buffer can always hold 2 blocks and that it
1008 is big enough to hold 1 tar record (512 bytes) even if it
1009 is not aligned on a block boundary. The extra buffer space
1010 is needed by process_copyin and peek_in_buf to automatically
1011 figure out what kind of archive it is reading. */
1012 if (io_block_size >= 512)
1013 in_buf_size = 2 * io_block_size;
1014 else
1015 in_buf_size = 1024;
1016 out_buf_size = DISK_IO_BLOCK_SIZE;
1017
1018 input_buffer = (char *)xmalloc(in_buf_size);
1019 in_buff = input_buffer;
1020 input_buffer_size = in_buf_size;
1021 input_size = 0;
1022 input_bytes = 0;
1023
1024 output_buffer = (char *)xmalloc(out_buf_size);
1025 out_buff = output_buffer;
1026 output_size = 0;
1027 output_bytes = 0;
1028
1029 }
1030
1031 int main(int argc, char *argv[])
1032 {
1033 int c;
1034 int extract_flag = false;
1035
1036 progname = argv[0];
1037
1038 do {
1039 c = getopt(argc, argv, "iV");
1040 if (c == EOF)
1041 break;
1042 switch (c) {
1043 case 'V':
1044 dot_flag = true;
1045 break;
1046
1047 case 'i':
1048 extract_flag = true;
1049 break;
1050 case '?':
1051 fprintf(stderr,
1052 "%s: not implemented or invalid option -%c\n",
1053 progname, optopt);
1054 exit(1);
1055
1056 }
1057 } while (1);
1058
1059 if (extract_flag) {
1060 initialize_buffers();
1061
1062 process_copy_in();
1063 } else {
1064 fprintf(stderr, "Usage: %s [-V] -i [< archive]\n", progname);
1065 exit(1);
1066 }
1067
1068 return 0;
1069 }