~sergei.glushchenko/+junk/page-scan-hack

« back to all changes in this revision

Viewing changes to src/libarchive/libarchive/archive_write_set_format_ustar.c

merge parallel compression branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2007 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
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 *
 
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
17
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
24
 */
 
25
 
 
26
#include "archive_platform.h"
 
27
__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ustar.c 191579 2009-04-27 18:35:03Z kientzle $");
 
28
 
 
29
 
 
30
#ifdef HAVE_ERRNO_H
 
31
#include <errno.h>
 
32
#endif
 
33
#include <stdio.h>
 
34
#ifdef HAVE_STDLIB_H
 
35
#include <stdlib.h>
 
36
#endif
 
37
#ifdef HAVE_STRING_H
 
38
#include <string.h>
 
39
#endif
 
40
 
 
41
#include "archive.h"
 
42
#include "archive_entry.h"
 
43
#include "archive_private.h"
 
44
#include "archive_write_private.h"
 
45
 
 
46
struct ustar {
 
47
        uint64_t        entry_bytes_remaining;
 
48
        uint64_t        entry_padding;
 
49
};
 
50
 
 
51
/*
 
52
 * Define structure of POSIX 'ustar' tar header.
 
53
 */
 
54
#define USTAR_name_offset 0
 
55
#define USTAR_name_size 100
 
56
#define USTAR_mode_offset 100
 
57
#define USTAR_mode_size 6
 
58
#define USTAR_mode_max_size 8
 
59
#define USTAR_uid_offset 108
 
60
#define USTAR_uid_size 6
 
61
#define USTAR_uid_max_size 8
 
62
#define USTAR_gid_offset 116
 
63
#define USTAR_gid_size 6
 
64
#define USTAR_gid_max_size 8
 
65
#define USTAR_size_offset 124
 
66
#define USTAR_size_size 11
 
67
#define USTAR_size_max_size 12
 
68
#define USTAR_mtime_offset 136
 
69
#define USTAR_mtime_size 11
 
70
#define USTAR_mtime_max_size 11
 
71
#define USTAR_checksum_offset 148
 
72
#define USTAR_checksum_size 8
 
73
#define USTAR_typeflag_offset 156
 
74
#define USTAR_typeflag_size 1
 
75
#define USTAR_linkname_offset 157
 
76
#define USTAR_linkname_size 100
 
77
#define USTAR_magic_offset 257
 
78
#define USTAR_magic_size 6
 
79
#define USTAR_version_offset 263
 
80
#define USTAR_version_size 2
 
81
#define USTAR_uname_offset 265
 
82
#define USTAR_uname_size 32
 
83
#define USTAR_gname_offset 297
 
84
#define USTAR_gname_size 32
 
85
#define USTAR_rdevmajor_offset 329
 
86
#define USTAR_rdevmajor_size 6
 
87
#define USTAR_rdevmajor_max_size 8
 
88
#define USTAR_rdevminor_offset 337
 
89
#define USTAR_rdevminor_size 6
 
90
#define USTAR_rdevminor_max_size 8
 
91
#define USTAR_prefix_offset 345
 
92
#define USTAR_prefix_size 155
 
93
#define USTAR_padding_offset 500
 
94
#define USTAR_padding_size 12
 
95
 
 
96
/*
 
97
 * A filled-in copy of the header for initialization.
 
98
 */
 
