Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #573, add OS_FileSysStatVolume #717

Merged
merged 1 commit into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/os/inc/osapi-filesys.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ typedef struct
uint32 FreeVolumes; /**< @brief Total number of volumes free */
} os_fsinfo_t;

/*
* @brief The data type filled in by the OS_FileSysStatVolume() call.
*
* Encapsulates detail information about the size and available space
* in a mounted file system volume.
*/
typedef struct
{
size_t block_size; /**< Block size of underlying FS */
osal_blockcount_t total_blocks; /**< Total blocks in underlying FS */
osal_blockcount_t blocks_free; /**< Available blocks in underlying FS */
} OS_statvfs_t;

/*
* Exported Functions
*/
Expand Down Expand Up @@ -201,6 +214,30 @@ int32 OS_fsBlocksFree(const char *name);
*/
int32 OS_fsBytesFree(const char *name, uint64 *bytes_free);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Obtains information about size and free space in a volume
*
* Populates the supplied OS_statvfs_t structure, which includes
* the block size and total/free blocks in a file system volume.
*
* This replaces two older OSAL calls:
*
* OS_fsBlocksFree() is determined by reading the blocks_free
* output struct member
* OS_fsBytesFree() is determined by multiplying blocks_free
* by the block_size member
*
* @param[in] name The device/path to operate on
* @param[out] statbuf Output structure to populate
*
* @return Execution status, see @ref OSReturnCodes
* @retval #OS_SUCCESS @copybrief OS_SUCCESS
* @retval #OS_INVALID_POINTER if name or statbuf is NULL
* @retval #OS_ERROR if the OS call failed
*/
int32 OS_FileSysStatVolume(const char *name, OS_statvfs_t *statbuf);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Checks the health of a file system and repairs it if necessary
Expand Down
16 changes: 0 additions & 16 deletions src/os/shared/inc/os-shared-filesys.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,6 @@ enum
OS_FILESYS_TYPE_MAX
};

/*
* The data type filled in by the "statvfs" call.
*
* This is defined here since there is no public API to get this info,
* only the total bytes free is accessible via the current OSAL API.
*
* However, returning the detailed info at this level means that the
* more detailed information could be made available with a new API call.
*/
typedef struct
{
size_t block_size;
osal_blockcount_t total_blocks;
osal_blockcount_t blocks_free;
} OS_statvfs_t;

typedef struct
{
char device_name[OS_FS_DEV_NAME_LEN]; /**< The name of the underlying block device, if applicable */
Expand Down
31 changes: 31 additions & 0 deletions src/os/shared/src/osapi-filesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,37 @@ int32 OS_fsBytesFree(const char *name, uint64 *bytes_free)

} /* end OS_fsBytesFree */

/*----------------------------------------------------------------
*
* Function: OS_FileSysStatVolume
*
* Purpose: Implemented per public OSAL API
* See description in API and header file for detail
*
*-----------------------------------------------------------------*/
int32 OS_FileSysStatVolume(const char *name, OS_statvfs_t *statbuf)
{
int32 return_code;
OS_object_token_t token;

/* Check parameters */
OS_CHECK_PATHNAME(name);
OS_CHECK_POINTER(statbuf);

return_code = OS_ObjectIdGetBySearch(OS_LOCK_MODE_GLOBAL, LOCAL_OBJID_TYPE, OS_FileSys_FindVirtMountPoint,
(void *)name, &token);

if (return_code == OS_SUCCESS)
{
return_code = OS_FileSysStatVolume_Impl(&token, statbuf);

OS_ObjectIdRelease(&token);
}

return return_code;

} /* end OS_FileSysStatVolume */

