Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 32979 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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