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