Panda3D
|
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 }