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