Skip to content

Commit

Permalink
Fix nasa#573, add OS_FileSysStatVolume
Browse files Browse the repository at this point in the history
Add OS_FileSysStatVolume as replacement for OS_fsBytesFree and
OS_fsBlocksFree.  Update unit tests and stubs for the new API
call.

Does not (yet) deprecate the existing functions, as references
still need to be updated elsewhere in apps.
  • Loading branch information
jphickey committed Dec 29, 2020
1 parent d698a4d commit b04c4ff
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 34 deletions.
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

0 comments on commit b04c4ff

Please sign in to comment.