]> cygwin.com Git - cygwin-apps/setup.git/blob - archive.cc
2002-02-19 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 "log.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, String ("Failed to make the path for ") + destfilename);
95 return 1;}
96 io_stream::remove (destfilename);
97 io_stream *tmp = io_stream::open (destfilename, "wb");
98 if (!tmp)
99 {
100 log (LOG_TIMESTAMP, String ("Failed to open ") + destfilename + " for writing.");
101 return 1;
102 }
103 io_stream *in = source->extract_file ();
104 if (!in)
105 {
106 delete tmp;
107 log (LOG_TIMESTAMP, String("Failed to extract the file ") + destfilename + " from the archive");
108 return 1;
109 }
110 if (io_stream::copy (in, tmp))
111 {
112 log (LOG_TIMESTAMP, String("Failed to output ") + destfilename);
113 delete tmp;
114 io_stream::remove (destfilename);
115 return 1;
116 }
117 tmp->set_mtime (in->get_mtime ());
118 delete in;
119 delete tmp;
120 }
121 break;
122 case ARCHIVE_FILE_SYMLINK:
123 {
124 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename))
125 {log (LOG_TIMESTAMP, "Failed to make the path for %s", destfilename.cstr_oneuse());
126 return 1;}
127 io_stream::remove (destfilename);
128 int ok =
129 io_stream::mklink (destfilename,
130 prefixURL+ source->linktarget (),
131 IO_STREAM_SYMLINK);
132 /* FIXME: check what tar's filelength is set to for symlinks */
133 source->skip_file ();
134 return ok;
135 }
136 case ARCHIVE_FILE_HARDLINK:
137 {
138 if (io_stream::mkpath_p (PATH_TO_FILE, destfilename))
139 {log (LOG_TIMESTAMP, "Failed to make the path for %s", destfilename.cstr_oneuse());
140 return 1;}
141 io_stream::remove (destfilename);
142 int ok =
143 io_stream::mklink (destfilename,
144 prefixURL + source->linktarget (),
145 IO_STREAM_HARDLINK);
146 /* FIXME: check what tar's filelength is set to for hardlinks */
147 source->skip_file ();
148 return ok;
149 }
150 case ARCHIVE_FILE_DIRECTORY:
151 {
152 char *path = (char *) alloca (destfilename.size());
153 strcpy (path, destfilename.cstr_oneuse());
154 while (path[0] && path[strlen (path) - 1] == '/')
155 path[strlen (path) - 1] = 0;
156 source->skip_file ();
157 return io_stream::mkpath_p (PATH_TO_DIR, path);
158 }
159 case ARCHIVE_FILE_INVALID:
160 source->skip_file ();
161 break;
162 }
163 return 0;
164 }
165
166 #if 0
167 ssize_t archive::read (void *buffer, size_t len)
168 {
169 log (LOG_TIMESTAMP, "archive::read called");
170 return 0;
171 }
172
173 ssize_t archive::write (void *buffer, size_t len)
174 {
175 log (LOG_TIMESTAMP, "archive::write called");
176 return 0;
177 }
178
179 ssize_t archive::peek (void *buffer, size_t len)
180 {
181 log (LOG_TIMESTAMP, "archive::peek called");
182 return 0;
183 }
184
185 long
186 archive::tell ()
187 {
188 log (LOG_TIMESTAMP, "bz::tell called");
189 return 0;
190 }
191
192 int
193 archive::error ()
194 {
195 log (LOG_TIMESTAMP, "archive::error called");
196 return 0;
197 }
198
199 const char *
200 archive::next_file_name ()
201 {
202 log (LOG_TIMESTAMP, "archive::next_file_name called");
203 return NULL;
204 }
205
206 archive::~archive ()
207 {
208 log (LOG_TIMESTAMP, "archive::~archive called");
209 return;
210 }
211 #endif
This page took 0.043465 seconds and 5 git commands to generate.