2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Cfilearchiver/CfileArchiver.cpp $
15 * Program to create an archive file for use with cfile stuff
18 * Revision 1.6 2004/12/15 04:10:45 taylor
19 * outwnd_unix.cpp from fs2_open for logging to file in debug mode
20 * fixes for default function values
21 * always use vm_* functions for sanity sake
22 * make cfilearchiver 64-bit compatible
23 * fix crash on exit from double free()
24 * fix crash on startup from extra long GL extension string in debug
26 * Revision 1.5 2003/05/04 04:49:48 taylor
27 * improve error handling, instructions
29 * Revision 1.4 2003/01/30 20:01:46 relnev
30 * ported (Taylor Richards)
32 * Revision 1.3 2002/06/09 04:41:15 relnev
33 * added copyright header
35 * Revision 1.2 2002/05/07 03:16:43 theoddone33
36 * The Great Newline Fix
38 * Revision 1.1.1.1 2002/05/03 03:28:08 root
42 * 2 10/23/98 6:15p Dave
58 #include <sys/types.h>
61 #define SDL_MAIN_HANDLED
66 #define strcasecmp stricmp
69 static int data_error;
72 unsigned int Total_size=16; // Start with size of header
73 unsigned int Num_files =0;
75 FILE * fp_out_hdr = NULL;
77 typedef struct vp_header {
84 //vp_header Vp_header;
86 char archive_dat[1024];
87 char archive_hdr[1024];
89 #define BLOCK_SIZE (1024*1024)
90 #define VERSION_NUMBER 2;
92 char tmp_data[BLOCK_SIZE]; // 1 MB
96 fseek(fp_out, 0, SEEK_SET);
97 fwrite("VPVP", 1, 4, fp_out);
98 int ver = VERSION_NUMBER;
99 fwrite(&ver, 1, 4, fp_out);
100 fwrite(&Total_size, 1, 4, fp_out);
101 fwrite(&Num_files, 1, 4, fp_out);
104 int write_index(char *hf, char *df)
106 FILE *h = fopen(hf, "rb");
112 FILE *d = fopen(df, "a+b");
119 for (unsigned int i=0;i<Num_files;i++) {
120 if ( !fread(tmp_data, 32+4+4+4, 1, h) ) {
126 fwrite(tmp_data, 32+4+4+4, 1, d);
135 void pack_file(const char *filespec, const char *filename, int filesize, fs_time_t time_write )
139 if ( strstr( filename, ".vp" )) {
140 // Don't pack yourself!!
144 if ( strstr( filename, ".hdr" )) {
145 // Don't pack yourself!!
149 if ( filesize == 0 ) {
150 // Don't pack 0 length files, screws up directory structure!
154 memset( path, 0, sizeof(path));
155 strcpy( path, filename );
156 if ( strlen(filename)>31 ) {
157 printf( "Filename '%s' too long\n", filename );
160 fwrite( &Total_size, 1, 4, fp_out_hdr );
161 fwrite( &filesize, 1, 4, fp_out_hdr );
162 fwrite( &path, 1, 32, fp_out_hdr );
163 fwrite( &time_write, 1, sizeof(fs_time_t), fp_out_hdr);
165 Total_size += filesize;
168 printf( "Packing %s%s%s...", filespec, DIR_SEPARATOR_STR, filename );
171 sprintf( path, "%s%s%s", filespec, DIR_SEPARATOR_STR, filename );
174 FILE *fp = fopen( path, "rb" );
177 printf( "Error opening '%s'\n", path );
181 int nbytes, nbytes_read=0;
184 nbytes = fread( tmp_data, 1, BLOCK_SIZE, fp );
186 fwrite( tmp_data, 1, nbytes, fp_out );
187 nbytes_read += nbytes;
190 } while( nbytes > 0 );
194 printf( " %d bytes\n", nbytes_read );
197 // This function adds a directory marker to the header file
198 void add_directory(const char * dirname)
201 char *pathptr = path;
204 if ( strlen(dirname) >= sizeof(path) )
207 strcpy(path, dirname);
208 fwrite(&Total_size, 1, 4, fp_out_hdr);
210 fwrite(&i, 1, 4, fp_out_hdr);
211 // strip out any directories that this dir is a subdir of
212 while ((tmpptr = strchr(pathptr, DIR_SEPARATOR_CHAR)) != NULL) {
215 fwrite(pathptr, 1, 32, fp_out_hdr);
216 fwrite(&i, 1, 4, fp_out_hdr); // timestamp = 0
220 void pack_directory(const char * filespec)
231 if ( strlen(filespec) >= (sizeof(tmp1) + 5) )
238 last_slash = strrchr(filespec, '\\');
240 strcpy(dir_name, last_slash+1);
242 strcpy(dir_name, filespec);
245 if ( !strcasecmp(dir_name, "voice") ) {
250 strcpy( tmp1, filespec );
252 // strip trailing slash
253 ts = tmp1+(strlen(tmp1)-1);
254 if (*ts == DIR_SEPARATOR_CHAR)
258 strcat( tmp1, DIR_SEPARATOR_STR );
259 strcat( tmp1, "*.*" );
261 printf( "In dir '%s'\n", tmp1 );
264 find_handle = _findfirst( tmp1, &find );
265 if( find_handle != -1 ) {
266 if ( find.attrib & _A_SUBDIR ) {
267 if (strcmp( "..", find.name) && strcmp( ".", find.name)) {
268 strcpy( tmp, filespec );
270 strcat( tmp, find.name );
274 pack_file( filespec, find.name, find.size, (fs_time_t)find.time_write );
277 while( !_findnext( find_handle, &find ) ) {
278 if ( find.attrib & _A_SUBDIR ) {
279 if (strcmp( "..", find.name) && strcmp( ".", find.name)) {
280 strcpy( tmp, filespec );
282 strcat( tmp, find.name );
287 pack_file( filespec, find.name, find.size, (fs_time_t)find.time_write );
295 dirp = opendir (filespec);
297 while ((dir = readdir(dirp)) != NULL) {
299 char fn[MAX_PATH_LEN];
300 snprintf(fn, MAX_PATH_LEN-1, "%s/%s", filespec, dir->d_name);
301 fn[MAX_PATH_LEN-1] = 0;
304 if (stat(fn, &buf) == -1) {
308 if ( (strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0) ) {
312 if (S_ISDIR(buf.st_mode)) {
313 strcpy( tmp, filespec );
315 strcat( tmp, dir->d_name );
318 pack_file( filespec, dir->d_name, buf.st_size, buf.st_mtime );
323 printf("Error: Source directory does not exist!\n");
330 int verify_directory(const char *filespec )
332 char tmp[512] = { 0 };
336 // strip trailing slash
337 strncpy(tmp, filespec, sizeof(tmp)-1);
339 ts = tmp+(strlen(tmp)-1);
340 if (*ts == DIR_SEPARATOR_CHAR)
343 // make sure last directory is named "data", ignoring case
344 dd = tmp+(strlen(tmp)-4);
345 if ( strcasecmp( dd, "data" ) )
351 int main(int argc, char *argv[] )
357 printf("Creates a vp archive out of a FreeSpace data tree.\n\n");
358 printf("Usage: cfilearchiver archive_name src_dir\n");
360 printf("Example: cfilearchiver freespace /tmp/freespace/data\n\n");
362 printf("Example: cfilearchiver freespace c:\\freespace\\data\n\n");
363 printf("Press any key to exit...\n");
369 strcpy( archive, argv[1] );
370 p = strchr( archive, '.' );
371 if (p) *p = 0; // remove extension
373 strcpy( archive_dat, archive );
374 strcat( archive_dat, ".vp" );
376 strcpy( archive_hdr, archive );
377 strcat( archive_hdr, ".hdr" );
379 fp_out = fopen( archive_dat, "wb" );
381 printf( "Couldn't open '%s'!\n", archive_dat );
383 printf( "Press any key to exit...\n" );
389 fp_out_hdr = fopen( archive_hdr, "wb" );
391 printf( "Couldn't open '%s'!\n", archive_hdr );
393 printf( "Press any key to exit...\n" );
399 if ( verify_directory( argv[2] ) != 0 ) {
400 printf("Warning! Last directory must be named \"data\" (not case sensitive)\n");
406 pack_directory( argv[2] );
408 // in case the directory doesn't exist
417 printf( "Data files written, appending index...\n" );
419 if (!write_index(archive_hdr, archive_dat)) {
420 printf("Error appending index!\n");
422 printf("Press any key to exit...\n");
428 printf( "%d total KB.\n", Total_size/1024 );