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. */
19 static const char *cvsid
=
25 #include <sys/types.h>
26 #include <sys/fcntl.h>
29 //#include "zlib/zlib.h"
30 #include "io_stream.h"
31 //#include "compress.h"
33 #include "archive_tar.h"
35 #include "LogSingleton.h"
36 #include "filemanip.h"
43 #define FACTOR (0x19db1ded53ea710LL)
44 #define NSPERSEC 10000000LL
45 #define SYMLINK_COOKIE "!<symlink>"
49 //static char file_name[_MAX_PATH+512];
50 //static char have_longname = 0;
51 //static int file_length;
57 #define vp if (_tar_verbose) fprintf
58 #define vp2 if (_tar_verbose>1) fprintf
60 archive_tar::archive_tar (io_stream
* original
)
66 vp2 (_tar_vfile
, "tar: open `%p'\n", original
);
70 state
.lasterr
= EBADF
;
73 state
.parent
= original
;
75 if (sizeof (state
.tar_header
) != 512)
77 /* drastic, but important */
78 log (LOG_TIMESTAMP
) << "compilation error: tar header struct not 512"
79 << " bytes (it's " << sizeof (state
.tar_header
)
81 LogSingleton::GetInstance().exit (1);
86 archive_tar::read (void *buffer
, size_t len
)
92 archive_tar::write (const void *buffer
, size_t len
)
98 archive_tar::peek (void *buffer
, size_t len
)
104 archive_tar::error ()
106 return state
.lasterr
;
112 return state
.file_offset
;
116 archive_tar::seek (long where
, io_stream_seek_t whence
)
118 /* seeking in the parent archive doesn't make sense. although we could
120 Also, seeking might make sense for rewing..??
126 archive_tar::skip_file ()
128 while (state
.file_length
> state
.file_offset
)
130 int len
= state
.parent
->read (buf
, 512);
131 state
.file_offset
+= 512;
135 state
.file_length
= 0;
136 state
.file_offset
= 0;
137 state
.header_read
= 0;
142 archive_tar::next_file_name ()
146 if (state
.header_read
)
147 if (strlen (state
.filename
))
148 return state
.filename
;
153 int r
= state
.parent
->read (&state
.tar_header
, 512);
155 /* See if we're at end of file */
159 /* See if the header is all zeros (i.e. last block) */
161 for (r
= 512 / sizeof (int); r
; r
--)
162 n
|= ((int *) &state
.tar_header
)[r
- 1];
166 if (!state
.have_longname
&& state
.tar_header
.typeflag
!= 'L')
168 memcpy (state
.filename
, state
.tar_header
.name
, 100);
169 state
.filename
[100] = 0;
171 else if (state
.have_longname
)
172 state
.have_longname
= 0;
174 sscanf (state
.tar_header
.size
, "%o", &state
.file_length
);
175 state
.file_offset
= 0;
177 // vp2 (_tar_vfile, "%c %9d %s\n", state.tar_header.typeflag,
178 // state.file_length, state.filename);
180 switch (state
.tar_header
.typeflag
)
182 case 'L': /* GNU tar long name extension */
183 /* we read the 'file' into the long filename, then call back into here
184 * to find out if the actual file is a real file, or a special file..
186 if (state
.file_length
> _MAX_PATH
)
189 fprintf (stderr
, "error: long file name exceeds %d characters\n",
192 state
.parent
->read (&state
.tar_header
, 512);
193 sscanf (state
.tar_header
.size
, "%o", &state
.file_length
);
194 state
.file_offset
= 0;
196 return next_file_name ();
199 /* FIXME: this should be a single read() call */
200 while (state
.file_length
> state
.file_offset
)
203 state
.file_length
- state
.file_offset
>
204 512 ? 512 : state
.file_length
- state
.file_offset
;
205 if (state
.parent
->read (buf
, 512) < 512)
207 memcpy (c
, buf
, need
);
209 state
.file_offset
+= need
;
212 state
.have_longname
= 1;
213 return next_file_name ();
216 case '4': /* block */
218 fprintf (stderr
, "warning: not extracting special file %s\n",
221 return next_file_name ();
223 case '0': /* regular file */
224 case 0: /* regular file also */
225 case '2': /* symbolic link */
226 case '5': /* directory */
227 case '7': /* contiguous file */
228 state
.header_read
= 1;
229 return state
.filename
;
231 case '1': /* hard link, we just copy */
232 state
.header_read
= 1;
233 return state
.filename
;
236 fprintf (stderr
, "error: unknown (or unsupported) file type `%c'\n",
237 state
.tar_header
.typeflag
);
240 return next_file_name ();
245 archive_tar::~archive_tar ()
254 fix_time_stamp (char *path
)
261 sscanf (tar_header
.mtime
, "%o", &mtime
);
262 ftimev
= mtime
* NSPERSEC
+ FACTOR
;
263 ftime
.dwHighDateTime
= ftimev
>> 32;
264 ftime
.dwLowDateTime
= ftimev
;
265 h
= CreateFileA (path
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
267 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_BACKUP_SEMANTICS
, 0);
270 SetFileTime (h
, 0, 0, &ftime
);
276 archive_tar::next_file_type ()
278 switch (state
.tar_header
.typeflag
)
284 return ARCHIVE_FILE_REGULAR
;
286 return ARCHIVE_FILE_HARDLINK
;
288 return ARCHIVE_FILE_DIRECTORY
;
290 return ARCHIVE_FILE_SYMLINK
;
292 return ARCHIVE_FILE_INVALID
;
297 archive_tar::linktarget ()
299 /* TODO: consider .. path traversal issues */
300 if (next_file_type () == ARCHIVE_FILE_SYMLINK
||
301 next_file_type () == ARCHIVE_FILE_HARDLINK
)
302 return state
.tar_header
.linkname
;
307 archive_tar::extract_file ()
309 if (archive_children
)
311 archive_tar_file
*rv
= new archive_tar_file (state
);
316 archive_tar::get_mtime ()
319 return state
.parent
->get_mtime ();