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