Skip to content

Commit

Permalink
Fix memory leak in file_stat(). (#1871)
Browse files Browse the repository at this point in the history
* Change vfs_stat() api to pre-allocated buffer for stat info.
* Change vfs_readdir() api to stat buffer as well. vfs_item api removed.
  • Loading branch information
devsaurus authored and marcelstoer committed Mar 29, 2017
1 parent 92cfbb4 commit fc887e9
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 309 deletions.
159 changes: 34 additions & 125 deletions app/fatfs/myfatfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,12 @@ static uint32_t myfatfs_fsize( const struct vfs_file *fd );
static sint32_t myfatfs_ferrno( const struct vfs_file *fd );

static sint32_t myfatfs_closedir( const struct vfs_dir *dd );
static vfs_item *myfatfs_readdir( const struct vfs_dir *dd );

static void myfatfs_iclose( const struct vfs_item *di );
static uint32_t myfatfs_isize( const struct vfs_item *di );
static sint32_t myfatfs_time( const struct vfs_item *di, struct vfs_time *tm );
static const char *myfatfs_name( const struct vfs_item *di );
static sint32_t myfatfs_is_dir( const struct vfs_item *di );
static sint32_t myfatfs_is_rdonly( const struct vfs_item *di );
static sint32_t myfatfs_is_hidden( const struct vfs_item *di );
static sint32_t myfatfs_is_sys( const struct vfs_item *di );
static sint32_t myfatfs_is_arch( const struct vfs_item *di );
static sint32_t myfatfs_readdir( const struct vfs_dir *dd, struct vfs_stat *buf );

static vfs_vol *myfatfs_mount( const char *name, int num );
static vfs_file *myfatfs_open( const char *name, const char *mode );
static vfs_dir *myfatfs_opendir( const char *name );
static vfs_item *myfatfs_stat( const char *name );
static sint32_t myfatfs_stat( const char *name, struct vfs_stat *buf );
static sint32_t myfatfs_remove( const char *name );
static sint32_t myfatfs_rename( const char *oldname, const char *newname );
static sint32_t myfatfs_mkdir( const char *name );
Expand Down Expand Up @@ -89,18 +79,6 @@ static vfs_file_fns myfatfs_file_fns = {
.ferrno = myfatfs_ferrno
};

static vfs_item_fns myfatfs_item_fns = {
.close = myfatfs_iclose,
.size = myfatfs_isize,
.time = myfatfs_time,
.name = myfatfs_name,
.is_dir = myfatfs_is_dir,
.is_rdonly = myfatfs_is_rdonly,
.is_hidden = myfatfs_is_hidden,
.is_sys = myfatfs_is_sys,
.is_arch = myfatfs_is_arch
};

static vfs_dir_fns myfatfs_dir_fns = {
.close = myfatfs_closedir,
.readdir = myfatfs_readdir
Expand Down Expand Up @@ -130,11 +108,6 @@ struct myvfs_dir {
DIR dp;
};

struct myvfs_item {
struct vfs_item vfs_item;
FILINFO fno;
};


// ---------------------------------------------------------------------------
// exported helper functions for FatFS
Expand Down Expand Up @@ -321,105 +294,45 @@ static sint32_t myfatfs_closedir( const struct vfs_dir *dd )
return last_result == FR_OK ? VFS_RES_OK : VFS_RES_ERR;
}

static vfs_item *myfatfs_readdir( const struct vfs_dir *dd )
static void myfatfs_fill_stat( const FILINFO *fno, struct vfs_stat *buf )
{
GET_DIR_DP(dd);
struct myvfs_item *di;
c_memset( buf, 0, sizeof( struct vfs_stat ) );

if (di = c_malloc( sizeof( struct myvfs_item ) )) {
FILINFO *fno = &(di->fno);

if (FR_OK == (last_result = f_readdir( dp, fno ))) {
// condition "no further item" is signalled with empty name
if (fno->fname[0] != '\0') {
di->vfs_item.fs_type = VFS_FS_FATFS;
di->vfs_item.fns = &myfatfs_item_fns;
return (vfs_item *)di;
}
}
c_free( di );
}

return NULL;
}


// ---------------------------------------------------------------------------
// dir info functions
//
#define GET_FILINFO_FNO(descr) \
const struct myvfs_item *mydi = (const struct myvfs_item *)descr; \
FILINFO *fno = (FILINFO *)&(mydi->fno);

static void myfatfs_iclose( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);

// free descriptor memory
c_free( (void *)di );
}

static uint32_t myfatfs_isize( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);

