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 SPARSES_INIT_COUNT SPARSES_IN_SPARSE_HEADER
82
83 #define COPY_BUF(arch,b,buf,src) \
84 do \
85 { \
86 char *endp = b->buffer + BLOCKSIZE; \
87 char *dst = buf; \
88 do \
89 { \
90 if (dst == buf + UINTMAX_STRSIZE_BOUND - 1) \
91 \
92 return FALSE; \
93 if (src == endp) \
94 { \
95 tar_set_next_block_after (b); \
96 b = tar_find_next_block (arch); \
97 if (b == NULL) \
98 \
99 return FALSE; \
100 src = b->buffer; \
101 endp = b->buffer + BLOCKSIZE; \
102 } \
103 *dst = *src++; \
104 } \
105 while (*dst++ != '\n'); \
106 dst[-1] = '\0'; \
107 } \
108 while (FALSE)
109
110
111
112 struct tar_sparse_file;
113
114 struct tar_sparse_optab
115 {
116 gboolean (*init) (struct tar_sparse_file * file);
117 gboolean (*done) (struct tar_sparse_file * file);
118 gboolean (*sparse_member_p) (struct tar_sparse_file * file);
119 gboolean (*fixup_header) (struct tar_sparse_file * file);
120 gboolean (*decode_header) (tar_super_t * archive, struct tar_sparse_file * file);
121 };
122
123 struct tar_sparse_file
124 {
125 int fd;
126 off_t dumped_size;
127 struct tar_stat_info *stat_info;
128 struct tar_sparse_optab const *optab;
129 void *closure;
130 };
131
132 enum oldgnu_add_status
133 {
134 add_ok,
135 add_finish,
136 add_fail
137 };
138
139
140
141 static gboolean oldgnu_sparse_member_p (struct tar_sparse_file *file);
142 static gboolean oldgnu_fixup_header (struct tar_sparse_file *file);
143 static gboolean oldgnu_get_sparse_info (tar_super_t * archive, struct tar_sparse_file *file);
144
145 static gboolean star_sparse_member_p (struct tar_sparse_file *file);
146 static gboolean star_fixup_header (struct tar_sparse_file *file);
147 static gboolean star_get_sparse_info (tar_super_t * archive, struct tar_sparse_file *file);
148
149 static gboolean pax_sparse_member_p (struct tar_sparse_file *file);
150 static gboolean pax_decode_header (tar_super_t * archive, struct tar_sparse_file *file);
151
152
153
154
155 static struct tar_sparse_optab const oldgnu_optab =
156 {
157 .init = NULL,
158 .done = NULL,
159 .sparse_member_p = oldgnu_sparse_member_p,
160 .fixup_header = oldgnu_fixup_header,
161 .decode_header = oldgnu_get_sparse_info
162 };
163
164
165
166 static struct tar_sparse_optab const star_optab =
167 {
168 .init = NULL,
169 .done = NULL,
170 .sparse_member_p = star_sparse_member_p,
171 .fixup_header = star_fixup_header,
172 .decode_header = star_get_sparse_info
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
240
241 static struct tar_sparse_optab const pax_optab = {
242 .init = NULL,
243 .done = NULL,
244 .sparse_member_p = pax_sparse_member_p,
245 .fixup_header = NULL,
246 .decode_header = pax_decode_header
247 };
248
249
250
251
252
253 static gboolean
254 decode_num (uintmax_t *num, const char *arg, uintmax_t maxval)
255 {
256 char *arg_lim = NULL;
257 gboolean overflow = FALSE;
258
259 *num = stoint (arg, &arg_lim, &overflow, 0, maxval);
260 return !(arg_lim == arg || *arg_lim != '\0' || overflow);
261 }
262
263
264
265 static gboolean
266 sparse_select_optab (const tar_super_t *archive, struct tar_sparse_file *file)
267 {
268 switch (archive->type)
269 {
270 case TAR_V7:
271 case TAR_USTAR:
272 return FALSE;
273
274 case TAR_OLDGNU:
275 case TAR_GNU:
276 file->optab = &oldgnu_optab;
277 break;
278
279 case TAR_POSIX:
280 file->optab = &pax_optab;
281 break;
282
283 case TAR_STAR:
284 file->optab = &star_optab;
285 break;
286
287 default:
288 return FALSE;
289 }
290
291 return TRUE;
292 }
293
294
295
296 static gboolean
297 sparse_init (tar_super_t *archive, struct tar_sparse_file *file)
298 {
299 memset (file, 0, sizeof (*file));
300
301 if (!sparse_select_optab (archive, file))
302 return FALSE;
303
304 if (file->optab->init != NULL)
305 return file->optab->init (file);
306
307 return TRUE;
308 }
309
310
311
312 static gboolean
313 sparse_done (struct tar_sparse_file *file)
314 {
315 if (file->optab->done != NULL)
316 return file->optab->done (file);
317
318 return TRUE;
319 }
320
321
322
323 static gboolean
324 sparse_member_p (struct tar_sparse_file *file)
325 {
326 if (file->optab->sparse_member_p != NULL)
327 return file->optab->sparse_member_p (file);
328
329 return FALSE;
330 }
331
332
333
334 static gboolean
335 sparse_fixup_header (struct tar_sparse_file *file)
336 {
337 if (file->optab->fixup_header != NULL)
338 return file->optab->fixup_header (file);
339
340 return TRUE;
341 }
342
343
344
345 static gboolean
346 sparse_decode_header (tar_super_t *archive, struct tar_sparse_file *file)
347 {
348 if (file->optab->decode_header != NULL)
349 return file->optab->decode_header (archive, file);
350
351 return TRUE;
352 }
353
354
355
356 static inline void
357 sparse_add_map (struct tar_stat_info *st, struct sp_array *sp)
358 {
359 if (st->sparse_map == NULL)
360 st->sparse_map = g_array_sized_new (FALSE, FALSE, sizeof (struct sp_array), 1);
361 g_array_append_val (st->sparse_map, *sp);
362 }
363
364
365
366
367
368
369 static enum oldgnu_add_status
370 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
371 {
372 struct sp_array sp;
373 off_t size;
374
375 if (s->numbytes[0] == '\0')
376 return add_finish;
377
378 sp.offset = OFF_FROM_HEADER (s->offset);
379 sp.numbytes = OFF_FROM_HEADER (s->numbytes);
380
381 if (sp.offset < 0 || sp.numbytes < 0 || ckd_add (&size, sp.offset, sp.numbytes)
382 || file->stat_info->stat.st_size < size || file->stat_info->archive_file_size < 0)
383 return add_fail;
384
385 sparse_add_map (file->stat_info, &sp);
386
387 return add_ok;
388 }
389
390
391
392 static gboolean
393 oldgnu_sparse_member_p (struct tar_sparse_file *file)
394 {
395 (void) file;
396
397 return current_header->header.typeflag == GNUTYPE_SPARSE;
398 }
399
400
401
402 static gboolean
403 oldgnu_fixup_header (struct tar_sparse_file *file)
404 {
405
406
407 off_t realsize;
408
409 realsize = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
410 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
411 file->stat_info->stat.st_size = MAX (0, realsize);
412
413 return (realsize >= 0);
414 }
415
416
417
418
419
420
421 static gboolean
422 oldgnu_get_sparse_info (tar_super_t *archive, struct tar_sparse_file *file)
423 {
424 size_t i;
425 union block *h = current_header;
426 gboolean ext_p;
427 enum oldgnu_add_status rc = add_fail;
428
429 if (file->stat_info->sparse_map != NULL)
430 g_array_set_size (file->stat_info->sparse_map, 0);
431
432 for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
433 {
434 rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
435 if (rc != add_ok)
436 break;
437 }
438
439 for (ext_p = h->oldgnu_header.isextended != 0; rc == add_ok && ext_p;
440 ext_p = h->sparse_header.isextended != 0)
441 {
442 h = tar_find_next_block (archive);
443 if (h == NULL)
444 return FALSE;
445
446 tar_set_next_block_after (h);
447
448 for (i = 0; i < SPARSES_IN_SPARSE_HEADER && rc == add_ok; i++)
449 rc = oldgnu_add_sparse (file, &h->sparse_header.sp[i]);
450 }
451
452 return (rc != add_fail);
453 }
454
455
456
457 static gboolean
458 star_sparse_member_p (struct tar_sparse_file *file)
459 {
460 (void) file;
461
462 return current_header->header.typeflag == GNUTYPE_SPARSE;
463 }
464
465
466
467 static gboolean
468 star_fixup_header (struct tar_sparse_file *file)
469 {
470
471
472 off_t realsize;
473
474 realsize = OFF_FROM_HEADER (current_header->star_in_header.realsize);
475 file->stat_info->archive_file_size = file->stat_info->stat.st_size;
476 file->stat_info->stat.st_size = MAX (0, realsize);
477
478 return (realsize >= 0);
479 }
480
481
482
483
484
485
486 static gboolean
487 star_get_sparse_info (tar_super_t *archive, struct tar_sparse_file *file)
488 {
489 size_t i;
490 union block *h = current_header;
491 gboolean ext_p = TRUE;
492 enum oldgnu_add_status rc = add_ok;
493
494 if (file->stat_info->sparse_map != NULL)
495 g_array_set_size (file->stat_info->sparse_map, 0);
496
497 if (h->star_in_header.prefix[0] == '\0' && h->star_in_header.sp[0].offset[10] != '\0')
498 {
499
500 for (i = 0; i < SPARSES_IN_STAR_HEADER; i++)
501 {
502 rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]);
503 if (rc != add_ok)
504 break;
505 }
506
507 ext_p = h->star_in_header.isextended != 0;
508 }
509
510 for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended != 0)
511 {
512 h = tar_find_next_block (archive);
513 if (h == NULL)
514 return FALSE;
515
516 tar_set_next_block_after (h);
517
518 for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++)
519 rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]);
520
521 file->dumped_size += BLOCKSIZE;
522 }
523
524 return (rc != add_fail);
525 }
526
527
528
529 static gboolean
530 pax_sparse_member_p (struct tar_sparse_file *file)
531 {
532 return file->stat_info->sparse_map != NULL && file->stat_info->sparse_map->len > 0
533 && file->stat_info->sparse_major > 0;
534 }
535
536
537
538 static gboolean
539 pax_decode_header (tar_super_t *archive, struct tar_sparse_file *file)
540 {
541 if (file->stat_info->sparse_major > 0)
542 {
543 uintmax_t u;
544 char nbuf[UINTMAX_STRSIZE_BOUND];
545 union block *blk;
546 char *p;
547 size_t sparse_map_len;
548 size_t i;
549 off_t start;
550
551 start = tar_current_block_ordinal (archive);
552 tar_set_next_block_after (current_header);
553 blk = tar_find_next_block (archive);
554 if (blk == NULL)
555
556 return FALSE;
557 p = blk->buffer;
558 COPY_BUF (archive, blk, nbuf, p);
559
560 if (!decode_num (&u, nbuf, SIZE_MAX))
561 {
562
563 return FALSE;
564 }
565
566 if (file->stat_info->sparse_map == NULL)
567 file->stat_info->sparse_map =
568 g_array_sized_new (FALSE, FALSE, sizeof (struct sp_array), u);
569 else
570 g_array_set_size (file->stat_info->sparse_map, u);
571
572 sparse_map_len = u;
573
574 for (i = 0; i < sparse_map_len; i++)
575 {
576 struct sp_array sp;
577 off_t size;
578
579 COPY_BUF (archive, blk, nbuf, p);
580 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
581 {
582
583 return FALSE;
584 }
585 sp.offset = u;
586 COPY_BUF (archive, blk, nbuf, p);
587 if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)) || ckd_add (&size, sp.offset, u)
588 || file->stat_info->stat.st_size < size)
589 {
590
591 return FALSE;
592 }
593 sp.numbytes = u;
594 sparse_add_map (file->stat_info, &sp);
595 }
596
597 tar_set_next_block_after (blk);
598
599 file->dumped_size += BLOCKSIZE * (tar_current_block_ordinal (archive) - start);
600 }
601
602 return TRUE;
603 }
604
605
606
607
608
609 gboolean
610 tar_sparse_member_p (tar_super_t *archive, struct tar_stat_info *st)
611 {
612 struct tar_sparse_file file;
613
614 if (!sparse_init (archive, &file))
615 return FALSE;
616
617 file.stat_info = st;
618 return sparse_member_p (&file);
619 }
620
621
622
623 gboolean
624 tar_sparse_fixup_header (tar_super_t *archive, struct tar_stat_info *st)
625 {
626 struct tar_sparse_file file;
627
628 if (!sparse_init (archive, &file))
629 return FALSE;
630
631 file.stat_info = st;
632 return sparse_fixup_header (&file);
633 }
634
635
636
637 enum dump_status
638 tar_sparse_skip_file (tar_super_t *archive, struct tar_stat_info *st)
639 {
640 gboolean rc = TRUE;
641 struct tar_sparse_file file;
642
643 if (!sparse_init (archive, &file))
644 return dump_status_not_implemented;
645
646 file.stat_info = st;
647 file.fd = -1;
648
649 rc = sparse_decode_header (archive, &file);
650 (void) tar_skip_file (archive, file.stat_info->archive_file_size - file.dumped_size);
651 return (sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
652 }
653
654