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