99
static const char template_header[] = {
 
100
        /* name: 100 bytes */
 
101
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
102
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
103
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
104
        0,0,0,0,
 
105
        /* Mode, space-null termination: 8 bytes */
 
106
        '0','0','0','0','0','0', ' ','\0',
 
107
        /* uid, space-null termination: 8 bytes */
 
108
        '0','0','0','0','0','0', ' ','\0',
 
109
        /* gid, space-null termination: 8 bytes */
 
110
        '0','0','0','0','0','0', ' ','\0',
 
111
        /* size, space termation: 12 bytes */
 
112
        '0','0','0','0','0','0','0','0','0','0','0', ' ',
 
113
        /* mtime, space termation: 12 bytes */
 
114
        '0','0','0','0','0','0','0','0','0','0','0', ' ',
 
115
        /* Initial checksum value: 8 spaces */
 
116
        ' ',' ',' ',' ',' ',' ',' ',' ',
 
117
        /* Typeflag: 1 byte */
 
118
        '0',                    /* '0' = regular file */
 
119
        /* Linkname: 100 bytes */
 
120
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
121
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
122
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
123
        0,0,0,0,
 
124
        /* Magic: 6 bytes, Version: 2 bytes */
 
125
        'u','s','t','a','r','\0', '0','0',
 
126
        /* Uname: 32 bytes */
 
127
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
128
        /* Gname: 32 bytes */
 
129
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
130
        /* rdevmajor + space/null padding: 8 bytes */
 
131
        '0','0','0','0','0','0', ' ','\0',
 
132
        /* rdevminor + space/null padding: 8 bytes */
 
133
        '0','0','0','0','0','0', ' ','\0',
 
134
        /* Prefix: 155 bytes */
 
135
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
136
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
137
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
138
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
 
139
        0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,
 
140
        /* Padding: 12 bytes */
 
141
        0,0,0,0,0,0,0,0, 0,0,0,0
 
142
};
 
143
 
 
144
static ssize_t  archive_write_ustar_data(struct archive_write *a, const void *buff,
 
145
                    size_t s);
 
146
static int      archive_write_ustar_destroy(struct archive_write *);
 
147
static int      archive_write_ustar_finish(struct archive_write *);
 
148
static int      archive_write_ustar_finish_entry(struct archive_write *);
 
149
static int      archive_write_ustar_header(struct archive_write *,
 
150
                    struct archive_entry *entry);
 
151
static int      format_256(int64_t, char *, int);
 
152
static int      format_number(int64_t, char *, int size, int max, int strict);
 
153
static int      format_octal(int64_t, char *, int);
 
154
static int      write_nulls(struct archive_write *a, size_t);
 
155
 
 
156
/*
 
157
 * Set output format to 'ustar' format.
 
158
 */
 
159
int
 
160
archive_write_set_format_ustar(struct archive *_a)
 
161
{
 
162
        struct archive_write *a = (struct archive_write *)_a;
 
163
        struct ustar *ustar;
 
164
 
 
165
        /* If someone else was already registered, unregister them. */
 
166
        if (a->format_destroy != NULL)
 
167
                (a->format_destroy)(a);
 
168
 
 
169
        /* Basic internal sanity test. */
 
170
        if (sizeof(template_header) != 512) {
 
171
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header));
 
172
                return (ARCHIVE_FATAL);
 
173
        }
 
174
 
 
175
        ustar = (struct ustar *)malloc(sizeof(*ustar));
 
176
        if (ustar == NULL) {
 
177
                archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data");
 
178
                return (ARCHIVE_FATAL);
 
179
        }
 
180
        memset(ustar, 0, sizeof(*ustar));
 
181
        a->format_data = ustar;
 
182
 
 
183
        a->pad_uncompressed = 1;        /* Mimic gtar in this respect. */
 
184
        a->format_name = "ustar";
 
185
        a->format_write_header = archive_write_ustar_header;
 
186
        a->format_write_data = archive_write_ustar_data;
 
187
        a->format_finish = archive_write_ustar_finish;
 
188
        a->format_destroy = archive_write_ustar_destroy;
 
189
        a->format_finish_entry = archive_write_ustar_finish_entry;
 
190
        a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR;
 
191
        a->archive.archive_format_name = "POSIX ustar";
 
192
        return (ARCHIVE_OK);
 
193
}
 
194
 
 
195
static int
 
196
archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
 