/*----------------------------------------------------------------
*
* Function: OS_chkfs
Expand Down
40 changes: 22 additions & 18 deletions src/tests/file-api-test/file-api-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -424,18 +424,19 @@ void TestReadWriteLseek(void)
---------------------------------------------------------------------------------------*/
void TestMkRmDirFreeBytes(void)
{
int32 status;
char filename1[OS_MAX_PATH_LEN];
char filename2[OS_MAX_PATH_LEN];
char dir1[OS_MAX_PATH_LEN];
char dir2[OS_MAX_PATH_LEN];
char buffer1[OS_MAX_PATH_LEN];
char buffer2[OS_MAX_PATH_LEN];
char copybuffer1[OS_MAX_PATH_LEN];
char copybuffer2[OS_MAX_PATH_LEN];
osal_id_t fd1;
osal_id_t fd2;
size_t size;
int32 status;
char filename1[OS_MAX_PATH_LEN];
char filename2[OS_MAX_PATH_LEN];
char dir1[OS_MAX_PATH_LEN];
char dir2[OS_MAX_PATH_LEN];
char buffer1[OS_MAX_PATH_LEN];
char buffer2[OS_MAX_PATH_LEN];
char copybuffer1[OS_MAX_PATH_LEN];
char copybuffer2[OS_MAX_PATH_LEN];
osal_id_t fd1;
osal_id_t fd2;
size_t size;
OS_statvfs_t statbuf;

/* make the directory names for testing, as well as the filenames and the buffers
* to put in the files */
Expand All @@ -450,8 +451,9 @@ void TestMkRmDirFreeBytes(void)

/* NOTE: The blocks free call is not necessarily implemented on all filesystems.
* So the response of OS_ERR_NOT_IMPLEMENTED is acceptable. */
status = OS_fsBlocksFree("/drive0");
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status >= OS_SUCCESS, "Checking Free Blocks: %d", (int)status);
status = OS_FileSysStatVolume("/drive0", &statbuf);
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status == OS_SUCCESS, "Checking Free Blocks: status=%d blocks=%lu",
(int)status, (unsigned long)statbuf.blocks_free);

/* make the two directories */
status = OS_mkdir(dir1, 0);
Expand Down Expand Up @@ -486,8 +488,9 @@ void TestMkRmDirFreeBytes(void)

memset(buffer1, 0, sizeof(buffer1));
memset(buffer2, 0, sizeof(buffer2));
status = OS_fsBlocksFree("/drive0");
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status >= OS_SUCCESS, "Checking Free Blocks: %d", (int)status);
status = OS_FileSysStatVolume("/drive0", &statbuf);
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status == OS_SUCCESS, "Checking Free Blocks: status=%d blocks=%lu",
(int)status, (unsigned long)statbuf.blocks_free);

/* read back out of the files what we wrote into them */
size = strlen(copybuffer1);
Expand Down Expand Up @@ -526,8 +529,9 @@ void TestMkRmDirFreeBytes(void)
status = OS_rmdir(dir2);
UtAssert_True(status == OS_SUCCESS, "status after rmdir 2 = %d", (int)status);

status = OS_fsBlocksFree("/drive0");
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status >= OS_SUCCESS, "Checking Free Blocks: %d", (int)status);
status = OS_FileSysStatVolume("/drive0", &statbuf);
UtAssert_True(status == OS_ERR_NOT_IMPLEMENTED || status == OS_SUCCESS, "Checking Free Blocks: status=%d blocks=%lu",
(int)status, (unsigned long)statbuf.blocks_free);
}

/*---------------------------------------------------------------------------------------
Expand Down
52 changes: 52 additions & 0 deletions src/unit-test-coverage/shared/src/coveragetest-filesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,57 @@ void Test_OS_fsBytesFree(void)
UtAssert_True(actual == expected, "OS_fsBytesFree() (%ld) == OS_FS_ERR_PATH_INVALID", (long)actual);
}

void Test_OS_FileSysStatVolume(void)
{
/*
* Test Case For:
* int32 OS_FileSysStatVolume(const char *name, OS_statvfs_t *statbuf)
*/

OS_statvfs_t statbuf;
OS_statvfs_t statref;
int32 expected;
int32 actual;

statref.block_size = OSAL_SIZE_C(1024);
statref.blocks_free = OSAL_BLOCKCOUNT_C(1111);
statref.total_blocks = OSAL_BLOCKCOUNT_C(2222);
UT_SetDataBuffer(UT_KEY(OS_FileSysStatVolume_Impl), &statref, sizeof(statref), false);
OS_filesys_table[1].flags = OS_FILESYS_FLAG_IS_READY | OS_FILESYS_FLAG_IS_MOUNTED_SYSTEM |
OS_FILESYS_FLAG_IS_MOUNTED_VIRTUAL;

