]> git.seodisparate.com - c_simple_http/commitdiff
Impl. copying over "static-dir" files on generate
authorStephen Seo <seo.disparate@gmail.com>
Mon, 11 Nov 2024 06:09:12 +0000 (15:09 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 11 Nov 2024 06:09:12 +0000 (15:09 +0900)
src/helpers.c
src/helpers.h
src/main.c
src/static.c
src/static.h

index 6a9bbc296be181bf9d2e8a0a70599736ca8fe667..efad799f395ca15592503c698120757784cfdf8a 100644 (file)
@@ -24,7 +24,6 @@
 // libc includes.
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <dirent.h>
 #include <errno.h>
 #include <libgen.h>
 
@@ -258,4 +257,11 @@ int c_simple_http_helper_mkdir_tree(const char *path) {
   }
 }
 
+void c_simple_http_cleanup_DIR(DIR **fd) {
+  if (fd && *fd) {
+    closedir(*fd);
+    *fd = NULL;
+  }
+}
+
 // vim: et ts=2 sts=2 sw=2
index a428388e48fe55dbb75b6824d49901de5e61b214..0039f635b70bf6c67ce3e146662729e3409556e0 100644 (file)
@@ -23,6 +23,7 @@
 
 // libc includes.
 #include <time.h>
+#include <dirent.h>
 
 // Local includes.
 #include "config.h"
@@ -77,6 +78,8 @@ char *c_simple_http_helper_unescape_uri(const char *uri);
 /// Other return values are errors.
 int c_simple_http_helper_mkdir_tree(const char *dirpath);
 
+void c_simple_http_cleanup_DIR(DIR **fd);
+
 #endif
 
 // vim: et ts=2 sts=2 sw=2
