2 * Copyright (c) 2000, 2001, Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* Built-in tar functionality. See tar.h for usage. */
18 static char *cvsid
= "\n%%% $Id$\n";
23 #include <sys/types.h>
24 #include <sys/fcntl.h>
30 #include "filemanip.h"
36 #define FACTOR (0x19db1ded53ea710LL)
37 #define NSPERSEC 10000000LL
38 #define SYMLINK_COOKIE "!<symlink>"
41 char name
[100]; /* 0 */
42 char mode
[8]; /* 100 */
43 char uid
[8]; /* 108 */
44 char gid
[8]; /* 116 */
45 char size
[12]; /* 124 */
46 char mtime
[12]; /* 136 */
47 char chksum
[8]; /* 148 */
48 char typeflag
; /* 156 */
49 char linkname
[100]; /* 157 */
50 char magic
[6]; /* 257 */
51 char version
[2]; /* 263 */
52 char uname
[32]; /* 265 */
53 char gname
[32]; /* 297 */
54 char devmajor
[8]; /* 329 */
55 char devminor
[8]; /* 337 */
56 char prefix
[155]; /* 345 */
57 char junk
[12]; /* 500 */
60 typedef struct tar_map_result_type_s
{
61 struct tar_map_result_type_s
*next
;
64 } tar_map_result_type
;
66 static tar_map_result_type
*tar_map_result
= 0;
70 static char file_name
[_MAX_PATH
+512];
71 static char have_longname
= 0;
72 static int file_length
;
74 static tar_header_type tar_header
;
77 static int _tar_file_size
= 0;
79 FILE * _tar_vfile
= 0;
80 #define vp if (_tar_verbose) fprintf
81 #define vp2 if (_tar_verbose>1) fprintf
93 virtual int read (void *buf
, int len
) {};
94 virtual int close () {};
95 virtual off_t
tell () {};
96 operator int () {return (int) g
;}
102 gz (const char *pathname
)
104 g
= gzopen (pathname
, "rb");
106 int read (void *buf
, int len
)
108 return gzread (g
, buf
, len
);
114 off_t
tell () {return gzctell (g
);}
118 class bz
: public gzbz
121 bz (const char *pathname
)
123 fd
= open (pathname
, O_RDONLY
| O_BINARY
);
125 b
= BZ2_bzdopen (fd
, "rb");
129 int read (void *buf
, int len
)
131 return BZ2_bzread (b
, buf
, len
);
138 off_t
tell () {return ::tell (fd
);}
147 char *r
= (char *) malloc (strlen (c
) + 1);
155 tar_open (const char *pathname
)
160 vp2 (_tar_vfile
, "tar: open `%s'\n", pathname
);
162 if ((size
= get_file_size (pathname
)) == 0)
164 _tar_file_size
= size
;
166 if (strstr (pathname
, ".bz2"))
167 z
= new bz (pathname
);
169 z
= new gz (pathname
);
170 if (sizeof (tar_header
) != 512)
172 /* drastic, but important */
173 fprintf (stderr
, "compilation error: tar header struct not 512"
174 " bytes (it's %d)\n", sizeof (tar_header
));
190 while (file_length
> 0)
202 r
= z
->read (&tar_header
, 512);
204 /* See if we're at end of file */
208 /* See if the header is all zeros (i.e. last block) */
210 for (r
= 512/sizeof (int); r
; r
--)
211 n
|= ((int *)&tar_header
)[r
-1];
215 if (!have_longname
&& tar_header
.typeflag
!= 'L')
217 memcpy (file_name
, tar_header
.name
, 100);
221 sscanf (tar_header
.size
, "%o", &file_length
);
223 vp2 (_tar_vfile
, "%c %9d %s\n", tar_header
.typeflag
, file_length
, file_name
);
225 switch (tar_header
.typeflag
)
227 case 'L': /* GNU tar long name extension */
228 if (file_length
> _MAX_PATH
)
231 fprintf (stderr
, "error: long file name exceeds %d characters\n",
234 z
->read (&tar_header
, 512);
235 sscanf (tar_header
.size
, "%o", &file_length
);
237 return tar_next_file ();
240 while (file_length
> 0)
242 int need
= file_length
> 512 ? 512 : file_length
;
243 if (z
->read (buf
, 512) < 512)
245 memcpy (c
, buf
, need
);
251 return tar_next_file ();
254 case '4': /* block */
256 fprintf (stderr
, "warning: not extracting special file %s\n",
259 return tar_next_file ();
261 case '0': /* regular file */
262 case 0: /* regular file also */
263 case '2': /* symbolic link */
264 case '5': /* directory */
265 case '7': /* contiguous file */
268 case '1': /* hard link, we just copy */
272 fprintf (stderr
, "error: unknown (or unsupported) file type `%c'\n",
273 tar_header
.typeflag
);
276 return tar_next_file ();
281 fix_time_stamp (char *path
)
288 sscanf (tar_header
.mtime
, "%o", &mtime
);
289 ftimev
= mtime
* NSPERSEC
+ FACTOR
;
290 ftime
.dwHighDateTime
= ftimev
>> 32;
291 ftime
.dwLowDateTime
= ftimev
;
292 h
= CreateFileA (path
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
294 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_BACKUP_SEMANTICS
, 0);
297 SetFileTime (h
, 0, 0, &ftime
);
303 common_fopen (char *path
)
306 out
= fopen (path
, "wb");
309 /* maybe we need to create a directory */
310 if (mkdir_p (0, path
))
315 out
= fopen (path
, "wb");
319 fprintf (stderr
, "unable to write to file %s\n", path
);
320 perror ("The error was");
328 prepare_for_file (char *path
)
333 w
= GetFileAttributes (path
);
334 if (w
!= 0xffffffff && w
& FILE_ATTRIBUTE_DIRECTORY
)
336 char *tmp
= (char *) malloc (strlen (path
) + 10);
340 sprintf (tmp
, "%s.old-%d", path
, i
);
341 } while (GetFileAttributes (tmp
) != 0xffffffff);
342 fprintf (stderr
, "warning: moving directory \"%s\" out of the way.\n", path
);
343 MoveFile (path
, tmp
);
351 tar_read_file (char *path
)
357 tar_map_result_type
*tmr
;
359 switch (tar_header
.typeflag
)
361 case '0': /* regular files */
364 vp (_tar_vfile
, "F %s\n", path
);
365 prepare_for_file (path
);
366 out
= common_fopen (path
);
370 while (file_length
> 0)
373 int want
= file_length
> 512 ? 512 : file_length
;
374 got
= z
->read (buf
, 512);
377 fprintf (stderr
, "tar: unexpected end of file reading %s\n", path
);
382 put
= fwrite (buf
, 1, want
, out
);
385 fprintf (stderr
, "tar: out of disk space writing %s\n", path
);
395 fix_time_stamp (path
);
397 /* we need this to do hard links below */
398 tmr
= (tar_map_result_type
*) malloc (sizeof (tar_map_result_type
));
399 tmr
->next
= tar_map_result
;
400 tmr
->stored_name
= xstrdup (file_name
);
401 tmr
->mapped_name
= xstrdup (path
);
402 tar_map_result
= tmr
;
406 case '1': /* hard links; we just copy */
407 for (tmr
= tar_map_result
; tmr
; tmr
=tmr
->next
)
408 if (strcmp (tmr
->stored_name
, tar_header
.linkname
) == 0)
412 fprintf (stderr
, "tar: can't find %s to link %s to\n",
413 tar_header
.linkname
, path
);
416 vp (_tar_vfile
, "H %s <- %s\n", path
, tmr
->mapped_name
);
417 prepare_for_file (path
);
418 copy
= fopen (tmr
->mapped_name
, "rb");
421 fprintf (stderr
, "tar: unable to read %s\n", tmr
->mapped_name
);
424 out
= common_fopen (path
);
428 while ((got
= fread (buf
, 1, 512, copy
)) > 0)
430 int put
= fwrite (buf
, 1, got
, out
);
433 fprintf (stderr
, "tar: out of disk space writing %s\n", path
);
443 fix_time_stamp (path
);
446 case '5': /* directories */
447 vp (_tar_vfile
, "D %s\n", path
);
448 while (path
[0] && path
[strlen (path
)-1] == '/')
449 path
[strlen (path
) - 1] = 0;
450 return mkdir_p (1, path
);
453 case '2': /* symbolic links */
454 vp (_tar_vfile
, "L %s -> %s\n", path
, tar_header
.linkname
);
455 prepare_for_file (path
);
456 h
= CreateFileA (path
, GENERIC_WRITE
, 0, 0, CREATE_NEW
,
457 FILE_ATTRIBUTE_NORMAL
, 0);
458 if (h
== INVALID_HANDLE_VALUE
)
460 fprintf (stderr
, "error: unable to create symlink \"%s\" -> \"%s\"\n",
461 path
, tar_header
.linkname
);
464 strcpy (buf
, SYMLINK_COOKIE
);
465 strcat (buf
, tar_header
.linkname
);
466 if (WriteFile (h
, buf
, strlen (buf
) + 1, &w
, NULL
))
469 SetFileAttributesA (path
, FILE_ATTRIBUTE_SYSTEM
);
473 fprintf (stderr
, "error: unable to write symlink \"%s\"\n", path
);
483 while (tar_map_result
)
485 tar_map_result_type
*t
= tar_map_result
->next
;
486 free (tar_map_result
->stored_name
);
487 free (tar_map_result
->mapped_name
);
488 free (tar_map_result
);
496 return err
; /* includes errors for skipped files, etc */
506 static map_type
*map
;
510 tar_auto (char *pathname
, char **maplist
)
516 char newname
[_MAX_PATH
+512];
517 static char twiddles
[] = "|\b/\b-\b\\\b";
520 for (nmaps
=0; maplist
[nmaps
*2]; nmaps
++) ;
521 map
= (map_type
*) malloc ((nmaps
+1) * sizeof (map_type
));
522 for (nmaps
=0; maplist
[nmaps
*2]; nmaps
++)
524 map
[nmaps
].from
= maplist
[nmaps
*2];
525 map
[nmaps
].from_len
= strlen (maplist
[nmaps
*2]);
526 map
[nmaps
].to
= maplist
[nmaps
*2+1];
527 map
[nmaps
].to_len
= strlen (maplist
[nmaps
*2+1]);
529 /* bubble sort - expect the maps to be short */
530 for (i
=0; i
<nmaps
-1; i
++)
531 for (j
=i
+1; j
<nmaps
; j
++)
532 if (map
[i
].from_len
< map
[j
].from_len
)
539 if (tar_open (pathname
))
541 while (c
= tar_next_file ())
544 for (i
=0; i
<nmaps
; i
++)
545 if (l
>= map
[i
].from_len
546 && strncmp (c
, map
[i
].from
, map
[i
].from_len
) == 0)
548 strcpy (newname
, map
[i
].to
);
549 strcpy (newname
+map
[i
].to_len
, c
+ map
[i
].from_len
);
555 fwrite (twiddles
+t
, 1, 2, stderr
);
557 if (tar_read_file (c
))
563 fwrite (" \b", 1, 2, stderr
);
565 vp2 (_tar_vfile
, "tar_auto returns %d\n", err
);