summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/chunkio/src/cio_file_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/chunkio/src/cio_file_win32.c')
-rw-r--r--fluent-bit/lib/chunkio/src/cio_file_win32.c549
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;
+}