28 #include <sys/types.h>
42 #define CF_ROOTTYPE_PATH 0
43 #define CF_ROOTTYPE_PACK 1
65 #define CF_NUM_ROOTS_PER_BLOCK 32
66 #define CF_MAX_ROOT_BLOCKS 256 // Can store 32*256 = 8192 Roots
67 #define CF_MAX_ROOTS (CF_NUM_ROOTS_PER_BLOCK * CF_MAX_ROOT_BLOCKS)
73 static int Num_roots = 0;
76 static int Num_path_roots = 0;
88 #define CF_NUM_FILES_PER_BLOCK 512
89 #define CF_MAX_FILE_BLOCKS 128 // Can store 512*128 = 65536 files
116 if ( File_blocks[block] == NULL ) {
118 Assert( File_blocks[block] != NULL);
147 if ( Root_blocks[block] == NULL ) {
149 Assert(Root_blocks[block] != NULL);
168 filespec = root->
path;
185 find_handle = _findfirst( filespec.c_str( ), &find );
187 if (find_handle != -1) {
189 if (!(find.attrib & _A_SUBDIR)) {
193 }
while (!_findnext(find_handle, &find));
195 _findclose( find_handle );
197 #elif defined SCP_UNIX
198 filespec +=
"*.[vV][pP]";
201 memset(&globinfo, 0,
sizeof(globinfo));
202 int status = glob(filespec.c_str( ), 0, NULL, &globinfo);
204 for (
unsigned int j = 0; j < globinfo.gl_pathc; j++) {
207 memset(&statbuf, 0,
sizeof(statbuf));
208 stat(globinfo.gl_pathv[j], &statbuf);
209 if (S_ISREG(statbuf.st_mode)) {
218 return packfile_count;
239 int temp_root_count, root_index;
244 if (temp_root_count <= 0)
250 if (temp_roots_sort == NULL) {
273 find_handle = _findfirst( filespec, &find );
275 if (find_handle != -1) {
278 if (!(find.attrib & _A_SUBDIR)) {
279 Assert(root_index < temp_root_count);
282 rptr_sort = &temp_roots_sort[root_index++];
298 }
while (!_findnext(find_handle, &find));
300 _findclose( find_handle );
302 #elif defined SCP_UNIX
306 memset(&globinfo, 0,
sizeof(globinfo));
308 int status = glob(filespec, 0, NULL, &globinfo);
311 for (
uint j = 0; j < globinfo.gl_pathc; j++) {
314 memset(&statbuf, 0,
sizeof(statbuf));
315 stat(globinfo.gl_pathv[j], &statbuf);
317 if ( S_ISREG(statbuf.st_mode) ) {
318 Assert(root_index < temp_root_count);
321 rptr_sort = &temp_roots_sort[root_index++];
336 Assert(root_index == temp_root_count);
343 for (i = 0; i < temp_root_count; i++) {
350 mprintf((
"Found root pack '%s' with a checksum of 0x%08x\n", temp_roots_sort[i].path, chksum));
377 for (cur_pos=
Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
386 Error(
LOCATION,
"Home directory plus mod directory exceeds CF_MAX_PATHNAME_LENGTH\n");
428 for (cur_pos=
Cmdline_mod; *cur_pos !=
'\0'; cur_pos+= (strlen(cur_pos)+1))
437 Error(
LOCATION,
"Can't get current working directory -- %d", errno );
442 Error(
LOCATION,
"Installed path plus mod directory exceeds CF_MAX_PATHNAME_LENGTH\n");
445 path_len = strlen(root->
path);
462 Error(
LOCATION,
"Can't get current working directory -- %d", errno );
465 path_len = strlen(root->
path);
507 if ( strstr(ext_list, tmp_ext )) {
521 mprintf((
"Searching root '%s' ... ", root->
path ));
547 find_handle = _findfirst( search_path, &find );
549 if (find_handle != -1) {
551 if (!(find.attrib & _A_SUBDIR)) {
553 char *ext = strrchr( find.name,
'.' );
563 file->
size = find.size;
573 }
while (!_findnext(find_handle, &find));
575 _findclose( find_handle );
577 #elif defined SCP_UNIX
581 dirp = opendir (search_path);
583 while ((dir = readdir (dirp)) != NULL)
585 if (!fnmatch (
"*.*", dir->d_name, 0))
588 snprintf(fn,
MAX_PATH-1,
"%s%s", search_path, dir->d_name);
592 if (stat(fn, &buf) == -1) {
596 if (!S_ISREG(buf.st_mode)) {
600 char *ext = strrchr( dir->d_name,
'.' );
612 file->
size = buf.st_size;
627 mprintf((
"%i files\n", num_files ));
653 FILE *
fp = fopen( root->
path,
"rb" );
660 mprintf((
"Skipping VP file ('%s') of invalid size...\n", root->
path ));
667 Assert(
sizeof(VP_header) == 16 );
668 if (fread(&VP_header,
sizeof(VP_header), 1, fp) != 1) {
669 mprintf((
"Skipping VP file ('%s') because the header could not be read...\n", root->
path));
678 mprintf((
"Searching root pack '%s' ... ", root->
path ));
692 if (fread( &find,
sizeof(
VP_FILE), 1, fp ) != 1) {
693 mprintf((
"Failed to read file entry (currently in directory %s)!\n", search_path));
702 if ( find.
size == 0 ) {
703 int search_path_len = strlen(search_path);
705 char *
p = &search_path[search_path_len-1];
725 char *ext = strrchr( find.
filename,
'.' );
748 mprintf((
"%i files\n", num_files ));
760 for (i=0; i<Num_roots; i++ ) {
782 Root_blocks[
i] = NULL;
787 File_blocks[
i] = NULL;
790 mprintf((
"Building file index...\n" ));
807 if ( Root_blocks[i] ) {
809 Root_blocks[
i] = NULL;
816 if ( File_blocks[i] ) {
818 File_blocks[
i] = NULL;
843 int cfs_slow_search = 0;
848 _finddata_t findstruct;
851 Assert( (filespec != NULL) && (strlen(filespec) > 0) );
852 Assert( (pack_filename == NULL) || (max_out > 1) );
862 if ( strpbrk(filespec,
"/") ) {
864 if ( strpbrk(filespec,
"/\\:") ) {
866 FILE *
fp = fopen(filespec,
"rb" );
869 if ( offset ) *offset = 0;
870 if ( pack_filename ) {
871 strncpy( pack_filename, filespec, max_out );
881 uint num_search_dirs = 0;
885 search_order[num_search_dirs++] = pathtype;
889 search_order[num_search_dirs++] =
i;
893 memset( longname, 0,
sizeof(longname) );
896 for (ui=0; ui<num_search_dirs; ui++ ) {
897 switch (search_order[ui])
911 cfs_slow_search = (num_search_dirs == 1) ? 1 : 0;
915 if (cfs_slow_search) {
919 findhandle = _findfirst(longname, &findstruct);
920 if (findhandle != -1) {
922 *size = findstruct.size;
924 _findclose(findhandle);
930 strncpy( pack_filename, longname, max_out );
936 FILE *
fp = fopen(longname,
"rb" );
948 strncpy(pack_filename, longname, max_out);
980 strncpy( pack_filename, r->
path, max_out );
1005 if (pack_filename) {
1008 strcpy( pack_filename, r->
path );
1030 extern char *
stristr(
char *str,
const char *substr);
1050 int cf_find_file_location_ext(
const char *
filename,
const int ext_num,
const char **ext_list,
int pathtype,
int max_out,
char *pack_filename,
int *size,
int *offset,
bool localize )
1054 int cfs_slow_search = 0;
1061 _finddata_t findstruct;
1065 Assert( (ext_list != NULL) && (ext_num > 1) );
1067 Assert( (pack_filename == NULL) || (max_out > 1) );
1072 if ( strpbrk(filename,
"/") ) {
1074 if ( strpbrk(filename,
"/\\:") ) {
1081 uint num_search_dirs = 0;
1085 search_order[num_search_dirs++] = pathtype;
1088 search_order[num_search_dirs++] = i;
1091 memset( longname, 0,
sizeof(longname) );
1092 memset( filespec, 0,
sizeof(filespec) );
1097 for (ui = 0; ui < num_search_dirs; ui++) {
1099 if (num_search_dirs == 1) {
1100 cfs_slow_search = 1;
1104 switch (search_order[ui])
1113 cfs_slow_search = 1;
1118 if ( !cfs_slow_search )
1121 for (cur_ext = 0; cur_ext < ext_num; cur_ext++) {
1125 p = strrchr(filespec,
'.');
1126 if ( p && (strlen(p) > 2) )
1129 strcat_s( filespec, ext_list[cur_ext] );
1134 findhandle = _findfirst(longname, &findstruct);
1135 if (findhandle != -1) {
1137 *size = findstruct.size;
1139 _findclose(findhandle);
1145 strncpy( pack_filename, longname, max_out );
1151 FILE *
fp = fopen(longname,
"rb" );
1163 strncpy(pack_filename, longname, max_out);
1176 p = strrchr(filespec,
'.');
1177 if ( p && (strlen(p) > 2) )
1181 int filespec_len = strlen(filespec);
1185 uint filespec_len_big = filespec_len + strlen(ext_list[0]);
1188 int last_root_index = -1;
1189 int last_path_index = -1;
1191 file_list_index.reserve(
MIN(ext_num * 4, (
int)
Num_files) );
1202 if ( strlen(f->
name_ext) != filespec_len_big )
1210 bool found_one =
false;
1211 for (cur_ext = 0; cur_ext < ext_num; cur_ext++) {
1222 if (last_root_index == -1) {
1234 file_list_index.push_back( f );
1238 for (cur_ext = 0; cur_ext < ext_num; cur_ext++) {
1242 strcat_s( filespec, ext_list[cur_ext] );
1256 if (pack_filename) {
1259 strncpy( pack_filename, r->
path, max_out );
1272 file_list_index.clear();
1287 if (pack_filename) {
1290 strcpy( pack_filename, r->
path );
1306 file_list_index.clear();
1313 p = strrchr(filespec,
'.');
1314 if ( p && (strlen(p) > 2) )
1326 const char *src_ext;
1327 const char *dst_ext;
1329 src_ext = strrchr(filespec,
'*');
1332 src_ext = strrchr(filespec,
'.');
1341 if(strlen(filespec) > strlen(filename))
1346 dst_ext = filename + strlen(filename) - ((filespec + strlen(filespec)) - src_ext);
1350 if(src_ext == filespec)
1352 return !
stricmp(dst_ext, src_ext);
1356 return (!
stricmp(dst_ext, src_ext) && !
strnicmp(dst_ext, src_ext, src_ext - filespec));
1364 static bool verify_file_list_child()
1366 if (Get_file_list_child == NULL) {
1371 size_t len = strlen(Get_file_list_child);
1382 if ( strchr(Get_file_list_child,
':') || strchr(Get_file_list_child,
' ') ) {
1392 size_t i, size = list.size();
1398 strcpy_s(name_no_extension, filename );
1399 char *p = strrchr( name_no_extension,
'.' );
1402 for (i = 0; i <
size; i++) {
1403 if ( !
stricmp(list[i].c_str(), name_no_extension ) ) {
1421 int l, own_flag = 0;
1432 bool check_duplicates = !list.empty();
1439 if (Get_file_list_child && !verify_file_list_child() ) {
1440 Get_file_list_child = NULL;
1451 find_handle = _findfirst( filespec, &find );
1452 if (find_handle != -1) {
1454 if (strcmp(strrchr(filter,
'.'), strrchr(find.name,
'.')) != 0)
1457 if (!(find.attrib & _A_SUBDIR)) {
1463 ptr = strrchr(find.name,
'.');
1465 l = ptr - find.name;
1467 l = strlen(find.name);
1473 info->push_back( tinfo );
1478 }
while (!_findnext(find_handle, &find));
1480 _findclose( find_handle );
1483 #elif defined SCP_UNIX
1489 dirp = opendir (filespec);
1491 while ((dir = readdir (dirp)) != NULL) {
1493 if (fnmatch(filter, dir->d_name, 0) != 0)
1497 snprintf(fn,
MAX_PATH-1,
"%s/%s", filespec, dir->d_name);
1501 if (stat(fn, &buf) == -1) {
1505 if (!S_ISREG(buf.st_mode)) {
1514 ptr = strrchr(dir->d_name,
'.');
1516 l = ptr - dir->d_name;
1518 l = strlen(dir->d_name);
1520 list.push_back(
SCP_string(dir->d_name, l) );
1524 info->push_back( tinfo );
1533 bool skip_packfiles = (Skip_packfile_search != 0);
1536 skip_packfiles =
true;
1537 }
else if (Get_file_list_child != NULL) {
1538 skip_packfiles =
true;
1542 if ( !skip_packfiles ) {
1572 info->push_back( tinfo );
1589 Get_file_list_child = NULL;
1591 return (
int)list.size();
1600 strcpy_s(name_no_extension, filename );
1601 char *p = strrchr( name_no_extension,
'.' );
1604 for (i=0; i<num_files; i++ ) {
1605 if ( !
stricmp(list[i], name_no_extension ) ) {
1622 int l, num_files = 0, own_flag = 0;
1645 find_handle = _findfirst( filespec, &find );
1646 if (find_handle != -1) {
1648 if (num_files >= max)
1651 if (strcmp(strrchr(filter,
'.'), strrchr(find.name,
'.')) != 0)
1657 if (!(find.attrib & _A_SUBDIR)) {
1659 ptr = strrchr(find.name,
'.');
1661 l = ptr - find.name;
1663 l = strlen(find.name);
1665 list[num_files] = (
char *)
vm_malloc(l + 1);
1666 strncpy(list[num_files], find.name, l);
1667 list[num_files][l] = 0;
1669 info[num_files].
write_time = find.time_write;
1675 }
while (!_findnext(find_handle, &find));
1677 _findclose( find_handle );
1680 #elif defined SCP_UNIX
1686 dirp = opendir (filespec);
1688 while ((dir = readdir (dirp)) != NULL)
1690 if (num_files >= max)
1697 if (fnmatch(filter, dir->d_name, 0) != 0)
1701 snprintf(fn,
MAX_PATH-1,
"%s/%s", filespec, dir->d_name);
1705 if (stat(fn, &buf) == -1) {
1709 if (!S_ISREG(buf.st_mode)) {
1714 ptr = strrchr(dir->d_name,
'.');
1716 l = ptr - dir->d_name;
1718 l = strlen(dir->d_name);
1720 list[num_files] = (
char *)
vm_malloc(l + 1);
1721 strncpy(list[num_files], dir->d_name, l);
1722 list[num_files][l] = 0;
1735 if ( !Skip_packfile_search ) {
1744 if (num_files >= max)
1765 list[num_files] = (
char *)
vm_malloc(l + 1);
1766 strncpy(list[num_files], f->
name_ext, l);
1767 list[num_files][l] = 0;
1799 strcpy_s(name_no_extension, filename );
1800 char *p = strrchr( name_no_extension,
'.' );
1803 for (i=0; i<num_files; i++ ) {
1804 if ( !
stricmp(arr[i], name_no_extension ) ) {
1819 int num_files = 0, own_flag = 0;
1828 for (
int i=0; i<max; i++) {
1851 find_handle = _findfirst( filespec, &find );
1852 if (find_handle != -1) {
1854 if (num_files >= max)
1857 if (!(find.attrib & _A_SUBDIR)) {
1859 if (strcmp(strstr(filter,
"."), strstr(find.name,
".")) != 0)
1862 if ( strlen(find.name) >= MAX_FILENAME_LEN )
1867 strncpy(arr[num_files], find.name, MAX_FILENAME_LEN - 1 );
1868 char *ptr = strrchr(arr[num_files],
'.');
1874 info[num_files].
write_time = find.time_write;
1881 }
while (!_findnext(find_handle, &find));
1883 _findclose( find_handle );
1886 #elif defined SCP_UNIX
1892 dirp = opendir (filespec);
1894 while ((dir = readdir (dirp)) != NULL)
1896 if (num_files >= max)
1899 if (fnmatch(filter, dir->d_name, 0) != 0)
1903 snprintf(fn,
MAX_PATH-1,
"%s/%s", filespec, dir->d_name);
1907 if (stat(fn, &buf) == -1) {
1911 if (!S_ISREG(buf.st_mode)) {
1915 if ( strlen(dir->d_name) >= MAX_FILENAME_LEN ) {
1921 strncpy(arr[num_files], dir->d_name, MAX_FILENAME_LEN - 1 );
1922 char *ptr = strrchr(arr[num_files],
'.');
1939 if ( !Skip_packfile_search ) {
1948 if (num_files >= max)
1964 strncpy(arr[num_files], f->
name_ext, MAX_FILENAME_LEN - 1 );
1965 char *ptr = strrchr(arr[num_files],
'.');
2007 if ( filename && strpbrk(filename,
"/") ) {
2009 if ( filename && strpbrk(filename,
"/\\:") ) {
2012 strncpy( path, filename, path_max );
2018 Assert( filename != NULL );
2019 strncpy(path, filename, path_max);
2029 strncpy(path, root->
path, path_max);
2035 if (
Pathtypes[pathtype].path[0] !=
'\0') {
2043 strcat_s(path, path_max, filename);
2054 FILE *
fp = fopen(path,
"rb");
2079 if ( filename && strpbrk(filename,
"/") ) {
2081 if ( filename && strpbrk(filename,
"/\\:") ) {
2084 path.assign(filename);
2090 Assert( filename != NULL );
2091 path.assign(filename);
2096 std::ostringstream s_path;
2102 s_path << root->
path;
2108 if (
Pathtypes[pathtype].path[0] !=
'\0') {
2122 path = s_path.str().c_str();
2142 FILE *out = fopen(out_path,
"w");
2149 my_time = time(NULL);
2151 memset( datetime, 0,
sizeof(datetime) );
2152 snprintf(datetime,
sizeof(datetime)-1,
"%s", ctime(&my_time));
2154 datetime[strlen(datetime)-1] =
'\0';
2156 fprintf(out,
"Pack file CRC log (%s) ... \n", datetime);
2157 fprintf(out,
"-------------------------------------------------------------------------------\n");
2159 for (i = 0; i < Num_roots; i++) {
2168 fprintf(out,
" %s -- 0x%x\n", cur_root->
path, chksum);
2171 fprintf(out,
"-------------------------------------------------------------------------------\n");
#define CF_TYPE_SINGLE_PLAYERS
void cfile_spew_pack_file_crcs()
const char * Get_file_list_child
void cf_build_root_list(const char *cdrom_dir)
cf_file * cf_create_file()
#define DIR_SEPARATOR_CHAR
char name_ext[CF_MAX_FILENAME_LENGTH]
void cf_free_secondary_filelist()
#define Assertion(expr, msg,...)
#define CF_NUM_ROOTS_PER_BLOCK
void cf_search_root_path(int root_index)
char path[CF_MAX_PATHNAME_LENGTH]
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
bool cf_packfile_sort_func(const cf_root_sort &r1, const cf_root_sort &r2)
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize)
char path[CF_MAX_PATHNAME_LENGTH]
#define CF_TYPE_MULTI_CACHE
int cf_chksum_pack(const char *filename, uint *chk_long, bool full)
void cf_build_pack_list(cf_root *root)
cf_root roots[CF_NUM_ROOTS_PER_BLOCK]
int _getcwd(char *buffer, unsigned int len)
int lcl_add_dir_to_path_with_filename(char *current_path, size_t path_max)
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define CF_MAX_PATHNAME_LENGTH
GLdouble GLdouble GLdouble r
void cf_search_root_pack(int root_index)
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES]
#define CF_TYPE_MULTI_PLAYERS
#define DIR_SEPARATOR_STR
struct cf_root_block cf_root_block
#define strnicmp(s1, s2, n)
int cf_get_packfile_count(cf_root *root)
cf_file files[CF_NUM_FILES_PER_BLOCK]
char * stristr(char *str, const char *substr)
#define CF_NUM_FILES_PER_BLOCK
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
int(* Get_file_list_filter)(const char *filename)
void cf_sort_filenames(int n, char **list, int sort, file_list_info *info=NULL)
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, const char *filter, int sort, file_list_info *info)
int cf_matches_spec(const char *filespec, const char *filename)
cf_root * cf_create_root()
int cf_find_file_location(const char *filespec, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize)
cf_file * cf_get_file(int index)
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define CF_MAX_FILE_BLOCKS
void cf_build_secondary_filelist(const char *cdrom_dir)
int cf_get_file_list(SCP_vector< SCP_string > &list, int pathtype, const char *filter, int sort, SCP_vector< file_list_info > *info)
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, int *size, int *offset, bool localize)
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN]
#define CF_MAX_ROOT_BLOCKS
#define CF_TYPE_SPECIFIED(path_type)
void cf_build_file_list()
#define CFILE_ROOT_DIRECTORY_LEN
GLsizei const GLchar ** path
int cf_file_already_in_list(int num_files, char **list, const char *filename)
int is_ext_in_list(const char *ext_list, const char *ext)
int cf_file_already_in_list_preallocated(int num_files, char arr[][MAX_FILENAME_LEN], const char *filename)
#define CF_MAX_FILENAME_LENGTH
#define CF_MAX_PATH_TYPES
struct cf_root_sort cf_root_sort
struct VP_FILE_HEADER VP_FILE_HEADER
cf_root * cf_get_root(int n)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
struct cf_file_block cf_file_block