Panda3D
Loading...
Searching...
No Matches
virtualFileSimple.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 virtualFileSimple.cxx
10 * @author drose
11 * @date 2002-08-03
12 */
13
14#include "virtualFileSimple.h"
15#include "virtualFileMount.h"
16#include "virtualFileList.h"
17#include "dcast.h"
18
19using std::iostream;
20using std::istream;
21using std::ostream;
22using std::string;
23
24TypeHandle VirtualFileSimple::_type_handle;
25
26
27/**
28 * Returns the VirtualFileSystem this file is associated with.
29 */
34
35/**
36 * Returns the full pathname to this file within the virtual file system.
37 */
39get_filename() const {
40 string mount_point = _mount->get_mount_point();
41 if (_local_filename.empty()) {
42 if (mount_point.empty()) {
43 return "/";
44 } else {
45 return string("/") + mount_point;
46 }
47
48 } else {
49 if (mount_point.empty()) {
50 return string("/") + _local_filename.get_fullpath();
51 } else {
52 return string("/") + mount_point + string("/") + _local_filename.get_fullpath();
53 }
54 }
55}
56
57/**
58 * Returns true if this file exists, false otherwise.
59 */
61has_file() const {
62 return _mount->has_file(_local_filename);
63}
64
65/**
66 * Returns true if this file represents a directory (and scan_directory() may
67 * be called), false otherwise.
68 */
70is_directory() const {
71 return _mount->is_directory(_local_filename);
72}
73
74/**
75 * Returns true if this file represents a regular file (and read_file() may be
76 * called), false otherwise.
77 */
79is_regular_file() const {
80 return _mount->is_regular_file(_local_filename);
81}
82
83/**
84 * Returns true if this file represents a writable regular file (and
85 * write_file() may be called), false otherwise.
86 */
88is_writable() const {
89 return _mount->is_writable(_local_filename);
90}
91
92/**
93 * Attempts to delete this file or directory. This can remove a single file
94 * or an empty directory. It will not remove a nonempty directory. Returns
95 * true on success, false on failure.
96 */
99 return _mount->delete_file(_local_filename);
100}
101
102/**
103 * Attempts to move or rename this file or directory. If the original file is
104 * an ordinary file, it will quietly replace any already-existing file in the
105 * new filename (but not a directory). If the original file is a directory,
106 * the new filename must not already exist.
107 *
108 * If the file is a directory, the new filename must be within the same mount
109 * point. If the file is an ordinary file, the new filename may be anywhere;
110 * but if it is not within the same mount point then the rename operation is
111 * automatically performed as a two-step copy-and-delete operation.
112 */
114rename_file(VirtualFile *new_file) {
115 if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
116 VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
117 if (new_file_simple->_mount == _mount) {
118 // Same mount pount.
119 if (_mount->rename_file(_local_filename, new_file_simple->_local_filename)) {
120 return true;
121 }
122 }
123 }
124
125 // Different mount point, or the mount doesn't support renaming. Do it by
126 // hand.
127 if (is_regular_file() && !new_file->is_directory()) {
128 // copy-and-delete.
129 new_file->delete_file();
130 if (copy_file(new_file)) {
131 delete_file();
132 return true;
133 }
134 }
135
136 return false;
137}
138
139/**
140 * Attempts to copy the contents of this file to the indicated file. Returns
141 * true on success, false on failure.
142 */
144copy_file(VirtualFile *new_file) {
145 if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
146 VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
147 if (new_file_simple->_mount == _mount) {
148 // Same mount pount.
149 if (_mount->copy_file(_local_filename, new_file_simple->_local_filename)) {
150 return true;
151 }
152 }
153 }
154
155 // Different mount point, or the mount doesn't support copying. Do it by
156 // hand.
157 ostream *out = new_file->open_write_file(false, true);
158 if (out == nullptr) {
159 return false;
160 }
161
162 istream *in = open_read_file(false);
163 if (in == nullptr) {
164 new_file->close_write_file(out);
165 new_file->delete_file();
166 return false;
167 }
168
169 static const size_t buffer_size = 4096;
170 char buffer[buffer_size];
171
172 in->read(buffer, buffer_size);
173 size_t count = in->gcount();
174 while (count != 0) {
175 out->write(buffer, count);
176 if (out->fail()) {
177 new_file->close_write_file(out);
178 close_read_file(in);
179 new_file->delete_file();
180 return false;
181 }
182 in->read(buffer, buffer_size);
183 count = in->gcount();
184 }
185
186 if (!in->eof()) {
187 new_file->close_write_file(out);
188 close_read_file(in);
189 new_file->delete_file();
190 return false;
191 }
192
193 new_file->close_write_file(out);
194 close_read_file(in);
195 return true;
196}
197
198/**
199 * Opens the file for reading. Returns a newly allocated istream on success
200 * (which you should eventually delete when you are done reading). Returns
201 * NULL on failure.
202 *
203 * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
204 * decompressed and the decompressed contents are returned. This is different
205 * than vfs-implicit-pz, which will automatically decompress a file if the
206 * extension .pz is *not* given.
207 */
209open_read_file(bool auto_unwrap) const {
210
211 // Will we be automatically unwrapping a .pz file?
212 bool do_uncompress = (_implicit_pz_file ||
213 (auto_unwrap && (_local_filename.get_extension() == "pz" ||
214 _local_filename.get_extension() == "gz")));
215
216 Filename local_filename(_local_filename);
217 if (do_uncompress) {
218 // .pz files are always binary, of course.
219 local_filename.set_binary();
220 }
221
222 return _mount->open_read_file(local_filename, do_uncompress);
223}
224
225/**
226 * Closes a file opened by a previous call to open_read_file(). This really
227 * just deletes the istream pointer, but it is recommended to use this
228 * interface instead of deleting it explicitly, to help work around compiler
229 * issues.
230 */
232close_read_file(istream *stream) const {
233 _mount->close_read_file(stream);
234}
235
236/**
237 * Opens the file for writing. Returns a newly allocated ostream on success
238 * (which you should eventually delete when you are done writing). Returns
239 * NULL on failure.
240 *
241 * If auto_wrap is true, an explicitly-named .pz file is automatically
242 * compressed while writing. If truncate is true, the file is truncated to
243 * zero length before writing.
244 */
246open_write_file(bool auto_wrap, bool truncate) {
247 // Will we be automatically wrapping a .pz file?
248 bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));
249
250 Filename local_filename(_local_filename);
251 if (do_compress) {
252 // .pz files are always binary, of course.
253 local_filename.set_binary();
254 }
255
256 return _mount->open_write_file(local_filename, do_compress, truncate);
257}
258
259/**
260 * Works like open_write_file(), but the file is opened in append mode. Like
261 * open_write_file, the returned pointer should eventually be passed to
262 * close_write_file().
263 */
266 return _mount->open_append_file(_local_filename);
267}
268
269/**
270 * Closes a file opened by a previous call to open_write_file(). This really
271 * just deletes the ostream pointer, but it is recommended to use this
272 * interface instead of deleting it explicitly, to help work around compiler
273 * issues.
274 */
276close_write_file(ostream *stream) {
277 _mount->close_write_file(stream);
278}
279
280/**
281 * Opens the file for writing. Returns a newly allocated iostream on success
282 * (which you should eventually delete when you are done writing). Returns
283 * NULL on failure.
284 */
286open_read_write_file(bool truncate) {
287 return _mount->open_read_write_file(_local_filename, truncate);
288}
289
290/**
291 * Works like open_read_write_file(), but the file is opened in append mode.
292 * Like open_read_write_file, the returned pointer should eventually be passed
293 * to close_read_write_file().
294 */
297 return _mount->open_read_append_file(_local_filename);
298}
299
300/**
301 * Closes a file opened by a previous call to open_read_write_file(). This
302 * really just deletes the iostream pointer, but it is recommended to use this
303 * interface instead of deleting it explicitly, to help work around compiler
304 * issues.
305 */
307close_read_write_file(iostream *stream) {
308 _mount->close_read_write_file(stream);
309}
310
311/**
312 * Returns the current size on disk (or wherever it is) of the already-open
313 * file. Pass in the stream that was returned by open_read_file(); some
314 * implementations may require this stream to determine the size.
315 */
316std::streamsize VirtualFileSimple::
317get_file_size(istream *stream) const {
318 return _mount->get_file_size(_local_filename, stream);
319}
320
321/**
322 * Returns the current size on disk (or wherever it is) of the file before it
323 * has been opened.
324 */
325std::streamsize VirtualFileSimple::
326get_file_size() const {
327 return _mount->get_file_size(_local_filename);
328}
329
330/**
331 * Returns a time_t value that represents the time the file was last modified,
332 * to within whatever precision the operating system records this information
333 * (on a Windows95 system, for instance, this may only be accurate to within 2
334 * seconds).
335 *
336 * If the timestamp cannot be determined, either because it is not supported
337 * by the operating system or because there is some error (such as file not
338 * found), returns 0.
339 */
341get_timestamp() const {
342 return _mount->get_timestamp(_local_filename);
343}
344
345/**
346 * Populates the SubfileInfo structure with the data representing where the
347 * file actually resides on disk, if this is knowable. Returns true if the
348 * file might reside on disk, and the info is populated, or false if it does
349 * not (or it is not known where the file resides), in which case the info is
350 * meaningless.
351 */
354 return _mount->get_system_info(_local_filename, info);
355}
356
357/**
358 * See Filename::atomic_compare_and_exchange_contents().
359 */
361atomic_compare_and_exchange_contents(string &orig_contents,
362 const string &old_contents,
363 const string &new_contents) {
364 return _mount->atomic_compare_and_exchange_contents(_local_filename, orig_contents, old_contents, new_contents);
365}
366
367/**
368 * See Filename::atomic_read_contents().
369 */
371atomic_read_contents(string &contents) const {
372 return _mount->atomic_read_contents(_local_filename, contents);
373}
374
375/**
376 * Fills up the indicated pvector with the contents of the file, if it is a
377 * regular file. Returns true on success, false otherwise.
378 */
380read_file(vector_uchar &result, bool auto_unwrap) const {
381
382 // Will we be automatically unwrapping a .pz file?
383 bool do_uncompress = (_implicit_pz_file ||
384 (auto_unwrap && (_local_filename.get_extension() == "pz" ||
385 _local_filename.get_extension() == "gz")));
386
387 Filename local_filename(_local_filename);
388 if (do_uncompress) {
389 // .pz files are always binary, of course.
390 local_filename.set_binary();
391 }
392
393 return _mount->read_file(local_filename, do_uncompress, result);
394}
395
396/**
397 * Writes the indicated data to the file, if it is writable. Returns true on
398 * success, false otherwise.
399 */
401write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
402 // Will we be automatically wrapping a .pz file?
403 bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));
404
405 Filename local_filename(_local_filename);
406 if (do_compress) {
407 // .pz files are always binary, of course.
408 local_filename.set_binary();
409 }
410
411 return _mount->write_file(local_filename, do_compress, data, data_size);
412}
413
414/**
415 * Fills file_list up with the list of files that are within this directory,
416 * excluding those whose basenames are listed in mount_points. Returns true
417 * if successful, false if the file is not a directory or the directory cannot
418 * be read.
419 */
420bool VirtualFileSimple::
421scan_local_directory(VirtualFileList *file_list,
422 const ov_set<string> &mount_points) const {
423 vector_string names;
424 if (!_mount->scan_directory(names, _local_filename)) {
425 return false;
426 }
427
428 // Now the scan above gave us a list of basenames. Turn these back into
429 // VirtualFile pointers.
430
431 // Each of the files returned by the mount will be just a simple file within
432 // the same mount tree, unless it is shadowed by a mount point listed in
433 // mount_points.
434
435 vector_string::const_iterator ni;
436 for (ni = names.begin(); ni != names.end(); ++ni) {
437 const string &basename = (*ni);
438 if (mount_points.find(basename) == mount_points.end()) {
439 Filename filename(_local_filename, basename);
440 VirtualFileSimple *file = new VirtualFileSimple(_mount, filename, false, 0);
441 file_list->add_file(file);
442 }
443 }
444
445 return true;
446}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
void set_binary()
Indicates that the filename represents a binary file.
Definition filename.I:414
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
Definition filename.I:338
std::string get_extension() const
Returns the file extension.
Definition filename.I:400
This class records a particular byte sub-range within an existing file on disk.
Definition subfileInfo.h:26
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
A list of VirtualFiles, as returned by VirtualFile::scan_directory().
void add_file(VirtualFile *file)
Adds a new file to the list.
virtual std::iostream * open_read_write_file(const Filename &file, bool truncate)
Opens the file for writing.
virtual bool atomic_read_contents(const Filename &file, std::string &contents) const
See Filename::atomic_read_contents().
virtual bool is_writable(const Filename &file) const
Returns true if the named file or directory may be written to, false otherwise.
const Filename & get_mount_point() const
Returns the name of the directory within the virtual file system that this mount object is attached t...
virtual bool delete_file(const Filename &file)
Attempts to delete the indicated file or directory within the mount.
virtual bool read_file(const Filename &file, bool do_uncompress, vector_uchar &result) const
Fills up the indicated pvector with the contents of the file, if it is a regular file.
virtual void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
virtual void close_read_write_file(std::iostream *stream)
Closes a file opened by a previous call to open_read_write_file().
virtual bool copy_file(const Filename &orig_filename, const Filename &new_filename)
Attempts to copy the contents of the indicated file to the indicated file.
virtual bool write_file(const Filename &file, bool do_compress, const unsigned char *data, size_t data_size)
Writes the indicated data to the file, if it is a writable file.
VirtualFileSystem * get_file_system() const
Returns the file system this mount object is attached to.
virtual std::ostream * open_write_file(const Filename &file, bool truncate)
Opens the file for writing.
virtual std::ostream * open_append_file(const Filename &file)
Works like open_write_file(), but the file is opened in append mode.
virtual bool get_system_info(const Filename &file, SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
virtual bool atomic_compare_and_exchange_contents(const Filename &file, std::string &orig_contents, const std::string &old_contents, const std::string &new_contents)
See Filename::atomic_compare_and_exchange_contents().
virtual std::iostream * open_read_append_file(const Filename &file)
Works like open_read_write_file(), but the file is opened in append mode.
virtual bool rename_file(const Filename &orig_filename, const Filename &new_filename)
Attempts to rename the contents of the indicated file to the indicated file.
virtual void close_read_file(std::istream *stream) const
Closes a file opened by a previous call to open_read_file().
A simple file or directory within the VirtualFileSystem: this maps to exactly one file on one mount p...
virtual bool read_file(vector_uchar &result, bool auto_unwrap) const
Fills up the indicated pvector with the contents of the file, if it is a regular file.
virtual std::ostream * open_append_file()
Works like open_write_file(), but the file is opened in append mode.
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().
virtual bool atomic_read_contents(std::string &contents) const
See Filename::atomic_read_contents().
virtual bool get_system_info(SubfileInfo &info)
Populates the SubfileInfo structure with the data representing where the file actually resides on dis...
virtual bool is_regular_file() const
Returns true if this file represents a regular file (and read_file() may be called),...
virtual bool has_file() const
Returns true if this file exists, false otherwise.
virtual std::ostream * open_write_file(bool auto_wrap, bool truncate)
Opens the file for writing.
virtual VirtualFileSystem * get_file_system() const
Returns the VirtualFileSystem this file is associated with.
virtual bool delete_file()
Attempts to delete this file or directory.
virtual bool write_file(const unsigned char *data, size_t data_size, bool auto_wrap)
Writes the indicated data to the file, if it is writable.
virtual bool copy_file(VirtualFile *new_file)
Attempts to copy the contents of this file to the indicated file.
virtual std::iostream * open_read_write_file(bool truncate)
Opens the file for writing.
virtual std::istream * open_read_file(bool auto_unwrap) const
Opens the file for reading.
virtual time_t get_timestamp() const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
virtual std::iostream * open_read_append_file()
Works like open_read_write_file(), but the file is opened in append mode.
virtual void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
virtual void close_read_file(std::istream *stream) const
Closes a file opened by a previous call to open_read_file().
virtual bool rename_file(VirtualFile *new_file)
Attempts to move or rename this file or directory.
virtual bool is_directory() const
Returns true if this file represents a directory (and scan_directory() may be called),...
virtual bool is_writable() const
Returns true if this file represents a writable regular file (and write_file() may be called),...
virtual void close_read_write_file(std::iostream *stream)
Closes a file opened by a previous call to open_read_write_file().
virtual Filename get_filename() const
Returns the full pathname to this file within the virtual file system.
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.
A hierarchy of directories and files that appears to be one continuous file system,...
The abstract base class for a file or directory within the VirtualFileSystem.
Definition virtualFile.h:35
virtual bool delete_file()
Attempts to delete this file or directory.
virtual std::ostream * open_write_file(bool auto_wrap, bool truncate)
Opens the file for writing.
virtual bool is_directory() const
Returns true if this file represents a directory (and scan_directory() may be called),...
virtual void close_write_file(std::ostream *stream)
Closes a file opened by a previous call to open_write_file().
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
A specialization of ordered_vector that emulates a standard STL set: one copy of each element is allo...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.