volume.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  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 create(const Path& path,FileNode::Mode) = 0;
  241. virtual bool remove(const Path& path) = 0;
  242. virtual bool rename(const Path& a,const Path& b) = 0;
  243. virtual Path mapTo(const Path& path) = 0;
  244. virtual Path mapFrom(const Path& path) = 0;
  245. /// Returns the file change notifier.
  246. /// @see FS::AddChangeNotification
  247. /// @see FS::RemoveChangeNotification
  248. FileSystemChangeNotifier *getChangeNotifier() { return mChangeNotifier; }
  249. bool isReadOnly() { return mReadOnly; }
  250. protected:
  251. FileSystemChangeNotifier *mChangeNotifier;
  252. bool mReadOnly;
  253. };
  254. typedef WeakRefPtr<FileSystem> FileSystemPtr;
  255. typedef StrongRefPtr<FileSystem> FileSystemRef;
  256. //-----------------------------------------------------------------------------
  257. ///@name File System Access
  258. /// A collection of file systems.
  259. /// @ingroup VolumeSystem
  260. class MountSystem
  261. {
  262. public:
  263. virtual ~MountSystem() {}
  264. FileRef createFile(const Path& path);
  265. DirectoryRef createDirectory(const Path& path, FileSystemRef fs = NULL);
  266. virtual bool createPath(const Path& path);
  267. FileRef openFile(const Path& path,File::AccessMode mode);
  268. DirectoryRef openDirectory(const Path& path);
  269. bool remove(const Path& path);
  270. bool rename(const Path& from,const Path& to);
  271. virtual bool mount(String root, FileSystemRef fs);
  272. virtual bool mount(String root, const Path &path);
  273. virtual FileSystemRef unmount(String root);
  274. virtual bool unmount(FileSystemRef fs);
  275. bool setCwd(const Path& file);
  276. const Path &getCwd() const;
  277. FileSystemRef getFileSystem(const Path& path);
  278. bool getFileAttributes(const Path& path,FileNode::Attributes* attr);
  279. FileNodeRef getFileNode(const Path& path);
  280. bool mapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  281. virtual S32 findByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool includeDirs=false, bool multiMatch = true );
  282. bool isFile(const Path &path);
  283. bool isDirectory(const Path &path, FileSystemRef fsRef = NULL);
  284. bool isReadOnly(const Path &path);
  285. S32 getNumMounts() const { return mMountList.size(); }
  286. String getMountRoot( S32 index ) const { return mMountList[index].root; }
  287. String getMountPath( S32 index ) const { return mMountList[index].fileSystem->mapTo(mMountList[index].path); }
  288. String getMountType( S32 index ) const { return mMountList[index].fileSystem->getTypeStr(); }
  289. // File system notifications
  290. void startFileChangeNotifications();
  291. void stopFileChangeNotifications();
  292. protected:
  293. virtual void _log(const String& msg);
  294. protected:
  295. struct MountFS
  296. {
  297. String root; // Root for file system
  298. String path; // File system path
  299. FileSystemRef fileSystem;
  300. };
  301. virtual FileSystemRef _removeMountFromList(String root);
  302. virtual FileSystemRef _getFileSystemFromList(const Path& path) const ;
  303. void _setFindByPatternOverrideFS(FileSystemRef fs) { mFindByPatternOverrideFS = fs; }
  304. Path _normalize(const Path& path);
  305. Vector<MountFS> mMountList;
  306. Path mCWD;
  307. FileSystemRef mFindByPatternOverrideFS;
  308. };
  309. ///@name File System Access
  310. /// Functions for mounting file systems and dealing with files and directories.
  311. /// The kernel provides FileSystem mounting, the concept of a current working
  312. /// directory as well as relative paths.
  313. ///@{
  314. /// Mount file system
  315. ///@ingroup VolumeSystem
  316. bool Mount(String root, FileSystemRef fs);
  317. /// Mount file system redirect
  318. ///@ingroup VolumeSystem
  319. bool Mount(String root, const Path &path);
  320. /// Remove mounted file system.
  321. /// The file system object associated with the given root is unmounted.
  322. /// Open files associated with this file system are unaffected.
  323. ///@return The unmounted file system.
  324. ///@ingroup VolumeSystem
  325. FileSystemRef Unmount(String root);
  326. /// Remove mounted file system.
  327. /// Open files associated with this file system are unaffected.
  328. ///@return true if the filesystem was successfully unmounted, false otherwise (most likely, the FS was not mounted)
  329. bool Unmount(FileSystemRef fs);
  330. /// Find the the file system which owns the given file.
  331. ///@ingroup VolumeSystem
  332. FileSystemRef GetFileSystem(const Path &file);
  333. /// Find the file system node for the given file.
  334. ///@return Null if the file doesn't exist
  335. ///@ingroup VolumeSystem
  336. FileNodeRef GetFileNode(const Path &path);
  337. /// Adds a file change notification callback.
  338. ///@ingroup VolumeSystem
  339. template <class T,class U>
  340. inline bool AddChangeNotification( const Path &path, T obj, U func )
  341. {
  342. FileSystemRef fs = GetFileSystem( path );
  343. if ( !fs || !fs->getChangeNotifier() )
  344. return false;
  345. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  346. return fs->getChangeNotifier()->addNotification( path, dlg );
  347. }
  348. /// Removes an existing file change notification callback.
  349. ///@ingroup VolumeSystem
  350. template <class T,class U>
  351. inline bool RemoveChangeNotification( const Path &path, T obj, U func )
  352. {
  353. FileSystemRef fs = GetFileSystem( path );
  354. if ( !fs || !fs->getChangeNotifier() )
  355. return false;
  356. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  357. return fs->getChangeNotifier()->removeNotification( path, dlg );
  358. }
  359. /// Map a real file system path to a virtual one based on a root.
  360. /// This is useful when we get a real path back from an OS file dialog for example.
  361. /// e.g. If we have a root "gumby" which points at "C:/foo/bar",
  362. /// MapFSPath("gumby", "C:/foo/bar/blat/picture.png", path );
  363. /// will map "C:/foo/bar/blat/picture.png" to "gumby:/blat/picture.png"
  364. ///@param inRoot The root to check
  365. ///@param inPath The real file system path
  366. ///@param outPath The resulting volume system path
  367. ///@return Success or failure
  368. bool MapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  369. /// Returns a true file system path without virtual mounts.
  370. ///
  371. ///@param inPath The path to convert.
  372. ///@param outPath The resulting real file system path.
  373. ///
  374. bool GetFSPath( const Path &inPath, Path &outPath );
  375. /// Find files matching a pattern starting in a given dir.
  376. ///@param inBasePath path to start in
  377. ///@param inFilePattern the file pattern [it uses the FindMatch class]
  378. ///@param inRecursive do we search recursively?
  379. ///@param outList the list of files as Strings [Paths are more expensive to compute, so these may be converted on demand]
  380. ///@param multiMatch match against multiple file patterns given in inFilePattern?
  381. ///@return number of files which matched
  382. ///@ingroup VolumeSystem
  383. S32 FindByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool multiMatch = false );
  384. /// Set current working directory.
  385. ///@ingroup VolumeSystem
  386. bool SetCwd(const Path &file);
  387. /// Get the current working directory.
  388. ///@ingroup VolumeSystem
  389. const Path& GetCwd();
  390. /// Remove (or delete) a file from the file system.
  391. ///@ingroup VolumeSystem
  392. bool Remove(const Path &file);
  393. /// Rename a file or directory.
  394. ///@ingroup VolumeSystem
  395. bool Rename(const Path &from, const Path &to);
  396. /// Get the file attributes.
  397. /// @return success
  398. ///@ingroup VolumeSystem
  399. bool GetFileAttributes(const Path &path, FileNode::Attributes *attr);
  400. /// Compare modified times of p1 & p2
  401. /// @return -1 if p1 < p2, 0 if p1 == p2, 1 if p1 > p2
  402. S32 CompareModifiedTimes(const Path& p1, const Path& p2);
  403. /// Open a file.
  404. /// If the file exists a file object will be returned even if the
  405. /// open operation fails.
  406. ///@return Null if the file does not exist
  407. ///@ingroup VolumeSystem
  408. FileRef OpenFile(const Path &file, File::AccessMode mode);
  409. /// Read in an entire file
  410. /// @note Caller is responsible for freeing memory
  411. ///@param inPath the file
  412. ///@param outData the pointer to return the data
  413. ///@param outSize the size of the data returned
  414. ///@param inNullTerminate add an extra '\0' byte to the return buffer
  415. ///@return successful read? If not, outData will be NULL and outSize will be 0
  416. bool ReadFile(const Path &inPath, void *&outData, U32 &outSize, bool inNullTerminate = false );
  417. /// Open a directory.
  418. /// If the directory exists a directory object will be returned even if the
  419. /// open operation fails.
  420. ///@return Null if the file does not exist
  421. ///@ingroup VolumeSystem
  422. DirectoryRef OpenDirectory(const Path &file);
  423. /// Create a file.
  424. /// The file object is returned in a closed state.
  425. ///@ingroup VolumeSystem
  426. FileRef CreateFile(const Path &file);
  427. /// Create a directory.
  428. /// The directory object is returned in a closed state.
  429. ///@ingroup VolumeSystem
  430. DirectoryRef CreateDirectory(const Path &file);
  431. /// Create all the directories in the path if they don't already exist
  432. ///@ingroup VolumeSystem
  433. bool CreatePath(const Path &path);
  434. bool IsReadOnly(const Path &path);
  435. bool IsDirectory(const Path &path);
  436. bool IsFile(const Path &path);
  437. bool VerifyWriteAccess(const Path &path);
  438. /// This returns a unique file path from the components
  439. /// by appending numbers to the end of the file name if
  440. /// a file with the same name already exists.
  441. ///
  442. /// @param path The root and directory for the file.
  443. /// @param fileName The file name without extension.
  444. /// @param ext The dot-less extension.
  445. String MakeUniquePath( const char *path, const char *fileName, const char *ext );
  446. void StartFileChangeNotifications();
  447. void StopFileChangeNotifications();
  448. S32 GetNumMounts();
  449. String GetMountRoot( S32 index );
  450. String GetMountPath( S32 index );
  451. String GetMountType( S32 index );
  452. ///@}
  453. } // Namespace FS
  454. } // Namespace Torque
  455. #endif