Skip to content

Commit

Permalink
calculate file and directory size (#197)
Browse files Browse the repository at this point in the history
* calculate file and directory size

Signed-off-by: Karsten Knese <karsten@openrobotics.org>

* fix typo

Signed-off-by: Karsten Knese <karsten@openrobotics.org>

* more error handling

Signed-off-by: Karsten Knese <karsten@openrobotics.org>

* not a

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
  • Loading branch information
Karsten1987 authored Jan 10, 2020
1 parent 9c80b76 commit a742b36
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
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) {
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)
{
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);
});
}

0 comments on commit a742b36

Please sign in to comment.