virtualFile.cxx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // Filename: virtualFile.cxx
  2. // Created by: drose (03Aug02)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "virtualFile.h"
  15. #include "virtualFileSystem.h"
  16. #include "virtualFileList.h"
  17. #include "config_express.h"
  18. #include "pvector.h"
  19. #include <iterator>
  20. TypeHandle VirtualFile::_type_handle;
  21. ////////////////////////////////////////////////////////////////////
  22. // Function: VirtualFile::has_file
  23. // Access: Published, Virtual
  24. // Description: Returns true if this file exists, false otherwise.
  25. ////////////////////////////////////////////////////////////////////
  26. bool VirtualFile::
  27. has_file() const {
  28. return false;
  29. }
  30. ////////////////////////////////////////////////////////////////////
  31. // Function: VirtualFile::is_directory
  32. // Access: Published, Virtual
  33. // Description: Returns true if this file represents a directory (and
  34. // scan_directory() may be called), false otherwise.
  35. ////////////////////////////////////////////////////////////////////
  36. bool VirtualFile::
  37. is_directory() const {
  38. return false;
  39. }
  40. ////////////////////////////////////////////////////////////////////
  41. // Function: VirtualFile::is_regular_file
  42. // Access: Published, Virtual
  43. // Description: Returns true if this file represents a regular file
  44. // (and read_file() may be called), false otherwise.
  45. ////////////////////////////////////////////////////////////////////
  46. bool VirtualFile::
  47. is_regular_file() const {
  48. return false;
  49. }
  50. ////////////////////////////////////////////////////////////////////
  51. // Function: VirtualFile::is_writable
  52. // Access: Published, Virtual
  53. // Description: Returns true if this file may be written to, which
  54. // implies write_file() may be called (unless it is a
  55. // directory instead of a regular file).
  56. ////////////////////////////////////////////////////////////////////
  57. bool VirtualFile::
  58. is_writable() const {
  59. return false;
  60. }
  61. ////////////////////////////////////////////////////////////////////
  62. // Function: VirtualFile::delete_file
  63. // Access: Public
  64. // Description: Attempts to delete this file or directory. This can
  65. // remove a single file or an empty directory. It will
  66. // not remove a nonempty directory. Returns true on
  67. // success, false on failure.
  68. ////////////////////////////////////////////////////////////////////
  69. bool VirtualFile::
  70. delete_file() {
  71. return false;
  72. }
  73. ////////////////////////////////////////////////////////////////////
  74. // Function: VirtualFile::rename_file
  75. // Access: Public
  76. // Description: Attempts to move or rename this file or directory.
  77. // If the original file is an ordinary file, it will
  78. // quietly replace any already-existing file in the new
  79. // filename (but not a directory). If the original file
  80. // is a directory, the new filename must not already
  81. // exist.
  82. //
  83. // If the file is a directory, the new filename must be
  84. // within the same mount point. If the file is an
  85. // ordinary file, the new filename may be anywhere; but
  86. // if it is not within the same mount point then the
  87. // rename operation is automatically performed as a
  88. // two-step copy-and-delete operation.
  89. ////////////////////////////////////////////////////////////////////
  90. bool VirtualFile::
  91. rename_file(VirtualFile *new_file) {
  92. return false;
  93. }
  94. ////////////////////////////////////////////////////////////////////
  95. // Function: VirtualFile::copy_file
  96. // Access: Public
  97. // Description: Attempts to copy the contents of this file to the
  98. // indicated file. Returns true on success, false on
  99. // failure.
  100. ////////////////////////////////////////////////////////////////////
  101. bool VirtualFile::
  102. copy_file(VirtualFile *new_file) {
  103. return false;
  104. }
  105. ////////////////////////////////////////////////////////////////////
  106. // Function: VirtualFile::scan_directory
  107. // Access: Published
  108. // Description: If the file represents a directory (that is,
  109. // is_directory() returns true), this returns the list
  110. // of files within the directory at the current time.
  111. // Returns NULL if the file is not a directory or if the
  112. // directory cannot be read.
  113. ////////////////////////////////////////////////////////////////////
  114. PT(VirtualFileList) VirtualFile::
  115. scan_directory() const {
  116. // First, we have to make sure there aren't any mount points attached
  117. // under this directory. These will override any local filenames.
  118. VirtualFileSystem *file_system = get_file_system();
  119. Filename this_filename = get_filename();
  120. vector_string mount_points_flat;
  121. file_system->scan_mount_points(mount_points_flat, this_filename);
  122. // Copy the set of nested mount points to a sorted list so we can
  123. // search it quickly.
  124. ov_set<string> mount_points;
  125. copy(mount_points_flat.begin(), mount_points_flat.end(),
  126. back_inserter(mount_points));
  127. mount_points.sort();
  128. PT(VirtualFileList) file_list = new VirtualFileList;
  129. // Each of those mount points maps to a directory root or something
  130. // from the file system.
  131. ov_set<string>::const_iterator mi;
  132. for (mi = mount_points.begin(); mi != mount_points.end(); ++mi) {
  133. const string &basename = (*mi);
  134. Filename filename(this_filename, basename);
  135. PT(VirtualFile) file = file_system->get_file(filename);
  136. file_list->add_file(file);
  137. }
  138. // Now, get the actual local files in this directory.
  139. vector_string names;
  140. if (!scan_local_directory(file_list, mount_points)) {
  141. // Not a directory, or unable to read directory.
  142. if (file_list->get_num_files() == 0) {
  143. return NULL;
  144. }
  145. // We couldn't read the physical directory, but we do have some
  146. // mounted files to return.
  147. return file_list;
  148. }
  149. return file_list;
  150. }
  151. ////////////////////////////////////////////////////////////////////
  152. // Function: VirtualFile::output
  153. // Access: Published
  154. // Description:
  155. ////////////////////////////////////////////////////////////////////
  156. void VirtualFile::
  157. output(ostream &out) const {
  158. out << get_filename();
  159. }
  160. ////////////////////////////////////////////////////////////////////
  161. // Function: VirtualFile::ls
  162. // Access: Published
  163. // Description: If the file represents a directory, lists its
  164. // contents.
  165. ////////////////////////////////////////////////////////////////////
  166. void VirtualFile::
  167. ls(ostream &out) const {
  168. CPT(VirtualFileList) contents = scan_directory();
  169. if (contents == (VirtualFileList *)NULL) {
  170. if (!is_directory()) {
  171. out << get_filename() << "\n";
  172. } else {
  173. out << get_filename() << " cannot be read.\n";
  174. }
  175. return;
  176. }
  177. int num_files = contents->get_num_files();
  178. for (int i = 0; i < num_files; i++) {
  179. VirtualFile *file = contents->get_file(i);
  180. out << file->get_filename().get_basename() << "\n";
  181. }
  182. }
  183. ////////////////////////////////////////////////////////////////////
  184. // Function: VirtualFile::ls_all
  185. // Access: Published
  186. // Description: If the file represents a directory, recursively lists
  187. // its contents and those of all subdirectories.
  188. ////////////////////////////////////////////////////////////////////
  189. void VirtualFile::
  190. ls_all(ostream &out) const {
  191. if (!is_directory()) {
  192. out << get_filename() << " is not a directory.\n";
  193. } else {
  194. r_ls_all(out, get_filename());
  195. }
  196. }
  197. ////////////////////////////////////////////////////////////////////
  198. // Function: VirtualFile::open_read_file
  199. // Access: Published, Virtual
  200. // Description: Opens the file for reading. Returns a newly
  201. // allocated istream on success (which you should
  202. // eventually delete when you are done reading).
  203. // Returns NULL on failure.
  204. ////////////////////////////////////////////////////////////////////
  205. istream *VirtualFile::
  206. open_read_file(bool auto_unwrap) const {
  207. return NULL;
  208. }
  209. ////////////////////////////////////////////////////////////////////
  210. // Function: VirtualFile::close_read_file
  211. // Access: Published
  212. // Description: Closes a file opened by a previous call to
  213. // open_read_file(). This really just deletes the
  214. // istream pointer, but it is recommended to use this
  215. // interface instead of deleting it explicitly, to help
  216. // work around compiler issues.
  217. ////////////////////////////////////////////////////////////////////
  218. void VirtualFile::
  219. close_read_file(istream *stream) const {
  220. nassertv(false);
  221. }
  222. ////////////////////////////////////////////////////////////////////
  223. // Function: VirtualFile::was_read_successful
  224. // Access: Published, Virtual
  225. // Description: Call this method after a reading the istream returned
  226. // by open_read_file() to completion. If it returns
  227. // true, the file was read completely and without error;
  228. // if it returns false, there may have been some errors
  229. // or a truncated file read. This is particularly
  230. // likely if the stream is a VirtualFileHTTP.
  231. ////////////////////////////////////////////////////////////////////
  232. bool VirtualFile::
  233. was_read_successful() const {
  234. return true;
  235. }
  236. ////////////////////////////////////////////////////////////////////
  237. // Function: VirtualFile::open_write_file
  238. // Access: Published, Virtual
  239. // Description: Opens the file for writing. Returns a newly
  240. // allocated ostream on success (which you should
  241. // eventually delete when you are done writing).
  242. // Returns NULL on failure.
  243. ////////////////////////////////////////////////////////////////////
  244. ostream *VirtualFile::
  245. open_write_file(bool auto_wrap, bool truncate) {
  246. return NULL;
  247. }
  248. ////////////////////////////////////////////////////////////////////
  249. // Function: VirtualFile::open_append_file
  250. // Access: Published, Virtual
  251. // Description: Works like open_write_file(), but the file is opened
  252. // in append mode. Like open_write_file, the returned
  253. // pointer should eventually be passed to
  254. // close_write_file().
  255. ////////////////////////////////////////////////////////////////////
  256. ostream *VirtualFile::
  257. open_append_file() {
  258. return NULL;
  259. }
  260. ////////////////////////////////////////////////////////////////////
  261. // Function: VirtualFile::close_write_file
  262. // Access: Published
  263. // Description: Closes a file opened by a previous call to
  264. // open_write_file(). This really just deletes the
  265. // ostream pointer, but it is recommended to use this
  266. // interface instead of deleting it explicitly, to help
  267. // work around compiler issues.
  268. ////////////////////////////////////////////////////////////////////
  269. void VirtualFile::
  270. close_write_file(ostream *stream) {
  271. nassertv(false);
  272. }
  273. ////////////////////////////////////////////////////////////////////
  274. // Function: VirtualFile::open_read_write_file
  275. // Access: Published, Virtual
  276. // Description: Opens the file for writing. Returns a newly
  277. // allocated iostream on success (which you should
  278. // eventually delete when you are done writing).
  279. // Returns NULL on failure.
  280. ////////////////////////////////////////////////////////////////////
  281. iostream *VirtualFile::
  282. open_read_write_file(bool truncate) {
  283. return NULL;
  284. }
  285. ////////////////////////////////////////////////////////////////////
  286. // Function: VirtualFile::open_read_append_file
  287. // Access: Published, Virtual
  288. // Description: Works like open_read_write_file(), but the file is opened
  289. // in append mode. Like open_read_write_file, the returned
  290. // pointer should eventually be passed to
  291. // close_read_write_file().
  292. ////////////////////////////////////////////////////////////////////
  293. iostream *VirtualFile::
  294. open_read_append_file() {
  295. return NULL;
  296. }
  297. ////////////////////////////////////////////////////////////////////
  298. // Function: VirtualFile::close_read_write_file
  299. // Access: Published
  300. // Description: Closes a file opened by a previous call to
  301. // open_read_write_file(). This really just deletes the
  302. // iostream pointer, but it is recommended to use this
  303. // interface instead of deleting it explicitly, to help
  304. // work around compiler issues.
  305. ////////////////////////////////////////////////////////////////////
  306. void VirtualFile::
  307. close_read_write_file(iostream *stream) {
  308. nassertv(false);
  309. }
  310. ////////////////////////////////////////////////////////////////////
  311. // Function: VirtualFile::get_file_size
  312. // Access: Published, Virtual
  313. // Description: Returns the current size on disk (or wherever it is)
  314. // of the already-open file. Pass in the stream that
  315. // was returned by open_read_file(); some
  316. // implementations may require this stream to determine
  317. // the size.
  318. ////////////////////////////////////////////////////////////////////
  319. off_t VirtualFile::
  320. get_file_size(istream *stream) const {
  321. return get_file_size();
  322. }
  323. ////////////////////////////////////////////////////////////////////
  324. // Function: VirtualFile::get_file_size
  325. // Access: Published, Virtual
  326. // Description: Returns the current size on disk (or wherever it is)
  327. // of the file before it has been opened.
  328. ////////////////////////////////////////////////////////////////////
  329. off_t VirtualFile::
  330. get_file_size() const {
  331. return 0;
  332. }
  333. ////////////////////////////////////////////////////////////////////
  334. // Function: VirtualFile::get_timestamp
  335. // Access: Published, Virtual
  336. // Description: Returns a time_t value that represents the time the
  337. // file was last modified, to within whatever precision
  338. // the operating system records this information (on a
  339. // Windows95 system, for instance, this may only be
  340. // accurate to within 2 seconds).
  341. //
  342. // If the timestamp cannot be determined, either because
  343. // it is not supported by the operating system or
  344. // because there is some error (such as file not found),
  345. // returns 0.
  346. ////////////////////////////////////////////////////////////////////
  347. time_t VirtualFile::
  348. get_timestamp() const {
  349. return 0;
  350. }
  351. ////////////////////////////////////////////////////////////////////
  352. // Function: VirtualFile::get_system_info
  353. // Access: Published, Virtual
  354. // Description: Populates the SubfileInfo structure with the data
  355. // representing where the file actually resides on disk,
  356. // if this is knowable. Returns true if the file might
  357. // reside on disk, and the info is populated, or false
  358. // if it does not (or it is not known where the file
  359. // resides), in which case the info is meaningless.
  360. ////////////////////////////////////////////////////////////////////
  361. bool VirtualFile::
  362. get_system_info(SubfileInfo &info) {
  363. return false;
  364. }
  365. ////////////////////////////////////////////////////////////////////
  366. // Function: VirtualFile::atomic_compare_and_exchange_contents
  367. // Access: Public, Virtual
  368. // Description: See Filename::atomic_compare_and_exchange_contents().
  369. ////////////////////////////////////////////////////////////////////
  370. bool VirtualFile::
  371. atomic_compare_and_exchange_contents(string &orig_contents,
  372. const string &old_contents,
  373. const string &new_contents) {
  374. return false;
  375. }
  376. ////////////////////////////////////////////////////////////////////
  377. // Function: VirtualFile::atomic_read_contents
  378. // Access: Public, Virtual
  379. // Description: See Filename::atomic_read_contents().
  380. ////////////////////////////////////////////////////////////////////
  381. bool VirtualFile::
  382. atomic_read_contents(string &contents) const {
  383. return false;
  384. }
  385. ////////////////////////////////////////////////////////////////////
  386. // Function: VirtualFile::read_file
  387. // Access: Public
  388. // Description: Fills up the indicated string with the contents of
  389. // the file, if it is a regular file. Returns true on
  390. // success, false otherwise.
  391. ////////////////////////////////////////////////////////////////////
  392. bool VirtualFile::
  393. read_file(string &result, bool auto_unwrap) const {
  394. result = string();
  395. pvector<unsigned char> pv;
  396. if (!read_file(pv, auto_unwrap)) {
  397. return false;
  398. }
  399. if (!pv.empty()) {
  400. result.append((const char *)&pv[0], pv.size());
  401. }
  402. return true;
  403. }
  404. ////////////////////////////////////////////////////////////////////
  405. // Function: VirtualFile::read_file
  406. // Access: Public, Virtual
  407. // Description: Fills up the indicated pvector with the contents of
  408. // the file, if it is a regular file. Returns true on
  409. // success, false otherwise.
  410. ////////////////////////////////////////////////////////////////////
  411. bool VirtualFile::
  412. read_file(pvector<unsigned char> &result, bool auto_unwrap) const {
  413. return false;
  414. }
  415. ////////////////////////////////////////////////////////////////////
  416. // Function: VirtualFile::write_file
  417. // Access: Public, Virtual
  418. // Description: Writes the indicated data to the file, if it is
  419. // writable. Returns true on success, false otherwise.
  420. ////////////////////////////////////////////////////////////////////
  421. bool VirtualFile::
  422. write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
  423. return false;
  424. }
  425. ////////////////////////////////////////////////////////////////////
  426. // Function: VirtualFile::simple_read_file
  427. // Access: Public, Static
  428. // Description: Fills up the indicated pvector with the contents of
  429. // the just-opened file. Returns true on success, false
  430. // otherwise. If the pvector was not empty on entry, the
  431. // data read from the file will be appended onto it.
  432. ////////////////////////////////////////////////////////////////////
  433. bool VirtualFile::
  434. simple_read_file(istream *in, pvector<unsigned char> &result) {
  435. static const size_t buffer_size = 4096;
  436. char buffer[buffer_size];
  437. in->read(buffer, buffer_size);
  438. size_t count = in->gcount();
  439. while (count != 0) {
  440. thread_consider_yield();
  441. result.insert(result.end(), buffer, buffer + count);
  442. in->read(buffer, buffer_size);
  443. count = in->gcount();
  444. }
  445. return (!in->fail() || in->eof());
  446. }
  447. ////////////////////////////////////////////////////////////////////
  448. // Function: VirtualFile::simple_read_file
  449. // Access: Public
  450. // Description: As in simple_read_file() with two parameters, above,
  451. // but only reads up to max_bytes bytes from the file.
  452. ////////////////////////////////////////////////////////////////////
  453. bool VirtualFile::
  454. simple_read_file(istream *in, pvector<unsigned char> &result, size_t max_bytes) {
  455. static const size_t buffer_size = 4096;
  456. char buffer[buffer_size];
  457. in->read(buffer, min(buffer_size, max_bytes));
  458. size_t count = in->gcount();
  459. while (count != 0) {
  460. thread_consider_yield();
  461. nassertr(count <= max_bytes, false);
  462. result.insert(result.end(), buffer, buffer + count);
  463. max_bytes -= count;
  464. in->read(buffer, min(buffer_size, max_bytes));
  465. count = in->gcount();
  466. }
  467. return (!in->fail() || in->eof());
  468. }
  469. ////////////////////////////////////////////////////////////////////
  470. // Function: VirtualFile::scan_local_directory
  471. // Access: Protected, Virtual
  472. // Description: Fills file_list up with the list of files that are
  473. // within this directory, excluding those whose
  474. // basenames are listed in mount_points. Returns true
  475. // if successful, false if the file is not a directory
  476. // or the directory cannot be read.
  477. ////////////////////////////////////////////////////////////////////
  478. bool VirtualFile::
  479. scan_local_directory(VirtualFileList *, const ov_set<string> &) const {
  480. return false;
  481. }
  482. ////////////////////////////////////////////////////////////////////
  483. // Function: VirtualFile::r_ls_all
  484. // Access: Private
  485. // Description: The recursive implementation of ls_all().
  486. ////////////////////////////////////////////////////////////////////
  487. void VirtualFile::
  488. r_ls_all(ostream &out, const Filename &root) const {
  489. CPT(VirtualFileList) contents = scan_directory();
  490. if (contents == (VirtualFileList *)NULL) {
  491. return;
  492. }
  493. int num_files = contents->get_num_files();
  494. for (int i = 0; i < num_files; i++) {
  495. VirtualFile *file = contents->get_file(i);
  496. Filename filename = file->get_filename();
  497. filename.make_relative_to(root);
  498. out << filename << "\n";
  499. if (file->is_directory()) {
  500. file->r_ls_all(out, root);
  501. }
  502. }
  503. }