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