volume.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _VOLUME_H_
  23. #define _VOLUME_H_
  24. #ifndef _TSIGNAL_H_
  25. #include "core/util/tSignal.h"
  26. #endif
  27. #ifndef _TVECTOR_H_
  28. #include "core/util/tVector.h"
  29. #endif
  30. #ifndef _REFBASE_H_
  31. #include "core/util/refBase.h"
  32. #endif
  33. #ifndef _TDICTIONARY_H_
  34. #include "core/util/tDictionary.h"
  35. #endif
  36. #ifndef _TORQUE_LIST_
  37. #include "core/util/tList.h"
  38. #endif
  39. #ifndef _PATH_H_
  40. #include "core/util/path.h"
  41. #endif
  42. #ifndef _TIMECLASS_H_
  43. #include "core/util/timeClass.h"
  44. #endif
  45. namespace Torque
  46. {
  47. namespace FS
  48. {
  49. ///@defgroup VolumeSystem Volume System
  50. /// Volume access.
  51. //-----------------------------------------------------------------------------
  52. /// Base class for all FileIO objects.
  53. /// @ingroup VolumeSystem
  54. class FileBase : public StrongRefBase
  55. {
  56. public:
  57. virtual ~FileBase() {}
  58. };
  59. //-----------------------------------------------------------------------------
  60. /// Base class for objects in a FileSystem.
  61. /// This class provides the functionality required by all file system
  62. /// files, which is basically name and attributes.
  63. /// @ingroup VolumeSystem
  64. class FileNode : public FileBase
  65. {
  66. public:
  67. enum NodeStatus
  68. {
  69. Open, ///< In an open state
  70. Closed, ///< In a closed state
  71. EndOfFile, ///< End of file reached
  72. UnknownError, ///< An undetermined error has occurred
  73. FileSystemFull, ///< File system full
  74. NoSuchFile, ///< File or path does not exist
  75. AccessDenied, ///< File access denied
  76. IllegalCall, ///< An unsupported operation was used.
  77. SharingViolation, ///< File being used by another process
  78. NoDisk, ///< No disk or dvd in drive
  79. DriveOpen, ///< Disk or DVD drive open
  80. WrongDisk, ///< Disk or DVD has been swapped
  81. };
  82. enum Mode
  83. {
  84. File = 1 << 0, ///< Normal file
  85. Directory = 1 << 1, ///< Directory
  86. System = 1 << 2, ///< OS specific system file
  87. Hidden = 1 << 3, ///< Hidden file or directory
  88. ReadOnly = 1 << 4, ///< Read only
  89. Compressed = 1 << 5, ///< Part of a compressed archive?
  90. Encrypted = 1 << 6, ///< Part of an encrypted archive?
  91. Library = 1 << 7, ///< Dynamic Library
  92. Executable = 1 << 8, ///< Executable file
  93. };
  94. struct Attributes
  95. {
  96. U32 flags; ///< File/Directory modes
  97. String name; ///< File/Directory name
  98. Time mtime; ///< Last modified time
  99. Time atime; ///< Last access time
  100. U64 size;
  101. };
  102. public:
  103. FileNode();
  104. // Properties
  105. virtual Path getName() const = 0;
  106. virtual NodeStatus getStatus() const = 0;
  107. virtual bool getAttributes(Attributes*) = 0;
  108. // Convenience routines - may be overridden for optimal access
  109. virtual Time getModifiedTime(); ///< @note This will return Time() on failure
  110. virtual U64 getSize(); ///< @note This will return 0 on failure
  111. virtual U32 getChecksum(); ///< @note This will return 0 on failure
  112. protected:
  113. virtual U32 calculateChecksum() = 0; ///< return 0 on failure
  114. private:
  115. U32 mChecksum;
  116. Torque::Time mLastChecksum;
  117. };
  118. typedef WeakRefPtr<FileNode> FileNodePtr;
  119. typedef StrongRefPtr<FileNode> FileNodeRef;
  120. //-----------------------------------------------------------------------------
  121. /// File object in a FileSystem.
  122. /// File object in a FileSystem. When a file is initially obtained from a
  123. /// FileSystem it is in a closed state.
  124. /// @ingroup VolumeSystem
  125. class File : public FileNode
  126. {
  127. public:
  128. enum AccessMode
  129. {
  130. Read = 0, ///< Open for read only.
  131. Write = 1, ///< Open for write only.
  132. ReadWrite = 2, ///< Open for read-write.
  133. WriteAppend = 3 ///< Write-only, starting at end of file.
  134. };
  135. enum SeekMode
  136. {
  137. Begin, ///< Relative to the start of the file
  138. Current, ///< Relative to the current position
  139. End, ///< Relative to the end of the file
  140. };
  141. File();
  142. virtual ~File();
  143. // Properties
  144. virtual U32 getPosition() = 0;
  145. virtual U32 setPosition(U32 pos, SeekMode mode) = 0;
  146. // Functions
  147. virtual bool open(AccessMode mode) = 0;
  148. virtual bool close() = 0;
  149. virtual U32 read(void* dst, U32 size) = 0;
  150. virtual U32 write(const void* src, U32 size) = 0;
  151. };
  152. typedef WeakRefPtr<File> FilePtr;
  153. typedef StrongRefPtr<File> FileRef;
  154. //-----------------------------------------------------------------------------
  155. /// Directory in a FileSystem.
  156. /// Directory object in a FileSystem. When a directory is initially obtained from a
  157. /// FileSystem it is in a closed state.
  158. /// @ingroup VolumeSystem
  159. class Directory : public FileNode
  160. {
  161. public:
  162. Directory();
  163. virtual ~Directory();
  164. // Functions
  165. virtual bool open() = 0;
  166. virtual bool close() = 0;
  167. virtual bool read(Attributes*) = 0;
  168. };
  169. typedef WeakRefPtr<Directory> DirectoryPtr;
  170. typedef StrongRefPtr<Directory> DirectoryRef;
  171. //-----------------------------------------------------------------------------
  172. class FileSystem;
  173. class FileSystemChangeNotifier
  174. {
  175. public:
  176. typedef Delegate<void(const Path &)> ChangeDelegate;
  177. typedef Signal<void(const Path &)> ChangeSignal;
  178. public:
  179. FileSystemChangeNotifier( FileSystem *fs )
  180. : mFS( fs ),
  181. mNotifying( false )
  182. {
  183. }
  184. virtual ~FileSystemChangeNotifier() {}
  185. /// Adds a file change notification.
  186. /// @see FS::AddChangeNotification
  187. virtual bool addNotification( const Path &path, ChangeDelegate callback );
  188. /// Removes an existing file change notification.
  189. /// @see FS::RemoveChangeNotification
  190. virtual bool removeNotification( const Path &path, ChangeDelegate callback );
  191. void startNotifier();
  192. void stopNotifier();
  193. /// Returns true if the notifier is enabled and file
  194. /// change notifications will be sent.
  195. bool isNotifying() const { return mNotifying; }
  196. protected:
  197. struct FileInfo
  198. {
  199. /// The full path to the file.
  200. Path filePath;
  201. /// The last known modification time.
  202. Time savedLastModTime;
  203. /// The notifications and reference count.
  204. ChangeSignal signal;
  205. };
  206. typedef List<FileInfo> FileInfoList;
  207. typedef Map<Path, FileInfoList> DirMap; ///< map a directory to a list of files and their mod times
  208. void process();
  209. virtual void internalProcessOnce() = 0;
  210. /// This is called so the inherited class can do its own bookkeeping on addNotification()
  211. /// @note We pass the directory here, not the file
  212. virtual bool internalAddNotification( const Path &dir ) = 0;
  213. /// This is called so the inherited class can do its own bookkeeping on removeNotification()
  214. /// @note We pass the directory here, not the file
  215. virtual bool internalRemoveNotification( const Path &dir ) = 0;
  216. /// Called by the inherited class to let us know a directory has changed
  217. /// so we can find the file which changed and notify on it
  218. void internalNotifyDirChanged( const Path &dir );
  219. /// Makes sure paths going in and out of the notifier will have the same format
  220. String cleanPath(const Path& dir);
  221. FileSystem *mFS;
  222. DirMap mDirMap;
  223. bool mNotifying;
  224. };
  225. //-----------------------------------------------------------------------------
  226. /// Collection of FileNode objects.
  227. /// File systems represent collections of FileNode objects. Functions are
  228. /// provided for manipulating FileNode objects but the internal organization
  229. /// and representation is opaque.
  230. /// Path names must be fully specified relative to the file system root and
  231. /// names cannot contain relative path information.
  232. /// @ingroup VolumeSystem
  233. class FileSystem : public FileBase
  234. {
  235. public:
  236. FileSystem();
  237. virtual ~FileSystem();
  238. virtual String getTypeStr() const = 0; ///< Used for describing the file system type
  239. virtual FileNodeRef resolve(const Path& path) = 0;
  240. virtual FileNodeRef resolveLoose(const Path& path) { return resolve(path); }
  241. virtual FileNodeRef create(const Path& path,FileNode::Mode) = 0;
  242. virtual bool remove(const Path& path) = 0;
  243. virtual bool rename(const Path& a,const Path& b) = 0;
  244. virtual Path mapTo(const Path& path) = 0;
  245. virtual Path mapFrom(const Path& path) = 0;
  246. /// Returns the file change notifier.
  247. /// @see FS::AddChangeNotification
  248. /// @see FS::RemoveChangeNotification
  249. FileSystemChangeNotifier *getChangeNotifier() { return mChangeNotifier; }
  250. bool isReadOnly() { return mReadOnly; }
  251. protected:
  252. FileSystemChangeNotifier *mChangeNotifier;
  253. bool mReadOnly;
  254. };
  255. typedef WeakRefPtr<FileSystem> FileSystemPtr;
  256. typedef StrongRefPtr<FileSystem> FileSystemRef;
  257. //-----------------------------------------------------------------------------
  258. ///@name File System Access
  259. /// A collection of file systems.
  260. /// @ingroup VolumeSystem
  261. class MountSystem
  262. {
  263. public:
  264. virtual ~MountSystem() {}
  265. FileRef createFile(const Path& path);
  266. DirectoryRef createDirectory(const Path& path, FileSystemRef fs = NULL);
  267. virtual bool createPath(const Path& path);
  268. FileRef openFile(const Path& path,File::AccessMode mode);
  269. DirectoryRef openDirectory(const Path& path);
  270. bool remove(const Path& path);
  271. bool rename(const Path& from,const Path& to);
  272. virtual bool mount(String root, FileSystemRef fs);
  273. virtual bool mount(String root, const Path &path);
  274. virtual FileSystemRef unmount(String root);
  275. virtual bool unmount(FileSystemRef fs);
  276. bool setCwd(const Path& file);
  277. const Path &getCwd() const;
  278. FileSystemRef getFileSystem(const Path& path);
  279. bool getFileAttributes(const Path& path,FileNode::Attributes* attr);
  280. FileNodeRef getFileNode(const Path& path);
  281. bool mapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  282. virtual S32 findByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool includeDirs=false, bool multiMatch = true );
  283. bool isFile(const Path &path);
  284. bool isDirectory(const Path &path, FileSystemRef fsRef = NULL);
  285. bool isReadOnly(const Path &path);
  286. S32 getNumMounts() const { return mMountList.size(); }
  287. String getMountRoot( S32 index ) const { return mMountList[index].root; }
  288. String getMountPath( S32 index ) const { return mMountList[index].fileSystem->mapTo(mMountList[index].path); }
  289. String getMountType( S32 index ) const { return mMountList[index].fileSystem->getTypeStr(); }
  290. // File system notifications
  291. void startFileChangeNotifications();
  292. void stopFileChangeNotifications();
  293. protected:
  294. virtual void _log(const String& msg);
  295. protected:
  296. struct MountFS
  297. {
  298. String root; // Root for file system
  299. String path; // File system path
  300. FileSystemRef fileSystem;
  301. };
  302. virtual FileSystemRef _removeMountFromList(String root);
  303. virtual FileSystemRef _getFileSystemFromList(const Path& path) const ;
  304. void _setFindByPatternOverrideFS(FileSystemRef fs) { mFindByPatternOverrideFS = fs; }
  305. Path _normalize(const Path& path);
  306. Vector<MountFS> mMountList;
  307. Path mCWD;
  308. FileSystemRef mFindByPatternOverrideFS;
  309. };
  310. ///@name File System Access
  311. /// Functions for mounting file systems and dealing with files and directories.
  312. /// The kernel provides FileSystem mounting, the concept of a current working
  313. /// directory as well as relative paths.
  314. ///@{
  315. /// Mount file system
  316. ///@ingroup VolumeSystem
  317. bool Mount(String root, FileSystemRef fs);
  318. /// Mount file system redirect
  319. ///@ingroup VolumeSystem
  320. bool Mount(String root, const Path &path);
  321. /// Remove mounted file system.
  322. /// The file system object associated with the given root is unmounted.
  323. /// Open files associated with this file system are unaffected.
  324. ///@return The unmounted file system.
  325. ///@ingroup VolumeSystem
  326. FileSystemRef Unmount(String root);
  327. /// Remove mounted file system.
  328. /// Open files associated with this file system are unaffected.
  329. ///@return true if the filesystem was successfully unmounted, false otherwise (most likely, the FS was not mounted)
  330. bool Unmount(FileSystemRef fs);
  331. /// Find the the file system which owns the given file.
  332. ///@ingroup VolumeSystem
  333. FileSystemRef GetFileSystem(const Path &file);
  334. /// Find the file system node for the given file.
  335. ///@return Null if the file doesn't exist
  336. ///@ingroup VolumeSystem
  337. FileNodeRef GetFileNode(const Path &path);
  338. /// Adds a file change notification callback.
  339. ///@ingroup VolumeSystem
  340. template <class T,class U>
  341. inline bool AddChangeNotification( const Path &path, T obj, U func )
  342. {
  343. FileSystemRef fs = GetFileSystem( path );
  344. if ( !fs || !fs->getChangeNotifier() )
  345. return false;
  346. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  347. return fs->getChangeNotifier()->addNotification( path, dlg );
  348. }
  349. /// Removes an existing file change notification callback.
  350. ///@ingroup VolumeSystem
  351. template <class T,class U>
  352. inline bool RemoveChangeNotification( const Path &path, T obj, U func )
  353. {
  354. FileSystemRef fs = GetFileSystem( path );
  355. if ( !fs || !fs->getChangeNotifier() )
  356. return false;
  357. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  358. return fs->getChangeNotifier()->removeNotification( path, dlg );
  359. }
  360. /// Map a real file system path to a virtual one based on a root.
  361. /// This is useful when we get a real path back from an OS file dialog for example.
  362. /// e.g. If we have a root "gumby" which points at "C:/foo/bar",
  363. /// MapFSPath("gumby", "C:/foo/bar/blat/picture.png", path );
  364. /// will map "C:/foo/bar/blat/picture.png" to "gumby:/blat/picture.png"
  365. ///@param inRoot The root to check
  366. ///@param inPath The real file system path
  367. ///@param outPath The resulting volume system path
  368. ///@return Success or failure
  369. bool MapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  370. /// Returns a true file system path without virtual mounts.
  371. ///
  372. ///@param inPath The path to convert.
  373. ///@param outPath The resulting real file system path.
  374. ///
  375. bool GetFSPath( const Path &inPath, Path &outPath );
  376. /// Find files matching a pattern starting in a given dir.
  377. ///@param inBasePath path to start in
  378. ///@param inFilePattern the file pattern [it uses the FindMatch class]
  379. ///@param inRecursive do we search recursively?
  380. ///@param outList the list of files as Strings [Paths are more expensive to compute, so these may be converted on demand]
  381. ///@param multiMatch match against multiple file patterns given in inFilePattern?
  382. ///@return number of files which matched
  383. ///@ingroup VolumeSystem
  384. S32 FindByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool multiMatch = false );
  385. /// Set current working directory.
  386. ///@ingroup VolumeSystem
  387. bool SetCwd(const Path &file);
  388. /// Get the current working directory.
  389. ///@ingroup VolumeSystem
  390. const Path& GetCwd();
  391. /// Remove (or delete) a file from the file system.
  392. ///@ingroup VolumeSystem
  393. bool Remove(const Path &file);
  394. /// Rename a file or directory.
  395. ///@ingroup VolumeSystem
  396. bool Rename(const Path &from, const Path &to);
  397. /// Get the file attributes.
  398. /// @return success
  399. ///@ingroup VolumeSystem
  400. bool GetFileAttributes(const Path &path, FileNode::Attributes *attr);
  401. /// Compare modified times of p1 & p2
  402. /// @return -1 if p1 < p2, 0 if p1 == p2, 1 if p1 > p2
  403. S32 CompareModifiedTimes(const Path& p1, const Path& p2);
  404. /// Open a file.
  405. /// If the file exists a file object will be returned even if the
  406. /// open operation fails.
  407. ///@return Null if the file does not exist
  408. ///@ingroup VolumeSystem
  409. FileRef OpenFile(const Path &file, File::AccessMode mode);
  410. /// Read in an entire file
  411. /// @note Caller is responsible for freeing memory
  412. ///@param inPath the file
  413. ///@param outData the pointer to return the data
  414. ///@param outSize the size of the data returned
  415. ///@param inNullTerminate add an extra '\0' byte to the return buffer
  416. ///@return successful read? If not, outData will be NULL and outSize will be 0
  417. bool ReadFile(const Path &inPath, void *&outData, U32 &outSize, bool inNullTerminate = false );
  418. /// Open a directory.
  419. /// If the directory exists a directory object will be returned even if the
  420. /// open operation fails.
  421. ///@return Null if the file does not exist
  422. ///@ingroup VolumeSystem
  423. DirectoryRef OpenDirectory(const Path &file);
  424. /// Create a file.
  425. /// The file object is returned in a closed state.
  426. ///@ingroup VolumeSystem
  427. FileRef CreateFile(const Path &file);
  428. /// Create a directory.
  429. /// The directory object is returned in a closed state.
  430. ///@ingroup VolumeSystem
  431. DirectoryRef CreateDirectory(const Path &file);
  432. /// Create all the directories in the path if they don't already exist
  433. ///@ingroup VolumeSystem
  434. bool CreatePath(const Path &path);
  435. bool IsReadOnly(const Path &path);
  436. bool IsDirectory(const Path &path);
  437. bool IsFile(const Path &path);
  438. bool IsScriptFile(const char* pFilePath);
  439. bool VerifyWriteAccess(const Path &path);
  440. /// This returns a unique file path from the components
  441. /// by appending numbers to the end of the file name if
  442. /// a file with the same name already exists.
  443. ///
  444. /// @param path The root and directory for the file.
  445. /// @param fileName The file name without extension.
  446. /// @param ext The dot-less extension.
  447. String MakeUniquePath( const char *path, const char *fileName, const char *ext );
  448. void StartFileChangeNotifications();
  449. void StopFileChangeNotifications();
  450. S32 GetNumMounts();
  451. String GetMountRoot( S32 index );
  452. String GetMountPath( S32 index );
  453. String GetMountType( S32 index );
  454. ///@}
  455. } // Namespace FS
  456. } // Namespace Torque
  457. #endif