]> cygwin.com Git - cygwin-apps/setup.git/blame - io_stream.cc
Suggest URLs for updated setup based on build architecture
[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
155eacb6 31typedef std::map <std::string, IOStreamProvider *, casecompare_lt_op> providersType;
080bec6e 32static providersType *providers;
19911586
RC
33static size_t longestPrefix = 0;
34static int inited = 0;
35
36void
37io_stream::registerProvider (IOStreamProvider &theProvider,
a3a02820 38 const std::string& urlPrefix)
19911586
RC
39{
40 if (!inited)
41 {
080bec6e 42 providers = new providersType;
19911586
RC
43 inited = true;
44 }
45 theProvider.key = urlPrefix;
080bec6e 46 if (providers->find (urlPrefix) != providers->end())
155eacb6 47 throw new std::invalid_argument ("urlPrefix already registered!");
080bec6e 48 (*providers)[urlPrefix] = &theProvider;
19911586
RC
49 if (urlPrefix.size() > longestPrefix)
50 longestPrefix = urlPrefix.size();
51}
52
53static IOStreamProvider const *
a3a02820 54findProvider (const std::string& path)
19911586
RC
55{
56 if (path.size() < longestPrefix)
57 return NULL;
080bec6e
RC
58 for (providersType::const_iterator i = providers->begin();
59 i != providers->end(); ++i)
19911586 60 {
afa76033 61 if (!casecompare(path, i->first, i->first.size()))
080bec6e 62 return i->second;
19911586
RC
63 }
64 return NULL;
65}
b24c88b3
RC
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 */
157dc2b8 79 Log (LOG_TIMESTAMP) << "io_stream::factory has been called" << endLog;
b24c88b3
RC
80 return NULL;
81}
82
3d3c6047 83#define url_scheme_not_registered(name) \
155eacb6 84 throw new std::invalid_argument ((std::string("URL Scheme for '")+ \
3d3c6047
IP
85 name+"' not registered!").c_str())
86
b24c88b3 87io_stream *
26922cd2 88io_stream::open (const std::string& name, const std::string& mode, mode_t perms)
b24c88b3 89{
19911586
RC
90 IOStreamProvider const *p = findProvider (name);
91 if (!p)
3d3c6047 92 url_scheme_not_registered (name);
26922cd2 93 io_stream *rv = p->open (&name.c_str()[p->key.size()], mode, perms);
19911586
RC
94 if (!rv->error ())
95 return rv;
96 delete rv;
b24c88b3
RC
97 return NULL;
98}
99
100int
b41c2908 101io_stream::mkpath_p (path_type_t isadir, const std::string& name, mode_t mode)
b24c88b3 102{
19911586
RC
103 IOStreamProvider const *p = findProvider (name);
104 if (!p)
3d3c6047 105 url_scheme_not_registered (name);
b41c2908 106 return p->mkdir_p (isadir, &name.c_str()[p->key.size()], mode);
b24c88b3
RC
107}
108
109/* remove a file or directory. */
110int
a3a02820 111io_stream::remove (const std::string& name)
b24c88b3 112{
19911586
RC
113 IOStreamProvider const *p = findProvider (name);
114 if (!p)
3d3c6047 115 url_scheme_not_registered (name);
d2a3615c 116 return p->remove (&name.c_str()[p->key.size()]);
b24c88b3
RC
117}
118
119int
a3a02820 120io_stream::mklink (const std::string& from, const std::string& to,
b24c88b3
RC
121 io_stream_link_t linktype)
122{
157dc2b8 123 Log (LOG_BABBLE) << "io_stream::mklink (" << from << "->" << to << ")"
bf4ffcd9 124 << endLog;
19911586
RC
125 IOStreamProvider const *fromp = findProvider (from);
126 IOStreamProvider const *top = findProvider (to);
3d3c6047
IP
127 if (!fromp)
128 url_scheme_not_registered (from);
129 if (!top)
130 url_scheme_not_registered (to);
19911586 131 if (fromp != top)
155eacb6 132 throw new std::invalid_argument ("Attempt to link across url providers.");
d2a3615c
MB
133 return fromp->mklink (&from.c_str()[fromp->key.size()],
134 &to.c_str()[top->key.size()], linktype);
7c7034e8
RC
135}
136
137int
a3a02820 138io_stream::move_copy (const std::string& from, const std::string& to)
7c7034e8
RC
139{
140 /* parameters are ok - checked before calling us, and we are private */
26922cd2
CV
141 io_stream *in = io_stream::open (to, "wb", 0644);
142 io_stream *out = io_stream::open (from, "rb", 0);
341988b9
RC
143 if (io_stream::copy (in, out))
144 {
157dc2b8 145 Log (LOG_TIMESTAMP) << "Failed copy of " << from << " to " << to
bf4ffcd9 146 << endLog;
341988b9
RC
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
df62e023 161ssize_t io_stream::copy (io_stream * in, io_stream * out)
341988b9
RC
162{
163 if (!in || !out)
164 return -1;
df62e023 165 char
94dfd783 166 buffer[65536];
df62e023
RC
167 ssize_t
168 countin,
169 countout;
94dfd783 170 while ((countin = in->read (buffer, sizeof(buffer))) > 0)
7c7034e8
RC
171 {
172 countout = out->write (buffer, countin);
173 if (countout != countin)
df62e023 174 {
157dc2b8 175 Log (LOG_TIMESTAMP) << "io_stream::copy failed to write "
bf4ffcd9 176 << countin << " bytes" << endLog;
df62e023
RC
177 return countout ? countout : -1;
178 }
7c7034e8 179 }
eb20d728 180
9e9bdee2
JT
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;
eb20d728 187
9e9bdee2 188 /* Here it would be nice to be able to do something like
eb20d728 189 TODO:
7c7034e8
RC
190 out->set_mtime (in->get_mtime ());
191 */
7c7034e8
RC
192 return 0;
193}
194
195int
a3a02820 196io_stream::move (const std::string& from, const std::string& to)
7c7034e8 197{
19911586
RC
198 IOStreamProvider const *fromp = findProvider (from);
199 IOStreamProvider const *top = findProvider (to);
3d3c6047
IP
200 if (!fromp)
201 url_scheme_not_registered (from);
202 if (!top)
203 url_scheme_not_registered (to);
19911586
RC
204 if (fromp != top)
205 return io_stream::move_copy (from, to);
d2a3615c
MB
206 return fromp->move (&from.c_str()[fromp->key.size()],
207 &to.c_str()[top->key.size()]);
b24c88b3
RC
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 {
edef4f57
CV
221 --pos; /* end of line, remove from buffer */
222 if (pos > buffer && *(pos - 1) == '\r')
223 --pos;
b24c88b3
RC
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
a3a02820 235io_stream::exists (const std::string& name)
b24c88b3 236{
19911586
RC
237 IOStreamProvider const *p = findProvider (name);
238 if (!p)
3d3c6047 239 url_scheme_not_registered (name);
d2a3615c 240 return p->exists (&name.c_str()[p->key.size()]);
b24c88b3
RC
241}
242
243/* virtual members */
244
6b68e703 245io_stream::~io_stream () {}
This page took 0.177512 seconds and 6 git commands to generate.