Added statvfs API to get storage statistics

The API is as per posix standard, but does not provide stats for file/directory.
Stats buffer (block size, total block count, free block count) is filled for
entire mounted filesystem.
pull/5768/head
Deepika 2017-12-28 16:38:20 -06:00
parent 9cce4d2b06
commit 7a90be0ce1
10 changed files with 114 additions and 9 deletions

View File

@ -51,6 +51,11 @@ int FileSystem::mkdir(const char *path, mode_t mode)
return -ENOSYS;
}
int FileSystem::statvfs(const char *path, struct statvfs *buf)
{
return -ENOSYS;
}
int FileSystem::file_sync(fs_file_t file)
{
return 0;

View File

@ -109,6 +109,14 @@ public:
*/
virtual int mkdir(const char *path, mode_t mode);
/** Store information about the mounted filesystem in a statvfs structure
*
* @param path The name of the file to find information about
* @param buf The stat buffer to write to
* @return 0 on success, negative error code on failure
*/
virtual int statvfs(const char *path, struct statvfs *buf);
protected:
friend class File;
friend class Dir;

View File

@ -442,6 +442,34 @@ int FATFileSystem::stat(const char *path, struct stat *st) {
return 0;
}
int FATFileSystem::statvfs(const char *path, struct statvfs *buf) {
memset(buf, 0, sizeof(struct statvfs));
FATFS *fs;
DWORD fre_clust;
lock();
FRESULT res = f_getfree(_fsid, &fre_clust, &fs);
if (res != FR_OK) {
unlock();
return fat_error_remap(res);
}
buf->f_bsize = fs->ssize;
buf->f_frsize = fs->ssize;
buf->f_blocks = (fs->n_fatent - 2) * fs->csize;
buf->f_bfree = fre_clust * fs->csize;
buf->f_bavail = buf->f_bfree;
#if FF_USE_LFN
buf->f_namemax = FF_LFN_BUF;
#else
buf->f_namemax = FF_SFN_BUF;
#endif
unlock();
return 0;
}
void FATFileSystem::lock() {
_ffs_mutex->lock();
}

View File

@ -139,6 +139,14 @@ public:
*/
virtual int mkdir(const char *path, mode_t mode);
/** Store information about the mounted filesystem in a statvfs structure
*
* @param path The name of the file to find information about
* @param buf The stat buffer to write to
* @return 0 on success, negative error code on failure
*/
virtual int statvfs(const char *path, struct statvfs *buf);
protected:
/** Open a file on the filesystem
*

View File

@ -336,6 +336,9 @@ int LittleFileSystem::stat(const char *name, struct stat *st)
return lfs_toerror(err);
}
int LittleFileSystem::statvfs(const char *path, struct statvfs *buf)
{
}
////// File operations //////
int LittleFileSystem::file_open(fs_file_t *file, const char *path, int flags)

View File

@ -143,6 +143,14 @@ public:
*/
virtual int mkdir(const char *path, mode_t mode);
/** Store information about the mounted filesystem in a statvfs structure
*
* @param path The name of the file to find information about
* @param buf The stat buffer to write to
* @return 0 on success, negative error code on failure
*/
virtual int statvfs(const char *path, struct statvfs *buf);
protected:
/** Open a file on the filesystem
*

View File

@ -42,3 +42,8 @@ int FileSystemHandle::mkdir(const char *path, mode_t mode)
{
return -ENOSYS;
}
int FileSystemHandle::statvfs(const char *path, struct statvfs *buf)
{
return -ENOSYS;
}

View File

@ -94,6 +94,14 @@ public:
* @return 0 on success, negative error code on failure
*/
virtual int mkdir(const char *path, mode_t mode);
/** Store information about the mounted filesystem in a statvfs structure
*
* @param path The name of the file to find information about
* @param buf The stat buffer to write to
* @return 0 on success, negative error code on failure
*/
virtual int statvfs(const char *path, struct statvfs *buf);
};
/**@}*/

View File

@ -709,6 +709,23 @@ extern "C" int stat(const char *path, struct stat *st) {
}
}
extern "C" int statvfs(const char *path, struct statvfs *buf) {
FilePath fp(path);
FileSystemHandle *fs = fp.fileSystem();
if (fs == NULL) {
errno = ENODEV;
return -1;
}
int err = fs->statvfs(fp.fileName(), buf);
if (err < 0) {
errno = -err;
return -1;
} else {
return 0;
}
}
#if defined(TOOLCHAIN_GCC)
/* prevents the exception handling name demangling code getting pulled in */
#include "mbed_error.h"

View File

@ -28,8 +28,8 @@
/* We can get the following standard types from sys/types for gcc, but we
* need to define the types ourselves for the other compilers that normally
* target embedded systems */
typedef signed int ssize_t; ///< Signed size type, usually encodes negative errors
typedef signed long off_t; ///< Offset in a data stream
typedef signed int ssize_t; ///< Signed size type, usually encodes negative errors
typedef signed long off_t; ///< Offset in a data stream
#if defined(__ARMCC_VERSION) || !defined(__GNUC__)
typedef unsigned int mode_t; ///< Mode for opening files
typedef unsigned int dev_t; ///< Device ID type
@ -37,6 +37,7 @@ typedef unsigned long ino_t; ///< File serial number
typedef unsigned int nlink_t; ///< Number of links to a file
typedef unsigned int uid_t; ///< User ID
typedef unsigned int gid_t; ///< Group ID
typedef unsigned long long fsblkcnt_t; ///< Count of file system blocks
#endif
#define O_RDONLY 0 ///< Open for reading
@ -415,10 +416,24 @@ struct stat {
time_t st_ctime; ///< Time of last status change
};
struct statvfs {
unsigned long f_bsize; ///< Filesystem block size
unsigned long f_frsize; ///< Fragment size (block size)
fsblkcnt_t f_blocks; ///< Number of blocks
fsblkcnt_t f_bfree; ///< Number of free blocks
fsblkcnt_t f_bavail; ///< Number of free blocks for unprivileged users
unsigned long f_fsid; ///< Filesystem ID
unsigned long f_namemax; ///< Maximum filename length
};
#if __cplusplus
extern "C" {
#endif
int stat(const char *path, struct stat *st);
int statvfs(const char *path, struct statvfs *buf);
#if __cplusplus
};
#endif