Skip to content

Commit

Permalink
Update based on review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Barry Xu <[email protected]>
  • Loading branch information
Barry-Xu-2018 committed Nov 16, 2020
1 parent f517865 commit 767fd78
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 109 deletions.
22 changes: 15 additions & 7 deletions include/rcutils/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ extern "C"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifndef _WIN32
#include <sys/types.h>
#else
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif

#include "rcutils/allocator.h"
#include "rcutils/macros.h"
Expand Down Expand Up @@ -191,16 +197,17 @@ rcutils_mkdir(const char * abs_path);
* \note This operation is not recursive.
* \param[in] directory_path The directory path to calculate the size of.
* \param[in] allocator Allocator being used for internal file path composition.
* \return The size of the directory in bytes.
* \return The size of the directory in bytes on success.
* \return -1 on failure.
*/
RCUTILS_PUBLIC
size_t
ssize_t
rcutils_calculate_directory_size(const char * directory_path, rcutils_allocator_t allocator);

/// Calculate the size of the specified directory with recursive directory.
/// Calculate the size of the specified directory with recursion.
/**
* Calculates the size of a directory and subdirectory by summarizing the file size of all files.
* If necessary, you can specify maximum directory depth for calcation.
* If necessary, you can specify the maximum directory depth to recurse into.
* Depth definition as below.
* \code
* directory_path <= depth 1
Expand All @@ -213,13 +220,14 @@ rcutils_calculate_directory_size(const char * directory_path, rcutils_allocator_
* \param[in] directory_path The directory path to calculate the size of.
* \param[in] max_depth The maximum depth of subdirectory. 0 means no limitation.
* \param[in] allocator Allocator being used for internal file path composition.
* \return The size of the directory in bytes.
* \return The size of the directory in bytes on success.
* \return -1 on failure.
*/
RCUTILS_PUBLIC
size_t
ssize_t
rcutils_calculate_directory_size_with_recursion(
const char * directory_path,
const uint32_t max_depth,
const size_t max_depth,
rcutils_allocator_t allocator);

/// Calculate the size of the specifed file.
Expand Down
184 changes: 88 additions & 96 deletions src/filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,17 +238,9 @@ rcutils_mkdir(const char * abs_path)
return success;
}

size_t
ssize_t
rcutils_calculate_directory_size(const char * directory_path, rcutils_allocator_t allocator)
{
size_t dir_size = 0;

if (!rcutils_is_directory(directory_path)) {
RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(
"Path is not a directory: %s\n", directory_path);
return dir_size;
}

return rcutils_calculate_directory_size_with_recursion(directory_path, 1, allocator);
}

Expand All @@ -270,101 +262,130 @@ static inline void free_dir_list(dir_list_t * dir_list, rcutils_allocator_t allo
} while (dir_list);
}

size_t
static inline void remove_first_dir_from_list(dir_list_t ** dir_list, rcutils_allocator_t allocator)
{
dir_list_t * next_dir = (*dir_list)->next;
allocator.deallocate((*dir_list)->path, allocator.state);
allocator.deallocate(*dir_list, allocator.state);
*dir_list = next_dir;
}

static inline bool check_and_calculate_size(
const char * filename,
ssize_t * dir_size,
const size_t max_depth,
dir_list_t * dir_list,
rcutils_allocator_t allocator)
{
// Skip over local folder handle (`.`) and parent folder (`..`)
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) {
return true;
}

char * file_path = rcutils_join_path(dir_list->path, filename, allocator);
if (NULL == file_path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("rcutils_join_path return NULL !\n");
return false;
}

if (rcutils_is_directory(file_path)) {
if ((max_depth == 0) || ((dir_list->depth + 1) <= max_depth)) {
// Add new directory to dir_list
dir_list_t * found_new_dir =
allocator.allocate(sizeof(dir_list_t), allocator.state);
if (NULL == found_new_dir) {
RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(
"Failed to allocate memory for path %s !\n", file_path);
return false;
}
found_new_dir->path = file_path;
found_new_dir->depth = dir_list->depth + 1;
found_new_dir->next = dir_list->next;
dir_list->next = found_new_dir;
}
} else {
*dir_size += rcutils_get_file_size(file_path);
allocator.deallocate(file_path, allocator.state);
}

return true;
}

