2 * Copyright (c) 2001, 2002, Robert Collins.
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.
9 * A copy of the GNU General Public License can be found at
12 * Written by Robert Collins <rbtcollins@hotmail.com>
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
23 static const char *cvsid
=
27 #include "LogSingleton.h"
29 #include "io_stream.h"
32 #include "IOStreamProvider.h"
39 bool operator()(String
const &s1
, String
const &s2
) const
41 return s1
.casecompare (s2
) < 0;
45 typedef map
<String
, IOStreamProvider
* ,ltstr
> providersType
;
46 static providersType
*providers
;
47 static size_t longestPrefix
= 0;
48 static int inited
= 0;
51 io_stream::registerProvider (IOStreamProvider
&theProvider
,
52 String
const &urlPrefix
)
56 providers
= new providersType
;
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();
67 static IOStreamProvider
const *
68 findProvider (String
const &path
)
70 if (path
.size() < longestPrefix
)
72 for (providersType::const_iterator i
= providers
->begin();
73 i
!= providers
->end(); ++i
)
75 if (!path
.casecompare (i
->first
, i
->first
.size()))
83 io_stream::factory (io_stream
* parent
)
88 * switch (magic_id(peek (parent), max_magic_length))
89 * case io_stream * foo = new tar
90 * case io_stream * foo = new bz2
93 log (LOG_TIMESTAMP
) << "io_stream::factory has been called" << endLog
;
98 io_stream::open (String
const &name
, String
const &mode
)
100 IOStreamProvider
const *p
= findProvider (name
);
102 throw new invalid_argument ("URL Scheme not registered!");
103 io_stream
*rv
= p
->open (&name
.cstr_oneuse()[p
->key
.size()], mode
);
111 io_stream::mkpath_p (path_type_t isadir
, String
const &name
)
113 IOStreamProvider
const *p
= findProvider (name
);
115 throw new invalid_argument ("URL Scheme not registered!");
116 return p
->mkdir_p (isadir
, &name
.cstr_oneuse()[p
->key
.size()]);
119 /* remove a file or directory. */
121 io_stream::remove (String
const &name
)
123 IOStreamProvider
const *p
= findProvider (name
);
125 throw new invalid_argument ("URL Scheme not registered!");
126 return p
->remove (&name
.cstr_oneuse()[p
->key
.size()]);
130 io_stream::mklink (String
const &from
, String
const &to
,
131 io_stream_link_t linktype
)
133 log (LOG_BABBLE
) << "io_stream::mklink (" << from
<< "->" << to
<< ")"
135 IOStreamProvider
const *fromp
= findProvider (from
);
136 IOStreamProvider
const *top
= findProvider (to
);
138 throw new invalid_argument ("URL Scheme not registered!");
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
);
146 io_stream::move_copy (String
const &from
, String
const &to
)
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
))
153 log (LOG_TIMESTAMP
) << "Failed copy of " << from
<< " to " << to
156 io_stream::remove (to
);
161 out->set_mtime (in->get_mtime ());
165 io_stream::remove (from
);
169 ssize_t
io_stream::copy (io_stream
* in
, io_stream
* out
)
178 while ((countin
= in
->read (buffer
, 16384)) > 0)
180 countout
= out
->write (buffer
, countin
);
181 if (countout
!= countin
)
183 log (LOG_TIMESTAMP
) << "io_stream::copy failed to write "
184 << countin
<< " bytes" << endLog
;
185 return countout
? countout
: -1;
188 // XXX FIXME: What if countin < 0? return an error
191 out->set_mtime (in->get_mtime ());
197 io_stream::move (String
const &from
, String
const &to
)
199 IOStreamProvider
const *fromp
= findProvider (from
);
200 IOStreamProvider
const *top
= findProvider (to
);
202 throw new invalid_argument ("URL Scheme not registered!");
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()]);
210 io_stream::gets (char *buffer
, size_t length
)
214 while (count
+ 1 < length
&& read (pos
, 1) == 1)
218 if (*(pos
- 1) == '\n')
220 --pos
; /* end of line, remove from buffer */
221 if (pos
> buffer
&& *(pos
- 1) == '\r')
226 if (count
== 0 || error ())
227 /* EOF when no chars found, or an error */
234 io_stream::exists (String
const &name
)
236 IOStreamProvider
const *p
= findProvider (name
);
238 throw new invalid_argument ("URL Scheme not registered!");
239 return p
->exists (&name
.cstr_oneuse()[p
->key
.size()]);
242 /* virtual members */
244 io_stream::~io_stream ()
247 log (LOG_TIMESTAMP
) << "io_stream::~io_stream: It looks like a class "
248 << "hasn't overriden the destructor!" << endLog
;