virtualFileMountSystem.cxx 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. // Filename: virtualFileMountSystem.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 "virtualFileMountSystem.h"
  15. TypeHandle VirtualFileMountSystem::_type_handle;
  16. ////////////////////////////////////////////////////////////////////
  17. // Function: VirtualFileMountSystem::has_file
  18. // Access: Public, Virtual
  19. // Description: Returns true if the indicated file exists within the
  20. // mount system.
  21. ////////////////////////////////////////////////////////////////////
  22. bool VirtualFileMountSystem::
  23. has_file(const Filename &file) const {
  24. Filename pathname(_physical_filename, file);
  25. #ifdef WIN32
  26. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  27. Filename case_pathname = pathname;
  28. if (!case_pathname.make_true_case()) {
  29. return false;
  30. }
  31. if (case_pathname != pathname) {
  32. express_cat.warning()
  33. << "Filename is incorrect case: " << pathname
  34. << " instead of " << case_pathname << "\n";
  35. return false;
  36. }
  37. }
  38. #endif // WIN32
  39. return pathname.exists();
  40. }
  41. ////////////////////////////////////////////////////////////////////
  42. // Function: VirtualFileMountSystem::create_file
  43. // Access: Public, Virtual
  44. // Description: Attempts to create the indicated file within the
  45. // mount, if it does not already exist. Returns true on
  46. // success (or if the file already exists), or false if
  47. // it cannot be created.
  48. ////////////////////////////////////////////////////////////////////
  49. bool VirtualFileMountSystem::
  50. create_file(const Filename &file) {
  51. Filename pathname(_physical_filename, file);
  52. pathname.set_binary();
  53. ofstream stream;
  54. return pathname.open_write(stream, false);
  55. }
  56. ////////////////////////////////////////////////////////////////////
  57. // Function: VirtualFileMountSystem::delete_file
  58. // Access: Public, Virtual
  59. // Description: Attempts to delete the indicated file or directory
  60. // within the mount. This can remove a single file or
  61. // an empty directory. It will not remove a nonempty
  62. // directory. Returns true on success, false on
  63. // failure.
  64. ////////////////////////////////////////////////////////////////////
  65. bool VirtualFileMountSystem::
  66. delete_file(const Filename &file) {
  67. Filename pathname(_physical_filename, file);
  68. return pathname.unlink() || pathname.rmdir();
  69. }
  70. ////////////////////////////////////////////////////////////////////
  71. // Function: VirtualFileMountSystem::rename_file
  72. // Access: Public
  73. // Description: Attempts to rename the contents of the indicated file
  74. // to the indicated file. Both filenames will be within
  75. // the mount. Returns true on success, false on
  76. // failure. If this returns false, this will be
  77. // attempted again with a copy-and-delete operation.
  78. ////////////////////////////////////////////////////////////////////
  79. bool VirtualFileMountSystem::
  80. rename_file(const Filename &orig_filename, const Filename &new_filename) {
  81. Filename orig_pathname(_physical_filename, orig_filename);
  82. Filename new_pathname(_physical_filename, new_filename);
  83. return orig_pathname.rename_to(new_pathname);
  84. }
  85. ////////////////////////////////////////////////////////////////////
  86. // Function: VirtualFileMountSystem::copy_file
  87. // Access: Public
  88. // Description: Attempts to copy the contents of the indicated file
  89. // to the indicated file. Both filenames will be within
  90. // the mount. Returns true on success, false on
  91. // failure. If this returns false, the copy will be
  92. // performed by explicit read-and-write operations.
  93. ////////////////////////////////////////////////////////////////////
  94. bool VirtualFileMountSystem::
  95. copy_file(const Filename &orig_filename, const Filename &new_filename) {
  96. Filename orig_pathname(_physical_filename, orig_filename);
  97. Filename new_pathname(_physical_filename, new_filename);
  98. return orig_pathname.copy_to(new_pathname);
  99. }
  100. ////////////////////////////////////////////////////////////////////
  101. // Function: VirtualFileMountSystem::make_directory
  102. // Access: Public, Virtual
  103. // Description: Attempts to create the indicated file within the
  104. // mount, if it does not already exist. Returns true on
  105. // success, or false if it cannot be created. If the
  106. // directory already existed prior to this call, may
  107. // return either true or false.
  108. ////////////////////////////////////////////////////////////////////
  109. bool VirtualFileMountSystem::
  110. make_directory(const Filename &file) {
  111. Filename pathname(_physical_filename, file);
  112. return pathname.mkdir();
  113. }
  114. ////////////////////////////////////////////////////////////////////
  115. // Function: VirtualFileMountSystem::is_directory
  116. // Access: Public, Virtual
  117. // Description: Returns true if the indicated file exists within the
  118. // mount system and is a directory.
  119. ////////////////////////////////////////////////////////////////////
  120. bool VirtualFileMountSystem::
  121. is_directory(const Filename &file) const {
  122. #ifdef WIN32
  123. // First ensure that the file exists to validate its case.
  124. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  125. if (!has_file(file)) {
  126. return false;
  127. }
  128. }
  129. #endif // WIN32
  130. Filename pathname(_physical_filename, file);
  131. return pathname.is_directory();
  132. }
  133. ////////////////////////////////////////////////////////////////////
  134. // Function: VirtualFileMountSystem::is_regular_file
  135. // Access: Public, Virtual
  136. // Description: Returns true if the indicated file exists within the
  137. // mount system and is a regular file.
  138. ////////////////////////////////////////////////////////////////////
  139. bool VirtualFileMountSystem::
  140. is_regular_file(const Filename &file) const {
  141. #ifdef WIN32
  142. // First ensure that the file exists to validate its case.
  143. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  144. if (!has_file(file)) {
  145. return false;
  146. }
  147. }
  148. #endif // WIN32
  149. Filename pathname(_physical_filename, file);
  150. return pathname.is_regular_file();
  151. }
  152. ////////////////////////////////////////////////////////////////////
  153. // Function: VirtualFileMountSystem::is_writable
  154. // Access: Public, Virtual
  155. // Description: Returns true if the named file or directory may be
  156. // written to, false otherwise.
  157. ////////////////////////////////////////////////////////////////////
  158. bool VirtualFileMountSystem::
  159. is_writable(const Filename &file) const {
  160. #ifdef WIN32
  161. // First ensure that the file exists to validate its case.
  162. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  163. if (!has_file(file)) {
  164. return false;
  165. }
  166. }
  167. #endif // WIN32
  168. Filename pathname(_physical_filename, file);
  169. return pathname.is_writable();
  170. }
  171. ////////////////////////////////////////////////////////////////////
  172. // Function: VirtualFileMountSystem::open_read_file
  173. // Access: Public, Virtual
  174. // Description: Opens the file for reading, if it exists. Returns a
  175. // newly allocated istream on success (which you should
  176. // eventually delete when you are done reading).
  177. // Returns NULL on failure.
  178. ////////////////////////////////////////////////////////////////////
  179. istream *VirtualFileMountSystem::
  180. open_read_file(const Filename &file) const {
  181. #ifdef WIN32
  182. // First ensure that the file exists to validate its case.
  183. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  184. if (!has_file(file)) {
  185. return NULL;
  186. }
  187. }
  188. #endif // WIN32
  189. Filename pathname(_physical_filename, file);
  190. pifstream *stream = new pifstream;
  191. if (!pathname.open_read(*stream)) {
  192. // Couldn't open the file for some reason.
  193. close_read_file(stream);
  194. return NULL;
  195. }
  196. return stream;
  197. }
  198. ////////////////////////////////////////////////////////////////////
  199. // Function: VirtualFileMountSystem::open_write_file
  200. // Access: Published, Virtual
  201. // Description: Opens the file for writing. Returns a newly
  202. // allocated ostream on success (which you should
  203. // eventually delete when you are done writing).
  204. // Returns NULL on failure.
  205. ////////////////////////////////////////////////////////////////////
  206. ostream *VirtualFileMountSystem::
  207. open_write_file(const Filename &file, bool truncate) {
  208. #ifdef WIN32
  209. // First ensure that the file exists to validate its case.
  210. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  211. if (!has_file(file)) {
  212. return NULL;
  213. }
  214. }
  215. #endif // WIN32
  216. Filename pathname(_physical_filename, file);
  217. pofstream *stream = new pofstream;
  218. if (!pathname.open_write(*stream, truncate)) {
  219. // Couldn't open the file for some reason.
  220. close_write_file(stream);
  221. return NULL;
  222. }
  223. return stream;
  224. }
  225. ////////////////////////////////////////////////////////////////////
  226. // Function: VirtualFileMountSystem::open_append_file
  227. // Access: Published
  228. // Description: Works like open_write_file(), but the file is opened
  229. // in append mode. Like open_write_file, the returned
  230. // pointer should eventually be passed to
  231. // close_write_file().
  232. ////////////////////////////////////////////////////////////////////
  233. ostream *VirtualFileMountSystem::
  234. open_append_file(const Filename &file) {
  235. #ifdef WIN32
  236. // First ensure that the file exists to validate its case.
  237. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  238. if (!has_file(file)) {
  239. return NULL;
  240. }
  241. }
  242. #endif // WIN32
  243. Filename pathname(_physical_filename, file);
  244. pofstream *stream = new pofstream;
  245. if (!pathname.open_append(*stream)) {
  246. // Couldn't open the file for some reason.
  247. close_write_file(stream);
  248. return NULL;
  249. }
  250. return stream;
  251. }
  252. ////////////////////////////////////////////////////////////////////
  253. // Function: VirtualFileMountSystem::open_read_write_file
  254. // Access: Published, Virtual
  255. // Description: Opens the file for writing. Returns a newly
  256. // allocated iostream on success (which you should
  257. // eventually delete when you are done writing).
  258. // Returns NULL on failure.
  259. ////////////////////////////////////////////////////////////////////
  260. iostream *VirtualFileMountSystem::
  261. open_read_write_file(const Filename &file, bool truncate) {
  262. #ifdef WIN32
  263. // First ensure that the file exists to validate its case.
  264. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  265. if (!has_file(file)) {
  266. return NULL;
  267. }
  268. }
  269. #endif // WIN32
  270. Filename pathname(_physical_filename, file);
  271. pfstream *stream = new pfstream;
  272. if (!pathname.open_read_write(*stream, truncate)) {
  273. // Couldn't open the file for some reason.
  274. close_read_write_file(stream);
  275. return NULL;
  276. }
  277. return stream;
  278. }
  279. ////////////////////////////////////////////////////////////////////
  280. // Function: VirtualFileMountSystem::open_read_append_file
  281. // Access: Published, Virtual
  282. // Description: Works like open_read_write_file(), but the file is opened
  283. // in append mode. Like open_read_write_file, the returned
  284. // pointer should eventually be passed to
  285. // close_read_write_file().
  286. ////////////////////////////////////////////////////////////////////
  287. iostream *VirtualFileMountSystem::
  288. open_read_append_file(const Filename &file) {
  289. #ifdef WIN32
  290. // First ensure that the file exists to validate its case.
  291. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  292. if (!has_file(file)) {
  293. return NULL;
  294. }
  295. }
  296. #endif // WIN32
  297. Filename pathname(_physical_filename, file);
  298. pfstream *stream = new pfstream;
  299. if (!pathname.open_read_append(*stream)) {
  300. // Couldn't open the file for some reason.
  301. close_read_write_file(stream);
  302. return NULL;
  303. }
  304. return stream;
  305. }
  306. ////////////////////////////////////////////////////////////////////
  307. // Function: VirtualFileMountSystem::get_file_size
  308. // Access: Published, Virtual
  309. // Description: Returns the current size on disk (or wherever it is)
  310. // of the already-open file. Pass in the stream that
  311. // was returned by open_read_file(); some
  312. // implementations may require this stream to determine
  313. // the size.
  314. ////////////////////////////////////////////////////////////////////
  315. off_t VirtualFileMountSystem::
  316. get_file_size(const Filename &file, istream *stream) const {
  317. // First, save the original stream position.
  318. streampos orig = stream->tellg();
  319. // Seek to the end and get the stream position there.
  320. stream->seekg(0, ios::end);
  321. if (stream->fail()) {
  322. // Seeking not supported.
  323. stream->clear();
  324. return get_file_size(file);
  325. }
  326. streampos size = stream->tellg();
  327. // Then return to the original point.
  328. stream->seekg(orig, ios::beg);
  329. // Make sure there are no error flags set as a result of the seek.
  330. stream->clear();
  331. return size;
  332. }
  333. ////////////////////////////////////////////////////////////////////
  334. // Function: VirtualFileMountSystem::get_file_size
  335. // Access: Published, Virtual
  336. // Description: Returns the current size on disk (or wherever it is)
  337. // of the file before it has been opened.
  338. ////////////////////////////////////////////////////////////////////
  339. off_t VirtualFileMountSystem::
  340. get_file_size(const Filename &file) const {
  341. Filename pathname(_physical_filename, file);
  342. return pathname.get_file_size();
  343. }
  344. ////////////////////////////////////////////////////////////////////
  345. // Function: VirtualFileMountSystem::get_timestamp
  346. // Access: Published, Virtual
  347. // Description: Returns a time_t value that represents the time the
  348. // file was last modified, to within whatever precision
  349. // the operating system records this information (on a
  350. // Windows95 system, for instance, this may only be
  351. // accurate to within 2 seconds).
  352. //
  353. // If the timestamp cannot be determined, either because
  354. // it is not supported by the operating system or
  355. // because there is some error (such as file not found),
  356. // returns 0.
  357. ////////////////////////////////////////////////////////////////////
  358. time_t VirtualFileMountSystem::
  359. get_timestamp(const Filename &file) const {
  360. Filename pathname(_physical_filename, file);
  361. return pathname.get_timestamp();
  362. }
  363. ////////////////////////////////////////////////////////////////////
  364. // Function: VirtualFileMountSystem::get_system_info
  365. // Access: Public, Virtual
  366. // Description: Populates the SubfileInfo structure with the data
  367. // representing where the file actually resides on disk,
  368. // if this is knowable. Returns true if the file might
  369. // reside on disk, and the info is populated, or false
  370. // if it does not (or it is not known where the file
  371. // resides), in which case the info is meaningless.
  372. ////////////////////////////////////////////////////////////////////
  373. bool VirtualFileMountSystem::
  374. get_system_info(const Filename &file, SubfileInfo &info) {
  375. Filename pathname(_physical_filename, file);
  376. info = SubfileInfo(pathname, 0, pathname.get_file_size());
  377. return true;
  378. }
  379. ////////////////////////////////////////////////////////////////////
  380. // Function: VirtualFileMountSystem::scan_directory
  381. // Access: Public, Virtual
  382. // Description: Fills the given vector up with the list of filenames
  383. // that are local to this directory, if the filename is
  384. // a directory. Returns true if successful, or false if
  385. // the file is not a directory or cannot be read.
  386. ////////////////////////////////////////////////////////////////////
  387. bool VirtualFileMountSystem::
  388. scan_directory(vector_string &contents, const Filename &dir) const {
  389. #ifdef WIN32
  390. // First ensure that the file exists to validate its case.
  391. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  392. if (!has_file(dir)) {
  393. return false;
  394. }
  395. }
  396. #endif // WIN32
  397. Filename pathname(_physical_filename, dir);
  398. return pathname.scan_directory(contents);
  399. }
  400. ////////////////////////////////////////////////////////////////////
  401. // Function: VirtualFileMountSystem::atomic_compare_and_exchange_contents
  402. // Access: Public, Virtual
  403. // Description: See Filename::atomic_compare_and_exchange_contents().
  404. ////////////////////////////////////////////////////////////////////
  405. bool VirtualFileMountSystem::
  406. atomic_compare_and_exchange_contents(const Filename &file, string &orig_contents,
  407. const string &old_contents,
  408. const string &new_contents) {
  409. #ifdef WIN32
  410. // First ensure that the file exists to validate its case.
  411. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  412. if (!has_file(file)) {
  413. return NULL;
  414. }
  415. }
  416. #endif // WIN32
  417. Filename pathname(_physical_filename, file);
  418. return pathname.atomic_compare_and_exchange_contents(orig_contents, old_contents, new_contents);
  419. }
  420. ////////////////////////////////////////////////////////////////////
  421. // Function: VirtualFileMountSystem::atomic_read_contents
  422. // Access: Public, Virtual
  423. // Description: See Filename::atomic_read_contents().
  424. ////////////////////////////////////////////////////////////////////
  425. bool VirtualFileMountSystem::
  426. atomic_read_contents(const Filename &file, string &contents) const {
  427. #ifdef WIN32
  428. // First ensure that the file exists to validate its case.
  429. if (VirtualFileSystem::get_global_ptr()->vfs_case_sensitive) {
  430. if (!has_file(file)) {
  431. return NULL;
  432. }
  433. }
  434. #endif // WIN32
  435. Filename pathname(_physical_filename, file);
  436. return pathname.atomic_read_contents(contents);
  437. }
  438. ////////////////////////////////////////////////////////////////////
  439. // Function: VirtualFileMountSystem::output
  440. // Access: Public, Virtual
  441. // Description:
  442. ////////////////////////////////////////////////////////////////////
  443. void VirtualFileMountSystem::
  444. output(ostream &out) const {
  445. out << get_physical_filename();
  446. }