]> Dogcows Code - chaz/tar/blob - src/xheader.c
Make xhdr_tab extern, not static.
[chaz/tar] / src / xheader.c
1 /* POSIX extended and STAR headers.
2
3 Copyright (C) 2003 Free Software Foundation, Inc.
4
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
8 version.
9
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.
14
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. */
18
19 #include "system.h"
20
21 #include <hash.h>
22 #include <quotearg.h>
23
24 #include "common.h"
25
26 #define obstack_chunk_alloc xmalloc
27 #define obstack_chunk_free free
28 #include <obstack.h>
29
30 /* General Interface */
31
32 struct xhdr_tab
33 {
34 char const *keyword;
35 void (*coder) (struct tar_stat_info const *, char const *, struct xheader *);
36 void (*decoder) (struct tar_stat_info *, char const *);
37 };
38
39 /* This declaration must be extern, because ISO C99 section 6.9.2
40 prohibits a tentative definition that has both internal linkage and
41 incomplete type. If we made it static, we'd have to declare its
42 size which would be a maintenance pain; if we put its initializer
43 here, we'd need a boatload of forward declarations, which would be
44 even more of a pain. */
45 extern struct xhdr_tab const xhdr_tab[];
46
47 static struct xhdr_tab const *
48 locate_handler (char const *keyword)
49 {
50 struct xhdr_tab const *p;
51
52 for (p = xhdr_tab; p->keyword; p++)
53 if (strcmp (p->keyword, keyword) == 0)
54 return p;
55 return NULL;
56 }
57
58 /* Decodes a single extended header record. Advances P to the next
59 record.
60 Returns true on success, false otherwise. */
61 static bool
62 decode_record (char **p, struct tar_stat_info *st)
63 {
64 size_t len;
65 char const *keyword;
66 char *eqp;
67 char *start = *p;
68 struct xhdr_tab const *t;
69
70 if (**p == 0)
71 return false;
72
73 len = strtoul (*p, p, 10);
74 if (**p != ' ')
75 {
76 ERROR ((0, 0, _("Malformed extended header: missing whitespace after the length")));
77 return false;
78 }
79
80 keyword = ++*p;
81 for (;*p < start + len; ++*p)
82 if (**p == '=')
83 break;
84
85 if (**p != '=')
86 {
87 ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
88 return false;
89 }
90
91 eqp = *p;
92 **p = 0;
93 t = locate_handler (keyword);
94 if (t)
95 {
96 char endc;
97 char *value;
98
99 value = ++*p;
100
101 endc = start[len-1];
102 start[len-1] = 0;
103 t->decoder (st, value);
104 start[len-1] = endc;
105 }
106 *eqp = '=';
107 *p = &start[len];
108 return true;
109 }
110
111 void
112 xheader_decode (struct tar_stat_info *st)
113 {
114 char *p = extended_header.buffer + BLOCKSIZE;
115 char *endp = &extended_header.buffer[extended_header.size-1];
116
117 while (p < endp)
118 if (!decode_record (&p, st))
119 break;
120 }
121
122 void
123 xheader_store (char const *keyword, struct tar_stat_info const *st)
124 {
125 struct xhdr_tab const *t;
126
127 if (extended_header.buffer)
128 return;
129 t = locate_handler (keyword);
130 if (!t)
131 return;
132 if (!extended_header.stk)
133 {
134 extended_header.stk = xmalloc (sizeof *extended_header.stk);
135 obstack_init (extended_header.stk);
136 }
137 t->coder (st, keyword, &extended_header);
138 }
139
140 void
141 xheader_read (union block *p, size_t size)
142 {
143 size_t j = 0;
144 size_t nblocks;
145
146 free (extended_header.buffer);
147 size += BLOCKSIZE;
148 extended_header.size = size;
149 nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
150 extended_header.buffer = xmalloc (size + 1);
151
152 do
153 {
154 size_t len = size;
155
156 if (len > BLOCKSIZE)
157 len = BLOCKSIZE;
158
159 memcpy (&extended_header.buffer[j], p->buffer, len);
160 set_next_block_after (p);
161
162 p = find_next_block ();
163
164 j += len;
165 size -= len;
166 }
167 while (size > 0);
168 }
169
170 static size_t
171 format_uintmax (uintmax_t val, char *buf, size_t s)
172 {
173 if (!buf)
174 {
175 s = 0;
176 do
177 s++;
178 while ((val /= 10) != 0);
179 }
180 else
181 {
182 char *p = buf + s - 1;
183
184 do
185 {
186 *p-- = val % 10 + '0';
187 }
188 while ((val /= 10) != 0);
189
190 while (p >= buf)
191 *p-- = '0';
192 }
193 return s;
194 }
195
196 static void
197 xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
198 {
199 size_t len = strlen (keyword) + strlen (value) + 3; /* ' ' + '=' + '\n' */
200 size_t p, n = 0;
201 char nbuf[100];
202
203 do
204 {
205 p = n;
206 n = format_uintmax (len + p, NULL, 0);
207 }
208 while (n != p);
209
210 format_uintmax (len + n, nbuf, n);
211 obstack_grow (xhdr->stk, nbuf, n);
212 obstack_1grow (xhdr->stk, ' ');
213 obstack_grow (xhdr->stk, keyword, strlen (keyword));
214 obstack_1grow (xhdr->stk, '=');
215 obstack_grow (xhdr->stk, value, strlen (value));
216 obstack_1grow (xhdr->stk, '\n');
217 }
218
219 void
220 xheader_finish (struct xheader *xhdr)
221 {
222 obstack_1grow (xhdr->stk, 0);
223 xhdr->buffer = obstack_finish (xhdr->stk);
224 xhdr->size = strlen (xhdr->buffer);
225 }
226
227 void
228 xheader_destroy (struct xheader *xhdr)
229 {
230 if (xhdr->stk)
231 {
232 obstack_free (xhdr->stk, NULL);
233 free (xhdr->stk);
234 xhdr->stk = NULL;
235 }
236 else
237 free (xhdr->buffer);
238 xhdr->buffer = 0;
239 xhdr->size = 0;
240 }
241
242 \f
243 /* Implementations */
244 static void
245 code_string (char const *string, char const *keyword, struct xheader *xhdr)
246 {
247 xheader_print (xhdr, keyword, string);
248 }
249
250 static void
251 code_time (time_t t, char const *keyword, struct xheader *xhdr)
252 {
253 char sbuf[100];
254 size_t s = format_uintmax (t, NULL, 0);
255 format_uintmax (t, sbuf, s);
256 sbuf[s++] = '.';
257 format_uintmax (0, sbuf + s, 9);
258 sbuf[s+9] = 0;
259 xheader_print (xhdr, keyword, sbuf);
260 }
261
262 static void
263 code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
264 {
265 char sbuf[100];
266 size_t s = format_uintmax (value, NULL, 0);
267 format_uintmax (value, sbuf, s);
268 sbuf[s] = 0;
269 xheader_print (xhdr, keyword, sbuf);
270 }
271
272 static void
273 dummy_coder (struct tar_stat_info const *st, char const *keyword,
274 struct xheader *xhdr)
275 {
276 }
277
278 static void
279 dummy_decoder (struct tar_stat_info *st, char const *arg)
280 {
281 }
282
283 static void
284 atime_coder (struct tar_stat_info const *st, char const *keyword,
285 struct xheader *xhdr)
286 {
287 code_time (st->stat.st_atime, keyword, xhdr);
288 }
289
290 static void
291 atime_decoder (struct tar_stat_info *st, char const *arg)
292 {
293 st->stat.st_atime = strtoul (arg, NULL, 0);
294 }
295
296 static void
297 gid_coder (struct tar_stat_info const *st, char const *keyword,
298 struct xheader *xhdr)
299 {
300 code_num (st->stat.st_gid, keyword, xhdr);
301 }
302
303 static void
304 gid_decoder (struct tar_stat_info *st, char const *arg)
305 {
306 st->stat.st_gid = strtoul (arg, NULL, 0);
307 }
308
309 static void
310 gname_coder (struct tar_stat_info const *st, char const *keyword,
311 struct xheader *xhdr)
312 {
313 code_string (st->gname, keyword, xhdr);
314 }
315
316 static void
317 gname_decoder (struct tar_stat_info *st, char const *arg)
318 {
319 assign_string (&st->gname, arg);
320 }
321
322 static void
323 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
324 struct xheader *xhdr)
325 {
326 code_string (st->link_name, keyword, xhdr);
327 }
328
329 static void
330 linkpath_decoder (struct tar_stat_info *st, char const *arg)
331 {
332 assign_string (&st->link_name, arg);
333 }
334
335 static void
336 ctime_coder (struct tar_stat_info const *st, char const *keyword,
337 struct xheader *xhdr)
338 {
339 code_time (st->stat.st_ctime, keyword, xhdr);
340 }
341
342 static void
343 ctime_decoder (struct tar_stat_info *st, char const *arg)
344 {
345 st->stat.st_ctime = strtoul (arg, NULL, 0);
346 }
347
348 static void
349 mtime_coder (struct tar_stat_info const *st, char const *keyword,
350 struct xheader *xhdr)
351 {
352 code_time (st->stat.st_mtime, keyword, xhdr);
353 }
354
355 static void
356 mtime_decoder (struct tar_stat_info *st, char const *arg)
357 {
358 st->stat.st_mtime = strtoul (arg, NULL, 0);
359 }
360
361 static void
362 path_coder (struct tar_stat_info const *st, char const *keyword,
363 struct xheader *xhdr)
364 {
365 code_string (st->file_name, keyword, xhdr);
366 }
367
368 static void
369 path_decoder (struct tar_stat_info *st, char const *arg)
370 {
371 assign_string (&st->orig_file_name, arg);
372 assign_string (&st->file_name, arg);
373 st->had_trailing_slash = strip_trailing_slashes (st->file_name);
374 }
375
376 static void
377 size_coder (struct tar_stat_info const *st, char const *keyword,
378 struct xheader *xhdr)
379 {
380 code_num (st->stat.st_size, keyword, xhdr);
381 }
382
383 static void
384 size_decoder (struct tar_stat_info *st, char const *arg)
385 {
386 st->stat.st_size = strtoul (arg, NULL, 0);
387 }
388
389 static void
390 uid_coder (struct tar_stat_info const *st, char const *keyword,
391 struct xheader *xhdr)
392 {
393 code_num (st->stat.st_uid, keyword, xhdr);
394 }
395
396 static void
397 uid_decoder (struct tar_stat_info *st, char const *arg)
398 {
399 st->stat.st_uid = strtoul (arg, NULL, 0);
400 }
401
402 static void
403 uname_coder (struct tar_stat_info const *st, char const *keyword,
404 struct xheader *xhdr)
405 {
406 code_string (st->uname, keyword, xhdr);
407 }
408
409 static void
410 uname_decoder (struct tar_stat_info *st, char const *arg)
411 {
412 assign_string (&st->uname, arg);
413 }
414
415 struct xhdr_tab const xhdr_tab[] = {
416 { "atime", atime_coder, atime_decoder },
417 { "comment", dummy_coder, dummy_decoder },
418 { "charset", dummy_coder, dummy_decoder },
419 { "ctime", ctime_coder, ctime_decoder },
420 { "gid", gid_coder, gid_decoder },
421 { "gname", gname_coder, gname_decoder },
422 { "linkpath", linkpath_coder, linkpath_decoder},
423 { "mtime", mtime_coder, mtime_decoder },
424 { "path", path_coder, path_decoder },
425 { "size", size_coder, size_decoder },
426 { "uid", uid_coder, uid_decoder },
427 { "uname", uname_coder, uname_decoder },
428
429 /* The number of entries in xhdr_tab must agree with the array
430 bounds in xhdr_tab's forward declaration. */
431
432 #if 0 /* GNU private keywords (not yet implemented) */
433 /* Sparse file handling */
434 { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder },
435 { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder },
436
437 /* The next directory entry actually contains the names of files
438 that were in the directory at the time the dump was made.
439 Supersedes GNUTYPE_DUMPDIR header type. */
440 { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder },
441
442 /* Keeps the tape/volume header. May be present only in the global headers.
443 Equivalent to GNUTYPE_VOLHDR. */
444 { "GNU.volume.header", volume_header_coder, volume_header_decoder },
445
446 /* These may be present in a first global header of the archive.
447 They provide the same functionality as GNUTYPE_MULTIVOL header.
448 The GNU.volume.size keeps the real_s_sizeleft value, which is
449 otherwise kept in the size field of a multivolume header. The
450 GNU.volume.offset keeps the offset of the start of this volume,
451 otherwise kept in oldgnu_header.offset. */
452 { "GNU.volume.size", volume_size_coder, volume_size_decoder },
453 { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder },
454 #endif
455
456 { NULL, NULL, NULL }
457 };
This page took 0.053923 seconds and 5 git commands to generate.