volume.h

Engine/source/core/volume.h

More...

Classes:

Namespaces:

namespace
namespace

Detailed Description

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