ssize_t
rcutils_calculate_directory_size_with_recursion(
const char * directory_path,
const uint32_t max_deepth,
const size_t max_depth,
rcutils_allocator_t allocator)
{
dir_list_t * dir_list = NULL;
size_t dir_size = 0;
ssize_t dir_size = 0;

if (!rcutils_is_directory(directory_path)) {
RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(
"Path is not a directory: %s\n", directory_path);
return -1;
}

dir_list = (dir_list_t *) allocator.allocate(sizeof(dir_list_t), allocator.state);
dir_list = allocator.zero_allocate(1, sizeof(dir_list_t), allocator.state);
if (NULL == dir_list) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to allocate memory !\n");
return 0;
return -1;
}

#ifdef _WIN32
HANDLE handle = INVALID_HANDLE_VALUE;

dir_list->next = NULL;
dir_list->depth = 1;
dir_list->path = rcutils_join_path(directory_path, "*", allocator);

dir_list->path = rcutils_strdup(directory_path, allocator);
if (NULL == dir_list->path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to duplicate directory path !\n");
goto fail;
return -1;
}

#ifdef _WIN32
HANDLE handle = INVALID_HANDLE_VALUE;
char * dir_path = NULL;

do {
dir_path = rcutils_join_path(dir_list->path, "*", allocator);
if (NULL == dir_path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to duplicate directory path !\n");
goto fail;
}

WIN32_FIND_DATA data;
handle = FindFirstFile(dir_list->path, &data);
handle = FindFirstFile(dir_path, &data);
if (INVALID_HANDLE_VALUE == handle) {
RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(
"Can't open directory %s. Error code: %lu\n", dir_list->path, GetLastError());
goto fail;
}

do {
// Skip over local folder handle (`.`) and parent folder (`..`)
if (strcmp(data.cFileName, ".") != 0 && strcmp(data.cFileName, "..") != 0) {
char * file_path = rcutils_join_path(dir_list->path, data.cFileName, allocator);
if (NULL == file_path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("rcutils_join_path return NULL !\n");
goto fail;
}

if (rcutils_is_directory(file_path)) {
if ((max_deepth == 0) || ((dir_list->depth + 1) <= max_deepth)) {
// Add new directory to dir_list
dir_list_t * found_new_dir =
(dir_list_t *) allocator.allocate(sizeof(dir_list_t), allocator.state);
if (NULL == found_new_dir) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to allocate memory !\n");
goto fail;
}

found_new_dir->path = file_path;
found_new_dir->depth = dir_list->depth + 1;
found_new_dir->next = dir_list->next;

dir_list->next = found_new_dir;
}
} else {
dir_size += rcutils_get_file_size(file_path);
allocator.deallocate(file_path, allocator.state);
}
if (!check_and_calculate_size(data.cFileName, &dir_size, max_depth, dir_list, allocator)) {
goto fail;
}
} while (FindNextFile(handle, &data));

FindClose(handle);
allocator.deallocate(dir_path, allocator.state);

dir_list_t * next_dir = dir_list->next;
allocator.deallocate(dir_list->path, allocator.state);
allocator.deallocate(dir_list, allocator.state);
dir_list = next_dir;
remove_first_dir_from_list(&dir_list, allocator);
} while (dir_list);

return dir_size;

fail:
if (NULL != dir_path) {
allocator.deallocate(dir_path, allocator.state);
}

if (INVALID_HANDLE_VALUE != handle) {
FindClose(handle);
}
free_dir_list(dir_list, allocator);
return dir_size;
return -1;
#else
DIR * dir = NULL;

dir_list->next = NULL;
dir_list->depth = 1;
dir_list->path = rcutils_strdup(directory_path, allocator);

if (NULL == dir_list->path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to duplicate directory path !\n");
goto fail;
}

