vegastrike  0.5.1.r1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vsfilesystem.h
Go to the documentation of this file.
1 #ifndef __VSFILESYS_H
2 #define __VSFILESYS_H
3 #include "config.h"
4 #include <stdio.h>
5 #include <string>
6 #include <vector>
7 #include <iostream>
8 using std::string;
9 using std::vector;
10 #include <stdarg.h>
11 #include "gfx/vec.h"
12 #include "networking/const.h"
13 #include "pk3.h"
14 #include <gnuhash.h>
15 
16 class VegaConfig;
17 class VSImage;
18 
19 extern char *CONFIGFILE;
20 extern VegaConfig * createVegaConfig( const char *file );
21 extern ObjSerial serial_seed;
22 ObjSerial getUniqueSerial();
23 #define DELIM '/'
24 #define DELIMSTR "/"
25 namespace VSFileSystem
26 {
27 class VSFile;
28 
29 /*
30  ***********************************************************************************************
31  **** VSFileSystem enums ***
32  ***********************************************************************************************
33  */
34 
35 //VSErrors that can be return by various functions
36 enum VSError
37 {
40 }; //Failure condition when result > Ok
41 
42 //The mode of an opened file
44 
45 //Different file type we have to deal with
47 {
48  //File types
49  UniverseFile, //Loaded from universe subdir
50  SystemFile, //Loaded from sectors subdir written in homedir/sectors/universename
51  CockpitFile, //Loaded from cockpits subdir
52  UnitFile, //Loaded from units subdir
53  UnitSaveFile, //Saved unit file
54  TextureFile, //Loaded from current path or from textures subdir
55  SoundFile, //Loaded from current path or from sounds subdir
56  PythonFile, //Loaded from bases subdir // not really used
57  MeshFile, //Loaded from current path or from meshes subdir
58  CommFile, //Loaded from communications subdir
59  AiFile, //Loaded from ai subdir
60  SaveFile, //Loaded from homedir/save and saved in homedir/save
61  AnimFile, //Loaded from animations subdir
62  VideoFile, //Loaded from movies subdir
63  VSSpriteFile, //Loaded from current path or from sprites subdir
64  MissionFile, //Loaded from mission subdir
65  MusicFile, //Loaded from homedir
66  AccountFile, //Loaded from datadir/accounts and written in datadir/accounts
67  //Buffer types
68  ZoneBuffer, //Indicates a ZoneInfo buffer coming from server
69  JPEGBuffer, //Indicates a JPEG buffer coming from network
70  //Unknown
71  UnknownFile //Loaded from homedir or datadir and written in homedir
72 };
73 
76 
77 void DisplayType( VSFileType type );
78 void DisplayType( VSFileType type, std::ostream &ostr );
79 
80 int GetReadBytes( char *fmt, va_list ap );
81 
82 typedef vsUMap< string, VSError > FileLookupCache;
83 VSError CachedFileLookup( FileLookupCache &cache, const string &file, VSFileType type );
84 
85 /*
86  ***********************************************************************************************
87  **** VSFileSystem global variables ***
88  ***********************************************************************************************
89  */
90 
91 extern bool use_volumes;
92 extern string volume_format;
94 
95 extern vector< std::string >curdir; //current dir starting from datadir
96 extern vector< std::string >savedpwd;
97 extern vector< string >Rootdir;
98 extern string sharedtextures;
99 extern string sharedsounds;
100 extern string sharedmeshes;
101 extern string sharedunits;
102 extern string sharedsectors;
103 extern string sharedcockpits;
104 extern string shareduniverse;
105 extern string sharedanims;
106 extern string sharedsprites;
107 extern string savedunitpath;
108 extern string moddir;
109 extern string datadir;
110 extern string homedir; //User home directory including .vegastrike subdir
111 
112 extern string config_file;
113 extern string weapon_list;
114 extern string universe_name;
115 extern string HOMESUBDIR;
116 extern vector< string > current_path;
117 extern vector< string > current_directory;
118 extern vector< string > current_subdirectory;
119 extern vector< VSFileType >current_type;
120 
121 extern vector< vector< string > >SubDirectories; //Subdirectories where we should look for VSFileTypes files
122 extern vector< string > Directories;
123 extern vector< string > Rootdir; //Root directories where we should look for VSFileTypes files
124 
125 extern vector< int >UseVolumes; //Tells us for which VSFileType we will use volumes
126 //0 tells FileType doesn't use volumes
127 //1 tells it uses a volume based on the FileType
128 //2 tells it uses a big data volume
129 
130 extern string failed;
131 extern vsUMap< string, CPK3* >pk3_opened_files; //Map of the currently opened PK3 volume/resource files
132 /*
133  ***********************************************************************************************
134  **** VSFileSystem wrappers to stdio calls ***
135  ***********************************************************************************************
136  */
137 
138 FILE * vs_open( const char *filename, const char *mode );
139 size_t vs_read( void *ptr, size_t size, size_t nmemb, FILE *fp );
140 size_t vs_write( const void *ptr, size_t size, size_t nmemb, FILE *fp );
141 int vs_fseek( FILE *fp, long offset, int whence );
142 long vs_ftell( FILE *fp );
143 void vs_rewind( FILE *fp );
144 void vs_close( FILE *fp );
145 bool vs_feof( FILE *fp );
146 long vs_getsize( FILE *fp );
147 
148 int vs_fprintf( FILE *fp, const char *format, ... );
149 /* Debug level is a character, 1, 2, or 3. 1 is most important warnings only. 2 is warnings that are important but not hazardous to gameplay
150  * 3 is for developer type messages, more akin to informational output but not relevant to anything an end user would care about.
151  * example usage. vegastrike --debug=3 leaving --debug empty as an argument is the same as --debug=1
152  * all output is sent to stderr
153  */
154 void vs_dprintf( char level, const char *format, ... );
155 #if 0
156 int vs_fscanf( FILE *fp, const char *format, ... );
157 #endif
158 template < class A >
159 int vs_fscanf( FILE *fp, const char *format, A *a )
160 {
161  return fscanf( fp, format, a );
162 }
163 template < class A, class B >
164 int vs_fscanf( FILE *fp, const char *format, A *a, B *b )
165 {
166  return fscanf( fp, format, a, b );
167 }
168 template < class A, class B, class C >
169 int vs_fscanf( FILE *fp, const char *format, A *a, B *b, C *c )
170 {
171  return fscanf( fp, format, a, b, c );
172 }
173 template < class A, class B, class C, class D >
174 int vs_fscanf( FILE *fp, const char *format, A *a, B *b, C *c, D *d )
175 {
176  return fscanf( fp, format, a, b, c, d );
177 }
178 template < class A, class B, class C, class D, class E >
179 int vs_fscanf( FILE *fp, const char *format, A *a, B *b, C *c, D *d, E *e )
180 {
181  return fscanf( fp, format, a, b, c, d, e );
182 }
183 template < class A, class B, class C, class D, class E, class F >
184 int vs_fscanf( FILE *fp, const char *format, A *a, B *b, C *c, D *d, E *e, F *f )
185 {
186  return fscanf( fp, format, a, b, c, d, e, f );
187 }
188 
189 /*
190  * template< class A>
191  * int vs_sscanf( FILE * fp, const char * format, A * a)
192  * { return sscanf( buf, newformat, a); }
193  * template< class A, class B>
194  * int vs_sscanf( FILE * fp, const char * format, A * a, B * b)
195  * { return sscanf( buf, newformat, a, b); }
196  * template< class A, class B, class C>
197  * int vs_sscanf( FILE * fp, const char * format, A * a, B * b, C * c)
198  * { return sscanf( buf, newformat, a, b, c); }
199  * template< class A, class B, class C, class D>
200  * int vs_sscanf( FILE * fp, const char * format, A * a, B * b, C * c, D * d)
201  * { return sscanf( buf, newformat, a, b, d); }
202  * template< class A, class B, class C, class D, class E>
203  * int vs_sscanf( const char * buf, const char * format, A * a, B * b, C * c, D * d, E * e)
204  * { return sscanf( buf, newformat, a, b, c, d, e); }
205  * template< class A, class B, class C, class D, class E, class F>
206  * int vs_sscanf( const char * buf, const char * format, A * a, B * b, C * c, D * d, E * e, F * f)
207  * { return sscanf( buf, newformat, a, b, c, d, e, f); }
208  * // We need 1 arg more than vs_fscanf because we pass an extra arg to get the number of bytes read by sscanf in the last arg
209  * template< class A, class B, class C, class D, class E, class F, class G>
210  * int vs_sscanf( const char * buf, const char * format, A * a, B * b, C * c, D * d, E * e, F * f, G * g)
211  * { return sscanf( buf, newformat, a, b, c, d, e, f); }
212  */
213 
214 /*
215  ***********************************************************************************************
216  **** vs_path functions : mostly obsolete stuff now ***
217  ***********************************************************************************************
218  */
219 
220 string GetHashName( const std::string &name );
221 string GetHashName( const std::string &name, const class Vector &scale, int faction );
222 string GetSharedTextureHashName( const std::string& );
223 string GetSharedSoundHashName( const std::string& );
224 string GetSharedMeshHashName( const std::string&, const class Vector &scale, int faction );
225 string MakeSharedStarSysPath( const std::string& );
226 string MakeSharedPath( const std::string &path );
227 string GetCorrectStarSysPath( const std::string&, bool &autogenerated );
228 
229 //string GetSharedUnitPath ();
230 //string GetSharedMeshPath (const std::string &name);
231 //string GetSharedSoundPath (const std::string &name);
232 //string GetSharedTexturePath (const std::string &name);
233 
234 /*
235  * void initpaths(const std::string& modname=""); // Sets up datadir and load VS config file
236  * void changehome(bool makehomedir=false); // Changes to user homedir in an OS independant way
237  * void returnfromhome(); // Return from homedir to calling directory
238  * void vs_chdir (const char *path); // Changes the directory and the current path to reflect it
239  * // Note : may only change ONE level of directory or it breaks
240  * void vs_cdup(); // Goes up one level and changes the direcrtory accordingly
241  * void vs_mkdir (const std::string &nam); // Creates a directory
242  * void vs_setdir (const char * path); // Sets the current directory
243  * void vs_resetdir (); // Reset the current directory
244  */
245 
246 /*
247  ***********************************************************************************************
248  **** VSFileSystem functions ***
249  ***********************************************************************************************
250  */
251 
252 //Initialize paths
253 void InitPaths( string conf, string subdir = "" );
254 void InitDataDirectory();
255 void InitHomeDirectory();
256 void LoadConfig( string subdir = "" );
257 void InitMods();
258 void ChangeToProgramDirectory( char *argv0 );
259 
260 //Create a directory
261 void CreateDirectoryAbs( const char *filename );
262 void CreateDirectoryAbs( const string &filename );
263 //Create a directory in home_path
264 void CreateDirectoryHome( const char *filename );
265 void CreateDirectoryHome( const string &filename );
266 //Create a directory in data_path_path
267 void CreateDirectoryData( const char *filename );
268 void CreateDirectoryData( const string &filename );
269 
270 /********** DO NO USE FileExists functions directly : USE LookForFile instead **********/
271 //Test if a directory exists (absolute path)
272 bool DirectoryExists( const char *filename );
273 bool DirectoryExists( const string &filename );
274 //Returns positive int or index in archive if found or -1 if not found
275 //Test if a file exists (absolute path)
276 int FileExists( const string &root, const char *filename, VSFileType type = UnknownFile, bool lookinvolume = true );
277 int FileExists( const string &root, const string &filename, VSFileType type = UnknownFile, bool lookinvolume = true );
278 //Test if a file exists relative to home_path
279 int FileExistsHome( const char *filename, VSFileType type = UnknownFile );
280 int FileExistsHome( const string &filename, VSFileType type = UnknownFile );
281 //Test if a file exists relative to data_path
282 int FileExistsData( const char *filename, VSFileType type = UnknownFile );
283 int FileExistsData( const string &filename, VSFileType type = UnknownFile );
284 
285 VSError GetError( const char *str = NULL );
286 
287 VSError LookForFile( VSFile &f, VSFileType type, VSFileMode mode = ReadOnly );
288 VSError LookForFile( const string &filename, VSFileType type, VSFileMode mode = ReadOnly );
289 
290 /*
291  ***********************************************************************************************
292  **** VSFileSystem::VSFile functions ***
293  ***********************************************************************************************
294  */
295 
296 class VSFile
297 {
298 private:
299 //STDIO stuff
300  FILE *fp;
301 
302 //PK3 stuff
303  CPK3 *pk3_file;
304  char *pk3_extracted_file;
305  int file_index;
306  unsigned int offset;
307 
308  void checkExtracted();
309 
310 //VSFile internals
311  VSFileType file_type;
312  VSFileType alt_type;
313  VSFileMode file_mode;
314  VSVolumeType volume_type;
315 
316  string filename;
317  string subdirectoryname;
318  string directoryname;
319  string rootname;
320 
321  unsigned long size;
322  bool valid;
323 
324 public:
325  char * get_pk3_data()
326  {
327  return pk3_extracted_file;
328  }
329 
330 public: VSFile();
331  VSFile( const char *buffer, long size, VSFileType type = ZoneBuffer, VSFileMode = ReadOnly );
332  VSFile( const char *filename, VSFileType type = UnknownFile, VSFileMode = ReadOnly );
333  ~VSFile();
334 
335  FILE * GetFP()
336  {
337  return this->fp;
338  } //This is still needed for special cases (when loading PNG files)
339  char * GetFileBuffer()
340  {
341  return this->pk3_extracted_file;
342  }
343 
344 /********************************** OPEN A FILE *********************************/
345 //Open an existing file read only
346  VSError OpenReadOnly( const char *filename, VSFileType type = UnknownFile );
347  VSError OpenReadOnly( const string &filename, VSFileType type = UnknownFile )
348  {
349  return OpenReadOnly( filename.c_str(), type );
350  }
351 //Open an existing file read/write
352  VSError OpenReadWrite( const char *filename, VSFileType type = UnknownFile );
353  VSError OpenReadWrite( const string &filename, VSFileType type = UnknownFile )
354  {
355  return OpenReadWrite( filename.c_str(), type );
356  }
357 //Open (truncate) or create a file read/write
358  VSError OpenCreateWrite( const char *filename, VSFileType type = UnknownFile );
359  VSError OpenCreateWrite( const string &filename, VSFileType type = UnknownFile )
360  {
361  return OpenCreateWrite( filename.c_str(), type );
362  }
363 //Close the file
364  void Close();
365 
366 /********************************** READ/WRITE OPERATIONS IN A FILE *********************************/
367  size_t Read( void *ptr, size_t length ); //Read length in ptr (store read bytes number in length)
368  VSError ReadLine( void *ptr, size_t length ); //Read a line of maximum length
369  string ReadFull(); //Read the entire file and returns the content in a string
370  size_t Write( const void *ptr, size_t length ); //Write length from ptr (store written bytes number in length)
371  size_t Write( const string &content ); //Write a string
372  VSError WriteLine( const void *ptr ); //Write a line
373  void WriteFull( void *ptr ); //Write
374 
375 #if 0
376  int Fscanf( const char *format, ... );
377 #endif
378  void GoAfterEOL( unsigned int length );
379  void GoAfterEOL();
380 
381  template < class A >
382  int Fscanf( const char *format, A *a )
383  {
384  int ret = -1;
385  if (!UseVolumes[this->alt_type]) {
386  ret = fscanf( fp, format, a );
387  } else {
388  if (q_volume_format == vfmtPK3) {
389  checkExtracted();
390  int ret = -1, readbytes = 0;
391  int length = strlen( format );
392  int newlength = length+3;
393  char *newformat = new char[newlength];
394  memset( newformat, 0, newlength );
395  memcpy( newformat, format, length );
396  strcat( newformat, "%n" );
397  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, &readbytes );
398  delete[] newformat;
399  std::cerr<<"FSCANF : sscanf read "<<readbytes<<" bytes - OFFSET="<<offset<<" VALUES : a="<<(*a)<<std::endl;
400  this->offset += readbytes;
401  this->GoAfterEOL();
402  } else if (q_volume_format == vfmtVSR) {}
403  }
404  return ret;
405  }
406  template < class A, class B >
407  int Fscanf( const char *format, A *a, B *b )
408  {
409  int ret = -1;
410  if (!UseVolumes[this->alt_type]) {
411  ret = fscanf( fp, format, a, b );
412  } else {
413  if (q_volume_format == vfmtPK3) {
414  checkExtracted();
415  int ret = -1, readbytes = 0;
416  int length = strlen( format );
417  int newlength = length+3;
418  char *newformat = new char[newlength];
419  memset( newformat, 0, newlength );
420  memcpy( newformat, format, length );
421  strcat( newformat, "%n" );
422  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, b, &readbytes );
423  delete[] newformat;
424  std::cerr<<"FSCANF : sscanf read "<<readbytes<<" bytes - OFFSET="<<offset<<" VALUES : a="<<(*a)<<", b="<<(*b)
425  <<std::endl;
426  this->offset += readbytes;
427  this->GoAfterEOL();
428  } else if (q_volume_format == vfmtVSR) {}
429  }
430  return ret;
431  }
432  template < class A, class B, class C >
433  int Fscanf( const char *format, A *a, B *b, C *c )
434  {
435  int ret = -1;
436  if (!UseVolumes[this->alt_type]) {
437  ret = fscanf( fp, format, a, b, c );
438  } else {
439  if (q_volume_format == vfmtPK3) {
440  checkExtracted();
441  int ret = -1, readbytes = 0;
442  int length = strlen( format );
443  int newlength = length+3;
444  char *newformat = new char[newlength];
445  memset( newformat, 0, newlength );
446  memcpy( newformat, format, length );
447  strcat( newformat, "%n" );
448  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, b, c, &readbytes );
449  delete[] newformat;
450  std::cerr<<"FSCANF : sscanf read "<<readbytes<<" bytes - OFFSET="<<offset<<" VALUES : a="<<(*a)<<", b="<<(*b)
451  <<", c="<<(*c)<<std::endl;
452  this->offset += readbytes;
453  this->GoAfterEOL();
454  } else if (q_volume_format == vfmtVSR) {}
455  }
456  return ret;
457  }
458  template < class A, class B, class C, class D >
459  int Fscanf( const char *format, A *a, B *b, C *c, D *d )
460  {
461  int ret = -1;
462  if (!UseVolumes[this->alt_type]) {
463  ret = fscanf( fp, format, a, b, c, d );
464  } else {
465  if (q_volume_format == vfmtPK3) {
466  checkExtracted();
467  int ret = -1, readbytes = 0;
468  int length = strlen( format );
469  int newlength = length+3;
470  char *newformat = new char[newlength];
471  memset( newformat, 0, newlength );
472  memcpy( newformat, format, length );
473  strcat( newformat, "%n" );
474  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, b, c, d, &readbytes );
475  delete[] newformat;
476  this->offset += readbytes;
477  this->GoAfterEOL();
478  } else if (q_volume_format == vfmtVSR) {}
479  }
480  return ret;
481  }
482  template < class A, class B, class C, class D, class E >
483  int Fscanf( const char *format, A *a, B *b, C *c, D *d, E *e )
484  {
485  int ret = -1;
486  if (!UseVolumes[this->alt_type]) {
487  ret = fscanf( fp, format, a, b, c, d, e );
488  } else {
489  if (q_volume_format == vfmtPK3) {
490  checkExtracted();
491  int ret = -1, readbytes = 0;
492  int length = strlen( format );
493  int newlength = length+3;
494  char *newformat = new char[newlength];
495  memset( newformat, 0, newlength );
496  memcpy( newformat, format, length );
497  strcat( newformat, "%n" );
498  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, b, c, d, e, &readbytes );
499  delete[] newformat;
500  this->offset += readbytes;
501  this->GoAfterEOL();
502  } else if (q_volume_format == vfmtVSR) {}
503  }
504  return ret;
505  }
506  template < class A, class B, class C, class D, class E, class F >
507  int Fscanf( const char *format, A *a, B *b, C *c, D *d, E *e, F *f )
508  {
509  int ret = -1;
510  if (!UseVolumes[this->alt_type]) {
511  ret = fscanf( fp, format, a, b, c, d, e, f );
512  } else {
513  if (q_volume_format == vfmtPK3) {
514  checkExtracted();
515  int ret = -1, readbytes = 0;
516  int length = strlen( format );
517  int newlength = length+3;
518  char *newformat = new char[newlength];
519  memset( newformat, 0, newlength );
520  memcpy( newformat, format, length );
521  strcat( newformat, "%n" );
522  ret = sscanf( this->pk3_extracted_file+offset, newformat, a, b, c, d, e, f, &readbytes );
523  delete[] newformat;
524  this->offset += readbytes;
525  this->GoAfterEOL();
526  } else if (q_volume_format == vfmtVSR) {}
527  }
528  return ret;
529  }
530 
531  int Fprintf( const char *format, ... );
532 
533 /********************************** FILE POINTER POSITION OPERATIONS IN A FILE *********************************/
534  long Size(); //Returns the size of the file : current position in file is not changed
535  void Begin(); //Set the file pointer to the beginning of the file
536  long GetPosition(); //Get the current file pointer position
537  void End(); //Set the file pointer to the end of the file
538  void GoTo( long offset ); //Does a fseek( fp, offset, SEEK_SET);
539  void Clear(); //Empty the file and then set file pointer to the beginning
540  bool Eof(); //Return true if end of file
541  bool Valid(); //Tells wether the file is valid or not
542 
543 /********************************** FILE PATH *********************************/
544  const string& GetFilename() const
545  {
546  return this->filename;
547  }
548  const string& GetDirectory() const
549  {
550  return this->directoryname;
551  }
552  const string& GetSubDirectory() const
553  {
554  return this->subdirectoryname;
555  }
556  const string& GetRoot() const
557  {
558  return this->rootname;
559  }
560 
561  void SetFilename( const string &filename )
562  {
563  this->filename = filename;
564  }
565  void SetDirectory( const string &directory )
566  {
567  this->directoryname = directory;
568  }
569  void SetSubDirectory( const string &subdirectory )
570  {
571  this->subdirectoryname = subdirectory;
572  }
573  void SetRoot( const string &root )
574  {
575  this->rootname = root;
576  }
577 
578  string GetFullPath();
579  string GetAbsPath();
580 
581  void SetType( VSFileType type );
582  void SetAltType( VSFileType type );
584  {
585  return file_type;
586  }
588  {
589  return alt_type;
590  }
591 
592  void SetIndex( int index );
593  void SetVolume( VSVolumeType big );
594  bool UseVolume();
595 
596  friend class VSImage;
597 
598 private:
599  void private_init();
600 };
601 };
602 
603 std::ostream&operator<<( std::ostream &ostr, VSFileSystem::VSError err );
604 std::ostream&operator<<( std::ostream &ostr, VSFileSystem::VSFileType type );
605 std::string nameof( VSFileSystem::VSFileType type );
606 
607 #if defined (_WIN32) && !defined (__CYGWIN__)
608 //Emulation of posix scandir() call
609 int scandir( const char *dirname, struct dirent ***namelist,
610  int (*select)( const struct dirent* ),
611  int (*compar)( const struct dirent**, const struct dirent** ) );
612 #endif
613 
614 #endif
615