Fix MD5sum.str () formatting bug
[cygwin-setup.git] / archive_tar.cc
bloba07756e988131a727a87fc722a3d40ea2f1d4aa9
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 #if 0
19 static const char *cvsid =
20 "\n%%% $Id$\n";
21 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/fcntl.h>
27 #include <errno.h>
29 //#include "zlib/zlib.h"
30 #include "io_stream.h"
31 //#include "compress.h"
32 #include "win32.h"
33 #include "archive.h"
34 #include "archive_tar.h"
35 #include "mkdir.h"
36 #include "LogFile.h"
37 #include "filemanip.h"
39 #if 0
40 #undef _WIN32
41 #include "bzlib.h"
43 #define SYMLINK_COOKIE "!<symlink>"
44 #endif
45 static int err;
47 static char buf[512];
49 int _tar_verbose = 0;
51 archive_tar::archive_tar (io_stream * original)
53 archive_children = 0;
55 if (_tar_verbose)
56 LogBabblePrintf("tar: open `%p'\n", original);
58 if (!original)
60 state.lasterr = EBADF;
61 return;
63 state.parent = original;
65 if (sizeof (state.tar_header) != 512)
67 /* drastic, but important */
68 Log (LOG_TIMESTAMP) << "compilation error: tar header struct not 512"
69 << " bytes (it's " << sizeof (state.tar_header)
70 << ")" << endLog;
71 Logger ().exit (1);
75 ssize_t
76 archive_tar::read (void *buffer, size_t len)
78 return -1;
81 ssize_t
82 archive_tar::write (const void *buffer, size_t len)
84 return 0;
87 ssize_t
88 archive_tar::peek (void *buffer, size_t len)
90 return 0;
93 int
94 archive_tar::error ()
96 return state.lasterr;
99 long
100 archive_tar::tell ()
102 return state.file_offset;
106 archive_tar::seek (long where, io_stream_seek_t whence)
108 /* seeking in the parent archive doesn't make sense. although we could
109 map to files ?
110 Also, seeking might make sense for rewing..??
112 return -1;
116 archive_tar::skip_file ()
118 while (state.file_length > state.file_offset)
120 int len = state.parent->read (buf, 512);
121 state.file_offset += 512;
122 if (len != 512)
123 return 1;
125 state.file_length = 0;
126 state.file_offset = 0;
127 state.header_read = 0;
128 return 0;
131 const std::string
132 archive_tar::next_file_name ()
134 char *c;
136 if (state.header_read)
138 if (strlen (state.filename))
139 return state.filename;
140 else
141 /* End of tar */
142 return std::string();
145 int r = state.parent->read (&state.tar_header, 512);
147 /* See if we're at end of file */
148 if (r != 512)
149 return std::string();
151 /* See if the header is all zeros (i.e. last block) */
152 int n = 0;
153 for (r = 512 / sizeof (int); r; r--)
154 n |= ((int *) &state.tar_header)[r - 1];
155 if (n == 0)
156 return std::string();
158 if (!state.have_longname && state.tar_header.typeflag != 'L')
160 memcpy (state.filename, state.tar_header.name, 100);
161 state.filename[100] = 0;
163 else if (state.have_longname)
164 state.have_longname = 0;
166 sscanf (state.tar_header.size, "%Io", &state.file_length);
167 state.file_offset = 0;
169 if (_tar_verbose)
170 LogBabblePrintf ("%c %9d %s\n", state.tar_header.typeflag,
171 state.file_length, state.filename);
173 switch (state.tar_header.typeflag)
175 case 'L': /* GNU tar long name extension */
176 /* we read the 'file' into the long filename, then call back into here
177 * to find out if the actual file is a real file, or a special file..
179 if (state.file_length > CYG_PATH_MAX)
181 skip_file ();
182 LogPlainPrintf( "error: long file name exceeds %d characters\n",
183 CYG_PATH_MAX);
184 err++;
185 state.parent->read (&state.tar_header, 512);
186 sscanf (state.tar_header.size, "%Io", &state.file_length);
187 state.file_offset = 0;
188 skip_file ();
189 return next_file_name ();
191 c = state.filename;
192 /* FIXME: this should be a single read() call */
193 while (state.file_length > state.file_offset)
195 int need =
196 state.file_length - state.file_offset >
197 512 ? 512 : state.file_length - state.file_offset;
198 if (state.parent->read (buf, 512) < 512)
199 // FIXME: What's up with the "0"? It's probably a mistake, and
200 // should be "". It used to be written as 0, and was subject to a
201 // bizarre implicit conversion by the unwise String(int)
202 // constructor.
203 return "0";
204 memcpy (c, buf, need);
205 c += need;
206 state.file_offset += need;
208 *c = 0;
209 state.have_longname = 1;
210 return next_file_name ();
212 case '3': /* char */
213 case '4': /* block */
214 case '6': /* fifo */
215 LogPlainPrintf ("warning: not extracting special file %s\n",
216 state.filename);
217 err++;
218 return next_file_name ();
220 case '0': /* regular file */
221 case 0: /* regular file also */
222 case '2': /* symbolic link */
223 case '5': /* directory */
224 case '7': /* contiguous file */
225 state.header_read = 1;
226 return state.filename;
228 case '1': /* hard link, we just copy */
229 state.header_read = 1;
230 return state.filename;
232 default:
233 LogPlainPrintf ("error: unknown (or unsupported) file type `%c'\n",
234 state.tar_header.typeflag);
235 err++;
236 /* fall through */
237 case 'g': /* POSIX.1-2001 global extended header */
238 case 'x': /* POSIX.1-2001 extended header */
239 skip_file ();
240 return next_file_name ();
242 return std::string();
245 archive_tar::~archive_tar ()
247 if (state.parent)
248 delete state.parent;
251 # if 0
252 static void
253 fix_time_stamp (char *path)
255 int mtime;
256 long long ftimev;
257 FILETIME ftime;
258 HANDLE h;
260 sscanf (tar_header.mtime, "%o", &mtime);
261 ftimev = mtime * NSPERSEC + FACTOR;
262 ftime.dwHighDateTime = ftimev >> 32;
263 ftime.dwLowDateTime = ftimev;
264 h = CreateFileA (path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
265 0, OPEN_EXISTING,
266 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
267 if (h)
269 SetFileTime (h, 0, 0, &ftime);
270 CloseHandle (h);
273 #endif
274 archive_file_t
275 archive_tar::next_file_type ()
277 switch (state.tar_header.typeflag)
279 /* regular files */
280 case '0':
281 case 0:
282 case '7':
283 return ARCHIVE_FILE_REGULAR;
284 case '1':
285 return ARCHIVE_FILE_HARDLINK;
286 case '5':
287 return ARCHIVE_FILE_DIRECTORY;
288 case '2':
289 return ARCHIVE_FILE_SYMLINK;
290 default:
291 return ARCHIVE_FILE_INVALID;
295 const std::string
296 archive_tar::linktarget ()
298 /* TODO: consider .. path traversal issues */
299 if (next_file_type () == ARCHIVE_FILE_SYMLINK ||
300 next_file_type () == ARCHIVE_FILE_HARDLINK)
301 return state.tar_header.linkname;
302 return std::string();
305 io_stream *
306 archive_tar::extract_file ()
308 if (archive_children)
309 return NULL;
310 archive_tar_file *rv = new archive_tar_file (state);
311 return rv;
314 time_t
315 archive_tar::get_mtime ()
317 if (state.parent)
318 return state.parent->get_mtime ();
319 return 0;
322 mode_t
323 archive_tar::get_mode ()
325 if (state.parent)
326 return state.parent->get_mode ();
327 return 0;