Panda3D
 All Classes Functions Variables Enumerations
virtualFileMountSystem.cxx
00001 // Filename: virtualFileMountSystem.cxx
00002 // Created by:  drose (03Aug02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "virtualFileMountSystem.h"
00016 
00017 TypeHandle VirtualFileMountSystem::_type_handle;
00018 
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: VirtualFileMountSystem::has_file
00022 //       Access: Public, Virtual
00023 //  Description: Returns true if the indicated file exists within the
00024 //               mount system.
00025 ////////////////////////////////////////////////////////////////////
00026 bool VirtualFileMountSystem::
00027 has_file(const Filename &file) const {
00028   Filename pathname(_physical_filename, file);
00029 #ifdef WIN32
00030   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00031     Filename case_pathname = pathname;
00032     if (!case_pathname.make_true_case()) {
00033       return false;
00034     }
00035     if (case_pathname != pathname) {
00036       express_cat.warning()
00037         << "Filename is incorrect case: " << pathname
00038         << " instead of " << case_pathname << "\n";
00039       return false;
00040     }
00041   }
00042 #endif  // WIN32
00043   return pathname.exists();
00044 }
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: VirtualFileMountSystem::create_file
00048 //       Access: Public, Virtual
00049 //  Description: Attempts to create the indicated file within the
00050 //               mount, if it does not already exist.  Returns true on
00051 //               success (or if the file already exists), or false if
00052 //               it cannot be created.
00053 ////////////////////////////////////////////////////////////////////
00054 bool VirtualFileMountSystem::
00055 create_file(const Filename &file) {
00056   Filename pathname(_physical_filename, file);
00057   pathname.set_binary();
00058   ofstream stream;
00059   return pathname.open_write(stream, false);
00060 }
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: VirtualFileMountSystem::delete_file
00064 //       Access: Public, Virtual
00065 //  Description: Attempts to delete the indicated file or directory
00066 //               within the mount.  This can remove a single file or
00067 //               an empty directory.  It will not remove a nonempty
00068 //               directory.  Returns true on success, false on
00069 //               failure.
00070 ////////////////////////////////////////////////////////////////////
00071 bool VirtualFileMountSystem::
00072 delete_file(const Filename &file) {
00073   Filename pathname(_physical_filename, file);
00074   return pathname.unlink() || pathname.rmdir();
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: VirtualFileMountSystem::rename_file
00079 //       Access: Public
00080 //  Description: Attempts to rename the contents of the indicated file
00081 //               to the indicated file.  Both filenames will be within
00082 //               the mount.  Returns true on success, false on
00083 //               failure.  If this returns false, this will be
00084 //               attempted again with a copy-and-delete operation.
00085 ////////////////////////////////////////////////////////////////////
00086 bool VirtualFileMountSystem::
00087 rename_file(const Filename &orig_filename, const Filename &new_filename) {
00088   Filename orig_pathname(_physical_filename, orig_filename);
00089   Filename new_pathname(_physical_filename, new_filename);
00090   return orig_pathname.rename_to(new_pathname);
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: VirtualFileMountSystem::copy_file
00095 //       Access: Public
00096 //  Description: Attempts to copy the contents of the indicated file
00097 //               to the indicated file.  Both filenames will be within
00098 //               the mount.  Returns true on success, false on
00099 //               failure.  If this returns false, the copy will be
00100 //               performed by explicit read-and-write operations.
00101 ////////////////////////////////////////////////////////////////////
00102 bool VirtualFileMountSystem::
00103 copy_file(const Filename &orig_filename, const Filename &new_filename) {
00104   Filename orig_pathname(_physical_filename, orig_filename);
00105   Filename new_pathname(_physical_filename, new_filename);
00106   return orig_pathname.copy_to(new_pathname);
00107 }
00108 
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: VirtualFileMountSystem::make_directory
00111 //       Access: Public, Virtual
00112 //  Description: Attempts to create the indicated file within the
00113 //               mount, if it does not already exist.  Returns true on
00114 //               success, or false if it cannot be created.  If the
00115 //               directory already existed prior to this call, may
00116 //               return either true or false.
00117 ////////////////////////////////////////////////////////////////////
00118 bool VirtualFileMountSystem::
00119 make_directory(const Filename &file) {
00120   Filename pathname(_physical_filename, file);
00121   return pathname.mkdir();
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: VirtualFileMountSystem::is_directory
00126 //       Access: Public, Virtual
00127 //  Description: Returns true if the indicated file exists within the
00128 //               mount system and is a directory.
00129 ////////////////////////////////////////////////////////////////////
00130 bool VirtualFileMountSystem::
00131 is_directory(const Filename &file) const {
00132 #ifdef WIN32
00133   // First ensure that the file exists to validate its case.
00134   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00135     if (!has_file(file)) {
00136       return false;
00137     }
00138   }
00139 #endif  // WIN32
00140   Filename pathname(_physical_filename, file);
00141   return pathname.is_directory();
00142 }
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: VirtualFileMountSystem::is_regular_file
00146 //       Access: Public, Virtual
00147 //  Description: Returns true if the indicated file exists within the
00148 //               mount system and is a regular file.
00149 ////////////////////////////////////////////////////////////////////
00150 bool VirtualFileMountSystem::
00151 is_regular_file(const Filename &file) const {
00152 #ifdef WIN32
00153   // First ensure that the file exists to validate its case.
00154   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00155     if (!has_file(file)) {
00156       return false;
00157     }
00158   }
00159 #endif  // WIN32
00160   Filename pathname(_physical_filename, file);
00161   return pathname.is_regular_file();
00162 }
00163 
00164 ////////////////////////////////////////////////////////////////////
00165 //     Function: VirtualFileMountSystem::is_writable
00166 //       Access: Public, Virtual
00167 //  Description: Returns true if the named file or directory may be
00168 //               written to, false otherwise.
00169 ////////////////////////////////////////////////////////////////////
00170 bool VirtualFileMountSystem::
00171 is_writable(const Filename &file) const {
00172 #ifdef WIN32
00173   // First ensure that the file exists to validate its case.
00174   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00175     if (!has_file(file)) {
00176       return false;
00177     }
00178   }
00179 #endif  // WIN32
00180   Filename pathname(_physical_filename, file);
00181   return pathname.is_writable();
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: VirtualFileMountSystem::open_read_file
00186 //       Access: Public, Virtual
00187 //  Description: Opens the file for reading, if it exists.  Returns a
00188 //               newly allocated istream on success (which you should
00189 //               eventually delete when you are done reading).
00190 //               Returns NULL on failure.
00191 ////////////////////////////////////////////////////////////////////
00192 istream *VirtualFileMountSystem::
00193 open_read_file(const Filename &file) const {
00194 #ifdef WIN32
00195   // First ensure that the file exists to validate its case.
00196   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00197     if (!has_file(file)) {
00198       return NULL;
00199     }
00200   }
00201 #endif  // WIN32
00202   Filename pathname(_physical_filename, file);
00203   pifstream *stream = new pifstream;
00204   if (!pathname.open_read(*stream)) {
00205     // Couldn't open the file for some reason.
00206     close_read_file(stream);
00207     return NULL;
00208   }
00209 
00210   return stream;
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: VirtualFileMountSystem::open_write_file
00215 //       Access: Published, Virtual
00216 //  Description: Opens the file for writing.  Returns a newly
00217 //               allocated ostream on success (which you should
00218 //               eventually delete when you are done writing).
00219 //               Returns NULL on failure.
00220 ////////////////////////////////////////////////////////////////////
00221 ostream *VirtualFileMountSystem::
00222 open_write_file(const Filename &file, bool truncate) {
00223 #ifdef WIN32
00224   // First ensure that the file exists to validate its case.
00225   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00226     if (!has_file(file)) {
00227       return NULL;
00228     }
00229   }
00230 #endif  // WIN32
00231   Filename pathname(_physical_filename, file);
00232   pofstream *stream = new pofstream;
00233   if (!pathname.open_write(*stream, truncate)) {
00234     // Couldn't open the file for some reason.
00235     close_write_file(stream);
00236     return NULL;
00237   }
00238 
00239   return stream;
00240 }
00241 
00242 ////////////////////////////////////////////////////////////////////
00243 //     Function: VirtualFileMountSystem::open_append_file
00244 //       Access: Published
00245 //  Description: Works like open_write_file(), but the file is opened
00246 //               in append mode.  Like open_write_file, the returned
00247 //               pointer should eventually be passed to
00248 //               close_write_file().
00249 ////////////////////////////////////////////////////////////////////
00250 ostream *VirtualFileMountSystem::
00251 open_append_file(const Filename &file) {
00252 #ifdef WIN32
00253   // First ensure that the file exists to validate its case.
00254   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00255     if (!has_file(file)) {
00256       return NULL;
00257     }
00258   }
00259 #endif  // WIN32
00260   Filename pathname(_physical_filename, file);
00261   pofstream *stream = new pofstream;
00262   if (!pathname.open_append(*stream)) {
00263     // Couldn't open the file for some reason.
00264     close_write_file(stream);
00265     return NULL;
00266   }
00267 
00268   return stream;
00269 }
00270 
00271 ////////////////////////////////////////////////////////////////////
00272 //     Function: VirtualFileMountSystem::open_read_write_file
00273 //       Access: Published, Virtual
00274 //  Description: Opens the file for writing.  Returns a newly
00275 //               allocated iostream on success (which you should
00276 //               eventually delete when you are done writing).
00277 //               Returns NULL on failure.
00278 ////////////////////////////////////////////////////////////////////
00279 iostream *VirtualFileMountSystem::
00280 open_read_write_file(const Filename &file, bool truncate) {
00281 #ifdef WIN32
00282   // First ensure that the file exists to validate its case.
00283   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00284     if (!has_file(file)) {
00285       return NULL;
00286     }
00287   }
00288 #endif  // WIN32
00289   Filename pathname(_physical_filename, file);
00290   pfstream *stream = new pfstream;
00291   if (!pathname.open_read_write(*stream, truncate)) {
00292     // Couldn't open the file for some reason.
00293     close_read_write_file(stream);
00294     return NULL;
00295   }
00296 
00297   return stream;
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: VirtualFileMountSystem::open_read_append_file
00302 //       Access: Published, Virtual
00303 //  Description: Works like open_read_write_file(), but the file is opened
00304 //               in append mode.  Like open_read_write_file, the returned
00305 //               pointer should eventually be passed to
00306 //               close_read_write_file().
00307 ////////////////////////////////////////////////////////////////////
00308 iostream *VirtualFileMountSystem::
00309 open_read_append_file(const Filename &file) {
00310 #ifdef WIN32
00311   // First ensure that the file exists to validate its case.
00312   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00313     if (!has_file(file)) {
00314       return NULL;
00315     }
00316   }
00317 #endif  // WIN32
00318   Filename pathname(_physical_filename, file);
00319   pfstream *stream = new pfstream;
00320   if (!pathname.open_read_append(*stream)) {
00321     // Couldn't open the file for some reason.
00322     close_read_write_file(stream);
00323     return NULL;
00324   }
00325 
00326   return stream;
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: VirtualFileMountSystem::get_file_size
00331 //       Access: Published, Virtual
00332 //  Description: Returns the current size on disk (or wherever it is)
00333 //               of the already-open file.  Pass in the stream that
00334 //               was returned by open_read_file(); some
00335 //               implementations may require this stream to determine
00336 //               the size.
00337 ////////////////////////////////////////////////////////////////////
00338 off_t VirtualFileMountSystem::
00339 get_file_size(const Filename &file, istream *stream) const {
00340   // First, save the original stream position.
00341   streampos orig = stream->tellg();
00342 
00343   // Seek to the end and get the stream position there.
00344   stream->seekg(0, ios::end);
00345   if (stream->fail()) {
00346     // Seeking not supported.
00347     stream->clear();
00348     return get_file_size(file);
00349   }
00350   streampos size = stream->tellg();
00351 
00352   // Then return to the original point.
00353   stream->seekg(orig, ios::beg);
00354 
00355   // Make sure there are no error flags set as a result of the seek.
00356   stream->clear();
00357 
00358   return size;
00359 }
00360 
00361 ////////////////////////////////////////////////////////////////////
00362 //     Function: VirtualFileMountSystem::get_file_size
00363 //       Access: Published, Virtual
00364 //  Description: Returns the current size on disk (or wherever it is)
00365 //               of the file before it has been opened.
00366 ////////////////////////////////////////////////////////////////////
00367 off_t VirtualFileMountSystem::
00368 get_file_size(const Filename &file) const {
00369   Filename pathname(_physical_filename, file);
00370   return pathname.get_file_size();
00371 }
00372 
00373 ////////////////////////////////////////////////////////////////////
00374 //     Function: VirtualFileMountSystem::get_timestamp
00375 //       Access: Published, Virtual
00376 //  Description: Returns a time_t value that represents the time the
00377 //               file was last modified, to within whatever precision
00378 //               the operating system records this information (on a
00379 //               Windows95 system, for instance, this may only be
00380 //               accurate to within 2 seconds).
00381 //
00382 //               If the timestamp cannot be determined, either because
00383 //               it is not supported by the operating system or
00384 //               because there is some error (such as file not found),
00385 //               returns 0.
00386 ////////////////////////////////////////////////////////////////////
00387 time_t VirtualFileMountSystem::
00388 get_timestamp(const Filename &file) const {
00389   Filename pathname(_physical_filename, file);
00390   return pathname.get_timestamp();
00391 }
00392 
00393 ////////////////////////////////////////////////////////////////////
00394 //     Function: VirtualFileMountSystem::get_system_info
00395 //       Access: Public, Virtual
00396 //  Description: Populates the SubfileInfo structure with the data
00397 //               representing where the file actually resides on disk,
00398 //               if this is knowable.  Returns true if the file might
00399 //               reside on disk, and the info is populated, or false
00400 //               if it does not (or it is not known where the file
00401 //               resides), in which case the info is meaningless.
00402 ////////////////////////////////////////////////////////////////////
00403 bool VirtualFileMountSystem::
00404 get_system_info(const Filename &file, SubfileInfo &info) {
00405   Filename pathname(_physical_filename, file);
00406   info = SubfileInfo(pathname, 0, pathname.get_file_size());
00407   return true;
00408 }
00409 
00410 ////////////////////////////////////////////////////////////////////
00411 //     Function: VirtualFileMountSystem::scan_directory
00412 //       Access: Public, Virtual
00413 //  Description: Fills the given vector up with the list of filenames
00414 //               that are local to this directory, if the filename is
00415 //               a directory.  Returns true if successful, or false if
00416 //               the file is not a directory or cannot be read.
00417 ////////////////////////////////////////////////////////////////////
00418 bool VirtualFileMountSystem::
00419 scan_directory(vector_string &contents, const Filename &dir) const {
00420 #ifdef WIN32
00421   // First ensure that the file exists to validate its case.
00422   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00423     if (!has_file(dir)) {
00424       return false;
00425     }
00426   }
00427 #endif  // WIN32
00428   Filename pathname(_physical_filename, dir);
00429   return pathname.scan_directory(contents);
00430 }
00431 
00432 
00433 ////////////////////////////////////////////////////////////////////
00434 //     Function: VirtualFileMountSystem::atomic_compare_and_exchange_contents
00435 //       Access: Public, Virtual
00436 //  Description: See Filename::atomic_compare_and_exchange_contents().
00437 ////////////////////////////////////////////////////////////////////
00438 bool VirtualFileMountSystem::
00439 atomic_compare_and_exchange_contents(const Filename &file, string &orig_contents,
00440                                      const string &old_contents, 
00441                                      const string &new_contents) {
00442 #ifdef WIN32
00443   // First ensure that the file exists to validate its case.
00444   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00445     if (!has_file(file)) {
00446       return NULL;
00447     }
00448   }
00449 #endif  // WIN32
00450   Filename pathname(_physical_filename, file);
00451   return pathname.atomic_compare_and_exchange_contents(orig_contents, old_contents, new_contents);
00452 }
00453 
00454 ////////////////////////////////////////////////////////////////////
00455 //     Function: VirtualFileMountSystem::atomic_read_contents
00456 //       Access: Public, Virtual
00457 //  Description: See Filename::atomic_read_contents().
00458 ////////////////////////////////////////////////////////////////////
00459 bool VirtualFileMountSystem::
00460 atomic_read_contents(const Filename &file, string &contents) const {
00461 #ifdef WIN32
00462   // First ensure that the file exists to validate its case.
00463   if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
00464     if (!has_file(file)) {
00465       return NULL;
00466     }
00467   }
00468 #endif  // WIN32
00469   Filename pathname(_physical_filename, file);
00470   return pathname.atomic_read_contents(contents);
00471 }
00472 
00473 ////////////////////////////////////////////////////////////////////
00474 //     Function: VirtualFileMountSystem::output
00475 //       Access: Public, Virtual
00476 //  Description: 
00477 ////////////////////////////////////////////////////////////////////
00478 void VirtualFileMountSystem::
00479 output(ostream &out) const {
00480   out << get_physical_filename();
00481 }
 All Classes Functions Variables Enumerations