Beispiel #1
0
/**
 * 文字列が余分なセパレータで終わっているかどうかを返します。
 */
bool isTerminatedByRedundantSeparator(const PathString &s)
{
	// 完全修飾パス
	// \\Server\a\ => true?
	// \\Server\ => true?
	// \\?\C:\ => false
	// \\?\ => false
	// C:\a\ => true
	// C:\ => false
	//
	// 非完全修飾パス
	// \ => false
	// C:a\ => true
	// .\ => true
	// a\ => true

	std::size_t lastSepPos = s.size();
	NativeChar prevChar = AUSH_NATIVE_L('\0');
	NativeChar lastSepPrevChar = AUSH_NATIVE_L('\0');

	for(std::size_t pos = 0; pos < s.size(); pos = next_char_pos(s, pos)){
		NativeChar currChar = s[pos];
		if(is_separator()(currChar)){
			lastSepPos = pos;
			lastSepPrevChar = prevChar;
		}
		prevChar = currChar;
	}

	return (lastSepPos + 1 == s.size()
		&& lastSepPrevChar != AUSH_NATIVE_L(':')
		&& lastSepPrevChar != AUSH_NATIVE_L('?')
		&& lastSepPrevChar != AUSH_NATIVE_L('\0'));
}
Beispiel #2
0
	PathString get_program_directory()
	{
		PathString directory;

		DWORD result = GetModuleFileNameA(
			GetModuleHandleA(0),
			&directory[0],
			static_cast<DWORD>(directory.max_size())
		);

		// GetModuleFilenameA failed!
		assert(result != 0);

		char* path = &directory[0];
		char* sep;
		if (result != 0)
		{
			sep = strrchr(path, PATH_SEPARATOR);

			if (sep)
			{
				int32_t index = static_cast<int32_t>(sep - path);
				directory[index] = '\0';
				directory.recompute_size();
			}
		}

		return directory;
	}
Beispiel #3
0
FCIMPLEND

FCIMPL0(StringObject*, SystemNative::_GetModuleFileName)
{
    FCALL_CONTRACT;

    STRINGREF   refRetVal = NULL;

    HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal);
    if (g_pCachedModuleFileName)
    {
        refRetVal = StringObject::NewString(g_pCachedModuleFileName);
    }
    else
    {
        PathString wszFilePathString;

       
        DWORD lgth = WszGetModuleFileName(NULL, wszFilePathString);
        if (!lgth)
        {
            COMPlusThrowWin32();
        }
       

        refRetVal = StringObject::NewString(wszFilePathString.GetUnicode());
    }
    HELPER_METHOD_FRAME_END();

    return (StringObject*)OBJECTREFToObject(refRetVal);
}
Beispiel #4
0
ZFile::ZFile(const PathString& strPath, DWORD how) : 
    m_p(NULL)
{
	// BT - CSS - 12/8/2011 - Fixing 128 character path limit.
	DWORD dwDesiredAccess = GENERIC_READ;
	DWORD dwShareMode = FILE_SHARE_WRITE;
	DWORD dwCreationDisposition = OPEN_EXISTING;

	if((how & OF_WRITE) == OF_WRITE)
		dwDesiredAccess = GENERIC_WRITE;

	if((how & OF_SHARE_DENY_WRITE) == OF_SHARE_DENY_WRITE)
		dwShareMode = FILE_SHARE_READ;

	if((how & OF_CREATE) == OF_CREATE)
		dwCreationDisposition = CREATE_ALWAYS;

	// Unicode markers / wide format enables up to 32K path length. 
	PathString unicodePath("\\\\?\\");

	// If the path is relative, don't use unicode marker.
	if(strPath.Left(1) == ZString(".") || strPath.FindAny("//") == -1)
		unicodePath = strPath;
	else
		unicodePath += strPath;

	WCHAR* pszw = new WCHAR[unicodePath.GetLength() + 1];
    int result = MultiByteToWideChar(CP_ACP, 0, unicodePath, unicodePath.GetLength(), pszw, unicodePath.GetLength());
	pszw[result] = NULL;

	m_handle = CreateFileW(pszw, dwDesiredAccess,  dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);

	delete pszw;
	// BT - End fix.
}
 virtual String get(const String& key) const
 {
     using namespace std;
     PathString path = base_path.c_str();
     path += key;
     String value;
     int fd = open(path.c_str(), O_RDONLY);
     if (fd >= 0)
     {
         char buffer[MaxStringLength + 1];
         (void)memset(buffer, 0, sizeof(buffer));
         int len = read(fd, buffer, MaxStringLength);
         (void)close(fd);
         if (len > 0)
         {
             for (int i = 0; i < len; i++)
             {
                 if (buffer[i] == ' ' || buffer[i] == '\n' || buffer[i] == '\r' )
                 {
                     buffer[i] = '\0';
                     break;
                 }
             }
             value = buffer;
         }
     }
     return value;
 }
