]> cygwin.com Git - cygwin-apps/setup.git/blame - archive_tar.cc
2002-05-04 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / archive_tar.cc
CommitLineData
b24c88b3
RC
1/*
2 * Copyright (c) 2000, 2001, Red Hat, Inc.
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16/* Built-in tar functionality. See tar.h for usage. */
17
18#if 0
19static const char *cvsid =
20 "\n%%% $Id$\n";
21#endif
22
23#include "win32.h"
24#include <stdio.h>
25#include <stdlib.h>
26#include <sys/types.h>
27#include <sys/fcntl.h>
28#include <errno.h>
29
30//#include "zlib/zlib.h"
31#include "io_stream.h"
32//#include "compress.h"
33#include "archive.h"
34#include "archive_tar.h"
35#include "mkdir.h"
36#include "log.h"
37#include "filemanip.h"
b24c88b3
RC
38
39#include "port.h"
40#if 0
41#undef _WIN32
42#include "bzlib.h"
43
44#define FACTOR (0x19db1ded53ea710LL)
45#define NSPERSEC 10000000LL
46#define SYMLINK_COOKIE "!<symlink>"
47#endif
48static int err;
49
50//static char file_name[_MAX_PATH+512];
51//static char have_longname = 0;
52//static int file_length;
53
54static char buf[512];
55
56int _tar_verbose = 0;
57FILE *_tar_vfile = 0;
58#define vp if (_tar_verbose) fprintf
59#define vp2 if (_tar_verbose>1) fprintf
60
61archive_tar::archive_tar (io_stream * original)
62{
63 archive_children = 0;
64 if (_tar_vfile == 0)
65 _tar_vfile = stderr;
66
67 vp2 (_tar_vfile, "tar: open `%p'\n", original);
68
69 if (!original)
70 {
71 state.lasterr = EBADF;
72 return;
73 }
74 state.parent = original;
75
76 if (sizeof (state.tar_header) != 512)
77 {
78 /* drastic, but important */
79 fprintf (stderr, "compilation error: tar header struct not 512"
80 " bytes (it's %d)\n", sizeof (state.tar_header));
81 exit_setup (1);
82 }
83}
84
85ssize_t
86archive_tar::read (void *buffer, size_t len)
87{
88 return -1;
89}
90
91ssize_t
ca9506cc 92archive_tar::write (const void *buffer, size_t len)
b24c88b3
RC
93{
94 return 0;
95}
96
97ssize_t
98archive_tar::peek (void *buffer, size_t len)
99{
100 return 0;
101}
102
103int
104archive_tar::error ()
105{
106 return state.lasterr;
107}
108
109long
110archive_tar::tell ()
111{
112 return state.file_offset;
113}
114
ca9506cc
RC
115int
116archive_tar::seek (long where, io_stream_seek_t whence)
117{
118 /* seeking in the parent archive doesn't make sense. although we could
119 map to files ?
120 Also, seeking might make sense for rewing..??
121 */
122 return -1;
123}
124
b24c88b3
RC
125int
126archive_tar::skip_file ()
127{
128 while (state.file_length > state.file_offset)
129 {
130 int len = state.parent->read (buf, 512);
131 state.file_offset += 512;
132 if (len != 512)
133 return 1;
134 }
135 state.file_length = 0;
136 state.file_offset = 0;
137 state.header_read = 0;
138 return 0;
139}
140
3c054baf 141String const
b24c88b3
RC
142archive_tar::next_file_name ()
143{
144 char *c;
145
146 if (state.header_read)
147 if (strlen (state.filename))
148 return state.filename;
149 else
150 /* End of tar */
3c054baf 151 return String();
b24c88b3
RC
152
153 int r = state.parent->read (&state.tar_header, 512);
154
155 /* See if we're at end of file */
156 if (r != 512)
076654e7 157 return String();
b24c88b3
RC
158
159 /* See if the header is all zeros (i.e. last block) */
160 int n = 0;
161 for (r = 512 / sizeof (int); r; r--)
162 n |= ((int *) &state.tar_header)[r - 1];
163 if (n == 0)
076654e7 164 return String();
b24c88b3
RC
165
166 if (!state.have_longname && state.tar_header.typeflag != 'L')
167 {
168 memcpy (state.filename, state.tar_header.name, 100);
169 state.filename[100] = 0;
170 }
171
172 sscanf (state.tar_header.size, "%o", &state.file_length);
173 state.file_offset = 0;
174
175// vp2 (_tar_vfile, "%c %9d %s\n", state.tar_header.typeflag,
176// state.file_length, state.filename);
177
178 switch (state.tar_header.typeflag)
179 {
180 case 'L': /* GNU tar long name extension */
181 /* we read the 'file' into the long filename, then call back into here
182 * to find out if the actual file is a real file, or a special file..
183 */
184 if (state.file_length > _MAX_PATH)
185 {
186 skip_file ();
187 fprintf (stderr, "error: long file name exceeds %d characters\n",
188 _MAX_PATH);
189 err++;
190 state.parent->read (&state.tar_header, 512);
191 sscanf (state.tar_header.size, "%o", &state.file_length);
192 state.file_offset = 0;
193 skip_file ();
194 return next_file_name ();
195 }
196 c = state.filename;
197 /* FIXME: this should be a single read() call */
198 while (state.file_length > state.file_offset)
199 {
200 int need =
201 state.file_length - state.file_offset >
202 512 ? 512 : state.file_length - state.file_offset;
203 if (state.parent->read (buf, 512) < 512)
204 return 0;
205 memcpy (c, buf, need);
206 c += need;
207 state.file_offset += need;
208 }
209 *c = 0;
210 state.have_longname = 1;
211 return next_file_name ();
212
213 case '3': /* char */
214 case '4': /* block */
215 case '6': /* fifo */
216 fprintf (stderr, "warning: not extracting special file %s\n",
217 state.filename);
218 err++;
219 return next_file_name ();
220
221 case '0': /* regular file */
222 case 0: /* regular file also */
223 case '2': /* symbolic link */
224 case '5': /* directory */
225 case '7': /* contiguous file */
226 state.header_read = 1;
227 return state.filename;
228
229 case '1': /* hard link, we just copy */
230 state.header_read = 1;
231 return state.filename;
232
233 default:
234 fprintf (stderr, "error: unknown (or unsupported) file type `%c'\n",
235 state.tar_header.typeflag);
236 err++;
237 skip_file ();
238 return next_file_name ();
239 }
076654e7 240 return String();
b24c88b3
RC
241}
242
243archive_tar::~archive_tar ()
244{
245 if (state.parent)
246 delete state.parent;
e9440f0f 247 destroyed = 1;
b24c88b3
RC
248}
249
250# if 0
251static void
252fix_time_stamp (char *path)
253{
254 int mtime;
255 long long ftimev;
256 FILETIME ftime;
257 HANDLE h;
258
259 sscanf (tar_header.mtime, "%o", &mtime);
260 ftimev = mtime * NSPERSEC + FACTOR;
261 ftime.dwHighDateTime = ftimev >> 32;
262 ftime.dwLowDateTime = ftimev;
263 h = CreateFileA (path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
264 0, OPEN_EXISTING,
265 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
266 if (h)
267 {
268 SetFileTime (h, 0, 0, &ftime);
269 CloseHandle (h);
270 }
271}
272#endif
273archive_file_t
274archive_tar::next_file_type ()
275{
276 switch (state.tar_header.typeflag)
277 {
278 /* regular files */
279 case '0':
280 case 0:
281 case '7':
282 return ARCHIVE_FILE_REGULAR;
283 case '1':
284 return ARCHIVE_FILE_HARDLINK;
285 case '5':
286 return ARCHIVE_FILE_DIRECTORY;
287 case '2':
288 return ARCHIVE_FILE_SYMLINK;
289 default:
290 return ARCHIVE_FILE_INVALID;
291 }
292}
293
3c054baf 294String const
b24c88b3
RC
295archive_tar::linktarget ()
296{
297 /* TODO: consider .. path traversal issues */
298 if (next_file_type () == ARCHIVE_FILE_SYMLINK ||
299 next_file_type () == ARCHIVE_FILE_HARDLINK)
300 return state.tar_header.linkname;
3c054baf 301 return String();
b24c88b3
RC
302}
303
304io_stream *
305archive_tar::extract_file ()
306{
307 if (archive_children)
308 return NULL;
309 archive_tar_file *rv = new archive_tar_file (state);
310 return rv;
311}
312
313int
314archive_tar::get_mtime ()
315{
316 if (state.parent)
317 return state.parent->get_mtime ();
318 return 0;
319}
This page took 0.049187 seconds and 5 git commands to generate.