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