]>
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> | |
29 | #include "log.h" | |
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 | */ | |
50 | log (LOG_TIMESTAMP, "io_stream::factory has been called"); | |
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 | { | |
3c054baf RC |
115 | log (LOG_BABBLE, String("io_stream::mklink (") + from + "->" + to + ")"); |
116 | if (!from.size() || !to.size()) | |
7c7034e8 | 117 | { |
3c054baf | 118 | log (LOG_TIMESTAMP, "invalid string in from or to parameters to mklink"); |
7c7034e8 RC |
119 | return 1; |
120 | } | |
b24c88b3 | 121 | /* iterate through the known url prefixes */ |
3c054baf | 122 | if (!from.casecompare ("file://", 7)) |
b24c88b3 RC |
123 | { |
124 | /* file urls can symlink or hardlink to file url's. */ | |
125 | /* TODO: allow linking to cygfile url's */ | |
3c054baf RC |
126 | if (!to.casecompare ("file://", 7)) |
127 | return io_stream_file::mklink (&from.cstr_oneuse()[7], &to.cstr_oneuse()[7], linktype); | |
b24c88b3 RC |
128 | log (LOG_TIMESTAMP, "Attempt to link across url providers"); |
129 | return 1; | |
130 | } | |
3c054baf | 131 | if (!from.casecompare ("cygfile://", 10)) |
b24c88b3 RC |
132 | { |
133 | /* cygfile urls can symlink or hardlink to cygfile urls's. */ | |
134 | /* TODO: allow -> file urls */ | |
3c054baf RC |
135 | if (!to.casecompare ("cygfile://", 10)) |
136 | return io_stream_cygfile::mklink (&from.cstr_oneuse()[10], &to.cstr_oneuse()[10], linktype); | |
b24c88b3 RC |
137 | log (LOG_TIMESTAMP, "Attempt to link across url providers"); |
138 | return 1; | |
139 | } | |
140 | #if 0 | |
141 | if (!strmcasecmp ("http://", from, 7)) | |
142 | { | |
143 | /* http urls can symlink to http or ftp url's */ | |
144 | } | |
7c7034e8 | 145 | #endif |
3c054baf | 146 | log (LOG_TIMESTAMP, String ("Unsupported url providers for ") + from); |
7c7034e8 RC |
147 | return 1; |
148 | } | |
149 | ||
150 | int | |
3c054baf | 151 | io_stream::move_copy (String const &from, String const &to) |
7c7034e8 RC |
152 | { |
153 | /* parameters are ok - checked before calling us, and we are private */ | |
154 | io_stream *in = io_stream::open (to, "wb"); | |
155 | io_stream *out = io_stream::open (from, "rb"); | |
341988b9 RC |
156 | if (io_stream::copy (in, out)) |
157 | { | |
3c054baf | 158 | log (LOG_TIMESTAMP, String("Failed copy of ") + from + " to "+ to); |
341988b9 RC |
159 | delete out; |
160 | io_stream::remove (to); | |
161 | delete in; | |
162 | return 1; | |
163 | } | |
164 | /* TODO: | |
165 | out->set_mtime (in->get_mtime ()); | |
166 | */ | |
167 | delete in; | |
168 | delete out; | |
169 | io_stream::remove (from); | |
170 | return 0; | |
171 | } | |
172 | ||
df62e023 | 173 | ssize_t io_stream::copy (io_stream * in, io_stream * out) |
341988b9 RC |
174 | { |
175 | if (!in || !out) | |
176 | return -1; | |
df62e023 RC |
177 | char |
178 | buffer[16384]; | |
179 | ssize_t | |
180 | countin, | |
181 | countout; | |
7c7034e8 RC |
182 | while ((countin = in->read (buffer, 16384)) > 0) |
183 | { | |
184 | countout = out->write (buffer, countin); | |
185 | if (countout != countin) | |
df62e023 RC |
186 | { |
187 | log (LOG_TIMESTAMP, "io_stream::copy failed to write %ld bytes", | |
188 | countin); | |
189 | return countout ? countout : -1; | |
190 | } | |
7c7034e8 | 191 | } |
3c054baf | 192 | // XXX FIXME: What if countin < 0? return an error |
341988b9 | 193 | |
7c7034e8 RC |
194 | /* TODO: |
195 | out->set_mtime (in->get_mtime ()); | |
196 | */ | |
7c7034e8 RC |
197 | return 0; |
198 | } | |
199 | ||
200 | int | |
3c054baf | 201 | io_stream::move (String const &from, String const &to) |
7c7034e8 | 202 | { |
3c054baf | 203 | if (!from.size() || !to.size()) |
7c7034e8 RC |
204 | { |
205 | log (LOG_TIMESTAMP, "invalid string in from or to parameters to move"); | |
206 | return 1; | |
207 | } | |
208 | /* iterate through the known url prefixes */ | |
3c054baf | 209 | if (!from.casecompare ("file://", 7)) |
7c7034e8 RC |
210 | { |
211 | /* TODO: allow 'move' to cygfile url's */ | |
3c054baf | 212 | if (to.casecompare ("file://", 7)) |
7c7034e8 | 213 | return io_stream::move_copy (from, to); |
3c054baf | 214 | return io_stream_file::move (&from.cstr_oneuse()[7], &to.cstr_oneuse()[7]); |
7c7034e8 | 215 | } |
3c054baf | 216 | if (!from.casecompare ("cygfile://", 10)) |
7c7034e8 RC |
217 | { |
218 | /* TODO: allow -> file urls */ | |
3c054baf | 219 | if (to.casecompare ("cygfile://", 10)) |
7c7034e8 | 220 | return io_stream::move_copy (from, to); |
3c054baf | 221 | return io_stream_cygfile::move (&from.cstr_oneuse()[10], &to.cstr_oneuse()[10]); |
7c7034e8 RC |
222 | } |
223 | #if 0 | |
224 | if (!strmcasecmp ("http://", from, 7)) | |
225 | { | |
226 | /* http urls can symlink to http or ftp url's */ | |
227 | } | |
b24c88b3 | 228 | #endif |
1ac649ed | 229 | log (LOG_TIMESTAMP, String ("Unsupported url providers for ") + from); |
b24c88b3 RC |
230 | return 1; |
231 | } | |
232 | ||
233 | char * | |
234 | io_stream::gets (char *buffer, size_t length) | |
235 | { | |
236 | char *pos = buffer; | |
237 | size_t count = 0; | |
238 | while (count + 1 < length && read (pos, 1) == 1) | |
239 | { | |
240 | count++; | |
241 | pos++; | |
242 | if (*(pos - 1) == '\n') | |
243 | { | |
edef4f57 CV |
244 | --pos; /* end of line, remove from buffer */ |
245 | if (pos > buffer && *(pos - 1) == '\r') | |
246 | --pos; | |
b24c88b3 RC |
247 | break; |
248 | } | |
249 | } | |
250 | if (count == 0 || error ()) | |
251 | /* EOF when no chars found, or an error */ | |
252 | return NULL; | |
253 | *pos = '\0'; | |
254 | return buffer; | |
255 | } | |
256 | ||
257 | int | |
3c054baf | 258 | io_stream::exists (String const &name) |
b24c88b3 | 259 | { |
3c054baf | 260 | if (!name.size()) |
b24c88b3 RC |
261 | return 1; |
262 | /* iterate through the known url prefix's */ | |
3c054baf RC |
263 | if (!name.casecompare ("file://", 7)) |
264 | return io_stream_file::exists (&name.cstr_oneuse()[7]); | |
265 | if (!name.casecompare ("cygfile://", 10)) | |
266 | return io_stream_cygfile::exists (&name.cstr_oneuse()[10]); | |
b24c88b3 RC |
267 | return 1; |
268 | } | |
269 | ||
270 | /* virtual members */ | |
271 | ||
272 | io_stream::~io_stream () | |
273 | { | |
e9440f0f RC |
274 | if (!destroyed) |
275 | log (LOG_TIMESTAMP, "io_stream::~io_stream: It looks like a class hasn't overriden the destructor!"); | |
b24c88b3 RC |
276 | return; |
277 | } |