1
0
forked from 0ad/0ad

1) file: clean up path conversion call sites (was using private routine)

2) all: change file_enum and cohorts to pass struct stat instead of just
size

3) minor cleanup

This was SVN commit r1465.
This commit is contained in:
janwas 2004-12-07 01:19:10 +00:00
parent 1d1a2ce3e4
commit e15562b7ae
4 changed files with 59 additions and 68 deletions

View File

@ -197,7 +197,7 @@ int file_rel_chdir(const char* argv0, const char* const rel_path)
msg = "realpath returned an invalid path?";
goto fail;
}
CHECK_ERR(convert_path(fn+1, rel_path));
CHECK_ERR(file_make_native_path(rel_path, fn+1));
if(chdir(n_path) < 0)
goto fail;
@ -231,18 +231,29 @@ fail:
struct DirEnt
{
const std::string name;
const off_t size;
DirEnt(const char* const _name, const off_t _size)
: name(_name), size(_size) {}
// store only required fields from struct stat to save space.
// in order of decl in VC2003 sys/stat.h.
mode_t st_mode;
off_t st_size;
time_t st_mtime;
DirEnt(const char* _name, mode_t _st_mode, off_t _st_size, time_t _st_mtime)
: name(_name)
{
st_mode = _st_mode;
st_size = _st_size;
st_mtime = _st_mtime;
}
// no copy ctor, since some members are const
private:
DirEnt& operator=(const DirEnt&);
};
// pointer to DirEnt: faster sorting, but more allocs.
typedef std::vector<const DirEnt*> DirEnts;
typedef DirEnts::const_iterator DirEntIt;
typedef DirEnts::const_iterator DirEntCIt;
typedef DirEnts::reverse_iterator DirEntRIt;
static bool dirent_less(const DirEnt* const d1, const DirEnt* const d2)
@ -250,7 +261,7 @@ static bool dirent_less(const DirEnt* const d1, const DirEnt* const d2)
// call <cb> for each file and subdirectory in <dir> (alphabetical order),
// passing <user> and the entry name (not full path!).
// passing the entry name (not full path!), stat info, and <user>.
//
// first builds a list of entries (sorted) and remembers if an error occurred.
// if <cb> returns non-zero, abort immediately and return that; otherwise,
@ -297,8 +308,9 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
const char* fn = os_ent->d_name;
strncpy(fn_start, fn, PATH_MAX-n_path_len-1);
// stat needs the full path. this is easier than changing
// directory every time, and should be fast enough.
// need path for stat (we only have filename ATM).
// this is easier than changing directory every time,
// and should be fast enough.
// BTW, direct strcpy is faster than path_append -
// we save a strlen every iteration.
@ -313,34 +325,33 @@ int file_enum(const char* const dir, const FileCB cb, const uintptr_t user)
continue;
}
off_t size = s.st_size;
// dir
if(S_ISDIR(s.st_mode))
{
// skip . and ..
if(fn[0] == '.' && (fn[1] == '\0' || (fn[1] == '.' && fn[2] == '\0')))
continue;
size = -1;
}
// skip if neither dir nor file
else if(!S_ISREG(s.st_mode))
continue;
const DirEnt* const ent = new DirEnt(fn, size);
dirents.push_back(ent);
dirents.push_back(new DirEnt(fn, s.st_mode, s.st_size, s.st_mtime));
}
closedir(os_dir);
std::sort(dirents.begin(), dirents.end(), dirent_less);
for(DirEntIt it = dirents.begin(); it != dirents.end(); ++it)
struct stat s;
memset(&s, 0, sizeof(s));
for(DirEntCIt 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);
s.st_mode = ent->st_mode;
s.st_size = ent->st_size;
s.st_mtime = ent->st_mtime;
ret = cb(name_c, &s, user);
if(ret != 0)
{
cb_err = ret; // first error (since we now abort)
@ -364,7 +375,7 @@ int file_stat(const char* const path, struct stat* const s)
memset(s, 0, sizeof(struct stat));
char n_path[PATH_MAX+1];
CHECK_ERR(convert_path(n_path, path));
CHECK_ERR(file_make_native_path(path, n_path));
return stat(n_path, s);
}
@ -456,7 +467,7 @@ int file_open(const char* const p_fn, const uint flags, File* const f)
memset(f, 0, sizeof(File));
char n_fn[PATH_MAX];
CHECK_ERR(convert_path(n_fn, p_fn));
CHECK_ERR(file_make_native_path(p_fn, n_fn));
if(!f)
goto invalid_f;

View File

