summaryrefslogtreecommitdiff
path: root/support/dktools/dk4symlink.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4symlink.c
Initial commit
Diffstat (limited to 'support/dktools/dk4symlink.c')
-rw-r--r--support/dktools/dk4symlink.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/support/dktools/dk4symlink.c b/support/dktools/dk4symlink.c
new file mode 100644
index 0000000000..39f4fb57ea
--- /dev/null
+++ b/support/dktools/dk4symlink.c
@@ -0,0 +1,365 @@
+/*
+ WARNING: This file was generated by dkct.
+ Changes you make here will be lost if dkct is run again!
+ You should modify the original source and run dkct on it.
+ Original source: dk4symlink.ctr
+*/
+
+/*
+Copyright (C) 2015-2017, Dirk Krause
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above opyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** @file dk4symlink.c The dk4symlink module.
+*/
+
+
+#line 61 "dk4symlink.ctr"
+
+#include "dk4symlink.h"
+
+#if DK4_ON_WINDOWS
+#ifndef WINDOWS_H_INCLUDED
+#include <windows.h>
+#define WINDOWS_H_INCLUDED 1
+#endif
+#if DK4_HAVE_NTIFS_H
+#ifndef NTIFS_H_INCLUDED
+#include <ntifs.h>
+#define NTIFS_H_INCLUDED 1
+#endif
+#endif
+#endif
+
+#if DK4_HAVE_UNISTD_H
+#ifndef UNISTD_H_INCLUDED
+#include <unistd.h>
+#define UNISTD_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_ERRNO_H
+#ifndef ERRNO_H_INCLUDED
+#include <errno.h>
+#define ERRNO_H_INCLUDED 1
+#endif
+#endif
+
+#include "dk4mpl.h"
+#include "dk4mem.h"
+#include "dk4strd.h"
+
+
+
+
+
+#line 98 "dk4symlink.ctr"
+
+
+
+#if DK4_ON_WINDOWS
+
+#if !DK4_HAVE_NTIFS_H
+
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+#endif
+
+
+#if defined(FSCTL_GET_REPARSE_POINT)
+/** Size of reparse point information for a symlink.
+*/
+#define SYMLINK_INFO_SIZE ((8 * (DK4_MAX_PATH))+sizeof(REPARSE_DATA_BUFFER))
+/** The above size aligned to 16 bytes.
+*/
+#define SYMLINK_INFO_ALIGNED (16 * (((SYMLINK_INFO_SIZE) / 16) + 1))
+
+#ifdef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
+#define SYMLINK_BUFFER_SIZE \
+(MAXIMUM_REPARSE_DATA_BUFFER_SIZE + SYMLINK_INFO_ALIGNED)
+#endif
+#endif
+
+/** Copy path name from reparse point buffer to destination buffer.
+ @param bptr Destination buffer.
+ @param szb Destination buffer size (number of wchar_t).
+ @param sptr Source pointer.
+ @param offs Offset of path name in source (in bytes).
+ @param length Length of path name (in bytes).
+ @param erp Error report, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk4symlink_copy_string(
+ wchar_t *bptr,
+ size_t szb,
+ const wchar_t *sptr,
+ USHORT offs,
+ USHORT length,
+ dk4_er_t *erp
+)
+{
+ int back = 0;
+ if ((length / sizeof(wchar_t)) < szb) {
+ DK4_MEMCPY(bptr,&(sptr[offs / sizeof(wchar_t)]),length);
+ bptr[length / sizeof(wchar_t)] = L'\0';
+ back = 1;
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
+ }
+ return back;
+}
+
+#endif
+
+int
+dk4symlink_target(dkChar *bptr, size_t szb, const dkChar *fn, dk4_er_t *erp)
+{
+#if DK4_ON_WINDOWS
+#if defined(FSCTL_GET_REPARSE_POINT)
+ char repdabuf[SYMLINK_BUFFER_SIZE];
+ REPARSE_DATA_BUFFER *rdb;
+#endif
+ HANDLE fh;
+ DWORD dwres;
+ BOOL result;
+#else
+ ssize_t res;
+#endif
+ int back = 0;
+
+
+
+#line 198 "dk4symlink.ctr"
+ if ((NULL != bptr) && (NULL != fn) && (0 < szb)) {
+ *bptr = dkT('\0');
+#if DK4_ON_WINDOWS
+#if DK4_CHAR_SIZE > 1
+#if DK4_HAVE_GETFINALPATHNAMEBYHANDLE
+ fh = CreateFileW(
+ fn,
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+ if (INVALID_HANDLE_VALUE != fh) {
+ dwres = GetFinalPathNameByHandleW(fh, bptr, (DWORD)szb, 0);
+ if (0 < dwres) {
+ if (dwres < (DWORD)szb) {
+ back = 1;
+ }
+ }
+ CloseHandle(fh);
+ }
+#else
+
+
+#line 223 "dk4symlink.ctr"
+#endif
+ if (0 == back) {
+#if defined(FSCTL_GET_REPARSE_POINT)
+ /* !!!!! Second attempt with legacy procedure */
+
+
+#line 228 "dk4symlink.ctr"
+ fh = CreateFileW(
+ fn,
+ FILE_READ_ATTRIBUTES,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE),
+ NULL,
+ OPEN_EXISTING,
+ (
+ FILE_FLAG_BACKUP_SEMANTICS
+ | FILE_FLAG_OPEN_REPARSE_POINT
+ | FILE_ATTRIBUTE_REPARSE_POINT
+ ),
+ NULL
+ );
+ if (INVALID_HANDLE_VALUE != fh) {
+ dwres = 0;
+
+#line 243 "dk4symlink.ctr"
+ result = DeviceIoControl(
+ fh,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ (DWORD)0U,
+ (void *)repdabuf,
+ (DWORD)sizeof(repdabuf),
+ &dwres,
+ NULL
+ );
+ if (result) {
+
+#line 254 "dk4symlink.ctr"
+ rdb = (REPARSE_DATA_BUFFER *)repdabuf;
+ if (IO_REPARSE_TAG_MOUNT_POINT == rdb->ReparseTag) {
+
+
+#line 257 "dk4symlink.ctr"
+ back = dk4symlink_copy_string(
+ bptr, szb,
+ &(rdb->MountPointReparseBuffer.PathBuffer[0]),
+ rdb->MountPointReparseBuffer.SubstituteNameOffset,
+ rdb->MountPointReparseBuffer.SubstituteNameLength,
+ erp
+ );
+ } else {
+ if (IO_REPARSE_TAG_SYMLINK == rdb->ReparseTag) {
+
+
+#line 267 "dk4symlink.ctr"
+ back = dk4symlink_copy_string(
+ bptr, szb,
+ &(rdb->SymbolicLinkReparseBuffer.PathBuffer[0]),
+ rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset,
+ rdb->SymbolicLinkReparseBuffer.SubstituteNameLength,
+ erp
+ );
+ } else {
+ /* !!!!! Not mount point, not symlink */
+
+
+#line 277 "dk4symlink.ctr"
+ }
+ }
+ } else {
+
+#line 280 "dk4symlink.ctr"
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
+ }
+ CloseHandle(fh);
+ } else {
+
+#line 284 "dk4symlink.ctr"
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
+ }
+#else
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
+#endif
+ }
+#else
+#if DK4_HAVE_GETFINALPATHNAMEBYHANDLE
+ fh = CreateFileA(
+ fn,
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL
+ );
+ if (INVALID_HANDLE_VALUE != fh) {
+ dwres = GetFinalPathNameByHandleA(fh, bptr, (DWORD)szb, 0);
+ if (0 < dwres) {
+ if (dwres < (DWORD)szb) {
+ back = 1;
+ }
+ }
+ CloseHandle(fh);
+ }
+#else
+ /* Legacy procedure only available for wchar_t.
+ */
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
+#endif
+#endif
+ if (0 < back) {
+ if (dkT('\\') == bptr[0]) {
+ if ((dkT('\\') == bptr[1]) || (dkT('?') == bptr[1])) {
+ if (dkT('?') == bptr[2]) {
+ if (dkT('\\') == bptr[3]) {
+ if (260 > dk4str_len(&(bptr[4]))) {
+ dk4str_cpy_to_left(bptr, &(bptr[4]));
+ }
+ }
+ }
+ }
+ }
+ }
+#else
+#if DK4_CHAR_SIZE > 1
+ dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
+#else
+ errno = 0;
+ res = readlink(fn, bptr, szb);
+ if (0 < res) {
+ if (res < szb) {
+ bptr[res] = dkT('\0');
+ back = 1;
+ } else {
+
+#line 340 "dk4symlink.ctr"
+ bptr[0] = dkT('\0');
+ dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
+ }
+ } else {
+
+#line 344 "dk4symlink.ctr"
+ bptr[0] = dkT('\0');
+ if (0 > res) {
+ dk4error_set_idetails(erp, DK4_E_SYSTEM, errno);
+ }
+ }
+#endif
+#endif
+ if (0 == back) { *bptr = dkT('\0'); }
+ } else {
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+
+#line 355 "dk4symlink.ctr"
+ return back;
+}
+