return fno->fsize;
}

static sint32_t myfatfs_time( const struct vfs_item *di, struct vfs_time *tm )
{
GET_FILINFO_FNO(di);
// fill in supported stat entries
c_strncpy( buf->name, fno->fname, FS_OBJ_NAME_LEN+1 );
buf->name[FS_OBJ_NAME_LEN] = '\0';
buf->size = fno->fsize;
buf->is_dir = fno->fattrib & AM_DIR ? 1 : 0;
buf->is_rdonly = fno->fattrib & AM_RDO ? 1 : 0;
buf->is_hidden = fno->fattrib & AM_HID ? 1 : 0;
buf->is_sys = fno->fattrib & AM_SYS ? 1 : 0;
buf->is_arch = fno->fattrib & AM_ARC ? 1 : 0;

struct vfs_time *tm = &(buf->tm);
tm->year = (fno->fdate >> 9) + 1980;
tm->mon = (fno->fdate >> 5) & 0x0f;
tm->day = fno->fdate & 0x1f;
tm->hour = (fno->ftime >> 11);
tm->min = (fno->ftime >> 5) & 0x3f;
tm->sec = fno->ftime & 0x3f;

return VFS_RES_OK;
buf->tm_valid = 1;
}

static const char *myfatfs_name( const struct vfs_item *di )
static sint32_t myfatfs_readdir( const struct vfs_dir *dd, struct vfs_stat *buf )
{
GET_FILINFO_FNO(di);

return fno->fname;
}

static sint32_t myfatfs_is_dir( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);

return fno->fattrib & AM_DIR ? 1 : 0;
}

static sint32_t myfatfs_is_rdonly( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);

return fno->fattrib & AM_RDO ? 1 : 0;
}

static sint32_t myfatfs_is_hidden( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);

return fno->fattrib & AM_HID ? 1 : 0;
}

static sint32_t myfatfs_is_sys( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);
GET_DIR_DP(dd);
FILINFO fno;

return fno->fattrib & AM_SYS ? 1 : 0;
}
if (FR_OK == (last_result = f_readdir( dp, &fno ))) {
// condition "no further item" is signalled with empty name
if (fno.fname[0] != '\0') {
myfatfs_fill_stat( &fno, buf );

static sint32_t myfatfs_is_arch( const struct vfs_item *di )
{
GET_FILINFO_FNO(di);
return VFS_RES_OK;
}
}

return fno->fattrib & AM_ARC ? 1 : 0;
return VFS_RES_ERR;
}


Expand Down Expand Up @@ -521,21 +434,17 @@ static vfs_dir *myfatfs_opendir( const char *name )
return NULL;
}

static vfs_item *myfatfs_stat( const char *name )
static sint32_t myfatfs_stat( const char *name, struct vfs_stat *buf )
{
struct myvfs_item *di;
FILINFO fno;

if (di = c_malloc( sizeof( struct myvfs_item ) )) {
if (FR_OK == (last_result = f_stat( name, &(di->fno) ))) {
di->vfs_item.fs_type = VFS_FS_FATFS;
di->vfs_item.fns = &myfatfs_item_fns;
return (vfs_item *)di;
} else {
c_free( di );
}
}
if (FR_OK == (last_result = f_stat( name, &fno ))) {
myfatfs_fill_stat( &fno, buf );

return NULL;
return VFS_RES_OK;
} else {
return VFS_RES_ERR;
}
}

