[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [tyndur-devel] [PATCH] Re: +cp: -r, -v und -t hinzugefügt



So, hier die neue Variante
From 8c65c7f908b7bc943e46378e92b22f737f6dbc10 Mon Sep 17 00:00:00 2001
From: Alexander Siol <alex@xxxxxxxxxx>
Date: Tue, 7 Jul 2009 21:59:18 +0200
Subject: [PATCH] + cp: -r, -v und -t hinzugefügt
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

---
 trunk/src/modules/c/shell/cmds/cp.c |  203 ++++++++++++++++++++++++++++++-----
 1 files changed, 177 insertions(+), 26 deletions(-)

diff --git a/trunk/src/modules/c/shell/cmds/cp.c b/trunk/src/modules/c/shell/cmds/cp.c
index 2c1ada5..09ffb1a 100644
--- a/trunk/src/modules/c/shell/cmds/cp.c
+++ b/trunk/src/modules/c/shell/cmds/cp.c
@@ -37,15 +37,21 @@
 #include <dir.h>
 #include <io.h>
 
-#include "types.h"
-#include "stdlib.h"
-#include "stdio.h"
-#include "unistd.h"
+#include <types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <collections.h>
 #include <lost/config.h>
 
 #define BUFFER_SIZE 4096
 
+static int verbosity = 0;
+
 void cp_display_usage(void);
+int cp_file(char* src_path, char* dst_path);
+int cp_recursive(char* src_path, char* dst_path);
 
 #ifdef CONFIG_SHELL_BUILTIN_ONLY
     int shell_command_cp(int argc, char* argv[], const char* args)
@@ -53,21 +59,172 @@ void cp_display_usage(void);
     int main(int argc, char* argv[])
 #endif
 {
-    if (argc != 3) {
+    static const struct option long_options[] =
+    {
+        { "target", required_argument, 0, 't' },
+        { "recursive", no_argument,    0, 'r' },
+        { "verbose", no_argument,      0, 'v' },
+        { "help", no_argument,         0, 'h' },
+        { 0, 0, 0, 0 }
+    };
+
+    optind = 0;
+    verbosity = 0;
+
+    char* targetpath = NULL;
+    list_t* sources = list_create();
+
+    int index = -1;
+    int result;
+
+    int recursive = 0;
+
+    while (optind < argc) {
+        result = getopt_long(argc, argv, "vrt:h", long_options, &index);
+        if (result == -1) {
+            break;
+        }
+        switch (result) {
+            case 't':
+                targetpath = optarg;
+                break;
+            case 'r':
+                recursive = 1;
+                break;
+            case 'v':
+                verbosity++;
+                break;
+            case 'h':
+                cp_display_usage();
+                return EXIT_SUCCESS;
+            default:
+                break;
+        }
+    }
+
+    while (optind < argc) {
+        list_push(sources, argv[optind++]);
+    }
+
+    // Falls kein Target-Parameter gegeben ist, letztes Element des Listings.
+    if (targetpath == NULL) {
+        targetpath = (char*)list_pop(sources);
+    }
+
+    if (targetpath == NULL || list_size(sources) == 0) {
         cp_display_usage();
+        goto bad_exit;
+    }
+
+    if ( (list_size(sources) > 1) && (!is_directory(targetpath)) ) {
+        fprintf(stderr, 
+            "Fehler: Mehrere Quellen, aber Ziel ist kein Verzeichnis!\n");
+        goto bad_exit;
+    }
+
+    char* src_path = NULL;
+    while ( (src_path = (char*)list_pop(sources)) ) {
+        if (is_directory(src_path)) {
+            if (recursive) {
+                cp_recursive(src_path, targetpath);
+            } else {
+                fprintf(stderr, "%s übersprungen (suchen Sie 'cp -r' ?)\n", src_path);
+                goto bad_exit;
+            }
+        } else {
+            result = cp_file(src_path, targetpath);
+            if (result == -1) {
+                fprintf(stderr, "Konnte die Quelldatei nicht öffnen\n Pfad: %s\n",
+                    src_path);
+                goto bad_exit;
+            }  else if (result == -2) {
+                fprintf(stderr, "Konnte die Zieldatei nicht öffnen\n Pfad: %s\n",
+                    targetpath);
+                goto bad_exit;
+            }
+        }
+    }
+
+    list_destroy(sources);
+    return EXIT_SUCCESS;
+
+    bad_exit:
+    list_destroy(sources);
+    return EXIT_FAILURE;
+}
+
+void cp_display_usage()
+{
+    printf("Aufruf: cp [OPTIONEN] <Quelle> <Ziel>\n"
+           "  oder: cp [OPTIONEN] <Quelle> ... <Verzeichniss>\n"
+           "  oder: cp [OPTIONEN] -t <Verzeichniss> <Quelle> ...\n"
+           "\n"
+           "Optionen:\n"
+           "    -v --verbose     durchgeführte Tätigkeiten erklären\n"
+           "    -r --recursive   Verzeichnisse rekursiv kopieren\n"
+           "    -h --help        diese Hilfe anzeigen\n");
+}
+
+int cp_recursive(char* src_path, char* dst_path)
+{
+    int length = -1;
+    if (is_directory(dst_path)) {
+        length = asprintf(&dst_path, "%s%s", dst_path, io_split_filename(src_path));
+        if (length < 0) {
+            // src_path hilft hier nicht, dst_path ist per asprintf undefiniert, 
+            // sollte also nicht verwendet werden. Wahrscheinlichste Fehlerursache
+            // bleibt aber OOM, ergo sind beide Pfade nicht hilfreich.
+            printf("Fehler beim Setzen des Zielpfades!\n");
+            return -1;
+        }
+    } 
+    if (!directory_create(dst_path)) {
+        fprintf(stderr, "Fehler: Pfad %s konnte nicht angelegt werden!\n", dst_path);
+        fprintf(stderr, "        %s übersprungen.\n", src_path);
         return -1;
     }
+    if (verbosity > 0) {
+        printf("'%s' -> '%s'\n", src_path, dst_path);
+    }
     
-    char* src_path = argv[1];
-    char* dst_path = argv[2];
+    io_resource_t* dir_res = directory_open(src_path);
+    char* full_src_path = NULL;
+    char* full_dst_path = NULL;
+    if (dir_res != NULL) {
+        io_direntry_t* direntry;
+        while ((direntry = directory_read(dir_res))) {
+            asprintf(&full_src_path, "%s/%s", src_path, direntry->name);
+            asprintf(&full_dst_path, "%s/%s", dst_path, direntry->name);
+            if (direntry->type == IO_DIRENTRY_FILE) {
+                cp_file(full_src_path, full_dst_path);
+            } else {
+                cp_recursive(full_src_path, full_dst_path);
+            }
+            free(full_src_path);
+            free(full_dst_path);
+            free(direntry);
+        }
+        directory_close(dir_res);
+        if (length >= 0) {
+            free(dst_path);
+        }
+        return 1;
+    }
+    else {
+        if (length >= 0) {
+            free(dst_path);
+        }
+        return -1;
+    }
+}
 
+int cp_file(char* src_path, char* dst_path) {
     FILE* src = fopen(src_path, "r");
     if (src == NULL) {
-        fprintf(stderr, "Konnte die Quelldatei nicht oeffnen\n");
-        return EXIT_FAILURE;        
+        return -1;
     }
 
-    FILE* dst;
+    FILE* dst = NULL;
     if (is_directory(dst_path)) {
         char* filename = io_split_filename(src_path);
         size_t length = strlen(filename) + strlen(dst_path) + 1;
@@ -78,20 +235,20 @@ void cp_display_usage(void);
         dst_file_path[strlen(dst_file_path)] = '/';
         strcat(dst_file_path, filename);
         dst_file_path[length] = '\0';
-
-        dst = fopen(dst_file_path, "w");
-    } else {
-        dst = fopen(dst_path, "w");
+        dst_path = dst_file_path;
     }
+    dst = fopen(dst_path, "w");
 
     if (dst == NULL) {
-        fprintf(stderr, "Konnte die Zieldatei nicht oeffnen\n");
-        fclose(src);
-        return EXIT_FAILURE;        
+        return -2;
     }
 
     uint8_t buffer[BUFFER_SIZE];
-        
+
+    if (verbosity > 0) {
+        printf("'%s' -> '%s'\n", src_path, dst_path);
+    }
+
     while (!feof(src)) { 
         size_t length = fread(buffer, BUFFER_SIZE, 1, src);
         if (length == 0) {
@@ -100,18 +257,12 @@ void cp_display_usage(void);
             fclose(dst);
             return EXIT_FAILURE;
         }
-        
+
         fwrite(buffer, length, 1, dst);
     }
 
     fclose(src);
     fclose(dst);
 
-    return EXIT_SUCCESS;
-}
-
-void cp_display_usage()
-{
-    puts("\nAufruf: cp <Quelle> <Ziel>");
+    return 1;
 }
-
-- 
1.6.0.4

Attachment: signature.asc
Description: Digital signature