expected = OS_SUCCESS;
actual = OS_FileSysStatVolume("/cf", &statbuf);
UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_SUCCESS", (long)actual);

UtAssert_True(statbuf.block_size == statref.block_size, "blocks_size (%lu) == %lu", (unsigned long)statbuf.block_size,
(unsigned long)statref.block_size);
UtAssert_True(statbuf.total_blocks == statref.total_blocks, "total_blocks (%lu) == %lu",
(unsigned long)statbuf.total_blocks, (unsigned long)statref.total_blocks);
UtAssert_True(statbuf.blocks_free == statref.blocks_free, "blocks_free (%lu) == %lu", (unsigned long)statbuf.blocks_free,
(unsigned long)statref.blocks_free);

/* validate error checking */
expected = OS_INVALID_POINTER;
actual = OS_FileSysStatVolume(NULL, &statbuf);
UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_INVALID_POINTER", (long)actual);
actual = OS_FileSysStatVolume("/cf", NULL);
UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_INVALID_POINTER", (long)actual);

/* Test Fail due to no matching VolTab entry */
UT_SetDefaultReturnValue(UT_KEY(OS_ObjectIdGetBySearch), OS_ERR_NAME_NOT_FOUND);
expected = OS_ERR_NAME_NOT_FOUND;
actual = OS_FileSysStatVolume("/cf", &statbuf);
UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_ERR_NAME_NOT_FOUND", (long)actual);
UT_ResetState(UT_KEY(OS_ObjectIdGetBySearch));

/* Verify pass through of impl error */
UT_SetDefaultReturnValue(UT_KEY(OS_FileSysStatVolume_Impl), OS_ERR_OPERATION_NOT_SUPPORTED);
expected = OS_ERR_OPERATION_NOT_SUPPORTED;
actual = OS_FileSysStatVolume("/cf", &statbuf);
UtAssert_True(actual == expected, "OS_FileSysStatVolume() (%ld) == OS_ERR_OPERATION_NOT_SUPPORTED", (long)actual);
}

void Test_OS_chkfs(void)
{
/*
Expand Down Expand Up @@ -577,4 +628,5 @@ void UtTest_Setup(void)
ADD_TEST(OS_GetFsInfo);
ADD_TEST(OS_TranslatePath);
ADD_TEST(OS_FileSys_FindVirtMountPoint);
ADD_TEST(OS_FileSysStatVolume);
}
117 changes: 117 additions & 0 deletions src/unit-tests/osfilesys-test/ut_osfilesys_diskio_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,123 @@ void UT_os_fsbytesfree_test()
return;
}

/*--------------------------------------------------------------------------------*
** Syntax: int32 OS_fsstatvolume(const char *name)
** Purpose: Returns the number of blocks free in a the file system
** Parameters: *name - a pointer to the name of the drive to check for free blocks
** Returns: OS_INVALID_POINTER if the pointer passed in is NULL
** OS_FS_ERR_PATH_TOO_LONG if the path passed in is too long
** OS_ERROR if the OS call failed
** Number of blocks free in a volume if succeeded
** OS_ERR_NOT_IMPLEMENTED if not implemented
** -----------------------------------------------------
** Test #0: Not-implemented condition
** 1) Call this routine
** 2) If the returned value is OS_ERR_NOT_IMPLEMENTED, then exit test
** 3) Otherwise, continue.
** -----------------------------------------------------
** Test #1: Null-pointer-arg condition
** 1) Call this routine with a null pointer as one of the arguments
** 2) Expect the returned value to be
** (a) OS_INVALID_POINTER
** -----------------------------------------------------
** Test #2: Path-too-long-arg condition
** 1) Call this routine with a path name of length greater than Volume table's
** name as argument
** 2) Expect the returned value to be
** (a) OS_FS_ERR_PATH_TOO_LONG
** -----------------------------------------------------
** Test #3: OS-call-failure condition
** 1) Setup the test to cause the OS call to fail inside this routine
** 2) Call this routine
** 3) Expect the returned value to be
** (a) OS_ERROR
** -----------------------------------------------------
** Test#4: Nominal condition
** 1) Make sure no file system has been previously created
** 2) Call OS_mkfs
** 3) Expect the returned value to be
** (a) OS_SUCCESS
** 4) Call OS_mount with device name used in #2
** 5) Expect the returned value to be
** (a) OS_SUCCESS
** 6) Call this routine with mount-point used in #4
** 7) Expect the returned value to be
** (a) greater than or equal to 0
** --------------------------------------------------------------------------------*/
void UT_os_fsstatvolume_test(void)
{
const char * testDesc;
OS_statvfs_t statbuf;

/*-----------------------------------------------------*/
testDesc = "API not implemented";

if (OS_FileSysStatVolume("/cf", &statbuf) == OS_ERR_NOT_IMPLEMENTED)
{
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_NA);
goto UT_os_fsstatvolume_test_exit_tag;
}

/*-----------------------------------------------------*/
testDesc = "#1a Null-pointer-arg";

if (OS_FileSysStatVolume(NULL, &statbuf) == OS_INVALID_POINTER)
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_PASS);
else
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_FAILURE);

