diff options
Diffstat (limited to 'fluent-bit/lib/chunkio/src/cio_file_win32.c')
-rw-r--r-- | fluent-bit/lib/chunkio/src/cio_file_win32.c | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/fluent-bit/lib/chunkio/src/cio_file_win32.c b/fluent-bit/lib/chunkio/src/cio_file_win32.c new file mode 100644 index 00000000..18044c40 --- /dev/null +++ b/fluent-bit/lib/chunkio/src/cio_file_win32.c @@ -0,0 +1,549 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Chunk I/O + * ========= + * Copyright 2018 Eduardo Silva <eduardo@monkey.io> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <inttypes.h> +#include <stdio.h> + +#include <chunkio/chunkio_compat.h> +#include <chunkio/chunkio.h> +#include <chunkio/cio_crc32.h> +#include <chunkio/cio_chunk.h> +#include <chunkio/cio_file.h> +#include <chunkio/cio_file_native.h> +#include <chunkio/cio_file_st.h> +#include <chunkio/cio_log.h> +#include <chunkio/cio_stream.h> + +int cio_file_native_unmap(struct cio_file *cf) +{ + int result; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_open(cf)) { + return CIO_OK; + } + + if (!cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + result = UnmapViewOfFile(cf->map); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + CloseHandle(cf->backing_mapping); + + cf->backing_mapping = INVALID_HANDLE_VALUE; + cf->alloc_size = 0; + cf->map = NULL; + + return CIO_OK; +} + +int cio_file_native_map(struct cio_file *cf, size_t map_size) +{ + DWORD desired_protection; + DWORD desired_access; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (!cio_file_native_is_open(cf)) { + return CIO_ERROR; + } + + if (cio_file_native_is_mapped(cf)) { + return CIO_OK; + } + + if (cf->flags & CIO_OPEN_RW) { + desired_protection = PAGE_READWRITE; + desired_access = FILE_MAP_ALL_ACCESS; + } + else if (cf->flags & CIO_OPEN_RD) { + desired_protection = PAGE_READONLY; + desired_access = FILE_MAP_READ; + } + else { + return CIO_ERROR; + } + + cf->backing_mapping = CreateFileMappingA(cf->backing_file, NULL, + desired_protection, + 0, 0, NULL); + + if (cf->backing_mapping == NULL) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->map = MapViewOfFile(cf->backing_mapping, desired_access, 0, 0, map_size); + + if (cf->map == NULL) { + cio_file_native_report_os_error(); + + CloseHandle(cf->backing_mapping); + + cf->backing_mapping = INVALID_HANDLE_VALUE; + + return CIO_ERROR; + } + + cf->alloc_size = map_size; + + return CIO_OK; +} + +int cio_file_native_remap(struct cio_file *cf, size_t new_size) +{ + /* + * There's no reason for this function to exist because in windows + * we need to unmap, resize and then map again so there's no benefit + * from remapping and I'm not implementing a dummy version because I + * don't want anyone to read it and think there are any reasonable use + * cases for it. + */ + + (void) cf; + (void) new_size; + + return CIO_ERROR; +} + +static SID *perform_sid_lookup(char *account_name, SID_NAME_USE *result_sid_type) +{ + DWORD referenced_domain_name_length; + char referenced_domain_name[256]; + SID *reallocated_sid_buffer; + DWORD sid_buffer_size; + size_t retry_index; + SID *sid_buffer; + SID_NAME_USE sid_type; + int result; + + referenced_domain_name_length = 256; + sid_buffer_size = 256; + + sid_buffer = calloc(1, sid_buffer_size); + + if (sid_buffer == NULL) { + cio_file_native_report_runtime_error(); + + return NULL; + } + + result = 0; + sid_type = SidTypeUnknown; + + for (retry_index = 0 ; retry_index < 5 && !result ; retry_index++) { + result = LookupAccountNameA(NULL, + account_name, + sid_buffer, + &sid_buffer_size, + referenced_domain_name, + &referenced_domain_name_length, + &sid_type); + + if (!result) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + sid_buffer_size *= 2; + + reallocated_sid_buffer = realloc(sid_buffer, sid_buffer_size); + + if (reallocated_sid_buffer == NULL) { + cio_file_native_report_runtime_error(); + + free(sid_buffer); + + return NULL; + } + } + else { + cio_file_native_report_os_error(); + + free(sid_buffer); + + return NULL; + } + } + } + + if (result_sid_type != NULL) { + *result_sid_type = sid_type; + } + + return sid_buffer; +} + +static int perform_entity_lookup(char *name, + void **result, + SID_NAME_USE desired_sid_type) +{ + SID_NAME_USE result_sid_type; + + *result = (void **) perform_sid_lookup(name, &result_sid_type); + + if (*result == NULL) { + return CIO_ERROR; + } + + if (desired_sid_type != result_sid_type) { + free(*result); + + *result = NULL; + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_lookup_user(char *user, void **result) +{ + return perform_entity_lookup(user, result, SidTypeUser); +} + +int cio_file_native_lookup_group(char *group, void **result) +{ + return perform_entity_lookup(group, result, SidTypeGroup); +} + +static DWORD cio_file_win_chown(char *path, SID *user, SID *group) +{ + int result; + + /* Ownership here does not work in the same way it works in unixes + * so specifying both a user and group will end up with the group + * overriding the user if possible which can cause some misunderstandings. + */ + + result = ERROR_SUCCESS; + + if (user != NULL) { + result = SetNamedSecurityInfoA(path, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, + user, NULL, NULL, NULL); + } + + if (group != NULL && result == ERROR_SUCCESS) { + result = SetNamedSecurityInfoA(path, SE_FILE_OBJECT, + GROUP_SECURITY_INFORMATION, + group, NULL, NULL, NULL); + } + + return result; +} + +int cio_file_native_apply_acl_and_settings(struct cio_ctx *ctx, struct cio_file *cf) +{ + int result; + + if (ctx->processed_user != NULL) { + result = cio_file_win_chown(cf->path, ctx->processed_user, ctx->processed_group); + + if (result != ERROR_SUCCESS) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + } + + return CIO_OK; +} + +static int get_file_size_by_handle(struct cio_file *cf, size_t *file_size) +{ + LARGE_INTEGER native_file_size; + int ret; + + memset(&native_file_size, 0, sizeof(native_file_size)); + + ret = GetFileSizeEx(cf->backing_file, &native_file_size); + + if (ret == 0) { + return CIO_ERROR; + } + + if (file_size != NULL) { + *file_size = (size_t) native_file_size.QuadPart; + } + + return CIO_OK; +} + +static int get_file_size_by_path(struct cio_file *cf, size_t *file_size) +{ + int ret; +#ifdef _WIN64 + struct _stat64 st; +#else + struct _stat32 st; +#endif + +#ifdef _WIN64 + ret = _stat64(cf->path, &st); +#else + ret = _stat32(cf->path, &st); +#endif + + if (ret == -1) { + return CIO_ERROR; + } + + if (file_size != NULL) { + *file_size = st.st_size; + } + + return CIO_OK; +} + +int cio_file_native_get_size(struct cio_file *cf, size_t *file_size) +{ + int ret; + + ret = CIO_ERROR; + + if (cf->backing_file != INVALID_HANDLE_VALUE) { + ret = get_file_size_by_handle(cf, file_size); + } + + if (ret != CIO_OK) { + ret = get_file_size_by_path(cf, file_size); + } + + return ret; +} + +char *cio_file_native_compose_path(char *root_path, char *stream_name, + char *chunk_name) +{ + size_t psize; + char *path; + int ret; + + /* Compose path for the file */ + psize = strlen(root_path) + + strlen(stream_name) + + strlen(chunk_name) + + 3; + + path = malloc(psize); + + if (path == NULL) { + cio_file_native_report_runtime_error(); + + return NULL; + } + + ret = snprintf(path, psize, "%s\\%s\\%s", + root_path, stream_name, chunk_name); + + if (ret == -1) { + cio_file_native_report_runtime_error(); + + free(path); + + return NULL; + } + + return path; +} + +int cio_file_native_filename_check(char *name) +{ + size_t len; + + len = strlen(name); + + if (len == 0) { + return CIO_ERROR; + } + else if (len == 1) { + if (name[0] == '\\' || name[0] == '.' || name[0] == '/') { + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_open(struct cio_file *cf) +{ + DWORD creation_disposition; + DWORD desired_access; + + if (cio_file_native_is_open(cf)) { + return CIO_OK; + } + + if (cf->flags & CIO_OPEN) { + desired_access = GENERIC_READ | GENERIC_WRITE; + creation_disposition = OPEN_ALWAYS; + } + else if (cf->flags & CIO_OPEN_RD) { + desired_access = GENERIC_READ; + creation_disposition = OPEN_EXISTING; + } + else { + return CIO_ERROR; + } + + cf->backing_file = CreateFileA(cf->path, + desired_access, + FILE_SHARE_DELETE | + FILE_SHARE_READ | + FILE_SHARE_WRITE, + NULL, + creation_disposition, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (cf->backing_file == INVALID_HANDLE_VALUE) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_close(struct cio_file *cf) +{ + int result; + + if (cf == NULL) { + return CIO_ERROR; + } + + if (cio_file_native_is_open(cf)) { + result = CloseHandle(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->backing_file = INVALID_HANDLE_VALUE; + } + + return CIO_OK; +} + +int cio_file_native_delete_by_path(const char *path) +{ + int result; + + result = DeleteFileA(path); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_delete(struct cio_file *cf) +{ + int result; + + result = DeleteFileA(cf->path); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + return CIO_OK; +} + +int cio_file_native_sync(struct cio_file *cf, int sync_mode) +{ + int result; + + result = FlushViewOfFile(cf->map, cf->alloc_size); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + if (sync_mode & CIO_FULL_SYNC) { + result = FlushFileBuffers(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + } + + return CIO_OK; +} + +int cio_file_native_resize(struct cio_file *cf, size_t new_size) +{ + LARGE_INTEGER movement_distance; + int result; + + if (!cio_file_native_is_open(cf)) { + return CIO_ERROR; + } + + if (cio_file_native_is_mapped(cf)) { + return CIO_ERROR; + } + + movement_distance.QuadPart = new_size; + + result = SetFilePointerEx(cf->backing_file, + movement_distance, + NULL, FILE_BEGIN); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + result = SetEndOfFile(cf->backing_file); + + if (result == 0) { + cio_file_native_report_os_error(); + + return CIO_ERROR; + } + + cf->fs_size = new_size; + + return CIO_OK; +} |