From 3d164b948951514ee277a17fdf32f74dc409bf44 Mon Sep 17 00:00:00 2001
From: "tanguy.cavagna" <tanguy.cavagna@etu.hesge.ch>
Date: Mon, 27 Jun 2022 19:21:31 +0200
Subject: [PATCH] Added source folder creation in destination and list_dir
 after copy

---
 ultra-cp/ultra-cp.c | 104 +++++++++++++++++++++++++++++++++++---------
 ultra-cp/ultra-cp.h |   1 +
 2 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/ultra-cp/ultra-cp.c b/ultra-cp/ultra-cp.c
index 48e8603..cb618ec 100644
--- a/ultra-cp/ultra-cp.c
+++ b/ultra-cp/ultra-cp.c
@@ -19,6 +19,56 @@ int get_int_permissions(const char *path) {
     return entry_stat.st_mode;
 }
 
+/**
+ * @brief Copy a single file
+ *
+ * @param source Source file
+ * @param destination Destination file
+ */
+void copy_single_file(const char *source, const char *destination) {
+    int dst_path_lenght = 0;
+    char dst_path[PATH_MAX];
+
+    // Check if the basename already exists in the destination path
+    if (strstr(destination, basename((char *)source)) == NULL) {
+        dst_path_lenght = snprintf(dst_path, PATH_MAX, "%s/%s", destination,
+                                   basename((char *)source));
+    } else {
+        dst_path_lenght = strlen(destination);
+        strcpy(dst_path, destination);
+    }
+
+    // Path length exceeded clause
+    if (dst_path_lenght >= PATH_MAX) {
+        fprintf(stderr, "Path length has got too long.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    FILE *src_file, *dst_file;
+    src_file = fopen(source, "rb");
+    dst_file = fopen(dst_path, "wb");
+
+    size_t n;
+    char buff[BUFSIZ];
+    while ((n = fread(buff, 1, BUFSIZ, src_file)) != 0)
+        fwrite(buff, 1, n, dst_file);
+
+    fclose(src_file);
+    fclose(dst_file);
+
+    chmod(destination, get_int_permissions(source));
+}
+
+/**
+ * @brief Copy a directory
+ *
+ * @param source Source directory
+ * @param destination Destination directory
+ */
+void copy_directory(const char *source, const char *destination) {
+    mkdir(destination, get_int_permissions(source));
+}
+
 /**
  * @brief Copy a source entry to a destination location
  *
@@ -33,25 +83,12 @@ void copy_entry(struct dirent *entry, const char *source,
         return;
 
     // Entry is a file, copy it
-    if (entry->d_type == DT_REG) {
-        FILE *src_file, *dst_file;
-        src_file = fopen(source, "rb");
-        dst_file = fopen(destination, "wb");
-
-        size_t n;
-        char buff[BUFSIZ];
-        while ((n = fread(buff, 1, BUFSIZ, src_file)) != 0)
-            fwrite(buff, 1, n, dst_file);
-
-        fclose(src_file);
-        fclose(dst_file);
-
-        chmod(destination, get_int_permissions(source));
-    }
+    if (entry->d_type == DT_REG)
+        copy_single_file(source, destination);
 
     // Go deeper if directory
     if (entry->d_type == DT_DIR)
-        mkdir(destination, get_int_permissions(source));
+        copy_directory(source, destination);
 
     struct utimbuf new_time;
     new_time.actime = entry_stat.st_atim.tv_sec;
@@ -66,7 +103,7 @@ void copy_entry(struct dirent *entry, const char *source,
  * @param source Source directory
  * @param destination Destination directory
  */
-void copy_directory(const char *source, const char *destination) {
+void copy_directory_content(const char *source, const char *destination) {
     DIR *dir;
     struct dirent *entry;
 
@@ -87,7 +124,7 @@ void copy_directory(const char *source, const char *destination) {
         char dst_path[PATH_MAX];
         char src_path[PATH_MAX];
 
-        // Create the full source and destination paths
+        // Concatenate entry name to source and destination directory
         snprintf(src_path, PATH_MAX, "%s/%s", source, d_name);
         dst_path_lenght =
             snprintf(dst_path, PATH_MAX, "%s/%s", destination, d_name);
@@ -100,8 +137,9 @@ void copy_directory(const char *source, const char *destination) {
 
         copy_entry(entry, src_path, dst_path);
 
+        // Go deeper
         if (entry->d_type == DT_DIR)
-            copy_directory(src_path, dst_path);
+            copy_directory_content(src_path, dst_path);
     }
 
     closedir(dir);
@@ -203,6 +241,32 @@ void list_dir(const char *name) {
 void copy_files(const char **sources, const char *destination, uint8_t options,
                 int source_count) {
     for (int s = 0; s < source_count; s++) {
-        copy_directory(sources[s], destination);
+        struct stat source_stat;
+
+        if (stat(sources[s], &source_stat) < 0)
+            continue;
+
+        if (S_ISDIR(source_stat.st_mode)) {
+            int dst_path_lenght;
+            char dst_path[PATH_MAX];
+
+            // Create the full source and destination paths
+            dst_path_lenght =
+                snprintf(dst_path, PATH_MAX, "%s/%s", destination, basename((char *)sources[s]));
+
+            // Path length exceeded clause
+            if (dst_path_lenght >= PATH_MAX) {
+                fprintf(stderr, "Path length has got too long.\n");
+                exit(EXIT_FAILURE);
+            }
+
+            copy_directory(sources[s], dst_path);
+            copy_directory_content(sources[s], dst_path);
+        }
+
+        if (S_ISREG(source_stat.st_mode))
+            copy_single_file(sources[s], destination);
     }
+
+    list_dir(destination);
 }
diff --git a/ultra-cp/ultra-cp.h b/ultra-cp/ultra-cp.h
index 28e2c44..8f9ea90 100644
--- a/ultra-cp/ultra-cp.h
+++ b/ultra-cp/ultra-cp.h
@@ -2,6 +2,7 @@
 #define ULTRA_CP_
 
 #include <dirent.h>
+#include <libgen.h>
 #include <linux/limits.h>
 #include <stdint.h>
 #include <stdio.h>
-- 
GitLab