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

calculate file and directory size #197

Merged
merged 4 commits into from
Jan 10, 2020
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
21 changes: 21 additions & 0 deletions include/rcutils/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,27 @@ RCUTILS_PUBLIC
bool
rcutils_mkdir(const char * abs_path);

/// Calculate the size of the specified directory.
/*
* Calculates the size of a directory by summarizing the file size of all files.
* \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.
*/
RCUTILS_PUBLIC
size_t
rcutils_calculate_directory_size(const char * directory_path, rcutils_allocator_t allocator);

/// Calculate the size of the specifed file.
/*
* \param[in] file_path The path of the file to obtain its size of.
* \return The size of the file in bytes.
*/
RCUTILS_PUBLIC
size_t
rcutils_get_file_size(const char * file_path);

#ifdef __cplusplus
}
#endif
Expand Down
65 changes: 65 additions & 0 deletions src/filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ extern "C"
#include <string.h>
#include <sys/stat.h>
#ifndef _WIN32
#include <dirent.h>
#include <unistd.h>
#else
#include <windows.h>
#include <direct.h>
#endif // _WIN32

Expand Down Expand Up @@ -210,6 +212,69 @@ rcutils_mkdir(const char * abs_path)
return success;
}

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

if (!rcutils_is_directory(directory_path)) {
fprintf(stderr, "Path is not a directory: %s\n", directory_path);
return dir_size;
}
#ifdef _WIN32
char * path = rcutils_join_path(directory_path, "*", allocator);
WIN32_FIND_DATA data;
HANDLE handle = FindFirstFile(path, &data);
if (INVALID_HANDLE_VALUE == handle) {
fprintf(stderr, "Can't open directory %s. Error code: %lu\n", directory_path, GetLastError());
return dir_size;
}
allocator.deallocate(path, allocator.state);
if (handle != INVALID_HANDLE_VALUE) {
do {
// Skip over local folder handle (`.`) and parent folder (`..`)
if (strcmp(data.cFileName, ".") != 0 && strcmp(data.cFileName, "..") != 0) {
Karsten1987 marked this conversation as resolved.
Show resolved Hide resolved
char * file_path = rcutils_join_path(directory_path, data.cFileName, allocator);
dir_size += rcutils_get_file_size(file_path);
allocator.deallocate(file_path, allocator.state);
}
} while (FindNextFile(handle, &data));
FindClose(handle);
}
return dir_size;
#else
DIR * dir = opendir(directory_path);
if (NULL == dir) {
fprintf(stderr, "Can't open directory %s. Error code: %d\n", directory_path, errno);
return dir_size;
}
struct dirent * entry;
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(directory_path, entry->d_name, allocator);
dir_size += rcutils_get_file_size(file_path);
allocator.deallocate(file_path, allocator.state);
}
}
closedir(dir);
return dir_size;
#endif
}

size_t
rcutils_get_file_size(const char * file_path)
Karsten1987 marked this conversation as resolved.
Show resolved Hide resolved
{
if (!rcutils_is_file(file_path)) {
fprintf(stderr, "Path is not a file: %s\n", file_path);
return 0;
}

struct stat stat_buffer;
int rc = stat(file_path, &stat_buffer);
return rc == 0 ? (size_t)(stat_buffer.st_size) : 0;
}

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions test/dummy_folder/dummy.dummy
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ROS2
1 change: 1 addition & 0 deletions test/dummy_readable_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ROS2
35 changes: 35 additions & 0 deletions test/test_filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,38 @@ TEST_F(TestFilesystemFixture, mkdir) {
ASSERT_FALSE(rcutils_mkdir(path2));
}
}

TEST_F(TestFilesystemFixture, calculate_directory_size) {
char * path =
rcutils_join_path(this->test_path, "dummy_folder", g_allocator);
size_t size = rcutils_calculate_directory_size(path, g_allocator);
ASSERT_EQ(5u, size);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
g_allocator.deallocate(path, g_allocator.state);
});

char * non_existing_path = rcutils_join_path(this->test_path, "non_existing_folder", g_allocator);
size = rcutils_calculate_directory_size(non_existing_path, g_allocator);
ASSERT_EQ(0u, size);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
g_allocator.deallocate(non_existing_path, g_allocator.state);
});
}

TEST_F(TestFilesystemFixture, calculate_file_size) {
char * path =
rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator);
size_t size = rcutils_get_file_size(path);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
g_allocator.deallocate(path, g_allocator.state);
});
ASSERT_EQ(5u, size);

char * non_existing_path =
rcutils_join_path(this->test_path, "non_existing_file.txt", g_allocator);
size = rcutils_get_file_size(non_existing_path);
ASSERT_EQ(0u, size);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
g_allocator.deallocate(non_existing_path, g_allocator.state);
});
}