1
0
forked from 0ad/0ad

1) file.cpp: add functions for relative path conversion, also better dox

2) ERR_PATH_LENGTH (instead of ERR_VFS_): now used by file.cpp also
3) better document file_enum and FileCB

This was SVN commit r1433.
This commit is contained in:
janwas 2004-12-01 18:44:38 +00:00
parent f04af0077e
commit c0ef326340
5 changed files with 83 additions and 43 deletions

View File

@ -125,9 +125,9 @@ enum LibError
ERR_INVALID_PARAM = -1003,
ERR_FILE_NOT_FOUND = -1004,
ERR_PATH_NOT_FOUND = -1005,
ERR_AGAIN = -1006, // try again later
ERR_PATH_LENGTH = -1006,
ERR_AGAIN = -1007, // try again later
ERR_VFS_PATH_LENGTH = -1007,
ERR_VFS_DIR_END = -1008,
ERR_LAST

View File

@ -60,6 +60,8 @@ const size_t SECTOR_SIZE = 4096;
// * requests for part of a block are usually followed by another.
enum Conversion
{
TO_NATIVE,
@ -68,15 +70,7 @@ enum Conversion
static int convert_path(char* dst, const char* src, Conversion conv = TO_NATIVE)
{
/*
// if there's a platform with multiple-character DIR_SEP,
// scan through the path and add space for each separator found.
const size_t len = strlen(p_path);
n_path = (const char*)malloc(len * sizeof(char));
if(!n_path)
return ERR_NO_MEM;
*/
// DIR_SEP is assumed to be a single character!
const char* s = src;
char* d = dst;
@ -91,7 +85,7 @@ static int convert_path(char* dst, const char* src, Conversion conv = TO_NATIVE)
{
len++;
if(len >= PATH_MAX)
return -1;
return ERR_PATH_LENGTH;
char c = *s++;
@ -112,21 +106,43 @@ static char n_root_dir[PATH_MAX];
static size_t n_root_dir_len;
// return the native equivalent of the given portable path
// return the native equivalent of the given relative portable path
// (i.e. convert all '/' to the platform's directory separator)
// makes sure length < PATH_MAX.
int file_make_native_path(const char* const path, char* const n_path)
{
strcpy(n_path, n_root_dir);
return convert_path(n_path+n_root_dir_len, path, TO_NATIVE);
return convert_path(n_path, path, TO_NATIVE);
}
// return the portable equivalent of the given relative native path
// (i.e. convert the platform's directory separators to '/')
// makes sure length < PATH_MAX.
int file_make_portable_path(const char* const n_path, char* const path)
{
return convert_path(path, n_path, TO_PORTABLE);
}
int file_make_portable_path(const char* const n_path, char* const path)
// return the native equivalent of the given portable path
// (i.e. convert all '/' to the platform's directory separator).
// also prepends current directory => n_full_path is absolute.
// makes sure length < PATH_MAX.
int file_make_full_native_path(const char* const path, char* const n_full_path)
{
if(strncmp(n_path, n_root_dir, n_root_dir_len) != 0)
strcpy(n_full_path, n_root_dir);
return convert_path(n_full_path+n_root_dir_len, path, TO_NATIVE);
}
// return the portable equivalent of the given relative native path
// (i.e. convert the platform's directory separators to '/')
// n_full_path is absolute; if it doesn't match the current dir, fail.
// (note: portable paths are always relative to file_rel_chdir root).
// makes sure length < PATH_MAX.
int file_make_full_portable_path(const char* const n_full_path, char* const path)
{
if(strncmp(n_full_path, n_root_dir, n_root_dir_len) != 0)
return -1;
return convert_path(path, n_path+n_root_dir_len, TO_PORTABLE);
return convert_path(path, n_full_path+n_root_dir_len, TO_PORTABLE);
}
@ -227,13 +243,18 @@ private:
// pointer to DirEnt: faster sorting, but more allocs.
typedef std::vector<const DirEnt*> DirEnts;
typedef DirEnts::const_iterator DirEntIt;
typedef DirEnts::reverse_iterator DirEntRIt;
static bool dirent_less(const DirEnt* const d1, const DirEnt* const d2)
{ return d1->name.compare(d2->name) < 0; }
// for all files and dirs in <dir> (but not its subdirs!):
// call <cb>, passing <user> and the entries's name (not path!)
// call <cb> for each file and subdirectory in <dir> (alphabetical order),
// passing <user> and the entry name (not full path!).
//
// first builds a list of entries (sorted) and remembers if an error occurred.
// if <cb> returns non-zero, abort immediately and return that; otherwise,
// return first error encountered while listing files, or 0 on success.
//
// rationale:
// this makes file_enum and zip_enum slightly incompatible, since zip_enum
@ -251,14 +272,14 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
n_path[PATH_MAX-1] = '\0';
// will append filename to this, hence "path".
// 0-terminate simplifies filename strncpy below.
CHECK_ERR(convert_path(n_path, dir));
CHECK_ERR(file_make_native_path(dir, n_path));
// all entries are enumerated (adding to this container),
// std::sort-ed, then all passed to cb.
DirEnts dirents;
int stat_err = 0;
int cb_err = 0;
int stat_err = 0; // first error encountered by stat()
int cb_err = 0; // first error returned by cb
int ret;
DIR* const os_dir = opendir(n_path);
@ -288,7 +309,7 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
if(ret < 0)
{
if(stat_err == 0)
stat_err = ret;
stat_err = ret; // first error (see decl)
continue;
}
@ -314,21 +335,24 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
std::sort(dirents.begin(), dirents.end(), dirent_less);
DirEntIt it;
for(it = dirents.begin(); it != dirents.end(); ++it)
for(DirEntIt it = dirents.begin(); it != dirents.end(); ++it)
{
const DirEnt* const ent = *it;
const char* name_c = ent->name.c_str();
const ssize_t size = ent->size;
ret = cb(name_c, size, user);
if(ret < 0)
if(cb_err == 0)
cb_err = ret;
delete ent;
if(ret != 0)
{
cb_err = ret; // first error (since we now abort)
break;
}
}
if(cb_err < 0)
// free all memory (can't do in loop above because it can be aborted).
for(DirEntRIt rit = dirents.rbegin(); rit != dirents.rend(); ++rit)
delete *rit;
if(cb_err != 0)
return cb_err;
return stat_err;
}

View File

@ -62,11 +62,22 @@ enum
};
// convert to/from our portable path representation,
// e.g. for external libraries that require the real filename.
// note: also removes/adds current directory.
extern int file_make_native_path(const char* path, char* n_path);
extern int file_make_portable_path(const char* n_path, char* path);
//
// path conversion functions (native <--> portable),
// for external libraries that require the real filename.
//
// replaces '/' with platform's directory separator and vice versa.
// verifies path length < PATH_MAX (otherwise return ERR_PATH_LENGTH).
//
// relative paths (relative to root, established with file_rel_chdir)
extern int file_make_native_path(const char* const path, char* const n_path);
extern int file_make_portable_path(const char* const n_path, char* const path);
// as above, but with full native paths (portable paths are always relative).
// prepends current directory, resp. makes sure it matches the given path.
extern int file_make_full_native_path(const char* const path, char* const n_full_path);
extern int file_make_full_portable_path(const char* const n_full_path, char* const path);
// set current directory to rel_path, relative to the path to the executable,
@ -83,12 +94,17 @@ extern int file_make_portable_path(const char* n_path, char* path);
extern int file_rel_chdir(const char* argv0, const char* rel_path);
// called for each entry in a directory.
// name is the complete path (see below); it's a directory iff size < 0.
// called by file_enum for each entry in the directory.
// name doesn't include path! it's a directory <==> size < 0.
// return non-zero to immediately abort; file_enum will return that value.
typedef int(*FileCB)(const char* const name, const ssize_t size, const uintptr_t user);
// for all files and dirs in <dir> (but not its subdirs!):
// call <cb>, passing <user> and the entries's name (not path!)
// call <cb> for each file and subdirectory in <dir> (alphabetical order),
// passing <user> and the entry name (not full path!).
//
// first builds a list of entries (sorted) and remembers if an error occurred.
// if <cb> returns non-zero, abort immediately and return that; otherwise,
// return first error encountered while listing files, or 0 on success.
extern int file_enum(const char* dir, FileCB cb, uintptr_t user);
// get file status. output param is zeroed on error.

View File

@ -19,7 +19,7 @@ int res_reload(const char* const fn)
int res_watch_dir(const char* const path, intptr_t* const watch)
{
char n_path[PATH_MAX];
CHECK_ERR(file_make_native_path(path, n_path));
CHECK_ERR(file_make_full_native_path(path, n_path));
return dir_add_watch(n_path, watch);
}

View File

@ -115,7 +115,7 @@ static int path_append(char* dst, const char* path1, const char* path2)
}
if(total_len+1 > VFS_MAX_PATH)
return ERR_VFS_PATH_LENGTH;
return ERR_PATH_LENGTH;
char* p = dst;