Skip to content

Commit

Permalink
initial pass
Browse files Browse the repository at this point in the history
  • Loading branch information
TingDaoK committed Aug 2, 2024
1 parent 2add521 commit 62048f5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 5 deletions.
14 changes: 14 additions & 0 deletions include/aws/common/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct aws_directory_entry {
int64_t file_size;
};

struct aws_file_handle;

/**
* Invoked during calls to aws_directory_traverse() as an entry is encountered. entry will contain
* the parsed directory entry info.
Expand Down Expand Up @@ -207,6 +209,18 @@ int aws_fseek(FILE *file, int64_t offset, int whence);
AWS_COMMON_API
int aws_file_get_length(FILE *file, int64_t *length);

/**
* @brief Wrapper for os-specific pwrite implementation.
*
* @param fd
* @param buf
* @param count
* @param offset
* @return AWS_COMMON_API
*/
AWS_COMMON_API
int aws_pwrite(int fd, const void *buf, size_t count, uint64_t offset, size_t *bytes_written);

AWS_EXTERN_C_END
AWS_POP_SANE_WARNING_LEVEL

Expand Down
18 changes: 18 additions & 0 deletions source/posix/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,21 @@ int aws_file_get_length(FILE *file, int64_t *length) {

return AWS_OP_SUCCESS;
}

int aws_pwrite(int fd, const void *buf, size_t count, uint64_t offset, size_t *bytes_written) {
if (fd == -1) {
return aws_raise_error(AWS_ERROR_INVALID_FILE_HANDLE);
}
#ifdef AWS_OS_MACOS
/* MacOS doesn't have pwrite64. */
*bytes_written = pwrite(fd, buf, count, offset);
#else
*bytes_written = pwrite64(fd, buf, count, offset);
#endif
int errno_value = errno; /* Always cache errno before potential side-effect */
if (*bytes_written == -1) {
/* TODO: maybe some other default error? */
return aws_translate_and_raise_io_error_or(errno_value, AWS_ERROR_UNKNOWN);
}
return AWS_OP_SUCCESS;
}
34 changes: 34 additions & 0 deletions source/windows/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,37 @@ int aws_file_get_length(FILE *file, int64_t *length) {

return AWS_OP_SUCCESS;
}

int aws_pwrite(int fd, const void *buf, size_t count, uint64_t offset, size_t *bytes_written) {
if (fd == -1) {
return aws_raise_error(AWS_ERROR_INVALID_FILE_HANDLE);
}

HANDLE os_file = (HANDLE)_get_osfhandle(fd);
if (os_file == INVALID_HANDLE_VALUE) {
int errno_value = errno; /* Always cache errno before potential side-effect */
return aws_translate_and_raise_io_error(errno_value);
}
DWORD bytesWritten;
OVERLAPPED ol = {0};
LARGE_INTEGER li;

/* Convert uint64_t offset to OVERLAPPED */
li.QuadPart = offset;
ol.Offset = li.LowPart;
ol.OffsetHigh = li.HighPart;

if (!WriteFile(os_file, buf, (DWORD)count, &bytesWritten, &ol)) {
int error = GetLastError();

if (error == ERROR_IO_PENDING) {
/* TODO: check for different errors. */
return aws_raise_error(AWS_ERROR_INVALID_FILE_HANDLE);
}
return aws_raise_error(AWS_ERROR_UNKNOWN);
}
*bytes_written = (size_t)bytesWritten;
/* TODO: verify the fd offset is not affected. */
/* Never call CloseHandle on the return value of _get_osfhandle */
return AWS_OP_SUCCESS;
}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ add_test_case(test_home_directory_not_null)
add_test_case(test_normalize_posix_directory_separator)
add_test_case(test_normalize_windows_directory_separator)
add_test_case(test_byte_buf_init_from_file)
add_test_case(test_aws_pwrite)

add_test_case(test_json_parse_from_string)
add_test_case(test_json_parse_to_string)
Expand Down
35 changes: 30 additions & 5 deletions tests/file_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@
#include <aws/testing/aws_test_harness.h>

#include <fcntl.h>
#include <unistd.h>

static int s_aws_fopen_test_helper(char *file_path, char *content) {
static int s_read_and_verify_helper(char *file_path, char *content) {
char read_result[100];
AWS_ZERO_ARRAY(read_result);
FILE *file = aws_fopen(file_path, "w+");
ASSERT_NOT_NULL(file);
fprintf(file, "%s", content);
fclose(file);
FILE *readfile = aws_fopen(file_path, "r");
ASSERT_NOT_NULL(readfile);
size_t read_len = fread(read_result, sizeof(char), strlen(content), readfile);
Expand All @@ -36,6 +33,14 @@ static int s_aws_fopen_test_helper(char *file_path, char *content) {
return AWS_OP_SUCCESS;
}

static int s_aws_fopen_test_helper(char *file_path, char *content) {
FILE *file = aws_fopen(file_path, "w+");
ASSERT_NOT_NULL(file);
fprintf(file, "%s", content);
fclose(file);
return s_read_and_verify_helper(file_path, content);
}

static int s_aws_fopen_content_matches(char *file_path, char *content) {
char read_result[100];
AWS_ZERO_ARRAY(read_result);
Expand Down Expand Up @@ -542,3 +547,23 @@ static int s_test_byte_buf_init_from_file(struct aws_allocator *allocator, void
}

AWS_TEST_CASE(test_byte_buf_init_from_file, s_test_byte_buf_init_from_file)

static int s_test_aws_pwrite(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
char file_path[] = "sample.txt";
int fd = open(file_path, O_RDWR | O_NONBLOCK | O_CREAT, 0666);
struct aws_byte_cursor contents = aws_byte_cursor_from_c_str("hello world");

size_t byte_written = 0;
aws_pwrite(fd, contents.ptr, contents.len, 0, &byte_written);
aws_pwrite(fd, contents.ptr, contents.len, contents.len, &byte_written);
close(fd);

/* Verify the written content match expected */
ASSERT_SUCCESS(s_read_and_verify_helper(file_path, "hello worldhello world"));

/* TODO: test error handling. */
return AWS_OP_SUCCESS;
}

AWS_TEST_CASE(test_aws_pwrite, s_test_aws_pwrite)

0 comments on commit 62048f5

Please sign in to comment.