Skip to content

Commit

Permalink
New fsio_join_paths, fsio_file_size and fsio_read_text_file_with_opti…
Browse files Browse the repository at this point in the history
…ons functions
  • Loading branch information
sagiegurari committed Jul 31, 2021
1 parent 30b144c commit cba0a7e
Show file tree
Hide file tree
Showing 32 changed files with 794 additions and 8 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
## CHANGELOG

### v0.1.7
### v0.1.7 (2021-07-31)

* New fsio_join_paths function.
* New fsio_file_size function.
* New fsio_read_text_file_with_options function.
* Improved input validation for more stable API.
* Added cargo-make makefile for simpler sharing of optional development build instructions.

### v0.1.6 (2020-12-27)
Expand Down
29 changes: 28 additions & 1 deletion include/fsio.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,21 @@ struct FsIORecursiveCallbackInfo
bool is_file;
};

struct FsIOReadTextFileOptions
{
// the limit to read. 0 or negative value for no limit.
long max_read_limit;
// if limit is set, if true, read from end, else read from start.
bool tail;
};

struct FsIOCopyFileOptions
{
// amount of additional retries in case of write error
unsigned int write_retries;
unsigned int retry_interval_seconds;
};


struct FsIOMoveFileOptions
{
// True to force move via file copy instead of rename
Expand All @@ -34,6 +41,13 @@ struct FsIOMoveFileOptions
*/
extern const mode_t FSIO_MODE_ALL;

/**
* Returns the file size.
* If no input provided, file is not found or path does not point to a file,
* -1 will be returned.
*/
long fsio_file_size(char * /* file */);

/**
* Writes the provided text into the file, deleting any previous content.
* In case of any error or invalid input, this function will return false.
Expand All @@ -54,6 +68,12 @@ bool fsio_append_text_file(char * /* file */, char * /* text */);
*/
char *fsio_read_text_file(char * /* file */);

/**
* Reads and returns the text from the provided file.
* In case of any error or invalid input, this function will return NULL.
*/
char *fsio_read_text_file_with_options(char * /* file */, struct FsIOReadTextFileOptions);

/**
* Creates an empty file for the provided path.
* If a file exists in that path, it will be truncated.
Expand Down Expand Up @@ -92,6 +112,13 @@ bool fsio_move_file(char * /* source */, char * /* target */);
*/
bool fsio_move_file_with_options(char * /* source */, char * /* target */, struct FsIOMoveFileOptions);

/**
* Will join the provided paths and return a new allocated string with
* the result.
* If needed, a unix style separator will be added.
*/
char *fsio_join_paths(char *, char *);

/**
* Returns true if the provided path exists.
*/
Expand Down
146 changes: 140 additions & 6 deletions src/fsio.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,33 @@ bool _fsio_chmod_recursive_callback(struct FsIORecursiveCallbackInfo);
bool _fsio_recursive_operation(char *, bool (*callback)(struct FsIORecursiveCallbackInfo), void *, struct StringBuffer *);


long fsio_file_size(char *file)
{
if (!fsio_file_exists(file))
{
return(-1);
}

FILE *fp = fopen(file, "r");
if (fp == NULL)
{
return(-1);
}

long current_position = ftell(fp);

fseek(fp, 0L, SEEK_END);
long size = ftell(fp);

// set back to original position
fseek(fp, current_position, SEEK_SET);

fclose(fp);

return(size);
}


bool fsio_write_text_file(char *file, char *text)
{
return(_fsio_write_text_file(file, text, "w"));
Expand All @@ -33,18 +60,51 @@ bool fsio_append_text_file(char *file, char *text)

char *fsio_read_text_file(char *file)
{
FILE *fp = fopen(file, "r");
struct FsIOReadTextFileOptions options;

options.max_read_limit = 0;
options.tail = false;

return(fsio_read_text_file_with_options(file, options));
}


char *fsio_read_text_file_with_options(char *file, struct FsIOReadTextFileOptions options)
{
long file_size = fsio_file_size(file);

if (file_size < 0)
{
return(NULL);
}
if (!file_size)
{
return(strdup(""));
}

FILE *fp = fopen(file, "r");
if (fp == NULL)
{
return(NULL);
}

long left_to_read = file_size;
if (options.max_read_limit > 0 && left_to_read > options.max_read_limit)
{
left_to_read = options.max_read_limit;

if (options.tail)
{
fseek(fp, (-1) * left_to_read, SEEK_END);
}
}

int character;
struct StringBuffer *buffer = string_buffer_new();
while ((character = getc(fp)) != EOF)
while ((character = getc(fp)) != EOF && left_to_read > 0)
{
string_buffer_append(buffer, (char)character);
left_to_read--;
}

fclose(fp);
Expand All @@ -54,7 +114,7 @@ char *fsio_read_text_file(char *file)
string_buffer_release(buffer);

return(text);
}
} /* fsio_read_text_file_with_options */


