Import of libarchive and bsdtar 1.3.1
[dragonfly.git] / contrib / libarchive-1.3.1 / libarchive / archive_write_set_format_ustar.c
1 /*-
2  * Copyright (c) 2003-2004 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_ustar.c,v 1.14 2005/11/08 03:52:42 kientzle Exp $");
29
30 #include <sys/stat.h>
31 #ifdef MAJOR_IN_MKDEV
32 #include <sys/mkdev.h>
33 #else
34 #ifdef MAJOR_IN_SYSMACROS
35 #include <sys/sysmacros.h>
36 #endif
37 #endif
38 #include <errno.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "archive.h"
44 #include "archive_entry.h"
45 #include "archive_private.h"
46
47 struct ustar {
48         uint64_t        entry_bytes_remaining;
49         uint64_t        entry_padding;
50         char            written;
51 };
52
53 /*
54  * Define structure of POSIX 'ustar' tar header.
55  */
56 struct archive_entry_header_ustar {
57         char    name[100];
58         char    mode[6];
59         char    mode_padding[2];
60         char    uid[6];
61         char    uid_padding[2];
62         char    gid[6];
63         char    gid_padding[2];
64         char    size[11];
65         char    size_padding[1];
66         char    mtime[11];
67         char    mtime_padding[1];
68         char    checksum[8];
69         char    typeflag[1];
70         char    linkname[100];
71         char    magic[6]; /* For POSIX: "ustar\0" */
72         char    version[2]; /* For POSIX: "00" */
73         char    uname[32];
74         char    gname[32];
75         char    rdevmajor[6];
76         char    rdevmajor_padding[2];
77         char    rdevminor[6];
78         char    rdevminor_padding[2];
79         char    prefix[155];
80         char    padding[12];
81 };
82
83 /*
84  * A filled-in copy of the header for initialization.
85  */
86 static const struct archive_entry_header_ustar template_header = {
87         { "" },                         /* name */
88         { "000000" }, { ' ', '\0' },    /* mode, space-null termination. */
89         { "000000" }, { ' ', '\0' },    /* uid, space-null termination. */
90         { "000000" }, { ' ', '\0' },    /* gid, space-null termination. */
91         { "00000000000" }, { ' ' },     /* size, space termination. */
92         { "00000000000" }, { ' ' },     /* mtime, space termination. */
93         { "        " },                 /* Initial checksum value. */
94         { '0' },                        /* default: regular file */
95         { "" },                         /* linkname */
96         { "ustar" },                    /* magic */
97         { '0', '0' },                   /* version */
98         { "" },                         /* uname */
99         { "" },                         /* gname */
100         { "000000" }, { ' ', '\0' },    /* rdevmajor, space-null termination */
101         { "000000" }, { ' ', '\0' },    /* rdevminor, space-null termination */
102         { "" },                         /* prefix */
103         { "" }                          /* padding */
104 };
105
106 static ssize_t  archive_write_ustar_data(struct archive *a, const void *buff,
107                     size_t s);
108 static int      archive_write_ustar_finish(struct archive *);
109 static int      archive_write_ustar_finish_entry(struct archive *);
110 static int      archive_write_ustar_header(struct archive *,
111                     struct archive_entry *entry);
112 static int      format_256(int64_t, char *, int);
113 static int      format_number(int64_t, char *, int size, int max, int strict);
114 static int      format_octal(int64_t, char *, int);
115 static int      write_nulls(struct archive *a, size_t);
116
117 /*
118  * Set output format to 'ustar' format.
119  */
120 int
121 archive_write_set_format_ustar(struct archive *a)
122 {
123         struct ustar *ustar;
124
125         /* If someone else was already registered, unregister them. */
126         if (a->format_finish != NULL)
127                 (a->format_finish)(a);
128
129         ustar = malloc(sizeof(*ustar));
130         if (ustar == NULL) {
131                 archive_set_error(a, ENOMEM, "Can't allocate ustar data");
132                 return (ARCHIVE_FATAL);
133         }
134         memset(ustar, 0, sizeof(*ustar));
135         a->format_data = ustar;
136
137         a->pad_uncompressed = 1;        /* Mimic gtar in this respect. */
138         a->format_write_header = archive_write_ustar_header;
139         a->format_write_data = archive_write_ustar_data;
140         a->format_finish = archive_write_ustar_finish;
141         a->format_finish_entry = archive_write_ustar_finish_entry;
142         a->archive_format = ARCHIVE_FORMAT_TAR_USTAR;
143         a->archive_format_name = "POSIX ustar";
144         return (ARCHIVE_OK);
145 }
146
147 static int
148 archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
149 {
150         char buff[512];
151         int ret;
152         struct ustar *ustar;
153
154         ustar = a->format_data;
155         ustar->written = 1;
156
157         /* Only regular files (not hardlinks) have data. */
158         if (archive_entry_hardlink(entry) != NULL ||
159             archive_entry_symlink(entry) != NULL ||
160             !S_ISREG(archive_entry_mode(entry)))
161                 archive_entry_set_size(entry, 0);
162
163         ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1);
164         if (ret != ARCHIVE_OK)
165                 return (ret);
166         ret = (a->compression_write)(a, buff, 512);
167         if (ret != ARCHIVE_OK)
168                 return (ret);
169
170         ustar->entry_bytes_remaining = archive_entry_size(entry);
171         ustar->entry_padding = 0x1ff & (- ustar->entry_bytes_remaining);
172         return (ARCHIVE_OK);
173 }
174
175 /*
176  * Format a basic 512-byte "ustar" header.
177  *
178  * Returns -1 if format failed (due to field overflow).
179  * Note that this always formats as much of the header as possible.
180  * If "strict" is set to zero, it will extend numeric fields as
181  * necessary (overwriting terminators or using base-256 extensions).
182  *
183  * This is exported so that other 'tar' formats can use it.
184  */
185 int
186 __archive_write_format_header_ustar(struct archive *a, char buff[512],
187     struct archive_entry *entry, int tartype, int strict)
188 {
189         unsigned int checksum;
190         struct archive_entry_header_ustar *h;
191         int i, ret;
192         size_t copy_length;
193         const char *p, *pp;
194         const struct stat *st;
195         int mytartype;
196
197         ret = 0;
198         mytartype = -1;
199         /*
200          * The "template header" already includes the "ustar"
201          * signature, various end-of-field markers and other required
202          * elements.
203          */
204         memcpy(buff, &template_header, 512);
205
206         h = (struct archive_entry_header_ustar *)buff;
207
208         /*
209          * Because the block is already null-filled, and strings
210          * are allowed to exactly fill their destination (without null),
211          * I use memcpy(dest, src, strlen()) here a lot to copy strings.
212          */
213
214         pp = archive_entry_pathname(entry);
215         if (strlen(pp) <= sizeof(h->name))
216                 memcpy(h->name, pp, strlen(pp));
217         else {
218                 /* Store in two pieces, splitting at a '/'. */
219                 p = strchr(pp + strlen(pp) - sizeof(h->name) - 1, '/');
220                 /*
221                  * If there is no path separator, or the prefix or
222                  * remaining name are too large, return an error.
223                  */
224                 if (!p) {
225                         archive_set_error(a, ENAMETOOLONG,
226                             "Pathname too long");
227                         ret = ARCHIVE_WARN;
228                 } else if (p  > pp + sizeof(h->prefix)) {
229                         archive_set_error(a, ENAMETOOLONG,
230                             "Pathname too long");
231                         ret = ARCHIVE_WARN;
232                 } else {
233                         /* Copy prefix and remainder to appropriate places */
234                         memcpy(h->prefix, pp, p - pp);
235                         memcpy(h->name, p + 1, pp + strlen(pp) - p - 1);
236                 }
237         }
238
239         p = archive_entry_hardlink(entry);
240         if (p != NULL)
241                 mytartype = '1';
242         else
243                 p = archive_entry_symlink(entry);
244         if (p != NULL && p[0] != '\0') {
245                 copy_length = strlen(p);
246                 if (copy_length > sizeof(h->linkname)) {
247                         archive_set_error(a, ENAMETOOLONG,
248                             "Link contents too long");
249                         ret = ARCHIVE_WARN;
250                         copy_length = sizeof(h->linkname);
251                 }
252                 memcpy(h->linkname, p, copy_length);
253         }
254
255         p = archive_entry_uname(entry);
256         if (p != NULL && p[0] != '\0') {
257                 copy_length = strlen(p);
258                 if (copy_length > sizeof(h->uname)) {
259                         archive_set_error(a, ARCHIVE_ERRNO_MISC,
260                             "Username too long");
261                         ret = ARCHIVE_WARN;
262                         copy_length = sizeof(h->uname);
263                 }
264                 memcpy(h->uname, p, copy_length);
265         }
266
267         p = archive_entry_gname(entry);
268         if (p != NULL && p[0] != '\0') {
269                 copy_length = strlen(p);
270                 if (strlen(p) > sizeof(h->gname)) {
271                         archive_set_error(a, ARCHIVE_ERRNO_MISC,
272                             "Group name too long");
273                         ret = ARCHIVE_WARN;
274                         copy_length = sizeof(h->gname);
275                 }
276                 memcpy(h->gname, p, copy_length);
277         }
278
279         st = archive_entry_stat(entry);
280
281         if (format_number(st->st_mode & 07777, h->mode, sizeof(h->mode), 8, strict)) {
282                 archive_set_error(a, ERANGE, "Numeric mode too large");
283                 ret = ARCHIVE_WARN;
284         }
285
286         if (format_number(st->st_uid, h->uid, sizeof(h->uid), 8, strict)) {
287                 archive_set_error(a, ERANGE, "Numeric user ID too large");
288                 ret = ARCHIVE_WARN;
289         }
290
291         if (format_number(st->st_gid, h->gid, sizeof(h->gid), 8, strict)) {
292                 archive_set_error(a, ERANGE, "Numeric group ID too large");
293                 ret = ARCHIVE_WARN;
294         }
295
296         if (format_number(st->st_size, h->size, sizeof(h->size), 12, strict)) {
297                 archive_set_error(a, ERANGE, "File size out of range");
298                 ret = ARCHIVE_WARN;
299         }
300
301         if (format_number(st->st_mtime, h->mtime, sizeof(h->mtime), 12, strict)) {
302                 archive_set_error(a, ERANGE,
303                     "File modification time too large");
304                 ret = ARCHIVE_WARN;
305         }
306
307         if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) {
308                 if (format_number(major(st->st_rdev), h->rdevmajor,
309                         sizeof(h->rdevmajor), 8, strict)) {
310                         archive_set_error(a, ERANGE,
311                             "Major device number too large");
312                         ret = ARCHIVE_WARN;
313                 }
314
315                 if (format_number(minor(st->st_rdev), h->rdevminor,
316                         sizeof(h->rdevminor), 8, strict)) {
317                         archive_set_error(a, ERANGE,
318                             "Minor device number too large");
319                         ret = ARCHIVE_WARN;
320                 }
321         }
322
323         if (tartype >= 0) {
324                 h->typeflag[0] = tartype;
325         } else if (mytartype >= 0) {
326                 h->typeflag[0] = mytartype;
327         } else {
328                 switch (st->st_mode & S_IFMT) {
329                 case S_IFREG: h->typeflag[0] = '0' ; break;
330                 case S_IFLNK: h->typeflag[0] = '2' ; break;
331                 case S_IFCHR: h->typeflag[0] = '3' ; break;
332                 case S_IFBLK: h->typeflag[0] = '4' ; break;
333                 case S_IFDIR: h->typeflag[0] = '5' ; break;
334                 case S_IFIFO: h->typeflag[0] = '6' ; break;
335                 case S_IFSOCK:
336                         archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
337                             "tar format cannot archive socket");
338                         ret = ARCHIVE_WARN;
339                         break;
340                 default:
341                         archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
342                             "tar format cannot archive this (mode=0%lo)",
343                             (unsigned long)st->st_mode);
344                         ret = ARCHIVE_WARN;
345                 }
346         }
347
348         checksum = 0;
349         for (i = 0; i < 512; i++)
350                 checksum += 255 & (unsigned int)buff[i];
351         h->checksum[6] = '\0'; /* Can't be pre-set in the template. */
352         /* h->checksum[7] = ' '; */ /* This is pre-set in the template. */
353         format_octal(checksum, h->checksum, 6);
354         return (ret);
355 }
356
357 /*
358  * Format a number into a field, with some intelligence.
359  */
360 static int
361 format_number(int64_t v, char *p, int s, int maxsize, int strict)
362 {
363         int64_t limit;
364
365         limit = ((int64_t)1 << (s*3));
366
367         /* "Strict" only permits octal values with proper termination. */
368         if (strict)
369                 return (format_octal(v, p, s));
370
371         /*
372          * In non-strict mode, we allow the number to overwrite one or
373          * more bytes of the field termination.  Even old tar
374          * implementations should be able to handle this with no
375          * problem.
376          */
377         if (v >= 0) {
378                 while (s <= maxsize) {
379                         if (v < limit)
380                                 return (format_octal(v, p, s));
381                         s++;
382                         limit <<= 3;
383                 }
384         }
385
386         /* Base-256 can handle any number, positive or negative. */
387         return (format_256(v, p, maxsize));
388 }
389
390 /*
391  * Format a number into the specified field using base-256.
392  */
393 static int
394 format_256(int64_t v, char *p, int s)
395 {
396         p += s;
397         while (s-- > 0) {
398                 *--p = (char)(v & 0xff);
399                 v >>= 8;
400         }
401         *p |= 0x80; /* Set the base-256 marker bit. */
402         return (0);
403 }
404
405 /*
406  * Format a number into the specified field.
407  */
408 static int
409 format_octal(int64_t v, char *p, int s)
410 {
411         int len;
412
413         len = s;
414
415         /* Octal values can't be negative, so use 0. */
416         if (v < 0) {
417                 while (len-- > 0)
418                         *p++ = '0';
419                 return (-1);
420         }
421
422         p += s;         /* Start at the end and work backwards. */
423         while (s-- > 0) {
424                 *--p = '0' + (v & 7);
425                 v >>= 3;
426         }
427
428         if (v == 0)
429                 return (0);
430
431         /* If it overflowed, fill field with max value. */
432         while (len-- > 0)
433                 *p++ = '7';
434
435         return (-1);
436 }
437
438 static int
439 archive_write_ustar_finish(struct archive *a)
440 {
441         struct ustar *ustar;
442         int r;
443
444         r = ARCHIVE_OK;
445         ustar = a->format_data;
446         /*
447          * Suppress end-of-archive if nothing else was ever written.
448          * This fixes a problem where setting one format, then another
449          * ends up writing a gratuitous end-of-archive marker.
450          */
451         if (ustar->written && a->compression_write != NULL)
452                 r = write_nulls(a, 512*2);
453         free(ustar);
454         a->format_data = NULL;
455         return (r);
456 }
457
458 static int
459 archive_write_ustar_finish_entry(struct archive *a)
460 {
461         struct ustar *ustar;
462         int ret;
463
464         ustar = a->format_data;
465         ret = write_nulls(a,
466             ustar->entry_bytes_remaining + ustar->entry_padding);
467         ustar->entry_bytes_remaining = ustar->entry_padding = 0;
468         return (ret);
469 }
470
471 static int
472 write_nulls(struct archive *a, size_t padding)
473 {
474         int ret, to_write;
475
476         while (padding > 0) {
477                 to_write = padding < a->null_length ? padding : a->null_length;
478                 ret = (a->compression_write)(a, a->nulls, to_write);
479                 if (ret != ARCHIVE_OK)
480                         return (ret);
481                 padding -= to_write;
482         }
483         return (ARCHIVE_OK);
484 }
485
486 static ssize_t
487 archive_write_ustar_data(struct archive *a, const void *buff, size_t s)
488 {
489         struct ustar *ustar;
490         int ret;
491
492         ustar = a->format_data;
493         if (s > ustar->entry_bytes_remaining)
494                 s = ustar->entry_bytes_remaining;
495         ret = (a->compression_write)(a, buff, s);
496         ustar->entry_bytes_remaining -= s;
497         if (ret != ARCHIVE_OK)
498                 return (ret);
499         return (s);
500 }