Panda3D
Loading...
Searching...
No Matches
virtualFileMountSystem.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 virtualFileMountSystem.cxx
10 * @author drose
11 * @date 2002-08-03
12 */
13
15#include "virtualFileSystem.h"
16
17using std::iostream;
18using std::istream;
19using std::ostream;
20using std::streampos;
21using std::streamsize;
22using std::string;
23
24TypeHandle VirtualFileMountSystem::_type_handle;
25
26
27/**
28 * Returns true if the indicated file exists within the mount system.
29 */
31has_file(const Filename &file) const {
32 Filename pathname(_physical_filename, file);
33#ifdef WIN32
34 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
35 Filename case_pathname = pathname;
36 if (!case_pathname.make_true_case()) {
37 return false;
38 }
39 if (case_pathname != pathname) {
40 express_cat.warning()
41 << "Filename is incorrect case: " << pathname
42 << " instead of " << case_pathname << "\n";
43 return false;
44 }
45 }
46#endif // WIN32
47 return pathname.exists();
48}
49
50/**
51 * Attempts to create the indicated file within the mount, if it does not
52 * already exist. Returns true on success (or if the file already exists), or
53 * false if it cannot be created.
54 */
56create_file(const Filename &file) {
57 Filename pathname(_physical_filename, file);
58 pathname.set_binary();
59 std::ofstream stream;
60 return pathname.open_write(stream, false);
61}
62
63/**
64 * Attempts to delete the indicated file or directory within the mount. This
65 * can remove a single file or an empty directory. It will not remove a
66 * nonempty directory. Returns true on success, false on failure.
67 */
69delete_file(const Filename &file) {
70 Filename pathname(_physical_filename, file);
71 return pathname.unlink() || pathname.rmdir();
72}
73
74/**
75 * Attempts to rename the contents of the indicated file to the indicated
76 * file. Both filenames will be within the mount. Returns true on success,
77 * false on failure. If this returns false, this will be attempted again with
78 * a copy-and-delete operation.
79 */
81rename_file(const Filename &orig_filename, const Filename &new_filename) {
82 Filename orig_pathname(_physical_filename, orig_filename);
83 Filename new_pathname(_physical_filename, new_filename);
84 return orig_pathname.rename_to(new_pathname);
85}
86
87/**
88 * Attempts to copy the contents of the indicated file to the indicated file.
89 * Both filenames will be within the mount. Returns true on success, false on
90 * failure. If this returns false, the copy will be performed by explicit
91 * read-and-write operations.
92 */
94copy_file(const Filename &orig_filename, const Filename &new_filename) {
95 Filename orig_pathname(_physical_filename, orig_filename);
96 Filename new_pathname(_physical_filename, new_filename);
97 return orig_pathname.copy_to(new_pathname);
98}
99
100/**
101 * Attempts to create the indicated file within the mount, if it does not
102 * already exist. Returns true on success, or false if it cannot be created.
103 * If the directory already existed prior to this call, may return either true
104 * or false.
105 */
107make_directory(const Filename &file) {
108 Filename pathname(_physical_filename, file);
109 return pathname.mkdir();
110}
111
112/**
113 * Returns true if the indicated file exists within the mount system and is a
114 * directory.
115 */
117is_directory(const Filename &file) const {
118#ifdef WIN32
119 // First ensure that the file exists to validate its case.
120 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
121 if (!has_file(file)) {
122 return false;
123 }
124 }
125#endif // WIN32
126 Filename pathname(_physical_filename, file);
127 return pathname.is_directory();
128}
129
130/**
131 * Returns true if the indicated file exists within the mount system and is a
132 * regular file.
133 */
135is_regular_file(const Filename &file) const {
136#ifdef WIN32
137 // First ensure that the file exists to validate its case.
138 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
139 if (!has_file(file)) {
140 return false;
141 }
142 }
143#endif // WIN32
144 Filename pathname(_physical_filename, file);
145 return pathname.is_regular_file();
146}
147
148/**
149 * Returns true if the named file or directory may be written to, false
150 * otherwise.
151 */
153is_writable(const Filename &file) const {
154#ifdef WIN32
155 // First ensure that the file exists to validate its case.
156 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
157 if (!has_file(file)) {
158 return false;
159 }
160 }
161#endif // WIN32
162 Filename pathname(_physical_filename, file);
163 return pathname.is_writable();
164}
165
166/**
167 * Opens the file for reading, if it exists. Returns a newly allocated
168 * istream on success (which you should eventually delete when you are done
169 * reading). Returns NULL on failure.
170 */
172open_read_file(const Filename &file) const {
173#ifdef WIN32
174 // First ensure that the file exists to validate its case.
175 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
176 if (!has_file(file)) {
177 return nullptr;
178 }
179 }
180#endif // WIN32
181 Filename pathname(_physical_filename, file);
182 pifstream *stream = new pifstream;
183 if (!pathname.open_read(*stream)) {
184 // Couldn't open the file for some reason.
185 close_read_file(stream);
186 return nullptr;
187 }
188
189 return stream;
190}
191
192/**
193 * Opens the file for writing. Returns a newly allocated ostream on success
194 * (which you should eventually delete when you are done writing). Returns
195 * NULL on failure.
196 */
198open_write_file(const Filename &file, bool truncate) {
199#ifdef WIN32
200 // First ensure that the file exists to validate its case.
201 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
202 if (!has_file(file)) {
203 return nullptr;
204 }
205 }
206#endif // WIN32
207 Filename pathname(_physical_filename, file);
208 pofstream *stream = new pofstream;
209 if (!pathname.open_write(*stream, truncate)) {
210 // Couldn't open the file for some reason.
211 close_write_file(stream);
212 return nullptr;
213 }
214
215 return stream;
216}
217
218/**
219 * Works like open_write_file(), but the file is opened in append mode. Like
220 * open_write_file, the returned pointer should eventually be passed to
221 * close_write_file().
222 */
224open_append_file(const Filename &file) {
225#ifdef WIN32
226 // First ensure that the file exists to validate its case.
227 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
228 if (!has_file(file)) {
229 return nullptr;
230 }
231 }
232#endif // WIN32
233 Filename pathname(_physical_filename, file);
234 pofstream *stream = new pofstream;
235 if (!pathname.open_append(*stream)) {
236 // Couldn't open the file for some reason.
237 close_write_file(stream);
238 return nullptr;
239 }
240
241 return stream;
242}
243
244/**
245 * Opens the file for writing. Returns a newly allocated iostream on success
246 * (which you should eventually delete when you are done writing). Returns
247 * NULL on failure.
248 */
250open_read_write_file(const Filename &file, bool truncate) {
251#ifdef WIN32
252 // First ensure that the file exists to validate its case.
253 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
254 if (!has_file(file)) {
255 return nullptr;
256 }
257 }
258#endif // WIN32
259 Filename pathname(_physical_filename, file);
260 pfstream *stream = new pfstream;
261 if (!pathname.open_read_write(*stream, truncate)) {
262 // Couldn't open the file for some reason.
263 close_read_write_file(stream);
264 return nullptr;
265 }
266
267 return stream;
268}
269
270/**
271 * Works like open_read_write_file(), but the file is opened in append mode.
272 * Like open_read_write_file, the returned pointer should eventually be passed
273 * to close_read_write_file().
274 */
276open_read_append_file(const Filename &file) {
277#ifdef WIN32
278 // First ensure that the file exists to validate its case.
279 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
280 if (!has_file(file)) {
281 return nullptr;
282 }
283 }
284#endif // WIN32
285 Filename pathname(_physical_filename, file);
286 pfstream *stream = new pfstream;
287 if (!pathname.open_read_append(*stream)) {
288 // Couldn't open the file for some reason.
289 close_read_write_file(stream);
290 return nullptr;
291 }
292
293 return stream;
294}
295
296/**
297 * Returns the current size on disk (or wherever it is) of the already-open
298 * file. Pass in the stream that was returned by open_read_file(); some
299 * implementations may require this stream to determine the size.
300 */
302get_file_size(const Filename &file, istream *stream) const {
303 // First, save the original stream position.
304 streampos orig = stream->tellg();
305
306 // Seek to the end and get the stream position there.
307 stream->seekg(0, std::ios::end);
308 if (stream->fail()) {
309 // Seeking not supported.
310 stream->clear();
311 return get_file_size(file);
312 }
313 streampos size = stream->tellg();
314
315 // Then return to the original point.
316 stream->seekg(orig, std::ios::beg);
317
318 // Make sure there are no error flags set as a result of the seek.
319 stream->clear();
320
321 return size;
322}
323
324/**
325 * Returns the current size on disk (or wherever it is) of the file before it
326 * has been opened.
327 */
329get_file_size(const Filename &file) const {
330 Filename pathname(_physical_filename, file);
331 return pathname.get_file_size();
332}
333
334/**
335 * Returns a time_t value that represents the time the file was last modified,
336 * to within whatever precision the operating system records this information
337 * (on a Windows95 system, for instance, this may only be accurate to within 2
338 * seconds).
339 *
340 * If the timestamp cannot be determined, either because it is not supported
341 * by the operating system or because there is some error (such as file not
342 * found), returns 0.
343 */
345get_timestamp(const Filename &file) const {
346 Filename pathname(_physical_filename, file);
347 return pathname.get_timestamp();
348}
349
350/**
351 * Populates the SubfileInfo structure with the data representing where the
352 * file actually resides on disk, if this is knowable. Returns true if the
353 * file might reside on disk, and the info is populated, or false if it does
354 * not (or it is not known where the file resides), in which case the info is
355 * meaningless.
356 */
358get_system_info(const Filename &file, SubfileInfo &info) {
359 Filename pathname(_physical_filename, file);
360 info = SubfileInfo(pathname, 0, pathname.get_file_size());
361 return true;
362}
363
364/**
365 * Fills the given vector up with the list of filenames that are local to this
366 * directory, if the filename is a directory. Returns true if successful, or
367 * false if the file is not a directory or cannot be read.
368 */
370scan_directory(vector_string &contents, const Filename &dir) const {
371#ifdef WIN32
372 // First ensure that the file exists to validate its case.
373 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
374 if (!has_file(dir)) {
375 return false;
376 }
377 }
378#endif // WIN32
379 Filename pathname(_physical_filename, dir);
380 return pathname.scan_directory(contents);
381}
382
383
384/**
385 * See Filename::atomic_compare_and_exchange_contents().
386 */
388atomic_compare_and_exchange_contents(const Filename &file, string &orig_contents,
389 const string &old_contents,
390 const string &new_contents) {
391#ifdef WIN32
392 // First ensure that the file exists to validate its case.
393 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
394 if (!has_file(file)) {
395 return false;
396 }
397 }
398#endif // WIN32
399 Filename pathname(_physical_filename, file);
400 return pathname.atomic_compare_and_exchange_contents(orig_contents, old_contents, new_contents);
401}
402
403/**
404 * See Filename::atomic_read_contents().
405 */
407atomic_read_contents(const Filename &file, string &contents) const {
408#ifdef WIN32
409 // First ensure that the file exists to validate its case.
410 if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
411 if (!has_file(file)) {
412 return false;
413 }
414 }
415#endif // WIN32
416 Filename pathname(_physical_filename, file);
417 return pathname.atomic_read_contents(contents);
418}
419
420/**
421 *
422 */
423void VirtualFileMountSystem::
424output(ostream &out) const {
425 out << get_physical_filename();
426}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
bool open_append(std::ofstream &stream) const
Opens the indicated ofstream for writing the file, if possible.
bool is_regular_file() const
Returns true if the filename exists on the physical disk and is the name of a regular file (i....
bool scan_directory(vector_string &contents) const
Attempts to open the named filename as if it were a directory and looks for the non-hidden files with...
bool copy_to(const Filename &other) const
Copies the file to the indicated new filename, by reading the contents and writing it to the new file...
bool open_read_append(std::fstream &stream) const
Opens the indicated ifstream for reading and writing the file, if possible; writes are appended to th...
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
bool rmdir() const
The inverse of mkdir(): this removes the directory named by this Filename, if it is in fact a directo...
bool rename_to(const Filename &other) const
Renames the file to the indicated new filename.
bool open_read_write(std::fstream &stream, bool truncate=false) const
Opens the indicated fstream for read/write access to the file, if possible.
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
bool is_writable() const
Returns true if the filename exists on the physical disk and is either a directory or a regular file ...
void set_binary()
Indicates that the filename represents a binary file.
Definition filename.I:414
bool make_true_case()
On a case-insensitive operating system (e.g.
time_t get_timestamp() const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
bool is_directory() const
Returns true if the filename exists on the physical disk and is a directory name, false otherwise.
bool atomic_compare_and_exchange_contents(std::string &orig_contents, const std::string &old_contents, const std::string &new_contents) const
Uses native file-locking mechanisms to atomically replace the contents of a (small) file with the spe...
bool atomic_read_contents(std::string &contents) const
Uses native file-locking mechanisms to atomically read the contents of a (small) file.
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
bool mkdir() const
Creates the directory named by this filename.
bool exists() const
Returns true if the filename exists on the physical disk, false otherwise.
std::streamsize get_file_size() const
Returns the size of the file in bytes, or 0 if there is an error.
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
virtual std::streamsize get_file_size(const Filename &file, std::istream *stream) const
Returns the current size on disk (or wherever it is) of the already-open file.
virtual bool make_directory(const Filename &file)
Attempts to create the indicated file within the mount, if it does not already exist.
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_write_file(const Filename &file, bool truncate)
Opens the file for writing.
virtual std::istream * open_read_file(const Filename &file) const
Opens the file for reading, if it exists.
virtual std::ostream * open_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.
virtual bool delete_file(const Filename &file)
Attempts to delete the indicated file or directory within the mount.
virtual bool scan_directory(vector_string &contents, const Filename &dir) const
Fills the given vector up with the list of filenames that are local to this directory,...
const Filename & get_physical_filename() const
Returns the name of the source file on the OS filesystem of the directory or file that is mounted.
virtual bool is_regular_file(const Filename &file) const
Returns true if the indicated file exists within the mount system and is a regular file.
virtual bool is_directory(const Filename &file) const
Returns true if the indicated file exists within the mount system and is a directory.
virtual bool create_file(const Filename &file)
Attempts to create the indicated file within the mount, if it does not already exist.
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 has_file(const Filename &file) const
Returns true if the indicated file exists within the mount system.
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 time_t get_timestamp(const Filename &file) const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
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 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 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 void close_read_file(std::istream *stream) const
Closes a file opened by a previous call to open_read_file().
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.