]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/cpio/src/copyout.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / cpio / src / copyout.c
1 /* $FreeBSD$ */
2
3 /* copyout.c - create a cpio archive
4    Copyright (C) 1990, 1991, 1992, 2001, 2003, 2004 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include <system.h>
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include "filetypes.h"
26 #include "cpiohdr.h"
27 #include "dstring.h"
28 #include "extern.h"
29 #include "defer.h"
30 #include <rmt.h>
31
32 static int check_rdev ();
33
34 /* Read FILE_SIZE bytes of FILE_NAME from IN_FILE_DES and
35    compute and return a checksum for them.  */
36
37 static unsigned long
38 read_for_checksum (int in_file_des, int file_size, char *file_name)
39 {
40   unsigned long crc;
41   char buf[BUFSIZ];
42   int bytes_left;
43   int bytes_read;
44   int i;
45
46   crc = 0;
47
48   for (bytes_left = file_size; bytes_left > 0; bytes_left -= bytes_read)
49     {
50       bytes_read = read (in_file_des, buf, BUFSIZ);
51       if (bytes_read < 0)
52         error (1, errno, _("cannot read checksum for %s"), file_name);
53       if (bytes_read == 0)
54         break;
55       if (bytes_left < bytes_read)
56         bytes_read = bytes_left;
57       for (i = 0; i < bytes_read; ++i)
58         crc += buf[i] & 0xff;
59     }
60   if (lseek (in_file_des, 0L, SEEK_SET))
61     error (1, errno, _("cannot read checksum for %s"), file_name);
62
63   return crc;
64 }
65
66 /* Write out NULs to fill out the rest of the current block on
67    OUT_FILE_DES.  */
68
69 static void
70 tape_clear_rest_of_block (int out_file_des)
71 {
72   while (output_size < io_block_size)
73     {
74       if ((io_block_size - output_size) > 512)
75         tape_buffered_write (zeros_512, out_file_des, 512);
76       else
77         tape_buffered_write (zeros_512, out_file_des, io_block_size - output_size);
78     }
79 }
80
81 /* Write NULs on OUT_FILE_DES to move from OFFSET (the current location)
82    to the end of the header.  */
83
84 static void
85 tape_pad_output (int out_file_des, int offset)
86 {
87   int pad;
88
89   if (archive_format == arf_newascii || archive_format == arf_crcascii)
90     pad = (4 - (offset % 4)) % 4;
91   else if (archive_format == arf_tar || archive_format == arf_ustar)
92     pad = (512 - (offset % 512)) % 512;
93   else if (archive_format != arf_oldascii && archive_format != arf_hpoldascii)
94     pad = (2 - (offset % 2)) % 2;
95   else
96     pad = 0;
97
98   if (pad != 0)
99     tape_buffered_write (zeros_512, out_file_des, pad);
100 }
101
102
103 /* When creating newc and crc archives if a file has multiple (hard)
104    links, we don't put any of them into the archive until we have seen
105    all of them (or until we get to the end of the list of files that
106    are going into the archive and know that we have seen all of the links
107    to the file that we will see).  We keep these "defered" files on
108    this list.   */
109
110 struct deferment *deferouts = NULL;
111
112 /* Count the number of other (hard) links to this file that have
113    already been defered.  */
114
115 static int
116 count_defered_links_to_dev_ino (struct new_cpio_header *file_hdr)
117 {
118   struct deferment *d;
119   int   ino;
120   int   maj;
121   int   min;
122   int   count;
123   ino = file_hdr->c_ino;
124   maj = file_hdr->c_dev_maj;
125   min = file_hdr->c_dev_min;
126   count = 0;
127   for (d = deferouts; d != NULL; d = d->next)
128     {
129       if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
130           && (d->header.c_dev_min == min) )
131         ++count;
132     }
133   return count;
134 }
135
136 /* Is this file_hdr the last (hard) link to a file?  I.e., have
137    we already seen and defered all of the other links?  */
138
139 static int
140 last_link (struct new_cpio_header *file_hdr)
141 {
142   int   other_files_sofar;
143
144   other_files_sofar = count_defered_links_to_dev_ino (file_hdr);
145   if (file_hdr->c_nlink == (other_files_sofar + 1) )
146     {
147       return 1;
148     }
149   return 0;
150 }
151
152
153 /* Add the file header for a link that is being defered to the deferouts
154    list.  */
155
156 static void
157 add_link_defer (struct new_cpio_header *file_hdr)
158 {
159   struct deferment *d;
160   d = create_deferment (file_hdr);
161   d->next = deferouts;
162   deferouts = d;
163 }
164
165 /* We are about to put a file into a newc or crc archive that is
166    multiply linked.  We have already seen and defered all of the
167    other links to the file but haven't written them into the archive.
168    Write the other links into the archive, and remove them from the
169    deferouts list.  */
170
171 static void
172 writeout_other_defers (struct new_cpio_header *file_hdr, int out_des)
173 {
174   struct deferment *d;
175   struct deferment *d_prev;
176   int   ino;
177   int   maj;
178   int   min;
179   ino = file_hdr->c_ino;
180   maj = file_hdr->c_dev_maj;
181   min = file_hdr->c_dev_min;
182   d_prev = NULL;
183   d = deferouts;
184   while (d != NULL)
185     {
186       if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj)
187           && (d->header.c_dev_min == min) )
188         {
189           struct deferment *d_free;
190           d->header.c_filesize = 0;
191           write_out_header (&d->header, out_des);
192           if (d_prev != NULL)
193             d_prev->next = d->next;
194           else
195             deferouts = d->next;
196           d_free = d;
197           d = d->next;
198           free_deferment (d_free);
199         }
200       else
201         {
202           d_prev = d;
203           d = d->next;
204         }
205     }
206   return;
207 }
208
209 /* Write a file into the archive.  This code is the same as
210    the code in process_copy_out(), but we need it here too
211    for writeout_final_defers() to call.  */
212
213 static void
214 writeout_defered_file (struct new_cpio_header *header, int out_file_des)
215 {
216   int in_file_des;
217   struct new_cpio_header file_hdr;
218   struct utimbuf times;         /* For setting file times.  */
219   /* Initialize this in case it has members we don't know to set.  */
220   bzero (&times, sizeof (struct utimbuf));
221
222   file_hdr = *header;
223
224
225   in_file_des = open (header->c_name,
226                       O_RDONLY | O_BINARY, 0);
227   if (in_file_des < 0)
228     {
229       error (0, errno, "%s", header->c_name);
230       return;
231     }
232
233   if (archive_format == arf_crcascii)
234     file_hdr.c_chksum = read_for_checksum (in_file_des,
235                                            file_hdr.c_filesize,
236                                            header->c_name);
237
238   write_out_header (&file_hdr, out_file_des);
239   copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, header->c_name);
240   warn_if_file_changed(header->c_name, file_hdr.c_filesize, file_hdr.c_mtime);
241
242   if (archive_format == arf_tar || archive_format == arf_ustar)
243     add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
244                file_hdr.c_dev_min);
245
246   tape_pad_output (out_file_des, file_hdr.c_filesize);
247
248   if (close (in_file_des) < 0)
249     error (0, errno, "%s", header->c_name);
250   if (reset_time_flag)
251     {
252       times.actime = file_hdr.c_mtime;
253       times.modtime = file_hdr.c_mtime;
254       /* Debian hack: Silently ignore EROFS because reading the file
255          won't have upset its timestamp if it's on a read-only
256          filesystem.  This has been submitted as a suggestion to
257          "bug-gnu-utils@prep.ai.mit.edu".  -BEM */
258       if (utime (file_hdr.c_name, &times) < 0
259           && errno != EROFS)
260         error (0, errno, "%s", file_hdr.c_name);
261     }
262   return;
263 }
264
265 /* When writing newc and crc format archives we defer multiply linked
266    files until we have seen all of the links to the file.  If a file
267    has links to it that aren't going into the archive, then we will
268    never see the "last" link to the file, so at the end we just write 
269    all of the leftover defered files into the archive.  */
270
271 static void
272 writeout_final_defers (int out_des)
273 {
274   struct deferment *d;
275   int other_count;
276   while (deferouts != NULL)
277     {
278       d = deferouts;
279       other_count = count_defered_links_to_dev_ino (&d->header);
280       if (other_count == 1)
281         {
282           writeout_defered_file (&d->header, out_des);
283         }
284       else
285         {
286           struct new_cpio_header file_hdr;
287           file_hdr = d->header;
288           file_hdr.c_filesize = 0;
289           write_out_header (&file_hdr, out_des);
290         }
291       deferouts = deferouts->next;
292     }
293 }
294
295 \f
296 /* Write out header FILE_HDR, including the file name, to file
297    descriptor OUT_DES.  */
298
299 void
300 write_out_header (struct new_cpio_header *file_hdr, int out_des)
301 {
302   if (archive_format == arf_newascii || archive_format == arf_crcascii)
303     {
304       char ascii_header[112];
305       char *magic_string;
306       int ret;
307
308       if (archive_format == arf_crcascii)
309         magic_string = "070702";
310       else
311         magic_string = "070701";
312       ret = snprintf (ascii_header, sizeof(ascii_header),
313                "%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
314                magic_string,
315                file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
316                file_hdr->c_gid, file_hdr->c_nlink, file_hdr->c_mtime,
317              file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
318            file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
319                file_hdr->c_chksum);
320       if (ret >= sizeof(ascii_header)) {
321         fprintf(stderr, "Internal overflow, aborting\n");
322         exit (1);
323       }
324       tape_buffered_write (ascii_header, out_des, 110L);
325
326       /* Write file name to output.  */
327       tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
328       tape_pad_output (out_des, file_hdr->c_namesize + 110);
329     }
330   else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
331     {
332       char ascii_header[78];
333       int ret;
334       dev_t dev;
335       dev_t rdev;
336
337       if (archive_format == arf_oldascii)
338         {
339           dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
340           rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
341         }
342       else
343         {
344           /* HP/UX cpio creates archives that look just like ordinary archives,
345              but for devices it sets major = 0, minor = 1, and puts the
346              actual major/minor number in the filesize field.  */
347           switch (file_hdr->c_mode & CP_IFMT)
348             {
349               case CP_IFCHR:
350               case CP_IFBLK:
351 #ifdef CP_IFSOCK
352               case CP_IFSOCK:
353 #endif
354 #ifdef CP_IFIFO
355               case CP_IFIFO:
356 #endif
357                 file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
358                                                 file_hdr->c_rdev_min);
359                 rdev = 1;
360                 break;
361               default:
362                 dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
363                 rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
364                 break;
365             }
366         }
367
368       if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
369         error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
370
371       /* Debian hack: The type of dev_t has changed in glibc.  Fixed output
372          to ensure that a long int is passed to sprintf.  This has been
373          reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */
374       snprintf (ascii_header, sizeof(ascii_header),
375                "%06ho%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
376                file_hdr->c_magic & 0xFFFF, (long) dev & 0xFFFF,
377                file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
378                file_hdr->c_uid & 0xFFFF, file_hdr->c_gid & 0xFFFF,
379                file_hdr->c_nlink & 0xFFFF, (long) rdev & 0xFFFF,
380                file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
381                file_hdr->c_filesize);
382       if (ret >= sizeof(ascii_header)) {
383         fprintf(stderr, "Internal overflow, aborting\n");
384         exit (1);
385       }
386       tape_buffered_write (ascii_header, out_des, 76L);
387
388       /* Write file name to output.  */
389       tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
390     }
391   else if (archive_format == arf_tar || archive_format == arf_ustar)
392     {
393       write_out_tar_header (file_hdr, out_des);
394     }
395   else
396     {
397       struct old_cpio_header short_hdr;
398
399       short_hdr.c_magic = 070707;
400       short_hdr.c_dev = makedev (file_hdr->c_dev_maj, file_hdr->c_dev_min);
401
402       if ((warn_option & CPIO_WARN_TRUNCATE) && (file_hdr->c_ino >> 16) != 0)
403         error (0, 0, _("%s: truncating inode number"), file_hdr->c_name);
404
405       short_hdr.c_ino = file_hdr->c_ino & 0xFFFF;
406       short_hdr.c_mode = file_hdr->c_mode & 0xFFFF;
407       short_hdr.c_uid = file_hdr->c_uid & 0xFFFF;
408       short_hdr.c_gid = file_hdr->c_gid & 0xFFFF;
409       short_hdr.c_nlink = file_hdr->c_nlink & 0xFFFF;
410       if (archive_format != arf_hpbinary)
411         short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
412       else
413         {
414           switch (file_hdr->c_mode & CP_IFMT)
415             {
416               /* HP/UX cpio creates archives that look just like ordinary 
417                  archives, but for devices it sets major = 0, minor = 1, and 
418                  puts the actual major/minor number in the filesize field.  */
419               case CP_IFCHR:
420               case CP_IFBLK:
421 #ifdef CP_IFSOCK
422               case CP_IFSOCK:
423 #endif
424 #ifdef CP_IFIFO
425               case CP_IFIFO:
426 #endif
427                 file_hdr->c_filesize = makedev (file_hdr->c_rdev_maj,
428                                                 file_hdr->c_rdev_min);
429                 short_hdr.c_rdev = makedev (0, 1);
430                 break;
431               default:
432                 short_hdr.c_rdev = makedev (file_hdr->c_rdev_maj, 
433                                             file_hdr->c_rdev_min);
434                 break;
435             }
436         }
437       short_hdr.c_mtimes[0] = file_hdr->c_mtime >> 16;
438       short_hdr.c_mtimes[1] = file_hdr->c_mtime & 0xFFFF;
439
440       short_hdr.c_namesize = file_hdr->c_namesize & 0xFFFF;
441
442       short_hdr.c_filesizes[0] = file_hdr->c_filesize >> 16;
443       short_hdr.c_filesizes[1] = file_hdr->c_filesize & 0xFFFF;
444
445       /* Output the file header.  */
446       tape_buffered_write ((char *) &short_hdr, out_des, 26L);
447
448       /* Write file name to output.  */
449       tape_buffered_write (file_hdr->c_name, out_des, (long) file_hdr->c_namesize);
450
451       tape_pad_output (out_des, file_hdr->c_namesize + 26);
452     }
453 }
454
455 /* Read a list of file names from the standard input
456    and write a cpio collection on the standard output.
457    The format of the header depends on the compatibility (-c) flag.  */
458
459 void
460 process_copy_out ()
461 {
462   int res;                      /* Result of functions.  */
463   dynamic_string input_name;    /* Name of file read from stdin.  */
464   struct utimbuf times;         /* For resetting file times after copy.  */
465   struct stat file_stat;        /* Stat record for file.  */
466   struct new_cpio_header file_hdr; /* Output header information.  */
467   int in_file_des;              /* Source file descriptor.  */
468   int out_file_des;             /* Output file descriptor.  */
469   char *p;
470
471   /* Initialize the copy out.  */
472   ds_init (&input_name, 128);
473   /* Initialize this in case it has members we don't know to set.  */
474   bzero (&times, sizeof (struct utimbuf));
475   file_hdr.c_magic = 070707;
476
477   /* Check whether the output file might be a tape.  */
478   out_file_des = archive_des;
479   if (_isrmt (out_file_des))
480     {
481       output_is_special = 1;
482       output_is_seekable = 0;
483     }
484   else
485     {
486       if (fstat (out_file_des, &file_stat))
487         error (1, errno, _("standard output is closed"));
488       output_is_special =
489 #ifdef S_ISBLK
490         S_ISBLK (file_stat.st_mode) ||
491 #endif
492         S_ISCHR (file_stat.st_mode);
493       output_is_seekable = S_ISREG (file_stat.st_mode);
494     }
495
496   if (append_flag)
497     {
498       process_copy_in ();
499       prepare_append (out_file_des);
500     }
501
502   /* Copy files with names read from stdin.  */
503   while (ds_fgetstr (stdin, &input_name, name_end) != NULL)
504     {
505       /* Check for blank line.  */
506       if (input_name.ds_string[0] == 0)
507         {
508           error (0, 0, _("blank line ignored"));
509           continue;
510         }
511
512       /* Process next file.  */
513       if ((*xstat) (input_name.ds_string, &file_stat) < 0)
514         error (0, errno, "%s", input_name.ds_string);
515       else
516         {
517           /* Set values in output header.  */
518           file_hdr.c_dev_maj = major (file_stat.st_dev);
519           file_hdr.c_dev_min = minor (file_stat.st_dev);
520           file_hdr.c_ino = file_stat.st_ino;
521
522           /* Skip files larger than 4GB which will cause problems on
523              64bit platforms (and just not work on 32bit). */
524           if (file_stat.st_size > 0xffffffff) {
525             error (0, 0, "%s: skipping >4GB file", input_name.ds_string);
526             continue;
527           }
528
529           /* For POSIX systems that don't define the S_IF macros,
530              we can't assume that S_ISfoo means the standard Unix
531              S_IFfoo bit(s) are set.  So do it manually, with a
532              different name.  Bleah.  */
533           file_hdr.c_mode = (file_stat.st_mode & 07777);
534           if (S_ISREG (file_stat.st_mode))
535             file_hdr.c_mode |= CP_IFREG;
536           else if (S_ISDIR (file_stat.st_mode))
537             file_hdr.c_mode |= CP_IFDIR;
538 #ifdef S_ISBLK
539           else if (S_ISBLK (file_stat.st_mode))
540             file_hdr.c_mode |= CP_IFBLK;
541 #endif
542 #ifdef S_ISCHR
543           else if (S_ISCHR (file_stat.st_mode))
544             file_hdr.c_mode |= CP_IFCHR;
545 #endif
546 #ifdef S_ISFIFO
547           else if (S_ISFIFO (file_stat.st_mode))
548             file_hdr.c_mode |= CP_IFIFO;
549 #endif
550 #ifdef S_ISLNK
551           else if (S_ISLNK (file_stat.st_mode))
552             file_hdr.c_mode |= CP_IFLNK;
553 #endif
554 #ifdef S_ISSOCK
555           else if (S_ISSOCK (file_stat.st_mode))
556             file_hdr.c_mode |= CP_IFSOCK;
557 #endif
558 #ifdef S_ISNWK
559           else if (S_ISNWK (file_stat.st_mode))
560             file_hdr.c_mode |= CP_IFNWK;
561 #endif
562           file_hdr.c_uid = file_stat.st_uid;
563           file_hdr.c_gid = file_stat.st_gid;
564           file_hdr.c_nlink = file_stat.st_nlink;
565
566           /* The rdev is meaningless except for block and character
567              special files (POSIX standard) and perhaps fifos and
568              sockets.  Clear it for other types of files so that
569              check_rdev() doesn't reject files just because stat()
570              put garbage in st_rdev and so that the output doesn't
571              depend on the garbage.  */
572           switch (file_hdr.c_mode & CP_IFMT)
573             {
574               case CP_IFBLK:
575               case CP_IFCHR:
576 #ifdef CP_IFIFO
577               case CP_IFIFO:
578 #endif
579 #ifdef CP_IFSOCK
580               case CP_IFSOCK:
581 #endif
582                 file_hdr.c_rdev_maj = major (file_stat.st_rdev);
583                 file_hdr.c_rdev_min = minor (file_stat.st_rdev);
584                 break;
585               default:
586                 file_hdr.c_rdev_maj = 0;
587                 file_hdr.c_rdev_min = 0;
588                 break;
589             }
590
591           file_hdr.c_mtime = file_stat.st_mtime;
592           file_hdr.c_filesize = file_stat.st_size;
593           file_hdr.c_chksum = 0;
594           file_hdr.c_tar_linkname = NULL;
595           
596           if (archive_format == arf_tar || archive_format == arf_ustar)
597             {
598               if (file_hdr.c_mode & CP_IFDIR)
599                 {
600                   int len = strlen (input_name.ds_string);
601                   /* Make sure the name ends with a slash */
602                   if (input_name.ds_string[len-1] != '/')
603                     {
604                       ds_resize (&input_name, len + 2);
605                       input_name.ds_string[len] = '/';
606                       input_name.ds_string[len+1] = 0;
607                     }
608                 }
609             }
610           
611           /* Strip leading `./' from the filename.  */
612           p = input_name.ds_string;
613           while (*p == '.' && *(p + 1) == '/')
614             {
615               ++p;
616               while (*p == '/')
617                 ++p;
618             }
619 #ifndef HPUX_CDF
620           file_hdr.c_name = p;
621           file_hdr.c_namesize = strlen (p) + 1;
622 #else
623           if ( (archive_format != arf_tar) && (archive_format != arf_ustar) )
624             {
625               /* We mark CDF's in cpio files by adding a 2nd `/' after the
626                  "hidden" directory name.  We need to do this so we can
627                  properly recreate the directory as hidden (in case the
628                  files of a directory go into the archive before the
629                  directory itself (e.g from "find ... -depth ... | cpio")).  */
630               file_hdr.c_name = add_cdf_double_slashes (p);
631               file_hdr.c_namesize = strlen (file_hdr.c_name) + 1;
632             }
633           else
634             {
635               /* We don't mark CDF's in tar files.  We assume the "hidden"
636                  directory will always go into the archive before any of
637                  its files.  */
638               file_hdr.c_name = p;
639               file_hdr.c_namesize = strlen (p) + 1;
640             }
641 #endif
642           if ((archive_format == arf_tar || archive_format == arf_ustar)
643               && is_tar_filename_too_long (file_hdr.c_name))
644             {
645               error (0, 0, _("%s: file name too long"),
646                      file_hdr.c_name);
647               continue;
648             }
649
650           switch (check_rdev (&file_hdr))
651             {
652               case 1:
653                 error (0, 0, "%s not dumped: major number would be truncated",
654                        file_hdr.c_name);
655                 continue;
656               case 2:
657                 error (0, 0, "%s not dumped: minor number would be truncated",
658                        file_hdr.c_name);
659                 continue;
660               case 4:
661                 error (0, 0, "%s not dumped: device number would be truncated",
662                        file_hdr.c_name);
663                 continue;
664             }
665           
666           /* Copy the named file to the output.  */
667           switch (file_hdr.c_mode & CP_IFMT)
668             {
669             case CP_IFREG:
670               if (archive_format == arf_tar || archive_format == arf_ustar)
671                 {
672                   char *otherfile;
673                   if ((otherfile = find_inode_file (file_hdr.c_ino,
674                                                     file_hdr.c_dev_maj,
675                                                     file_hdr.c_dev_min)))
676                     {
677                       file_hdr.c_tar_linkname = otherfile;
678                       write_out_header (&file_hdr, out_file_des);
679                       break;
680                     }
681                 }
682               if ( (archive_format == arf_newascii || archive_format == arf_crcascii)
683                   && (file_hdr.c_nlink > 1) )
684                 {
685                   if (last_link (&file_hdr) )
686                     {
687                       writeout_other_defers (&file_hdr, out_file_des);
688                     }
689                   else
690                     {
691                       add_link_defer (&file_hdr);
692                       break;
693                     }
694                 }
695               in_file_des = open (input_name.ds_string,
696                                   O_RDONLY | O_BINARY, 0);
697               if (in_file_des < 0)
698                 {
699                   error (0, errno, "%s", input_name.ds_string);
700                   continue;
701                 }
702
703               if (archive_format == arf_crcascii)
704                 file_hdr.c_chksum = read_for_checksum (in_file_des,
705                                                        file_hdr.c_filesize,
706                                                        input_name.ds_string);
707
708               write_out_header (&file_hdr, out_file_des);
709               copy_files_disk_to_tape (in_file_des, out_file_des, file_hdr.c_filesize, input_name.ds_string);
710               warn_if_file_changed(input_name.ds_string, file_hdr.c_filesize,
711                                    file_hdr.c_mtime);
712
713               if (archive_format == arf_tar || archive_format == arf_ustar)
714                 add_inode (file_hdr.c_ino, file_hdr.c_name, file_hdr.c_dev_maj,
715                            file_hdr.c_dev_min);
716
717               tape_pad_output (out_file_des, file_hdr.c_filesize);
718
719               if (close (in_file_des) < 0)
720                 error (0, errno, "%s", input_name.ds_string);
721               if (reset_time_flag)
722                 {
723                   times.actime = file_stat.st_atime;
724                   times.modtime = file_stat.st_mtime;
725                   /* Debian hack: Silently ignore EROFS because
726                      reading the file won't have upset its timestamp
727                      if it's on a read-only filesystem.  This has been
728                      submitted as a suggestion to
729                      "bug-gnu-utils@prep.ai.mit.edu".  -BEM */
730                   if (utime (file_hdr.c_name, &times) < 0
731                       && errno != EROFS)
732                     error (0, errno, "%s", file_hdr.c_name);
733                 }
734               break;
735
736             case CP_IFDIR:
737               file_hdr.c_filesize = 0;
738               write_out_header (&file_hdr, out_file_des);
739               break;
740
741             case CP_IFCHR:
742             case CP_IFBLK:
743 #ifdef CP_IFSOCK
744             case CP_IFSOCK:
745 #endif
746 #ifdef CP_IFIFO
747             case CP_IFIFO:
748 #endif
749               if (archive_format == arf_tar)
750                 {
751                   error (0, 0, _("%s not dumped: not a regular file"),
752                          file_hdr.c_name);
753                   continue;
754                 }
755               else if (archive_format == arf_ustar)
756                 {
757                   char *otherfile;
758                   if ((otherfile = find_inode_file (file_hdr.c_ino,
759                                                     file_hdr.c_dev_maj,
760                                                     file_hdr.c_dev_min)))
761                     {
762                       /* This file is linked to another file already in the 
763                          archive, so write it out as a hard link. */
764                       file_hdr.c_mode = (file_stat.st_mode & 07777);
765                       file_hdr.c_mode |= CP_IFREG;
766                       file_hdr.c_tar_linkname = otherfile;
767                       write_out_header (&file_hdr, out_file_des);
768                       break;
769                     }
770                   add_inode (file_hdr.c_ino, file_hdr.c_name, 
771                              file_hdr.c_dev_maj, file_hdr.c_dev_min);
772                 }
773               file_hdr.c_filesize = 0;
774               write_out_header (&file_hdr, out_file_des);
775               break;
776
777 #ifdef CP_IFLNK
778             case CP_IFLNK:
779               {
780                 char *link_name = (char *) xmalloc (file_stat.st_size + 1);
781                 int link_size;
782
783                 link_size = readlink (input_name.ds_string, link_name,
784                                       file_stat.st_size);
785                 if (link_size < 0)
786                   {
787                     error (0, errno, "%s", input_name.ds_string);
788                     free (link_name);
789                     continue;
790                   }
791                 file_hdr.c_filesize = link_size;
792                 if (archive_format == arf_tar || archive_format == arf_ustar)
793                   {
794                     if (link_size + 1 > 100)
795                       {
796                         error (0, 0, _("%s: symbolic link too long"),
797                                file_hdr.c_name);
798                       }
799                     else
800                       {
801                         link_name[link_size] = '\0';
802                         file_hdr.c_tar_linkname = link_name;
803                         write_out_header (&file_hdr, out_file_des);
804                       }
805                   }
806                 else
807                   {
808                     write_out_header (&file_hdr, out_file_des);
809                     tape_buffered_write (link_name, out_file_des, link_size);
810                     tape_pad_output (out_file_des, link_size);
811                   }
812                 free (link_name);
813               }
814               break;
815 #endif
816
817             default:
818               error (0, 0, _("%s: unknown file type"), input_name.ds_string);
819             }
820
821           if (verbose_flag)
822             fprintf (stderr, "%s\n", input_name.ds_string);
823           if (dot_flag)
824             fputc ('.', stderr);
825         }
826     }
827
828   writeout_final_defers(out_file_des);
829   /* The collection is complete; append the trailer.  */
830   file_hdr.c_ino = 0;
831   file_hdr.c_mode = 0;
832   file_hdr.c_uid = 0;
833   file_hdr.c_gid = 0;
834   file_hdr.c_nlink = 1;         /* Must be 1 for crc format.  */
835   file_hdr.c_dev_maj = 0;
836   file_hdr.c_dev_min = 0;
837   file_hdr.c_rdev_maj = 0;
838   file_hdr.c_rdev_min = 0;
839   file_hdr.c_mtime = 0;
840   file_hdr.c_chksum = 0;
841
842   file_hdr.c_filesize = 0;
843   file_hdr.c_namesize = 11;
844   file_hdr.c_name = "TRAILER!!!";
845   if (archive_format != arf_tar && archive_format != arf_ustar)
846     write_out_header (&file_hdr, out_file_des);
847   else
848     {
849       tape_buffered_write (zeros_512, out_file_des, 512);
850       tape_buffered_write (zeros_512, out_file_des, 512);
851     }
852
853   /* Fill up the output block.  */
854   tape_clear_rest_of_block (out_file_des);
855   tape_empty_output_buffer (out_file_des);
856   if (dot_flag)
857     fputc ('\n', stderr);
858   if (!quiet_flag)
859     {
860       res = (output_bytes + io_block_size - 1) / io_block_size;
861       fprintf (stderr, ngettext ("%d block\n", "%d blocks\n", res), res);
862     }
863 }
864
865 static int
866 check_rdev (file_hdr)
867      struct new_cpio_header *file_hdr;
868 {
869   if (archive_format == arf_newascii || archive_format == arf_crcascii)
870     {
871       if ((file_hdr->c_rdev_maj & 0xFFFFFFFF) != file_hdr->c_rdev_maj)
872         return 1;
873       if ((file_hdr->c_rdev_min & 0xFFFFFFFF) != file_hdr->c_rdev_min)
874         return 2;
875     }
876   else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
877     {
878 #ifndef __MSDOS__
879       dev_t rdev;
880
881       rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
882       if (archive_format == arf_oldascii)
883         {
884           if ((rdev & 0xFFFF) != rdev)
885             return 4;
886         }
887       else
888         {
889           switch (file_hdr->c_mode & CP_IFMT)
890             {
891               case CP_IFCHR:
892               case CP_IFBLK:
893 #ifdef CP_IFSOCK
894               case CP_IFSOCK:
895 #endif
896 #ifdef CP_IFIFO
897               case CP_IFIFO:
898 #endif
899                 /* We could handle one more bit if longs are >= 33 bits.  */
900                 if ((rdev & 037777777777) != rdev)
901                   return 4;
902                 break;
903               default:
904                 if ((rdev & 0xFFFF) != rdev)
905                   return 4;
906                 break;
907             }
908         }
909 #endif
910     }
911   else if (archive_format == arf_tar || archive_format == arf_ustar)
912     {
913       /* The major and minor formats are limited to 7 octal digits in ustar
914          format, and to_oct () adds a gratuitous trailing blank to further
915          limit the format to 6 octal digits.  */
916       if ((file_hdr->c_rdev_maj & 0777777) != file_hdr->c_rdev_maj)
917         return 1;
918       if ((file_hdr->c_rdev_min & 0777777) != file_hdr->c_rdev_min)
919         return 2;
920     }
921   else
922     {
923 #ifndef __MSDOS__
924       dev_t rdev;
925
926       rdev = makedev (file_hdr->c_rdev_maj, file_hdr->c_rdev_min);
927       if (archive_format != arf_hpbinary)
928         {
929           if ((rdev & 0xFFFF) != rdev)
930         return 4;
931     }
932   else
933     {
934       switch (file_hdr->c_mode & CP_IFMT)
935         {
936           case CP_IFCHR:
937           case CP_IFBLK:
938 #ifdef CP_IFSOCK
939           case CP_IFSOCK:
940 #endif
941 #ifdef CP_IFIFO
942           case CP_IFIFO:
943 #endif
944             if ((rdev & 0xFFFFFFFF) != rdev)
945               return 4;
946             file_hdr->c_filesize = rdev;
947             rdev = makedev (0, 1);
948             break;
949           default:
950             if ((rdev & 0xFFFF) != rdev)
951               return 4;
952             break;
953         }
954     }
955 #endif
956   }
957   return 0;
958 }