/* ********************************************
*
* Apliacation to archive multiple files into
* a single file, without compression
*
* (c) Travis Smith [2007]
*
*************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char * HEADER = "NCA v0.2";
char * archive;
struct FILE_OBJ
{
char * filename;
char * filedata;
int size;
};
typedef struct FILE_OBJ FileObj;
/*******************************
*
* ADD
*
* When writing to the file
* the following sytax is used:
*
* One time:
* 1) One line for the NCA header
* Fpr Every File:
* 2) One line for the file name
* 3) One line for the size of the file
* 4) Binary file data
*
* *****************************/
void addToArchive( char * toAdd )
{
FileObj myFile;
FILE *in;
FILE *out;
myFile.filename = toAdd;
// Tell the user which file is being archived
printf( "Archiving file: %s\n", toAdd );
// Open the input stream
in = fopen( toAdd, "rb" );
// Get the size in bytes of the file
fseek( in, 0, SEEK_END );
myFile.size = ftell( in );
// Re-open the file
fclose( in );
in = fopen( toAdd, "rb" );
// Initialize the filedata string
myFile.filedata = (char *)malloc( myFile.size +1 );
// Read the file and store its contents
fread( myFile.filedata, 1, myFile.size, in );
//printf( "File data read\n" );
// Done reading, close the input stream
fclose( in );
// Open an output stream
out = fopen( archive, "ab" );
// If the file doesn't exist, create it and write the header
if ( ftell( out ) == 0 )
fprintf( out, "%s\n", HEADER );
// Print the file name and filesize to the stream
fprintf( out, "%s\n%i\n", myFile.filename, myFile.size );
// Print the file data itself to the stream
fwrite( myFile.filedata, 1, myFile.size, out );
// Close the stream
fclose( out );
// Free allocated memory
free( myFile.filedata );
myFile.filedata = NULL;
}
/*******************************
*
* LIST
*
* ****************************/
void list( )
{
FILE * in = fopen( archive, "rb" );
char * buff = (char *)malloc( 256 );
// Read in the header
fgets( buff, 256, in );
printf( "Header: %s", buff );
printf( "Files archived in %s: \n", archive );
// Read in the names and file sizes for each file
while( fgets( buff, 256, in ) )
{
buff[ strlen(buff) -1 ] = '\0';
// Buff is the filename, without the \n
printf( "\t%s ", buff );
// Read in the file size
fgets( buff, 256, in );
printf( "\t%i bytes\n", atoi( buff ) );
// Skip over the binary data
fseek( in, atoi( buff ), SEEK_CUR );
}
// Free allocated memory
free( buff );
buff = NULL;
}
/*******************************
*
* EXTRACT
*
* *****************************/
void extractAll( )
{
FILE * in; // In stream
FILE * out; // Out stream
char * buff; // buffer for text data
char * filedata; // Buffer for binary data
long size; // Size of binary data
buff = (char *)malloc(256);
in = fopen( archive, "rb" );
// Read in the header
fgets( buff, 256, in );
printf( "Header: %s", buff );
// Read in the names and file sizes for each
// And write the filedata to new files
while( fgets( buff, 256, in ) )
{
buff[ strlen(buff) -1 ] = '\0';
// Tell the user which file is being extracted
printf( "Extracting: %s\n", buff );
// Create the new file
out = fopen( buff, "w+b" );
// Get the size of the file
fgets( buff, 256, in );
size = atoi( buff );
// Prepare filedata buffer
filedata = (char *)malloc(size +1);
// Read in the file data
fread( filedata, 1, size, in );
// Wrote the file to disk
fwrite( filedata, 1, size, out );
// Close the output file
fclose( out );
// Free allocated memory
free( filedata );
filedata = NULL;
} // While
fclose( in );
// Free allocated memory
free( buff );
buff = NULL;
}
/*******************************
*
* MAIN
*
* ******************************/
int main( int argc, char *argv[] )
{
int i; // Loop counter
archive = argv[ 2 ];
char * usage = "Usage: nca [OPTION] [FILE]...\n"
"nca saves many files together into a single archive,"
"without using any compression\n"
"\nExamples: \n"
" nca -a archive.nca foo.txt bar.mp3 \n"
" nca -l archive.nca \n"
" nca -e archive.nca \n"
"\nFlags are: \n"
"\t-a, --add \t\tAdd files to archive\n"
"\t-e, --extract \t\tExtract all files from archive\n"
"\t-l, --list \t\tList all files within archive\n"
"\t-h, --help \t\tPrint this help menu\n"
"\nBugs? Fix it yourself, it's open source :)\n";
if ( argc < 3 )
{
printf( "%s", usage );
exit(1);
}
if ( strncmp( argv[ 1 ], "-a", 2 ) == 0 ||
strncmp( argv[ 1 ], "--add", 5 ) == 0 )
{
// Make sure there are enough args
if ( argc < 4 )
{
printf( "%s", usage );
exit( 1 );
}
// Add each file specified to the archive
for ( i = 3; i < argc; i++ )
addToArchive( argv[ i ] );
}
else if ( strcmp( argv[ 1 ], "-l") == 0 ||
strcmp( argv[ 1 ], "--list" ) == 0 )
list( );
else if ( strcmp( argv[ 1 ], "-e" ) == 0 ||
strcmp( argv[ 1 ], "--extract" ) == 0 )
extractAll( );
else
printf( "%s", usage );
return 0;
}