]> cygwin.com Git - cygwin-apps/setup.git/blame - io_stream.cc
* filemanip.cc (nt_wfopen): Only call nt_sec.SetPosixPerms if we have
[cygwin-apps/setup.git] / io_stream.cc
CommitLineData
b24c88b3 1/*
19911586 2 * Copyright (c) 2001, 2002, Robert Collins.
b24c88b3
RC
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
23static const char *cvsid =
24 "\n%%% $Id$\n";
25#endif
26
bf4ffcd9 27#include "LogSingleton.h"
b24c88b3
RC
28
29#include "io_stream.h"
a3a02820 30
19911586
RC
31#include <stdexcept>
32#include "IOStreamProvider.h"
080bec6e 33#include <map>
a3a02820 34#include "String++.h"
19911586 35
6625e635
RC
36using namespace std;
37
a3a02820 38typedef map <std::string, IOStreamProvider *, casecompare_lt_op> providersType;
080bec6e 39static providersType *providers;
19911586
RC
40static size_t longestPrefix = 0;
41static int inited = 0;
42
43void
44io_stream::registerProvider (IOStreamProvider &theProvider,
a3a02820 45 const std::string& urlPrefix)
19911586
RC
46{
47 if (!inited)
48 {
080bec6e 49 providers = new providersType;
19911586
RC
50 inited = true;
51 }
52 theProvider.key = urlPrefix;
080bec6e 53 if (providers->find (urlPrefix) != providers->end())
19911586 54 throw new invalid_argument ("urlPrefix already registered!");
080bec6e 55 (*providers)[urlPrefix] = &theProvider;
19911586
RC
56 if (urlPrefix.size() > longestPrefix)
57 longestPrefix = urlPrefix.size();
58}
59
60static IOStreamProvider const *
a3a02820 61findProvider (const std::string& path)
19911586
RC
62{
63 if (path.size() < longestPrefix)
64 return NULL;
080bec6e
RC
65 for (providersType::const_iterator i = providers->begin();
66 i != providers->end(); ++i)
19911586 67 {
afa76033 68 if (!casecompare(path, i->first, i->first.size()))
080bec6e 69 return i->second;
19911586
RC
70 }
71 return NULL;
72}
b24c88b3
RC
73
74/* Static members */
75io_stream *
76io_stream::factory (io_stream * parent)
77{
78 /* something like,
79 * if !next_file_name
80 * return NULL
81 * switch (magic_id(peek (parent), max_magic_length))
82 * case io_stream * foo = new tar
83 * case io_stream * foo = new bz2
84 * return foo
85 */
bf4ffcd9 86 log (LOG_TIMESTAMP) << "io_stream::factory has been called" << endLog;
b24c88b3
RC
87 return NULL;
88}
89
3d3c6047 90#define url_scheme_not_registered(name) \
a3a02820 91 throw new invalid_argument ((std::string("URL Scheme for '")+ \
3d3c6047
IP
92 name+"' not registered!").c_str())
93
b24c88b3 94io_stream *
a3a02820 95io_stream::open (const std::string& name, const std::string& mode)
b24c88b3 96{
19911586
RC
97 IOStreamProvider const *p = findProvider (name);
98 if (!p)
3d3c6047 99 url_scheme_not_registered (name);
d2a3615c 100 io_stream *rv = p->open (&name.c_str()[p->key.size()], mode);
19911586
RC
101 if (!rv->error ())
102 return rv;
103 delete rv;
b24c88b3
RC
104 return NULL;
105}
106
107int
b41c2908 108io_stream::mkpath_p (path_type_t isadir, const std::string& name, mode_t mode)
b24c88b3 109{
19911586
RC
110 IOStreamProvider const *p = findProvider (name);
111 if (!p)
3d3c6047 112 url_scheme_not_registered (name);
b41c2908 113 return p->mkdir_p (isadir, &name.c_str()[p->key.size()], mode);
b24c88b3
RC
114}
115
116/* remove a file or directory. */
117int
a3a02820 118io_stream::remove (const std::string& name)
b24c88b3 119{
19911586
RC
120 IOStreamProvider const *p = findProvider (name);
121 if (!p)
3d3c6047 122 url_scheme_not_registered (name);
d2a3615c 123 return p->remove (&name.c_str()[p->key.size()]);
b24c88b3
RC
124}
125
126int
a3a02820 127io_stream::mklink (const std::string& from, const std::string& to,
b24c88b3
RC
128 io_stream_link_t linktype)
129{
bf4ffcd9
RC
130 log (LOG_BABBLE) << "io_stream::mklink (" << from << "->" << to << ")"
131 << endLog;
19911586
RC
132 IOStreamProvider const *fromp = findProvider (from);
133 IOStreamProvider const *top = findProvider (to);
3d3c6047
IP
134 if (!fromp)
135 url_scheme_not_registered (from);
136 if (!top)
137 url_scheme_not_registered (to);
19911586
RC
138 if (fromp != top)
139 throw new invalid_argument ("Attempt to link across url providers.");
d2a3615c
MB
140 return fromp->mklink (&from.c_str()[fromp->key.size()],
141 &to.c_str()[top->key.size()], linktype);
7c7034e8
RC
142}
143
144int
a3a02820 145io_stream::move_copy (const std::string& from, const std::string& to)
7c7034e8
RC
146{
147 /* parameters are ok - checked before calling us, and we are private */
148 io_stream *in = io_stream::open (to, "wb");
149 io_stream *out = io_stream::open (from, "rb");
341988b9
RC
150 if (io_stream::copy (in, out))
151 {
bf4ffcd9
RC
152 log (LOG_TIMESTAMP) << "Failed copy of " << from << " to " << to
153 << endLog;
341988b9
RC
154 delete out;
155 io_stream::remove (to);
156 delete in;
157 return 1;
158 }
159 /* TODO:
160 out->set_mtime (in->get_mtime ());
161 */
162 delete in;
163 delete out;
164 io_stream::remove (from);
165 return 0;
166}
167
df62e023 168ssize_t io_stream::copy (io_stream * in, io_stream * out)
341988b9
RC
169{
170 if (!in || !out)
171 return -1;
df62e023
RC
172 char
173 buffer[16384];
174 ssize_t
175 countin,
176 countout;
7c7034e8
RC
177 while ((countin = in->read (buffer, 16384)) > 0)
178 {
179 countout = out->write (buffer, countin);
180 if (countout != countin)
df62e023 181 {
bf4ffcd9
RC
182 log (LOG_TIMESTAMP) << "io_stream::copy failed to write "
183 << countin << " bytes" << endLog;
df62e023
RC
184 return countout ? countout : -1;
185 }
7c7034e8 186 }
eb20d728
BD
187
188 /* Here it would be nice to be able to do something like
341988b9 189
eb20d728
BD
190 if (countin < 0)
191 return -1;
192
193 in order to be able to detect a read error occured and pass it on
194 to the caller, however with the current io_stream class this will fail
195 spectacularly because there is no way to signal an EOF condition, and
196 thus the only way the while loop above ends is the resulting error from
197 trying to read past EOF.
198
199 TODO:
7c7034e8
RC
200 out->set_mtime (in->get_mtime ());
201 */
7c7034e8
RC
202 return 0;
203}
204
205int
a3a02820 206io_stream::move (const std::string& from, const std::string& to)
7c7034e8 207{
19911586
RC
208 IOStreamProvider const *fromp = findProvider (from);
209 IOStreamProvider const *top = findProvider (to);
3d3c6047
IP
210 if (!fromp)
211 url_scheme_not_registered (from);
212 if (!top)
213 url_scheme_not_registered (to);
19911586
RC
214 if (fromp != top)
215 return io_stream::move_copy (from, to);
d2a3615c
MB
216 return fromp->move (&from.c_str()[fromp->key.size()],
217 &to.c_str()[top->key.size()]);
b24c88b3
RC
218}
219
220char *
221io_stream::gets (char *buffer, size_t length)
222{
223 char *pos = buffer;
224 size_t count = 0;
225 while (count + 1 < length && read (pos, 1) == 1)
226 {
227 count++;
228 pos++;
229 if (*(pos - 1) == '\n')
230 {
edef4f57
CV
231 --pos; /* end of line, remove from buffer */
232 if (pos > buffer && *(pos - 1) == '\r')
233 --pos;
b24c88b3
RC
234 break;
235 }
236 }
237 if (count == 0 || error ())
238 /* EOF when no chars found, or an error */
239 return NULL;
240 *pos = '\0';
241 return buffer;
242}
243
244int
a3a02820 245io_stream::exists (const std::string& name)
b24c88b3 246{
19911586
RC
247 IOStreamProvider const *p = findProvider (name);
248 if (!p)
3d3c6047 249 url_scheme_not_registered (name);
d2a3615c 250 return p->exists (&name.c_str()[p->key.size()]);
b24c88b3
RC
251}
252
253/* virtual members */
254
6b68e703 255io_stream::~io_stream () {}
This page took 0.074176 seconds and 5 git commands to generate.