#include "precomp.h"

#include "..\..\rfstool\IFilesystem.h"


char szLastKnownPartition[512] = "";

void WINAPI FoundPartitionCallback(LPCSTR lpszName, LPVOID lpContext )
{
    printf("%s is a ReiserFS partition\n", lpszName );

    // bad hack: remember first known partition

    if( szLastKnownPartition[0] == 0 )
    {
        strcpy( szLastKnownPartition, lpszName );
    }
}

/*

    Sample code: retrieve everything

*/
#define ONE_MEGABYTE    (1024*1024)

#define SIZE_OF_MEMORY_CACHE (ONE_MEGABYTE*60)


#define MAX_RETRIEVE_SIZE (ONE_MEGABYTE*200)


BYTE* memoryCache = NULL;

void GetSingleFile( IFilesystem* pInstance, LPCSTR lpszPath, UNIX_FILEINFO& fi )
{   
    if( fi.i_size > MAX_RETRIEVE_SIZE )
    {
        printf("%s is probably too large to retrieve, skipping it.\n", lpszPath );
        return;
    }
    HANDLE hFile = pInstance->OpenFile(lpszPath);
    if( hFile != INVALID_HANDLE_VALUE )
    {
        DWORD dwBytesRead;
        INT64 dwBytesActuallyRead = 0;

        while( 1 )
        {
            pInstance->ReadFile( hFile, memoryCache, SIZE_OF_MEMORY_CACHE, dwBytesRead );
            if( !dwBytesRead )
                break;
            dwBytesActuallyRead += dwBytesRead;
        }
        pInstance->CloseFile(hFile);

        if( fi.i_size != (__u64) dwBytesActuallyRead )
        {
            printf("ERROR, size mismatch: expected %"FMT_QWORD", got %"FMT_QWORD"\n", fi.i_size , dwBytesActuallyRead );
            getchar();
        }
    }
    else 
    {
        printf("ERROR, unable to open file %s <----------\n", lpszPath);
        GetSingleFile( pInstance, lpszPath, fi );
        getchar();
    }
}

void WalkTreeRecursive(IFilesystem* pInstance, LPCSTR lpszPath)
{
    printf("WalkTreeRecursive(%s)\n", lpszPath );

    int nLenOfName = strlen(lpszPath);
    char* tempBuffer = new char[nLenOfName + 2 + UNIX_FILENAME_LENGTH];
    if( tempBuffer )
    {
        HANDLE hFF = pInstance->FindFirstFile(lpszPath);
        if( hFF != INVALID_HANDLE_VALUE )
        {
            UNIX_FILEINFO fi; 
            while( pInstance->FindNextFile(hFF, fi) )
            {
                if( !strcmp(fi.szFileName,".") ||
                    !strcmp(fi.szFileName,"..") )
                    continue;

                sprintf(tempBuffer,"%s/%s", lpszPath, fi.szFileName );
                if( S_ISDIR(fi.i_mode) )
                {
                    WalkTreeRecursive(pInstance, tempBuffer);
                }
                else if( S_ISREG(fi.i_mode) )
                {
                    printf("%s (%"FMT_QWORD" bytes)\n", tempBuffer, fi.i_size );
                    GetSingleFile(pInstance, tempBuffer, fi);
                }
            }
            pInstance->CloseFind(hFF);
        }
        delete tempBuffer;
    }
}


void CheckRetrieveAllFiles(LPCSTR lpszPartition)
{
    memoryCache = new BYTE[SIZE_OF_MEMORY_CACHE];
    if( !memoryCache )
    {
        printf("ERROR, unable to allocate %d bytes\n", SIZE_OF_MEMORY_CACHE );
    }
    else
    {
        IFilesystem* pInstance = FS_CreateInstance( szLastKnownPartition );
        if( pInstance )
        {
            WalkTreeRecursive(pInstance,"");

            // finally, free up any associated memory

            pInstance->Release();
        }
        else printf("ERROR, unable to open partition %s\n", szLastKnownPartition );
        delete memoryCache;
    }
}

/******************************************************************************************************/

class MyCopyFileMethod : public ICreateFileInfo
    {
    public:
        MyCopyFileMethod( LPCSTR filename );
        virtual ~MyCopyFileMethod();
        virtual BOOL SetFileSize( INT64 Size );
        virtual void Write( LPBYTE lpbData, DWORD dwSize );

        FILE* m_pFile;
    };


MyCopyFileMethod::MyCopyFileMethod( LPCSTR filename )
{
    m_pFile = fopen(filename,"wb");
}

MyCopyFileMethod::~MyCopyFileMethod()
{
    if( m_pFile )
    {
        fclose(m_pFile);
    }
}

BOOL MyCopyFileMethod::SetFileSize( INT64 Size )
{
    return TRUE;
}

void MyCopyFileMethod::Write( LPBYTE lpbData, DWORD dwSize )
{
    if(m_pFile)
        fwrite(lpbData,dwSize,1,m_pFile);
}

void Example_CopyFile(IFilesystem* instance, LPCSTR source, LPCSTR target)
{
    MyCopyFileMethod example(target);

    if( instance->CopyFile(source, &example) )
        printf("OK, %s copied successfully to %s\n", source, target );
    else
        printf("ERROR, unable to copy %s to %s\n", source, target );
}

/******************************************************************************************************/

void Example_ListDir(IFilesystem* instance, LPCSTR lpszDir)
{
    printf("*** Listing of \"%s\":\n", lpszDir);
    HANDLE hFF = instance->FindFirstFile(lpszDir);
    if( hFF != INVALID_HANDLE_VALUE )
    {
        UNIX_FILEINFO fi; 
        while( instance->FindNextFile(hFF, fi) )
        {
            printf("%s\n", fi.szFileName );
        }
        instance->CloseFind(hFF);
    }
}

/******************************************************************************************************/

void Example_PrintFile( IFilesystem* instance, LPCSTR path)
{
    printf("*** Contents of /etc/fstab:\n" );

    HANDLE hFile = instance->OpenFile( "/etc/fstab");
    if( hFile != INVALID_HANDLE_VALUE )
    {
        BYTE buffer[10240];
        DWORD dwBytesRead = ~0;

        while( dwBytesRead )
        {
            instance->ReadFile( hFile, buffer, sizeof(buffer)-1, dwBytesRead );
            if( !dwBytesRead )
                break;
            buffer[sizeof(buffer)-1] = 0;
            fwrite(buffer,dwBytesRead,1,stdout);
        }
        instance->CloseFile(hFile);
    }
    else printf("ERROR, unable to open file \"%s\"", path);
}

int main( int argc, char* argv[] )
{
    // example 1: autodetect reiserfs partitions

    FS_Autodetect( FoundPartitionCallback, 0 );

    if( szLastKnownPartition[0] )
    {
        // example: retrieve whole partition

        //CheckRetrieveAllFiles(szLastKnownPartition);


        // example 2: open a reiserfs partition, and display a directory listing.

        IFilesystem* instance = FS_CreateInstance( szLastKnownPartition );
        if( instance )
        {
            // here are some examples

            Example_ListDir(instance, "/");
            Example_PrintFile(instance, "/etc/fstab");
            Example_CopyFile(instance, "/usr/include/stdio.h", "stdio.h");
            // copy files recursive not implemented here...


            // finally, free up any associated memory

            instance->Release();
        }
        else printf("ERROR, unable to open partition %s\n", szLastKnownPartition );

        }

	return 0;
} // main()






syntax highlighted by Code2HTML, v. 0.9.1