197
{
 
198
        char buff[512];
 
199
        int ret, ret2;
 
200
        struct ustar *ustar;
 
201
 
 
202
        ustar = (struct ustar *)a->format_data;
 
203
 
 
204
        /* Only regular files (not hardlinks) have data. */
 
205
        if (archive_entry_hardlink(entry) != NULL ||
 
206
            archive_entry_symlink(entry) != NULL ||
 
207
            !(archive_entry_filetype(entry) == AE_IFREG))
 
208
                archive_entry_set_size(entry, 0);
 
209
 
 
210
        if (AE_IFDIR == archive_entry_filetype(entry)) {
 
211
                const char *p;
 
212
                char *t;
 
213
                /*
 
214
                 * Ensure a trailing '/'.  Modify the entry so
 
215
                 * the client sees the change.
 
216
                 */
 
217
                p = archive_entry_pathname(entry);
 
218
                if (p[strlen(p) - 1] != '/') {
 
219
                        t = (char *)malloc(strlen(p) + 2);
 
220
                        if (t == NULL) {
 
221
                                archive_set_error(&a->archive, ENOMEM,
 
222
                                "Can't allocate ustar data");
 
223
                                return(ARCHIVE_FATAL);
 
224
                        }
 
225
                        strcpy(t, p);
 
226
                        strcat(t, "/");
 
227
                        archive_entry_copy_pathname(entry, t);
 
228
                        free(t);
 
229
                }
 
230
        }
 
231
 
 
232
        ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1);
 
233
        if (ret < ARCHIVE_WARN)
 
234
                return (ret);
 
235
        ret2 = (a->compressor.write)(a, buff, 512);
 
236
        if (ret2 < ARCHIVE_WARN)
 
237
                return (ret2);
 
238
        if (ret2 < ret)
 
239
                ret = ret2;
 
240
 
 
241
        ustar->entry_bytes_remaining = archive_entry_size(entry);
 
242
        ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining);
 
243
        return (ret);
 
244
}
 
245
 
 
246
/*
 
247
 * Format a basic 512-byte "ustar" header.
 
248
 *
 
249
 * Returns -1 if format failed (due to field overflow).
 
250
 * Note that this always formats as much of the header as possible.
 
251
 * If "strict" is set to zero, it will extend numeric fields as
 
252
 * necessary (overwriting terminators or using base-256 extensions).
 
253
 *
 
254
 * This is exported so that other 'tar' formats can use it.
 
255
 */
 
256
int
 
257
__archive_write_format_header_ustar(struct archive_write *a, char h[512],
 
258
    struct archive_entry *entry, int tartype, int strict)
 
