]>
Commit | Line | Data |
---|---|---|
b24c88b3 RC |
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 | /* this is the parent class for all IO operations. It's flexable enough to be cover for | |
17 | * HTTP access, local file access, and files being extracted from archives. | |
18 | * It also encapsulates the idea of an archive, and all non-archives become the special | |
19 | * case. | |
20 | */ | |
21 | ||
22 | #if 0 | |
23 | static const char *cvsid = | |
24 | "\n%%% $Id$\n"; | |
25 | #endif | |
26 | ||
27 | #include "win32.h" | |
28 | #include <stdio.h> | |
bf4ffcd9 | 29 | #include "LogSingleton.h" |
b24c88b3 RC |
30 | #include "port.h" |
31 | ||
32 | #include "io_stream.h" | |
33 | #include "io_stream_file.h" | |
34 | #include "io_stream_cygfile.h" | |
35 | #include "mkdir.h" | |
3c054baf | 36 | #include "String++.h" |
b24c88b3 RC |
37 | |
38 | /* Static members */ | |
39 | io_stream * | |
40 | io_stream::factory (io_stream * parent) | |
41 | { | |
42 | /* something like, | |
43 | * if !next_file_name | |
44 | * return NULL | |
45 | * switch (magic_id(peek (parent), max_magic_length)) | |
46 | * case io_stream * foo = new tar | |
47 | * case io_stream * foo = new bz2 | |
48 | * return foo | |
49 | */ | |
bf4ffcd9 | 50 | log (LOG_TIMESTAMP) << "io_stream::factory has been called" << endLog; |
b24c88b3 RC |
51 | return NULL; |
52 | } | |
53 | ||
54 | io_stream * | |
3c054baf | 55 | io_stream::open (String const &name, String const &mode) |
b24c88b3 | 56 | { |
3c054baf RC |
57 | if (name.size() < 7 || |
58 | mode.size() == 0) | |
b24c88b3 RC |
59 | return NULL; |
60 | /* iterate through the known url prefix's */ | |
3c054baf | 61 | if (!name.casecompare ("file://", 7)) |
b24c88b3 | 62 | { |
3c054baf | 63 | io_stream_file *rv = new io_stream_file (&name.cstr_oneuse()[7], mode.cstr_oneuse()); |
b24c88b3 RC |
64 | if (!rv->error ()) |
65 | return rv; | |
66 | delete rv; | |
67 | return NULL; | |
68 | } | |
3c054baf | 69 | if (!name.casecompare ("cygfile://", 10)) |
b24c88b3 | 70 | { |
3c054baf | 71 | io_stream_cygfile *rv = new io_stream_cygfile (&name.cstr_oneuse()[10], mode.cstr_oneuse()); |
b24c88b3 RC |
72 | if (!rv->error ()) |
73 | return rv; | |
74 | delete rv; | |
75 | return NULL; | |
76 | } | |
77 | return NULL; | |
78 | } | |
79 | ||
80 | int | |
3c054baf | 81 | io_stream::mkpath_p (path_type_t isadir, String const &name) |
b24c88b3 | 82 | { |
3c054baf | 83 | if (name.size() < 7) |
b24c88b3 RC |
84 | return 1; |
85 | /* iterate through the known url prefix's */ | |
3c054baf | 86 | if (!name.casecompare ("file://", 7)) |
b24c88b3 | 87 | { |
3c054baf | 88 | return mkdir_p (isadir == PATH_TO_DIR ? 1 : 0, &name.cstr_oneuse()[7]); |
b24c88b3 | 89 | } |
3c054baf | 90 | if (!name.casecompare ("cygfile://", 10)) |
b24c88b3 | 91 | { |
3c054baf | 92 | return cygmkdir_p (isadir, &name.cstr_oneuse()[10]); |
b24c88b3 RC |
93 | } |
94 | return 1; | |
95 | } | |
96 | ||
97 | /* remove a file or directory. */ | |
98 | int | |
3c054baf | 99 | io_stream::remove (String const &name) |
b24c88b3 | 100 | { |
3c054baf | 101 | if (!name.size()) |
b24c88b3 RC |
102 | return 1; |
103 | /* iterate through the known url prefix's */ | |
3c054baf RC |
104 | if (!name.casecompare ("file://", 7)) |
105 | return io_stream_file::remove (&name.cstr_oneuse()[7]); | |
106 | if (!name.casecompare ("cygfile://", 10)) | |
107 | return io_stream_cygfile::remove (&name.cstr_oneuse()[10]); | |
b24c88b3 RC |
108 | return 1; |
109 | } | |
110 | ||
111 | int | |
3c054baf | 112 | io_stream::mklink (String const &from, String const &to, |
b24c88b3 RC |
113 | io_stream_link_t linktype) |
114 | { | |
bf4ffcd9 RC |
115 | log (LOG_BABBLE) << "io_stream::mklink (" << from << "->" << to << ")" |
116 | << endLog; | |
3c054baf | 117 | if (!from.size() || !to.size()) |
7c7034e8 | 118 | { |
bf4ffcd9 RC |
119 | log (LOG_TIMESTAMP) << "invalid string in from or to parameters to mklink" |
120 | << endLog; | |
7c7034e8 RC |
121 | return 1; |
122 | } | |
b24c88b3 | 123 | /* iterate through the known url prefixes */ |
3c054baf | 124 | if (!from.casecompare ("file://", 7)) |
b24c88b3 RC |
125 | { |
126 | /* file urls can symlink or hardlink to file url's. */ | |
127 | /* TODO: allow linking to cygfile url's */ | |
3c054baf RC |
128 | if (!to.casecompare ("file://", 7)) |
129 | return io_stream_file::mklink (&from.cstr_oneuse()[7], &to.cstr_oneuse()[7], linktype); | |
bf4ffcd9 | 130 | log (LOG_TIMESTAMP) << "Attempt to link across url providers" << endLog; |
b24c88b3 RC |
131 | return 1; |
132 | } | |
3c054baf | 133 | if (!from.casecompare ("cygfile://", 10)) |
b24c88b3 RC |
134 | { |
135 | /* cygfile urls can symlink or hardlink to cygfile urls's. */ | |
136 | /* TODO: allow -> file urls */ | |
3c054baf RC |
137 | if (!to.casecompare ("cygfile://", 10)) |
138 | return io_stream_cygfile::mklink (&from.cstr_oneuse()[10], &to.cstr_oneuse()[10], linktype); | |
bf4ffcd9 | 139 | log (LOG_TIMESTAMP) << "Attempt to link across url providers" << endLog; |
b24c88b3 RC |
140 | return 1; |
141 | } | |
142 | #if 0 | |
143 | if (!strmcasecmp ("http://", from, 7)) | |
144 | { | |
145 | /* http urls can symlink to http or ftp url's */ | |
146 | } | |
7c7034e8 | 147 | #endif |
bf4ffcd9 | 148 | log (LOG_TIMESTAMP) << "Unsupported url providers for " << from << endLog; |
7c7034e8 RC |
149 | return 1; |
150 | } | |
151 | ||
152 | int | |
3c054baf | 153 | io_stream::move_copy (String const &from, String const &to) |
7c7034e8 RC |
154 | { |
155 | /* parameters are ok - checked before calling us, and we are private */ | |
156 | io_stream *in = io_stream::open (to, "wb"); | |
157 | io_stream *out = io_stream::open (from, "rb"); | |
341988b9 RC |
158 | if (io_stream::copy (in, out)) |
159 | { | |
bf4ffcd9 RC |
160 | log (LOG_TIMESTAMP) << "Failed copy of " << from << " to " << to |
161 | << endLog; | |
341988b9 RC |
162 | delete out; |
163 | io_stream::remove (to); | |
164 | delete in; | |
165 | return 1; | |
166 | } | |
167 | /* TODO: | |
168 | out->set_mtime (in->get_mtime ()); | |
169 | */ | |
170 | delete in; | |
171 | delete out; | |
172 | io_stream::remove (from); | |
173 | return 0; | |
174 | } | |
175 | ||
df62e023 | 176 | ssize_t io_stream::copy (io_stream * in, io_stream * out) |
341988b9 RC |
177 | { |
178 | if (!in || !out) | |
179 | return -1; | |
df62e023 RC |
180 | char |
181 | buffer[16384]; | |
182 | ssize_t | |
183 | countin, | |
184 | countout; | |
7c7034e8 RC |
185 | while ((countin = in->read (buffer, 16384)) > 0) |
186 | { | |
187 | countout = out->write (buffer, countin); | |
188 | if (countout != countin) | |
df62e023 | 189 | { |
bf4ffcd9 RC |
190 | log (LOG_TIMESTAMP) << "io_stream::copy failed to write " |
191 | << countin << " bytes" << endLog; | |
df62e023 RC |
192 | return countout ? countout : -1; |
193 | } | |
7c7034e8 | 194 | } |
3c054baf | 195 | // XXX FIXME: What if countin < 0? return an error |
341988b9 | 196 | |
7c7034e8 RC |
197 | /* TODO: |
198 | out->set_mtime (in->get_mtime ()); | |
199 | */ | |
7c7034e8 RC |
200 | return 0; |
201 | } | |
202 | ||
203 | int | |
3c054baf | 204 | io_stream::move (String const &from, String const &to) |
7c7034e8 | 205 | { |
3c054baf | 206 | if (!from.size() || !to.size()) |
7c7034e8 | 207 | { |
bf4ffcd9 RC |
208 | log (LOG_TIMESTAMP) << "invalid string in from or to parameters to move" |
209 | << endLog; | |
7c7034e8 RC |
210 | return 1; |
211 | } | |
212 | /* iterate through the known url prefixes */ | |
3c054baf | 213 | if (!from.casecompare ("file://", 7)) |
7c7034e8 RC |
214 | { |
215 | /* TODO: allow 'move' to cygfile url's */ | |
3c054baf | 216 | if (to.casecompare ("file://", 7)) |
7c7034e8 | 217 | return io_stream::move_copy (from, to); |
3c054baf | 218 | return io_stream_file::move (&from.cstr_oneuse()[7], &to.cstr_oneuse()[7]); |
7c7034e8 | 219 | } |
3c054baf | 220 | if (!from.casecompare ("cygfile://", 10)) |
7c7034e8 RC |
221 | { |
222 | /* TODO: allow -> file urls */ | |
3c054baf | 223 | if (to.casecompare ("cygfile://", 10)) |
7c7034e8 | 224 | return io_stream::move_copy (from, to); |
3c054baf | 225 | return io_stream_cygfile::move (&from.cstr_oneuse()[10], &to.cstr_oneuse()[10]); |
7c7034e8 RC |
226 | } |
227 | #if 0 | |
228 | if (!strmcasecmp ("http://", from, 7)) | |
229 | { | |
230 | /* http urls can symlink to http or ftp url's */ | |
231 | } | |
b24c88b3 | 232 | #endif |
bf4ffcd9 | 233 | log (LOG_TIMESTAMP) << "Unsupported url providers for " << from << endLog; |
b24c88b3 RC |
234 | return 1; |
235 | } | |
236 | ||
237 | char * | |
238 | io_stream::gets (char *buffer, size_t length) | |
239 | { | |
240 | char *pos = buffer; | |
241 | size_t count = 0; | |
242 | while (count + 1 < length && read (pos, 1) == 1) | |
243 | { | |
244 | count++; | |
245 | pos++; | |
246 | if (*(pos - 1) == '\n') | |
247 | { | |
edef4f57 CV |
248 | --pos; /* end of line, remove from buffer */ |
249 | if (pos > buffer && *(pos - 1) == '\r') | |
250 | --pos; | |
b24c88b3 RC |
251 | break; |
252 | } | |
253 | } | |
254 | if (count == 0 || error ()) | |
255 | /* EOF when no chars found, or an error */ | |
256 | return NULL; | |
257 | *pos = '\0'; | |
258 | return buffer; | |
259 | } | |
260 | ||
261 | int | |
3c054baf | 262 | io_stream::exists (String const &name) |
b24c88b3 | 263 | { |
3c054baf | 264 | if (!name.size()) |
b24c88b3 RC |
265 | return 1; |
266 | /* iterate through the known url prefix's */ | |
3c054baf RC |
267 | if (!name.casecompare ("file://", 7)) |
268 | return io_stream_file::exists (&name.cstr_oneuse()[7]); | |
269 | if (!name.casecompare ("cygfile://", 10)) | |
270 | return io_stream_cygfile::exists (&name.cstr_oneuse()[10]); | |
b24c88b3 RC |
271 | return 1; |
272 | } | |
273 | ||
274 | /* virtual members */ | |
275 | ||
276 | io_stream::~io_stream () | |
277 | { | |
e9440f0f | 278 | if (!destroyed) |
bf4ffcd9 RC |
279 | log (LOG_TIMESTAMP) << "io_stream::~io_stream: It looks like a class " |
280 | << "hasn't overriden the destructor!" << endLog; | |
b24c88b3 RC |
281 | return; |
282 | } |