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.5 2003/05/04 04:49:48 taylor
19 * improve error handling, instructions
21 * Revision 1.4 2003/01/30 20:01:46 relnev
22 * ported (Taylor Richards)
24 * Revision 1.3 2002/06/09 04:41:15 relnev
25 * added copyright header
27 * Revision 1.2 2002/05/07 03:16:43 theoddone33
28 * The Great Newline Fix
30 * Revision 1.1.1.1 2002/05/03 03:28:08 root
34 * 2 10/23/98 6:15p Dave
50 #include <sys/types.h>
55 static int data_error;
58 unsigned int Total_size=16; // Start with size of header
59 unsigned int Num_files =0;
61 FILE * fp_out_hdr = NULL;
63 typedef struct vp_header {
70 //vp_header Vp_header;
72 char archive_dat[1024];
73 char archive_hdr[1024];
75 #define BLOCK_SIZE (1024*1024)
76 #define VERSION_NUMBER 2;
78 char tmp_data[BLOCK_SIZE]; // 1 MB
82 fseek(fp_out, 0, SEEK_SET);
83 fwrite("VPVP", 1, 4, fp_out);
84 int ver = VERSION_NUMBER;
85 fwrite(&ver, 1, 4, fp_out);
86 fwrite(&Total_size, 1, 4, fp_out);
87 fwrite(&Num_files, 1, 4, fp_out);
90 int write_index(char *hf, char *df)
92 FILE *h = fopen(hf, "rb");
94 FILE *d = fopen(df, "a+b");
96 for (unsigned int i=0;i<Num_files;i++) {
97 fread(tmp_data, 32+4+4+4, 1, h);
98 fwrite(tmp_data, 32+4+4+4, 1, d);
105 void pack_file( char *filespec, char *filename, int filesize, time_t time_write )
109 if ( strstr( filename, ".vp" )) {
110 // Don't pack yourself!!
114 if ( strstr( filename, ".hdr" )) {
115 // Don't pack yourself!!
119 if ( filesize == 0 ) {
120 // Don't pack 0 length files, screws up directory structure!
124 memset( path, 0, sizeof(path));
125 strcpy( path, filename );
126 if ( strlen(filename)>31 ) {
127 printf( "Filename '%s' too long\n", filename );
130 fwrite( &Total_size, 1, 4, fp_out_hdr );
131 fwrite( &filesize, 1, 4, fp_out_hdr );
132 fwrite( &path, 1, 32, fp_out_hdr );
133 fwrite( &time_write, 1, sizeof(time_t), fp_out_hdr);
135 Total_size += filesize;
138 printf( "Packing %s\\%s...", filespec, filename );
141 sprintf( path, "%s\\%s", filespec, filename );
143 printf( "Packing %s/%s...", filespec, filename );
146 sprintf( path, "%s/%s", filespec, filename );
149 FILE *fp = fopen( path, "rb" );
152 printf( "Error opening '%s'\n", path );
156 int nbytes, nbytes_read=0;
159 nbytes = fread( tmp_data, 1, BLOCK_SIZE, fp );
161 fwrite( tmp_data, 1, nbytes, fp_out );
162 nbytes_read += nbytes;
165 } while( nbytes > 0 );
169 printf( " %d bytes\n", nbytes_read );
172 // This function adds a directory marker to the header file
173 void add_directory( char * dirname)
176 char *pathptr = path;
179 strcpy(path, dirname);
180 fwrite(&Total_size, 1, 4, fp_out_hdr);
182 fwrite(&i, 1, 4, fp_out_hdr);
183 // strip out any directories that this dir is a subdir of
185 while ((tmpptr = strchr(pathptr, '\\')) != NULL) {
187 while ((tmpptr = strchr(pathptr, '/')) != NULL) {
191 fwrite(pathptr, 1, 32, fp_out_hdr);
192 fwrite(&i, 1, 4, fp_out_hdr); // timestamp = 0
196 void pack_directory( char * filespec)
209 last_slash = strrchr(filespec, '\\');
211 strcpy(dir_name, last_slash+1);
213 strcpy(dir_name, filespec);
216 if ( !stricmp(dir_name, "voice") ) {
224 // strip trailing '/'
225 ts = filespec+(strlen(filespec)-1);
226 while(*ts == '/' && ts > filespec)
229 strcpy( tmp1, filespec );
231 add_directory(filespec);
232 strcat( tmp1, "/*.*" );
234 strcpy( tmp1, filespec );
236 add_directory(filespec);
237 strcat( tmp1, "\\*.*" );
240 printf( "In dir '%s'\n", tmp1 );
243 find_handle = _findfirst( tmp1, &find );
244 if( find_handle != -1 ) {
245 if ( find.attrib & _A_SUBDIR ) {
246 if (strcmp( "..", find.name) && strcmp( ".", find.name)) {
247 strcpy( tmp, filespec );
249 strcat( tmp, find.name );
253 pack_file( filespec, find.name, find.size, find.time_write );
256 while( !_findnext( find_handle, &find ) ) {
257 if ( find.attrib & _A_SUBDIR ) {
258 if (strcmp( "..", find.name) && strcmp( ".", find.name)) {
259 strcpy( tmp, filespec );
261 strcat( tmp, find.name );
266 pack_file( filespec, find.name, find.size, find.time_write );
274 dirp = opendir (filespec);
276 while ((dir = readdir(dirp)) != NULL) {
279 snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
283 if (stat(fn, &buf) == -1) {
287 if ( (strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0) ) {
291 if (S_ISDIR(buf.st_mode)) {
292 strcpy( tmp, filespec );
294 strcat( tmp, dir->d_name );
297 pack_file( filespec, dir->d_name, buf.st_size, buf.st_mtime );
302 printf("Error: Source directory does not exist!\n");
309 int verify_directory( char *filespec )
314 // strip trailing '/'
315 ts = filespec+(strlen(filespec)-1);
316 while(*ts == '/' && ts > filespec)
319 // make sure last directory is named "data", ignoring case
320 dd = filespec+(strlen(filespec)-4);
321 if ( stricmp( dd, "data" ) )
327 void print_instructions()
329 printf( "Creates a vp archive out of a FreeSpace data tree.\n\n" );
330 printf( "Usage: cfilearchiver archive_name src_dir\n");
331 printf( "Example: cfilearchiver freespace /tmp/freespace/data\n\n");
332 printf( "Directory structure options:\n" );
333 printf( " Effects (.ani .pcx .neb .tga)\n" );
334 printf( " Fonts (.vf)\n" );
335 printf( " Hud (.ani .pcx .tga\n" );
336 printf( " Interface (.pcx .ani .tga)\n" );
337 printf( " Maps (.pcx .ani .tga)\n" );
338 printf( " Missions (.ntl .ssv), FS1(.fsm .fsc), FS2(.fs2 .fc2)\n" );
339 printf( " Models (.pof)\n" );
340 printf( " Music (.wav)\n" );
341 printf( " Sounds/8b22k (.wav)\n" );
342 printf( " Sounds/16b11k (.wav)\n" );
343 printf( " Tables (.tbl)\n" );
344 printf( " Voice/Briefing (.wav)\n" );
345 printf( " Voice/Command briefings (.wav)\n" );
346 printf( " Voice/Debriefing (.wav)\n" );
347 printf( " Voice/Personas (.wav)\n" );
348 printf( " Voice/Special (.wav)\n" );
349 printf( " Voice/Training (.wav)\n" );
354 int main(int argc, char *argv[] )
361 printf( "Usage: %s archive_name src_dir\n", argv[0] );
362 printf( "Example: %s freespace c:\\freespace\\data\n", argv[0] );
363 printf( "Creates an archive named freespace out of the\nfreespace data tree\n" );
364 printf( "Press any key to exit...\n" );
368 print_instructions();
372 strcpy( archive, argv[1] );
373 p = strchr( archive, '.' );
374 if (p) *p = 0; // remove extension
376 strcpy( archive_dat, archive );
377 strcat( archive_dat, ".vp" );
379 strcpy( archive_hdr, archive );
380 strcat( archive_hdr, ".hdr" );
382 fp_out = fopen( archive_dat, "wb" );
384 printf( "Couldn't open '%s'!\n", archive_dat );
386 printf( "Press any key to exit...\n" );
394 fp_out_hdr = fopen( archive_hdr, "wb" );
396 printf( "Couldn't open '%s'!\n", archive_hdr );
398 printf( "Press any key to exit...\n" );
406 if ( verify_directory( argv[2] ) != 0 ) {
407 printf("Warning! Last directory must be named \"data\" (not case sensitive)\n");
413 pack_directory( argv[2] );
415 // in case the directory doesn't exist
424 printf( "Data files written, appending index...\n" );
426 if (!write_index(archive_hdr, archive_dat)) {
427 printf("Error appending index!\n");
429 printf("Press any key to exit...\n");
435 printf( "%d total KB.\n", Total_size/1024 );