]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - contrib/cpio/src/tar.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / contrib / cpio / src / tar.c
1 /* $FreeBSD$ */
2
3 /* tar.c - read in write tar headers for cpio
4    Copyright (C) 1992, 2001, 2004, 2006 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
17    License along with this program; if not, write to the Free
18    Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301 USA.  */
20
21 #include <system.h>
22
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include "filetypes.h"
27 #include "cpiohdr.h"
28 #include "dstring.h"
29 #include "extern.h"
30 #include <rmt.h>
31 #include "tarhdr.h"
32
33 /* Stash the tar linkname in static storage.  */
34
35 static char *
36 stash_tar_linkname (char *linkname)
37 {
38   static char hold_tar_linkname[TARLINKNAMESIZE + 1];
39
40   strncpy (hold_tar_linkname, linkname, TARLINKNAMESIZE);
41   hold_tar_linkname[TARLINKNAMESIZE] = '\0';
42   return hold_tar_linkname;
43 }
44
45 /* Try to split a long file name into prefix and suffix parts separated
46    by a slash. Return the length of the prefix (not counting the slash). */
47    
48 static size_t
49 split_long_name (const char *name, size_t length)
50 {
51   size_t i;
52
53   if (length > TARPREFIXSIZE)
54     length = TARPREFIXSIZE+2;
55   for (i = length - 1; i > 0; i--)
56     if (name[i] == '/')
57       break;
58   return i;
59 }
60
61 /* Stash the tar filename and optional prefix in static storage.  */
62
63 static char *
64 stash_tar_filename (char *prefix, char *filename)
65 {
66   static char hold_tar_filename[TARNAMESIZE + TARPREFIXSIZE + 2];
67   if (prefix == NULL || *prefix == '\0')
68     {
69       strncpy (hold_tar_filename, filename, TARNAMESIZE);
70       hold_tar_filename[TARNAMESIZE] = '\0';
71     }
72   else
73     {
74       strncpy (hold_tar_filename, prefix, TARPREFIXSIZE);
75       hold_tar_filename[TARPREFIXSIZE] = '\0';
76       strcat (hold_tar_filename, "/");
77       strncat (hold_tar_filename, filename, TARNAMESIZE);
78       hold_tar_filename[TARPREFIXSIZE + TARNAMESIZE] = '\0';
79     }
80   return hold_tar_filename;
81 }
82
83 /* Convert a number into a string of octal digits.
84    Convert long VALUE into a DIGITS-digit field at WHERE,
85    including a trailing space and room for a NUL.  DIGITS==3 means
86    1 digit, a space, and room for a NUL.
87
88    We assume the trailing NUL is already there and don't fill it in.
89    This fact is used by start_header and finish_header, so don't change it!
90
91    This is be equivalent to:
92    sprintf (where, "%*lo ", digits - 2, value);
93    except that sprintf fills in the trailing NUL and we don't.  */
94
95 static void
96 to_oct (register long value, register int digits, register char *where)
97 {
98   --digits;                     /* Leave the trailing NUL slot alone.  */
99
100   /* Produce the digits -- at least one.  */
101   do
102     {
103       where[--digits] = '0' + (char) (value & 7); /* One octal digit.  */
104       value >>= 3;
105     }
106   while (digits > 0 && value != 0);
107
108   /* Add leading zeroes, if necessary.  */
109   while (digits > 0)
110     where[--digits] = '0';
111 }
112
113 \f
114
115 /* Compute and return a checksum for TAR_HDR,
116    counting the checksum bytes as if they were spaces.  */
117
118 unsigned int
119 tar_checksum (struct tar_header *tar_hdr)
120 {
121   unsigned int sum = 0;
122   char *p = (char *) tar_hdr;
123   char *q = p + TARRECORDSIZE;
124   int i;
125
126   while (p < tar_hdr->chksum)
127     sum += *p++ & 0xff;
128   for (i = 0; i < 8; ++i)
129     {
130       sum += ' ';
131       ++p;
132     }
133   while (p < q)
134     sum += *p++ & 0xff;
135   return sum;
136 }
137
138 /* Write out header FILE_HDR, including the file name, to file
139    descriptor OUT_DES.  */
140
141 void
142 write_out_tar_header (struct cpio_file_stat *file_hdr, int out_des)
143 {
144   int name_len;
145   union tar_record tar_rec;
146   struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
147
148   memset (&tar_rec, 0, sizeof tar_rec);
149
150   /* process_copy_out must ensure that file_hdr->c_name is short enough,
151      or we will lose here.  */
152
153   name_len = strlen (file_hdr->c_name);
154   if (name_len <= TARNAMESIZE)
155     {
156       strncpy (tar_hdr->name, file_hdr->c_name, name_len);
157     }
158   else
159     {
160       /* Fit as much as we can into `name', the rest into `prefix'.  */
161       int prefix_len = split_long_name (file_hdr->c_name, name_len);
162
163       strncpy (tar_hdr->prefix, file_hdr->c_name, prefix_len);
164       strncpy (tar_hdr->name, file_hdr->c_name + prefix_len + 1,
165                name_len - prefix_len - 1);
166     }
167
168   /* Ustar standard (POSIX.1-1988) requires the mode to contain only 3 octal
169      digits */
170   to_oct (file_hdr->c_mode & MODE_ALL, 8, tar_hdr->mode);
171   to_oct (file_hdr->c_uid, 8, tar_hdr->uid);
172   to_oct (file_hdr->c_gid, 8, tar_hdr->gid);
173   to_oct (file_hdr->c_filesize, 12, tar_hdr->size);
174   to_oct (file_hdr->c_mtime, 12, tar_hdr->mtime);
175
176   switch (file_hdr->c_mode & CP_IFMT)
177     {
178     case CP_IFREG:
179       if (file_hdr->c_tar_linkname)
180         {
181           /* process_copy_out makes sure that c_tar_linkname is shorter
182              than TARLINKNAMESIZE.  */
183           strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
184                    TARLINKNAMESIZE);
185           tar_hdr->typeflag = LNKTYPE;
186           to_oct (0, 12, tar_hdr->size);
187         }
188       else
189         tar_hdr->typeflag = REGTYPE;
190       break;
191     case CP_IFDIR:
192       tar_hdr->typeflag = DIRTYPE;
193       break;
194     case CP_IFCHR:
195       tar_hdr->typeflag = CHRTYPE;
196       break;
197     case CP_IFBLK:
198       tar_hdr->typeflag = BLKTYPE;
199       break;
200 #ifdef CP_IFIFO
201     case CP_IFIFO:
202       tar_hdr->typeflag = FIFOTYPE;
203       break;
204 #endif /* CP_IFIFO */
205 #ifdef CP_IFLNK
206     case CP_IFLNK:
207       tar_hdr->typeflag = SYMTYPE;
208       /* process_copy_out makes sure that c_tar_linkname is shorter
209          than TARLINKNAMESIZE.  */
210       strncpy (tar_hdr->linkname, file_hdr->c_tar_linkname,
211                TARLINKNAMESIZE);
212       to_oct (0, 12, tar_hdr->size);
213       break;
214 #endif /* CP_IFLNK */
215     }
216
217   if (archive_format == arf_ustar)
218     {
219       char *name;
220
221       strncpy (tar_hdr->magic, TMAGIC, TMAGLEN);
222       strncpy (tar_hdr->magic + TMAGLEN, TVERSION, TVERSLEN);
223
224       name = getuser (file_hdr->c_uid);
225       if (name)
226         strcpy (tar_hdr->uname, name);
227       name = getgroup (file_hdr->c_gid);
228       if (name)
229         strcpy (tar_hdr->gname, name);
230
231       to_oct (file_hdr->c_rdev_maj, 8, tar_hdr->devmajor);
232       to_oct (file_hdr->c_rdev_min, 8, tar_hdr->devminor);
233     }
234
235   to_oct (tar_checksum (tar_hdr), 8, tar_hdr->chksum);
236
237   tape_buffered_write ((char *) &tar_rec, out_des, TARRECORDSIZE);
238 }
239
240 /* Return nonzero iff all the bytes in BLOCK are NUL.
241    SIZE is the number of bytes to check in BLOCK; it must be a
242    multiple of sizeof (long).  */
243
244 int
245 null_block (long *block, int size)
246 {
247   register long *p = block;
248   register int i = size / sizeof (long);
249
250   while (i--)
251     if (*p++)
252       return 0;
253   return 1;
254 }
255
256 /* Read a tar header, including the file name, from file descriptor IN_DES
257    into FILE_HDR.  */
258
259 void
260 read_in_tar_header (struct cpio_file_stat *file_hdr, int in_des)
261 {
262   long bytes_skipped = 0;
263   int warned = false;
264   union tar_record tar_rec;
265   struct tar_header *tar_hdr = (struct tar_header *) &tar_rec;
266   uid_t *uidp;
267   gid_t *gidp;
268
269   tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
270
271   /* Check for a block of 0's.  */
272   if (null_block ((long *) &tar_rec, TARRECORDSIZE))
273     {
274 #if 0
275       /* Found one block of 512 0's.  If the next block is also all 0's
276          then this is the end of the archive.  If not, assume the
277          previous block was all corruption and continue reading
278          the archive.  */
279       /* Commented out because GNU tar sometimes creates archives with
280          only one block of 0's at the end.  This happened for the
281          cpio 2.0 distribution!  */
282       tape_buffered_read ((char *) &tar_rec, in_des, TARRECORDSIZE);
283       if (null_block ((long *) &tar_rec, TARRECORDSIZE))
284 #endif
285         {
286           file_hdr->c_name = CPIO_TRAILER_NAME;
287           return;
288         }
289 #if 0
290       bytes_skipped = TARRECORDSIZE;
291 #endif
292     }
293
294   while (1)
295     {
296       file_hdr->c_chksum = FROM_OCTAL (tar_hdr->chksum);
297
298       if (file_hdr->c_chksum != tar_checksum (tar_hdr))
299         {
300           /* If the checksum is bad, skip 1 byte and try again.  When
301              we try again we do not look for an EOF record (all zeros),
302              because when we start skipping bytes in a corrupted archive
303              the chances are pretty good that we might stumble across
304              2 blocks of 512 zeros (that probably is not really the last
305              record) and it is better to miss the EOF and give the user
306              a "premature EOF" error than to give up too soon on a corrupted
307              archive.  */
308           if (!warned)
309             {
310               error (0, 0, _("invalid header: checksum error"));
311               warned = true;
312             }
313           memmove (&tar_rec, ((char *) &tar_rec) + 1, TARRECORDSIZE - 1);
314           tape_buffered_read (((char *) &tar_rec) + (TARRECORDSIZE - 1), in_des, 1);
315           ++bytes_skipped;
316           continue;
317         }
318
319       if (archive_format != arf_ustar)
320         file_hdr->c_name = stash_tar_filename (NULL, tar_hdr->name);
321       else
322         file_hdr->c_name = stash_tar_filename (tar_hdr->prefix, tar_hdr->name);
323       file_hdr->c_nlink = 1;
324       file_hdr->c_mode = FROM_OCTAL (tar_hdr->mode);
325       file_hdr->c_mode = file_hdr->c_mode & 07777;
326   /* Debian hack: This version of cpio uses the -n flag also to extract
327      tar archives using the numeric UID/GID instead of the user/group
328      names in /etc/passwd and /etc/groups.  (98/10/15) -BEM */
329       if (archive_format == arf_ustar && !numeric_uid
330           && (uidp = getuidbyname (tar_hdr->uname)))
331         file_hdr->c_uid = *uidp;
332       else
333         file_hdr->c_uid = FROM_OCTAL (tar_hdr->uid);
334
335       if (archive_format == arf_ustar && !numeric_uid
336           && (gidp = getgidbyname (tar_hdr->gname)))
337         file_hdr->c_gid = *gidp;
338       else
339         file_hdr->c_gid = FROM_OCTAL (tar_hdr->gid);
340       file_hdr->c_filesize = FROM_OCTAL (tar_hdr->size);
341       file_hdr->c_mtime = FROM_OCTAL (tar_hdr->mtime);
342       file_hdr->c_rdev_maj = FROM_OCTAL (tar_hdr->devmajor);
343       file_hdr->c_rdev_min = FROM_OCTAL (tar_hdr->devminor);
344       file_hdr->c_tar_linkname = NULL;
345
346       switch (tar_hdr->typeflag)
347         {
348         case REGTYPE:
349         case CONTTYPE:          /* For now, punt.  */
350         default:
351           file_hdr->c_mode |= CP_IFREG;
352           break;
353         case DIRTYPE:
354           file_hdr->c_mode |= CP_IFDIR;
355           break;
356         case CHRTYPE:
357           file_hdr->c_mode |= CP_IFCHR;
358           /* If a POSIX tar header has a valid linkname it's always supposed
359              to set typeflag to be LNKTYPE.  System V.4 tar seems to
360              be broken, and for device files with multiple links it
361              puts the name of the link into linkname, but leaves typeflag 
362              as CHRTYPE, BLKTYPE, FIFOTYPE, etc.  */
363           file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
364
365           /* Does POSIX say that the filesize must be 0 for devices?  We
366              assume so, but HPUX's POSIX tar sets it to be 1 which causes
367              us problems (when reading an archive we assume we can always
368              skip to the next file by skipping filesize bytes).  For 
369              now at least, it's easier to clear filesize for devices,
370              rather than check everywhere we skip in copyin.c.  */
371           file_hdr->c_filesize = 0;
372           break;
373         case BLKTYPE:
374           file_hdr->c_mode |= CP_IFBLK;
375           file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
376           file_hdr->c_filesize = 0;
377           break;
378 #ifdef CP_IFIFO
379         case FIFOTYPE:
380           file_hdr->c_mode |= CP_IFIFO;
381           file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
382           file_hdr->c_filesize = 0;
383           break;
384 #endif
385         case SYMTYPE:
386 #ifdef CP_IFLNK
387           file_hdr->c_mode |= CP_IFLNK;
388           file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
389           file_hdr->c_filesize = 0;
390           break;
391           /* Else fall through.  */
392 #endif
393         case LNKTYPE:
394           file_hdr->c_mode |= CP_IFREG;
395           file_hdr->c_tar_linkname = stash_tar_linkname (tar_hdr->linkname);
396           file_hdr->c_filesize = 0;
397           break;
398
399         case AREGTYPE:
400           /* Old tar format; if the last char in filename is '/' then it is
401              a directory, otherwise it's a regular file.  */
402           if (file_hdr->c_name[strlen (file_hdr->c_name) - 1] == '/')
403             file_hdr->c_mode |= CP_IFDIR;
404           else
405             file_hdr->c_mode |= CP_IFREG;
406           break;
407         case 'x': case 'g':
408           /* Ignore pax 'x' and 'g' extension entries. */
409           /* Skip body of this entry. */
410           while (file_hdr->c_filesize > 0) {
411             tape_buffered_read(((char *) &tar_rec), in_des, TARRECORDSIZE);
412             if (file_hdr->c_filesize > TARRECORDSIZE)
413                     file_hdr->c_filesize -= TARRECORDSIZE;
414             else
415                     file_hdr->c_filesize = 0;
416           }
417           /* Read next header and return that instead. */
418           read_in_tar_header(file_hdr, in_des);
419           break;
420         }
421       break;
422     }
423   if (bytes_skipped > 0)
424     warn_junk_bytes (bytes_skipped);
425 }
426
427 /* Return
428    2 if BUF is a valid POSIX tar header (the checksum is correct
429    and it has the "ustar" magic string),
430    1 if BUF is a valid old tar header (the checksum is correct),
431    0 otherwise.  */
432
433 int
434 is_tar_header (char *buf)
435 {
436   struct tar_header *tar_hdr = (struct tar_header *) buf;
437   unsigned long chksum;
438
439   chksum = FROM_OCTAL (tar_hdr->chksum);
440
441   if (chksum != tar_checksum (tar_hdr))
442     return 0;
443
444   /* GNU tar 1.10 and previous set the magic field to be "ustar " instead
445      of "ustar\0".  Only look at the first 5 characters of the magic
446      field so we can recognize old GNU tar ustar archives.  */
447   if (!strncmp (tar_hdr->magic, TMAGIC, TMAGLEN - 1))
448       return 2;
449   return 1;
450 }
451
452 /* Return true if the filename is too long to fit in a tar header.
453    For old tar headers, if the filename's length is less than or equal
454    to 100 then it will fit, otherwise it will not.  For POSIX tar headers,
455    if the filename's length is less than or equal to 100 then it
456    will definitely fit, and if it is greater than 256 then it
457    will definitely not fit.  If the length is between 100 and 256,
458    then the filename will fit only if it is possible to break it
459    into a 155 character "prefix" and 100 character "name".  There
460    must be a slash between the "prefix" and the "name", although
461    the slash is not stored or counted in either the "prefix" or
462    the "name", and there must be at least one character in both
463    the "prefix" and the "name".  If it is not possible to break down
464    the filename like this then it will not fit.  */
465
466 int
467 is_tar_filename_too_long (char *name)
468 {
469   int whole_name_len;
470   int prefix_name_len;
471
472   whole_name_len = strlen (name);
473   if (whole_name_len <= TARNAMESIZE)
474     return false;
475
476   if (archive_format != arf_ustar)
477     return true;
478
479   if (whole_name_len > TARNAMESIZE + TARPREFIXSIZE + 1)
480     return true;
481
482   /* See whether we can split up the name into acceptably-sized
483      `prefix' and `name' (`p') pieces. */
484   prefix_name_len = split_long_name (name, whole_name_len);
485
486   /* Interestingly, a name consisting of a slash followed by
487      TARNAMESIZE characters can't be stored, because the prefix
488      would be empty, and thus ignored.  */
489   if (prefix_name_len == 0
490       || whole_name_len - prefix_name_len - 1 > TARNAMESIZE)
491     return true;
492
493   return false;
494 }