1
2 #ifndef MC__VFS_TAR_INTERNAL_H
3 #define MC__VFS_TAR_INTERNAL_H
4
5 #include <inttypes.h> // (u)intmax_t
6 #include <limits.h> // CHAR_BIT, INT_MAX, etc
7 #include <sys/stat.h>
8 #include <sys/types.h>
9
10 #ifdef HAVE_STDCKDINT_H
11 #include <stdckdint.h>
12 #else
13 #include "lib/stdckdint.h"
14 #endif
15 #include "lib/intprops.h"
16 #include "lib/idx.h"
17 #include "lib/vfs/xdirentry.h" // vfs_s_super
18
19 /*** typedefs(not structures) and defined constants **********************************************/
20
21 /* tar files are made in basic blocks of this size. */
22 #define BLOCKSIZE 512
23
24 #define DEFAULT_BLOCKING 20
25
26 /* Sparse files are not supported in POSIX ustar format. For sparse files
27 with a POSIX header, a GNU extra header is provided which holds overall
28 sparse information and a few sparse descriptors. When an old GNU header
29 replaces both the POSIX header and the GNU extra header, it holds some
30 sparse descriptors too. Whether POSIX or not, if more sparse descriptors
31 are still needed, they are put into as many successive sparse headers as
32 necessary. The following constants tell how many sparse descriptors fit
33 in each kind of header able to hold them. */
34
35 #define SPARSES_IN_EXTRA_HEADER 16
36 #define SPARSES_IN_OLDGNU_HEADER 4
37 #define SPARSES_IN_SPARSE_HEADER 21
38
39 #define SPARSES_IN_STAR_HEADER 4
40 #define SPARSES_IN_STAR_EXT_HEADER 21
41
42 /* *BEWARE* *BEWARE* *BEWARE* that the following information is still
43 boiling, and may change. Even if the OLDGNU format description should be
44 accurate, the so-called GNU format is not yet fully decided. It is
45 surely meant to use only extensions allowed by POSIX, but the sketch
46 below repeats some ugliness from the OLDGNU format, which should rather
47 go away. Sparse files should be saved in such a way that they do *not*
48 require two passes at archive creation time. Huge files get some POSIX
49 fields to overflow, alternate solutions have to be sought for this. */
50
51 /* This is a dir entry that contains the names of files that were in the
52 dir at the time the dump was made. */
53 #define GNUTYPE_DUMPDIR 'D'
54
55 /* Identifies the *next* file on the tape as having a long linkname. */
56 #define GNUTYPE_LONGLINK 'K'
57
58 /* Identifies the *next* file on the tape as having a long name. */
59 #define GNUTYPE_LONGNAME 'L'
60
61 /* Solaris extended header */
62 #define SOLARIS_XHDTYPE 'X'
63
64 #define GNUTYPE_SPARSE 'S'
65
66 #define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
67
68 /*** enums ***************************************************************************************/
69
70 /*** structures declarations (and typedefs of structures)*****************************************/
71
72 /* POSIX header */
73 struct posix_header
74 { // byte offset
75 char name[100]; // 0
76 char mode[8]; // 100
77 char uid[8]; // 108
78 char gid[8]; // 116
79 char size[12]; // 124
80 char mtime[12]; // 136
81 char chksum[8]; // 148
82 char typeflag; // 156
83 char linkname[100]; // 157
84 char magic[6]; // 257
85 char version[2]; // 263
86 char uname[32]; // 265
87 char gname[32]; // 297
88 char devmajor[8]; // 329
89 char devminor[8]; // 337
90 char prefix[155]; // 345
91 // 500
92 };
93
94 /* Descriptor for a single file hole */
95 struct sparse
96 { // byte offset
97 char offset[12]; // 0
98 char numbytes[12]; // 12
99 // 24
100 };
101
102 /* Extension header for sparse files, used immediately after the GNU extra
103 header, and used only if all sparse information cannot fit into that
104 extra header. There might even be many such extension headers, one after
105 the other, until all sparse information has been recorded. */
106 struct sparse_header
107 { // byte offset
108 struct sparse sp[SPARSES_IN_SPARSE_HEADER];
109 // 0
110 char isextended; // 504
111 // 505
112 };
113
114 /* The old GNU format header conflicts with POSIX format in such a way that
115 POSIX archives may fool old GNU tar's, and POSIX tar's might well be
116 fooled by old GNU tar archives. An old GNU format header uses the space
117 used by the prefix field in a POSIX header, and cumulates information
118 normally found in a GNU extra header. With an old GNU tar header, we
119 never see any POSIX header nor GNU extra header. Supplementary sparse
120 headers are allowed, however. */
121 struct oldgnu_header
122 { // byte offset
123 char unused_pad1[345]; // 0
124 char atime[12]; // 345 Incr. archive: atime of the file
125 char ctime[12]; // 357 Incr. archive: ctime of the file
126 char offset[12]; // 369 Multivolume archive: the offset of start of this volume
127 char longnames[4]; // 381 Not used
128 char unused_pad2; // 385
129 struct sparse sp[SPARSES_IN_OLDGNU_HEADER];
130 // 386
131 char isextended; // 482 Sparse file: Extension sparse header follows
132 char realsize[12]; // 483 Sparse file: Real size
133 // 495
134 };
135
136 /* J@"org Schilling star header */
137 struct star_header
138 { // byte offset
139 char name[100]; // 0
140 char mode[8]; // 100
141 char uid[8]; // 108
142 char gid[8]; // 116
143 char size[12]; // 124
144 char mtime[12]; // 136
145 char chksum[8]; // 148
146 char typeflag; // 156
147 char linkname[100]; // 157
148 char magic[6]; // 257
149 char version[2]; // 263
150 char uname[32]; // 265
151 char gname[32]; // 297
152 char devmajor[8]; // 329
153 char devminor[8]; // 337
154 char prefix[131]; // 345
155 char atime[12]; // 476
156 char ctime[12]; // 488
157 // 500
158 };
159
160 struct star_in_header
161 {
162 char fill[345]; // 0 Everything that is before t_prefix
163 char prefix[1]; // 345 t_name prefix
164 char fill2; // 346
165 char fill3[8]; // 347
166 char isextended; // 355
167 struct sparse sp[SPARSES_IN_STAR_HEADER]; // 356
168 char realsize[12]; // 452 Actual size of the file
169 char offset[12]; // 464 Offset of multivolume contents
170 char atime[12]; // 476
171 char ctime[12]; // 488
172 char mfill[8]; // 500
173 char xmagic[4]; // 508 "tar"
174 };
175
176 struct star_ext_header
177 {
178 struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
179 char isextended;
180 };
181
182 /* tar Header Block, overall structure */
183 union block
184 {
185 char buffer[BLOCKSIZE];
186 struct posix_header header;
187 struct star_header star_header;
188 struct oldgnu_header oldgnu_header;
189 struct sparse_header sparse_header;
190 struct star_in_header star_in_header;
191 struct star_ext_header star_ext_header;
192 };
193
194 /* Information about a sparse file */
195 struct sp_array
196 {
197 off_t offset; // chunk offset in file
198 off_t numbytes; // length of chunk
199 off_t arch_offset; // chunk offset in archive
200 };
201
202 enum dump_status
203 {
204 dump_status_ok,
205 dump_status_short,
206 dump_status_fail,
207 dump_status_not_implemented
208 };
209
210 enum archive_format
211 {
212 TAR_UNKNOWN = 0, // format to be decided later
213 TAR_V7, // old V7 tar format
214 TAR_OLDGNU, // GNU format as per before tar 1.12
215 TAR_USTAR, // POSIX.1-1988 (ustar) format
216 TAR_POSIX, // POSIX.1-2001 format
217 TAR_STAR, // star format defined in 1994
218 TAR_GNU // almost same as OLDGNU_FORMAT
219 };
220
221 typedef struct
222 {
223 struct vfs_s_super base; // base class
224
225 int fd;
226 struct stat st;
227 enum archive_format type; // type of the archive
228 union block *record_start; // start of record of archive
229 } tar_super_t;
230
231 struct xheader
232 {
233 size_t size;
234 char *buffer;
235 };
236
237 struct tar_stat_info
238 {
239 char *orig_file_name; // name of file read from the archive header
240 char *file_name; // name of file for the current archive entry after being normalized
241 char *link_name; // name of link for the current archive entry
242 #if 0
243 char *uname; // user name of owner
244 char *gname; // group name of owner
245 #endif
246 struct stat stat; // regular filesystem stat
247
248 /* stat() doesn't always have access, data modification, and status
249 change times in a convenient form, so store them separately. */
250 struct timespec atime;
251 struct timespec mtime;
252 struct timespec ctime;
253
254 off_t archive_file_size; // size of file as stored in the archive, equals stat.st_size for
255 // non-sparse files
256 gboolean is_sparse; // is the file sparse
257
258 // For sparse files
259 intmax_t sparse_major;
260 intmax_t sparse_minor;
261 GArray *sparse_map; // array of struct sp_array
262
263 off_t real_size; // real size of sparse file
264 gboolean real_size_set; // TRUE when GNU.sparse.realsize is set in archived file
265
266 gboolean
267 sparse_name_done; // TRUE if 'GNU.sparse.name' header was processed pax header parsing.
268 // Following 'path' header (lower priority) will be ignored.
269
270 // Extended headers
271 struct xheader xhdr;
272
273 // For dumpdirs
274 gboolean is_dumpdir; // is the member a dumpdir?
275 gboolean skipped; // the member contents is already read (for GNUTYPE_DUMPDIR)
276 char *dumpdir; // contents of the dump directory
277 };
278
279 /*** global variables defined in .c file *********************************************************/
280
281 extern const idx_t blocking_factor;
282 extern const idx_t record_size;
283
284 extern union block *record_end; // last+1 block of archive record
285 extern union block *current_block; // current block of archive
286 extern off_t record_start_block; // block ordinal at record_start
287
288 extern union block *current_header;
289
290 /* Have we hit EOF yet? */
291 extern gboolean hit_eof;
292
293 extern struct tar_stat_info current_stat_info;
294
295 /*** declarations of public functions ************************************************************/
296
297 /* tar-internal.c */
298 gboolean is_octal_digit (char c);
299 void tar_assign_string (char **string, char *value);
300 void tar_assign_string_dup (char **string, const char *value);
301 void tar_assign_string_dup_n (char **string, const char *value, size_t n);
302 intmax_t stoint (const char *arg, char **arglim, gboolean *overflow, intmax_t minval,
303 uintmax_t maxval);
304 intmax_t tar_from_header (const char *where0, size_t digs, char const *type, intmax_t minval,
305 uintmax_t maxval, gboolean octal_only);
306 off_t off_from_header (const char *p, size_t s);
307 union block *tar_find_next_block (tar_super_t *archive);
308 gboolean tar_set_next_block_after (union block *block);
309 off_t tar_current_block_ordinal (const tar_super_t *archive);
310 gboolean tar_skip_file (tar_super_t *archive, off_t size);
311
312 /* tar-sparse.c */
313 gboolean tar_sparse_member_p (tar_super_t *archive, struct tar_stat_info *st);
314 gboolean tar_sparse_fixup_header (tar_super_t *archive, struct tar_stat_info *st);
315 enum dump_status tar_sparse_skip_file (tar_super_t *archive, struct tar_stat_info *st);
316
317 /* tar-xheader.c */
318 gboolean tar_xheader_decode (struct tar_stat_info *st);
319 gboolean tar_xheader_read (tar_super_t *archive, struct xheader *xhdr, union block *header,
320 off_t size);
321 gboolean tar_xheader_decode_global (struct xheader *xhdr);
322 void tar_xheader_destroy (struct xheader *xhdr);
323
324 /*** inline functions ****************************************************************************/
325
326 /**
327 * Represent @n using a signed integer I such that (uintmax_t) I == @n.
328 With a good optimizing compiler, this is equivalent to (intmax_t) i
329 and requires zero machine instructions. */
330 #if !(UINTMAX_MAX / 2 <= INTMAX_MAX)
331 #error "tar_represent_uintmax() returns intmax_t to represent uintmax_t"
332 #endif
333 static inline intmax_t
334 tar_represent_uintmax (uintmax_t n)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
335 {
336 intmax_t nd;
337
338 if (n <= INTMAX_MAX)
339 return n;
340
341 // Avoid signed integer overflow on picky platforms.
342 nd = n - INTMAX_MIN;
343 return nd + INTMAX_MIN;
344 }
345
346 #endif