00001 // Filename: virtualFileMountMultifile.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 "virtualFileMountMultifile.h" 00016 #include "virtualFileSystem.h" 00017 00018 TypeHandle VirtualFileMountMultifile::_type_handle; 00019 00020 00021 //////////////////////////////////////////////////////////////////// 00022 // Function: VirtualFileMountMultifile::Destructor 00023 // Access: Public, Virtual 00024 // Description: 00025 //////////////////////////////////////////////////////////////////// 00026 VirtualFileMountMultifile:: 00027 ~VirtualFileMountMultifile() { 00028 } 00029 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: VirtualFileMountMultifile::has_file 00033 // Access: Public, Virtual 00034 // Description: Returns true if the indicated file exists within the 00035 // mount system. 00036 //////////////////////////////////////////////////////////////////// 00037 bool VirtualFileMountMultifile:: 00038 has_file(const Filename &file) const { 00039 return (file.empty() || 00040 _multifile->find_subfile(file) >= 0 || 00041 _multifile->has_directory(file)); 00042 } 00043 00044 //////////////////////////////////////////////////////////////////// 00045 // Function: VirtualFileMountMultifile::is_directory 00046 // Access: Public, Virtual 00047 // Description: Returns true if the indicated file exists within the 00048 // mount system and is a directory. 00049 //////////////////////////////////////////////////////////////////// 00050 bool VirtualFileMountMultifile:: 00051 is_directory(const Filename &file) const { 00052 return (file.empty() || _multifile->has_directory(file)); 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: VirtualFileMountMultifile::is_regular_file 00057 // Access: Public, Virtual 00058 // Description: Returns true if the indicated file exists within the 00059 // mount system and is a regular file. 00060 //////////////////////////////////////////////////////////////////// 00061 bool VirtualFileMountMultifile:: 00062 is_regular_file(const Filename &file) const { 00063 return (_multifile->find_subfile(file) >= 0); 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: VirtualFileMountMultifile::read_file 00068 // Access: Public, Virtual 00069 // Description: Fills up the indicated pvector with the contents of 00070 // the file, if it is a regular file. Returns true on 00071 // success, false otherwise. 00072 //////////////////////////////////////////////////////////////////// 00073 bool VirtualFileMountMultifile:: 00074 read_file(const Filename &file, bool do_uncompress, 00075 pvector<unsigned char> &result) const { 00076 if (do_uncompress) { 00077 // If the file is to be decompressed, we'd better just use the 00078 // higher-level implementation, which includes support for 00079 // on-the-fly decompression. 00080 return VirtualFileMount::read_file(file, do_uncompress, result); 00081 } 00082 00083 // But if we're just reading a straight file, let the Multifile do 00084 // the reading, which avoids a few levels of buffer copies. 00085 00086 int subfile_index = _multifile->find_subfile(file); 00087 if (subfile_index < 0) { 00088 express_cat.info() 00089 << "Unable to read " << file << "\n"; 00090 return false; 00091 } 00092 00093 return _multifile->read_subfile(subfile_index, result); 00094 } 00095 00096 //////////////////////////////////////////////////////////////////// 00097 // Function: VirtualFileMountMultifile::open_read_file 00098 // Access: Public, Virtual 00099 // Description: Opens the file for reading, if it exists. Returns a 00100 // newly allocated istream on success (which you should 00101 // eventually delete when you are done reading). 00102 // Returns NULL on failure. 00103 //////////////////////////////////////////////////////////////////// 00104 istream *VirtualFileMountMultifile:: 00105 open_read_file(const Filename &file) const { 00106 int subfile_index = _multifile->find_subfile(file); 00107 if (subfile_index < 0) { 00108 return NULL; 00109 } 00110 00111 // The caller will eventually pass this pointer to 00112 // VirtualFileSystem::close_read_file(), not to 00113 // Multifile::close_read_subfile(). Fortunately, these two methods 00114 // do the same thing, so that doesn't matter. 00115 return _multifile->open_read_subfile(subfile_index); 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: VirtualFileMountMultifile::get_file_size 00120 // Access: Published, Virtual 00121 // Description: Returns the current size on disk (or wherever it is) 00122 // of the already-open file. Pass in the stream that 00123 // was returned by open_read_file(); some 00124 // implementations may require this stream to determine 00125 // the size. 00126 //////////////////////////////////////////////////////////////////// 00127 off_t VirtualFileMountMultifile:: 00128 get_file_size(const Filename &file, istream *) const { 00129 int subfile_index = _multifile->find_subfile(file); 00130 if (subfile_index < 0) { 00131 return 0; 00132 } 00133 return _multifile->get_subfile_length(subfile_index); 00134 } 00135 00136 //////////////////////////////////////////////////////////////////// 00137 // Function: VirtualFileMountMultifile::get_file_size 00138 // Access: Published, Virtual 00139 // Description: Returns the current size on disk (or wherever it is) 00140 // of the file before it has been opened. 00141 //////////////////////////////////////////////////////////////////// 00142 off_t VirtualFileMountMultifile:: 00143 get_file_size(const Filename &file) const { 00144 int subfile_index = _multifile->find_subfile(file); 00145 if (subfile_index < 0) { 00146 return 0; 00147 } 00148 return _multifile->get_subfile_length(subfile_index); 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: VirtualFileMountMultifile::get_timestamp 00153 // Access: Published, Virtual 00154 // Description: Returns a time_t value that represents the time the 00155 // file was last modified, to within whatever precision 00156 // the operating system records this information (on a 00157 // Windows95 system, for instance, this may only be 00158 // accurate to within 2 seconds). 00159 // 00160 // If the timestamp cannot be determined, either because 00161 // it is not supported by the operating system or 00162 // because there is some error (such as file not found), 00163 // returns 0. 00164 //////////////////////////////////////////////////////////////////// 00165 time_t VirtualFileMountMultifile:: 00166 get_timestamp(const Filename &file) const { 00167 int subfile_index = _multifile->find_subfile(file); 00168 if (subfile_index < 0) { 00169 return 0; 00170 } 00171 return _multifile->get_subfile_timestamp(subfile_index); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: VirtualFileMountMultifile::get_system_info 00176 // Access: Public, Virtual 00177 // Description: Populates the SubfileInfo structure with the data 00178 // representing where the file actually resides on disk, 00179 // if this is knowable. Returns true if the file might 00180 // reside on disk, and the info is populated, or false 00181 // if it might not (or it is not known where the file 00182 // resides), in which case the info is meaningless. 00183 //////////////////////////////////////////////////////////////////// 00184 bool VirtualFileMountMultifile:: 00185 get_system_info(const Filename &file, SubfileInfo &info) { 00186 Filename multifile_name = _multifile->get_multifile_name(); 00187 if (multifile_name.empty()) { 00188 return false; 00189 } 00190 int subfile_index = _multifile->find_subfile(file); 00191 if (subfile_index < 0) { 00192 return false; 00193 } 00194 if (_multifile->is_subfile_compressed(subfile_index) || 00195 _multifile->is_subfile_encrypted(subfile_index)) { 00196 return false; 00197 } 00198 00199 streampos start = _multifile->get_subfile_internal_start(subfile_index); 00200 size_t length = _multifile->get_subfile_internal_length(subfile_index); 00201 00202 info = SubfileInfo(multifile_name, start, length); 00203 return true; 00204 } 00205 00206 //////////////////////////////////////////////////////////////////// 00207 // Function: VirtualFileMountMultifile::scan_directory 00208 // Access: Public, Virtual 00209 // Description: Fills the given vector up with the list of filenames 00210 // that are local to this directory, if the filename is 00211 // a directory. Returns true if successful, or false if 00212 // the file is not a directory or cannot be read. 00213 //////////////////////////////////////////////////////////////////// 00214 bool VirtualFileMountMultifile:: 00215 scan_directory(vector_string &contents, const Filename &dir) const { 00216 return _multifile->scan_directory(contents, dir); 00217 } 00218 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: VirtualFileMountMultifile::output 00222 // Access: Public, Virtual 00223 // Description: 00224 //////////////////////////////////////////////////////////////////// 00225 void VirtualFileMountMultifile:: 00226 output(ostream &out) const { 00227 out << _multifile->get_multifile_name(); 00228 }