/*-----------------------------------------------------*/
testDesc = "#1b Null-pointer-arg";

if (OS_FileSysStatVolume("/cf", NULL) == OS_INVALID_POINTER)
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_PASS);
else
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_FAILURE);

/*-----------------------------------------------------*/
testDesc = "#2 Path-too-long-arg";

if (OS_FileSysStatVolume(g_fsLongName, &statbuf) == OS_FS_ERR_PATH_TOO_LONG)
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_PASS);
else
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_FAILURE);

/*-----------------------------------------------------*/
testDesc = "#3 OS-call-failure";

UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_INFO);

/*-----------------------------------------------------*/
testDesc = "#4 Nominal";

if (OS_mkfs(g_fsAddrPtr, g_devNames[4], g_volNames[4], g_blkSize, g_blkCnt) != OS_SUCCESS)
{
testDesc = "#4 Nominal - File-system-create failed";
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_TSF);
goto UT_os_fsstatvolume_test_exit_tag;
}

if (OS_mount(g_devNames[4], g_mntNames[4]) != OS_SUCCESS)
{
testDesc = "#4 Nominal - File-system-mount failed";
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_TSF);
goto UT_os_fsstatvolume_test_exit_tag;
}

if (OS_FileSysStatVolume(g_mntNames[4], &statbuf) >= 0)
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_PASS);
else
UT_OS_TEST_RESULT(testDesc, UTASSERT_CASETYPE_FAILURE);

/* Reset test environment */
OS_unmount(g_mntNames[4]);
OS_rmfs(g_devNames[4]);

UT_os_fsstatvolume_test_exit_tag:
return;
}

/*================================================================================*
** End of File: ut_osfilesys_diskio_test.c
**================================================================================*/
1 change: 1 addition & 0 deletions src/unit-tests/osfilesys-test/ut_osfilesys_diskio_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ void UT_os_checkfs_test(void);

void UT_os_fsblocksfree_test(void);
void UT_os_fsbytesfree_test(void);
void UT_os_fsstatvolume_test(void);

/*--------------------------------------------------------------------------------*/

Expand Down
1 change: 1 addition & 0 deletions src/unit-tests/osfilesys-test/ut_osfilesys_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void UtTest_Setup(void)
UtTest_Add(UT_os_checkfs_test, NULL, NULL, "OS_chkfs");
UtTest_Add(UT_os_fsblocksfree_test, NULL, NULL, "OS_fsBlocksFree");
UtTest_Add(UT_os_fsbytesfree_test, NULL, NULL, "OS_fsBytesFree");
UtTest_Add(UT_os_fsstatvolume_test, NULL, NULL, "OS_FileSysStatVolume");
}

/*================================================================================*
Expand Down
Loading