@ -20,6 +20,8 @@
#ifndef FILE_H
#define FILE_H
#include "posix.h" // struct stat
struct File
{
@ -95,12 +97,12 @@ extern int file_rel_chdir(const char* argv0, const char* rel_path);
// called by file_enum for each entry in the directory.
// name doesn't include path! it's a directory <==> size < 0.
// name doesn't include path!
// 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);
typedef int(*FileCB)(const char* const name, const struct stat* s, const uintptr_t user);
// call <cb> for each file and subdirectory in <dir> (alphabetical order),
// passing <user> and the entry name (not full path!).
// passing the entry name (not full path!), stat info, and <user>.
//
// first builds a list of entries (sorted) and remembers if an error occurred.
// if <cb> returns non-zero, abort immediately and return that; otherwise,

View File

@ -38,6 +38,8 @@
#include "zip.h"
#include "res.h"
#include <map>
#include <assert.h>
// provision for removing all ZLib code (all inflate calls will fail).
@ -57,8 +59,6 @@
# endif
#endif
#include <map>
///////////////////////////////////////////////////////////////////////////////
//
@ -190,14 +190,6 @@ static int z_verify_lfh(const void* const file, const off_t lfh_ofs, const off_t
//
///////////////////////////////////////////////////////////////////////////////
static inline uint is_leap_year(uint year)
{
if(year % 4 != 0)
return 0;
return (year % 100 != 0 || year % 400 == 0)? 1 : 0;
}
static uint bits(uint num, uint lo_idx, uint hi_idx)
{
uint result = num;
@ -211,39 +203,19 @@ static uint bits(uint num, uint lo_idx, uint hi_idx)
static time_t convert_dos_date(u16 fatdate, u16 fattime)
{
time_t result = 0;
struct tm t;
t.tm_sec = bits(fattime, 0,4) * 2; // [0,59]
t.tm_min = bits(fattime, 5,10); // [0,59]
t.tm_hour = bits(fattime, 11,15); // [0,23]
t.tm_mday = bits(fatdate, 0,4); // [1,31]
t.tm_mon = bits(fatdate, 5,8)-1; // [0,11]
t.tm_year = bits(fatdate, 9,15) + 80; // since 1900
t.tm_isdst = -1; // unknown - let libc determine
uint second = bits(fattime, 0,4) * 2;
uint minute = bits(fattime, 5,10); // 0..59
uint hour = bits(fattime, 11,15); // 0..23
uint day = bits(fatdate, 0,4); // of month; 1..31
uint month = bits(fatdate, 5,8); // 1..12
uint year = bits(fatdate, 9,15) + 1980;
if(second >= 60 || minute >= 60 || hour >= 24 || !day || day > 31 || !month || month > 12)
{
debug_warn("convert_dos_date: not normalized");
return 0;
}
// add days in previous years
for(uint y = 1970; y < year; y++)
{
result += 365;
if(is_leap_year(y))
result++;
}
// add days in previous months
static uint days_in_month[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
days_in_month[1] = is_leap_year(year)? 29 : 28;
for(uint m = 1; m < month; m++)
result += days_in_month[m-1];
result += day-1; // total days since 1970
result *= 86400; // now seconds
result += hour*3600 + minute*60 + second; // total seconds since 1970
return result;
time_t ret = mktime(&t);
if(ret == (time_t)-1)
debug_warn("convert_dos_date: mktime failed");
return ret;
}
@ -283,7 +255,6 @@ static int z_extract_cdfh(const u8* cdfh, const ssize_t bytes_left, const char*&
const char* fn_ = (const char*)cdfh+CDFH_SIZE;
// not 0-terminated!
//
// check if valid and data should actually be returned
//
@ -296,7 +267,7 @@ static int z_extract_cdfh(const u8* cdfh, const ssize_t bytes_left, const char*&
}
// .. this is a directory entry; we only want files.
if(!csize_ && !ucsize_)
return -1;
return -1;
#ifdef PARANOIA
// .. CDFH's file ofs doesn't match that reported by LFH.
// don't check this in normal builds - seeking between LFHs and
@ -633,10 +604,17 @@ have_idx:
// if it returns a nonzero value, abort and return that, otherwise 0.
static int lookup_enum_files(LookupInfo* const li, FileCB cb, uintptr_t user)
{
struct stat s;
memset(&s, 0, sizeof(s));
const ZEnt* ent = li->ents;
for(i32 i = 0; i < li->num_files; i++, ent++)
{
int ret = cb(ent->fn, (ssize_t)ent->loc.ucsize, user);
s.st_mode = S_IFREG;
s.st_size = (off_t)ent->loc.ucsize;
s.st_mtime = ent->loc.mtime;
int ret = cb(ent->fn, &s, user);
if(ret != 0)
return ret;
}

View File

@ -335,7 +335,7 @@ struct PathInfo
// if this file is an OpenAL DLL, add it to our list.
// (match "*oal.dll" and "*OpenAL*", as with OpenAL router's search).
static int check_if_oal_dll(const char* fn, const ssize_t size, const uintptr_t user)
static int check_if_oal_dll(const char* fn, const struct stat* s, const uintptr_t user)
{
PathInfo* pi = (PathInfo*)user;
strncpy(pi->end, fn, pi->remaining);