bool fsio_create_empty_file(char *file)
Expand All @@ -76,6 +136,11 @@ bool fsio_copy_file(char *source, char *target)

bool fsio_copy_file_with_options(char *source, char *target, struct FsIOCopyFileOptions options)
{
if (source == NULL || target == NULL)
{
return(false);
}

FILE *source_fp = fopen(source, "r");

if (source_fp == NULL)
Expand Down Expand Up @@ -124,7 +189,7 @@ bool fsio_copy_file_with_options(char *source, char *target, struct FsIOCopyFile
}

return(true);
} /* fsio_copy_file_with_options */
} /* fsio_copy_file_with_options */


bool fsio_move_file(char *source, char *target)
Expand All @@ -141,7 +206,7 @@ bool fsio_move_file(char *source, char *target)

bool fsio_move_file_with_options(char *source, char *target, struct FsIOMoveFileOptions options)
{
if (!fsio_file_exists(source))
if (target == NULL || !fsio_file_exists(source))
{
return(false);
}
Expand Down Expand Up @@ -172,6 +237,75 @@ bool fsio_move_file_with_options(char *source, char *target, struct FsIOMoveFile
}


char *fsio_join_paths(char *path1, char *path2)
{
if (path1 == NULL)
{
if (path2 == NULL)
{
return(NULL);
}

return(strdup(path2));
}
if (path2 == NULL)
{
return(strdup(path1));
}

size_t len1 = strlen(path1);
if (!len1)
{
return(strdup(path2));
}
size_t len2 = strlen(path2);
if (!len2)
{
return(strdup(path1));
}

bool path1_ends_with_separator = path1[len1 - 1] == '/' || path1[len1 - 1] == '\\';
bool path2_starts_with_separator = path2[0] == '/' || path2[0] == '\\';
bool need_to_add_separator = !path1_ends_with_separator && !path2_starts_with_separator;
bool need_to_remove_separator = path1_ends_with_separator && path2_starts_with_separator;

size_t concat_len = len1 + len2;
if (need_to_add_separator)
{
concat_len = concat_len + 1;
}
else if (need_to_remove_separator)
{
concat_len = concat_len - 1;
}

char *concat_path = malloc(sizeof(char *) * (concat_len + 1));

for (size_t index = 0; index < len1; index++)
{
concat_path[index] = path1[index];
}
size_t offset = len1;
if (need_to_add_separator)
{
concat_path[len1] = '/';
offset = offset + 1;
}
else if (need_to_remove_separator)
{
offset = offset - 1;
}
for (size_t index = 0; index < len2; index++)
{
concat_path[offset + index] = path2[index];
}

concat_path[concat_len] = 0;

return(concat_path);
} /* fsio_join_paths */


bool fsio_path_exists(char *path)
{
struct stat info;
Expand Down Expand Up @@ -458,5 +592,5 @@ bool _fsio_recursive_operation(char *path, bool (*callback)(struct FsIORecursive
}

return(false);
} /* _fsio_recursive_operation */
} /* _fsio_recursive_operation */

10 changes: 10 additions & 0 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ void assert_string_equal(char *value1, char *value2)
}


void assert_num_equal(long value1, long value2)
{
if (value1 != value2)
{
printf("Assert Failed, value: %ld not equals to value: %ld", value1, value2);
test_fail();
}
}


void assert_mode_equal(mode_t value1, mode_t value2)
{
if (value1 != value2)
Expand Down
1 change: 1 addition & 0 deletions tests/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ void test_fail();
void assert_true(bool);

void assert_string_equal(char *, char *);
void assert_num_equal(long, long);

void assert_mode_equal(mode_t, mode_t);

Expand Down
19 changes: 19 additions & 0 deletions tests/test_copy_file_null_source.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "fsio.h"
#include "test.h"
#include <stdio.h>
#include <stdlib.h>


void test_impl()
{
bool done = fsio_copy_file(NULL, "./test.txt");

assert_true(!done);
}


int main()
{
test_run(test_impl);
}

25 changes: 25 additions & 0 deletions tests/test_copy_file_null_target.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "fsio.h"
#include "test.h"
#include <stdio.h>
#include <stdlib.h>


void test_impl()
{
char *file1 = "./copy_file_null_target.txt";
bool done = fsio_write_text_file(file1, "some\ncontent");

assert_true(done);

done = fsio_copy_file(file1, NULL);
assert_true(!done);

remove(file1);
}


int main()
{
test_run(test_impl);
}

25 changes: 25 additions & 0 deletions tests/test_file_size_exists.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "fsio.h"
#include "test.h"
#include <stdio.h>


void test_impl()
{
char *file = "./file_size_exists.txt";
bool done = fsio_write_text_file(file, "123456789");

assert_true(done);

long size = fsio_file_size(file);

remove(file);

assert_num_equal(size, 9);
}


int main()
{
test_run(test_impl);
}

Loading

0 comments on commit cba0a7e

Please sign in to comment.