index 988f67af4cb5a358a4a1d91d9b9b4d721848c973..601a5a09148dc979f559080e7e5e0bc073b91f51 100644 (file)
@@ -351,6 +351,7 @@ int main(int argc, char **argv) {
     ConnectionContext ctx;
     ctx.args = &args;
     ctx.parsed = &parsed_config;
+    printf("Generating html files to \"%s\"...\n", args.generate_dir);
     if (simple_archiver_hash_map_iter(parsed_config.paths,
                                       c_simple_http_generate_paths_fn,
                                       &ctx)) {
@@ -358,6 +359,17 @@ int main(int argc, char **argv) {
       return 1;
     }
     puts("Finished generating.");
+    if (args.static_dir) {
+      puts("Static dir option specified, copying over static dir entries...");
+      if (c_simple_http_static_copy_over_dir(args.static_dir,
+                                             args.generate_dir,
+                                             (args.flags & 4) != 0 ? 1 : 0)
+          != 0) {
+        fprintf(stderr, "ERROR during static-dir-entires copying!\n");
+        return 1;
+      }
+      puts("Finished copying over static-dir files.");
+    }
     return 0;
   }
 
index fc682e06d3e98622c5d6c57bd064ac4284a44c2a..435409ae4ab858b1b252e195c8279a6a7048e45d 100644 (file)
 #include <unistd.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <libgen.h>
 
 // Third party includes.
+#include "SimpleArchiver/src/data_structures/linked_list.h"
 #include "SimpleArchiver/src/helpers.h"
 
+// Local includes.
+#include "helpers.h"
+
 char **environ;
 
 void internal_fd_cleanup_helper(int *fd) {
@@ -180,7 +187,9 @@ C_SIMPLE_HTTP_StaticFileInfo c_simple_http_get_file(
 
   if (fd == NULL) {
     fprintf(
-      stderr, "WARNING Failed to open path \"%s\" in static dir!\n", path + idx);
+      stderr,
+      "WARNING Failed to open path \"%s\" in static dir!\n",
+      path + idx);
     file_info.result = STATIC_FILE_RESULT_404NotFound;
     return file_info;
   }
@@ -331,4 +340,161 @@ int c_simple_http_static_validate_path(const char *path) {
   return 0;
 }
 
+int c_simple_http_static_copy_over_dir(const char *from,
+                                       const char *to,
+                                       uint_fast8_t overwrite_enabled) {
+  __attribute__((cleanup(c_simple_http_cleanup_DIR)))
+  DIR *from_fd = opendir(from);
+  if (!from_fd) {
+    fprintf(stderr, "ERROR Failed to open directory \"%s\"!\n", from);
+    return 1;
+  }
+
+  const unsigned long from_len = strlen(from);
+  const unsigned long to_len = strlen(to);
+
+  struct dirent *dir_entry = NULL;
+  do {
+    dir_entry = readdir(from_fd);
+    if (!dir_entry) {
+      break;
+    } else if (strcmp(dir_entry->d_name, ".") == 0
+        || strcmp(dir_entry->d_name, "..") == 0) {
+      continue;
+    } else if (dir_entry->d_type == DT_DIR) {
+      // Dir entry is a directory.
+      __attribute__((cleanup(simple_archiver_list_free)))
+      SDArchiverLinkedList *string_parts = simple_archiver_list_init();
+      c_simple_http_add_string_part(string_parts, from, 0);
+      if (from_len > 0 && from[from_len - 1] != '/') {
+        c_simple_http_add_string_part(string_parts, "/", 0);
+      }
+      c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+      char *combined_from = c_simple_http_combine_string_parts(string_parts);
+
+      simple_archiver_list_free(&string_parts);
+      string_parts = simple_archiver_list_init();
+      c_simple_http_add_string_part(string_parts, to, 0);
+      if (to_len > 0 && to[to_len - 1] != '/') {
+        c_simple_http_add_string_part(string_parts, "/", 0);
+      }
+      c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+      char *combined_to = c_simple_http_combine_string_parts(string_parts);
+
+      int ret = c_simple_http_static_copy_over_dir(combined_from,
+                                                   combined_to,
+                                                   overwrite_enabled);
+      if (ret != 0) {
+        return ret;
+      }
+    } else if (dir_entry->d_type == DT_REG) {
+      // Dir entry is a file.
+      __attribute__((cleanup(simple_archiver_list_free)))
+      SDArchiverLinkedList *string_parts = simple_archiver_list_init();
+      c_simple_http_add_string_part(string_parts, from, 0);
+      if (from_len > 0 && from[from_len - 1] != '/') {
+        c_simple_http_add_string_part(string_parts, "/", 0);
+      }
+      c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+      char *combined_from = c_simple_http_combine_string_parts(string_parts);
+
+      simple_archiver_list_free(&string_parts);
+      string_parts = simple_archiver_list_init();
+      c_simple_http_add_string_part(string_parts, to, 0);
+      if (to_len > 0 && to[to_len - 1] != '/') {
+        c_simple_http_add_string_part(string_parts, "/", 0);
+      }
+      c_simple_http_add_string_part(string_parts, dir_entry->d_name, 0);
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+      char *combined_to = c_simple_http_combine_string_parts(string_parts);
+
+      if (!overwrite_enabled) {
+        __attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
+        FILE *fd = fopen(combined_to, "rb");
+        if (fd) {
+          fprintf(
+            stderr,
+            "WARNING \"%s\" already exists and --generate-enable-overwrite not "
+              "specified, skipping!\n",
+            combined_to);
+          continue;
+        }
+      }
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
+      char *combined_to_dup = strdup(combined_to);
+      char *combined_to_dirname = dirname(combined_to_dup);
+
+      int ret = c_simple_http_helper_mkdir_tree(combined_to_dirname);
+      if (ret != 0 && ret != 1) {
+        fprintf(stderr,
+                "ERROR Failed to create directory \"%s\"!\n",
+                combined_to_dirname);
+        return 1;
+      }
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
+      FILE *from_file_fd = fopen(combined_from, "rb");
+      if (!from_file_fd) {
+        fprintf(stderr,
+                "ERROR Failed to open file \"%s\" for reading!\n",
+                combined_from);
+        return 1;
+      }
+
+      __attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
+      FILE *to_file_fd = fopen(combined_to, "wb");
+      if (!to_file_fd) {
+        fprintf(stderr,
+                "ERROR Failed to open file \"%s\" for writing!\n",
+                combined_to);
+        return 1;
+      }
+
+      char *buf[1024];
+      size_t fread_ret;
+      unsigned long fwrite_ret;
+      while (!feof(from_file_fd)
+          && !ferror(from_file_fd)
+          && !ferror(to_file_fd)) {
+        fread_ret = fread(buf, 1, 1024, from_file_fd);
+        if (fread_ret > 0) {
+          fwrite_ret = fwrite(buf, 1, fread_ret, to_file_fd);
+          if (fwrite_ret < fread_ret) {
+            fprintf(
+              stderr,
+              "ERROR Writing to file \"%s\" (not all bytes written)!\n",
+              combined_to);
+            return 1;
+          }
+        }
+      }
+
+      if (ferror(from_file_fd)) {
+        fprintf(stderr, "ERROR Reading from file \"%s\"!\n", combined_from);
+        return 1;
+      } else if (ferror(to_file_fd)) {
+        fprintf(stderr, "ERROR Writing to file \"%s\"!\n", combined_to);
+        return 1;
+      }
+
+      printf("%s -> %s\n", combined_from, combined_to);
+    } else {
+      fprintf(stderr,
+              "WARNING Non-dir and non-file \"%s/%s\", skipping...\n",
+              from,
+              dir_entry->d_name);
+    }
+  } while (dir_entry != NULL);
+
+  return 0;
+}
+
 // vim: et ts=2 sts=2 sw=2
index d36b1bc131430d52c041116a066edadfc215dc27..375544c47ab522b46f5bfa88c50895a9f953fa60 100644 (file)
@@ -51,6 +51,11 @@ C_SIMPLE_HTTP_StaticFileInfo c_simple_http_get_file(
 /// Returns zero if OK.
 int c_simple_http_static_validate_path(const char *path);
 
+/// Copies all files in "from" into "to". Returns non-zero on failure.
+int c_simple_http_static_copy_over_dir(const char *from,
+                                       const char *to,
+                                       uint_fast8_t overwrite_enabled);
+
 #endif
 
 // vim: et ts=2 sts=2 sw=2