Panda3D

virtualFile.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file virtualFile.cxx
10 * @author drose
11 * @date 2002-08-03
12 */
13
14 #include "virtualFile.h"
15 #include "virtualFileSystem.h"
16 #include "virtualFileList.h"
17 #include "config_express.h"
18 #include "pvector.h"
19 #include <iterator>
20
21 using std::iostream;
22 using std::istream;
23 using std::ostream;
24 using std::string;
25
26 TypeHandle VirtualFile::_type_handle;
27
28 /**
29 * Returns true if this file exists, false otherwise.
30 */
31 bool VirtualFile::
32 has_file() const {
33 return false;
34 }
35
36 /**
37 * Returns true if this file represents a directory (and scan_directory() may
38 * be called), false otherwise.
39 */
40 bool VirtualFile::
41 is_directory() const {
42 return false;
43 }
44
45 /**
46 * Returns true if this file represents a regular file (and read_file() may be
47 * called), false otherwise.
48 */
49 bool VirtualFile::
50 is_regular_file() const {
51 return false;
52 }
53
54 /**
55 * Returns true if this file may be written to, which implies write_file() may
56 * be called (unless it is a directory instead of a regular file).
57 */
58 bool VirtualFile::
59 is_writable() const {
60 return false;
61 }
62
63 /**
64 * Attempts to delete this file or directory. This can remove a single file
65 * or an empty directory. It will not remove a nonempty directory. Returns
66 * true on success, false on failure.
67 */
68 bool VirtualFile::
69 delete_file() {
70 return false;
71 }
72
73 /**
74 * Attempts to move or rename this file or directory. If the original file is
75 * an ordinary file, it will quietly replace any already-existing file in the
76 * new filename (but not a directory). If the original file is a directory,
77 * the new filename must not already exist.
78 *
79 * If the file is a directory, the new filename must be within the same mount
80 * point. If the file is an ordinary file, the new filename may be anywhere;
81 * but if it is not within the same mount point then the rename operation is
82 * automatically performed as a two-step copy-and-delete operation.
83 */
84 bool VirtualFile::
85 rename_file(VirtualFile *new_file) {
86 return false;
87 }
88
89 /**
90 * Attempts to copy the contents of this file to the indicated file. Returns
91 * true on success, false on failure.
92 */
93 bool VirtualFile::
94 copy_file(VirtualFile *new_file) {
95 return false;
96 }
97
98 /**
99 * If the file represents a directory (that is, is_directory() returns true),
100 * this returns the list of files within the directory at the current time.
101 * Returns NULL if the file is not a directory or if the directory cannot be
102 * read.
103 */
104 PT(VirtualFileList) VirtualFile::
105 scan_directory() const {
106 // First, we have to make sure there aren't any mount points attached under
107 // this directory. These will override any local filenames.
108 VirtualFileSystem *file_system = get_file_system();
109 Filename this_filename = get_filename();
110 vector_string mount_points_flat;
111 file_system->scan_mount_points(mount_points_flat, this_filename);
112
113 // Copy the set of nested mount points to a sorted list so we can search it
114 // quickly.
115 ov_set<string> mount_points;
116 std::copy(mount_points_flat.begin(), mount_points_flat.end(),
117 std::back_inserter(mount_points));
118 mount_points.sort();
119
120
121 PT(VirtualFileList) file_list = new VirtualFileList;
122
123 // Each of those mount points maps to a directory root or something from the
124 // file system.
125 ov_set<string>::const_iterator mi;
126 for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) {
127 const string &basename = (*mi);
128 Filename filename(this_filename, basename);
129 PT(VirtualFile) file = file_system->get_file(filename);
130 file_list->add_file(file);
131 }
132
133 // Now, get the actual local files in this directory.
134 vector_string names;
135 if (!scan_local_directory(file_list, mount_points)) {
136 // Not a directory, or unable to read directory.
137 if (file_list->get_num_files() == 0) {
138 return nullptr;
139 }
140
141 // We couldn't read the physical directory, but we do have some mounted
142 // files to return.
143 return file_list;
144 }
145
146 return file_list;
147 }
148
149 /**
150 *
151 */
152 void VirtualFile::
153 output(ostream &out) const {
154 out << get_filename();
155 }
156
157 /**
158 * If the file represents a directory, lists its contents.
159 */
160 void VirtualFile::
161 ls(ostream &out) const {
162 CPT(VirtualFileList) contents = scan_directory();
163 if (contents == nullptr) {
164 if (!is_directory()) {
165 out << get_filename() << "\n";
166 } else {
167 out << get_filename() << " cannot be read.\n";
168 }
169 return;
170 }
171
172 int num_files = contents->get_num_files();
173 for (int i = 0; i < num_files; i++) {
174 VirtualFile *file = contents->get_file(i);
175 out << file->get_filename().get_basename() << "\n";
176 }
177 }
178
179 /**
180 * If the file represents a directory, recursively lists its contents and
181 * those of all subdirectories.
182 */
183 void VirtualFile::
184 ls_all(ostream &out) const {
185 if (!is_directory()) {
186 out << get_filename() << " is not a directory.\n";
187 } else {
188 r_ls_all(out, get_filename());
189 }
190 }
191
192 /**
193 * Opens the file for reading. Returns a newly allocated istream on success
194 * (which you should eventually delete when you are done reading). Returns
195 * NULL on failure.
196 */
197 istream *VirtualFile::
198 open_read_file(bool auto_unwrap) const {
199 return nullptr;
200 }
201
202 /**
203 * Closes a file opened by a previous call to open_read_file(). This really
204 * just deletes the istream pointer, but it is recommended to use this
205 * interface instead of deleting it explicitly, to help work around compiler
206 * issues.
207 */
208 void VirtualFile::
209 close_read_file(istream *stream) const {
210 nassertv(false);
211 }
212
213 /**
214 * Call this method after a reading the istream returned by open_read_file()
215 * to completion. If it returns true, the file was read completely and
216 * without error; if it returns false, there may have been some errors or a
217 * truncated file read. This is particularly likely if the stream is a
218 * VirtualFileHTTP.
219 */
220 bool VirtualFile::
221 was_read_successful() const {
222 return true;
223 }
224
225 /**
226 * Opens the file for writing. Returns a newly allocated ostream on success
227 * (which you should eventually delete when you are done writing). Returns
228 * NULL on failure.
229 */
230 ostream *VirtualFile::
231 open_write_file(bool auto_wrap, bool truncate) {
232 return nullptr;
233 }
234
235 /**
236 * Works like open_write_file(), but the file is opened in append mode. Like
237 * open_write_file, the returned pointer should eventually be passed to
238 * close_write_file().
239 */
240 ostream *VirtualFile::
241 open_append_file() {
242 return nullptr;
243 }
244
245 /**
246 * Closes a file opened by a previous call to open_write_file(). This really
247 * just deletes the ostream pointer, but it is recommended to use this
248 * interface instead of deleting it explicitly, to help work around compiler
249 * issues.
250 */
251 void VirtualFile::
252 close_write_file(ostream *stream) {
253 nassertv(false);
254 }
255
256 /**
257 * Opens the file for writing. Returns a newly allocated iostream on success
258 * (which you should eventually delete when you are done writing). Returns
259 * NULL on failure.
260 */
261 iostream *VirtualFile::
262 open_read_write_file(bool truncate) {
263 return nullptr;
264 }
265
266 /**
267 * Works like open_read_write_file(), but the file is opened in append mode.
268 * Like open_read_write_file, the returned pointer should eventually be passed
269 * to close_read_write_file().
270 */
271 iostream *VirtualFile::
272 open_read_append_file() {
273 return nullptr;
274 }
275
276 /**
277 * Closes a file opened by a previous call to open_read_write_file(). This
278 * really just deletes the iostream pointer, but it is recommended to use this
279 * interface instead of deleting it explicitly, to help work around compiler
280 * issues.
281 */
282 void VirtualFile::
283 close_read_write_file(iostream *stream) {
284 nassertv(false);
285 }
286
287 /**
288 * Returns the current size on disk (or wherever it is) of the already-open
289 * file. Pass in the stream that was returned by open_read_file(); some
290 * implementations may require this stream to determine the size.
291 */
292 std::streamsize VirtualFile::
293 get_file_size(istream *stream) const {
294 return get_file_size();
295 }
296
297 /**
298 * Returns the current size on disk (or wherever it is) of the file before it
299 * has been opened.
300 */
301 std::streamsize VirtualFile::
302 get_file_size() const {
303 return 0;
304 }
305
306 /**
307 * Returns a time_t value that represents the time the file was last modified,
308 * to within whatever precision the operating system records this information
309 * (on a Windows95 system, for instance, this may only be accurate to within 2
310 * seconds).
311 *
312 * If the timestamp cannot be determined, either because it is not supported
313 * by the operating system or because there is some error (such as file not
314 * found), returns 0.
315 */
316 time_t VirtualFile::
317 get_timestamp() const {
318 return 0;
319 }
320
321 /**
322 * Populates the SubfileInfo structure with the data representing where the
323 * file actually resides on disk, if this is knowable. Returns true if the
324 * file might reside on disk, and the info is populated, or false if it does
325 * not (or it is not known where the file resides), in which case the info is
326 * meaningless.
327 */
328 bool VirtualFile::
329 get_system_info(SubfileInfo &info) {
330 return false;
331 }
332
333 /**
334 * See Filename::atomic_compare_and_exchange_contents().
335 */
336 bool VirtualFile::
337 atomic_compare_and_exchange_contents(string &orig_contents,
338 const string &old_contents,
339 const string &new_contents) {
340 return false;
341 }
342
343 /**
344 * See Filename::atomic_read_contents().
345 */
346 bool VirtualFile::
347 atomic_read_contents(string &contents) const {
348 return false;
349 }
350
351 /**
352 * Fills up the indicated string with the contents of the file, if it is a
353 * regular file. Returns true on success, false otherwise.
354 */
355 bool VirtualFile::
356 read_file(string &result, bool auto_unwrap) const {
357 result = string();
358
359 vector_uchar pv;
360 if (!read_file(pv, auto_unwrap)) {
361 return false;
362 }
363
364 if (!pv.empty()) {
365 result.append((const char *)&pv[0], pv.size());
366 }
367
368 return true;
369 }
370
371 /**
372 * Fills up the indicated pvector with the contents of the file, if it is a
373 * regular file. Returns true on success, false otherwise.
374 */
375 bool VirtualFile::
376 read_file(vector_uchar &result, bool auto_unwrap) const {
377 return false;
378 }
379
380 /**
381 * Writes the indicated data to the file, if it is writable. Returns true on
382 * success, false otherwise.
383 */
384 bool VirtualFile::
385 write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
386 return false;
387 }
388
389 /**
390 * Fills up the indicated pvector with the contents of the just-opened file.
391 * Returns true on success, false otherwise. If the pvector was not empty on
392 * entry, the data read from the file will be appended onto it.
393 */
394 bool VirtualFile::
395 simple_read_file(istream *in, vector_uchar &result) {
396 static const size_t buffer_size = 4096;
397 char buffer[buffer_size];
398
399 in->read(buffer, buffer_size);
400 size_t count = in->gcount();
401 while (count != 0) {
402 thread_consider_yield();
403 result.insert(result.end(), buffer, buffer + count);
404 in->read(buffer, buffer_size);
405 count = in->gcount();
406 }
407
408 return (!in->fail() || in->eof());
409 }
410
411 /**
412 * As in simple_read_file() with two parameters, above, but only reads up to
413 * max_bytes bytes from the file.
414 */
415 bool VirtualFile::
416 simple_read_file(istream *in, vector_uchar &result, size_t max_bytes) {
417 static const size_t buffer_size = 4096;
418 char buffer[buffer_size];
419
420 in->read(buffer, std::min(buffer_size, max_bytes));
421 size_t count = in->gcount();
422 while (count != 0) {
423 thread_consider_yield();
424 nassertr(count <= max_bytes, false);
425 result.insert(result.end(), buffer, buffer + count);
426 max_bytes -= count;
427 in->read(buffer, std::min(buffer_size, max_bytes));
428 count = in->gcount();
429 }
430
431 return (!in->fail() || in->eof());
432 }
433
434 /**
435 * Fills file_list up with the list of files that are within this directory,
436 * excluding those whose basenames are listed in mount_points. Returns true
437 * if successful, false if the file is not a directory or the directory cannot
438 * be read.
439 */
440 bool VirtualFile::
441 scan_local_directory(VirtualFileList *, const ov_set<string> &) const {
442 return false;
443 }
444
445 /**
446 * The recursive implementation of ls_all().
447 */
448 void VirtualFile::
449 r_ls_all(ostream &out, const Filename &root) const {
450 CPT(VirtualFileList) contents = scan_directory();
451 if (contents == nullptr) {
452 return;
453 }
454
455 int num_files = contents->get_num_files();
456 for (int i = 0; i < num_files; i++) {
457 VirtualFile *file = contents->get_file(i);
458 Filename filename = file->get_filename();
459 filename.make_relative_to(root);
460 out << filename << "\n";
461 if (file->is_directory()) {
462 file->r_ls_all(out, root);
463 }
464 }
465 }
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
Filename::get_basename
std::string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:367
Filename::make_relative_to
bool make_relative_to(Filename directory, bool allow_backups=true)
Adjusts this filename, which must be a fully-specified pathname beginning with a slash,...
Definition: filename.cxx:1640
SubfileInfo
This class records a particular byte sub-range within an existing file on disk.
Definition: subfileInfo.h:26
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
VirtualFileList
A list of VirtualFiles, as returned by VirtualFile::scan_directory().
Definition: virtualFileList.h:25
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
VirtualFileSystem::scan_mount_points
void scan_mount_points(vector_string &names, const Filename &path) const
Adds to names a list of all the mount points in use that are one directory below path,...
Definition: virtualFileSystem.cxx:1033
VirtualFileSystem::get_file
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
Definition: virtualFileSystem.cxx:515
VirtualFile
The abstract base class for a file or directory within the VirtualFileSystem.
Definition: virtualFile.h:35
VirtualFile::open_read_append_file
virtual std::iostream * open_read_append_file()
Works like open_read_write_file(), but the file is opened in append mode.
Definition: virtualFile.cxx:272
VirtualFile::close_read_file
virtual void close_read_file(std::istream *stream) const
Closes a file opened by a previous call to open_read_file().
Definition: virtualFile.cxx:209
VirtualFile::rename_file
virtual bool rename_file(VirtualFile *new_file)
Attempts to move or rename this file or directory.
Definition: virtualFile.cxx:85
VirtualFile::open_read_file
virtual std::istream * open_read_file(bool auto_unwrap) const
Opens the file for reading.
Definition: virtualFile.cxx:198
VirtualFile::is_regular_file
virtual bool is_regular_file() const
Returns true if this file represents a regular file (and read_file() may be called),...
Definition: virtualFile.cxx:50
VirtualFile::copy_file
virtual bool copy_file(VirtualFile *new_file)
Attempts to copy the contents of this file to the indicated file.
Definition: virtualFile.cxx:94
VirtualFile::get_system_info
virtual bool get_system_info(SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
Definition: virtualFile.cxx:329
VirtualFile::scan_directory
PointerTo< VirtualFileList > scan_directory() const
If the file represents a directory (that is, is_directory() returns true), this returns the list of f...
Definition: virtualFile.cxx:105
VirtualFile::delete_file
virtual bool delete_file()
Attempts to delete this file or directory.
Definition: virtualFile.cxx:69
VirtualFile::open_write_file
virtual std::ostream * open_write_file(bool auto_wrap, bool truncate)
Opens the file for writing.
Definition: virtualFile.cxx:231
VirtualFile::ls_all
void ls_all(std::ostream &out=std::cout) const
If the file represents a directory, recursively lists its contents and those of all subdirectories.
Definition: virtualFile.cxx:184
VirtualFile::simple_read_file
static bool simple_read_file(std::istream *stream, vector_uchar &result)
Fills up the indicated pvector with the contents of the just-opened file.
Definition: virtualFile.cxx:395
VirtualFile::is_writable
virtual bool is_writable() const
Returns true if this file may be written to, which implies write_file() may be called (unless it is a...
Definition: virtualFile.cxx:59
VirtualFile::has_file
virtual bool has_file() const
Returns true if this file exists, false otherwise.
Definition: virtualFile.cxx:32
VirtualFile::is_directory
virtual bool is_directory() const
Returns true if this file represents a directory (and scan_directory() may be called),...
Definition: virtualFile.cxx:41
VirtualFile::close_read_write_file
virtual void close_read_write_file(std::iostream *stream)
Closes a file opened by a previous call to open_read_write_file().
Definition: virtualFile.cxx:283
VirtualFile::atomic_read_contents
virtual bool atomic_read_contents(std::string &contents) const
See Filename::atomic_read_contents().
Definition: virtualFile.cxx:347
VirtualFile::was_read_successful
virtual bool was_read_successful() const
Call this method after a reading the istream returned by open_read_file() to completion.
Definition: virtualFile.cxx:221
VirtualFile::atomic_compare_and_exchange_contents
virtual bool atomic_compare_and_exchange_contents(std::string &orig_contents, const std::string &old_contents, const std::string &new_contents)
See Filename::atomic_compare_and_exchange_contents().
Definition: virtualFile.cxx:337
VirtualFile::read_file
std::string read_file(bool auto_unwrap) const
Returns the entire contents of the file as a string.
Definition: virtualFile.I:35
VirtualFile::ls
void ls(std::ostream &out=std::cout) const
If the file represents a directory, lists its contents.
Definition: virtualFile.cxx:161
VirtualFile::open_append_file
virtual std::ostream * open_append_file()
Works like open_write_file(), but the file is opened in append mode.
Definition: virtualFile.cxx:241
VirtualFile::get_timestamp
virtual time_t get_timestamp() const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
Definition: virtualFile.cxx:317
VirtualFile::open_read_write_file
virtual std::iostream * open_read_write_file(bool truncate)
Opens the file for writing.
Definition: virtualFile.cxx:262
VirtualFile::close_write_file
virtual void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
Definition: virtualFile.cxx:252
VirtualFile::write_file
bool write_file(const std::string &data, bool auto_wrap)
Writes the entire contents of the file as a string, if it is writable.
Definition: virtualFile.I:45
VirtualFile::get_file_size
virtual std::streamsize get_file_size() const
Returns the current size on disk (or wherever it is) of the file before it has been opened.
Definition: virtualFile.cxx:302
ordered_vector::begin
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
Definition: ordered_vector.I:41
ordered_vector::end
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
Definition: ordered_vector.I:50
ov_set
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
Definition: ordered_vector.h:269
ov_set::sort
void sort()
Maps to sort_unique().
Definition: ordered_vector.I:731
config_express.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pvector.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtualFileList.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtualFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.