driver GetDirListing, write logic, fixes
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "RageFileDriver.h"
|
#include "RageFileDriver.h"
|
||||||
|
#include "RageUtil.h"
|
||||||
|
|
||||||
void RageFileObj::SetError( const CString &err )
|
void RageFileObj::SetError( const CString &err )
|
||||||
{
|
{
|
||||||
@@ -58,6 +59,40 @@ int RageFileObj::GetFileSize()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RageFileDriver::GetPathValue( CString path )
|
||||||
|
{
|
||||||
|
vector<CString> parts;
|
||||||
|
split( path, SLASH, parts, true );
|
||||||
|
|
||||||
|
CString PartialPath;
|
||||||
|
|
||||||
|
for( unsigned i = 0; i < parts.size(); ++i )
|
||||||
|
{
|
||||||
|
PartialPath += parts[i];
|
||||||
|
if( i+1 < parts.size() )
|
||||||
|
PartialPath += SLASH;
|
||||||
|
|
||||||
|
const RageFileManager::FileType Type = GetFileType( PartialPath );
|
||||||
|
switch( Type )
|
||||||
|
{
|
||||||
|
case RageFileManager::TYPE_NONE:
|
||||||
|
return parts.size()-i;
|
||||||
|
|
||||||
|
/* If this is the last part (the whole path), it needs to be a file; otherwise a directory. */
|
||||||
|
case RageFileManager::TYPE_FILE:
|
||||||
|
if( i != parts.size()-1 )
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case RageFileManager::TYPE_DIR:
|
||||||
|
if( i == parts.size()-1 )
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
||||||
* Glenn Maynard
|
* Glenn Maynard
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ class RageFileDriver
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual RageFileObj *Open( CString path, RageFile::OpenMode mode, RageFile &p, int &err ) = 0;
|
virtual RageFileObj *Open( CString path, RageFile::OpenMode mode, RageFile &p, int &err ) = 0;
|
||||||
|
virtual void GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo ) = 0;
|
||||||
virtual RageFileManager::FileType GetFileType( CString sPath ) = 0;
|
virtual RageFileManager::FileType GetFileType( CString sPath ) = 0;
|
||||||
virtual int GetFileSizeInBytes( CString sFilePath ) = 0;
|
virtual int GetFileSizeInBytes( CString sFilePath ) = 0;
|
||||||
virtual int GetFileModTime( CString sPath ) = 0;
|
virtual int GetFileModTime( CString sPath ) = 0;
|
||||||
|
virtual int GetPathValue( CString path );
|
||||||
virtual bool Ready() { return true; } /* see RageFileManager::MountpointIsReady */
|
virtual bool Ready() { return true; } /* see RageFileManager::MountpointIsReady */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,24 @@ RageFileDriverDirect::RageFileDriverDirect( CString root_ ):
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FDB_GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo );
|
||||||
|
|
||||||
|
void RageFileDriverDirect::GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo )
|
||||||
|
{
|
||||||
|
const unsigned OldStart = AddTo.size();
|
||||||
|
FDB_GetDirListing( root+sPath, AddTo, bOnlyDirs, bReturnPathToo );
|
||||||
|
|
||||||
|
if( bReturnPathToo )
|
||||||
|
{
|
||||||
|
/* Remove the root path. */
|
||||||
|
for( unsigned j = OldStart; j < AddTo.size(); ++j )
|
||||||
|
AddTo[j].erase( 0, root.size() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RageFileObj *RageFileDriverDirect::Open( CString sPath, RageFile::OpenMode mode, RageFile &p, int &err )
|
RageFileObj *RageFileDriverDirect::Open( CString sPath, RageFile::OpenMode mode, RageFile &p, int &err )
|
||||||
{
|
{
|
||||||
|
sPath = root + sPath;
|
||||||
ResolvePath( sPath );
|
ResolvePath( sPath );
|
||||||
int flags = O_BINARY;
|
int flags = O_BINARY;
|
||||||
if( mode == RageFile::READ )
|
if( mode == RageFile::READ )
|
||||||
@@ -51,7 +67,7 @@ RageFileObj *RageFileDriverDirect::Open( CString sPath, RageFile::OpenMode mode,
|
|||||||
else
|
else
|
||||||
flags |= O_WRONLY|O_CREAT|O_TRUNC;
|
flags |= O_WRONLY|O_CREAT|O_TRUNC;
|
||||||
|
|
||||||
int fd = open( root + sPath, flags, 0644 );
|
int fd = open( sPath, flags, 0644 );
|
||||||
if( fd == -1 )
|
if( fd == -1 )
|
||||||
{
|
{
|
||||||
err = errno;
|
err = errno;
|
||||||
@@ -69,6 +85,8 @@ static bool DoStat(CString sPath, struct stat *st)
|
|||||||
|
|
||||||
RageFileManager::FileType RageFileDriverDirect::GetFileType( CString sPath )
|
RageFileManager::FileType RageFileDriverDirect::GetFileType( CString sPath )
|
||||||
{
|
{
|
||||||
|
sPath = root + sPath;
|
||||||
|
|
||||||
ResolvePath( sPath );
|
ResolvePath( sPath );
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -83,15 +101,19 @@ RageFileManager::FileType RageFileDriverDirect::GetFileType( CString sPath )
|
|||||||
|
|
||||||
int RageFileDriverDirect::GetFileSizeInBytes( CString sPath )
|
int RageFileDriverDirect::GetFileSizeInBytes( CString sPath )
|
||||||
{
|
{
|
||||||
|
sPath = root + sPath;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if( !DoStat(sPath, &st) )
|
if( !DoStat(sPath, &st) )
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
return st.st_size;
|
return st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RageFileDriverDirect::GetFileModTime( CString sPath )
|
int RageFileDriverDirect::GetFileModTime( CString sPath )
|
||||||
{
|
{
|
||||||
|
sPath = root + sPath;
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if( !DoStat(sPath, &st) )
|
if( !DoStat(sPath, &st) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public:
|
|||||||
virtual ~RageFileDriverDirect() { }
|
virtual ~RageFileDriverDirect() { }
|
||||||
|
|
||||||
RageFileObj *Open( CString path, RageFile::OpenMode mode, RageFile &p, int &err );
|
RageFileObj *Open( CString path, RageFile::OpenMode mode, RageFile &p, int &err );
|
||||||
|
void GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo );
|
||||||
RageFileManager::FileType GetFileType( CString sPath );
|
RageFileManager::FileType GetFileType( CString sPath );
|
||||||
int GetFileSizeInBytes( CString sFilePath );
|
int GetFileSizeInBytes( CString sFilePath );
|
||||||
int GetFileModTime( CString sPath );
|
int GetFileModTime( CString sPath );
|
||||||
|
|||||||
@@ -70,6 +70,26 @@ CString LoadedDriver::GetPath( CString path )
|
|||||||
return path.Right( path.size() - MountPoint.size() );
|
return path.Right( path.size() - MountPoint.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RageFileManager::GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo )
|
||||||
|
{
|
||||||
|
for( unsigned i = 0; i < g_Drivers.size(); ++i )
|
||||||
|
{
|
||||||
|
LoadedDriver &ld = g_Drivers[i];
|
||||||
|
const CString p = ld.GetPath( sPath );
|
||||||
|
if( p.size() == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const unsigned OldStart = AddTo.size();
|
||||||
|
|
||||||
|
g_Drivers[i].driver->GetDirListing( p, AddTo, bOnlyDirs, bReturnPathToo );
|
||||||
|
|
||||||
|
/* If returning the path, prepend the mountpoint name to the files this driver returned. */
|
||||||
|
if( bReturnPathToo )
|
||||||
|
for( unsigned j = OldStart; j < AddTo.size(); ++j )
|
||||||
|
AddTo[j] = ld.MountPoint + AddTo[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#include "RageFileDriverDirect.h"
|
#include "RageFileDriverDirect.h"
|
||||||
void RageFileManager::Mount( CString Type, CString Root, CString MountPoint )
|
void RageFileManager::Mount( CString Type, CString Root, CString MountPoint )
|
||||||
@@ -165,11 +185,21 @@ int RageFileManager::GetFileModTime( const CString &sPath )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool SortBySecond( const pair<int,int> &a, const pair<int,int> &b )
|
||||||
|
{
|
||||||
|
return a.second < b.second;
|
||||||
|
}
|
||||||
|
|
||||||
/* Used only by RageFile: */
|
/* Used only by RageFile: */
|
||||||
RageFileObj *RageFileManager::Open( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err )
|
RageFileObj *RageFileManager::Open( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err )
|
||||||
{
|
{
|
||||||
err = ENOENT;
|
err = ENOENT;
|
||||||
|
|
||||||
|
/* If writing, we need to do a heuristic to figure out which driver to write with--there
|
||||||
|
* may be several that will work. */
|
||||||
|
if( mode == RageFile::WRITE )
|
||||||
|
return OpenForWriting( sPath, mode, p, err );
|
||||||
|
|
||||||
/* XXX: WRITE logic */
|
/* XXX: WRITE logic */
|
||||||
for( unsigned i = 0; i < g_Drivers.size(); ++i )
|
for( unsigned i = 0; i < g_Drivers.size(); ++i )
|
||||||
{
|
{
|
||||||
@@ -190,6 +220,67 @@ RageFileObj *RageFileManager::Open( const CString &sPath, RageFile::OpenMode mod
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RageFileObj *RageFileManager::OpenForWriting( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The value for a driver to open a file is the number of directories and/or files
|
||||||
|
* that would have to be created in order to write it, or 0 if the file already exists.
|
||||||
|
* For example, if we're opening "foo/bar/baz.txt", and only "foo/" exists in a
|
||||||
|
* driver, we'd have to create the "bar" directory and the "baz.txt" file, so the
|
||||||
|
* value is 2. If "foo/bar/" exists, we'd only have to create the file, so the
|
||||||
|
* value is 1. Create the file with the driver that returns the lowest value;
|
||||||
|
* in case of a tie, earliest-loaded driver wins.
|
||||||
|
*
|
||||||
|
* The purpose of this is to create files in the expected place. For example, if we
|
||||||
|
* have both C:/games/StepMania and C:/games/DWI loaded, and we're writing
|
||||||
|
* "Songs/Music/Waltz/waltz.sm", and the song was loaded out of
|
||||||
|
* "C:/games/DWI/Songs/Music/Waltz/waltz.dwi", we want to write the new SM into the
|
||||||
|
* same directory (if possible). Don't split up files in the same directory any
|
||||||
|
* more than we have to.
|
||||||
|
*
|
||||||
|
* If the given path can not be created, return -1. This happens if a path
|
||||||
|
* that needs to be a directory is a file, or vice versa.
|
||||||
|
*/
|
||||||
|
vector< pair<int,int> > Values;
|
||||||
|
unsigned i;
|
||||||
|
for( i = 0; i < g_Drivers.size(); ++i )
|
||||||
|
{
|
||||||
|
LoadedDriver &ld = g_Drivers[i];
|
||||||
|
const CString path = ld.GetPath( sPath );
|
||||||
|
if( path.size() == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const int value = ld.driver->GetPathValue( path );
|
||||||
|
if( value == -1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Values.push_back( pair<int,int>( i, value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Values.size() )
|
||||||
|
{
|
||||||
|
err = EEXIST;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
stable_sort( Values.begin(), Values.end(), SortBySecond );
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
for( i = 0; i < Values.size(); ++i )
|
||||||
|
{
|
||||||
|
const int driver = Values[i].first;
|
||||||
|
LoadedDriver &ld = g_Drivers[driver];
|
||||||
|
const CString path = ld.GetPath( sPath );
|
||||||
|
ASSERT( path.size() );
|
||||||
|
|
||||||
|
RageFileObj *ret = ld.driver->Open( path, mode, p, error );
|
||||||
|
if( ret )
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
err = error;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool RageFileManager::IsAFile( const CString &sPath ) { return GetFileType(sPath) == TYPE_FILE; }
|
bool RageFileManager::IsAFile( const CString &sPath ) { return GetFileType(sPath) == TYPE_FILE; }
|
||||||
bool RageFileManager::IsADirectory( const CString &sPath ) { return GetFileType(sPath) == TYPE_DIR; }
|
bool RageFileManager::IsADirectory( const CString &sPath ) { return GetFileType(sPath) == TYPE_DIR; }
|
||||||
bool RageFileManager::DoesFileExist( const CString &sPath ) { return GetFileType(sPath) != TYPE_NONE; }
|
bool RageFileManager::DoesFileExist( const CString &sPath ) { return GetFileType(sPath) != TYPE_NONE; }
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ public:
|
|||||||
RageFileManager();
|
RageFileManager();
|
||||||
~RageFileManager();
|
~RageFileManager();
|
||||||
|
|
||||||
|
void GetDirListing( CString sPath, CStringArray &AddTo, bool bOnlyDirs, bool bReturnPathToo );
|
||||||
|
|
||||||
enum FileType { TYPE_FILE, TYPE_DIR, TYPE_NONE };
|
enum FileType { TYPE_FILE, TYPE_DIR, TYPE_NONE };
|
||||||
FileType GetFileType( const CString &sPath );
|
FileType GetFileType( const CString &sPath );
|
||||||
|
|
||||||
@@ -26,6 +28,9 @@ public:
|
|||||||
|
|
||||||
/* Used only by RageFile: */
|
/* Used only by RageFile: */
|
||||||
RageFileObj *Open( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err );
|
RageFileObj *Open( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err );
|
||||||
|
|
||||||
|
private:
|
||||||
|
RageFileObj *OpenForWriting( const CString &sPath, RageFile::OpenMode mode, RageFile &p, int &err );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern RageFileManager *FILEMAN;
|
extern RageFileManager *FILEMAN;
|
||||||
|
|||||||
Reference in New Issue
Block a user