summaryrefslogtreecommitdiffstats
path: root/fluent-bit/plugins/in_tail/win32
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:20:02 +0000
commit58daab21cd043e1dc37024a7f99b396788372918 (patch)
tree96771e43bb69f7c1c2b0b4f7374cb74d7866d0cb /fluent-bit/plugins/in_tail/win32
parentReleasing debian version 1.43.2-1. (diff)
downloadnetdata-58daab21cd043e1dc37024a7f99b396788372918.tar.xz
netdata-58daab21cd043e1dc37024a7f99b396788372918.zip
Merging upstream version 1.44.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/plugins/in_tail/win32')
-rw-r--r--fluent-bit/plugins/in_tail/win32/interface.h44
-rw-r--r--fluent-bit/plugins/in_tail/win32/io.c47
-rw-r--r--fluent-bit/plugins/in_tail/win32/stat.c332
3 files changed, 423 insertions, 0 deletions
diff --git a/fluent-bit/plugins/in_tail/win32/interface.h b/fluent-bit/plugins/in_tail/win32/interface.h
new file mode 100644
index 000000000..73b2ef233
--- /dev/null
+++ b/fluent-bit/plugins/in_tail/win32/interface.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 The Fluent Bit Authors
+ *
+ * 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.
+ */
+
+#ifndef FLB_TAIL_WIN32_INTERFACE_H
+#define FLB_TAIL_WIN32_INTERFACE_H
+
+struct win32_stat {
+ uint64_t st_ino;
+ uint16_t st_mode;
+ int64_t st_mtime;
+ int16_t st_nlink;
+ int64_t st_size;
+};
+
+int win32_stat(const char *path, struct win32_stat *wst);
+int win32_lstat(const char *path, struct win32_stat *wst);
+int win32_fstat(int fd, struct win32_stat *wst);
+
+int win32_open(const char *path, int flags);
+
+#define WIN32_S_IFDIR 0x1000
+#define WIN32_S_IFCHR 0x2000
+#define WIN32_S_IFIFO 0x4000
+#define WIN32_S_IFREG 0x8000
+#define WIN32_S_IFLNK 0xc000
+#define WIN32_S_IFMT 0xf000
+
+#endif
diff --git a/fluent-bit/plugins/in_tail/win32/io.c b/fluent-bit/plugins/in_tail/win32/io.c
new file mode 100644
index 000000000..45928b04a
--- /dev/null
+++ b/fluent-bit/plugins/in_tail/win32/io.c
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 The Fluent Bit Authors
+ *
+ * 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 <Windows.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <io.h>
+#include "interface.h"
+
+/*
+ * POSIX IO emulation tailored for in_tail's usage.
+ *
+ * open(2) that does not acquire an exclusive lock.
+ */
+
+int win32_open(const char *path, int flags)
+{
+ HANDLE h;
+ h = CreateFileA(path,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ NULL, /* lpSecurityAttributes */
+ OPEN_EXISTING, /* dwCreationDisposition */
+ 0, /* dwFlagsAndAttributes */
+ NULL); /* hTemplateFile */
+ if (h == INVALID_HANDLE_VALUE) {
+ return -1;
+ }
+ return _open_osfhandle((intptr_t) h, _O_RDONLY);
+}
diff --git a/fluent-bit/plugins/in_tail/win32/stat.c b/fluent-bit/plugins/in_tail/win32/stat.c
new file mode 100644
index 000000000..bce802749
--- /dev/null
+++ b/fluent-bit/plugins/in_tail/win32/stat.c
@@ -0,0 +1,332 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 The Fluent Bit Authors
+ *
+ * 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 <Windows.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <io.h>
+#include "interface.h"
+
+/*
+ * NTFS stat(2) emulation tailored for in_tail's usage.
+ *
+ * (1) Support st_ino (inode) for Windows NTFS.
+ * (2) Support NTFS symlinks.
+ * (3) Support large files >= 2GB.
+ *
+ * To use it, include "win32.h" and it will transparently
+ * replace stat(), lstat() and fstat().
+ */
+
+#define UINT64(high, low) ((uint64_t) (high) << 32 | (low))
+#define WINDOWS_TICKS_TO_SECONDS_RATIO 10000000
+#define WINDOWS_EPOCH_TO_UNIX_EPOCH_DELTA 11644473600
+
+/*
+ * FILETIME timestamps are represented in 100-nanosecond intervals,
+ * because of this, that's why we need to divide the number by 10000000
+ * in order to convert it to seconds.
+ *
+ * While UNIX timestamps use January 1, 1970 as epoch Windows FILETIME
+ * timestamps use January 1, 1601. Because of this we need to subtract
+ * 11644473600 seconds to account for it.
+ *
+ * Note: Even though this does not account for leap seconds it should be
+ * accurate enough.
+ */
+
+static uint64_t filetime_to_epoch(FILETIME *ft)
+{
+ ULARGE_INTEGER timestamp;
+
+ if (ft == NULL) {
+ return 0;
+ }
+
+ timestamp.HighPart = ft->dwHighDateTime;
+ timestamp.LowPart = ft->dwLowDateTime;
+
+ timestamp.QuadPart /= WINDOWS_TICKS_TO_SECONDS_RATIO;
+ timestamp.QuadPart -= WINDOWS_EPOCH_TO_UNIX_EPOCH_DELTA;
+
+ return timestamp.QuadPart;
+}
+
+static void reset_errno()
+{
+ errno = 0;
+}
+
+static void propagate_last_error_to_errno()
+{
+ DWORD error_code;
+
+ error_code = GetLastError();
+
+ switch (error_code) {
+ case ERROR_INVALID_TARGET_HANDLE:
+ case ERROR_INVALID_HANDLE:
+ errno = EBADF;
+ break;
+
+ case ERROR_TOO_MANY_OPEN_FILES:
+ errno = EMFILE;
+ break;
+
+ case ERROR_INVALID_FLAG_NUMBER:
+ case ERROR_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_OUTOFMEMORY:
+ errno = ENOMEM;
+ break;
+
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_PATH_BUSY:
+ case ERROR_BUSY:
+ errno = EBUSY;
+ break;
+
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ errno = ENOSPC;
+ break;
+
+ case ERROR_INVALID_ADDRESS:
+ errno = EFAULT;
+ break;
+
+ case ERROR_FILE_TOO_LARGE:
+ errno = EFBIG;
+ break;
+
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_FILE_EXISTS:
+ errno = EEXIST;
+ break;
+
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_UNIT:
+ errno = ENOENT;
+ break;
+
+ case ERROR_SEEK_ON_DEVICE:
+ case ERROR_NEGATIVE_SEEK:
+ errno = ESPIPE;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ errno = EACCES;
+ break;
+
+ case ERROR_DIR_NOT_EMPTY:
+ errno = ENOTEMPTY;
+ break;
+
+ case ERROR_BROKEN_PIPE:
+ errno = EPIPE;
+ break;
+
+ case ERROR_GEN_FAILURE:
+ errno = EIO;
+ break;
+
+ case ERROR_OPEN_FAILED:
+ errno = EIO;
+ break;
+
+ case ERROR_SUCCESS:
+ errno = 0;
+ break;
+
+ default:
+ /* This is just a canary, if you find this
+ * error then it means we need to expand the
+ * translation list.
+ */
+
+ errno = EOWNERDEAD;
+ break;
+ }
+}
+
+static int get_mode(unsigned int attr)
+{
+ if (attr & FILE_ATTRIBUTE_DIRECTORY) {
+ return WIN32_S_IFDIR;
+ }
+ return WIN32_S_IFREG;
+}
+
+
+
+static int is_symlink(const char *path)
+{
+ WIN32_FIND_DATA data;
+ HANDLE h;
+
+ SetLastError(0);
+ reset_errno();
+
+ h = FindFirstFileA(path, &data);
+
+ if (h == INVALID_HANDLE_VALUE) {
+ propagate_last_error_to_errno();
+
+ return 0;
+ }
+
+ FindClose(h);
+
+ /*
+ * A NTFS symlink is a file with a bit of metadata ("reparse point"),
+ * So (1) check if the file has metadata and then (2) confirm that
+ * it is indeed a symlink.
+ */
+ if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ if (data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int hstat(HANDLE h, struct win32_stat *wst)
+{
+ BY_HANDLE_FILE_INFORMATION info;
+ FILE_STANDARD_INFO std;
+
+ SetLastError(0);
+ reset_errno();
+
+ if (!GetFileInformationByHandle(h, &info)) {
+ propagate_last_error_to_errno();
+
+ return -1;
+ }
+
+ if (!GetFileInformationByHandleEx(h, FileStandardInfo,
+ &std, sizeof(std))) {
+ propagate_last_error_to_errno();
+
+ return -1;
+ }
+
+ wst->st_nlink = std.NumberOfLinks;
+ if (std.DeletePending) {
+ wst->st_nlink = 0;
+ }
+
+ wst->st_mode = get_mode(info.dwFileAttributes);
+ wst->st_size = UINT64(info.nFileSizeHigh, info.nFileSizeLow);
+ wst->st_ino = UINT64(info.nFileIndexHigh, info.nFileIndexLow);
+ wst->st_mtime = filetime_to_epoch(&info.ftLastWriteTime);
+
+ return 0;
+}
+
+int win32_stat(const char *path, struct win32_stat *wst)
+{
+ HANDLE h;
+
+ SetLastError(0);
+ reset_errno();
+
+ h = CreateFileA(path,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ NULL, /* lpSecurityAttributes */
+ OPEN_EXISTING, /* dwCreationDisposition */
+ 0, /* dwFlagsAndAttributes */
+ NULL); /* hTemplateFile */
+
+ if (h == INVALID_HANDLE_VALUE) {
+ propagate_last_error_to_errno();
+
+ return -1;
+ }
+
+ if (hstat(h, wst)) {
+ CloseHandle(h);
+ return -1;
+ }
+
+ CloseHandle(h);
+ return 0;
+}
+
+int win32_lstat(const char *path, struct win32_stat *wst)
+{
+ HANDLE h;
+
+ SetLastError(0);
+ reset_errno();
+
+ h = CreateFileA(path,
+ GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ NULL, /* lpSecurityAttributes */
+ OPEN_EXISTING, /* dwCreationDisposition */
+ FILE_FLAG_OPEN_REPARSE_POINT,
+ NULL); /* hTemplateFile */
+
+ if (h == INVALID_HANDLE_VALUE) {
+ propagate_last_error_to_errno();
+
+ return -1;
+ }
+
+ if (hstat(h, wst)) {
+ CloseHandle(h);
+ return -1;
+ }
+
+ if (is_symlink(path)) {
+ wst->st_mode = WIN32_S_IFLNK;
+ }
+
+ CloseHandle(h);
+ return 0;
+}
+
+int win32_fstat(int fd, struct win32_stat *wst)
+{
+ HANDLE h;
+
+ SetLastError(0);
+ reset_errno();
+
+ h = (HANDLE) _get_osfhandle(fd);
+
+ if (h == INVALID_HANDLE_VALUE) {
+ propagate_last_error_to_errno();
+
+ return -1;
+ }
+
+ return hstat(h, wst);
+}