struct dirent * entry;
do {
dir = opendir(dir_list->path);
Expand All @@ -378,43 +399,14 @@ rcutils_calculate_directory_size_with_recursion(
// If found directory, add to dir_list
// If found file, calculate file size
while (NULL != (entry = readdir(dir))) {
// Skip over local folder handle (`.`) and parent folder (`..`)
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
char * file_path = rcutils_join_path(dir_list->path, entry->d_name, allocator);
if (NULL == file_path) {
RCUTILS_SAFE_FWRITE_TO_STDERR("rcutils_join_path return NULL !\n");
goto fail;
}

if (rcutils_is_directory(file_path)) {
if ((max_deepth == 0) || ((dir_list->depth + 1) <= max_deepth)) {
// Add new directory to dir_list
dir_list_t * found_new_dir =
(dir_list_t *) allocator.allocate(sizeof(dir_list_t), allocator.state);
if (NULL == found_new_dir) {
RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to allocate memory !\n");
goto fail;
}

found_new_dir->path = file_path;
found_new_dir->depth = dir_list->depth + 1;
found_new_dir->next = dir_list->next;

dir_list->next = found_new_dir;
}
} else {
dir_size += rcutils_get_file_size(file_path);
allocator.deallocate(file_path, allocator.state);
}
if (!check_and_calculate_size(entry->d_name, &dir_size, max_depth, dir_list, allocator)) {
goto fail;
}
}

closedir(dir);

dir_list_t * next_dir = dir_list->next;
allocator.deallocate(dir_list->path, allocator.state);
allocator.deallocate(dir_list, allocator.state);
dir_list = next_dir;
remove_first_dir_from_list(&dir_list, allocator);
} while (dir_list);

return dir_size;
Expand All @@ -424,7 +416,7 @@ rcutils_calculate_directory_size_with_recursion(
closedir(dir);
}
free_dir_list(dir_list, allocator);
return dir_size;
return -1;
#endif
}

Expand Down
12 changes: 6 additions & 6 deletions test/test_filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ TEST_F(TestFilesystemFixture, calculate_directory_size) {
char * path =
rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
ASSERT_NE(nullptr, path);
size_t size = rcutils_calculate_directory_size(path, g_allocator);
ssize_t size = rcutils_calculate_directory_size(path, g_allocator);
#ifdef WIN32
// Due to different line breaks on windows, we have one more byte in the file.
// See https://github.com/ros2/rcutils/issues/198
Expand All @@ -443,7 +443,7 @@ TEST_F(TestFilesystemFixture, calculate_directory_size) {
char * non_existing_path = rcutils_join_path(this->test_path, "non_existing_folder", g_allocator);
ASSERT_NE(nullptr, non_existing_path);
size = rcutils_calculate_directory_size(non_existing_path, g_allocator);
EXPECT_EQ(0u, size);
EXPECT_EQ(-1, size);
g_allocator.deallocate(non_existing_path, g_allocator.state);

{
Expand All @@ -452,7 +452,7 @@ TEST_F(TestFilesystemFixture, calculate_directory_size) {
fs.file_info(path).st_mode |= mocking_utils::filesystem::file_types::DIRECTORY;
fs.exhaust_file_descriptors();
size = rcutils_calculate_directory_size(path, g_allocator);
EXPECT_EQ(0u, size);
EXPECT_EQ(-1, size);
}
}

Expand All @@ -461,7 +461,7 @@ TEST_F(TestFilesystemFixture, rcutils_calculate_directory_size_with_recursion) {
rcutils_join_path(this->test_path, "dummy_folder_with_subdir", g_allocator);
ASSERT_NE(nullptr, path);
// Check depth is 2
size_t size = rcutils_calculate_directory_size_with_recursion(path, 2, g_allocator);
ssize_t size = rcutils_calculate_directory_size_with_recursion(path, 2, g_allocator);
#ifdef WIN32
// Due to different line breaks on windows, we have one more byte in the file.
// See https://github.com/ros2/rcutils/issues/198
Expand All @@ -484,7 +484,7 @@ TEST_F(TestFilesystemFixture, rcutils_calculate_directory_size_with_recursion) {
char * non_existing_path = rcutils_join_path(this->test_path, "non_existing_folder", g_allocator);
ASSERT_NE(nullptr, non_existing_path);
size = rcutils_calculate_directory_size_with_recursion(non_existing_path, 0, g_allocator);
EXPECT_EQ(0u, size);
EXPECT_EQ(-1, size);
g_allocator.deallocate(non_existing_path, g_allocator.state);

{
Expand All @@ -493,7 +493,7 @@ TEST_F(TestFilesystemFixture, rcutils_calculate_directory_size_with_recursion) {
fs.file_info(path).st_mode |= mocking_utils::filesystem::file_types::DIRECTORY;
fs.exhaust_file_descriptors();
size = rcutils_calculate_directory_size_with_recursion(path, 0, g_allocator);
EXPECT_EQ(0u, size);
EXPECT_EQ(-1, size);
}
}

Expand Down

0 comments on commit 767fd78

Please sign in to comment.