From 8133bc4ed769b7e0795ac5bbc86cd210247e4540 Mon Sep 17 00:00:00 2001 From: "tanguy.cavagna" <tanguy.cavagna@etu.hesge.ch> Date: Mon, 27 Jun 2022 17:43:25 +0200 Subject: [PATCH] Can copy directory content except links and date attributes --- main.c | 5 +- ultra-cp/ultra-cp.c | 129 +++++++++++++++++++++++++++++++++++++------- ultra-cp/ultra-cp.h | 12 +++++ 3 files changed, 124 insertions(+), 22 deletions(-) diff --git a/main.c b/main.c index ab9e9bc..c182b2c 100644 --- a/main.c +++ b/main.c @@ -26,14 +26,13 @@ int main(int argc, char **argv) { source_paths[i][strlen(source_paths[i]) - 1] = '\0'; } - // TODO: Copy files form sources to destination + // Copy content + copy_files((const char **)source_paths, destination_path, opt, source_count); // Free sources for (int i = 0; i < source_count; i++) free(source_paths[i]); free(source_paths); - list_dir("/home/toguy/Documents/source"); - return EXIT_SUCCESS; } diff --git a/ultra-cp/ultra-cp.c b/ultra-cp/ultra-cp.c index 4e0e8e1..d8a31d8 100644 --- a/ultra-cp/ultra-cp.c +++ b/ultra-cp/ultra-cp.c @@ -1,34 +1,118 @@ #include "ultra-cp.h" -#include <stdlib.h> -#include <sys/stat.h> -#include <time.h> //==================== // PRIVATE //==================== +/** + * @brief Get the entry permissions as int + * + * @param path Entry path + * + * @returns Permissions + */ +int get_int_permissions(const char *path) { + struct stat entry_stat; + + if (stat(path, &entry_stat) < 0) + return -1; + + return entry_stat.st_mode; +} + +/** + * @brief Copy a source entry to a destination location + * + * @param source Source entry + * @param destination Destination location + */ +void copy_entry(struct dirent *entry, const char *source, + const char *destination) { + // 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)); + } + + // Go deeper if directory + if (entry->d_type == DT_DIR) + mkdir(destination, get_int_permissions(source)); +} + +/** + * @brief Copy the content of a directory to a destination + * + * @param source Source directory + * @param destination Destination directory + */ +void copy_directory(const char *source, const char *destination) { + DIR *dir; + struct dirent *entry; + + // Cannot open dir + if (!(dir = opendir(source))) + return; + + // Loop through all entries of the given directory + while ((entry = readdir(dir)) != NULL) { + const char *d_name; + d_name = entry->d_name; + + // Skip "." and ".." + if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) + continue; + + int dst_path_lenght; + char dst_path[PATH_MAX]; + char src_path[PATH_MAX]; + + // Create the full source and destination paths + snprintf(src_path, PATH_MAX, "%s/%s", source, d_name); + dst_path_lenght = + snprintf(dst_path, PATH_MAX, "%s/%s", destination, d_name); + + // Path length exceeded clause + if (dst_path_lenght >= PATH_MAX) { + fprintf(stderr, "Path length has got too long.\n"); + exit(EXIT_FAILURE); + } + + copy_entry(entry, src_path, dst_path); + + if (entry->d_type == DT_DIR) + copy_directory(src_path, dst_path); + } + + closedir(dir); +} //==================== // PUBLIC //==================== char *get_permissions(const char *name) { - struct stat file_stat; - - // Read stats - if (stat(name, &file_stat) < 0) - return NULL; - + int perms = get_int_permissions(name); char *permissions = calloc(10, sizeof(char)); - permissions[0] = S_ISDIR(file_stat.st_mode) ? 'd' : S_ISLNK(file_stat.st_mode) ? 'l' : '-'; - permissions[1] = (file_stat.st_mode & S_IRUSR) ? 'r' : '-'; - permissions[2] = (file_stat.st_mode & S_IWUSR) ? 'w' : '-'; - permissions[3] = (file_stat.st_mode & S_IXUSR) ? 'x' : '-'; - permissions[4] = (file_stat.st_mode & S_IRGRP) ? 'r' : '-'; - permissions[5] = (file_stat.st_mode & S_IWGRP) ? 'w' : '-'; - permissions[6] = (file_stat.st_mode & S_IXGRP) ? 'x' : '-'; - permissions[7] = (file_stat.st_mode & S_IROTH) ? 'r' : '-'; - permissions[8] = (file_stat.st_mode & S_IWOTH) ? 'w' : '-'; - permissions[9] = (file_stat.st_mode & S_IXOTH) ? 'x' : '-'; + permissions[0] = S_ISDIR(perms) ? 'd' : S_ISLNK(perms) ? 'l' : '-'; + permissions[1] = (perms & S_IRUSR) ? 'r' : '-'; + permissions[2] = (perms & S_IWUSR) ? 'w' : '-'; + permissions[3] = (perms & S_IXUSR) ? 'x' : '-'; + permissions[4] = (perms & S_IRGRP) ? 'r' : '-'; + permissions[5] = (perms & S_IWGRP) ? 'w' : '-'; + permissions[6] = (perms & S_IXGRP) ? 'x' : '-'; + permissions[7] = (perms & S_IROTH) ? 'r' : '-'; + permissions[8] = (perms & S_IWOTH) ? 'w' : '-'; + permissions[9] = (perms & S_IXOTH) ? 'x' : '-'; return permissions; } @@ -104,3 +188,10 @@ void list_dir(const char *name) { closedir(dir); } + +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); + } +} diff --git a/ultra-cp/ultra-cp.h b/ultra-cp/ultra-cp.h index b7ffca4..8f3878a 100644 --- a/ultra-cp/ultra-cp.h +++ b/ultra-cp/ultra-cp.h @@ -2,6 +2,8 @@ #define ULTRA_CP_ #include <dirent.h> +#include <linux/limits.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -44,4 +46,14 @@ char *get_date(const char *name); */ void list_dir(const char *name); +/** + * @brief Copy all content from sources to destination + * + * @param sources List of all sources to copy + * @param destination Destination for the content + * @param options Copy options + * @param source_count Source count + */ +void copy_files(const char **sources, const char *destination, uint8_t options, + int source_count); #endif // !ULTRA_CP_ -- GitLab