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