259
{
 
260
        unsigned int checksum;
 
261
        int i, ret;
 
262
        size_t copy_length;
 
263
        const char *p, *pp;
 
264
        int mytartype;
 
265
 
 
266
        ret = 0;
 
267
        mytartype = -1;
 
268
        /*
 
269
         * The "template header" already includes the "ustar"
 
270
         * signature, various end-of-field markers and other required
 
271
         * elements.
 
272
         */
 
273
        memcpy(h, &template_header, 512);
 
274
 
 
275
        /*
 
276
         * Because the block is already null-filled, and strings
 
277
         * are allowed to exactly fill their destination (without null),
 
278
         * I use memcpy(dest, src, strlen()) here a lot to copy strings.
 
279
         */
 
280
 
 
281
        pp = archive_entry_pathname(entry);
 
282
        if (strlen(pp) <= USTAR_name_size)
 
283
                memcpy(h + USTAR_name_offset, pp, strlen(pp));
 
284
        else {
 
285
                /* Store in two pieces, splitting at a '/'. */
 
286
                p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/');
 
287
                /*
 
288
                 * Look for the next '/' if we chose the first character
 
289
                 * as the separator.  (ustar format doesn't permit
 
290
                 * an empty prefix.)
 
291
                 */
 
292
                if (p == pp)
 
293
                        p = strchr(p + 1, '/');
 
294
                /* Fail if the name won't fit. */
 
295
                if (!p) {
 
296
                        /* No separator. */
 
297
                        archive_set_error(&a->archive, ENAMETOOLONG,
 
298
                            "Pathname too long");
 
299
                        ret = ARCHIVE_FAILED;
 
300
                } else if (p[1] == '\0') {
 
301
                        /*
 
302
                         * The only feasible separator is a final '/';
 
303
                         * this would result in a non-empty prefix and
 
304
                         * an empty name, which POSIX doesn't
 
305
                         * explicity forbid, but it just feels wrong.
 
306
                         */
 
307
                        archive_set_error(&a->archive, ENAMETOOLONG,
 
308
                            "Pathname too long");
 
309
                        ret = ARCHIVE_FAILED;
 
310
                } else if (p  > pp + USTAR_prefix_size) {
 
311
                        /* Prefix is too long. */
 
312
                        archive_set_error(&a->archive, ENAMETOOLONG,
 
313
                            "Pathname too long");
 
314
                        ret = ARCHIVE_FAILED;
 
315
                } else {
 
316
                        /* Copy prefix and remainder to appropriate places */
 
317
                        memcpy(h + USTAR_prefix_offset, pp, p - pp);
 
318
                        memcpy(h + USTAR_name_offset, p + 1, pp + strlen(pp) - p - 1);
 
319
                }
 
320
        }
 
321
 
 
322
        p = archive_entry_hardlink(entry);
 
323
        if (p != NULL)
 
324
                mytartype = '1';
 
325
        else
 
326
                p = archive_entry_symlink(entry);
 
327
        if (p != NULL && p[0] != '\0') {
 
328
                copy_length = strlen(p);
 
329
                if (copy_length > USTAR_linkname_size) {
 
330
                        archive_set_error(&a->archive, ENAMETOOLONG,
 
331
                            "Link contents too long");
 
332
                        ret = ARCHIVE_FAILED;
 
333
                        copy_length = USTAR_linkname_size;
 
334
                }
 
335
                memcpy(h + USTAR_linkname_offset, p, copy_length);
 
336
        }
 
337
 
 
338
        p = archive_entry_uname(entry);
 
339
        if (p != NULL && p[0] != '\0') {
 
340
                copy_length = strlen(p);
 
341
                if (copy_length > USTAR_uname_size) {
 
342
                        archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 
343
                            "Username too long");
 
344
                        ret = ARCHIVE_FAILED;
 
345
                        copy_length = USTAR_uname_size;
 
346
                }
 
347
                memcpy(h + USTAR_uname_offset, p, copy_length);
 
348
        }
 
349
 
 
350
        p = archive_entry_gname(entry);
 
351
        if (p != NULL && p[0] != '\0') {
 
352
                copy_length = strlen(p);
 
353
                if (strlen(p) > USTAR_gname_size) {
 
354
                        archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 
355
                            "Group name too long");
 
356
                        ret = ARCHIVE_FAILED;
 
357
                        copy_length = USTAR_gname_size;
 
358
                }
 
359
                memcpy(h + USTAR_gname_offset, p, copy_length);
 
360
        }
 
