This source file includes following definitions.
- tar_stat_destroy
- gid_from_header
- major_from_header
- minor_from_header
- mode_from_header
- time_from_header
- uid_from_header
- tar_calc_sparse_offsets
- tar_skip_member
- tar_available_space_after
- tar_checksum
- tar_decode_header
- tar_fill_stat
- tar_free_inode
- tar_insert_entry
- tar_read_header
- tar_new_archive
- tar_free_archive
- tar_open_archive_int
- tar_open_archive
- tar_super_check
- tar_super_same
- tar_get_sparse_chunk_idx
- tar_read_sparse
- tar_lseek_sparse
- tar_read
- tar_fh_open
- vfs_init_tarfs
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 #include <config.h>
37
38 #include <errno.h>
39 #include <string.h>
40
41 #ifdef hpux
42
43 #include <sys/mknod.h>
44 #endif
45
46 #include "lib/global.h"
47 #include "lib/util.h"
48 #include "lib/unixcompat.h"
49 #include "lib/widget.h"
50
51 #include "lib/vfs/vfs.h"
52 #include "lib/vfs/utilvfs.h"
53 #include "lib/vfs/gc.h"
54
55 #include "tar-internal.h"
56 #include "tar.h"
57
58
59
60
61
62 const idx_t blocking_factor = DEFAULT_BLOCKING;
63 const idx_t record_size = DEFAULT_BLOCKING * BLOCKSIZE;
64
65
66 union block *record_end;
67 union block *current_block;
68 off_t record_start_block;
69
70 union block *current_header;
71
72
73 gboolean hit_eof;
74
75 struct tar_stat_info current_stat_info;
76
77
78
79 #define TAR_SUPER(super) ((tar_super_t *) (super))
80
81
82
83
84 #define TMAGIC "ustar"
85
86 #define XHDTYPE 'x'
87 #define XGLTYPE 'g'
88
89
90 #define REGTYPE '0'
91 #define AREGTYPE '\0'
92 #define LNKTYPE '1'
93 #define SYMTYPE '2'
94 #define CHRTYPE '3'
95 #define BLKTYPE '4'
96 #define DIRTYPE '5'
97 #define FIFOTYPE '6'
98
99
100
101
102
103
104 #define OLDGNU_MAGIC "ustar "
105
106
107
108 #define TSUID 04000
109 #define TSGID 02000
110 #define TSVTX 01000
111
112 #define TUREAD 00400
113 #define TUWRITE 00200
114 #define TUEXEC 00100
115 #define TGREAD 00040
116 #define TGWRITE 00020
117 #define TGEXEC 00010
118 #define TOREAD 00004
119 #define TOWRITE 00002
120 #define TOEXEC 00001
121
122 #define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
123 #define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
124 #define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
125 #define MODE_FROM_HEADER(where,hbits) mode_from_header (where, sizeof (where), hbits)
126 #define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
127 #define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
128
129
130
131 typedef enum
132 {
133 HEADER_STILL_UNREAD,
134 HEADER_SUCCESS,
135 HEADER_ZERO_BLOCK,
136 HEADER_END_OF_FILE,
137 HEADER_FAILURE
138 } read_header;
139
140
141
142
143
144 static struct vfs_s_subclass tarfs_subclass;
145 static struct vfs_class *vfs_tarfs_ops = VFS_CLASS (&tarfs_subclass);
146
147 static struct timespec start_time;
148
149
150
151
152
153 static void
154 tar_stat_destroy (struct tar_stat_info *st)
155 {
156 g_free (st->orig_file_name);
157 g_free (st->file_name);
158 g_free (st->link_name);
159 #if 0
160 g_free (st->uname);
161 g_free (st->gname);
162 #endif
163 if (st->sparse_map != NULL)
164 {
165 g_array_free (st->sparse_map, TRUE);
166 st->sparse_map = NULL;
167 }
168 tar_xheader_destroy (&st->xhdr);
169 memset (st, 0, sizeof (*st));
170 }
171
172
173
174 static inline gid_t
175 gid_from_header (const char *p, size_t s)
176 {
177 return tar_from_header (p, s, "gid_t", TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t), FALSE);
178 }
179
180
181
182 static inline major_t
183 major_from_header (const char *p, size_t s)
184 {
185 return tar_from_header (p, s, "major_t", TYPE_MINIMUM (major_t), TYPE_MAXIMUM (major_t), FALSE);
186 }
187
188
189
190 static inline minor_t
191 minor_from_header (const char *p, size_t s)
192 {
193 return tar_from_header (p, s, "minor_t", TYPE_MINIMUM (minor_t), TYPE_MAXIMUM (minor_t), FALSE);
194 }
195
196
197
198
199
200
201
202
203 static inline mode_t
204 mode_from_header (const char *p, size_t s, gboolean *hbits)
205 {
206 unsigned int u;
207 mode_t mode;
208
209
210 u = tar_from_header (p, s, "mode_t", INTMAX_MIN, UINTMAX_MAX, FALSE);
211
212
213 mode = ((u & TSUID ? S_ISUID : 0)
214 | (u & TSGID ? S_ISGID : 0)
215 | (u & TSVTX ? S_ISVTX : 0)
216 | (u & TUREAD ? S_IRUSR : 0)
217 | (u & TUWRITE ? S_IWUSR : 0)
218 | (u & TUEXEC ? S_IXUSR : 0)
219 | (u & TGREAD ? S_IRGRP : 0)
220 | (u & TGWRITE ? S_IWGRP : 0)
221 | (u & TGEXEC ? S_IXGRP : 0)
222 | (u & TOREAD ? S_IROTH : 0)
223 | (u & TOWRITE ? S_IWOTH : 0)
224 | (u & TOEXEC ? S_IXOTH : 0));
225
226
227 if (hbits != NULL)
228 *hbits = (u & ~07777) != 0;
229
230 return mode;
231 }
232
233
234
235 static inline time_t
236 time_from_header (const char *p, size_t s)
237 {
238 return tar_from_header (p, s, "time_t", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), FALSE);
239 }
240
241
242
243 static inline uid_t
244 uid_from_header (const char *p, size_t s)
245 {
246 return tar_from_header (p, s, "uid_t", TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), FALSE);
247 }
248
249
250
251 static void
252 tar_calc_sparse_offsets (struct vfs_s_inode *inode)
253 {
254 off_t begin = inode->data_offset;
255 GArray *sm = (GArray *) inode->user_data;
256 size_t i;
257
258 for (i = 0; i < sm->len; i++)
259 {
260 struct sp_array *sp;
261
262 sp = &g_array_index (sm, struct sp_array, i);
263 sp->arch_offset = begin;
264 begin += BLOCKSIZE * (sp->numbytes / BLOCKSIZE + sp->numbytes % BLOCKSIZE);
265 }
266 }
267
268
269
270 static gboolean
271 tar_skip_member (tar_super_t *archive, struct vfs_s_inode *inode)
272 {
273 char save_typeflag;
274
275 if (current_stat_info.skipped)
276 return TRUE;
277
278 save_typeflag = current_header->header.typeflag;
279
280 tar_set_next_block_after (current_header);
281
282 if (current_stat_info.is_sparse)
283 {
284 if (inode != NULL)
285 inode->data_offset = BLOCKSIZE * tar_current_block_ordinal (archive);
286
287 (void) tar_sparse_skip_file (archive, ¤t_stat_info);
288
289 if (inode != NULL)
290 {
291
292 inode->user_data = current_stat_info.sparse_map;
293 current_stat_info.sparse_map = NULL;
294
295 tar_calc_sparse_offsets (inode);
296 }
297 }
298 else if (save_typeflag != DIRTYPE)
299 {
300 if (inode != NULL && (save_typeflag == REGTYPE || save_typeflag == AREGTYPE))
301 inode->data_offset = BLOCKSIZE * tar_current_block_ordinal (archive);
302
303 return tar_skip_file (archive, current_stat_info.stat.st_size);
304 }
305
306 return TRUE;
307 }
308
309
310
311
312
313
314
315
316
317 static inline size_t
318 tar_available_space_after (const union block *pointer)
319 {
320 return record_end->buffer - pointer->buffer;
321 }
322
323
324
325
326
327 static read_header
328 tar_checksum (const union block *header)
329 {
330 unsigned int i;
331 int unsigned_sum = 0;
332 int signed_sum = 0;
333 int recorded_sum;
334
335 for (i = 0; i < sizeof (*header); i++)
336 {
337 unsigned char uc = header->buffer[i];
338 signed char sc = header->buffer[i];
339
340 unsigned_sum += uc;
341 signed_sum += sc;
342 }
343
344 if (unsigned_sum == 0)
345 return HEADER_ZERO_BLOCK;
346
347
348 for (i = 0; i < sizeof (header->header.chksum); i++)
349 {
350 unsigned char uc = header->header.chksum[i];
351 signed char sc = header->header.chksum[i];
352
353 unsigned_sum -= uc;
354 signed_sum -= sc;
355 }
356
357 unsigned_sum += ' ' * sizeof (header->header.chksum);
358 signed_sum += ' ' * sizeof (header->header.chksum);
359
360 recorded_sum =
361 tar_from_header (header->header.chksum, sizeof (header->header.chksum), NULL, 0,
362 INT_MAX, TRUE);
363
364 if (recorded_sum < 0)
365 return HEADER_FAILURE;
366
367 if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
368 return HEADER_FAILURE;
369
370 return HEADER_SUCCESS;
371 }
372
373
374
375 static void
376 tar_decode_header (union block *header, tar_super_t *arch)
377 {
378 gboolean hbits = FALSE;
379
380 current_stat_info.stat.st_mode = MODE_FROM_HEADER (header->header.mode, &hbits);
381
382
383
384
385 if (arch->type == TAR_UNKNOWN)
386 {
387 if (strcmp (header->header.magic, TMAGIC) == 0)
388 {
389 if (header->star_header.prefix[130] == 0
390 && is_octal_digit (header->star_header.atime[0])
391 && header->star_header.atime[11] == ' '
392 && is_octal_digit (header->star_header.ctime[0])
393 && header->star_header.ctime[11] == ' ')
394 arch->type = TAR_STAR;
395 else if (current_stat_info.xhdr.buffer != NULL)
396 arch->type = TAR_POSIX;
397 else
398 arch->type = TAR_USTAR;
399 }
400 else if (strcmp (header->buffer + offsetof (struct posix_header, magic), OLDGNU_MAGIC) == 0)
401 arch->type = hbits ? TAR_OLDGNU : TAR_GNU;
402 else
403 arch->type = TAR_V7;
404 }
405
406
407
408
409 if (header->header.typeflag == '\000')
410 {
411 size_t len;
412
413 if (header->header.name[sizeof (header->header.name) - 1] != '\0')
414 len = sizeof (header->header.name);
415 else
416 len = strlen (header->header.name);
417
418 if (len != 0 && IS_PATH_SEP (header->header.name[len - 1]))
419 header->header.typeflag = DIRTYPE;
420 }
421
422 if (header->header.typeflag == GNUTYPE_DUMPDIR)
423 if (arch->type == TAR_UNKNOWN)
424 arch->type = TAR_GNU;
425 }
426
427
428
429 static void
430 tar_fill_stat (struct vfs_s_super *archive, union block *header)
431 {
432 tar_super_t *arch = TAR_SUPER (archive);
433
434
435
436
437
438
439 if (header->header.typeflag == DIRTYPE || header->header.typeflag == GNUTYPE_DUMPDIR)
440 current_stat_info.stat.st_mode |= S_IFDIR;
441 else if (header->header.typeflag == SYMTYPE)
442 current_stat_info.stat.st_mode |= S_IFLNK;
443 else if (header->header.typeflag == CHRTYPE)
444 current_stat_info.stat.st_mode |= S_IFCHR;
445 else if (header->header.typeflag == BLKTYPE)
446 current_stat_info.stat.st_mode |= S_IFBLK;
447 else if (header->header.typeflag == FIFOTYPE)
448 current_stat_info.stat.st_mode |= S_IFIFO;
449 else
450 current_stat_info.stat.st_mode |= S_IFREG;
451
452 current_stat_info.stat.st_dev = 0;
453 #ifdef HAVE_STRUCT_STAT_ST_RDEV
454 current_stat_info.stat.st_rdev = 0;
455 #endif
456
457 switch (arch->type)
458 {
459 case TAR_USTAR:
460 case TAR_POSIX:
461 case TAR_GNU:
462 case TAR_OLDGNU:
463
464 current_stat_info.stat.st_uid = *header->header.uname != '\0'
465 ? (uid_t) vfs_finduid (header->header.uname)
466 : UID_FROM_HEADER (header->header.uid);
467 current_stat_info.stat.st_gid = *header->header.gname != '\0'
468 ? (gid_t) vfs_findgid (header->header.gname)
469 : GID_FROM_HEADER (header->header.gid);
470
471
472 switch (header->header.typeflag)
473 {
474 case BLKTYPE:
475 case CHRTYPE:
476 #ifdef HAVE_STRUCT_STAT_ST_RDEV
477 current_stat_info.stat.st_rdev =
478 makedev (MAJOR_FROM_HEADER (header->header.devmajor),
479 MINOR_FROM_HEADER (header->header.devminor));
480 #endif
481 break;
482 default:
483 break;
484 }
485 break;
486
487 default:
488 current_stat_info.stat.st_uid = UID_FROM_HEADER (header->header.uid);
489 current_stat_info.stat.st_gid = GID_FROM_HEADER (header->header.gid);
490 break;
491 }
492
493 current_stat_info.atime.tv_nsec = 0;
494 current_stat_info.mtime.tv_nsec = 0;
495 current_stat_info.ctime.tv_nsec = 0;
496
497 current_stat_info.mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
498 if (arch->type == TAR_GNU || arch->type == TAR_OLDGNU)
499 {
500 current_stat_info.atime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.atime);
501 current_stat_info.ctime.tv_sec = TIME_FROM_HEADER (header->oldgnu_header.ctime);
502 }
503 else if (arch->type == TAR_STAR)
504 {
505 current_stat_info.atime.tv_sec = TIME_FROM_HEADER (header->star_header.atime);
506 current_stat_info.ctime.tv_sec = TIME_FROM_HEADER (header->star_header.ctime);
507 }
508 else
509 current_stat_info.atime = current_stat_info.ctime = start_time;
510
511 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
512 current_stat_info.stat.st_blksize = 8 * 1024;
513 #endif
514 vfs_adjust_stat (¤t_stat_info.stat);
515 }
516
517
518
519 static void
520 tar_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
521 {
522 (void) me;
523
524
525 if (ino->user_data != NULL)
526 g_array_free ((GArray *) ino->user_data, TRUE);
527 }
528
529
530
531 static read_header
532 tar_insert_entry (struct vfs_class *me, struct vfs_s_super *archive, union block *header,
533 struct vfs_s_inode **inode)
534 {
535 char *p, *q;
536 char *file_name = current_stat_info.file_name;
537 char *link_name = current_stat_info.link_name;
538 size_t len;
539 struct vfs_s_inode *parent;
540 struct vfs_s_entry *entry;
541
542 p = strrchr (file_name, PATH_SEP);
543 if (p == NULL)
544 {
545 len = strlen (file_name);
546 p = file_name;
547 q = file_name + len;
548 }
549 else
550 {
551 *(p++) = '\0';
552 q = file_name;
553 }
554
555 parent = vfs_s_find_inode (me, archive, q, LINK_NO_FOLLOW, FL_MKDIR);
556 if (parent == NULL)
557 return HEADER_FAILURE;
558
559 *inode = NULL;
560
561 if (header->header.typeflag == LNKTYPE)
562 {
563 if (*link_name != '\0')
564 {
565 len = strlen (link_name);
566 if (IS_PATH_SEP (link_name[len - 1]))
567 link_name[len - 1] = '\0';
568
569 *inode = vfs_s_find_inode (me, archive, link_name, LINK_NO_FOLLOW, FL_NONE);
570 }
571
572 if (*inode == NULL)
573 return HEADER_FAILURE;
574 }
575 else
576 {
577 if (S_ISDIR (current_stat_info.stat.st_mode))
578 {
579 entry = VFS_SUBCLASS (me)->find_entry (me, parent, p, LINK_NO_FOLLOW, FL_NONE);
580 if (entry != NULL)
581 return HEADER_SUCCESS;
582 }
583
584 *inode = vfs_s_new_inode (me, archive, ¤t_stat_info.stat);
585
586 (*inode)->st.st_mtime = current_stat_info.mtime.tv_sec;
587 (*inode)->st.st_atime = current_stat_info.atime.tv_sec;
588 (*inode)->st.st_ctime = current_stat_info.ctime.tv_sec;
589
590 if (link_name != NULL && *link_name != '\0')
591 (*inode)->linkname = g_strdup (link_name);
592 }
593
594 entry = vfs_s_new_entry (me, p, *inode);
595 vfs_s_insert_entry (me, parent, entry);
596
597 return HEADER_SUCCESS;
598 }
599
600
601
602 static read_header
603 tar_read_header (struct vfs_class *me, struct vfs_s_super *archive)
604 {
605 tar_super_t *arch = TAR_SUPER (archive);
606 union block *header;
607 union block *next_long_name = NULL, *next_long_link = NULL;
608 read_header status = HEADER_SUCCESS;
609
610 while (TRUE)
611 {
612 header = tar_find_next_block (arch);
613 current_header = header;
614 if (header == NULL)
615 {
616 status = HEADER_END_OF_FILE;
617 goto ret;
618 }
619
620 status = tar_checksum (header);
621 if (status != HEADER_SUCCESS)
622 goto ret;
623
624 if (header->header.typeflag == LNKTYPE || header->header.typeflag == DIRTYPE)
625 current_stat_info.stat.st_size = 0;
626 else
627 {
628 current_stat_info.stat.st_size = OFF_FROM_HEADER (header->header.size);
629 if (current_stat_info.stat.st_size < 0)
630 {
631 status = HEADER_FAILURE;
632 goto ret;
633 }
634 }
635
636 tar_decode_header (header, arch);
637 tar_fill_stat (archive, header);
638
639 if (header->header.typeflag == GNUTYPE_LONGNAME
640 || header->header.typeflag == GNUTYPE_LONGLINK)
641 {
642 off_t size;
643 union block *header_copy;
644 char *bp;
645 size_t written;
646
647 if (arch->type == TAR_UNKNOWN)
648 arch->type = TAR_GNU;
649
650 if (ckd_add (&size, current_stat_info.stat.st_size, 2 * BLOCKSIZE - 1))
651 {
652 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
653 status = HEADER_FAILURE;
654 goto ret;
655 }
656
657 size -= size % BLOCKSIZE;
658
659 header_copy = g_malloc (size + 1);
660
661 if (header->header.typeflag == GNUTYPE_LONGNAME)
662 {
663 g_free (next_long_name);
664 next_long_name = header_copy;
665 }
666 else
667 {
668 g_free (next_long_link);
669 next_long_link = header_copy;
670 }
671
672 tar_set_next_block_after (header);
673 *header_copy = *header;
674 bp = header_copy->buffer + BLOCKSIZE;
675
676 for (size -= BLOCKSIZE; size > 0; size -= written)
677 {
678 union block *data_block;
679
680 data_block = tar_find_next_block (arch);
681 if (data_block == NULL)
682 {
683 g_free (header_copy);
684 message (D_ERROR, MSG_ERROR, _("Unexpected EOF on archive file"));
685 status = HEADER_FAILURE;
686 goto ret;
687 }
688
689 written = tar_available_space_after (data_block);
690 if ((off_t) written > size)
691 written = (size_t) size;
692
693 memcpy (bp, data_block->buffer, written);
694 bp += written;
695 tar_set_next_block_after ((union block *) (data_block->buffer + written - 1));
696 }
697
698 *bp = '\0';
699 }
700 else if (header->header.typeflag == XHDTYPE || header->header.typeflag == SOLARIS_XHDTYPE)
701 {
702 if (arch->type == TAR_UNKNOWN)
703 arch->type = TAR_POSIX;
704 if (!tar_xheader_read
705 (arch, ¤t_stat_info.xhdr, header, OFF_FROM_HEADER (header->header.size)))
706 {
707 message (D_ERROR, MSG_ERROR, _("Unexpected EOF on archive file"));
708 status = HEADER_FAILURE;
709 goto ret;
710 }
711 }
712 else if (header->header.typeflag == XGLTYPE)
713 {
714 struct xheader xhdr;
715 gboolean ok;
716
717 if (arch->type == TAR_UNKNOWN)
718 arch->type = TAR_POSIX;
719
720 memset (&xhdr, 0, sizeof (xhdr));
721 tar_xheader_read (arch, &xhdr, header, OFF_FROM_HEADER (header->header.size));
722 ok = tar_xheader_decode_global (&xhdr);
723 tar_xheader_destroy (&xhdr);
724
725 if (!ok)
726 {
727 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
728 status = HEADER_FAILURE;
729 goto ret;
730 }
731 }
732 else
733 break;
734 }
735
736 {
737 static union block *recent_long_name = NULL, *recent_long_link = NULL;
738 struct posix_header const *h = &header->header;
739 char *file_name = NULL;
740 char *link_name;
741 struct vfs_s_inode *inode = NULL;
742
743 g_free (recent_long_name);
744
745 if (next_long_name != NULL)
746 {
747 file_name = g_strdup (next_long_name->buffer + BLOCKSIZE);
748 recent_long_name = next_long_name;
749 }
750 else
751 {
752
753 char *s1 = NULL;
754 char *s2;
755
756
757 if (h->prefix[0] != '\0' && strcmp (h->magic, TMAGIC) == 0)
758 s1 = g_strndup (h->prefix, sizeof (h->prefix));
759
760 s2 = g_strndup (h->name, sizeof (h->name));
761
762 if (s1 == NULL)
763 file_name = s2;
764 else
765 {
766 file_name = g_strconcat (s1, PATH_SEP_STR, s2, (char *) NULL);
767 g_free (s1);
768 g_free (s2);
769 }
770
771 recent_long_name = NULL;
772 }
773
774 tar_assign_string_dup (¤t_stat_info.orig_file_name, file_name);
775 tar_assign_string (¤t_stat_info.file_name, file_name);
776
777 g_free (recent_long_link);
778
779 if (next_long_link != NULL)
780 {
781 link_name = g_strdup (next_long_link->buffer + BLOCKSIZE);
782 recent_long_link = next_long_link;
783 }
784 else
785 {
786 link_name = g_strndup (h->linkname, sizeof (h->linkname));
787 recent_long_link = NULL;
788 }
789
790 tar_assign_string (¤t_stat_info.link_name, link_name);
791
792 if (current_stat_info.xhdr.buffer != NULL && !tar_xheader_decode (¤t_stat_info))
793 {
794 status = HEADER_FAILURE;
795 goto ret;
796 }
797
798 if (tar_sparse_member_p (arch, ¤t_stat_info))
799 {
800 if (!tar_sparse_fixup_header (arch, ¤t_stat_info))
801 {
802 status = HEADER_FAILURE;
803 goto ret;
804 }
805
806 current_stat_info.is_sparse = TRUE;
807 }
808 else
809 {
810 current_stat_info.is_sparse = FALSE;
811
812 if (((arch->type == TAR_GNU || arch->type == TAR_OLDGNU)
813 && current_header->header.typeflag == GNUTYPE_DUMPDIR)
814 || current_stat_info.dumpdir != NULL)
815 current_stat_info.is_dumpdir = TRUE;
816 }
817
818
819 canonicalize_pathname (current_stat_info.file_name);
820
821 status = tar_insert_entry (me, archive, header, &inode);
822 if (status != HEADER_SUCCESS)
823 {
824 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
825 goto ret;
826 }
827
828 if (recent_long_name == next_long_name)
829 recent_long_name = NULL;
830
831 if (recent_long_link == next_long_link)
832 recent_long_link = NULL;
833
834 if (tar_skip_member (arch, inode))
835 status = HEADER_SUCCESS;
836 else if (hit_eof)
837 status = HEADER_END_OF_FILE;
838 else
839 status = HEADER_FAILURE;
840 }
841
842 ret:
843 g_free (next_long_name);
844 g_free (next_long_link);
845
846 return status;
847 }
848
849
850
851 static struct vfs_s_super *
852 tar_new_archive (struct vfs_class *me)
853 {
854 tar_super_t *arch;
855 gint64 usec;
856
857 arch = g_new0 (tar_super_t, 1);
858 arch->base.me = me;
859 arch->fd = -1;
860 arch->type = TAR_UNKNOWN;
861
862
863 record_start_block = 0;
864 arch->record_start = g_malloc (record_size);
865 record_end = arch->record_start;
866 current_block = arch->record_start;
867 hit_eof = FALSE;
868
869
870 usec = g_get_real_time ();
871
872 start_time.tv_sec = usec / G_USEC_PER_SEC;
873 start_time.tv_nsec = (usec % G_USEC_PER_SEC) * 1000;
874
875 return VFS_SUPER (arch);
876 }
877
878
879
880 static void
881 tar_free_archive (struct vfs_class *me, struct vfs_s_super *archive)
882 {
883 tar_super_t *arch = TAR_SUPER (archive);
884
885 (void) me;
886
887 if (arch->fd != -1)
888 {
889 mc_close (arch->fd);
890 arch->fd = -1;
891 }
892
893 g_free (arch->record_start);
894 tar_stat_destroy (¤t_stat_info);
895 }
896
897
898
899
900 static gboolean
901 tar_open_archive_int (struct vfs_class *me, const vfs_path_t *vpath, struct vfs_s_super *archive)
902 {
903 tar_super_t *arch = TAR_SUPER (archive);
904 int result, type;
905 mode_t mode;
906 struct vfs_s_inode *root;
907
908 result = mc_open (vpath, O_RDONLY);
909 if (result == -1)
910 {
911 message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), vfs_path_as_str (vpath));
912 ERRNOR (ENOENT, FALSE);
913 }
914
915 archive->name = g_strdup (vfs_path_as_str (vpath));
916 mc_stat (vpath, &arch->st);
917
918
919 type = get_compression_type (result, archive->name);
920 if (type == COMPRESSION_NONE)
921 mc_lseek (result, 0, SEEK_SET);
922 else
923 {
924 char *s;
925 vfs_path_t *tmp_vpath;
926
927 mc_close (result);
928 s = g_strconcat (archive->name, decompress_extension (type), (char *) NULL);
929 tmp_vpath = vfs_path_from_str_flags (s, VPF_NO_CANON);
930 result = mc_open (tmp_vpath, O_RDONLY);
931 vfs_path_free (tmp_vpath, TRUE);
932 if (result == -1)
933 message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), s);
934 g_free (s);
935 if (result == -1)
936 {
937 MC_PTR_FREE (archive->name);
938 ERRNOR (ENOENT, FALSE);
939 }
940 }
941
942 arch->fd = result;
943 mode = arch->st.st_mode & 07777;
944 if (mode & 0400)
945 mode |= 0100;
946 if (mode & 0040)
947 mode |= 0010;
948 if (mode & 0004)
949 mode |= 0001;
950 mode |= S_IFDIR;
951
952 root = vfs_s_new_inode (me, archive, &arch->st);
953 root->st.st_mode = mode;
954 root->data_offset = -1;
955 root->st.st_nlink++;
956 root->st.st_dev = VFS_SUBCLASS (me)->rdev++;
957
958 archive->root = root;
959
960 return TRUE;
961 }
962
963
964
965
966
967
968 static int
969 tar_open_archive (struct vfs_s_super *archive, const vfs_path_t *vpath,
970 const vfs_path_element_t *vpath_element)
971 {
972 tar_super_t *arch = TAR_SUPER (archive);
973
974 read_header status = HEADER_STILL_UNREAD;
975
976
977 if (!tar_open_archive_int (vpath_element->class, vpath, archive))
978 return -1;
979
980 tar_find_next_block (arch);
981
982 while (TRUE)
983 {
984 read_header prev_status;
985
986 prev_status = status;
987 tar_stat_destroy (¤t_stat_info);
988 status = tar_read_header (vpath_element->class, archive);
989
990 switch (status)
991 {
992 case HEADER_STILL_UNREAD:
993 message (D_ERROR, MSG_ERROR, _("%s\ndoesn't look like a tar archive"),
994 vfs_path_as_str (vpath));
995 return -1;
996
997 case HEADER_SUCCESS:
998 continue;
999
1000
1001 case HEADER_ZERO_BLOCK:
1002 tar_set_next_block_after (current_header);
1003 (void) tar_read_header (vpath_element->class, archive);
1004 status = prev_status;
1005 continue;
1006
1007 case HEADER_END_OF_FILE:
1008 break;
1009
1010
1011
1012 case HEADER_FAILURE:
1013 tar_set_next_block_after (current_header);
1014
1015 switch (prev_status)
1016 {
1017 case HEADER_STILL_UNREAD:
1018 message (D_ERROR, MSG_ERROR, _("%s\ndoesn't look like a tar archive"),
1019 vfs_path_as_str (vpath));
1020 return -1;
1021
1022 case HEADER_ZERO_BLOCK:
1023 case HEADER_SUCCESS:
1024
1025 break;
1026
1027 case HEADER_END_OF_FILE:
1028 case HEADER_FAILURE:
1029
1030
1031 return -1;
1032
1033 default:
1034 break;
1035 }
1036 continue;
1037
1038 default:
1039 break;
1040 }
1041 break;
1042 }
1043
1044 return 0;
1045 }
1046
1047
1048
1049 static void *
1050 tar_super_check (const vfs_path_t *vpath)
1051 {
1052 static struct stat stat_buf;
1053 int stat_result;
1054
1055 stat_result = mc_stat (vpath, &stat_buf);
1056
1057 return (stat_result != 0) ? NULL : &stat_buf;
1058 }
1059
1060
1061
1062 static int
1063 tar_super_same (const vfs_path_element_t *vpath_element, struct vfs_s_super *parc,
1064 const vfs_path_t *vpath, void *cookie)
1065 {
1066 struct stat *archive_stat = cookie;
1067
1068 (void) vpath_element;
1069
1070 if (strcmp (parc->name, vfs_path_as_str (vpath)) != 0)
1071 return 0;
1072
1073
1074 if (parc != NULL && TAR_SUPER (parc)->st.st_mtime < archive_stat->st_mtime)
1075 {
1076
1077 vfs_tarfs_ops->free ((vfsid) parc);
1078 vfs_rmstamp (vfs_tarfs_ops, (vfsid) parc);
1079 return 2;
1080 }
1081
1082 vfs_stamp (vfs_tarfs_ops, (vfsid) parc);
1083 return 1;
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 static ssize_t
1104 tar_get_sparse_chunk_idx (const GArray *sparse_map, off_t offset)
1105 {
1106 size_t k;
1107
1108 for (k = 1; k <= sparse_map->len; k++)
1109 {
1110 const struct sp_array *chunk;
1111
1112 chunk = &g_array_index (sparse_map, struct sp_array, k - 1);
1113
1114
1115 if (offset >= chunk->offset && offset < chunk->offset + chunk->numbytes)
1116 return k;
1117
1118
1119 if (offset < chunk->offset)
1120 return -k;
1121 }
1122
1123
1124 return 0;
1125 }
1126
1127
1128
1129 static ssize_t
1130 tar_read_sparse (vfs_file_handler_t *fh, char *buffer, size_t count)
1131 {
1132 int fd = TAR_SUPER (fh->ino->super)->fd;
1133 const GArray *sm = (const GArray *) fh->ino->user_data;
1134 ssize_t chunk_idx;
1135 const struct sp_array *chunk;
1136 off_t remain;
1137 ssize_t res;
1138
1139 chunk_idx = tar_get_sparse_chunk_idx (sm, fh->pos);
1140 if (chunk_idx > 0)
1141 {
1142
1143 chunk = &g_array_index (sm, struct sp_array, chunk_idx - 1);
1144 remain = MIN ((off_t) count, chunk->offset + chunk->numbytes - fh->pos);
1145 res = mc_read (fd, buffer, (size_t) remain);
1146 }
1147 else
1148 {
1149 if (chunk_idx == 0)
1150 {
1151
1152 remain = MIN ((off_t) count, fh->ino->st.st_size - fh->pos);
1153
1154 remain = MAX (remain, 0);
1155 }
1156 else
1157 {
1158
1159 chunk = &g_array_index (sm, struct sp_array, -chunk_idx - 1);
1160 remain = MIN ((off_t) count, chunk->offset - fh->pos);
1161 }
1162
1163 memset (buffer, 0, (size_t) remain);
1164 res = (ssize_t) remain;
1165 }
1166
1167 return res;
1168 }
1169
1170
1171
1172 static off_t
1173 tar_lseek_sparse (vfs_file_handler_t *fh, off_t offset)
1174 {
1175 off_t saved_offset = offset;
1176 int fd = TAR_SUPER (fh->ino->super)->fd;
1177 const GArray *sm = (const GArray *) fh->ino->user_data;
1178 ssize_t chunk_idx;
1179 const struct sp_array *chunk;
1180 off_t res;
1181
1182 chunk_idx = tar_get_sparse_chunk_idx (sm, offset);
1183 if (chunk_idx > 0)
1184 {
1185
1186
1187 chunk = &g_array_index (sm, struct sp_array, chunk_idx - 1);
1188
1189 offset -= chunk->offset;
1190
1191 offset += chunk->arch_offset;
1192 }
1193 else
1194 {
1195
1196
1197
1198 switch (chunk_idx)
1199 {
1200 case -1:
1201 offset = fh->ino->data_offset;
1202 break;
1203
1204 case 0:
1205 chunk = &g_array_index (sm, struct sp_array, sm->len - 1);
1206
1207 offset = chunk->arch_offset + chunk->numbytes;
1208 break;
1209
1210 default:
1211 chunk = &g_array_index (sm, struct sp_array, -chunk_idx - 1);
1212 offset = chunk->arch_offset + chunk->numbytes;
1213 break;
1214 }
1215 }
1216
1217 res = mc_lseek (fd, offset, SEEK_SET);
1218
1219 if (res == offset)
1220 res = saved_offset;
1221
1222 return res;
1223 }
1224
1225
1226
1227 static ssize_t
1228 tar_read (void *fh, char *buffer, size_t count)
1229 {
1230 struct vfs_class *me = VFS_FILE_HANDLER_SUPER (fh)->me;
1231 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1232 int fd = TAR_SUPER (VFS_FILE_HANDLER_SUPER (fh))->fd;
1233 off_t begin = file->pos;
1234 ssize_t res;
1235
1236 if (file->ino->user_data != NULL)
1237 {
1238 if (tar_lseek_sparse (file, begin) != begin)
1239 ERRNOR (EIO, -1);
1240
1241 res = tar_read_sparse (file, buffer, count);
1242 }
1243 else
1244 {
1245 begin += file->ino->data_offset;
1246
1247 if (mc_lseek (fd, begin, SEEK_SET) != begin)
1248 ERRNOR (EIO, -1);
1249
1250 count = (size_t) MIN ((off_t) count, file->ino->st.st_size - file->pos);
1251 res = mc_read (fd, buffer, count);
1252 }
1253
1254 if (res == -1)
1255 ERRNOR (errno, -1);
1256
1257 file->pos += res;
1258 return res;
1259 }
1260
1261
1262
1263 static int
1264 tar_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
1265 {
1266 (void) fh;
1267 (void) mode;
1268
1269 if ((flags & O_ACCMODE) != O_RDONLY)
1270 ERRNOR (EROFS, -1);
1271 return 0;
1272 }
1273
1274
1275
1276
1277
1278 void
1279 vfs_init_tarfs (void)
1280 {
1281
1282 vfs_init_subclass (&tarfs_subclass, "tarfs", VFSF_READONLY, "utar");
1283 vfs_tarfs_ops->read = tar_read;
1284 vfs_tarfs_ops->setctl = NULL;
1285 tarfs_subclass.archive_check = tar_super_check;
1286 tarfs_subclass.archive_same = tar_super_same;
1287 tarfs_subclass.new_archive = tar_new_archive;
1288 tarfs_subclass.open_archive = tar_open_archive;
1289 tarfs_subclass.free_archive = tar_free_archive;
1290 tarfs_subclass.free_inode = tar_free_inode;
1291 tarfs_subclass.fh_open = tar_fh_open;
1292 vfs_register_class (vfs_tarfs_ops);
1293 }
1294
1295