00001 // Filename: virtualFile.cxx 00002 // Created by: drose (03Aug02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "virtualFile.h" 00020 #include "virtualFileSystem.h" 00021 #include "virtualFileList.h" 00022 #include "config_express.h" 00023 00024 TypeHandle VirtualFile::_type_handle; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: VirtualFile::is_directory 00028 // Access: Published, Virtual 00029 // Description: Returns true if this file represents a directory (and 00030 // scan_directory() may be called), false otherwise. 00031 //////////////////////////////////////////////////////////////////// 00032 bool VirtualFile:: 00033 is_directory() const { 00034 return false; 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: VirtualFile::is_regular_file 00039 // Access: Published, Virtual 00040 // Description: Returns true if this file represents a regular file 00041 // (and read_file() may be called), false otherwise. 00042 //////////////////////////////////////////////////////////////////// 00043 bool VirtualFile:: 00044 is_regular_file() const { 00045 return false; 00046 } 00047 00048 //////////////////////////////////////////////////////////////////// 00049 // Function: VirtualFile::scan_directory 00050 // Access: Published 00051 // Description: If the file represents a directory (that is, 00052 // is_directory() returns true), this returns the list 00053 // of files within the directory at the current time. 00054 // Returns NULL if the file is not a directory or if the 00055 // directory cannot be read. 00056 //////////////////////////////////////////////////////////////////// 00057 PT(VirtualFileList) VirtualFile:: 00058 scan_directory() const { 00059 // First, we have to make sure there aren't any mount points attached 00060 // under this directory. These will override any local filenames. 00061 VirtualFileSystem *file_system = get_file_system(); 00062 Filename this_filename = get_filename(); 00063 vector_string mount_points_flat; 00064 file_system->scan_mount_points(mount_points_flat, this_filename); 00065 00066 // Copy the set of nested mount points to a sorted list so we can 00067 // search it quickly. 00068 ov_set<string> mount_points; 00069 copy(mount_points_flat.begin(), mount_points_flat.end(), 00070 back_inserter(mount_points)); 00071 mount_points.sort(); 00072 00073 00074 PT(VirtualFileList) file_list = new VirtualFileList; 00075 00076 // Each of those mount points maps to a directory root or something 00077 // from the file system. 00078 ov_set<string>::const_iterator mi; 00079 for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) { 00080 const string &basename = (*mi); 00081 Filename filename(this_filename, basename); 00082 PT(VirtualFile) file = file_system->get_file(filename); 00083 file_list->add_file(file); 00084 } 00085 00086 // Now, get the actual local files in this directory. 00087 vector_string names; 00088 if (!scan_local_directory(file_list, mount_points)) { 00089 // Not a directory, or unable to read directory. 00090 if (file_list->get_num_files() == 0) { 00091 return NULL; 00092 } 00093 00094 // We couldn't read the physical directory, but we do have some 00095 // mounted files to return. 00096 return file_list; 00097 } 00098 00099 return file_list; 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: VirtualFile::output 00104 // Access: Published 00105 // Description: 00106 //////////////////////////////////////////////////////////////////// 00107 void VirtualFile:: 00108 output(ostream &out) const { 00109 out << get_filename(); 00110 } 00111 00112 //////////////////////////////////////////////////////////////////// 00113 // Function: VirtualFile::ls 00114 // Access: Published 00115 // Description: If the file represents a directory, lists its 00116 // contents. 00117 //////////////////////////////////////////////////////////////////// 00118 void VirtualFile:: 00119 ls(ostream &out) const { 00120 CPT(VirtualFileList) contents = scan_directory(); 00121 if (contents == (VirtualFileList *)NULL) { 00122 if (!is_directory()) { 00123 out << get_filename() << "\n"; 00124 } else { 00125 out << get_filename() << " cannot be read.\n"; 00126 } 00127 return; 00128 } 00129 00130 int num_files = contents->get_num_files(); 00131 for (int i = 0; i < num_files; i++) { 00132 VirtualFile *file = contents->get_file(i); 00133 out << file->get_filename().get_basename() << "\n"; 00134 } 00135 } 00136 00137 //////////////////////////////////////////////////////////////////// 00138 // Function: VirtualFile::ls_all 00139 // Access: Published 00140 // Description: If the file represents a directory, recursively lists 00141 // its contents and those of all subdirectories. 00142 //////////////////////////////////////////////////////////////////// 00143 void VirtualFile:: 00144 ls_all(ostream &out) const { 00145 if (!is_directory()) { 00146 out << get_filename() << " is not a directory.\n"; 00147 } else { 00148 r_ls_all(out, get_filename()); 00149 } 00150 } 00151 00152 //////////////////////////////////////////////////////////////////// 00153 // Function: VirtualFile::open_read_file 00154 // Access: Published, Virtual 00155 // Description: Opens the file for reading. Returns a newly 00156 // allocated istream on success (which you should 00157 // eventually delete when you are done reading). 00158 // Returns NULL on failure. 00159 //////////////////////////////////////////////////////////////////// 00160 istream *VirtualFile:: 00161 open_read_file() const { 00162 return NULL; 00163 } 00164 00165 //////////////////////////////////////////////////////////////////// 00166 // Function: VirtualFile::read_file 00167 // Access: Public 00168 // Description: Fills up the indicated string with the contents of 00169 // the file, if it is a regular file. Returns true on 00170 // success, false otherwise. 00171 //////////////////////////////////////////////////////////////////// 00172 bool VirtualFile:: 00173 read_file(string &result) const { 00174 result = string(); 00175 00176 istream *in = open_read_file(); 00177 if (in == (istream *)NULL) { 00178 express_cat.info() 00179 << "Unable to read " << get_filename() << "\n"; 00180 return false; 00181 } 00182 int byte = in->get(); 00183 while (!in->eof() && !in->fail()) { 00184 result += (char)byte; 00185 byte = in->get(); 00186 } 00187 bool failed = in->fail() && !in->eof(); 00188 delete in; 00189 00190 if (failed) { 00191 express_cat.info() 00192 << "Error while reading " << get_filename() << "\n"; 00193 } 00194 return !failed; 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: VirtualFile::scan_local_directory 00199 // Access: Protected, Virtual 00200 // Description: Fills file_list up with the list of files that are 00201 // within this directory, excluding those whose 00202 // basenames are listed in mount_points. Returns true 00203 // if successful, false if the file is not a directory 00204 // or the directory cannot be read. 00205 //////////////////////////////////////////////////////////////////// 00206 bool VirtualFile:: 00207 scan_local_directory(VirtualFileList *, const ov_set<string> &) const { 00208 return false; 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: VirtualFile::r_ls_all 00213 // Access: Private 00214 // Description: The recursive implementation of ls_all(). 00215 //////////////////////////////////////////////////////////////////// 00216 void VirtualFile:: 00217 r_ls_all(ostream &out, const Filename &root) const { 00218 CPT(VirtualFileList) contents = scan_directory(); 00219 if (contents == (VirtualFileList *)NULL) { 00220 return; 00221 } 00222 00223 int num_files = contents->get_num_files(); 00224 for (int i = 0; i < num_files; i++) { 00225 VirtualFile *file = contents->get_file(i); 00226 Filename filename = file->get_filename(); 00227 filename.make_relative_to(root); 00228 out << filename << "\n"; 00229 if (file->is_directory()) { 00230 file->r_ls_all(out, root); 00231 } 00232 } 00233 }