Panda3D
|
00001 // Filename: virtualFile.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 "virtualFile.h" 00016 #include "virtualFileSystem.h" 00017 #include "virtualFileList.h" 00018 #include "config_express.h" 00019 #include "pvector.h" 00020 #include <iterator> 00021 00022 TypeHandle VirtualFile::_type_handle; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: VirtualFile::has_file 00026 // Access: Published, Virtual 00027 // Description: Returns true if this file exists, false otherwise. 00028 //////////////////////////////////////////////////////////////////// 00029 bool VirtualFile:: 00030 has_file() const { 00031 return false; 00032 } 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: VirtualFile::is_directory 00036 // Access: Published, Virtual 00037 // Description: Returns true if this file represents a directory (and 00038 // scan_directory() may be called), false otherwise. 00039 //////////////////////////////////////////////////////////////////// 00040 bool VirtualFile:: 00041 is_directory() const { 00042 return false; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: VirtualFile::is_regular_file 00047 // Access: Published, Virtual 00048 // Description: Returns true if this file represents a regular file 00049 // (and read_file() may be called), false otherwise. 00050 //////////////////////////////////////////////////////////////////// 00051 bool VirtualFile:: 00052 is_regular_file() const { 00053 return false; 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: VirtualFile::is_writable 00058 // Access: Published, Virtual 00059 // Description: Returns true if this file may be written to, which 00060 // implies write_file() may be called (unless it is a 00061 // directory instead of a regular file). 00062 //////////////////////////////////////////////////////////////////// 00063 bool VirtualFile:: 00064 is_writable() const { 00065 return false; 00066 } 00067 00068 //////////////////////////////////////////////////////////////////// 00069 // Function: VirtualFile::delete_file 00070 // Access: Public 00071 // Description: Attempts to delete this file or directory. This can 00072 // remove a single file or an empty directory. It will 00073 // not remove a nonempty directory. Returns true on 00074 // success, false on failure. 00075 //////////////////////////////////////////////////////////////////// 00076 bool VirtualFile:: 00077 delete_file() { 00078 return false; 00079 } 00080 00081 //////////////////////////////////////////////////////////////////// 00082 // Function: VirtualFile::rename_file 00083 // Access: Public 00084 // Description: Attempts to move or rename this file or directory. 00085 // If the original file is an ordinary file, it will 00086 // quietly replace any already-existing file in the new 00087 // filename (but not a directory). If the original file 00088 // is a directory, the new filename must not already 00089 // exist. 00090 // 00091 // If the file is a directory, the new filename must be 00092 // within the same mount point. If the file is an 00093 // ordinary file, the new filename may be anywhere; but 00094 // if it is not within the same mount point then the 00095 // rename operation is automatically performed as a 00096 // two-step copy-and-delete operation. 00097 //////////////////////////////////////////////////////////////////// 00098 bool VirtualFile:: 00099 rename_file(VirtualFile *new_file) { 00100 return false; 00101 } 00102 00103 //////////////////////////////////////////////////////////////////// 00104 // Function: VirtualFile::copy_file 00105 // Access: Public 00106 // Description: Attempts to copy the contents of this file to the 00107 // indicated file. Returns true on success, false on 00108 // failure. 00109 //////////////////////////////////////////////////////////////////// 00110 bool VirtualFile:: 00111 copy_file(VirtualFile *new_file) { 00112 return false; 00113 } 00114 00115 //////////////////////////////////////////////////////////////////// 00116 // Function: VirtualFile::scan_directory 00117 // Access: Published 00118 // Description: If the file represents a directory (that is, 00119 // is_directory() returns true), this returns the list 00120 // of files within the directory at the current time. 00121 // Returns NULL if the file is not a directory or if the 00122 // directory cannot be read. 00123 //////////////////////////////////////////////////////////////////// 00124 PT(VirtualFileList) VirtualFile:: 00125 scan_directory() const { 00126 // First, we have to make sure there aren't any mount points attached 00127 // under this directory. These will override any local filenames. 00128 VirtualFileSystem *file_system = get_file_system(); 00129 Filename this_filename = get_filename(); 00130 vector_string mount_points_flat; 00131 file_system->scan_mount_points(mount_points_flat, this_filename); 00132 00133 // Copy the set of nested mount points to a sorted list so we can 00134 // search it quickly. 00135 ov_set<string> mount_points; 00136 copy(mount_points_flat.begin(), mount_points_flat.end(), 00137 back_inserter(mount_points)); 00138 mount_points.sort(); 00139 00140 00141 PT(VirtualFileList) file_list = new VirtualFileList; 00142 00143 // Each of those mount points maps to a directory root or something 00144 // from the file system. 00145 ov_set<string>::const_iterator mi; 00146 for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) { 00147 const string &basename = (*mi); 00148 Filename filename(this_filename, basename); 00149 PT(VirtualFile) file = file_system->get_file(filename); 00150 file_list->add_file(file); 00151 } 00152 00153 // Now, get the actual local files in this directory. 00154 vector_string names; 00155 if (!scan_local_directory(file_list, mount_points)) { 00156 // Not a directory, or unable to read directory. 00157 if (file_list->get_num_files() == 0) { 00158 return NULL; 00159 } 00160 00161 // We couldn't read the physical directory, but we do have some 00162 // mounted files to return. 00163 return file_list; 00164 } 00165 00166 return file_list; 00167 } 00168 00169 //////////////////////////////////////////////////////////////////// 00170 // Function: VirtualFile::output 00171 // Access: Published 00172 // Description: 00173 //////////////////////////////////////////////////////////////////// 00174 void VirtualFile:: 00175 output(ostream &out) const { 00176 out << get_filename(); 00177 } 00178 00179 //////////////////////////////////////////////////////////////////// 00180 // Function: VirtualFile::ls 00181 // Access: Published 00182 // Description: If the file represents a directory, lists its 00183 // contents. 00184 //////////////////////////////////////////////////////////////////// 00185 void VirtualFile:: 00186 ls(ostream &out) const { 00187 CPT(VirtualFileList) contents = scan_directory(); 00188 if (contents == (VirtualFileList *)NULL) { 00189 if (!is_directory()) { 00190 out << get_filename() << "\n"; 00191 } else { 00192 out << get_filename() << " cannot be read.\n"; 00193 } 00194 return; 00195 } 00196 00197 int num_files = contents->get_num_files(); 00198 for (int i = 0; i < num_files; i++) { 00199 VirtualFile *file = contents->get_file(i); 00200 out << file->get_filename().get_basename() << "\n"; 00201 } 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: VirtualFile::ls_all 00206 // Access: Published 00207 // Description: If the file represents a directory, recursively lists 00208 // its contents and those of all subdirectories. 00209 //////////////////////////////////////////////////////////////////// 00210 void VirtualFile:: 00211 ls_all(ostream &out) const { 00212 if (!is_directory()) { 00213 out << get_filename() << " is not a directory.\n"; 00214 } else { 00215 r_ls_all(out, get_filename()); 00216 } 00217 } 00218 00219 //////////////////////////////////////////////////////////////////// 00220 // Function: VirtualFile::open_read_file 00221 // Access: Published, Virtual 00222 // Description: Opens the file for reading. Returns a newly 00223 // allocated istream on success (which you should 00224 // eventually delete when you are done reading). 00225 // Returns NULL on failure. 00226 //////////////////////////////////////////////////////////////////// 00227 istream *VirtualFile:: 00228 open_read_file(bool auto_unwrap) const { 00229 return NULL; 00230 } 00231 00232 //////////////////////////////////////////////////////////////////// 00233 // Function: VirtualFile::close_read_file 00234 // Access: Published 00235 // Description: Closes a file opened by a previous call to 00236 // open_read_file(). This really just deletes the 00237 // istream pointer, but it is recommended to use this 00238 // interface instead of deleting it explicitly, to help 00239 // work around compiler issues. 00240 //////////////////////////////////////////////////////////////////// 00241 void VirtualFile:: 00242 close_read_file(istream *stream) const { 00243 nassertv(false); 00244 } 00245 00246 //////////////////////////////////////////////////////////////////// 00247 // Function: VirtualFile::was_read_successful 00248 // Access: Published, Virtual 00249 // Description: Call this method after a reading the istream returned 00250 // by open_read_file() to completion. If it returns 00251 // true, the file was read completely and without error; 00252 // if it returns false, there may have been some errors 00253 // or a truncated file read. This is particularly 00254 // likely if the stream is a VirtualFileHTTP. 00255 //////////////////////////////////////////////////////////////////// 00256 bool VirtualFile:: 00257 was_read_successful() const { 00258 return true; 00259 } 00260 00261 //////////////////////////////////////////////////////////////////// 00262 // Function: VirtualFile::open_write_file 00263 // Access: Published, Virtual 00264 // Description: Opens the file for writing. Returns a newly 00265 // allocated ostream on success (which you should 00266 // eventually delete when you are done writing). 00267 // Returns NULL on failure. 00268 //////////////////////////////////////////////////////////////////// 00269 ostream *VirtualFile:: 00270 open_write_file(bool auto_wrap, bool truncate) { 00271 return NULL; 00272 } 00273 00274 //////////////////////////////////////////////////////////////////// 00275 // Function: VirtualFile::open_append_file 00276 // Access: Published, Virtual 00277 // Description: Works like open_write_file(), but the file is opened 00278 // in append mode. Like open_write_file, the returned 00279 // pointer should eventually be passed to 00280 // close_write_file(). 00281 //////////////////////////////////////////////////////////////////// 00282 ostream *VirtualFile:: 00283 open_append_file() { 00284 return NULL; 00285 } 00286 00287 //////////////////////////////////////////////////////////////////// 00288 // Function: VirtualFile::close_write_file 00289 // Access: Published 00290 // Description: Closes a file opened by a previous call to 00291 // open_write_file(). This really just deletes the 00292 // ostream pointer, but it is recommended to use this 00293 // interface instead of deleting it explicitly, to help 00294 // work around compiler issues. 00295 //////////////////////////////////////////////////////////////////// 00296 void VirtualFile:: 00297 close_write_file(ostream *stream) { 00298 nassertv(false); 00299 } 00300 00301 //////////////////////////////////////////////////////////////////// 00302 // Function: VirtualFile::open_read_write_file 00303 // Access: Published, Virtual 00304 // Description: Opens the file for writing. Returns a newly 00305 // allocated iostream on success (which you should 00306 // eventually delete when you are done writing). 00307 // Returns NULL on failure. 00308 //////////////////////////////////////////////////////////////////// 00309 iostream *VirtualFile:: 00310 open_read_write_file(bool truncate) { 00311 return NULL; 00312 } 00313 00314 //////////////////////////////////////////////////////////////////// 00315 // Function: VirtualFile::open_read_append_file 00316 // Access: Published, Virtual 00317 // Description: Works like open_read_write_file(), but the file is opened 00318 // in append mode. Like open_read_write_file, the returned 00319 // pointer should eventually be passed to 00320 // close_read_write_file(). 00321 //////////////////////////////////////////////////////////////////// 00322 iostream *VirtualFile:: 00323 open_read_append_file() { 00324 return NULL; 00325 } 00326 00327 //////////////////////////////////////////////////////////////////// 00328 // Function: VirtualFile::close_read_write_file 00329 // Access: Published 00330 // Description: Closes a file opened by a previous call to 00331 // open_read_write_file(). This really just deletes the 00332 // iostream pointer, but it is recommended to use this 00333 // interface instead of deleting it explicitly, to help 00334 // work around compiler issues. 00335 //////////////////////////////////////////////////////////////////// 00336 void VirtualFile:: 00337 close_read_write_file(iostream *stream) { 00338 nassertv(false); 00339 } 00340 00341 //////////////////////////////////////////////////////////////////// 00342 // Function: VirtualFile::get_file_size 00343 // Access: Published, Virtual 00344 // Description: Returns the current size on disk (or wherever it is) 00345 // of the already-open file. Pass in the stream that 00346 // was returned by open_read_file(); some 00347 // implementations may require this stream to determine 00348 // the size. 00349 //////////////////////////////////////////////////////////////////// 00350 off_t VirtualFile:: 00351 get_file_size(istream *stream) const { 00352 return get_file_size(); 00353 } 00354 00355 //////////////////////////////////////////////////////////////////// 00356 // Function: VirtualFile::get_file_size 00357 // Access: Published, Virtual 00358 // Description: Returns the current size on disk (or wherever it is) 00359 // of the file before it has been opened. 00360 //////////////////////////////////////////////////////////////////// 00361 off_t VirtualFile:: 00362 get_file_size() const { 00363 return 0; 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: VirtualFile::get_timestamp 00368 // Access: Published, Virtual 00369 // Description: Returns a time_t value that represents the time the 00370 // file was last modified, to within whatever precision 00371 // the operating system records this information (on a 00372 // Windows95 system, for instance, this may only be 00373 // accurate to within 2 seconds). 00374 // 00375 // If the timestamp cannot be determined, either because 00376 // it is not supported by the operating system or 00377 // because there is some error (such as file not found), 00378 // returns 0. 00379 //////////////////////////////////////////////////////////////////// 00380 time_t VirtualFile:: 00381 get_timestamp() const { 00382 return 0; 00383 } 00384 00385 //////////////////////////////////////////////////////////////////// 00386 // Function: VirtualFile::get_system_info 00387 // Access: Published, Virtual 00388 // Description: Populates the SubfileInfo structure with the data 00389 // representing where the file actually resides on disk, 00390 // if this is knowable. Returns true if the file might 00391 // reside on disk, and the info is populated, or false 00392 // if it does not (or it is not known where the file 00393 // resides), in which case the info is meaningless. 00394 //////////////////////////////////////////////////////////////////// 00395 bool VirtualFile:: 00396 get_system_info(SubfileInfo &info) { 00397 return false; 00398 } 00399 00400 //////////////////////////////////////////////////////////////////// 00401 // Function: VirtualFile::atomic_compare_and_exchange_contents 00402 // Access: Public, Virtual 00403 // Description: See Filename::atomic_compare_and_exchange_contents(). 00404 //////////////////////////////////////////////////////////////////// 00405 bool VirtualFile:: 00406 atomic_compare_and_exchange_contents(string &orig_contents, 00407 const string &old_contents, 00408 const string &new_contents) { 00409 return false; 00410 } 00411 00412 //////////////////////////////////////////////////////////////////// 00413 // Function: VirtualFile::atomic_read_contents 00414 // Access: Public, Virtual 00415 // Description: See Filename::atomic_read_contents(). 00416 //////////////////////////////////////////////////////////////////// 00417 bool VirtualFile:: 00418 atomic_read_contents(string &contents) const { 00419 return false; 00420 } 00421 00422 //////////////////////////////////////////////////////////////////// 00423 // Function: VirtualFile::read_file 00424 // Access: Public 00425 // Description: Fills up the indicated string with the contents of 00426 // the file, if it is a regular file. Returns true on 00427 // success, false otherwise. 00428 //////////////////////////////////////////////////////////////////// 00429 bool VirtualFile:: 00430 read_file(string &result, bool auto_unwrap) const { 00431 result = string(); 00432 00433 pvector<unsigned char> pv; 00434 if (!read_file(pv, auto_unwrap)) { 00435 return false; 00436 } 00437 00438 if (!pv.empty()) { 00439 result.append((const char *)&pv[0], pv.size()); 00440 } 00441 00442 return true; 00443 } 00444 00445 //////////////////////////////////////////////////////////////////// 00446 // Function: VirtualFile::read_file 00447 // Access: Public, Virtual 00448 // Description: Fills up the indicated pvector with the contents of 00449 // the file, if it is a regular file. Returns true on 00450 // success, false otherwise. 00451 //////////////////////////////////////////////////////////////////// 00452 bool VirtualFile:: 00453 read_file(pvector<unsigned char> &result, bool auto_unwrap) const { 00454 return false; 00455 } 00456 00457 //////////////////////////////////////////////////////////////////// 00458 // Function: VirtualFile::write_file 00459 // Access: Public, Virtual 00460 // Description: Writes the indicated data to the file, if it is 00461 // writable. Returns true on success, false otherwise. 00462 //////////////////////////////////////////////////////////////////// 00463 bool VirtualFile:: 00464 write_file(const unsigned char *data, size_t data_size, bool auto_wrap) { 00465 return false; 00466 } 00467 00468 //////////////////////////////////////////////////////////////////// 00469 // Function: VirtualFile::simple_read_file 00470 // Access: Public, Static 00471 // Description: Fills up the indicated pvector with the contents of 00472 // the just-opened file. Returns true on success, false 00473 // otherwise. If the pvector was not empty on entry, the 00474 // data read from the file will be appended onto it. 00475 //////////////////////////////////////////////////////////////////// 00476 bool VirtualFile:: 00477 simple_read_file(istream *in, pvector<unsigned char> &result) { 00478 static const size_t buffer_size = 4096; 00479 char buffer[buffer_size]; 00480 00481 in->read(buffer, buffer_size); 00482 size_t count = in->gcount(); 00483 while (count != 0) { 00484 thread_consider_yield(); 00485 result.insert(result.end(), buffer, buffer + count); 00486 in->read(buffer, buffer_size); 00487 count = in->gcount(); 00488 } 00489 00490 return (!in->fail() || in->eof()); 00491 } 00492 00493 //////////////////////////////////////////////////////////////////// 00494 // Function: VirtualFile::simple_read_file 00495 // Access: Public 00496 // Description: As in simple_read_file() with two parameters, above, 00497 // but only reads up to max_bytes bytes from the file. 00498 //////////////////////////////////////////////////////////////////// 00499 bool VirtualFile:: 00500 simple_read_file(istream *in, pvector<unsigned char> &result, size_t max_bytes) { 00501 static const size_t buffer_size = 4096; 00502 char buffer[buffer_size]; 00503 00504 in->read(buffer, min(buffer_size, max_bytes)); 00505 size_t count = in->gcount(); 00506 while (count != 0) { 00507 thread_consider_yield(); 00508 nassertr(count <= max_bytes, false); 00509 result.insert(result.end(), buffer, buffer + count); 00510 max_bytes -= count; 00511 in->read(buffer, min(buffer_size, max_bytes)); 00512 count = in->gcount(); 00513 } 00514 00515 return (!in->fail() || in->eof()); 00516 } 00517 00518 //////////////////////////////////////////////////////////////////// 00519 // Function: VirtualFile::scan_local_directory 00520 // Access: Protected, Virtual 00521 // Description: Fills file_list up with the list of files that are 00522 // within this directory, excluding those whose 00523 // basenames are listed in mount_points. Returns true 00524 // if successful, false if the file is not a directory 00525 // or the directory cannot be read. 00526 //////////////////////////////////////////////////////////////////// 00527 bool VirtualFile:: 00528 scan_local_directory(VirtualFileList *, const ov_set<string> &) const { 00529 return false; 00530 } 00531 00532 //////////////////////////////////////////////////////////////////// 00533 // Function: VirtualFile::r_ls_all 00534 // Access: Private 00535 // Description: The recursive implementation of ls_all(). 00536 //////////////////////////////////////////////////////////////////// 00537 void VirtualFile:: 00538 r_ls_all(ostream &out, const Filename &root) const { 00539 CPT(VirtualFileList) contents = scan_directory(); 00540 if (contents == (VirtualFileList *)NULL) { 00541 return; 00542 } 00543 00544 int num_files = contents->get_num_files(); 00545 for (int i = 0; i < num_files; i++) { 00546 VirtualFile *file = contents->get_file(i); 00547 Filename filename = file->get_filename(); 00548 filename.make_relative_to(root); 00549 out << filename << "\n"; 00550 if (file->is_directory()) { 00551 file->r_ls_all(out, root); 00552 } 00553 } 00554 }