volume.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. Time ctime; ///< Creation Time
  101. U64 size;
  102. };
  103. public:
  104. FileNode();
  105. // Properties
  106. virtual Path getName() const = 0;
  107. virtual NodeStatus getStatus() const = 0;
  108. virtual bool getAttributes(Attributes*) = 0;
  109. // Convenience routines - may be overridden for optimal access
  110. virtual Time getModifiedTime(); ///< @note This will return Time() on failure
  111. virtual Time getCreatedTime(); ///< @note This will return Time() on failure
  112. virtual U64 getSize(); ///< @note This will return 0 on failure
  113. virtual U32 getChecksum(); ///< @note This will return 0 on failure
  114. protected:
  115. virtual U32 calculateChecksum() = 0; ///< return 0 on failure
  116. private:
  117. U32 mChecksum;
  118. Torque::Time mLastChecksum;
  119. };
  120. typedef WeakRefPtr<FileNode> FileNodePtr;
  121. typedef StrongRefPtr<FileNode> FileNodeRef;
  122. //-----------------------------------------------------------------------------
  123. /// File object in a FileSystem.
  124. /// File object in a FileSystem. When a file is initially obtained from a
  125. /// FileSystem it is in a closed state.
  126. /// @ingroup VolumeSystem
  127. class File : public FileNode
  128. {
  129. public:
  130. enum AccessMode
  131. {
  132. Read = 0, ///< Open for read only.
  133. Write = 1, ///< Open for write only.
  134. ReadWrite = 2, ///< Open for read-write.
  135. WriteAppend = 3 ///< Write-only, starting at end of file.
  136. };
  137. enum SeekMode
  138. {
  139. Begin, ///< Relative to the start of the file
  140. Current, ///< Relative to the current position
  141. End, ///< Relative to the end of the file
  142. };
  143. File();
  144. virtual ~File();
  145. // Properties
  146. virtual U32 getPosition() = 0;
  147. virtual U32 setPosition(U32 pos, SeekMode mode) = 0;
  148. // Functions
  149. virtual bool open(AccessMode mode) = 0;
  150. virtual bool close() = 0;
  151. virtual U32 read(void* dst, U32 size) = 0;
  152. virtual U32 write(const void* src, U32 size) = 0;
  153. };
  154. typedef WeakRefPtr<File> FilePtr;
  155. typedef StrongRefPtr<File> FileRef;
  156. //-----------------------------------------------------------------------------
  157. /// Directory in a FileSystem.
  158. /// Directory object in a FileSystem. When a directory is initially obtained from a
  159. /// FileSystem it is in a closed state.
  160. /// @ingroup VolumeSystem
  161. class Directory : public FileNode
  162. {
  163. public:
  164. Directory();
  165. virtual ~Directory();
  166. // Functions
  167. virtual bool open() = 0;
  168. virtual bool close() = 0;
  169. virtual bool read(Attributes*) = 0;
  170. bool dump(Vector<Path>& out);
  171. bool dumpFiles(Vector<Path>& out);
  172. bool dumpDirectories(Vector<Path>& out);
  173. };
  174. typedef WeakRefPtr<Directory> DirectoryPtr;
  175. typedef StrongRefPtr<Directory> DirectoryRef;
  176. //-----------------------------------------------------------------------------
  177. class FileSystem;
  178. class FileSystemChangeNotifier
  179. {
  180. public:
  181. typedef Delegate<void(const Path &)> ChangeDelegate;
  182. typedef Signal<void(const Path &)> ChangeSignal;
  183. public:
  184. FileSystemChangeNotifier( FileSystem *fs )
  185. : mFS( fs ),
  186. mNotifying( false )
  187. {
  188. }
  189. virtual ~FileSystemChangeNotifier() {}
  190. /// Adds a file change notification.
  191. /// @see FS::AddChangeNotification
  192. virtual bool addNotification( const Path &path, ChangeDelegate callback );
  193. /// Removes an existing file change notification.
  194. /// @see FS::RemoveChangeNotification
  195. virtual bool removeNotification( const Path &path, ChangeDelegate callback );
  196. void startNotifier();
  197. void stopNotifier();
  198. /// Returns true if the notifier is enabled and file
  199. /// change notifications will be sent.
  200. bool isNotifying() const { return mNotifying; }
  201. protected:
  202. struct FileInfo
  203. {
  204. /// The full path to the file.
  205. Path filePath;
  206. /// The last known modification time.
  207. Time savedLastModTime;
  208. /// The notifications and reference count.
  209. ChangeSignal signal;
  210. };
  211. typedef List<FileInfo> FileInfoList;
  212. typedef Map<Path, FileInfoList> DirMap; ///< map a directory to a list of files and their mod times
  213. void process();
  214. virtual void internalProcessOnce() = 0;
  215. /// This is called so the inherited class can do its own bookkeeping on addNotification()
  216. /// @note We pass the directory here, not the file
  217. virtual bool internalAddNotification( const Path &dir ) = 0;
  218. /// This is called so the inherited class can do its own bookkeeping on removeNotification()
  219. /// @note We pass the directory here, not the file
  220. virtual bool internalRemoveNotification( const Path &dir ) = 0;
  221. /// Called by the inherited class to let us know a directory has changed
  222. /// so we can find the file which changed and notify on it
  223. void internalNotifyDirChanged( const Path &dir );
  224. /// Makes sure paths going in and out of the notifier will have the same format
  225. String cleanPath(const Path& dir);
  226. FileSystem *mFS;
  227. DirMap mDirMap;
  228. bool mNotifying;
  229. };
  230. //-----------------------------------------------------------------------------
  231. /// Collection of FileNode objects.
  232. /// File systems represent collections of FileNode objects. Functions are
  233. /// provided for manipulating FileNode objects but the internal organization
  234. /// and representation is opaque.
  235. /// Path names must be fully specified relative to the file system root and
  236. /// names cannot contain relative path information.
  237. /// @ingroup VolumeSystem
  238. class FileSystem : public FileBase
  239. {
  240. public:
  241. FileSystem();
  242. virtual ~FileSystem();
  243. virtual String getTypeStr() const = 0; ///< Used for describing the file system type
  244. virtual FileNodeRef resolve(const Path& path) = 0;
  245. virtual FileNodeRef resolveLoose(const Path& path) { return resolve(path); }
  246. virtual FileNodeRef create(const Path& path,FileNode::Mode) = 0;
  247. virtual bool remove(const Path& path) = 0;
  248. virtual bool rename(const Path& a,const Path& b) = 0;
  249. virtual Path mapTo(const Path& path) = 0;
  250. virtual Path mapFrom(const Path& path) = 0;
  251. /// Returns the file change notifier.
  252. /// @see FS::AddChangeNotification
  253. /// @see FS::RemoveChangeNotification
  254. FileSystemChangeNotifier *getChangeNotifier() { return mChangeNotifier; }
  255. bool isReadOnly() { return mReadOnly; }
  256. protected:
  257. FileSystemChangeNotifier *mChangeNotifier;
  258. bool mReadOnly;
  259. };
  260. typedef WeakRefPtr<FileSystem> FileSystemPtr;
  261. typedef StrongRefPtr<FileSystem> FileSystemRef;
  262. //-----------------------------------------------------------------------------
  263. ///@name File System Access
  264. /// A collection of file systems.
  265. /// @ingroup VolumeSystem
  266. class MountSystem
  267. {
  268. public:
  269. virtual ~MountSystem() {}
  270. FileRef createFile(const Path& path);
  271. bool copyFile(const Path& source, const Path& destination, bool noOverwrite);
  272. bool dumpDirectories(const Path& path, Vector<StringTableEntry>& directories, S32 depth, bool noBasePath);
  273. DirectoryRef createDirectory(const Path& path, FileSystemRef fs = NULL);
  274. virtual bool createPath(const Path& path);
  275. FileRef openFile(const Path& path,File::AccessMode mode);
  276. DirectoryRef openDirectory(const Path& path);
  277. bool remove(const Path& path);
  278. bool rename(const Path& from,const Path& to);
  279. virtual bool mount(String root, FileSystemRef fs);
  280. virtual bool mount(String root, const Path &path);
  281. virtual FileSystemRef unmount(String root);
  282. virtual bool unmount(FileSystemRef fs);
  283. bool setCwd(const Path& file);
  284. const Path &getCwd() const;
  285. FileSystemRef getFileSystem(const Path& path);
  286. bool getFileAttributes(const Path& path,FileNode::Attributes* attr);
  287. FileNodeRef getFileNode(const Path& path);
  288. bool mapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  289. virtual S32 findByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool includeDirs=false, bool multiMatch = true );
  290. bool isFile(const Path &path);
  291. bool isDirectory(const Path &path, FileSystemRef fsRef = NULL);
  292. bool isReadOnly(const Path &path);
  293. S32 getNumMounts() const { return mMountList.size(); }
  294. String getMountRoot( S32 index ) const { return mMountList[index].root; }
  295. String getMountPath( S32 index ) const { return mMountList[index].fileSystem->mapTo(mMountList[index].path); }
  296. String getMountType( S32 index ) const { return mMountList[index].fileSystem->getTypeStr(); }
  297. // File system notifications
  298. void startFileChangeNotifications();
  299. void stopFileChangeNotifications();
  300. private:
  301. bool _dumpDirectories(DirectoryRef directory, Vector<StringTableEntry>& directories, S32 depth, bool noBasePath, S32 currentDepth, const Path& basePath);
  302. protected:
  303. virtual void _log(const String& msg);
  304. protected:
  305. struct MountFS
  306. {
  307. String root; // Root for file system
  308. String path; // File system path
  309. FileSystemRef fileSystem;
  310. };
  311. virtual FileSystemRef _removeMountFromList(String root);
  312. virtual FileSystemRef _getFileSystemFromList(const Path& path) const ;
  313. void _setFindByPatternOverrideFS(FileSystemRef fs) { mFindByPatternOverrideFS = fs; }
  314. Path _normalize(const Path& path);
  315. Vector<MountFS> mMountList;
  316. Path mCWD;
  317. FileSystemRef mFindByPatternOverrideFS;
  318. };
  319. ///@name File System Access
  320. /// Functions for mounting file systems and dealing with files and directories.
  321. /// The kernel provides FileSystem mounting, the concept of a current working
  322. /// directory as well as relative paths.
  323. ///@{
  324. /// Mount file system
  325. ///@ingroup VolumeSystem
  326. bool Mount(String root, FileSystemRef fs);
  327. /// Mount file system redirect
  328. ///@ingroup VolumeSystem
  329. bool Mount(String root, const Path &path);
  330. /// Remove mounted file system.
  331. /// The file system object associated with the given root is unmounted.
  332. /// Open files associated with this file system are unaffected.
  333. ///@return The unmounted file system.
  334. ///@ingroup VolumeSystem
  335. FileSystemRef Unmount(String root);
  336. /// Remove mounted file system.
  337. /// Open files associated with this file system are unaffected.
  338. ///@return true if the filesystem was successfully unmounted, false otherwise (most likely, the FS was not mounted)
  339. bool Unmount(FileSystemRef fs);
  340. /// Find the the file system which owns the given file.
  341. ///@ingroup VolumeSystem
  342. FileSystemRef GetFileSystem(const Path &file);
  343. /// Find the file system node for the given file.
  344. ///@return Null if the file doesn't exist
  345. ///@ingroup VolumeSystem
  346. FileNodeRef GetFileNode(const Path &path);
  347. /// Adds a file change notification callback.
  348. ///@ingroup VolumeSystem
  349. template <class T,class U>
  350. inline bool AddChangeNotification( const Path &path, T obj, U func )
  351. {
  352. FileSystemRef fs = GetFileSystem( path );
  353. if ( !fs || !fs->getChangeNotifier() )
  354. return false;
  355. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  356. return fs->getChangeNotifier()->addNotification( path, dlg );
  357. }
  358. /// Removes an existing file change notification callback.
  359. ///@ingroup VolumeSystem
  360. template <class T,class U>
  361. inline bool RemoveChangeNotification( const Path &path, T obj, U func )
  362. {
  363. FileSystemRef fs = GetFileSystem( path );
  364. if ( !fs || !fs->getChangeNotifier() )
  365. return false;
  366. FileSystemChangeNotifier::ChangeDelegate dlg( obj, func );
  367. return fs->getChangeNotifier()->removeNotification( path, dlg );
  368. }
  369. /// Map a real file system path to a virtual one based on a root.
  370. /// This is useful when we get a real path back from an OS file dialog for example.
  371. /// e.g. If we have a root "gumby" which points at "C:/foo/bar",
  372. /// MapFSPath("gumby", "C:/foo/bar/blat/picture.png", path );
  373. /// will map "C:/foo/bar/blat/picture.png" to "gumby:/blat/picture.png"
  374. ///@param inRoot The root to check
  375. ///@param inPath The real file system path
  376. ///@param outPath The resulting volume system path
  377. ///@return Success or failure
  378. bool MapFSPath( const String &inRoot, const Path &inPath, Path &outPath );
  379. /// Returns a true file system path without virtual mounts.
  380. ///
  381. ///@param inPath The path to convert.
  382. ///@param outPath The resulting real file system path.
  383. ///
  384. bool GetFSPath( const Path &inPath, Path &outPath );
  385. /// Find files matching a pattern starting in a given dir.
  386. ///@param inBasePath path to start in
  387. ///@param inFilePattern the file pattern [it uses the FindMatch class]
  388. ///@param inRecursive do we search recursively?
  389. ///@param outList the list of files as Strings [Paths are more expensive to compute, so these may be converted on demand]
  390. ///@param multiMatch match against multiple file patterns given in inFilePattern?
  391. ///@return number of files which matched
  392. ///@ingroup VolumeSystem
  393. S32 FindByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool multiMatch = false );
  394. /// Set current working directory.
  395. ///@ingroup VolumeSystem
  396. bool SetCwd(const Path &file);
  397. /// Get the current working directory.
  398. ///@ingroup VolumeSystem
  399. const Path& GetCwd();
  400. /// Remove (or delete) a file from the file system.
  401. ///@ingroup VolumeSystem
  402. bool Remove(const Path &file);
  403. /// Rename a file or directory.
  404. ///@ingroup VolumeSystem
  405. bool Rename(const Path &from, const Path &to);
  406. /// Get the file attributes.
  407. /// @return success
  408. ///@ingroup VolumeSystem
  409. bool GetFileAttributes(const Path &path, FileNode::Attributes *attr);
  410. /// Compare modified times of p1 & p2
  411. /// @return -1 if p1 < p2, 0 if p1 == p2, 1 if p1 > p2
  412. S32 CompareModifiedTimes(const Path& p1, const Path& p2);
  413. /// Open a file.
  414. /// If the file exists a file object will be returned even if the
  415. /// open operation fails.
  416. ///@return Null if the file does not exist
  417. ///@ingroup VolumeSystem
  418. FileRef OpenFile(const Path &file, File::AccessMode mode);
  419. /// Read in an entire file
  420. /// @note Caller is responsible for freeing memory
  421. ///@param inPath the file
  422. ///@param outData the pointer to return the data
  423. ///@param outSize the size of the data returned
  424. ///@param inNullTerminate add an extra '\0' byte to the return buffer
  425. ///@return successful read? If not, outData will be NULL and outSize will be 0
  426. bool ReadFile(const Path &inPath, void *&outData, U32 &outSize, bool inNullTerminate = false );
  427. /// Open a directory.
  428. /// If the directory exists a directory object will be returned even if the
  429. /// open operation fails.
  430. ///@return Null if the file does not exist
  431. ///@ingroup VolumeSystem
  432. DirectoryRef OpenDirectory(const Path &file);
  433. /// Create a file.
  434. /// The file object is returned in a closed state.
  435. ///@ingroup VolumeSystem
  436. FileRef CreateFile(const Path &file);
  437. /// Copy a file from one location to another.
  438. bool CopyFile(const Path& source, const Path& destination, bool noOverride);
  439. /// Retrieve list of directories in the specified directory.
  440. bool DumpDirectories(const Path& path, Vector<StringTableEntry>& directories, S32 depth, bool noBasePath);
  441. /// Create a directory.
  442. /// The directory object is returned in a closed state.
  443. ///@ingroup VolumeSystem
  444. DirectoryRef CreateDirectory(const Path &file);
  445. /// Create all the directories in the path if they don't already exist
  446. ///@ingroup VolumeSystem
  447. bool CreatePath(const Path &path);
  448. bool IsReadOnly(const Path &path);
  449. bool IsDirectory(const Path &path);
  450. bool IsFile(const Path &path);
  451. bool IsScriptFile(const char* pFilePath);
  452. bool VerifyWriteAccess(const Path &path);
  453. /// This returns a unique file path from the components
  454. /// by appending numbers to the end of the file name if
  455. /// a file with the same name already exists.
  456. ///
  457. /// @param path The root and directory for the file.
  458. /// @param fileName The file name without extension.
  459. /// @param ext The dot-less extension.
  460. String MakeUniquePath( const char *path, const char *fileName, const char *ext );
  461. void StartFileChangeNotifications();
  462. void StopFileChangeNotifications();
  463. S32 GetNumMounts();
  464. String GetMountRoot( S32 index );
  465. String GetMountPath( S32 index );
  466. String GetMountType( S32 index );
  467. ///@}
  468. } // Namespace FS
  469. } // Namespace Torque
  470. #endif