This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / gnu / usr.bin / cpio / copyin.c
CommitLineData
78ed81a3 1/* copyin.c - extract or list a cpio archive
2 Copyright (C) 1990, 1991, 1992 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
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18#include <stdio.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include "filetypes.h"
22#include "system.h"
23#include "cpiohdr.h"
24#include "dstring.h"
25#include "extern.h"
26#include "defer.h"
27#include "rmt.h"
28#ifndef FNM_PATHNAME
29#include <fnmatch.h>
30#endif
31
32#ifndef HAVE_LCHOWN
33#define lchown chown
34#endif
35
36static void read_pattern_file ();
37static void skip_padding ();
38static void defer_copyin ();
39static void create_defered_links ();
40static void create_final_defers ();
41
42/* Return 16-bit integer I with the bytes swapped. */
43#define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff))
44
45/* Read the header, including the name of the file, from file
46 descriptor IN_DES into FILE_HDR. */
47
48void
49read_in_header (file_hdr, in_des)
50 struct new_cpio_header *file_hdr;
51 int in_des;
52{
53 long bytes_skipped = 0; /* Bytes of junk found before magic number. */
54
55 /* Search for a valid magic number. */
56
57 if (archive_format == arf_unknown)
58 {
59 char tmpbuf[512];
60 int check_tar;
61 int peeked_bytes;
62
63 while (archive_format == arf_unknown)
64 {
65 peeked_bytes = peek_in_buf (tmpbuf, in_des, 512);
66 if (peeked_bytes < 6)
67 error (1, 0, "premature end of archive");
68
69 if (!strncmp (tmpbuf, "070701", 6))
70 archive_format = arf_newascii;
71 else if (!strncmp (tmpbuf, "070707", 6))
72 archive_format = arf_oldascii;
73 else if (!strncmp (tmpbuf, "070702", 6))
74 {
75 archive_format = arf_crcascii;
76 crc_i_flag = TRUE;
77 }
78 else if ((*((unsigned short *) tmpbuf) == 070707) ||
79 (*((unsigned short *) tmpbuf) == swab_short ((unsigned short) 070707)))
80 archive_format = arf_binary;
81 else if (peeked_bytes >= 512
82 && (check_tar = is_tar_header (tmpbuf)))
83 {
84 if (check_tar == 2)
85 archive_format = arf_ustar;
86 else
87 archive_format = arf_tar;
88 }
89 else
90 {
91 copy_in_buf ((char *) tmpbuf, in_des, 1L);
92 ++bytes_skipped;
93 }
94 }
95 }
96
97 if (archive_format == arf_tar || archive_format == arf_ustar)
98 {
99 if (append_flag)
100 last_header_start = input_bytes - io_block_size +
101 (in_buff - input_buffer);
102 if (bytes_skipped > 0)
103 error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
104 read_in_tar_header (file_hdr, in_des);
105 return;
106 }
107
108 file_hdr->c_tar_linkname = NULL;
109
110 copy_in_buf ((char *) file_hdr, in_des, 6L);
111 while (1)
112 {
113 if (append_flag)
114 last_header_start = input_bytes - io_block_size
115 + (in_buff - input_buffer) - 6;
116 if (archive_format == arf_newascii
117 && !strncmp ((char *) file_hdr, "070701", 6))
118 {
119 if (bytes_skipped > 0)
120 error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
121 read_in_new_ascii (file_hdr, in_des);
122 break;
123 }
124 if (archive_format == arf_crcascii
125 && !strncmp ((char *) file_hdr, "070702", 6))
126 {
127 if (bytes_skipped > 0)
128 error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
129 read_in_new_ascii (file_hdr, in_des);
130 break;
131 }
132 if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
133 && !strncmp ((char *) file_hdr, "070707", 6))
134 {
135 if (bytes_skipped > 0)
136 error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
137 read_in_old_ascii (file_hdr, in_des);
138 break;
139 }
140 if ( (archive_format == arf_binary || archive_format == arf_hpbinary)
141 && (file_hdr->c_magic == 070707
142 || file_hdr->c_magic == swab_short ((unsigned short) 070707)))
143 {
144 /* Having to skip 1 byte because of word alignment is normal. */
145 if (bytes_skipped > 0)
146 error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped);
147 read_in_binary (file_hdr, in_des);
148 break;
149 }
150 bytes_skipped++;
151 bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5);
152 copy_in_buf ((char *) file_hdr + 5, in_des, 1L);
153 }
154}
155
156/* Fill in FILE_HDR by reading an old-format ASCII format cpio header from
157 file descriptor IN_DES, except for the magic number, which is
158 already filled in. */
159
160void
161read_in_old_ascii (file_hdr, in_des)
162 struct new_cpio_header *file_hdr;
163 int in_des;
164{
165 char ascii_header[78];
166 unsigned long dev;
167 unsigned long rdev;
168
169 copy_in_buf (ascii_header, in_des, 70L);
170 ascii_header[70] = '\0';
171 sscanf (ascii_header,
172 "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
173 &dev, &file_hdr->c_ino,
174 &file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid,
175 &file_hdr->c_nlink, &rdev, &file_hdr->c_mtime,
176 &file_hdr->c_namesize, &file_hdr->c_filesize);
177 file_hdr->c_dev_maj = major (dev);
178 file_hdr->c_dev_min = minor (dev);
179 file_hdr->c_rdev_maj = major (rdev);
180 file_hdr->c_rdev_min = minor (rdev);
181
182 /* Read file name from input. */
183 if (file_hdr->c_name != NULL)
184 free (file_hdr->c_name);
185 file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize + 1);
186 copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
187#ifndef __MSDOS__
188 /* HP/UX cpio creates archives that look just like ordinary archives,
189 but for devices it sets major = 0, minor = 1, and puts the
190 actual major/minor number in the filesize field. See if this
191 is an HP/UX cpio archive, and if so fix it. We have to do this
192 here because process_copy_in() assumes filesize is always 0
193 for devices. */
194 switch (file_hdr->c_mode & CP_IFMT)
195 {
196 case CP_IFCHR:
197 case CP_IFBLK:
198#ifdef CP_IFSOCK
199 case CP_IFSOCK:
200#endif
201#ifdef CP_IFIFO
202 case CP_IFIFO:
203#endif
204 if (file_hdr->c_filesize != 0
205 && file_hdr->c_rdev_maj == 0
206 && file_hdr->c_rdev_min == 1)
207 {
208 file_hdr->c_rdev_maj = major (file_hdr->c_filesize);
209 file_hdr->c_rdev_min = minor (file_hdr->c_filesize);
210 file_hdr->c_filesize = 0;
211 }
212 break;
213 default:
214 break;
215 }
216#endif /* __MSDOS__ */
217}
218
219/* Fill in FILE_HDR by reading a new-format ASCII format cpio header from
220 file descriptor IN_DES, except for the magic number, which is
221 already filled in. */
222
223void
224read_in_new_ascii (file_hdr, in_des)
225 struct new_cpio_header *file_hdr;
226 int in_des;
227{
228 char ascii_header[112];
229
230 copy_in_buf (ascii_header, in_des, 104L);
231 ascii_header[104] = '\0';
232 sscanf (ascii_header,
233 "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
234 &file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid,
235 &file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime,
236 &file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min,
237 &file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize,
238 &file_hdr->c_chksum);
239 /* Read file name from input. */
240 if (file_hdr->c_name != NULL)
241 free (file_hdr->c_name);
242 file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
243 copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
244
245 /* In SVR4 ASCII format, the amount of space allocated for the header
246 is rounded up to the next long-word, so we might need to drop
247 1-3 bytes. */
248 skip_padding (in_des, file_hdr->c_namesize + 110);
249}
250
251/* Fill in FILE_HDR by reading a binary format cpio header from
252 file descriptor IN_DES, except for the first 6 bytes (the magic
253 number, device, and inode number), which are already filled in. */
254
255void
256read_in_binary (file_hdr, in_des)
257 struct new_cpio_header *file_hdr;
258 int in_des;
259{
260 struct old_cpio_header short_hdr;
261
262 /* Copy the data into the short header, then later transfer
263 it into the argument long header. */
264 short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev;
265 short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino;
266 copy_in_buf (((char *) &short_hdr) + 6, in_des, 20L);
267
268 /* If the magic number is byte swapped, fix the header. */
269 if (file_hdr->c_magic == swab_short ((unsigned short) 070707))
270 {
271 static int warned = 0;
272
273 /* Alert the user that they might have to do byte swapping on
274 the file contents. */
275 if (warned == 0)
276 {
277 error (0, 0, "warning: archive header has reverse byte-order");
278 warned = 1;
279 }
280 swab_array ((char *) &short_hdr, 13);
281 }
282
283 file_hdr->c_dev_maj = major (short_hdr.c_dev);
284 file_hdr->c_dev_min = minor (short_hdr.c_dev);
285 file_hdr->c_ino = short_hdr.c_ino;
286 file_hdr->c_mode = short_hdr.c_mode;
287 file_hdr->c_uid = short_hdr.c_uid;
288 file_hdr->c_gid = short_hdr.c_gid;
289 file_hdr->c_nlink = short_hdr.c_nlink;
290 file_hdr->c_rdev_maj = major (short_hdr.c_rdev);
291 file_hdr->c_rdev_min = minor (short_hdr.c_rdev);
292 file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16
293 | short_hdr.c_mtimes[1];
294
295 file_hdr->c_namesize = short_hdr.c_namesize;
296 file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16
297 | short_hdr.c_filesizes[1];
298
299 /* Read file name from input. */
300 if (file_hdr->c_name != NULL)
301 free (file_hdr->c_name);
302 file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize);
303 copy_in_buf (file_hdr->c_name, in_des, (long) file_hdr->c_namesize);
304
305 /* In binary mode, the amount of space allocated in the header for
306 the filename is `c_namesize' rounded up to the next short-word,
307 so we might need to drop a byte. */
308 if (file_hdr->c_namesize % 2)
309 toss_input (in_des, 1L);
310
311#ifndef __MSDOS__
312 /* HP/UX cpio creates archives that look just like ordinary archives,
313 but for devices it sets major = 0, minor = 1, and puts the
314 actual major/minor number in the filesize field. See if this
315 is an HP/UX cpio archive, and if so fix it. We have to do this
316 here because process_copy_in() assumes filesize is always 0
317 for devices. */
318 switch (file_hdr->c_mode & CP_IFMT)
319 {
320 case CP_IFCHR:
321 case CP_IFBLK:
322#ifdef CP_IFSOCK
323 case CP_IFSOCK:
324#endif
325#ifdef CP_IFIFO
326 case CP_IFIFO:
327#endif
328 if (file_hdr->c_filesize != 0
329 && file_hdr->c_rdev_maj == 0
330 && file_hdr->c_rdev_min == 1)
331 {
332 file_hdr->c_rdev_maj = major (file_hdr->c_filesize);
333 file_hdr->c_rdev_min = minor (file_hdr->c_filesize);
334 file_hdr->c_filesize = 0;
335 }
336 break;
337 default:
338 break;
339 }
340#endif /* __MSDOS__ */
341}
342
343/* Exchange the bytes of each element of the array of COUNT shorts
344 starting at PTR. */
345
346void
347swab_array (ptr, count)
348 char *ptr;
349 int count;
350{
351 char tmp;
352
353 while (count-- > 0)
354 {
355 tmp = *ptr;
356 *ptr = *(ptr + 1);
357 ++ptr;
358 *ptr = tmp;
359 ++ptr;
360 }
361}
362
363/* Current time for verbose table. */
364static time_t current_time;
365
366/* Read the collection from standard input and create files
367 in the file system. */
368
369void
370process_copy_in ()
371{
372 char done = FALSE; /* True if trailer reached. */
373 int res; /* Result of various function calls. */
374 dynamic_string new_name; /* New file name for rename option. */
375 FILE *tty_in; /* Interactive file for rename option. */
376 FILE *tty_out; /* Interactive file for rename option. */
377 char *str_res; /* Result for string function. */
378 struct utimbuf times; /* For setting file times. */
379 struct stat file_stat; /* Output file stat record. */
380 struct new_cpio_header file_hdr; /* Output header information. */
381 int out_file_des; /* Output file descriptor. */
382 int in_file_des; /* Input file descriptor. */
383 char skip_file; /* Flag for use with patterns. */
384 int existing_dir; /* True if file is a dir & already exists. */
385 int i; /* Loop index variable. */
386 char *link_name = NULL; /* Name of hard and symbolic links. */
387#ifdef HPUX_CDF
388 int cdf_flag; /* True if file is a CDF. */
389 int cdf_char; /* Index of `+' char indicating a CDF. */
390#endif
391
392 /* Initialize the copy in. */
393 if (pattern_file_name)
394 read_pattern_file ();
395 file_hdr.c_name = NULL;
396 ds_init (&new_name, 128);
397 /* Initialize this in case it has members we don't know to set. */
398 bzero (&times, sizeof (struct utimbuf));
399
400 /* Open interactive file pair for rename operation. */
401 if (rename_flag)
402 {
403 tty_in = fopen (CONSOLE, "r");
404 if (tty_in == NULL)
405 error (2, errno, CONSOLE);
406 tty_out = fopen (CONSOLE, "w");
407 if (tty_out == NULL)
408 error (2, errno, CONSOLE);
409 }
410
411 /* Get date and time if needed for processing the table option. */
412 if (table_flag && verbose_flag)
413 time (&current_time);
414
415#ifdef __MSDOS__
416 setmode (archive_des, O_BINARY);
417#endif
418 /* Check whether the input file might be a tape. */
419 in_file_des = archive_des;
420 if (_isrmt (in_file_des))
421 {
422 input_is_special = 1;
423 input_is_seekable = 0;
424 }
425 else
426 {
427 if (fstat (in_file_des, &file_stat))
428 error (1, errno, "standard input is closed");
429 input_is_special =
430#ifdef S_ISBLK
431 S_ISBLK (file_stat.st_mode) ||
432#endif
433 S_ISCHR (file_stat.st_mode);
434 input_is_seekable = S_ISREG (file_stat.st_mode);
435 }
436 output_is_seekable = TRUE;
437
438 /* While there is more input in the collection, process the input. */
439 while (!done)
440 {
441 link_name = NULL;
442 swapping_halfwords = swapping_bytes = FALSE;
443
444 /* Start processing the next file by reading the header. */
445 read_in_header (&file_hdr, in_file_des);
446
447#ifdef DEBUG_CPIO
448 if (debug_flag)
449 {
450 struct new_cpio_header *h;
451 h = &file_hdr;
452 fprintf (stderr,
453 "magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n",
454 h->c_magic, h->c_ino, h->c_mode, h->c_uid, h->c_gid);
455 fprintf (stderr,
456 "nlink = %d, mtime = %d, filesize = %d, dev_maj = 0x%x\n",
457 h->c_nlink, h->c_mtime, h->c_filesize, h->c_dev_maj);
458 fprintf (stderr,
459 "dev_min = 0x%x, rdev_maj = 0x%x, rdev_min = 0x%x, namesize = %d\n",
460 h->c_dev_min, h->c_rdev_maj, h->c_rdev_min, h->c_namesize);
461 fprintf (stderr,
462 "chksum = %d, name = \"%s\", tar_linkname = \"%s\"\n",
463 h->c_chksum, h->c_name,
464 h->c_tar_linkname ? h->c_tar_linkname : "(null)" );
465
466 }
467#endif
468 /* Is this the header for the TRAILER file? */
469 if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0)
470 {
471 done = TRUE;
472 break;
473 }
474
475 /* Does the file name match one of the given patterns? */
476 if (num_patterns <= 0)
477 skip_file = FALSE;
478 else
479 {
480 skip_file = copy_matching_files;
481 for (i = 0; i < num_patterns
482 && skip_file == copy_matching_files; i++)
483 {
484 if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0)
485 skip_file = !copy_matching_files;
486 }
487 }
488
489 if (skip_file)
490 {
491 toss_input (in_file_des, file_hdr.c_filesize);
492 skip_padding (in_file_des, file_hdr.c_filesize);
493 }
494 else if (table_flag)
495 {
496 if (verbose_flag)
497 {
498#ifdef CP_IFLNK
499 if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK)
500 {
501 if (archive_format != arf_tar && archive_format != arf_ustar)
502 {
503 link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
504 link_name[file_hdr.c_filesize] = '\0';
505 copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
506 long_format (&file_hdr, link_name);
507 free (link_name);
508 skip_padding (in_file_des, file_hdr.c_filesize);
509 continue;
510 }
511 else
512 {
513 long_format (&file_hdr, file_hdr.c_tar_linkname);
514 continue;
515 }
516 }
517 else
518#endif
519 long_format (&file_hdr, (char *) 0);
520 }
521 else
522 printf ("%s\n", file_hdr.c_name);
523
524 toss_input (in_file_des, file_hdr.c_filesize);
525 skip_padding (in_file_des, file_hdr.c_filesize);
526 }
527 else if (append_flag)
528 {
529 toss_input (in_file_des, file_hdr.c_filesize);
530 skip_padding (in_file_des, file_hdr.c_filesize);
531 }
532 else
533 {
534 /* Copy the input file into the directory structure. */
535
536 /* Do we need to rename the file? */
537 if (rename_flag)
538 {
539 fprintf (tty_out, "rename %s -> ", file_hdr.c_name);
540 fflush (tty_out);
541 str_res = ds_fgets (tty_in, &new_name);
542 if (str_res == NULL || str_res[0] == 0)
543 {
544 toss_input (in_file_des, file_hdr.c_filesize);
545 skip_padding (in_file_des, file_hdr.c_filesize);
546 continue;
547 }
548 else
549 file_hdr.c_name = xstrdup (new_name.ds_string);
550 }
551
552 /* See if the file already exists. */
553 existing_dir = FALSE;
554 if (lstat (file_hdr.c_name, &file_stat) == 0)
555 {
556 if (S_ISDIR (file_stat.st_mode)
557 && ((file_hdr.c_mode & CP_IFMT) == CP_IFDIR))
558 {
559 /* If there is already a directory there that
560 we are trying to create, don't complain about
561 it. */
562 existing_dir = TRUE;
563 }
564 else if (!unconditional_flag
565 && file_hdr.c_mtime <= file_stat.st_mtime)
566 {
567 error (0, 0, "%s not created: newer or same age version exists",
568 file_hdr.c_name);
569 toss_input (in_file_des, file_hdr.c_filesize);
570 skip_padding (in_file_des, file_hdr.c_filesize);
571 continue; /* Go to the next file. */
572 }
573 else if (S_ISDIR (file_stat.st_mode)
574 ? rmdir (file_hdr.c_name)
575 : unlink (file_hdr.c_name))
576 {
577 error (0, errno, "cannot remove current %s",
578 file_hdr.c_name);
579 toss_input (in_file_des, file_hdr.c_filesize);
580 skip_padding (in_file_des, file_hdr.c_filesize);
581 continue; /* Go to the next file. */
582 }
583 }
584
585 /* Do the real copy or link. */
586 switch (file_hdr.c_mode & CP_IFMT)
587 {
588 case CP_IFREG:
589#ifndef __MSDOS__
590 /* Can the current file be linked to a previously copied file? */
591 if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
592 || archive_format == arf_crcascii) )
593 {
594 int link_res;
595 if (file_hdr.c_filesize == 0)
596 {
597 /* The newc and crc formats store multiply linked copies
598 of the same file in the archive only once. The
599 actual data is attached to the last link in the
600 archive, and the other links all have a filesize
601 of 0. Since this file has multiple links and a
602 filesize of 0, its data is probably attatched to
603 another file in the archive. Save the link, and
604 process it later when we get the actual data. We
605 can't just create it with length 0 and add the
606 data later, in case the file is readonly. We still
607 lose if its parent directory is readonly (and we aren't
608 running as root), but there's nothing we can do about
609 that. */
610 defer_copyin (&file_hdr);
611 toss_input (in_file_des, file_hdr.c_filesize);
612 skip_padding (in_file_des, file_hdr.c_filesize);
613 break;
614 }
615 /* If the file has data (filesize != 0), then presumably
616 any other links have already been defer_copyin'ed(),
617 but GNU cpio version 2.0-2.2 didn't do that, so we
618 still have to check for links here (and also in case
619 the archive was created and later appeneded to). */
620 link_res = link_to_maj_min_ino (file_hdr.c_name,
621 file_hdr.c_dev_maj, file_hdr.c_dev_maj,
622 file_hdr.c_ino);
623 if (link_res == 0)
624 {
625 toss_input (in_file_des, file_hdr.c_filesize);
626 skip_padding (in_file_des, file_hdr.c_filesize);
627 break;
628 }
629 }
630 else if (file_hdr.c_nlink > 1 && archive_format != arf_tar
631 && archive_format != arf_ustar)
632 {
633 int link_res;
634 link_res = link_to_maj_min_ino (file_hdr.c_name,
635 file_hdr.c_dev_maj, file_hdr.c_dev_maj,
636 file_hdr.c_ino);
637 if (link_res == 0)
638 {
639 toss_input (in_file_des, file_hdr.c_filesize);
640 skip_padding (in_file_des, file_hdr.c_filesize);
641 break;
642 }
643 }
644 else if ((archive_format == arf_tar || archive_format == arf_ustar)
645 && file_hdr.c_tar_linkname &&
646 file_hdr.c_tar_linkname[0] != '\0')
647 {
648 int link_res;
649 link_res = link_to_name (file_hdr.c_name,
650 file_hdr.c_tar_linkname);
651 if (link_res < 0)
652 {
653 error (0, errno, "cannot link %s to %s",
654 file_hdr.c_tar_linkname, file_hdr.c_name);
655 }
656 break;
657 }
658#endif
659
660 /* If not linked, copy the contents of the file. */
661 if (link_name == NULL)
662 {
663 out_file_des = open (file_hdr.c_name,
664 O_CREAT | O_WRONLY | O_BINARY, 0600);
665 if (out_file_des < 0 && create_dir_flag)
666 {
667 create_all_directories (file_hdr.c_name);
668 out_file_des = open (file_hdr.c_name,
669 O_CREAT | O_WRONLY | O_BINARY,
670 0600);
671 }
672 if (out_file_des < 0)
673 {
674 error (0, errno, "%s", file_hdr.c_name);
675 toss_input (in_file_des, file_hdr.c_filesize);
676 skip_padding (in_file_des, file_hdr.c_filesize);
677 continue;
678 }
679
680 crc = 0;
681 if (swap_halfwords_flag)
682 {
683 if ((file_hdr.c_filesize % 4) == 0)
684 swapping_halfwords = TRUE;
685 else
686 error (0, 0, "cannot swap halfwords of %s: odd number of halfwords",
687 file_hdr.c_name);
688 }
689 if (swap_bytes_flag)
690 {
691 if ((file_hdr.c_filesize % 2) == 0)
692 swapping_bytes = TRUE;
693 else
694 error (0, 0, "cannot swap bytes of %s: odd number of bytes",
695 file_hdr.c_name);
696 }
697 copy_files (in_file_des, out_file_des, file_hdr.c_filesize);
698 empty_output_buffer (out_file_des);
699 if (close (out_file_des) < 0)
700 error (0, errno, "%s", file_hdr.c_name);
701
702 if (archive_format == arf_crcascii)
703 {
704 if (crc != file_hdr.c_chksum)
705 error (0, 0, "%s: checksum error (0x%x, should be 0x%x)",
706 file_hdr.c_name, crc, file_hdr.c_chksum);
707 }
708 /* File is now copied; set attributes. */
709 if (!no_chown_flag)
710 if ((chown (file_hdr.c_name,
711 set_owner_flag ? set_owner : file_hdr.c_uid,
712 set_group_flag ? set_group : file_hdr.c_gid) < 0)
713 && errno != EPERM)
714 error (0, errno, "%s", file_hdr.c_name);
715 /* chown may have turned off some permissions we wanted. */
716 if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
717 error (0, errno, "%s", file_hdr.c_name);
718 if (retain_time_flag)
719 {
720 times.actime = times.modtime = file_hdr.c_mtime;
721 if (utime (file_hdr.c_name, &times) < 0)
722 error (0, errno, "%s", file_hdr.c_name);
723 }
724 skip_padding (in_file_des, file_hdr.c_filesize);
725 if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
726 || archive_format == arf_crcascii) )
727 {
728 /* (see comment above for how the newc and crc formats
729 store multiple links). Now that we have the data
730 for this file, create any other links to it which
731 we defered. */
732 create_defered_links (&file_hdr);
733 }
734 }
735 break;
736
737 case CP_IFDIR:
738 /* Strip any trailing `/'s off the filename; tar puts
739 them on. We might as well do it here in case anybody
740 else does too, since they cause strange things to happen. */
741 strip_trailing_slashes (file_hdr.c_name);
742
743 /* Ignore the current directory. It must already exist,
744 and we don't want to change its permission, ownership
745 or time. */
746 if (file_hdr.c_name[0] == '.' && file_hdr.c_name[1] == '\0')
747 break;
748
749#ifdef HPUX_CDF
750 cdf_flag = 0;
751#endif
752 if (!existing_dir)
753
754 {
755#ifdef HPUX_CDF
756 /* If the directory name ends in a + and is SUID,
757 then it is a CDF. Strip the trailing + from
758 the name before creating it. */
759 cdf_char = strlen (file_hdr.c_name) - 1;
760 if ( (cdf_char > 0) &&
761 (file_hdr.c_mode & 04000) &&
762 (file_hdr.c_name [cdf_char] == '+') )
763 {
764 file_hdr.c_name [cdf_char] = '\0';
765 cdf_flag = 1;
766 }
767#endif
768 res = mkdir (file_hdr.c_name, file_hdr.c_mode);
769 }
770 else
771 res = 0;
772 if (res < 0 && create_dir_flag)
773 {
774 create_all_directories (file_hdr.c_name);
775 res = mkdir (file_hdr.c_name, file_hdr.c_mode);
776 }
777 if (res < 0)
778 {
779 error (0, errno, "%s", file_hdr.c_name);
780 continue;
781 }
782 if (!no_chown_flag)
783 if ((chown (file_hdr.c_name,
784 set_owner_flag ? set_owner : file_hdr.c_uid,
785 set_group_flag ? set_group : file_hdr.c_gid) < 0)
786 && errno != EPERM)
787 error (0, errno, "%s", file_hdr.c_name);
788 /* chown may have turned off some permissions we wanted. */
789 if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0)
790 error (0, errno, "%s", file_hdr.c_name);
791#ifdef HPUX_CDF
792 if (cdf_flag)
793 /* Once we "hide" the directory with the chmod(),
794 we have to refer to it using name+ instead of name. */
795 file_hdr.c_name [cdf_char] = '+';
796#endif
797 if (retain_time_flag)
798 {
799 times.actime = times.modtime = file_hdr.c_mtime;
800 if (utime (file_hdr.c_name, &times) < 0)
801 error (0, errno, "%s", file_hdr.c_name);
802 }
803 break;
804
805#ifndef __MSDOS__
806 case CP_IFCHR:
807 case CP_IFBLK:
808#ifdef CP_IFSOCK
809 case CP_IFSOCK:
810#endif
811#ifdef CP_IFIFO
812 case CP_IFIFO:
813#endif
814 if (file_hdr.c_nlink > 1 && archive_format != arf_tar
815 && archive_format != arf_ustar)
816 {
817 int link_res;
818 link_res = link_to_maj_min_ino (file_hdr.c_name,
819 file_hdr.c_dev_maj, file_hdr.c_dev_maj,
820 file_hdr.c_ino);
821 if (link_res == 0)
822 break;
823 }
824 else if (archive_format == arf_ustar &&
825 file_hdr.c_tar_linkname &&
826 file_hdr.c_tar_linkname [0] != '\0')
827 {
828 int link_res;
829 link_res = link_to_name (file_hdr.c_name,
830 file_hdr.c_tar_linkname);
831 if (link_res < 0)
832 {
833 error (0, errno, "cannot link %s to %s",
834 file_hdr.c_tar_linkname, file_hdr.c_name);
835 /* Something must be wrong, because we couldn't
836 find the file to link to. But can we assume
837 that the device maj/min numbers are correct
838 and fall through to the mknod? It's probably
839 safer to just break, rather than possibly
840 creating a bogus device file. */
841 }
842 break;
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 && create_dir_flag)
848 {
849 create_all_directories (file_hdr.c_name);
850 res = mknod (file_hdr.c_name, file_hdr.c_mode,
851 makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min));
852 }
853 if (res < 0)
854 {
855 error (0, errno, "%s", file_hdr.c_name);
856 continue;
857 }
858 if (!no_chown_flag)
859 if ((chown (file_hdr.c_name,
860 set_owner_flag ? set_owner : file_hdr.c_uid,
861 set_group_flag ? set_group : file_hdr.c_gid) < 0)
862 && errno != EPERM)
863 error (0, errno, "%s", file_hdr.c_name);
864 /* chown may have turned off some permissions we wanted. */
865 if (chmod (file_hdr.c_name, file_hdr.c_mode) < 0)
866 error (0, errno, "%s", file_hdr.c_name);
867 if (retain_time_flag)
868 {
869 times.actime = times.modtime = file_hdr.c_mtime;
870 if (utime (file_hdr.c_name, &times) < 0)
871 error (0, errno, "%s", file_hdr.c_name);
872 }
873 break;
874#endif
875
876#ifdef CP_IFLNK
877 case CP_IFLNK:
878 {
879 if (archive_format != arf_tar && archive_format != arf_ustar)
880 {
881 link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
882 link_name[file_hdr.c_filesize] = '\0';
883 copy_in_buf (link_name, in_file_des, file_hdr.c_filesize);
884 skip_padding (in_file_des, file_hdr.c_filesize);
885 }
886 else
887 {
888 link_name = xstrdup (file_hdr.c_tar_linkname);
889 }
890
891 res = UMASKED_SYMLINK (link_name, file_hdr.c_name,
892 file_hdr.c_mode);
893 if (res < 0 && create_dir_flag)
894 {
895 create_all_directories (file_hdr.c_name);
896 res = UMASKED_SYMLINK (link_name, file_hdr.c_name,
897 file_hdr.c_mode);
898 }
899 if (res < 0)
900 {
901 error (0, errno, "%s", file_hdr.c_name);
902 free (link_name);
903 link_name = NULL;
904 continue;
905 }
906 if (!no_chown_flag)
907 if ((lchown (file_hdr.c_name,
908 set_owner_flag ? set_owner : file_hdr.c_uid,
909 set_group_flag ? set_group : file_hdr.c_gid) < 0)
910 && errno != EPERM)
911 error (0, errno, "%s", file_hdr.c_name);
912 free (link_name);
913 link_name = NULL;
914 }
915 break;
916#endif
917
918 default:
919 error (0, 0, "%s: unknown file type", file_hdr.c_name);
920 toss_input (in_file_des, file_hdr.c_filesize);
921 skip_padding (in_file_des, file_hdr.c_filesize);
922 }
923
924 if (verbose_flag)
925 fprintf (stderr, "%s\n", file_hdr.c_name);
926 if (dot_flag)
927 fputc ('.', stderr);
928 }
929 }
930
931 if (dot_flag)
932 fputc ('\n', stderr);
933
934 if (append_flag)
935 return;
936
937 if (archive_format == arf_newascii || archive_format == arf_crcascii)
938 create_final_defers ();
939 res = (input_bytes + io_block_size - 1) / io_block_size;
940 if (res == 1)
941 fprintf (stderr, "1 block\n");
942 else
943 fprintf (stderr, "%d blocks\n", res);
944}
945\f
946/* Print the file described by FILE_HDR in long format.
947 If LINK_NAME is nonzero, it is the name of the file that
948 this file is a symbolic link to. */
949
950void
951long_format (file_hdr, link_name)
952 struct new_cpio_header *file_hdr;
953 char *link_name;
954{
955 char mbuf[11];
956 char tbuf[40];
957 time_t when;
958
959 mode_string (file_hdr->c_mode, mbuf);
960 mbuf[10] = '\0';
961
962 /* Get time values ready to print. */
963 when = file_hdr->c_mtime;
964 strcpy (tbuf, ctime (&when));
965 if (current_time - when > 6L * 30L * 24L * 60L * 60L
966 || current_time - when < 0L)
967 {
968 /* The file is older than 6 months, or in the future.
969 Show the year instead of the time of day. */
970 strcpy (tbuf + 11, tbuf + 19);
971 }
972 tbuf[16] = '\0';
973
974 printf ("%s %3u ", mbuf, file_hdr->c_nlink);
975
976#ifndef __MSDOS__
977 if (numeric_uid)
978#endif
979 printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid,
980 (unsigned int) file_hdr->c_gid);
981#ifndef __MSDOS__
982 else
983 printf ("%-8.8s %-8.8s ", getuser (file_hdr->c_uid),
984 getgroup (file_hdr->c_gid));
985
986 if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR
987 || (file_hdr->c_mode & CP_IFMT) == CP_IFBLK)
988 printf ("%3u, %3u ", file_hdr->c_rdev_maj,
989 file_hdr->c_rdev_min);
990 else
991#endif
992 printf ("%8lu ", file_hdr->c_filesize);
993
994 printf ("%s ", tbuf + 4);
995
996 print_name_with_quoting (file_hdr->c_name);
997 if (link_name)
998 {
999 printf (" -> ");
1000 print_name_with_quoting (link_name);
1001 }
1002 putc ('\n', stdout);
1003}
1004
1005void
1006print_name_with_quoting (p)
1007 register char *p;
1008{
1009 register unsigned char c;
1010
1011 while (c = *p++)
1012 {
1013 switch (c)
1014 {
1015#ifndef __MSDOS__
1016 case '\\':
1017 printf ("\\\\");
1018 break;
1019#endif
1020
1021 case '\n':
1022 printf ("\\n");
1023 break;
1024
1025 case '\b':
1026 printf ("\\b");
1027 break;
1028
1029 case '\r':
1030 printf ("\\r");
1031 break;
1032
1033 case '\t':
1034 printf ("\\t");
1035 break;
1036
1037 case '\f':
1038 printf ("\\f");
1039 break;
1040
1041 case ' ':
1042 printf ("\\ ");
1043 break;
1044
1045 case '"':
1046 printf ("\\\"");
1047 break;
1048
1049 default:
1050 if (c > 040 &&
1051#ifdef __MSDOS__
1052 c < 0377 && c != 0177
1053#else
1054 c < 0177
1055#endif
1056 )
1057 putchar (c);
1058 else
1059 printf ("\\%03o", (unsigned int) c);
1060 }
1061 }
1062}
1063
1064/* Read a pattern file (for the -E option). Put a list of
1065 `num_patterns' elements in `save_patterns'. Any patterns that were
1066 already in `save_patterns' (from the command line) are preserved. */
1067
1068static void
1069read_pattern_file ()
1070{
1071 int max_new_patterns;
1072 char **new_save_patterns;
1073 int new_num_patterns;
1074 int i;
1075 dynamic_string pattern_name;
1076 FILE *pattern_fp;
1077
1078 if (num_patterns < 0)
1079 num_patterns = 0;
1080 max_new_patterns = 1 + num_patterns;
1081 new_save_patterns = (char **) xmalloc (max_new_patterns * sizeof (char *));
1082 new_num_patterns = num_patterns;
1083 ds_init (&pattern_name, 128);
1084
1085 pattern_fp = fopen (pattern_file_name, "r");
1086 if (pattern_fp == NULL)
1087 error (1, errno, "%s", pattern_file_name);
1088 while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL)
1089 {
1090 if (new_num_patterns >= max_new_patterns)
1091 {
1092 max_new_patterns += 1;
1093 new_save_patterns = (char **)
1094 xrealloc ((char *) new_save_patterns,
1095 max_new_patterns * sizeof (char *));
1096 }
1097 new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string);
1098 ++new_num_patterns;
1099 }
1100 if (ferror (pattern_fp) || fclose (pattern_fp) == EOF)
1101 error (1, errno, "%s", pattern_file_name);
1102
1103 for (i = 0; i < num_patterns; ++i)
1104 new_save_patterns[i] = save_patterns[i];
1105
1106 save_patterns = new_save_patterns;
1107 num_patterns = new_num_patterns;
1108}
1109
1110/* Skip the padding on IN_FILE_DES after a header or file,
1111 up to the next header.
1112 The number of bytes skipped is based on OFFSET -- the current offset
1113 from the last start of a header (or file) -- and the current
1114 header type. */
1115
1116static void
1117skip_padding (in_file_des, offset)
1118 int in_file_des;
1119 int offset;
1120{
1121 int pad;
1122
1123 if (archive_format == arf_crcascii || archive_format == arf_newascii)
1124 pad = (4 - (offset % 4)) % 4;
1125 else if (archive_format == arf_binary || archive_format == arf_hpbinary)
1126 pad = (2 - (offset % 2)) % 2;
1127 else if (archive_format == arf_tar || archive_format == arf_ustar)
1128 pad = (512 - (offset % 512)) % 512;
1129 else
1130 pad = 0;
1131
1132 if (pad != 0)
1133 toss_input (in_file_des, pad);
1134}
1135
1136
1137/* The newc and crc formats store multiply linked copies of the same file
1138 in the archive only once. The actual data is attached to the last link
1139 in the archive, and the other links all have a filesize of 0. When a
1140 file in the archive has multiple links and a filesize of 0, its data is
1141 probably "attatched" to another file in the archive, so we can't create
1142 it right away. We have to "defer" creating it until we have created
1143 the file that has the data "attatched" to it. We keep a list of the
1144 "defered" links on deferments. */
1145
1146struct deferment *deferments = NULL;
1147
1148/* Add a file header to the deferments list. For now they all just
1149 go on one list, although we could optimize this if necessary. */
1150
1151static void
1152defer_copyin (file_hdr)
1153 struct new_cpio_header *file_hdr;
1154{
1155 struct deferment *d;
1156 d = create_deferment (file_hdr);
1157 d->next = deferments;
1158 deferments = d;
1159 return;
1160}
1161
1162/* We just created a file that (probably) has some other links to it
1163 which have been defered. Go through all of the links on the deferments
1164 list and create any which are links to this file. */
1165
1166static void
1167create_defered_links (file_hdr)
1168 struct new_cpio_header *file_hdr;
1169{
1170 struct deferment *d;
1171 struct deferment *d_prev;
1172 int ino;
1173 int maj;
1174 int min;
1175 int link_res;
1176 ino = file_hdr->c_ino;
1177 maj = file_hdr->c_dev_maj;
1178 min = file_hdr->c_dev_min;
1179 d = deferments;
1180 d_prev = NULL;
1181 while (d != NULL)
1182 {
1183 if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
1184 && (d->header.c_dev_min == min) )
1185 {
1186 struct deferment *d_free;
1187 link_res = link_to_name (d->header.c_name, file_hdr->c_name);
1188 if (link_res < 0)
1189 {
1190 error (0, errno, "cannot link %s to %s",
1191 d->header.c_name, file_hdr->c_name);
1192 }
1193 if (d_prev != NULL)
1194 d_prev->next = d->next;
1195 else
1196 deferments = d->next;
1197 d_free = d;
1198 d = d->next;
1199 free_deferment (d_free);
1200 }
1201 else
1202 {
1203 d_prev = d;
1204 d = d->next;
1205 }
1206 }
1207}
1208
1209/* If we had a multiply linked file that really was empty then we would
1210 have defered all of its links, since we never found any with data
1211 "attached", and they will still be on the deferment list even when
1212 we are done reading the whole archive. Write out all of these
1213 empty links that are still on the deferments list. */
1214
1215static void
1216create_final_defers ()
1217{
1218 struct deferment *d;
1219 struct deferment *d_prev;
1220 struct new_cpio_header *h;
1221 int link_res;
1222 int out_file_des;
1223 struct utimbuf times; /* For setting file times. */
1224 /* Initialize this in case it has members we don't know to set. */
1225 bzero (&times, sizeof (struct utimbuf));
1226
1227 for (d = deferments; d != NULL; d = d->next)
1228 {
1229 d = deferments;
1230 link_res = link_to_maj_min_ino (d->header.c_name,
1231 d->header.c_dev_maj, d->header.c_dev_maj,
1232 d->header.c_ino);
1233 if (link_res == 0)
1234 {
1235 continue;
1236 }
1237 out_file_des = open (d->header.c_name,
1238 O_CREAT | O_WRONLY | O_BINARY, 0600);
1239 if (out_file_des < 0 && create_dir_flag)
1240 {
1241 create_all_directories (d->header.c_name);
1242 out_file_des = open (d->header.c_name,
1243 O_CREAT | O_WRONLY | O_BINARY,
1244 0600);
1245 }
1246 if (out_file_des < 0)
1247 {
1248 error (0, errno, "%s", d->header.c_name);
1249 continue;
1250 }
1251
1252 if (close (out_file_des) < 0)
1253 error (0, errno, "%s", d->header.c_name);
1254
1255 /* File is now copied; set attributes. */
1256 if (!no_chown_flag)
1257 if ((chown (d->header.c_name,
1258 set_owner_flag ? set_owner : d->header.c_uid,
1259 set_group_flag ? set_group : d->header.c_gid) < 0)
1260 && errno != EPERM)
1261 error (0, errno, "%s", d->header.c_name);
1262 /* chown may have turned off some permissions we wanted. */
1263 if (chmod (d->header.c_name, (int) d->header.c_mode) < 0)
1264 error (0, errno, "%s", d->header.c_name);
1265 if (retain_time_flag)
1266 {
1267 times.actime = times.modtime = d->header.c_mtime;
1268 if (utime (d->header.c_name, &times) < 0)
1269 error (0, errno, "%s", d->header.c_name);
1270 }
1271 }
1272}