2 ** Copyright 1998-2003 University of Illinois Board of Trustees
3 ** Copyright 1998-2003 Mark D. Roth
4 ** All rights reserved.
6 ** block.c - libtar code to handle tar archive header blocks
8 ** Mark D. Roth <roth@uiuc.edu>
9 ** Campus Information Technologies and Educational Services
10 ** University of Illinois at Urbana-Champaign
23 #define BIT_ISSET(bitmask, bit) ((bitmask) & (bit))
26 /* read a header block */
28 th_read_internal(TAR
*t
)
31 int num_zero_blocks
= 0;
34 printf("==> th_read_internal(TAR=\"%s\")\n", t
->pathname
);
37 while ((i
= tar_block_read(t
, &(t
->th_buf
))) == T_BLOCKSIZE
)
39 /* two all-zero blocks mark EOF */
40 if (t
->th_buf
.name
[0] == '\0')
43 if (!BIT_ISSET(t
->options
, TAR_IGNORE_EOT
)
44 && num_zero_blocks
>= 2)
50 /* verify magic and version */
51 if (BIT_ISSET(t
->options
, TAR_CHECK_MAGIC
)
52 && strncmp(t
->th_buf
.magic
, TMAGIC
, TMAGLEN
- 1) != 0)
55 puts("!!! unknown magic value in tar header");
60 if (BIT_ISSET(t
->options
, TAR_CHECK_VERSION
)
61 && strncmp(t
->th_buf
.version
, TVERSION
, TVERSLEN
) != 0)
64 puts("!!! unknown version value in tar header");
70 if (!BIT_ISSET(t
->options
, TAR_IGNORE_CRC
)
74 puts("!!! tar header checksum error");
83 printf("<== th_read_internal(): returning %d\n", i
);
89 /* wrapper function for th_read_internal() to handle GNU extensions */
98 printf("==> th_read(t=0x%lx)\n", t
);
101 if (t
->th_buf
.gnu_longname
!= NULL
)
102 free(t
->th_buf
.gnu_longname
);
103 if (t
->th_buf
.gnu_longlink
!= NULL
)
104 free(t
->th_buf
.gnu_longlink
);
105 memset(&(t
->th_buf
), 0, sizeof(struct tar_header
));
107 i
= th_read_internal(t
);
110 else if (i
!= T_BLOCKSIZE
)
117 /* check for GNU long link extention */
118 if (TH_ISLONGLINK(t
))
121 blocks
= (sz
/ T_BLOCKSIZE
) + (sz
% T_BLOCKSIZE
? 1 : 0);
122 if (blocks
> ((size_t)-1 / T_BLOCKSIZE
))
128 printf(" th_read(): GNU long linkname detected "
129 "(%ld bytes, %d blocks)\n", sz
, blocks
);
131 t
->th_buf
.gnu_longlink
= (char *)malloc(blocks
* T_BLOCKSIZE
);
132 if (t
->th_buf
.gnu_longlink
== NULL
)
135 for (j
= 0, ptr
= t
->th_buf
.gnu_longlink
; j
< blocks
;
136 j
++, ptr
+= T_BLOCKSIZE
)
139 printf(" th_read(): reading long linkname "
140 "(%d blocks left, ptr == %ld)\n", blocks
-j
, ptr
);
142 i
= tar_block_read(t
, ptr
);
143 if (i
!= T_BLOCKSIZE
)
150 printf(" th_read(): read block == \"%s\"\n", ptr
);
154 printf(" th_read(): t->th_buf.gnu_longlink == \"%s\"\n",
155 t
->th_buf
.gnu_longlink
);
158 i
= th_read_internal(t
);
159 if (i
!= T_BLOCKSIZE
)
167 /* check for GNU long name extention */
168 if (TH_ISLONGNAME(t
))
171 blocks
= (sz
/ T_BLOCKSIZE
) + (sz
% T_BLOCKSIZE
? 1 : 0);
172 if (blocks
> ((size_t)-1 / T_BLOCKSIZE
))
178 printf(" th_read(): GNU long filename detected "
179 "(%ld bytes, %d blocks)\n", sz
, blocks
);
181 t
->th_buf
.gnu_longname
= (char *)malloc(blocks
* T_BLOCKSIZE
);
182 if (t
->th_buf
.gnu_longname
== NULL
)
185 for (j
= 0, ptr
= t
->th_buf
.gnu_longname
; j
< blocks
;
186 j
++, ptr
+= T_BLOCKSIZE
)
189 printf(" th_read(): reading long filename "
190 "(%d blocks left, ptr == %ld)\n", blocks
-j
, ptr
);
192 i
= tar_block_read(t
, ptr
);
193 if (i
!= T_BLOCKSIZE
)
200 printf(" th_read(): read block == \"%s\"\n", ptr
);
204 printf(" th_read(): t->th_buf.gnu_longname == \"%s\"\n",
205 t
->th_buf
.gnu_longname
);
208 i
= th_read_internal(t
);
209 if (i
!= T_BLOCKSIZE
)
219 ** work-around for old archive files with broken typeflag fields
220 ** NOTE: I fixed this in the TH_IS*() macros instead
224 ** (directories are signified with a trailing '/')
226 if (t
->th_buf
.typeflag
== AREGTYPE
227 && t
->th_buf
.name
[strlen(t
->th_buf
.name
) - 1] == '/')
228 t
->th_buf
.typeflag
= DIRTYPE
;
231 ** fallback to using mode bits
233 if (t
->th_buf
.typeflag
== AREGTYPE
)
235 mode
= (mode_t
)oct_to_int(t
->th_buf
.mode
);
238 t
->th_buf
.typeflag
= REGTYPE
;
239 else if (S_ISDIR(mode
))
240 t
->th_buf
.typeflag
= DIRTYPE
;
241 else if (S_ISFIFO(mode
))
242 t
->th_buf
.typeflag
= FIFOTYPE
;
243 else if (S_ISCHR(mode
))
244 t
->th_buf
.typeflag
= CHRTYPE
;
245 else if (S_ISBLK(mode
))
246 t
->th_buf
.typeflag
= BLKTYPE
;
247 else if (S_ISLNK(mode
))
248 t
->th_buf
.typeflag
= SYMTYPE
;
256 /* write a header block */
264 char buf
[T_BLOCKSIZE
];
267 printf("==> th_write(TAR=\"%s\")\n", t
->pathname
);
271 if ((t
->options
& TAR_GNU
) && t
->th_buf
.gnu_longlink
!= NULL
)
274 printf("th_write(): using gnu_longlink (\"%s\")\n",
275 t
->th_buf
.gnu_longlink
);
277 /* save old size and type */
278 type2
= t
->th_buf
.typeflag
;
279 sz2
= th_get_size(t
);
281 /* write out initial header block with fake size and type */
282 t
->th_buf
.typeflag
= GNU_LONGLINK_TYPE
;
283 sz
= strlen(t
->th_buf
.gnu_longlink
);
286 i
= tar_block_write(t
, &(t
->th_buf
));
287 if (i
!= T_BLOCKSIZE
)
294 /* write out extra blocks containing long name */
295 for (j
= (sz
/ T_BLOCKSIZE
) + (sz
% T_BLOCKSIZE
? 1 : 0),
296 ptr
= t
->th_buf
.gnu_longlink
; j
> 1;
297 j
--, ptr
+= T_BLOCKSIZE
)
299 i
= tar_block_write(t
, ptr
);
300 if (i
!= T_BLOCKSIZE
)
307 memset(buf
, 0, T_BLOCKSIZE
);
308 strncpy(buf
, ptr
, T_BLOCKSIZE
);
309 i
= tar_block_write(t
, &buf
);
310 if (i
!= T_BLOCKSIZE
)
317 /* reset type and size to original values */
318 t
->th_buf
.typeflag
= type2
;
322 if ((t
->options
& TAR_GNU
) && t
->th_buf
.gnu_longname
!= NULL
)
325 printf("th_write(): using gnu_longname (\"%s\")\n",
326 t
->th_buf
.gnu_longname
);
328 /* save old size and type */
329 type2
= t
->th_buf
.typeflag
;
330 sz2
= th_get_size(t
);
332 /* write out initial header block with fake size and type */
333 t
->th_buf
.typeflag
= GNU_LONGNAME_TYPE
;
334 sz
= strlen(t
->th_buf
.gnu_longname
);
337 i
= tar_block_write(t
, &(t
->th_buf
));
338 if (i
!= T_BLOCKSIZE
)
345 /* write out extra blocks containing long name */
346 for (j
= (sz
/ T_BLOCKSIZE
) + (sz
% T_BLOCKSIZE
? 1 : 0),
347 ptr
= t
->th_buf
.gnu_longname
; j
> 1;
348 j
--, ptr
+= T_BLOCKSIZE
)
350 i
= tar_block_write(t
, ptr
);
351 if (i
!= T_BLOCKSIZE
)
358 memset(buf
, 0, T_BLOCKSIZE
);
359 strncpy(buf
, ptr
, T_BLOCKSIZE
);
360 i
= tar_block_write(t
, &buf
);
361 if (i
!= T_BLOCKSIZE
)
368 /* reset type and size to original values */
369 t
->th_buf
.typeflag
= type2
;
376 /* print tar header */
380 i
= tar_block_write(t
, &(t
->th_buf
));
381 if (i
!= T_BLOCKSIZE
)
389 puts("th_write(): returning 0");