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