Vge(4) is miibus(4) aware, so nuke the already commented out link state change
[dragonfly/vkernel-mp.git] / contrib / cpio / copyout.c
blob39890b07ef3bf149d9666a530b836dd79729988a
1 /* copyout.c - create a cpio archive
2 Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
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.
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.
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. */
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"
29 static unsigned long read_for_checksum ();
30 static void tape_clear_rest_of_block ();
31 static void tape_pad_output ();
32 static int last_link ();
33 static int count_defered_links_to_dev_ino ();
34 static void add_link_defer ();
35 static void writeout_other_defers ();
36 static void writeout_final_defers();
37 static void writeout_defered_file ();
38 static int check_rdev ();
40 /* Write out header FILE_HDR, including the file name, to file
41 descriptor OUT_DES. */
43 void
44 write_out_header (file_hdr, out_des)
45 struct new_cpio_header *file_hdr;
46 int out_des;
48 if (archive_format == arf_newascii || archive_format == arf_crcascii)
50 char ascii_header[112];
51 char *magic_string;
53 if (archive_format == arf_crcascii)
54 magic_string = "070702";
55 else
56 magic_string = "070701";
57 sprintf (ascii_header,
58 "%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
59 magic_string,
60 file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
61 file_hdr->c_gid, file_hdr->c_nlink, file_hdr->c_mtime,
62 file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
63 file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
64 file_hdr->c_chksum);
65 tape_buffered_write (ascii_header, out_des, 110L);
67 /* Write file name to output. */
68 tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
69 tape_pad_output (out_des, file_hdr->c_namesize + 110);
71 else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
73 char ascii_header[78];
74 #ifndef __MSDOS__
75 dev_t dev;
76 dev_t rdev;
78 if (archive_format == arf_oldascii)
80 dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
81 rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
83 else
85 /* HP/UX cpio creates archives that look just like ordinary archives,
86 but for devices it sets major = 0, minor = 1, and puts the
87 actual major/minor number in the filesize field. */
88 switch (file_hdr->c_mode & CP_IFMT)
90 case CP_IFCHR:
91 case CP_IFBLK:
92 #ifdef CP_IFSOCK
93 case CP_IFSOCK:
94 #endif
95 #ifdef CP_IFIFO
96 case CP_IFIFO:
97 #endif
98 file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
99 file_hdr->c_rdev_min);
100 rdev = 1;
101 break;
102 default:
103 dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
104 rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
105 break;
108 #else
109 int dev = 0, rdev = 0;
110 #endif
112 if ((file_hdr->c_ino >> 16) != 0)
113 error (0, 0, "%s: truncating inode number", file_hdr->c_name);
115 sprintf (ascii_header,
116 "%06o%06o%06lo%06lo%06lo%06lo%06lo%06o%011lo%06lo%011lo",
117 file_hdr->c_magic & 0xFFFF, dev & 0xFFFF,
118 file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
119 file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
120 file_hdr->c_nlink & 0xFFFF, rdev & 0xFFFF,
121 file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
122 file_hdr->c_filesize);
123 tape_buffered_write (ascii_header, out_des, 76L);
125 /* Write file name to output. */
126 tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
128 else if (archive_format == arf_tar || archive_format == arf_ustar)
130 write_out_tar_header (file_hdr, out_des);
132 else
134 struct old_cpio_header short_hdr;
136 short_hdr.c_magic = 070707;
137 short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
139 if ((file_hdr->c_ino >> 16) != 0)
140 error (0, 0, "%s: truncating inode number", file_hdr->c_name);
142 short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
143 short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
144 short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
145 short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
146 short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
147 if (archive_format != arf_hpbinary)
148 short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
149 else
151 switch (file_hdr->c_mode & CP_IFMT)
153 /* HP/UX cpio creates archives that look just like ordinary
154 archives, but for devices it sets major = 0, minor = 1, and
155 puts the actual major/minor number in the filesize field. */
156 case CP_IFCHR:
157 case CP_IFBLK:
158 #ifdef CP_IFSOCK
159 case CP_IFSOCK:
160 #endif
161 #ifdef CP_IFIFO
162 case CP_IFIFO:
163 #endif
164 file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
165 file_hdr->c_rdev_min);
166 short_hdr.c_rdev = makedev (0, 1);
167 break;
168 default:
169 short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj,
170 file_hdr->c_rdev_min);
171 break;
174 short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
175 short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
177 short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
179 short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
180 short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
182 /* Output the file header. */
183 tape_buffered_write ((char *) &short_hdr, out_des, 26L);
185 /* Write file name to output. */
186 tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
188 tape_pad_output (out_des, file_hdr->c_namesize + 26);
192 /* Read a list of file names from the standard input
193 and write a cpio collection on the standard output.
194 The format of the header depends on the compatibility (-c) flag. */
196 void
197 process_copy_out ()
199 int res; /* Result of functions. */
200 dynamic_string input_name; /* Name of file read from stdin. */
201 struct utimbuf times; /* For resetting file times after copy. */
202 struct stat file_stat; /* Stat record for file. */
203 struct new_cpio_header file_hdr; /* Output header information. */
204 int in_file_des; /* Source file descriptor. */
205 int out_file_des; /* Output file descriptor. */
206 char *p;
208 /* Initialize the copy out. */
209 ds_init (&input_name, 128);
210 /* Initialize this in case it has members we don't know to set. */
211 bzero (&times, sizeof (struct utimbuf));
212 file_hdr.c_magic = 070707;
214 #ifdef __MSDOS__
215 setmode (archive_des, O_BINARY);
216 #endif
217 /* Check whether the output file might be a tape. */
218 out_file_des = archive_des;
219 if (_isrmt (out_file_des))
221 output_is_special = 1;
222 output_is_seekable = 0;
224 else
226 if (fstat (out_file_des, &file_stat))
227 error (1, errno, "standard output is closed");
228 output_is_special =
229 #ifdef S_ISBLK
230 S_ISBLK (file_stat.st_mode) ||
231 #endif
232 S_ISCHR (file_stat.st_mode);
233 output_is_seekable = S_ISREG (file_stat.st_mode);
236 if (append_flag)
238 process_copy_in ();
239 prepare_append (out_file_des);
242 /* Copy files with names read from stdin. */
243 while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
245 /* Check for blank line. */
246 if (input_name.ds_string[0] == 0)
248 error (0, 0, "blank line ignored");
249 continue;
252 /* Process next file. */
253 if ((*xstat) (input_name.ds_string, &file_stat) < 0)
254 error (0, errno, "%s", input_name.ds_string);
255 else
257 /* Set values in output header. */
258 file_hdr.c_dev_maj = major (file_stat.st_dev);
259 file_hdr.c_dev_min = minor (file_stat.st_dev);
260 file_hdr.c_ino = file_stat.st_ino;
261 /* For POSIX systems that don't define the S_IF macros,
262 we can't assume that S_ISfoo means the standard Unix
263 S_IFfoo bit(s) are set. So do it manually, with a
264 different name. Bleah. */
265 file_hdr.c_mode = (file_stat.st_mode & 07777);
266 if (S_ISREG (file_stat.st_mode))
267 file_hdr.c_mode |= CP_IFREG;
268 else if (S_ISDIR (file_stat.st_mode))
269 file_hdr.c_mode |= CP_IFDIR;
270 #ifdef S_ISBLK
271 else if (S_ISBLK (file_stat.st_mode))
272 file_hdr.c_mode |= CP_IFBLK;
273 #endif
274 #ifdef S_ISCHR
275 else if (S_ISCHR (file_stat.st_mode))
276 file_hdr.c_mode |= CP_IFCHR;
277 #endif
278 #ifdef S_ISFIFO
279 else if (S_ISFIFO (file_stat.st_mode))
280 file_hdr.c_mode |= CP_IFIFO;
281 #endif
282 #ifdef S_ISLNK
283 else if (S_ISLNK (file_stat.st_mode))
284 file_hdr.c_mode |= CP_IFLNK;
285 #endif
286 #ifdef S_ISSOCK
287 else if (S_ISSOCK (file_stat.st_mode))
288 file_hdr.c_mode |= CP_IFSOCK;
289 #endif
290 #ifdef S_ISNWK
291 else if (S_ISNWK (file_stat.st_mode))
292 file_hdr.c_mode |= CP_IFNWK;
293 #endif
294 file_hdr.c_uid = file_stat.st_uid;
295 file_hdr.c_gid = file_stat.st_gid;
296 file_hdr.c_nlink = file_stat.st_nlink;
298 /* The rdev is meaningless except for block and character
299 special files (POSIX standard) and perhaps fifos and
300 sockets. Clear it for other types of files so that
301 check_rdev() doesn't reject files just because stat()
302 put garbage in st_rdev and so that the output doesn't
303 depend on the garbage. */
304 switch (file_hdr.c_mode & CP_IFMT)
306 case CP_IFBLK:
307 case CP_IFCHR:
308 #ifdef CP_IFIFO
309 case CP_IFIFO:
310 #endif
311 #ifdef CP_IFSOCK
312 case CP_IFSOCK:
313 #endif
314 file_hdr.c_rdev_maj = major (file_stat.st_rdev);
315 file_hdr.c_rdev_min = minor (file_stat.st_rdev);
316 break;
317 default:
318 file_hdr.c_rdev_maj = 0;
319 file_hdr.c_rdev_min = 0;
320 break;
323 file_hdr.c_mtime = file_stat.st_mtime;
324 file_hdr.c_filesize = file_stat.st_size;
325 file_hdr.c_chksum = 0;
326 file_hdr.c_tar_linkname = NULL;
328 /* Strip leading `./' from the filename. */
329 p = input_name.ds_string;
330 while (*p == '.' && *(p + 1) == '/')
332 ++p;
333 while (*p == '/')
334 ++p;
336 #ifndef HPUX_CDF
337 file_hdr.c_name = p;
338 file_hdr.c_namesize = strlen (p) + 1;
339 #else
340 if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
342 /* We mark CDF's in cpio files by adding a 2nd `/' after the
343 "hidden" directory name. We need to do this so we can
344 properly recreate the directory as hidden (in case the
345 files of a directory go into the archive before the
346 directory itself (e.g from "find ... -depth ... | cpio")). */
347 file_hdr.c_name = add_cdf_double_slashes (p);
348 file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
350 else
352 /* We don't mark CDF's in tar files. We assume the "hidden"
353 directory will always go into the archive before any of
354 its files. */
355 file_hdr.c_name = p;
356 file_hdr.c_namesize = strlen (p) + 1;
358 #endif
359 if ((archive_format == arf_tar || archive_format == arf_ustar)
360 && is_tar_filename_too_long (file_hdr.c_name))
362 error (0, 0, "%s: file name too long", file_hdr.c_name);
363 continue;
366 switch (check_rdev (&file_hdr))
368 case 1:
369 error (0, 0, "%s not dumped: major number would be truncated",
370 file_hdr.c_name);
371 continue;
372 case 2:
373 error (0, 0, "%s not dumped: minor number would be truncated",
374 file_hdr.c_name);
375 continue;
376 case 4:
377 error (0, 0, "%s not dumped: device number would be truncated",
378 file_hdr.c_name);
379 continue;
383 /* Copy the named file to the output. */
384 switch (file_hdr.c_mode & CP_IFMT)
386 case CP_IFREG:
387 #ifndef __MSDOS__
388 if (archive_format == arf_tar || archive_format == arf_ustar)
390 char *otherfile;
391 if ((otherfile = find_inode_file (file_hdr.c_ino,
392 file_hdr.c_dev_maj,
393 file_hdr.c_dev_min)))
395 file_hdr.c_tar_linkname = otherfile;
396 write_out_header (&file_hdr, out_file_des);
397 break;
400 if ( (archive_format == arf_newascii || archive_format == arf_crcascii)
401 && (file_hdr.c_nlink > 1) )
403 if (last_link (&file_hdr) )
405 writeout_other_defers (&file_hdr, out_file_des);
407 else
409 add_link_defer (&file_hdr);
410 break;
413 #endif
414 in_file_des = open (input_name.ds_string,
415 O_RDONLY | O_BINARY, 0);
416 if (in_file_des < 0)
418 error (0, errno, "%s", input_name.ds_string);
419 continue;
422 if (archive_format == arf_crcascii)
423 file_hdr.c_chksum = read_for_checksum (in_file_des,
424 file_hdr.c_filesize,
425 input_name.ds_string);
427 write_out_header (&file_hdr, out_file_des);
428 copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, input_name.ds_string);
430 #ifndef __MSDOS__
431 if (archive_format == arf_tar || archive_format == arf_ustar)
432 add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
433 file_hdr.c_dev_min);
434 #endif
436 tape_pad_output (out_file_des, file_hdr.c_filesize);
438 if (close (in_file_des) < 0)
439 error (0, errno, "%s", input_name.ds_string);
440 if (reset_time_flag)
442 times.actime = file_stat.st_atime;
443 times.modtime = file_stat.st_mtime;
444 if (utime (file_hdr.c_name, &times) < 0)
445 error (0, errno, "%s", file_hdr.c_name);
447 break;
449 case CP_IFDIR:
450 file_hdr.c_filesize = 0;
451 write_out_header (&file_hdr, out_file_des);
452 break;
454 #ifndef __MSDOS__
455 case CP_IFCHR:
456 case CP_IFBLK:
457 #ifdef CP_IFSOCK
458 case CP_IFSOCK:
459 #endif
460 #ifdef CP_IFIFO
461 case CP_IFIFO:
462 #endif
463 if (archive_format == arf_tar)
465 error (0, 0, "%s not dumped: not a regular file",
466 file_hdr.c_name);
467 continue;
469 else if (archive_format == arf_ustar)
471 char *otherfile;
472 if ((otherfile = find_inode_file (file_hdr.c_ino,
473 file_hdr.c_dev_maj,
474 file_hdr.c_dev_min)))
476 /* This file is linked to another file already in the
477 archive, so write it out as a hard link. */
478 file_hdr.c_mode = (file_stat.st_mode & 07777);
479 file_hdr.c_mode |= CP_IFREG;
480 file_hdr.c_tar_linkname = otherfile;
481 write_out_header (&file_hdr, out_file_des);
482 break;
484 add_inode (file_hdr.c_ino, file_hdr.c_name,
485 file_hdr.c_dev_maj, file_hdr.c_dev_min);
487 file_hdr.c_filesize = 0;
488 write_out_header (&file_hdr, out_file_des);
489 break;
490 #endif
492 #ifdef CP_IFLNK
493 case CP_IFLNK:
495 char *link_name = (char *) xmalloc (file_stat.st_size + 1);
496 int link_size;
498 link_size = readlink (input_name.ds_string, link_name,
499 file_stat.st_size);
500 if (link_size < 0)
502 error (0, errno, "%s", input_name.ds_string);
503 free (link_name);
504 continue;
506 file_hdr.c_filesize = link_size;
507 if (archive_format == arf_tar || archive_format == arf_ustar)
509 if (link_size + 1 > 100)
511 error (0, 0, "%s: symbolic link too long",
512 file_hdr.c_name);
514 else
516 link_name[link_size] = '\0';
517 file_hdr.c_tar_linkname = link_name;
518 write_out_header (&file_hdr, out_file_des);
521 else
523 write_out_header (&file_hdr, out_file_des);
524 tape_buffered_write (link_name, out_file_des, link_size);
525 tape_pad_output (out_file_des, link_size);
527 free (link_name);
529 break;
530 #endif
532 default:
533 error (0, 0, "%s: unknown file type", input_name.ds_string);
536 if (verbose_flag)
537 fprintf (stderr, "%s\n", input_name.ds_string);
538 if (dot_flag)
539 fputc ('.', stderr);
543 writeout_final_defers(out_file_des);
544 /* The collection is complete; append the trailer. */
545 file_hdr.c_ino = 0;
546 file_hdr.c_mode = 0;
547 file_hdr.c_uid = 0;
548 file_hdr.c_gid = 0;
549 file_hdr.c_nlink = 1; /* Must be 1 for crc format. */
550 file_hdr.c_dev_maj = 0;
551 file_hdr.c_dev_min = 0;
552 file_hdr.c_rdev_maj = 0;
553 file_hdr.c_rdev_min = 0;
554 file_hdr.c_mtime = 0;
555 file_hdr.c_chksum = 0;
557 file_hdr.c_filesize = 0;
558 file_hdr.c_namesize = 11;
559 file_hdr.c_name = "TRAILER!!!";
560 if (archive_format != arf_tar && archive_format != arf_ustar)
561 write_out_header (&file_hdr, out_file_des);
562 else
564 tape_buffered_write (zeros_512, out_file_des, 512);
565 tape_buffered_write (zeros_512, out_file_des, 512);
568 /* Fill up the output block. */
569 tape_clear_rest_of_block (out_file_des);
570 tape_empty_output_buffer (out_file_des);
571 if (dot_flag)
572 fputc ('\n', stderr);
573 if (!quiet_flag)
575 res = (output_bytes + io_block_size - 1) / io_block_size;
576 if (res == 1)
577 fprintf (stderr, "1 block\n");
578 else
579 fprintf (stderr, "%d blocks\n", res);
583 /* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
584 compute and return a checksum for them. */
586 static unsigned long
587 read_for_checksum (in_file_des, file_size, file_name)
588 int in_file_des;
589 int file_size;
590 char *file_name;
592 unsigned long crc;
593 char buf[BUFSIZ];
594 int bytes_left;
595 int bytes_read;
596 int i;
598 crc = 0;
600 for (bytes_left = file_size; bytes_left > 0; bytes_left -= bytes_read)
602 bytes_read = read (in_file_des, buf, BUFSIZ);
603 if (bytes_read < 0)
604 error (1, errno, "cannot read checksum for %s", file_name);
605 if (bytes_read == 0)
606 break;
607 for (i = 0; i < bytes_read; ++i)
608 crc += buf[i] & 0xff;
610 if (lseek (in_file_des, 0L, SEEK_SET))
611 error (1, errno, "cannot read checksum for %s", file_name);
613 return crc;
616 /* Write out NULs to fill out the rest of the current block on
617 OUT_FILE_DES. */
619 static void
620 tape_clear_rest_of_block (out_file_des)
621 int out_file_des;
623 while (output_size < io_block_size)
625 if ((io_block_size - output_size) > 512)
626 tape_buffered_write (zeros_512, out_file_des, 512);
627 else
628 tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
632 /* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
633 to the end of the header. */
635 static void
636 tape_pad_output (out_file_des, offset)
637 int out_file_des;
638 int offset;
640 int pad;
642 if (archive_format == arf_newascii || archive_format == arf_crcascii)
643 pad = (4 - (offset % 4)) % 4;
644 else if (archive_format == arf_tar || archive_format == arf_ustar)
645 pad = (512 - (offset % 512)) % 512;
646 else if (archive_format != arf_oldascii && archive_format != arf_hpoldascii)
647 pad = (2 - (offset % 2)) % 2;
648 else
649 pad = 0;
651 if (pad != 0)
652 tape_buffered_write (zeros_512, out_file_des, pad);
656 /* When creating newc and crc archives if a file has multiple (hard)
657 links, we don't put any of them into the archive until we have seen
658 all of them (or until we get to the end of the list of files that
659 are going into the archive and know that we have seen all of the links
660 to the file that we will see). We keep these "defered" files on
661 this list. */
663 struct deferment *deferouts = NULL;
666 /* Is this file_hdr the last (hard) link to a file? I.e., have
667 we already seen and defered all of the other links? */
669 static int
670 last_link (file_hdr)
671 struct new_cpio_header *file_hdr;
673 int other_files_sofar;
675 other_files_sofar = count_defered_links_to_dev_ino (file_hdr);
676 if (file_hdr->c_nlink == (other_files_sofar + 1) )
678 return 1;
680 return 0;
683 /* Count the number of other (hard) links to this file that have
684 already been defered. */
686 static int
687 count_defered_links_to_dev_ino (file_hdr)
688 struct new_cpio_header *file_hdr;
690 struct deferment *d;
691 int ino;
692 int maj;
693 int min;
694 int count;
695 ino = file_hdr->c_ino;
696 maj = file_hdr->c_dev_maj;
697 min = file_hdr->c_dev_min;
698 count = 0;
699 for (d = deferouts; d != NULL; d = d->next)
701 if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
702 && (d->header.c_dev_min == min) )
703 ++count;
705 return count;
708 /* Add the file header for a link that is being defered to the deferouts
709 list. */
711 static void
712 add_link_defer (file_hdr)
713 struct new_cpio_header *file_hdr;
715 struct deferment *d;
716 d = create_deferment (file_hdr);
717 d->next = deferouts;
718 deferouts = d;
721 /* We are about to put a file into a newc or crc archive that is
722 multiply linked. We have already seen and defered all of the
723 other links to the file but haven't written them into the archive.
724 Write the other links into the archive, and remove them from the
725 deferouts list. */
727 static void
728 writeout_other_defers (file_hdr, out_des)
729 struct new_cpio_header *file_hdr;
730 int out_des;
732 struct deferment *d;
733 struct deferment *d_prev;
734 int ino;
735 int maj;
736 int min;
737 ino = file_hdr->c_ino;
738 maj = file_hdr->c_dev_maj;
739 min = file_hdr->c_dev_min;
740 d_prev = NULL;
741 d = deferouts;
742 while (d != NULL)
744 if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
745 && (d->header.c_dev_min == min) )
747 struct deferment *d_free;
748 d->header.c_filesize = 0;
749 write_out_header (&d->header, out_des);
750 if (d_prev != NULL)
751 d_prev->next = d->next;
752 else
753 deferouts = d->next;
754 d_free = d;
755 d = d->next;
756 free_deferment (d_free);
758 else
760 d_prev = d;
761 d = d->next;
764 return;
766 /* When writing newc and crc format archives we defer multiply linked
767 files until we have seen all of the links to the file. If a file
768 has links to it that aren't going into the archive, then we will
769 never see the "last" link to the file, so at the end we just write
770 all of the leftover defered files into the archive. */
772 static void
773 writeout_final_defers(out_des)
774 int out_des;
776 struct deferment *d;
777 int other_count;
778 while (deferouts != NULL)
780 d = deferouts;
781 other_count = count_defered_links_to_dev_ino (&d->header);
782 if (other_count == 1)
784 writeout_defered_file (&d->header, out_des);
786 else
788 struct new_cpio_header file_hdr;
789 file_hdr = d->header;
790 file_hdr.c_filesize = 0;
791 write_out_header (&file_hdr, out_des);
793 deferouts = deferouts->next;
797 /* Write a file into the archive. This code is the same as
798 the code in process_copy_out(), but we need it here too
799 for writeout_final_defers() to call. */
801 static void
802 writeout_defered_file (header, out_file_des)
803 struct new_cpio_header *header;
804 int out_file_des;
806 int in_file_des;
807 struct new_cpio_header file_hdr;
808 struct utimbuf times; /* For setting file times. */
809 /* Initialize this in case it has members we don't know to set. */
810 bzero (&times, sizeof (struct utimbuf));
812 file_hdr = *header;
815 in_file_des = open (header->c_name,
816 O_RDONLY | O_BINARY, 0);
817 if (in_file_des < 0)
819 error (0, errno, "%s", header->c_name);
820 return;
823 if (archive_format == arf_crcascii)
824 file_hdr.c_chksum = read_for_checksum (in_file_des,
825 file_hdr.c_filesize,
826 header->c_name);
828 write_out_header (&file_hdr, out_file_des);
829 copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, header->c_name);
831 #ifndef __MSDOS__
832 if (archive_format == arf_tar || archive_format == arf_ustar)
833 add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
834 file_hdr.c_dev_min);
835 #endif
837 tape_pad_output (out_file_des, file_hdr.c_filesize);
839 if (close (in_file_des) < 0)
840 error (0, errno, "%s", header->c_name);
841 if (reset_time_flag)
843 times.actime = file_hdr.c_mtime;
844 times.modtime = file_hdr.c_mtime;
845 if (utime (file_hdr.c_name, &times) < 0)
846 error (0, errno, "%s", file_hdr.c_name);
848 return;
852 static int
853 check_rdev (file_hdr)
854 struct new_cpio_header *file_hdr;
856 if (archive_format == arf_newascii || archive_format == arf_crcascii)
858 if ((file_hdr->c_rdev_maj & 0xFFFFFFFF) != file_hdr->c_rdev_maj)
859 return 1;
860 if ((file_hdr->c_rdev_min & 0xFFFFFFFF) != file_hdr->c_rdev_min)
861 return 2;
863 else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
865 #ifndef __MSDOS__
866 dev_t rdev;
868 rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
869 if (archive_format == arf_oldascii)
871 if ((rdev & 0xFFFF) != rdev)
872 return 4;
874 else
876 switch (file_hdr->c_mode & CP_IFMT)
878 case CP_IFCHR:
879 case CP_IFBLK:
880 #ifdef CP_IFSOCK
881 case CP_IFSOCK:
882 #endif
883 #ifdef CP_IFIFO
884 case CP_IFIFO:
885 #endif
886 /* We could handle one more bit if longs are >= 33 bits. */
887 if ((rdev & 037777777777) != rdev)
888 return 4;
889 break;
890 default:
891 if ((rdev & 0xFFFF) != rdev)
892 return 4;
893 break;
896 #endif
898 else if (archive_format == arf_tar || archive_format == arf_ustar)
900 /* The major and minor formats are limited to 7 octal digits in ustar
901 format, and to_oct () adds a gratuitous trailing blank to further
902 limit the format to 6 octal digits. */
903 if ((file_hdr->c_rdev_maj & 0777777) != file_hdr->c_rdev_maj)
904 return 1;
905 if ((file_hdr->c_rdev_min & 0777777) != file_hdr->c_rdev_min)
906 return 2;
908 else
910 #ifndef __MSDOS__
911 dev_t rdev;
913 rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
914 if (archive_format != arf_hpbinary)
916 if ((rdev & 0xFFFF) != rdev)
917 return 4;
919 else
921 switch (file_hdr->c_mode & CP_IFMT)
923 case CP_IFCHR:
924 case CP_IFBLK:
925 #ifdef CP_IFSOCK
926 case CP_IFSOCK:
927 #endif
928 #ifdef CP_IFIFO
929 case CP_IFIFO:
930 #endif
931 if ((rdev & 0xFFFFFFFF) != rdev)
932 return 4;
933 file_hdr->c_filesize = rdev;
934 rdev = makedev (0, 1);
935 break;
936 default:
937 if ((rdev & 0xFFFF) != rdev)
938 return 4;
939 break;
942 #endif
944 return 0;