361
 
 
362
        if (format_number(archive_entry_mode(entry) & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) {
 
363
                archive_set_error(&a->archive, ERANGE, "Numeric mode too large");
 
364
                ret = ARCHIVE_FAILED;
 
365
        }
 
366
 
 
367
        if (format_number(archive_entry_uid(entry), h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) {
 
368
                archive_set_error(&a->archive, ERANGE, "Numeric user ID too large");
 
369
                ret = ARCHIVE_FAILED;
 
370
        }
 
371
 
 
372
        if (format_number(archive_entry_gid(entry), h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) {
 
373
                archive_set_error(&a->archive, ERANGE, "Numeric group ID too large");
 
374
                ret = ARCHIVE_FAILED;
 
375
        }
 
376
 
 
377
        if (format_number(archive_entry_size(entry), h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) {
 
378
                archive_set_error(&a->archive, ERANGE, "File size out of range");
 
379
                ret = ARCHIVE_FAILED;
 
380
        }
 
381
 
 
382
        if (format_number(archive_entry_mtime(entry), h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) {
 
383
                archive_set_error(&a->archive, ERANGE,
 
384
                    "File modification time too large");
 
385
                ret = ARCHIVE_FAILED;
 
386
        }
 
387
 
 
388
        if (archive_entry_filetype(entry) == AE_IFBLK
 
389
            || archive_entry_filetype(entry) == AE_IFCHR) {
 
390
                if (format_number(archive_entry_rdevmajor(entry), h + USTAR_rdevmajor_offset,
 
391
                        USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) {
 
392
                        archive_set_error(&a->archive, ERANGE,
 
393
                            "Major device number too large");
 
394
                        ret = ARCHIVE_FAILED;
 
395
                }
 
396
 
 
397
                if (format_number(archive_entry_rdevminor(entry), h + USTAR_rdevminor_offset,
 
398
                        USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) {
 
399
                        archive_set_error(&a->archive, ERANGE,
 
400
                            "Minor device number too large");
 
401
                        ret = ARCHIVE_FAILED;
 
402
                }
 
403
        }
 
404
 
 
405
        if (tartype >= 0) {
 
406
                h[USTAR_typeflag_offset] = tartype;
 
407
        } else if (mytartype >= 0) {
 
408
                h[USTAR_typeflag_offset] = mytartype;
 
409
        } else {
 
410
                switch (archive_entry_filetype(entry)) {
 
411
                case AE_IFREG: h[USTAR_typeflag_offset] = '0' ; break;
 
412
                case AE_IFLNK: h[USTAR_typeflag_offset] = '2' ; break;
 
413
                case AE_IFCHR: h[USTAR_typeflag_offset] = '3' ; break;
 
414
                case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
 
415
                case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
 
416
                case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
 
417
                case AE_IFSOCK:
 
418
                        archive_set_error(&a->archive,
 
419
                            ARCHIVE_ERRNO_FILE_FORMAT,
 
420
                            "tar format cannot archive socket");
 
421
                        return (ARCHIVE_FAILED);
 
422
                default:
 
423
                        archive_set_error(&a->archive,
 
424
                            ARCHIVE_ERRNO_FILE_FORMAT,
 
425
                            "tar format cannot archive this (mode=0%lo)",
 
426
                            (unsigned long)archive_entry_mode(entry));
 
427
                        ret = ARCHIVE_FAILED;
 
428
                }
 
429
        }
 
430
 
 
431
        checksum = 0;
 
432
        for (i = 0; i < 512; i++)
 
433
                checksum += 255 & (unsigned int)h[i];
 
434
        h[USTAR_checksum_offset + 6] = '\0'; /* Can't be pre-set in the template. */
 
435
        /* h[USTAR_checksum_offset + 7] = ' '; */ /* This is pre-set in the template. */
 
436
        format_octal(checksum, h + USTAR_checksum_offset, 6);
 
437
        return (ret);
 
438
}
 
439
 
 
440
/*
 
441
 * Format a number into a field, with some intelligence.
 
442
 */
 
443
static int
 
444
format_number(int64_t v, char *p, int s, int maxsize, int strict)
 
445
{
 
446
        int64_t limit;
 
447
 
 
448
        limit = ((int64_t)1 << (s*3));
 
449
 
 
450
        /* "Strict" only permits octal values with proper termination. */
 
451
        if (strict)
 
452
                return (format_octal(v, p, s));
 
453
 
 
454
        /*
 
455
         * In non-strict mode, we allow the number to overwrite one or
 
456
         * more bytes of the field termination.  Even old tar
 
457
         * implementations should be able to handle this with no
 
458
         * problem.
 
459
         */
 
460
        if (v >= 0) {
 
461
                while (s <= maxsize) {
 
462
                        if (v < limit)
 
463
                                return (format_octal(v, p, s));
 
464
                        s++;
 
465
                        limit <<= 3;
 
466
                }
 
467
        }
 
468
 
 
469
        /* Base-256 can handle any number, positive or negative. */
 
470
        return (format_256(v, p, maxsize));
 
471
}
 
472
 
 
473
/*
 
474
 * Format a number into the specified field using base-256.
 
475
 */
 
476
static int
 
477
format_256(int64_t v, char *p, int s)
 
478
{
 
479
        p += s;
 
480
        while (s-- > 0) {
 
481
                *--p = (char)(v & 0xff);
 
482
                v >>= 8;
 
483
        }
 
484
        *p |= 0x80; /* Set the base-256 marker bit. */
 
485
        return (0);
 
486
}
 
487
 
 
488
/*
 
489
 * Format a number into the specified field.
 
490
 */
 
491
static int
 
492
format_octal(int64_t v, char *p, int s)
 
493
{
 
494
        int len;
 
495
 
 
496
        len = s;
 
497
 
 
498
        /* Octal values can't be negative, so use 0. */
 
499
        if (v < 0) {
 
500
                while (len-- > 0)
 
501
                        *p++ = '0';
 
502
                return (-1);
 
503
        }
 
504
 
 
505
        p += s;         /* Start at the end and work backwards. */
 
506
        while (s-- > 0) {
 
507
                *--p = (char)('0' + (v & 7));
 
508
                v >>= 3;
 
509
        }
 
510
 
 
511
        if (v == 0)
 
512
                return (0);
 
513
 
 
514
        /* If it overflowed, fill field with max value. */
 
515
        while (len-- > 0)
 
516
                *p++ = '7';
 
517
 
 
518
        return (-1);
 
519
}
 
520
 
 
521
static int
 
522
archive_write_ustar_finish(struct archive_write *a)
 
523
{
 
524
        int r;
 
525
 
 
526
        if (a->compressor.write == NULL)
 
527
                return (ARCHIVE_OK);
 
528
 
 
529
        r = write_nulls(a, 512*2);
 
530
        return (r);
 
531
}
 
532
 
 
533
static int
 
534
archive_write_ustar_destroy(struct archive_write *a)
 
535
{
 
536
        struct ustar *ustar;
 
537
 
 
538
        ustar = (struct ustar *)a->format_data;
 
539
        free(ustar);
 
540
        a->format_data = NULL;
 
541
        return (ARCHIVE_OK);
 
542
}
 
543
 
 
544
static int
 
545
archive_write_ustar_finish_entry(struct archive_write *a)
 
546
{
 
547
        struct ustar *ustar;
 
548
        int ret;
 
549
 
 
550
        ustar = (struct ustar *)a->format_data;
 
551
        ret = write_nulls(a,
 
552
            ustar->entry_bytes_remaining + ustar->entry_padding);
 
553
        ustar->entry_bytes_remaining = ustar->entry_padding = 0;
 
554
        return (ret);
 
555
}
 
556
 
 
557
static int
 
558
write_nulls(struct archive_write *a, size_t padding)
 
559
{
 
560
        int ret;
 
561
        size_t to_write;
 
562
 
 
563
        while (padding > 0) {
 
564
                to_write = padding < a->null_length ? padding : a->null_length;
 
565
                ret = (a->compressor.write)(a, a->nulls, to_write);
 
566
                if (ret != ARCHIVE_OK)
 
567
                        return (ret);
 
568
                padding -= to_write;
 
569
        }
 
570
        return (ARCHIVE_OK);
 
571
}
 
572
 
 
573
static ssize_t
 
574
archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s)
 
575
{
 
576
        struct ustar *ustar;
 
577
        int ret;
 
578
 
 
579
        ustar = (struct ustar *)a->format_data;
 
580
        if (s > ustar->entry_bytes_remaining)
 
581
                s = ustar->entry_bytes_remaining;
 
582
        ret = (a->compressor.write)(a, buff, s);
 
583
        ustar->entry_bytes_remaining -= s;
 
584
        if (ret != ARCHIVE_OK)
 
585
                return (ret);
 
586
        return (s);
 
587
}