Beispiel #6
0
	PathString get_user_application_directory(const char* application_data_path)
	{
		PathString result = get_environment_variable("LOCALAPPDATA");
		result.append(PATH_SEPARATOR_STRING);
		result.append(application_data_path);
		result.normalize(PATH_SEPARATOR);
		return result;
	}
 virtual void set(const String& key, const String& value)
 {
     using namespace std;
     PathString path = base_path.c_str();
     path += key;
     int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, FilePermissions);
     if (fd >= 0)
     {
         (void)write(fd, value.c_str(), value.size());       // TODO FIXME Write loop
         (void)fsync(fd);
         (void)close(fd);
     }
 }
Beispiel #8
0
void Disassembler::StaticInitialize()
{
    LIMITED_METHOD_CONTRACT;

#if USE_COREDISTOOLS_DISASSEMBLER
    _ASSERTE(!IsAvailable());

    PathString libPath;
    HMODULE libraryHandle = LoadCoreDisToolsModule(libPath);
    if (libraryHandle == nullptr)
        return;

    External_InitDisasm =
        reinterpret_cast<decltype(External_InitDisasm)>(GetProcAddress(libraryHandle, "InitDisasm"));
    if (External_InitDisasm == nullptr)
    {
        DISPLAYERROR(
            W("GetProcAddress failed for library '%s', function 'InitDisasm': error %u\n"),
            libPath.GetUnicode(),
            GetLastError());
        return;
    }

    External_DisasmInstruction =
        reinterpret_cast<decltype(External_DisasmInstruction)>(GetProcAddress(libraryHandle, "DisasmInstruction"));
    if (External_DisasmInstruction == nullptr)
    {
        DISPLAYERROR(
            W("GetProcAddress failed for library '%s', function 'DisasmInstruction': error %u\n"),
            libPath.GetUnicode(),
            GetLastError());
        return;
    }

    External_FinishDisasm =
        reinterpret_cast<decltype(External_FinishDisasm)>(GetProcAddress(libraryHandle, "FinishDisasm"));
    if (External_FinishDisasm == nullptr)
    {
        DISPLAYERROR(
            W("GetProcAddress failed for library '%s', function 'FinishDisasm': error %u\n"),
            libPath.GetUnicode(),
            GetLastError());
        return;
    }

    // Set this last to indicate successful load of the library and all exports
    s_libraryHandle = libraryHandle;
    _ASSERTE(IsAvailable());
#endif // USE_COREDISTOOLS_DISASSEMBLER
}
    /**
     * Initializes the file based backend storage by passing a path to
     * the directory where the key named files will be stored.
     * The return value should be 0 on success.
     * If it is -ErrInvalidConfiguration then the the path name is too long to
     * accommodate the trailing slash and max key length.
     */
    int init(const PathString& path)
    {
        using namespace std;

        int rv = -uavcan::ErrInvalidParam;

        if (path.size() > 0)
        {
            base_path = path.c_str();

            if (base_path.back() == '/')
            {
                base_path.pop_back();
            }

            rv = 0;
            struct stat sb;
            if (stat(base_path.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode))
            {
                rv = mkdir(base_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
            }
            if (rv >= 0 )
            {
                base_path.push_back('/');
                if ((base_path.size() + MaxStringLength) > MaxPathLength)
                {
                    rv = -uavcan::ErrInvalidConfiguration;
                }
            }
        }
        return rv;
    }
Beispiel #10
0
/**
 * ファイルの拡張子(ドットを含む)を返します。
 */
PathString getFileExtension(const PathString &s)
{
	const PathString filename = getLastFileName(s);
	if(filename.empty() || filename == AUSH_NATIVE_L(".") || filename == AUSH_NATIVE_L("..")){
		return PathString();
	}

	const std::size_t pos = find_last_char(filename, is_dot());
	if(pos >= filename.size()){
		return PathString();
	}

	return filename.substr(pos);
}
Beispiel #11
0
static bool locateFile(llvm::StringRef relativePath, PathString &path) {
    // relativePath has no suffix
    for (unsigned i = 0; i < searchPath.size(); ++i) {
        PathString pathWOSuffix(searchPath[i]);
        llvm::sys::path::append(pathWOSuffix, relativePath);
        for (unsigned j = 0; j < moduleSuffixes.size(); ++j) {
            path = pathWOSuffix;
            path.append(moduleSuffixes[j].begin(), moduleSuffixes[j].end());
            if (llvm::sys::fs::exists(path.str()))
                return true;
        }
    }
    return false;
}
Beispiel #12
0
    Bool FileSystem::Load( const PathString& fileName, void *& buffer, SizeT& size )
    {
        FILE * pFile;
        if ( fopen_s( &pFile, fileName.ConstPtr(), "rb" ) )
        {
            return false;
        }

        fseek( pFile , 0 , SEEK_END );
        size = ftell( pFile );

        if ( size == 0 )
        {
            fclose( pFile );
            return true;
        }

        rewind( pFile );

        buffer = UnknownAllocator::Allocate( size );

        if ( fread( buffer, 1, size, pFile ) != size )
        {
            UnknownAllocator::Deallocate( buffer );
            size = 0;
            fclose( pFile );
            return false;
        }

        fclose(pFile);

        return true;
    }
Beispiel #13
0
    void ResourceManager::Add( const Char * name, Resource * res )
    {
        PathString path;
        FileSystem::BuildPathName( name, path, FileSystem::PT_CACHE );

        ResourceRequest req;
        req.m_res = res;
        StringUtils::StrCpy( req.m_path, 256, path.ConstPtr() );
        if ( !res->IsPending() )
        {
            res->m_state |= Resource::PENDING;
            pendingResources.PushBack( req );
        }

        resourceTable.Insert( res->GetId(), res );
    }
Beispiel #14
0
    virtual void onEvent(uavcan::dynamic_node_id_server::TraceCode code, uavcan::int64_t argument)
    {
        using namespace std;

        timespec ts = timespec();               // If clock_gettime() fails, zero time will be used
        (void)clock_gettime(CLOCK_REALTIME, &ts);

        int fd = open(path_.c_str(), O_WRONLY | O_CREAT | O_APPEND, FilePermissions);
        if (fd >= 0)
        {
            const int FormatBufferLength = 63;
            char buffer[FormatBufferLength + 1];
            ssize_t remaining = snprintf(buffer, FormatBufferLength, "%ld.%06ld\t%d\t%lld\n",
                                         static_cast<long>(ts.tv_sec), static_cast<long>(ts.tv_nsec / 1000L),
                                         static_cast<int>(code), static_cast<long long>(argument));

            ssize_t total_written = 0;
            ssize_t written = 0;
            do
            {
                written = write(fd, &buffer[total_written], remaining);
                if (written > 0)
                {
                    total_written += written;
                    remaining -=  written;
                }
            }
            while (written > 0 && remaining > 0);
            (void)close(fd);
        }
    }
Beispiel #15
0
    void ProgramCache::LoadProgramFromBinaries( Program& program )
    {
        PathString binFileName = m_cachePath;
        binFileName += "/";
        binFileName += program.m_name;
        binFileName += ".bin";

        if ( FileSystem::Exists( binFileName ) )
        {
            PathString searchStr = m_dataPath;
            searchStr += "/";
            searchStr += program.m_name;
            searchStr += ".*";

            Array< PathString > shaderFileNames;
            FileSystem::Find( searchStr.ConstPtr(), shaderFileNames );

            U64 binLastWriteTime = FileSystem::GetLastWriteTime( binFileName );

            Bool binIsUpToDate = true;

            Array< PathString >::ConstIterator it = shaderFileNames.Begin();
            Array< PathString >::ConstIterator end = shaderFileNames.End();
            for ( ; it != end; ++it )
            {
                const PathString& shaderFileName = *it;

                if ( binLastWriteTime < FileSystem::GetLastWriteTime( shaderFileName ) )
                {
                    binIsUpToDate = false;
                    break;
                }
            }

            if ( binIsUpToDate )
            {
                SizeT size;
                void * buffer;
                if ( FileSystem::Load( binFileName, buffer, size ) )
                {
                    program.m_handle = RenderDevice::CreateProgramBinary( buffer, size ); 
                    UnknownAllocator::Deallocate( buffer );
                }
            }
        }
    }
Beispiel #16
0
/**
 * パス末尾の余分なセパレータを切り落とした文字列を返します。
 *
 * 切り落とすのは余分なセパレータであり、切り落とすことによって意味が変わってしまう場合は切り落としません。
 */
PathString chopLastRedundantSeparator(const PathString &s)
{
	if(isTerminatedByRedundantSeparator(s)){
		return PathString(s, 0, s.size() - 1);
	}
	else{
		return s;
	}
}
Beispiel #17
0
    /**
     * Initializes the file based event tracer.
     */
    int init(const PathString& path)
    {
        using namespace std;

        int rv = -uavcan::ErrInvalidParam;

        if (path.size() > 0)
        {
            rv = 0;
            path_ = path.c_str();
            int fd = open(path_.c_str(), O_RDWR | O_CREAT | O_TRUNC, FilePermissions);
            if (fd >= 0)
            {
                (void)close(fd);
            }
        }
        return rv;
    }
Beispiel #18
0
    void FileSystem::Initialize( const Char * root, const Char * dataDir, const Char * cacheDir )
    {
        CARBON_ASSERT( rootPath.Empty() );
        CARBON_ASSERT( dataPath.Empty() );
        CARBON_ASSERT( cachePath.Empty() );

        rootPath = root;

        dataPath = rootPath;
        dataPath += "/";
        dataPath += dataDir;
        dataPath += "/";

        cachePath = rootPath;
        cachePath += "/";
        cachePath += cacheDir;
        cachePath += "/";
    }
Beispiel #19
0
VOID LogAssert(
    LPCSTR      szFile,
    int         iLine,
    LPCSTR      szExpr
)
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_GC_NOTRIGGER;
    STATIC_CONTRACT_SO_TOLERANT;
    STATIC_CONTRACT_DEBUG_ONLY;

    // Log asserts to the stress log. Note that we can't include the szExpr b/c that 
    // may not be a string literal (particularly for formatt-able asserts).
    STRESS_LOG2(LF_ASSERT, LL_ALWAYS, "ASSERT:%s, line:%d\n", szFile, iLine);

    SYSTEMTIME st;
#ifndef FEATURE_PAL
    GetLocalTime(&st);
#else
    GetSystemTime(&st);
#endif

    PathString exename;
    WszGetModuleFileName(NULL, exename);

    LOG((LF_ASSERT,
         LL_FATALERROR,
         "FAILED ASSERT(PID %d [0x%08x], Thread: %d [0x%x]) (%lu/%lu/%lu: %02lu:%02lu:%02lu %s): File: %s, Line %d : %s\n",
         GetCurrentProcessId(),
         GetCurrentProcessId(),
         GetCurrentThreadId(),
         GetCurrentThreadId(),
         (ULONG)st.wMonth,
         (ULONG)st.wDay,
         (ULONG)st.wYear,
         1 + (( (ULONG)st.wHour + 11 ) % 12),
         (ULONG)st.wMinute,
         (ULONG)st.wSecond,
         (st.wHour < 12) ? "am" : "pm",
         szFile,
         iLine,
         szExpr));
    LOG((LF_ASSERT, LL_FATALERROR, "RUNNING EXE: %ws\n", exename.GetUnicode()));
}
Beispiel #20
0
    Bool FileSystem::Exists( const PathString& fileName )
    {
        HANDLE hFile = CreateFile( fileName.ConstPtr(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if ( hFile == INVALID_HANDLE_VALUE )
        {
            return false;
        }

        CloseHandle( hFile );
        return true;
    }
Beispiel #21
0
// Convert an absolute path to a path that's relative to "&relativeTo".
PathString PathString::AbsolutePathToRelative(const PathString &relativeTo) const
//-------------------------------------------------------------------------------
{
	mpt::PathString result = path;
	if(path.empty())
	{
		return result;
	}
	if(!_wcsnicmp(relativeTo.AsNative().c_str(), AsNative().c_str(), relativeTo.AsNative().length()))
	{
		// Path is OpenMPT's directory or a sub directory ("C:\OpenMPT\Somepath" => ".\Somepath")
		result = MPT_PATHSTRING(".\\"); // ".\"
		result += mpt::PathString::FromNative(AsNative().substr(relativeTo.AsNative().length()));
	} else if(!_wcsnicmp(relativeTo.AsNative().c_str(), AsNative().c_str(), 2))
	{
		// Path is on the same drive as OpenMPT ("C:\Somepath" => "\Somepath")
		result = mpt::PathString::FromNative(AsNative().substr(2));
	}
	return result;
}
Beispiel #22
0
/**
 * フルパス名を求めます。
 */
PathString getFullPath(const PathString &s)
{
	const DWORD bufferLen = MAX_PATH;
	TCHAR *filePart;
	TCHAR buffer[bufferLen + 1];
	DWORD len = GetFullPathName(s.c_str(), bufferLen, buffer, &filePart);
	if(len == 0 || len >= bufferLen){
		return PathString();
	}
	return PathString(buffer);
}
static PRLibrary*
MozAVLink(nsIFile* aFile)
{
  PRLibSpec lspec;
  PathString path = aFile->NativePath();
#ifdef XP_WIN
  lspec.type = PR_LibSpec_PathnameU;
  lspec.value.pathname_u = path.get();
#else
  lspec.type = PR_LibSpec_Pathname;
  lspec.value.pathname = path.get();
#endif
#ifdef MOZ_WIDGET_ANDROID
  PRLibrary* lib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_GLOBAL);
#else
  PRLibrary* lib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
#endif
  if (!lib) {
    FFMPEG_LOG("unable to load library %s", aFile->HumanReadablePath().get());
  }
  return lib;
}
Beispiel #24
0
    Bool FileSystem::Save( const PathString& fileName, const void * buffer, SizeT size )
    {
        Char dir[ 256 ];
        Char * fileStart;

        if ( GetFullPathName( fileName.ConstPtr(), 256, dir, &fileStart ) == 0 )
        {
            return false;
        }
        *( fileStart - 1 ) = 0;

        if ( ! RecursiveCreateDirectory( dir ) )
        {
            return false;
        }

        FILE * pFile;
        if ( fopen_s( &pFile, fileName.ConstPtr(), "wb" ) )
        {
            return false;
        }

        if ( size == 0 )
        {
            fclose( pFile );
            return true;
        }

        if ( fwrite( buffer, 1, size, pFile ) != size )
        {
            fclose( pFile );
            return false;
        }

        fclose(pFile);

        return true;
    }
Beispiel #25
0
/**
 * フルパス名のファイル部分を除いた物を求めます。
 *
 * chopLastFileName(getFullPath(s))とほぼ同じだと思います。
 */
PathString getFullPathDir(const PathString &s)
{
	const DWORD bufferLen = MAX_PATH;
	TCHAR *filePart;
	TCHAR buffer[bufferLen + 1];
	DWORD len = GetFullPathName(s.c_str(), bufferLen, buffer, &filePart);
	if(len == 0 || len == bufferLen){
		return PathString();
	}

	if(filePart == NULL){
		return PathString(buffer); // sがパス区切りで終わっていたり、//serverや//server/shareのようなUNC先頭。
	}
	else{
		return PathString(buffer, filePart); //ファイル部の直前までを返す。
	}
}
Beispiel #26
0
// Convert a path that is relative to "&relativeTo" to an absolute path.
PathString PathString::RelativePathToAbsolute(const PathString &relativeTo) const
//-------------------------------------------------------------------------------
{
	mpt::PathString result = path;
	if(path.empty())
	{
		return result;
	}
	if(AsNative().length() >= 2 && AsNative().substr(0, 1) == L"\\" && AsNative().substr(0, 2) != L"\\\\")
	{
		// Path is on the same drive as OpenMPT ("\Somepath\" => "C:\Somepath\"), but ignore network paths starting with "\\"
		result = mpt::PathString::FromNative(relativeTo.AsNative().substr(0, 2));
		result += path;
	} else if(AsNative().length() >= 2 && AsNative().substr(0, 2) == L".\\")
	{
		// Path is OpenMPT's directory or a sub directory (".\Somepath\" => "C:\OpenMPT\Somepath\")
		result = relativeTo; // "C:\OpenMPT\"
		result += mpt::PathString::FromNative(AsNative().substr(2));
	}
	return result;
}
Beispiel #27
0
    HRESULT FileOrDirectoryExists(PathString &path)
    {
        HRESULT hr = S_FALSE;

        DWORD dwFileAttributes = WszGetFileAttributes(path.GetUnicode());
        if (dwFileAttributes == INVALID_FILE_ATTRIBUTES)
        {
            hr = HRESULT_FROM_GetLastError();

            if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) ||
                (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)))
            {
                hr = S_FALSE;
            }
        }
        else
        {
            hr = S_TRUE;
        }

        return hr;
    }
