Wire up de-DE and pl-PL translations
[cygwin-setup.git] / archive_tar.cc
blobec7b003dd109e9b981d932fa78b9f9c6a8d8f2b9
1 /*
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
10 * http://www.gnu.org/
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* Built-in tar functionality. See tar.h for usage. */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/fcntl.h>
22 #include <errno.h>
24 #include "io_stream.h"
25 #include "win32.h"
26 #include "archive.h"
27 #include "archive_tar.h"
28 #include "mkdir.h"
29 #include "LogFile.h"
30 #include "filemanip.h"
32 static int err;
33 static char buf[512];
35 int _tar_verbose = 0;
37 archive_tar::archive_tar (io_stream * original)
39 archive_children = 0;
41 if (_tar_verbose)
42 LogBabblePrintf("tar: open `%p'\n", original);
44 if (!original)
46 state.lasterr = EBADF;
47 return;
49 state.parent = original;
51 if (sizeof (state.tar_header) != 512)
53 /* drastic, but important */
54 Log (LOG_TIMESTAMP) << "compilation error: tar header struct not 512"
55 << " bytes (it's " << sizeof (state.tar_header)
56 << ")" << endLog;
57 Logger ().exit (1);
61 ssize_t
62 archive_tar::read (void *buffer, size_t len)
64 return -1;
67 ssize_t
68 archive_tar::write (const void *buffer, size_t len)
70 return 0;
73 ssize_t
74 archive_tar::peek (void *buffer, size_t len)
76 return 0;
79 int
80 archive_tar::error ()
82 return state.lasterr;
85 off_t
86 archive_tar::tell ()
88 return state.file_offset;
91 off_t
92 archive_tar::seek (off_t where, io_stream_seek_t whence)
94 /* Because the parent stream is compressed, we can only easily support
95 seek()-ing to rewind to the start */
96 if ((whence == IO_SEEK_SET) && (where == 0))
98 state.header_read = 0;
99 return state.parent->seek(where, whence);
102 return -1;
106 archive_tar::skip_file ()
108 while (state.file_length > state.file_offset)
110 int len = state.parent->read (buf, 512);
111 state.file_offset += 512;
112 if (len != 512)
113 return 1;
115 state.file_length = 0;
116 state.file_offset = 0;
117 state.header_read = 0;
118 return 0;
121 const std::string
122 archive_tar::next_file_name ()
124 char *c;
126 if (state.header_read)
128 if (strlen (state.filename))
129 return state.filename;
130 else
131 /* End of tar */
132 return std::string();
135 int r = state.parent->read (&state.tar_header, 512);
137 /* See if we're at end of file */
138 if (r != 512)
139 return std::string();
141 /* See if the header is all zeros (i.e. last block) */
142 int n = 0;
143 for (r = 512 / sizeof (int); r; r--)
144 n |= ((int *) &state.tar_header)[r - 1];
145 if (n == 0)
146 return std::string();
148 if (!state.have_longname)
150 memcpy (state.filename, state.tar_header.name, 100);
151 state.filename[100] = 0;
154 if (!state.have_longlink)
156 memcpy (state.linkname, state.tar_header.linkname, 100);
157 state.linkname[100] = 0;
160 /* typeflag for any 'real' file consumes the longname/longlink state from
161 previous blocks */
162 if ((state.tar_header.typeflag != 'K') &&
163 (state.tar_header.typeflag != 'L'))
165 state.have_longname = 0;
166 state.have_longlink = 0;
169 state.file_length = strtoll (state.tar_header.size, NULL, 8);
170 state.file_offset = 0;
172 if (_tar_verbose)
173 LogBabblePrintf ("%c %9d %s\n", state.tar_header.typeflag,
174 state.file_length, state.filename);
176 switch (state.tar_header.typeflag)
178 case 'K': /* GNU tar long link extension */
179 case 'L': /* GNU tar long name extension */
180 if (strcmp(state.tar_header.name, "././@LongLink") != 0)
181 LogBabblePrintf("tar: unexpected filename %s in file type %c header\n", state.tar_header.name, state.tar_header.typeflag);
183 /* we read the 'file' into the long filename/linkname, then recursively
184 * call ourselves to handle the following block.
186 if (state.file_length > CYG_PATH_MAX)
188 skip_file ();
189 LogPlainPrintf( "error: long file name exceeds %d characters\n",
190 CYG_PATH_MAX);
191 err++;
192 state.parent->read (&state.tar_header, 512);
193 state.file_length = strtoll (state.tar_header.size, NULL, 8);
194 state.file_offset = 0;
195 skip_file ();
196 return next_file_name ();
199 if (state.tar_header.typeflag == 'L')
201 c = state.filename;
202 state.have_longname = 1;
204 else
206 c = state.linkname;
207 state.have_longlink = 1;
210 /* FIXME: this should be a single read() call */
211 while (state.file_length > state.file_offset)
213 int need =
214 state.file_length - state.file_offset >
215 512 ? 512 : state.file_length - state.file_offset;
216 if (state.parent->read (buf, 512) < 512)
218 LogPlainPrintf( "error: error reading long name\n");
219 return "";
221 memcpy (c, buf, need);
222 c += need;
223 state.file_offset += need;
225 *c = 0;
227 return next_file_name ();
229 case '3': /* char */
230 case '4': /* block */
231 case '6': /* fifo */
232 LogPlainPrintf ("warning: not extracting special file %s\n",
233 state.filename);
234 err++;
235 return next_file_name ();
237 case '0': /* regular file */
238 case 0: /* regular file also */
239 case '2': /* symbolic link */
240 case '5': /* directory */
241 case '7': /* contiguous file */
242 state.header_read = 1;
243 return state.filename;
245 case '1': /* hard link, we just copy */
246 state.header_read = 1;
247 return state.filename;
249 default:
250 LogPlainPrintf ("error: unknown (or unsupported) file type `%c'\n",
251 state.tar_header.typeflag);
252 err++;
253 /* fall through */
254 case 'g': /* POSIX.1-2001 global extended header */
255 case 'x': /* POSIX.1-2001 extended header */
256 skip_file ();
257 return next_file_name ();
259 return std::string();
262 archive_tar::~archive_tar ()
264 if (state.parent)
265 delete state.parent;
268 # if 0
269 static void
270 fix_time_stamp (char *path)
272 int mtime;
273 long long ftimev;
274 FILETIME ftime;
275 HANDLE h;
277 sscanf (tar_header.mtime, "%o", &mtime);
278 ftimev = mtime * NSPERSEC + FACTOR;
279 ftime.dwHighDateTime = ftimev >> 32;
280 ftime.dwLowDateTime = ftimev;
281 h = CreateFileA (path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
282 0, OPEN_EXISTING,
283 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
284 if (h)
286 SetFileTime (h, 0, 0, &ftime);
287 CloseHandle (h);
290 #endif
291 archive_file_t
292 archive_tar::next_file_type ()
294 switch (state.tar_header.typeflag)
296 /* regular files */
297 case '0':
298 case 0:
299 case '7':
300 return ARCHIVE_FILE_REGULAR;
301 case '1':
302 return ARCHIVE_FILE_HARDLINK;
303 case '5':
304 return ARCHIVE_FILE_DIRECTORY;
305 case '2':
306 return ARCHIVE_FILE_SYMLINK;
307 default:
308 return ARCHIVE_FILE_INVALID;
312 const std::string
313 archive_tar::linktarget ()
315 /* TODO: consider .. path traversal issues */
316 if (next_file_type () == ARCHIVE_FILE_SYMLINK ||
317 next_file_type () == ARCHIVE_FILE_HARDLINK)
318 return state.linkname;
319 return std::string();
322 io_stream *
323 archive_tar::extract_file ()
325 if (archive_children)
326 return NULL;
327 archive_tar_file *rv = new archive_tar_file (state);
328 return rv;
331 time_t
332 archive_tar::get_mtime ()
334 if (state.parent)
335 return state.parent->get_mtime ();
336 return 0;
339 mode_t
340 archive_tar::get_mode ()
342 if (state.parent)
343 return state.parent->get_mode ();
344 return 0;