]> cygwin.com Git - cygwin-apps/setup.git/blob - archive.cc
2002-07-15 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / archive.cc
1 /*
2 * Copyright (c) 2001, Robert Collins.
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 Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16 /* Archive IO operations
17 */
18
19 #if 0
20 static const char *cvsid =
21 "\n%%% $Id$\n";
22 #endif
23
24 //#include "win32.h"
25 //#include <stdio.h>
26 //#include <stdlib.h>
27 #include "LogSingleton.h"
28 //#include "port.h"
29 #include "String++.h"
30
31 #include "io_stream.h"
32 #include "archive.h"
33 #include "archive_tar.h"
34
35 /* In case you are wondering why the file magic is not in one place:
36 * It could be. But there is little (any?) benefit.
37 * What is important is that the file magic required for any _task_ is centralised.
38 * One such task is identifying archives
39 *
40 * to federate into each class one might add a magic parameter to the constructor, which
41 * the class could test itself.
42 */
43
44 /* GNU TAR:
45 * offset 257 string ustar\040\040\0
46 */
47
48
49 #define longest_magic 265
50
51 archive *
52 archive::extract (io_stream * original)
53 {
54 if (!original)
55 return NULL;
56 char magic[longest_magic];
57 if (original->peek (magic, longest_magic) > 0)
58 {
59 if (memcmp (&magic[257], "ustar\040\040\0", 8) == 0)
60 {
61 /* tar */
62 archive_tar *rv = new archive_tar (original);
63 if (!rv->error ())
64 return rv;
65 return NULL;
66 }
67 #if 0
68 else if (memcmp (magic, "BZh", 3) == 0)
69 {
70 archive_bz *rv = new archive_bz (original);
71 if (!rv->error ())
72 return rv;
73 return NULL;
74 }
75 #endif
76 }
77 return NULL;
78 }
79
80 int
81 archive::extract_file (archive * source, String const &prefixURL, String const &prefixPath, String suffix)
82 {
83 if (!source)
84 return 1;
85 String const destfilename = prefixURL+prefixPath+ source->next_file_name ()+ suffix;
86 switch (source->next_file_type ())
87 {
88 case ARCHIVE_FILE_REGULAR:
89 {
90
91 /* TODO: remove in-the-way directories via mkpath_p */
92 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename))
93 {
94 log (LOG_TIMESTAMP) << "Failed to make the path for " << destfilename
95 << endLog;
96 return 1;
97 }
98 io_stream::remove (destfilename);
99 io_stream *tmp = io_stream::open (destfilename, "wb");
100 if (!tmp)
101 {
102 log (LOG_TIMESTAMP) << "Failed to open " << destfilename;
103 log (LOG_TIMESTAMP) << " for writing." << endLog;
104 return 1;
105 }
106 io_stream *in = source->extract_file ();
107 if (!in)
108 {
109 delete tmp;
110 log (LOG_TIMESTAMP) << "Failed to extract the file "
111 << destfilename << " from the archive"
112 << endLog;
113 return 1;
114 }
115 if (io_stream::copy (in, tmp))
116 {
117 log (LOG_TIMESTAMP) << "Failed to output " << destfilename
118 << endLog;
119 delete tmp;
120 io_stream::remove (destfilename);
121 return 1;
122 }
123 tmp->set_mtime (in->get_mtime ());
124 delete in;
125 delete tmp;
126 }
127 break;
128 case ARCHIVE_FILE_SYMLINK:
129 {
130 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename))
131 {
132 log (LOG_TIMESTAMP) << "Failed to make the path for %s"
133 << destfilename << endLog;
134 return 1;}
135 io_stream::remove (destfilename);
136 int ok =
137 io_stream::mklink (destfilename,
138 prefixURL+ source->linktarget (),
139 IO_STREAM_SYMLINK);
140 /* FIXME: check what tar's filelength is set to for symlinks */
141 source->skip_file ();
142 return ok;
143 }
144 case ARCHIVE_FILE_HARDLINK:
145 {
146 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename))
147 {
148 log (LOG_TIMESTAMP) << "Failed to make the path for %s"
149 << destfilename << endLog;
150 return 1;
151 }
152 io_stream::remove (destfilename);
153 int ok =
154 io_stream::mklink (destfilename,
155 prefixURL + source->linktarget (),
156 IO_STREAM_HARDLINK);
157 /* FIXME: check what tar's filelength is set to for hardlinks */
158 source->skip_file ();
159 return ok;
160 }
161 case ARCHIVE_FILE_DIRECTORY:
162 {
163 char *path = (char *) alloca (destfilename.size());
164 strcpy (path, destfilename.cstr_oneuse());
165 while (path[0] && path[strlen (path) - 1] == '/')
166 path[strlen (path) - 1] = 0;
167 source->skip_file ();
168 return io_stream::mkpath_p (PATH_TO_DIR, path);
169 }
170 case ARCHIVE_FILE_INVALID:
171 source->skip_file ();
172 break;
173 }
174 return 0;
175 }
176
177 #if 0
178 ssize_t archive::read (void *buffer, size_t len)
179 {
180 log (LOG_TIMESTAMP, "archive::read called");
181 return 0;
182 }
183
184 ssize_t archive::write (void *buffer, size_t len)
185 {
186 log (LOG_TIMESTAMP, "archive::write called");
187 return 0;
188 }
189
190 ssize_t archive::peek (void *buffer, size_t len)
191 {
192 log (LOG_TIMESTAMP, "archive::peek called");
193 return 0;
194 }
195
196 long
197 archive::tell ()
198 {
199 log (LOG_TIMESTAMP, "bz::tell called");
200 return 0;
201 }
202
203 int
204 archive::error ()
205 {
206 log (LOG_TIMESTAMP, "archive::error called");
207 return 0;
208 }
209
210 const char *
211 archive::next_file_name ()
212 {
213 log (LOG_TIMESTAMP, "archive::next_file_name called");
214 return NULL;
215 }
216
217 archive::~archive ()
218 {
219 log (LOG_TIMESTAMP, "archive::~archive called");
220 return;
221 }
222 #endif
This page took 0.044378 seconds and 5 git commands to generate.