Beispiel #28
0
    U64 FileSystem::GetLastWriteTime( const PathString& fileName )
    {
        HANDLE hFile = CreateFile( fileName.ConstPtr(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

        if ( hFile == INVALID_HANDLE_VALUE )
        {
            return 0;
        }

        FILETIME ftCreate, ftAccess, ftWrite;
        if ( !GetFileTime( hFile, &ftCreate, &ftAccess, &ftWrite ) )
        {
            CloseHandle(hFile);
            return 0;
        }

        CloseHandle(hFile);

        ULARGE_INTEGER tmp;
        tmp.LowPart     = ftWrite.dwLowDateTime;
        tmp.HighPart    = ftWrite.dwHighDateTime;
        
        return tmp.QuadPart;
    }
Beispiel #29
0
int PathString::CompareNoCase(const PathString & a, const PathString & b)
//-----------------------------------------------------------------------
{
	return lstrcmpiW(a.ToWide().c_str(), b.ToWide().c_str());
}
Beispiel #30
0
namespace Core
{
    static PathString rootPath;
    static PathString dataPath;
    static PathString cachePath;

    Bool RecursiveCreateDirectory( const Char * dir )
    {
        if ( ! CreateDirectory( dir, NULL ) )
        {
            DWORD err = GetLastError();
            if ( err == ERROR_ALREADY_EXISTS )
            {
                return true;
            }
            if ( err == ERROR_PATH_NOT_FOUND )
            {
                Char * fileStart;
                Char parentDir[ 256 ];
                if ( GetFullPathName( dir, 256, parentDir, &fileStart ) == 0 )
                {
                    return false;
                }
                *(fileStart - 1 ) = 0;

                if ( RecursiveCreateDirectory( parentDir ) )
                {
                    return ( CreateDirectory( dir, NULL ) != 0 );
                }

                return false;
            }

            return false;
        }

        return true;
    }

    void FileSystem::Initialize( const Char * root, const Char * dataDir, const Char * cacheDir )
    {
        CARBON_ASSERT( rootPath.Empty() );
        CARBON_ASSERT( dataPath.Empty() );
        CARBON_ASSERT( cachePath.Empty() );

        rootPath = root;

        dataPath = rootPath;
        dataPath += "/";
        dataPath += dataDir;
        dataPath += "/";

        cachePath = rootPath;
        cachePath += "/";
        cachePath += cacheDir;
        cachePath += "/";
    }

    void FileSystem::Destroy()
    {
        rootPath.Clear();
        dataPath.Clear();
        cachePath.Clear();
    }

    void FileSystem::BuildPathName( const Char * src, PathString& dest, PathType relativeTo )
    {
        switch ( relativeTo )
        {
        case PT_ROOT:
            dest = rootPath;
            break;
        case PT_DATA:
            dest = dataPath;
            break;
        case PT_CACHE:
            dest = cachePath;
            break;
        };

        dest += src;
    }

    Bool FileSystem::Load( const PathString& fileName, void *& buffer, SizeT& size )
    {
        FILE * pFile;
        if ( fopen_s( &pFile, fileName.ConstPtr(), "rb" ) )
        {
            return false;
        }

        fseek( pFile , 0 , SEEK_END );
        size = ftell( pFile );

        if ( size == 0 )
        {
            fclose( pFile );
            return true;
        }

        rewind( pFile );

        buffer = UnknownAllocator::Allocate( size );

        if ( fread( buffer, 1, size, pFile ) != size )
        {
            UnknownAllocator::Deallocate( buffer );
            size = 0;
            fclose( pFile );
            return false;
        }

        fclose(pFile);

        return true;
    }

    Bool FileSystem::Save( const PathString& fileName, const void * buffer, SizeT size )
    {
        Char dir[ 256 ];
        Char * fileStart;

        if ( GetFullPathName( fileName.ConstPtr(), 256, dir, &fileStart ) == 0 )
        {
            return false;
        }
        *( fileStart - 1 ) = 0;

        if ( ! RecursiveCreateDirectory( dir ) )
        {
            return false;
        }

        FILE * pFile;
        if ( fopen_s( &pFile, fileName.ConstPtr(), "wb" ) )
        {
            return false;
        }

        if ( size == 0 )
        {
            fclose( pFile );
            return true;
        }

        if ( fwrite( buffer, 1, size, pFile ) != size )
        {
            fclose( pFile );
            return false;
        }

        fclose(pFile);

        return true;
    }

    Bool FileSystem::Exists( const PathString& fileName )
    {
        HANDLE hFile = CreateFile( fileName.ConstPtr(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if ( hFile == INVALID_HANDLE_VALUE )
        {
            return false;
        }

        CloseHandle( hFile );
        return true;
    }

    Bool FileSystem::Find( const Char * searchStr, Core::Array< PathString >& fileNames, Bool absolute )
    {
        WIN32_FIND_DATA ffd;
        HANDLE hFind;

        hFind = FindFirstFile( searchStr, &ffd );
        if ( hFind == INVALID_HANDLE_VALUE ) 
        {
            return false;
        }

        Char dir[ 256 ];
        Char * fileStart = dir;

        if ( absolute )
        {
            if ( GetFullPathName( searchStr, 256, dir, &fileStart ) == 0 )
            {
                return false;
            }
        }

        do
        {
            if ( ! ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
            {
                PathString f( dir, fileStart - dir );
                f += ffd.cFileName;
                fileNames.PushBack( f );
            }
        }
        while ( FindNextFile( hFind, &ffd ) != 0 );

        FindClose( hFind );

        return true;
    }

    U64 FileSystem::GetLastWriteTime( const PathString& fileName )
    {
        HANDLE hFile = CreateFile( fileName.ConstPtr(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

        if ( hFile == INVALID_HANDLE_VALUE )
        {
            return 0;
        }

        FILETIME ftCreate, ftAccess, ftWrite;
        if ( !GetFileTime( hFile, &ftCreate, &ftAccess, &ftWrite ) )
        {
            CloseHandle(hFile);
            return 0;
        }

        CloseHandle(hFile);

        ULARGE_INTEGER tmp;
        tmp.LowPart     = ftWrite.dwLowDateTime;
        tmp.HighPart    = ftWrite.dwHighDateTime;
        
        return tmp.QuadPart;
    }
}