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 | |
36 | static void read_pattern_file (); |
37 | static void skip_padding (); |
38 | static void defer_copyin (); |
39 | static void create_defered_links (); |
40 | static 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 | |
48 | void |
49 | read_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 | |
160 | void |
161 | read_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 | |
223 | void |
224 | read_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 | |
255 | void |
256 | read_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 | |
346 | void |
347 | swab_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. */ |
364 | static time_t current_time; |
365 | |
366 | /* Read the collection from standard input and create files |
367 | in the file system. */ |
368 | |
369 | void |
370 | process_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 (×, 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 (¤t_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, ×) < 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, ×) < 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, ×) < 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 | |
950 | void |
951 | long_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 | |
1005 | void |
1006 | print_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 | |
1068 | static void |
1069 | read_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 | |
1116 | static void |
1117 | skip_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 | |
1146 | struct 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 | |
1151 | static void |
1152 | defer_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 | |
1166 | static void |
1167 | create_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 | |
1215 | static void |
1216 | create_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 (×, 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, ×) < 0) |
1269 | error (0, errno, "%s", d->header.c_name); |
1270 | } |
1271 | } |
1272 | } |