]>
Dogcows Code - chaz/tar/blob - src/xheader.c
1 /* POSIX extended and STAR headers.
3 Copyright (C) 2003 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any later
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #define obstack_chunk_alloc xmalloc
28 #define obstack_chunk_free free
31 /* General Interface */
36 void (*coder
) (struct tar_stat_info
const *, char const *,
37 struct xheader
*, void *data
);
38 void (*decoder
) (struct tar_stat_info
*, char const *);
41 /* This declaration must be extern, because ISO C99 section 6.9.2
42 prohibits a tentative definition that has both internal linkage and
43 incomplete type. If we made it static, we'd have to declare its
44 size which would be a maintenance pain; if we put its initializer
45 here, we'd need a boatload of forward declarations, which would be
46 even more of a pain. */
47 extern struct xhdr_tab
const xhdr_tab
[];
49 static struct xhdr_tab
const *
50 locate_handler (char const *keyword
)
52 struct xhdr_tab
const *p
;
54 for (p
= xhdr_tab
; p
->keyword
; p
++)
55 if (strcmp (p
->keyword
, keyword
) == 0)
60 /* Decodes a single extended header record. Advances P to the next
62 Returns true on success, false otherwise. */
64 decode_record (char **p
, struct tar_stat_info
*st
)
70 struct xhdr_tab
const *t
;
75 len
= strtoul (*p
, p
, 10);
78 ERROR ((0, 0, _("Malformed extended header: missing whitespace after the length")));
83 for (;*p
< start
+ len
; ++*p
)
89 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
95 t
= locate_handler (keyword
);
105 t
->decoder (st
, value
);
114 xheader_decode (struct tar_stat_info
*st
)
116 char *p
= extended_header
.buffer
+ BLOCKSIZE
;
117 char *endp
= &extended_header
.buffer
[extended_header
.size
-1];
120 if (!decode_record (&p
, st
))
125 xheader_store (char const *keyword
, struct tar_stat_info
const *st
, void *data
)
127 struct xhdr_tab
const *t
;
129 if (extended_header
.buffer
)
131 t
= locate_handler (keyword
);
134 if (!extended_header
.stk
)
136 extended_header
.stk
= xmalloc (sizeof *extended_header
.stk
);
137 obstack_init (extended_header
.stk
);
139 t
->coder (st
, keyword
, &extended_header
, data
);
143 xheader_read (union block
*p
, size_t size
)
148 free (extended_header
.buffer
);
150 extended_header
.size
= size
;
151 nblocks
= (size
+ BLOCKSIZE
- 1) / BLOCKSIZE
;
152 extended_header
.buffer
= xmalloc (size
+ 1);
161 memcpy (&extended_header
.buffer
[j
], p
->buffer
, len
);
162 set_next_block_after (p
);
164 p
= find_next_block ();
173 format_uintmax (uintmax_t val
, char *buf
, size_t s
)
180 while ((val
/= 10) != 0);
184 char *p
= buf
+ s
- 1;
188 *p
-- = val
% 10 + '0';
190 while ((val
/= 10) != 0);
199 xheader_print (struct xheader
*xhdr
, char const *keyword
, char const *value
)
201 size_t len
= strlen (keyword
) + strlen (value
) + 3; /* ' ' + '=' + '\n' */
208 n
= format_uintmax (len
+ p
, NULL
, 0);
212 format_uintmax (len
+ n
, nbuf
, n
);
213 obstack_grow (xhdr
->stk
, nbuf
, n
);
214 obstack_1grow (xhdr
->stk
, ' ');
215 obstack_grow (xhdr
->stk
, keyword
, strlen (keyword
));
216 obstack_1grow (xhdr
->stk
, '=');
217 obstack_grow (xhdr
->stk
, value
, strlen (value
));
218 obstack_1grow (xhdr
->stk
, '\n');
222 xheader_finish (struct xheader
*xhdr
)
224 obstack_1grow (xhdr
->stk
, 0);
225 xhdr
->buffer
= obstack_finish (xhdr
->stk
);
226 xhdr
->size
= strlen (xhdr
->buffer
);
230 xheader_destroy (struct xheader
*xhdr
)
234 obstack_free (xhdr
->stk
, NULL
);
245 /* Implementations */
247 code_string (char const *string
, char const *keyword
, struct xheader
*xhdr
)
249 xheader_print (xhdr
, keyword
, string
);
253 code_time (time_t t
, unsigned long nano
,
254 char const *keyword
, struct xheader
*xhdr
)
257 size_t s
= format_uintmax (t
, NULL
, 0);
258 if (s
+ 11 >= sizeof sbuf
)
260 format_uintmax (t
, sbuf
, s
);
262 s
+= format_uintmax (nano
, sbuf
+ s
, 9);
264 xheader_print (xhdr
, keyword
, sbuf
);
268 decode_time (char const *arg
, time_t *secs
, unsigned long *nsecs
)
272 if (xstrtoumax (arg
, &p
, 10, &u
, "") == LONGINT_OK
)
275 if (*p
== '.' && xstrtoumax (p
+1, NULL
, 10, &u
, "") == LONGINT_OK
)
281 code_num (uintmax_t value
, char const *keyword
, struct xheader
*xhdr
)
284 size_t s
= format_uintmax (value
, NULL
, 0);
285 format_uintmax (value
, sbuf
, s
);
287 xheader_print (xhdr
, keyword
, sbuf
);
291 dummy_coder (struct tar_stat_info
const *st
, char const *keyword
,
292 struct xheader
*xhdr
, void *data
)
297 dummy_decoder (struct tar_stat_info
*st
, char const *arg
)
302 atime_coder (struct tar_stat_info
const *st
, char const *keyword
,
303 struct xheader
*xhdr
, void *data
)
305 code_time (st
->stat
.st_atime
, st
->atime_nsec
, keyword
, xhdr
);
309 atime_decoder (struct tar_stat_info
*st
, char const *arg
)
311 decode_time (arg
, &st
->stat
.st_atime
, &st
->atime_nsec
);
315 gid_coder (struct tar_stat_info
const *st
, char const *keyword
,
316 struct xheader
*xhdr
, void *data
)
318 code_num (st
->stat
.st_gid
, keyword
, xhdr
);
322 gid_decoder (struct tar_stat_info
*st
, char const *arg
)
325 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
330 gname_coder (struct tar_stat_info
const *st
, char const *keyword
,
331 struct xheader
*xhdr
, void *data
)
333 code_string (st
->gname
, keyword
, xhdr
);
337 gname_decoder (struct tar_stat_info
*st
, char const *arg
)
339 assign_string (&st
->gname
, arg
);
343 linkpath_coder (struct tar_stat_info
const *st
, char const *keyword
,
344 struct xheader
*xhdr
, void *data
)
346 code_string (st
->link_name
, keyword
, xhdr
);
350 linkpath_decoder (struct tar_stat_info
*st
, char const *arg
)
352 assign_string (&st
->link_name
, arg
);
356 ctime_coder (struct tar_stat_info
const *st
, char const *keyword
,
357 struct xheader
*xhdr
, void *data
)
359 code_time (st
->stat
.st_ctime
, st
->ctime_nsec
, keyword
, xhdr
);
363 ctime_decoder (struct tar_stat_info
*st
, char const *arg
)
365 decode_time (arg
, &st
->stat
.st_ctime
, &st
->ctime_nsec
);
369 mtime_coder (struct tar_stat_info
const *st
, char const *keyword
,
370 struct xheader
*xhdr
, void *data
)
372 code_time (st
->stat
.st_mtime
, st
->mtime_nsec
, keyword
, xhdr
);
376 mtime_decoder (struct tar_stat_info
*st
, char const *arg
)
378 decode_time (arg
, &st
->stat
.st_mtime
, &st
->mtime_nsec
);
382 path_coder (struct tar_stat_info
const *st
, char const *keyword
,
383 struct xheader
*xhdr
, void *data
)
385 code_string (st
->file_name
, keyword
, xhdr
);
389 path_decoder (struct tar_stat_info
*st
, char const *arg
)
391 assign_string (&st
->orig_file_name
, arg
);
392 assign_string (&st
->file_name
, arg
);
393 st
->had_trailing_slash
= strip_trailing_slashes (st
->file_name
);
397 size_coder (struct tar_stat_info
const *st
, char const *keyword
,
398 struct xheader
*xhdr
, void *data
)
400 code_num (st
->stat
.st_size
, keyword
, xhdr
);
404 size_decoder (struct tar_stat_info
*st
, char const *arg
)
407 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
408 st
->stat
.st_size
= u
;
412 uid_coder (struct tar_stat_info
const *st
, char const *keyword
,
413 struct xheader
*xhdr
, void *data
)
415 code_num (st
->stat
.st_uid
, keyword
, xhdr
);
419 uid_decoder (struct tar_stat_info
*st
, char const *arg
)
422 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
427 uname_coder (struct tar_stat_info
const *st
, char const *keyword
,
428 struct xheader
*xhdr
, void *data
)
430 code_string (st
->uname
, keyword
, xhdr
);
434 uname_decoder (struct tar_stat_info
*st
, char const *arg
)
436 assign_string (&st
->uname
, arg
);
440 sparse_size_coder (struct tar_stat_info
const *st
, char const *keyword
,
441 struct xheader
*xhdr
, void *data
)
443 size_coder (st
, keyword
, xhdr
, data
);
447 sparse_size_decoder (struct tar_stat_info
*st
, char const *arg
)
450 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
451 st
->archive_file_size
= u
;
455 sparse_numblocks_coder (struct tar_stat_info
const *st
, char const *keyword
,
456 struct xheader
*xhdr
, void *data
)
458 code_num (st
->sparse_map_avail
, keyword
, xhdr
);
462 sparse_numblocks_decoder (struct tar_stat_info
*st
, char const *arg
)
465 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
467 st
->sparse_map_size
= u
;
468 st
->sparse_map
= calloc(st
->sparse_map_size
, sizeof(st
->sparse_map
[0]));
469 st
->sparse_map_avail
= 0;
474 sparse_offset_coder (struct tar_stat_info
const *st
, char const *keyword
,
475 struct xheader
*xhdr
, void *data
)
477 size_t i
= *(size_t*)data
;
478 code_num (st
->sparse_map
[i
].offset
, keyword
, xhdr
);
482 sparse_offset_decoder (struct tar_stat_info
*st
, char const *arg
)
485 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
486 st
->sparse_map
[st
->sparse_map_avail
].offset
= u
;
490 sparse_numbytes_coder (struct tar_stat_info
const *st
, char const *keyword
,
491 struct xheader
*xhdr
, void *data
)
493 size_t i
= *(size_t*)data
;
494 code_num (st
->sparse_map
[i
].numbytes
, keyword
, xhdr
);
498 sparse_numbytes_decoder (struct tar_stat_info
*st
, char const *arg
)
501 if (xstrtoumax (arg
, NULL
, 10, &u
, "") == LONGINT_OK
)
503 if (st
->sparse_map_avail
== st
->sparse_map_size
)
505 size_t newsize
= st
->sparse_map_size
*= 2;
506 st
->sparse_map
= xrealloc (st
->sparse_map
,
508 * sizeof st
->sparse_map
[0]);
510 st
->sparse_map
[st
->sparse_map_avail
++].numbytes
= u
;
514 struct xhdr_tab
const xhdr_tab
[] = {
515 { "atime", atime_coder
, atime_decoder
},
516 { "comment", dummy_coder
, dummy_decoder
},
517 { "charset", dummy_coder
, dummy_decoder
},
518 { "ctime", ctime_coder
, ctime_decoder
},
519 { "gid", gid_coder
, gid_decoder
},
520 { "gname", gname_coder
, gname_decoder
},
521 { "linkpath", linkpath_coder
, linkpath_decoder
},
522 { "mtime", mtime_coder
, mtime_decoder
},
523 { "path", path_coder
, path_decoder
},
524 { "size", size_coder
, size_decoder
},
525 { "uid", uid_coder
, uid_decoder
},
526 { "uname", uname_coder
, uname_decoder
},
528 /* Sparse file handling */
529 { "GNU.sparse.size", sparse_size_coder
, sparse_size_decoder
},
530 { "GNU.sparse.numblocks", sparse_numblocks_coder
, sparse_numblocks_decoder
},
531 { "GNU.sparse.offset", sparse_offset_coder
, sparse_offset_decoder
},
532 { "GNU.sparse.numbytes", sparse_numbytes_coder
, sparse_numbytes_decoder
},
534 #if 0 /* GNU private keywords (not yet implemented) */
536 /* The next directory entry actually contains the names of files
537 that were in the directory at the time the dump was made.
538 Supersedes GNUTYPE_DUMPDIR header type. */
539 { "GNU.dumpdir", dumpdir_coder
, dumpdir_decoder
},
541 /* Keeps the tape/volume header. May be present only in the global headers.
542 Equivalent to GNUTYPE_VOLHDR. */
543 { "GNU.volume.header", volume_header_coder
, volume_header_decoder
},
545 /* These may be present in a first global header of the archive.
546 They provide the same functionality as GNUTYPE_MULTIVOL header.
547 The GNU.volume.size keeps the real_s_sizeleft value, which is
548 otherwise kept in the size field of a multivolume header. The
549 GNU.volume.offset keeps the offset of the start of this volume,
550 otherwise kept in oldgnu_header.offset. */
551 { "GNU.volume.size", volume_size_coder
, volume_size_decoder
},
552 { "GNU.volume.offset", volume_offset_coder
, volume_offset_decoder
},
This page took 0.061535 seconds and 4 git commands to generate.