static sint32_t myfatfs_remove( const char *name )
Expand Down
50 changes: 21 additions & 29 deletions app/modules/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,13 @@ static int file_open( lua_State* L )
static int file_list( lua_State* L )
{
vfs_dir *dir;
vfs_item *item;

if (dir = vfs_opendir("")) {
lua_newtable( L );
while (item = vfs_readdir(dir)) {
lua_pushinteger(L, vfs_item_size(item));
lua_setfield(L, -2, vfs_item_name(item));
vfs_closeitem(item);
struct vfs_stat stat;
while (vfs_readdir(dir, &stat) == VFS_RES_OK) {
lua_pushinteger(L, stat.size);
lua_setfield(L, -2, stat.name);
}
vfs_closedir(dir);
return 1;
Expand Down Expand Up @@ -270,11 +269,8 @@ static int file_exists( lua_State* L )
const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");

vfs_item *stat = vfs_stat((char *)fname);

lua_pushboolean(L, stat ? 1 : 0);

if (stat) vfs_closeitem(stat);
struct vfs_stat stat;
lua_pushboolean(L, vfs_stat((char *)fname, &stat) == VFS_RES_OK ? 1 : 0);

return 1;
}
Expand Down Expand Up @@ -332,58 +328,54 @@ static int file_stat( lua_State* L )
const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck( L, c_strlen(fname) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid" );

vfs_item *stat = vfs_stat( (char *)fname );

if (!stat) {
struct vfs_stat stat;
if (vfs_stat( (char *)fname, &stat ) != VFS_RES_OK) {
lua_pushnil( L );
return 1;
}

lua_createtable( L, 0, 7 );

lua_pushinteger( L, vfs_item_size( stat ) );
lua_pushinteger( L, stat.size );
lua_setfield( L, -2, "size" );

lua_pushstring( L, vfs_item_name( stat ) );
lua_pushstring( L, stat.name );
lua_setfield( L, -2, "name" );

lua_pushboolean( L, vfs_item_is_dir( stat ) );
lua_pushboolean( L, stat.is_dir );
lua_setfield( L, -2, "is_dir" );

lua_pushboolean( L, vfs_item_is_rdonly( stat ) );
lua_pushboolean( L, stat.is_rdonly );
lua_setfield( L, -2, "is_rdonly" );

lua_pushboolean( L, vfs_item_is_hidden( stat ) );
lua_pushboolean( L, stat.is_hidden );
lua_setfield( L, -2, "is_hidden" );

lua_pushboolean( L, vfs_item_is_sys( stat ) );
lua_pushboolean( L, stat.is_sys );
lua_setfield( L, -2, "is_sys" );

lua_pushboolean( L, vfs_item_is_arch( stat ) );
lua_pushboolean( L, stat.is_arch );
lua_setfield( L, -2, "is_arch" );

// time stamp as sub-table
vfs_time tm;
int got_time = VFS_RES_OK == vfs_item_time( stat, &tm ) ? TRUE : FALSE;

lua_createtable( L, 0, 6 );

lua_pushinteger( L, got_time ? tm.year : FILE_TIMEDEF_YEAR );
lua_pushinteger( L, stat.tm_valid ? stat.tm.year : FILE_TIMEDEF_YEAR );
lua_setfield( L, -2, "year" );

lua_pushinteger( L, got_time ? tm.mon : FILE_TIMEDEF_MON );
lua_pushinteger( L, stat.tm_valid ? stat.tm.mon : FILE_TIMEDEF_MON );
lua_setfield( L, -2, "mon" );

lua_pushinteger( L, got_time ? tm.day : FILE_TIMEDEF_DAY );
lua_pushinteger( L, stat.tm_valid ? stat.tm.day : FILE_TIMEDEF_DAY );
lua_setfield( L, -2, "day" );

lua_pushinteger( L, got_time ? tm.hour : FILE_TIMEDEF_HOUR );
lua_pushinteger( L, stat.tm_valid ? stat.tm.hour : FILE_TIMEDEF_HOUR );
lua_setfield( L, -2, "hour" );

lua_pushinteger( L, got_time ? tm.min : FILE_TIMEDEF_MIN );
lua_pushinteger( L, stat.tm_valid ? stat.tm.min : FILE_TIMEDEF_MIN );
lua_setfield( L, -2, "min" );

lua_pushinteger( L, got_time ? tm.sec : FILE_TIMEDEF_SEC );
lua_pushinteger( L, stat.tm_valid ? stat.tm.sec : FILE_TIMEDEF_SEC );
lua_setfield( L, -2, "sec" );

lua_setfield( L, -2, "time" );
Expand Down
8 changes: 4 additions & 4 deletions app/platform/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,27 +139,27 @@ vfs_dir *vfs_opendir( const char *name )
return NULL;
}

vfs_item *vfs_stat( const char *name )
sint32_t vfs_stat( const char *name, struct vfs_stat *buf )
{
vfs_fs_fns *fs_fns;
const char *normname = normalize_path( name );
char *outname;

#ifdef BUILD_SPIFFS
if (fs_fns = myspiffs_realm( normname, &outname, FALSE )) {
return fs_fns->stat( outname );
return fs_fns->stat( outname, buf );
}
#endif

#ifdef BUILD_FATFS
if (fs_fns = myfatfs_realm( normname, &outname, FALSE )) {
vfs_item *r = fs_fns->stat( outname );
sint32_t r = fs_fns->stat( outname, buf );
c_free( outname );
return r;
}
#endif

return NULL;
return VFS_RES_ERR;
}

sint32_t vfs_remove( const char *name )
Expand Down
Loading

0 comments on commit fc887e9

Please sign in to comment.