]> git.seodisparate.com - SimpleArchiver/commitdiff
WIP work on windows support windows
authorStephen Seo <seo.disparate@gmail.com>
Fri, 5 Jul 2024 11:47:30 +0000 (20:47 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 10 Jul 2024 10:01:22 +0000 (19:01 +0900)
Windows support is still WIP.

src/parser.c

index c14f2aa3854994314cf0eec7045e8dd8dbd6368e..b321810a2fee675ffd7824a7e15e6aae03be7dfc 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#elif SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_WINDOWS
+#include <fileapi.h>
+#include <wchar.h>
+#include <windows.h>
+#include <winioctl.h>
+#include <winnt.h>
 #endif
 
 #include "data_structures/hash_map.h"
@@ -61,7 +67,11 @@ unsigned int simple_archiver_parser_internal_filename_idx(
     } else if ((flags & 3) == 1) {
       if (filename[idx] == 0) {
         return known_good_idx;
+#if SIMPLE_ARCHIVER_PLATFORM != SIMPLE_ARCHIVER_PLATFORM_WINDOWS
       } else if (filename[idx] == '/') {
+#else
+      } else if (filename[idx] == '\\') {
+#endif
         flags |= 2;
       } else {
         return idx - 1;
@@ -69,7 +79,11 @@ unsigned int simple_archiver_parser_internal_filename_idx(
     } else if ((flags & 3) == 3) {
       if (filename[idx] == 0) {
         return known_good_idx;
+#if SIMPLE_ARCHIVER_PLATFORM != SIMPLE_ARCHIVER_PLATFORM_WINDOWS
       } else if (filename[idx] == '/') {
+#else
+      } else if (filename[idx] == '\\') {
+#endif
         continue;
       } else if (filename[idx] == '.') {
         flags &= 0xFFFFFFFC;
@@ -103,6 +117,34 @@ void simple_archiver_parser_internal_remove_end_slash(char *filename) {
   }
 }
 
+char *simple_archiver_internal_forward_to_backward_slash(const char *string) {
+  unsigned int len = strlen(string) + 1;
+  char *backward_slash_string = malloc(len);
+  strncpy(backward_slash_string, string, len);
+
+  for (unsigned int idx = 0; idx < len; ++idx) {
+    if (backward_slash_string[idx] == '/') {
+      backward_slash_string[idx] = '\\';
+    }
+  }
+
+  return backward_slash_string;
+}
+
+char *simple_archiver_internal_backward_to_forward_slash(const char *string) {
+  unsigned int len = strlen(string) + 1;
+  char *forward_slash_string = malloc(len);
+  strncpy(forward_slash_string, string, len);
+
+  for (unsigned int idx = 0; idx < len; ++idx) {
+    if (forward_slash_string[idx] == '\\') {
+      forward_slash_string[idx] = '/';
+    }
+  }
+
+  return forward_slash_string;
+}
+
 void simple_archiver_internal_free_file_info_fn(void *data) {
   SDArchiverFileInfo *file_info = data;
   if (file_info) {
@@ -418,6 +460,72 @@ SDArchiverLinkedList *simple_archiver_parsed_to_filenames(
       // Unhandled type. TODO handle this.
     }
   }
+#elif SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_WINDOWS
+  for (char **iter = parsed->working_files; iter && *iter; ++iter) {
+    DWORD file_stats = GetFileAttributesA(*iter);
+    if (file_stats == INVALID_FILE_ATTRIBUTES) {
+      printf("Failed to get attributes for %s\n", *iter);
+      continue;
+    } else if ((file_stats & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+      // Is not a directory.
+      if ((file_stats & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
+        // Is not a symbolic link. Is probably a regular file.
+        printf("%s is probably a regular file.\n", *iter);
+      } else {
+        // Check if "reparse point" is a symbolic link.
+        WIN32_FIND_DATAA find_data;
+        HANDLE find_handle = FindFirstFileA(*iter, &find_data);
+        if (find_handle == INVALID_HANDLE_VALUE) {
+          printf("Unable to verify if %s is a symbolic link!\n", *iter);
+          continue;
+        }
+        printf("Filename in find data structure is \"%s\".\n",
+               find_data.cFileName);
+        if (find_data.dwReserved0 != IO_REPARSE_TAG_SYMLINK) {
+          puts("NOTICE: result of FindFirstFileA does not have symlink tag!");
+          // printf("%s is not a symbolic link but is a reparse point (tag is
+          // %#lx).\n", *iter, find_data.dwReserved0);
+          // FindClose(find_handle);
+          // continue;
+        }
+        FindClose(find_handle);
+        // Is a symbolic link.
+        printf("%s is a symbolic link.\n", *iter);
+        HANDLE symlink_handle =
+            CreateFileA(*iter, GENERIC_READ, FILE_SHARE_READ, NULL,
+                        OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, NULL);
+        if (symlink_handle == INVALID_HANDLE_VALUE) {
+          puts("Failed to get handle on symbolic link!");
+          continue;
+        }
+
+        REPARSE_GUID_DATA_BUFFER output;
+        printf("Size of REPARSE_GUID_DATA_BUFFER is %llu\n",
+               sizeof(REPARSE_GUID_DATA_BUFFER));
+        DWORD count;
+        OVERLAPPED overlapped;
+        if (DeviceIoControl(symlink_handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
+                            &output, sizeof(REPARSE_GUID_DATA_BUFFER), &count,
+                            &overlapped) == 0) {
+          DWORD error = GetLastError();
+          printf("Failed to get info on symlink handle (%lu %#lx)!\n", error,
+                 error);
+          CloseHandle(symlink_handle);
+          continue;
+        }
+        printf("link destination count is %lu.\n", count);
+        // printf("First bytes:\n %#hhx %#hhx %#hhx %#hhx %#hhx %#hhx %#hhx
+        // %#hhx\n", output[0], output[1], output[2], output[3], output[4],
+        // output[5], output[6], output[7]);
+
+        // printf("Link to: %s\n", output.SymbolicLinkReparseBuffer.);
+        CloseHandle(symlink_handle);
+      }
+    } else {
+      // Is a directory.
+      printf("%s is a directory.\n", *iter);
+    }
+  }
 #endif
 
   // Remove leading "./" entries from files_list.