]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfilearchiver/cfilearchiver.cpp
ported (Taylor Richards)
[taylor/freespace2.git] / src / cfilearchiver / cfilearchiver.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Cfilearchiver/CfileArchiver.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Program to create an archive file for use with cfile stuff
16  *
17  * $Log$
18  * Revision 1.4  2003/01/30 20:01:46  relnev
19  * ported (Taylor Richards)
20  *
21  * Revision 1.3  2002/06/09 04:41:15  relnev
22  * added copyright header
23  *
24  * Revision 1.2  2002/05/07 03:16:43  theoddone33
25  * The Great Newline Fix
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:08  root
28  * Initial import.
29  *
30  * 
31  * 2     10/23/98 6:15p Dave
32  *
33  * $NoKeywords: $
34  */
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #ifndef PLAT_UNIX
40 #include <direct.h>
41 #include <io.h>
42 #include <conio.h>
43 #else
44 #include <dirent.h>
45 #include <unistd.h>
46 #include <sys/stat.h>
47 #include <sys/types.h>
48 #endif
49
50 #include "pstypes.h"
51
52 unsigned int Total_size=16; // Start with size of header
53 unsigned int Num_files =0;
54 FILE * fp_out = NULL;
55 FILE * fp_out_hdr = NULL;
56
57 typedef struct vp_header {
58         char id[4];
59         int version;
60         int index_offset;
61         int num_files;
62 } vp_header;
63
64 //vp_header Vp_header;
65
66 char archive_dat[1024];
67 char archive_hdr[1024];
68
69 #define BLOCK_SIZE (1024*1024)
70 #define VERSION_NUMBER 2;
71
72 char tmp_data[BLOCK_SIZE];              // 1 MB
73
74 void write_header()
75 {
76         fseek(fp_out, 0, SEEK_SET);
77         fwrite("VPVP", 1, 4, fp_out);
78         int ver = VERSION_NUMBER;
79         fwrite(&ver, 1, 4, fp_out);
80         fwrite(&Total_size, 1, 4, fp_out);
81         fwrite(&Num_files, 1, 4, fp_out);
82 }
83
84 int write_index(char *hf, char *df)
85 {
86         FILE *h = fopen(hf, "rb");
87         if (!h) return 0;
88         FILE *d = fopen(df, "a+b");
89         if (!d) return 0;
90         for (unsigned int i=0;i<Num_files;i++) {
91                 fread(tmp_data, 32+4+4+4, 1, h);
92                 fwrite(tmp_data, 32+4+4+4, 1, d);
93         }
94         fclose(h);
95         fclose(d);
96         return 1;
97 }
98
99 void pack_file( char *filespec, char *filename, int filesize, time_t time_write )
100 {
101         char path[1024];
102
103         if ( strstr( filename, ".vp" )) {
104                 // Don't pack yourself!!
105                 return;
106         }
107
108         if ( strstr( filename, ".hdr" ))        {
109                 // Don't pack yourself!!
110                 return;
111         }
112
113         if ( filesize == 0 ) {
114                 // Don't pack 0 length files, screws up directory structure!
115                 return;
116         }
117
118         memset( path, 0, sizeof(path));
119         strcpy( path, filename );
120         if ( strlen(filename)>31 )      {
121                 printf( "Filename '%s' too long\n", filename );
122                 exit(1);
123         }
124         fwrite( &Total_size, 1, 4, fp_out_hdr );
125         fwrite( &filesize, 1, 4, fp_out_hdr );
126         fwrite( &path, 1, 32, fp_out_hdr );
127         fwrite( &time_write, 1, sizeof(time_t), fp_out_hdr);
128
129         Total_size += filesize;
130         Num_files++;
131 #ifndef PLAT_UNIX
132         printf( "Packing %s\\%s...", filespec, filename );
133
134         
135         sprintf( path, "%s\\%s", filespec, filename );
136 #else
137         printf( "Packing %s/%s...", filespec, filename );
138
139
140         sprintf( path, "%s/%s", filespec, filename );
141 #endif
142
143         FILE *fp = fopen( path, "rb" );
144         
145         if ( fp == NULL )       {
146                 printf( "Error opening '%s'\n", path );
147                 exit(1);
148         }
149
150         int nbytes, nbytes_read=0;
151
152         do      {
153                 nbytes = fread( tmp_data, 1, BLOCK_SIZE, fp );
154                 if ( nbytes > 0 )       {
155                         fwrite( tmp_data, 1, nbytes, fp_out );
156                         nbytes_read += nbytes;
157
158                 }
159         } while( nbytes > 0 );
160
161         fclose(fp);
162
163         printf( " %d bytes\n", nbytes_read );
164 }
165
166 // This function adds a directory marker to the header file
167 void add_directory( char * dirname)
168 {
169         char path[256];
170         char *pathptr = path;
171         char *tmpptr;
172
173         strcpy(path, dirname);
174         fwrite(&Total_size, 1, 4, fp_out_hdr);
175         int i = 0;
176         fwrite(&i, 1, 4, fp_out_hdr);
177         // strip out any directories that this dir is a subdir of
178 #ifndef PLAT_UNIX
179         while ((tmpptr = strchr(pathptr, '\\')) != NULL) {
180 #else
181         while ((tmpptr = strchr(pathptr, '/')) != NULL) {
182 #endif
183                 pathptr = tmpptr+1;
184         }
185         fwrite(pathptr, 1, 32, fp_out_hdr);
186         fwrite(&i, 1, 4, fp_out_hdr); // timestamp = 0
187         Num_files++;
188 }
189
190 void pack_directory( char * filespec)
191 {
192 #ifndef PLAT_UNIX
193         int find_handle;
194         _finddata_t find;
195 #endif
196         char tmp[512];
197         char tmp1[512];
198
199 /*
200         char dir_name[512];
201         char *last_slash;
202
203         last_slash = strrchr(filespec, '\\');
204         if ( last_slash ) {
205                 strcpy(dir_name, last_slash+1);
206         } else {
207                 strcpy(dir_name, filespec);
208         }
209
210         if ( !stricmp(dir_name, "voice") ) {
211                 return;
212         }
213 */
214
215         strcpy( tmp1, filespec );
216 #ifdef PLAT_UNIX
217         // space for more unfinished things here
218         //
219
220         add_directory(filespec);
221         strcat( tmp1, "/*.*" );
222 #else
223         add_directory(filespec);
224         strcat( tmp1, "\\*.*" );
225 #endif
226         
227         printf( "In dir '%s'\n", tmp1 );
228
229 #ifndef PLAT_UNIX
230         find_handle = _findfirst( tmp1, &find );
231         if( find_handle != -1 ) {
232                 if ( find.attrib & _A_SUBDIR )  {
233                         if (strcmp( "..", find.name) && strcmp( ".", find.name))        {
234                                 strcpy( tmp, filespec );
235                                 strcat( tmp, "\\" );
236                                 strcat( tmp, find.name );
237                                 pack_directory(tmp);
238                         }
239                 } else {
240                         pack_file( filespec, find.name, find.size, find.time_write );
241                 }
242
243                 while( !_findnext( find_handle, &find ) )       {
244                         if ( find.attrib & _A_SUBDIR )  {
245                                 if (strcmp( "..", find.name) && strcmp( ".", find.name))        {
246                                         strcpy( tmp, filespec );
247                                         strcat( tmp, "\\" );
248                                         strcat( tmp, find.name );
249                                         pack_directory(tmp);
250
251                                 }
252                         } else {
253                                 pack_file( filespec, find.name, find.size, find.time_write );
254                         }
255                 }
256         }
257 #else
258         DIR *dirp;
259         struct dirent *dir;
260
261         dirp = opendir (filespec);
262         if ( dirp ) {
263                 while ((dir = readdir(dirp)) != NULL) {
264
265                         char fn[MAX_PATH];
266                         snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
267                         fn[MAX_PATH-1] = 0;
268                         
269                         struct stat buf;
270                         if (stat(fn, &buf) == -1) {
271                                 continue;
272                         }
273
274                         if ( (strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0) ) {
275                                 continue;
276                         }
277
278                         if (S_ISDIR(buf.st_mode)) {
279                                 strcpy( tmp, filespec );
280                                 strcat( tmp, "/" );
281                                 strcat( tmp, dir->d_name );
282                                 pack_directory(tmp);
283                         } else {
284                                 pack_file( filespec, dir->d_name, buf.st_size, buf.st_mtime );
285                         }
286                 }
287                 closedir(dirp);
288         }
289 #endif
290         add_directory("..");
291 }
292
293
294
295 int main(int argc, char *argv[] )
296 {
297         char archive[1024];
298         char *p;
299
300         if ( argc < 3 ) {
301 #ifndef PLAT_UNIX
302                 printf( "Usage: %s archive_name src_dir\n", argv[0] );
303                 printf( "Example: %s freespace c:\\freespace\\data\n", argv[0] );
304                 printf( "Creates an archive named freespace out of the\nfreespace data tree\n" );
305                 printf( "Press any key to exit...\n" );
306                 getch();
307 #else
308                 printf( "Creates a vp archive out of a FreeSpace data tree.\n\n" );
309                 printf( "Usage: %s archive_name src_dir\n", argv[0] );
310                 printf( "Example: %s freespace /tmp/freespace/data\n", argv[0] );
311                 printf( "NOTE: last directory must be named \"data\", no trailing \"/\"\n\n" );
312                 printf( "Directory structure options:\n" );
313                 printf( "   Effects                   (.ani .pcx .neb .tga)\n" );
314                 printf( "   Fonts                     (.vf)\n" );
315                 printf( "   Hud                       (.ani .pcx .tga\n" );
316                 printf( "   Interface                 (.pcx .ani .tga)\n" );
317                 printf( "   Maps                      (.pcx .ani .tga)\n" );
318                 printf( "   Missions                  (.ntl .ssv), FS1(.fsm .fsc), FS2(.fs2 .fc2)\n" );
319                 printf( "   Models                    (.pof)\n" );
320                 printf( "   Music                     (.wav)\n" );
321                 printf( "   Sounds/8b22k              (.wav)\n" );
322                 printf( "   Sounds/16b11k             (.wav)\n" );
323                 printf( "   Tables                    (.tbl)\n" );
324                 printf( "   Voice/Briefing            (.wav)\n" );
325                 printf( "   Voice/Command briefings   (.wav)\n" );
326                 printf( "   Voice/Debriefing          (.wav)\n" );
327                 printf( "   Voice/Personas            (.wav)\n" );
328                 printf( "   Voice/Special             (.wav)\n" );
329                 printf( "   Voice/Training            (.wav)\n" );
330 #endif
331                 return 1;
332         }
333
334         strcpy( archive, argv[1] );
335         p = strchr( archive, '.' );
336         if (p) *p = 0;          // remove extension     
337
338         strcpy( archive_dat, archive );
339         strcat( archive_dat, ".vp" );
340
341         strcpy( archive_hdr, archive );
342         strcat( archive_hdr, ".hdr" );
343
344         fp_out = fopen( archive_dat, "wb" );
345         if ( !fp_out )  {
346                 printf( "Couldn't open '%s'!\n", archive_dat );
347 #ifndef PLAT_UNIX
348                 printf( "Press any key to exit...\n" );
349                 getch();
350 #endif
351                 return 1;
352         }
353
354         fp_out_hdr = fopen( archive_hdr, "wb" );
355         if ( !fp_out_hdr )      {
356                 printf( "Couldn't open '%s'!\n", archive_hdr );
357 #ifndef PLAT_UNIX
358                 printf( "Press any key to exit...\n" );
359                 getch();
360 #endif
361                 return 1;
362         }
363
364         write_header();
365
366         pack_directory( argv[2] );
367
368         write_header();
369
370         fclose(fp_out);
371         fclose(fp_out_hdr);
372
373         printf( "Data files written, appending index...\n" );
374
375         if (!write_index(archive_hdr, archive_dat)) {
376                 printf("Error appending index!\n");
377 #ifndef PLAT_UNIX
378                 printf("Press any key to exit...\n");
379                 getch();
380 #endif
381                 return 1;
382         }
383         
384         printf( "%d total KB.\n", Total_size/1024 );
385         return 0;
386 }
387