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:
parent
f04af0077e
commit
c0ef326340
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user