summaryrefslogtreecommitdiff
path: root/src/sys_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys_unix.c')
-rw-r--r--src/sys_unix.c220
1 files changed, 78 insertions, 142 deletions
diff --git a/src/sys_unix.c b/src/sys_unix.c
index 1ab3630..94ec24e 100644
--- a/src/sys_unix.c
+++ b/src/sys_unix.c
@@ -835,187 +835,123 @@ MISC
===============================================================================
*/
+static void *copy_info( const char *name, const struct stat *st ) {
+ return FS_CopyInfo( name, st->st_size, st->st_ctime, st->st_mtime );
+}
+
/*
=================
-Sys_ListFilteredFiles
+Sys_ListFiles_r
+
+Internal function to filesystem. Conventions apply:
+ - files should hold at least MAX_LISTED_FILES
+ - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1]
+ - depth must be 0 on the first call
=================
*/
-static void Sys_ListFilteredFiles( void **listedFiles,
- int *count,
- const char *path,
- const char *filter,
- int flags,
- size_t baselen,
- int depth )
+void Sys_ListFiles_r( const char *path,
+ const char *filter,
+ unsigned flags,
+ size_t baselen,
+ int *count_p,
+ void **files,
+ int depth )
{
- struct dirent *findInfo;
- DIR *findHandle;
- struct stat st;
- char findPath[MAX_OSPATH];
- char *name;
- size_t len;
-
- if( depth >= 32 ) {
- return;
- }
-
- if( *count >= MAX_LISTED_FILES ) {
- return;
- }
+ struct dirent *ent;
+ DIR *dir;
+ struct stat st;
+ char fullpath[MAX_OSPATH];
+ char *name;
+ size_t len;
+ void *info;
- if( ( findHandle = opendir( path ) ) == NULL ) {
+ if( ( dir = opendir( path ) ) == NULL ) {
return;
}
- while( ( findInfo = readdir( findHandle ) ) != NULL ) {
- if( !strcmp( findInfo->d_name, "." ) ) {
- continue;
- }
- if( !strcmp( findInfo->d_name, ".." ) ) {
- continue;
- }
- len = Q_concat( findPath, sizeof( findPath ),
- path, "/", findInfo->d_name, NULL );
- if( len >= sizeof( findPath ) ) {
- continue;
+ while( ( ent = readdir( dir ) ) != NULL ) {
+ if( ent->d_name[0] == '.' ) {
+ continue; // ignore dotfiles
}
- if( stat( findPath, &st ) == -1 ) {
+ len = Q_concat( fullpath, sizeof( fullpath ),
+ path, "/", ent->d_name, NULL );
+ if( len >= sizeof( fullpath ) ) {
continue;
}
- if( st.st_mode & S_IFDIR ) {
- Sys_ListFilteredFiles( listedFiles, count, findPath,
- filter, flags, baselen, depth + 1 );
- }
-
- if( ( flags & FS_SEARCHDIRS_MASK ) == FS_SEARCHDIRS_ONLY ) {
- if( !( st.st_mode & S_IFDIR ) ) {
- continue;
- }
- } else if( ( flags & FS_SEARCHDIRS_MASK ) == FS_SEARCHDIRS_NO ) {
- if( st.st_mode & S_IFDIR ) {
- continue;
- }
- }
-
- if( !FS_WildCmp( filter, findPath + baselen ) ) {
+ if( stat( fullpath, &st ) == -1 ) {
continue;
}
- if( flags & FS_SEARCH_SAVEPATH ) {
- name = findPath + baselen;
- } else {
- name = findInfo->d_name;
- }
-
- if( flags & FS_SEARCH_EXTRAINFO ) {
- listedFiles[( *count )++] = FS_CopyInfo( name,
- st.st_size, st.st_ctime, st.st_mtime );
- } else {
- listedFiles[( *count )++] = FS_CopyString( name );
- }
- if( *count >= MAX_LISTED_FILES ) {
- break;
- }
-
- }
-
- closedir( findHandle );
-}
+ // pattern search implies recursive search
+ if( ( flags & FS_SEARCH_BYFILTER ) &&
+ S_ISDIR( st.st_mode ) && depth < MAX_LISTED_DEPTH )
+ {
+ Sys_ListFiles_r( fullpath, filter, flags, baselen,
+ count_p, files, depth + 1 );
-/*
-=================
-Sys_ListFiles
-=================
-*/
-void **Sys_ListFiles( const char *path,
- const char *extension,
- int flags,
- size_t baselen,
- int *numFiles )
-{
- struct dirent *findInfo;
- DIR *findHandle;
- struct stat st;
- char findPath[MAX_OSPATH];
- void *listedFiles[MAX_LISTED_FILES];
- int count = 0;
- char *s;
- size_t len;
-
- if( numFiles ) {
- *numFiles = 0;
- }
-
- if( flags & FS_SEARCH_BYFILTER ) {
- Sys_ListFilteredFiles( listedFiles, &count, path,
- extension, flags, baselen, 0 );
- } else {
- if( ( findHandle = opendir( path ) ) == NULL ) {
- return NULL;
+ // re-check count
+ if( *count_p >= MAX_LISTED_FILES ) {
+ break;
+ }
}
- while( ( findInfo = readdir( findHandle ) ) != NULL ) {
- if( !strcmp( findInfo->d_name, "." ) ) {
- continue;
- }
- if( !strcmp( findInfo->d_name, ".." ) ) {
+ // check type
+ if( flags & FS_SEARCH_DIRSONLY ) {
+ if( !S_ISDIR( st.st_mode ) ) {
continue;
}
-
- len = Q_concat( findPath, sizeof( findPath ),
- path, "/", findInfo->d_name, NULL );
- if( len >= sizeof( findPath ) ) {
+ } else {
+ if( !S_ISREG( st.st_mode ) ) {
continue;
}
+ }
- if( stat( findPath, &st ) == -1 ) {
- continue;
- }
- if( ( flags & FS_SEARCHDIRS_MASK ) == FS_SEARCHDIRS_ONLY ) {
- if( !( st.st_mode & S_IFDIR ) ) {
+ // check filter
+ if( filter ) {
+ if( flags & FS_SEARCH_BYFILTER ) {
+ if( !FS_WildCmp( filter, fullpath + baselen ) ) {
continue;
}
- } else if( ( flags & FS_SEARCHDIRS_MASK ) == FS_SEARCHDIRS_NO ) {
- if( st.st_mode & S_IFDIR ) {
+ } else {
+ if( !FS_ExtCmp( filter, ent->d_name ) ) {
continue;
}
}
+ }
- if( extension && !FS_ExtCmp( extension, findInfo->d_name ) ) {
- continue;
- }
-
- if( flags & FS_SEARCH_SAVEPATH ) {
- s = findPath + baselen;
- } else {
- s = findInfo->d_name;
- }
- if( flags & FS_SEARCH_EXTRAINFO ) {
- listedFiles[count++] = FS_CopyInfo( s, st.st_size,
- st.st_ctime, st.st_mtime );
- } else {
- listedFiles[count++] = FS_CopyString( s );
- }
+ // strip path
+ if( flags & FS_SEARCH_SAVEPATH ) {
+ name = fullpath + baselen;
+ } else {
+ name = ent->d_name;
+ }
- if( count >= MAX_LISTED_FILES ) {
- break;
+ // strip extension
+ if( flags & FS_SEARCH_STRIPEXT ) {
+ *COM_FileExtension( name ) = 0;
+
+ if( !*name ) {
+ continue;
}
}
- closedir( findHandle );
- }
+ // copy info off
+ if( flags & FS_SEARCH_EXTRAINFO ) {
+ info = copy_info( name, &st );
+ } else {
+ info = FS_CopyString( name );
+ }
- if( !count ) {
- return NULL;
- }
+ files[(*count_p)++] = info;
- if( numFiles ) {
- *numFiles = count;
+ if( *count_p >= MAX_LISTED_FILES ) {
+ break;
+ }
}
- return FS_CopyList( listedFiles, count );
+ closedir( dir );
}
/*