This source file includes following definitions.
- decode_num
- sparse_select_optab
- sparse_init
- sparse_done
- sparse_member_p
- sparse_fixup_header
- sparse_decode_header
- sparse_add_map
- oldgnu_add_sparse
- oldgnu_sparse_member_p
- oldgnu_fixup_header
- oldgnu_get_sparse_info
- star_sparse_member_p
- star_fixup_header
- star_get_sparse_info
- pax_sparse_member_p
- pax_decode_header
- tar_sparse_member_p
- tar_sparse_fixup_header
- tar_sparse_skip_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))
39 #pragma GCC diagnostic ignored "-Wtype-limits"
40 #endif
41
42 #include <config.h>
43
44 #include <inttypes.h>
45
46 #include "lib/global.h"
47
48 #include "tar-internal.h"
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 #define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)
74
75
76
77 #define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)
78
79 #define UINTMAX_STRSIZE_BOUND INT_BUFSIZE_BOUND (uintmax_t)
80
81 #define COPY_BUF(arch,b,buf,src) \
82 do \
83 { \
84 char *endp = b->buffer + BLOCKSIZE; \
85 char *dst = buf; \
86 do \
87 { \
88 if (dst == buf + UINTMAX_STRSIZE_BOUND - 1) \
89 \
90 return FALSE; \
91 if (src == endp) \
92 { \
93 tar_set_next_block_after (b); \
94 b = tar_find_next_block (arch); \
95 if (b == NULL) \
96 \
97 return FALSE; \
98 src = b->buffer; \
99 endp = b->buffer + BLOCKSIZE; \
100 } \
101 *dst = *src++; \
102 } \
103 while (*dst++ != '\n'); \
104 dst[-1] = '\0'; \
105 } \
106 while (FALSE)
107
108
109
110 struct tar_sparse_file;
111
112 struct tar_sparse_optab
113 {
114 gboolean (*init) (struct tar_sparse_file * file);
115 gboolean (*done) (struct tar_sparse_file * file);
116 gboolean (*sparse_member_p) (struct tar_sparse_file * file);
117 gboolean (*fixup_header) (struct tar_sparse_file * file);
118 gboolean (*decode_header) (tar_super_t * archive, struct tar_sparse_file * file);
119 };
120
121 struct tar_sparse_file
122 {
123 int fd;
124 off_t dumped_size;
125 struct tar_stat_info *stat_info;
126 struct tar_sparse_optab const *optab;
127 void *closure;
128 };
129
130 enum oldgnu_add_status
131 {
132 add_ok,
133 add_finish,
134 add_fail
135 };
136
137
138
139 static gboolean oldgnu_sparse_member_p (struct tar_sparse_file *file);
140 static gboolean oldgnu_fixup_header (struct tar_sparse_file *file);
141 static gboolean oldgnu_get_sparse_info (tar_super_t * archive, struct tar_sparse_file *file);
142
143 static gboolean star_sparse_member_p (struct tar_sparse_file *file);
144 static gboolean star_fixup_header (struct tar_sparse_file *file);
145 static gboolean star_get_sparse_info (tar_super_t * archive, struct tar_sparse_file *file);
146
147 static gboolean pax_sparse_member_p (struct tar_sparse_file *file);
148 static gboolean pax_decode_header (tar_super_t * archive, struct tar_sparse_file *file);
149
150
151
152
153 static struct tar_sparse_optab const oldgnu_optab =
154 {
155 .init = NULL,
156 .done = NULL,
157 .sparse_member_p = oldgnu_sparse_member_p,
158 .fixup_header = oldgnu_fixup_header,
159 .decode_header = oldgnu_get_sparse_info
160 };
161
162
163
164 static struct tar_sparse_optab const star_optab =
165 {
166 .init = NULL,
167 .done = NULL,
168 .sparse_member_p = star_sparse_member_p,
169 .fixup_header = star_fixup_header,
170 .decode_header = star_get_sparse_info
171 };
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239 static struct tar_sparse_optab const pax_optab = {
240 .init = NULL,
241 .done = NULL,
242 .sparse_member_p = pax_sparse_member_p,
243 .fixup_header = NULL,
244 .decode_header = pax_decode_header
245 };
246
247
248
249
250
251 static gboolean
252 decode_num (uintmax_t *num, const char *arg, uintmax_t maxval)
253 {
254 char *arg_lim = NULL;
255 gboolean overflow = FALSE;
256
257 *num = stoint (arg, &arg_lim, &overflow, 0, maxval);
258 return !(arg_lim == arg || *arg_lim != '\0' || overflow);
259 }
260
261
262
263 static gboolean
264 sparse_select_optab (const tar_super_t *archive, struct tar_sparse_file *file)
265 {
266 switch (archive->type)
267 {
268 case TAR_V7:
269 case TAR_USTAR:
270 return FALSE;
271
272 case TAR_OLDGNU:
273 case TAR_GNU:
274 file->optab = &oldgnu_optab;
275 break;
276
277 case TAR_POSIX:
278 file->optab = &pax_optab;
279 break;
280
281 case TAR_STAR:
282 file->optab = &star_optab;
283 break;
284
285 default:
286 return FALSE;
287 }
288
289 return TRUE;
290 }
291
292
293
294 static gboolean
295 sparse_init (tar_super_t *archive, struct tar_sparse_file *file)
296 {
297 memset (file, 0, sizeof (*file));
298
299 if (!sparse_select_optab (archive, file))
300 return FALSE;
301
302 if (file->optab->init != NULL)
303 return file->optab->init (file);
304
305 return TRUE;
306 }
307
308
309
310 static gboolean
311 sparse_done (struct tar_sparse_file *file)
312 {
313 if (file->optab->done != NULL)
314 return file->optab->done (file);
315
316 return TRUE;
317 }
318
319
320
321 static gboolean
322 sparse_member_p (struct tar_sparse_file *file)
323 {
324 if (file->optab->sparse_member_p != NULL)
325 return file->optab->sparse_member_p (file);
326
327 return FALSE;
328 }
329
330
331
332 static gboolean
333 sparse_fixup_header (struct tar_sparse_file *file)
334 {
335 if (file->optab->fixup_header != NULL)
336 return file->optab->fixup_header (file);
337
338 return TRUE;
339 }
340
341
342
343 static gboolean
344 sparse_decode_header (tar_super_t *archive, struct tar_sparse_file *file)
345 {
346 if (file->optab->decode_header != NULL)
347 return file->optab->decode_header (archive, file);
348
349 return TRUE;
350 }
351
352
353
354 static inline void
355 sparse_add_map (struct tar_stat_info *st, struct sp_array *sp)
356 {
357 if (st->sparse_map == NULL)
358 st->sparse_map = g_array_sized_new (FALSE, FALSE, sizeof (struct sp_array), 1);
359 g_array_append_val (st->sparse_map, *sp);
360 }
361
362
363
364
365
366
367 static enum oldgnu_add_status
368 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
369 {
370 struct sp_array sp;
371 off_t size;
372
373 if (s->numbytes[0] == '\0')
374 return add_finish;
375
376 sp.offset = OFF_FROM_HEADER (s->offset);
377 sp.numbytes = OFF_FROM_HEADER (s->numbytes);
378
379 if (sp.offset < 0 || sp.numbytes < 0 || ckd_add (&size, sp.offset, sp.numbytes)
380 || file->stat_info->stat.st_size < size || file->stat_info->archive_file_size < 0)
381 return add_fail;
382
383 sparse_add_map (file->stat_info, &sp);
384
385 return add_ok;
386 }
387
388
389
390 static gboolean
391 oldgnu_sparse_member_p (struct tar_sparse_file *file)
392 {
393 (void) file;
394
395 return current_header->header.typeflag == GNUTYPE_SPARSE;
396 }
397
398
399
400 static gboolean
401 oldgnu_fixup_header (struct tar_sparse_file *file)
402 {
403
404
405 off_t realsize;
406
407 realsize = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
408 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
409 file->stat_info->stat.st_size = MAX (0, realsize);
410
411 return (realsize >= 0);
412 }
413
414
415
416
417
418
419 static gboolean
420 oldgnu_get_sparse_info (tar_super_t *archive, struct tar_sparse_file *file)
421 {
422 size_t i;
423 union block *h = current_header;
424 gboolean ext_p;
425 enum oldgnu_add_status rc = add_fail;
426
427 if (file->stat_info->sparse_map != NULL)
428 g_array_set_size (file->stat_info->sparse_map, 0);
429
430 for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
431 {
432 rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
433 if (rc != add_ok)
434 break;
435 }
436
437 for (ext_p = h->oldgnu_header.isextended != 0; rc == add_ok && ext_p;
438 ext_p = h->sparse_header.isextended != 0)
439 {
440 h = tar_find_next_block (archive);
441 if (h == NULL)
442 return FALSE;
443
444 tar_set_next_block_after (h);
445
446 for (i = 0; i < SPARSES_IN_SPARSE_HEADER && rc == add_ok; i++)
447 rc = oldgnu_add_sparse (file, &h->sparse_header.sp[i]);
448 }
449
450 return (rc != add_fail);
451 }
452
453
454
455 static gboolean
456 star_sparse_member_p (struct tar_sparse_file *file)
457 {
458 (void) file;
459
460 return current_header->header.typeflag == GNUTYPE_SPARSE;
461 }
462
463
464
465 static gboolean
466 star_fixup_header (struct tar_sparse_file *file)
467 {
468
469
470 off_t realsize;
471
472 realsize = OFF_FROM_HEADER (current_header->star_in_header.realsize);
473 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
474 file->stat_info->stat.st_size = MAX (0, realsize);
475
476 return (realsize >= 0);
477 }
478
479
480
481
482
483
484 static gboolean
485 star_get_sparse_info (tar_super_t *archive, struct tar_sparse_file *file)
486 {
487 size_t i;
488 union block *h = current_header;
489 gboolean ext_p = TRUE;
490 enum oldgnu_add_status rc = add_ok;
491
492 if (file->stat_info->sparse_map != NULL)
493 g_array_set_size (file->stat_info->sparse_map, 0);
494
495 if (h->star_in_header.prefix[0] == '\0' && h->star_in_header.sp[0].offset[10] != '\0')
496 {
497
498 for (i = 0; i < SPARSES_IN_STAR_HEADER; i++)
499 {
500 rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]);
501 if (rc != add_ok)
502 break;
503 }
504
505 ext_p = h->star_in_header.isextended != 0;
506 }
507
508 for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended != 0)
509 {
510 h = tar_find_next_block (archive);
511 if (h == NULL)
512 return FALSE;
513
514 tar_set_next_block_after (h);
515
516 for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
517 rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
518
519 file->dumped_size += BLOCKSIZE;
520 }
521
522 return (rc != add_fail);
523 }
524
525
526
527 static gboolean
528 pax_sparse_member_p (struct tar_sparse_file *file)
529 {
530 return file->stat_info->sparse_map != NULL && file->stat_info->sparse_map->len > 0
531 && file->stat_info->sparse_major > 0;
532 }
533
534
535
536 static gboolean
537 pax_decode_header (tar_super_t *archive, struct tar_sparse_file *file)
538 {
539 if (file->stat_info->sparse_major > 0)
540 {
541 uintmax_t u;
542 char nbuf[UINTMAX_STRSIZE_BOUND];
543 union block *blk;
544 char *p;
545 size_t sparse_map_len;
546 size_t i;
547 off_t start;
548
549 start = tar_current_block_ordinal (archive);
550 tar_set_next_block_after (current_header);
551 blk = tar_find_next_block (archive);
552 if (blk == NULL)
553
554 return FALSE;
555 p = blk->buffer;
556 COPY_BUF (archive, blk, nbuf, p);
557
558 if (!decode_num (&u, nbuf, SIZE_MAX))
559 {
560
561 return FALSE;
562 }
563
564 if (file->stat_info->sparse_map == NULL)
565 file->stat_info->sparse_map =
566 g_array_sized_new (FALSE, FALSE, sizeof (struct sp_array), u);
567 else
568 g_array_set_size (file->stat_info->sparse_map, u);
569
570 sparse_map_len = u;
571
572 for (i = 0; i < sparse_map_len; i++)
573 {
574 struct sp_array sp;
575 off_t size;
576
577 COPY_BUF (archive, blk, nbuf, p);
578 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
579 {
580
581 return FALSE;
582 }
583 sp.offset = u;
584 COPY_BUF (archive, blk, nbuf, p);
585 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)) || ckd_add (&size, sp.offset, u)
586 || file->stat_info->stat.st_size < size)
587 {
588
589 return FALSE;
590 }
591 sp.numbytes = u;
592 sparse_add_map (file->stat_info, &sp);
593 }
594
595 tar_set_next_block_after (blk);
596
597 file->dumped_size += BLOCKSIZE * (tar_current_block_ordinal (archive) - start);
598 }
599
600 return TRUE;
601 }
602
603
604
605
606
607 gboolean
608 tar_sparse_member_p (tar_super_t *archive, struct tar_stat_info *st)
609 {
610 struct tar_sparse_file file;
611
612 if (!sparse_init (archive, &file))
613 return FALSE;
614
615 file.stat_info = st;
616 return sparse_member_p (&file);
617 }
618
619
620
621 gboolean
622 tar_sparse_fixup_header (tar_super_t *archive, struct tar_stat_info *st)
623 {
624 struct tar_sparse_file file;
625
626 if (!sparse_init (archive, &file))
627 return FALSE;
628
629 file.stat_info = st;
630 return sparse_fixup_header (&file);
631 }
632
633
634
635 enum dump_status
636 tar_sparse_skip_file (tar_super_t *archive, struct tar_stat_info *st)
637 {
638 gboolean rc = TRUE;
639 struct tar_sparse_file file;
640
641 if (!sparse_init (archive, &file))
642 return dump_status_not_implemented;
643
644 file.stat_info = st;
645 file.fd = -1;
646
647 rc = sparse_decode_header (archive, &file);
648 (void) tar_skip_file (archive, file.stat_info->archive_file_size - file.dumped_size);
649 return (sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
650 }
651
652