Changeset e8ab32f in mainline


Ignore:
Timestamp:
2011-10-29T19:21:33Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c83a55c
Parents:
bf9da656 (diff), 1737bfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

Location:
uspace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/cp/cp.c

    rbf9da656 re8ab32f  
    3333#include <str.h>
    3434#include <fcntl.h>
     35#include <sys/stat.h>
     36#include <dirent.h>
    3537#include "config.h"
    3638#include "util.h"
     
    5557};
    5658
     59typedef enum {
     60        TYPE_NONE,
     61        TYPE_FILE,
     62        TYPE_DIR
     63} dentry_type_t;
     64
     65static int64_t copy_file(const char *src, const char *dest,
     66    size_t blen, int vb);
     67
     68/** Get the type of a directory entry.
     69 *
     70 * @param path  Path of the directory entry.
     71 *
     72 * @return TYPE_DIR if the dentry is a directory.
     73 * @return TYPE_FILE if the dentry is a file.
     74 * @return TYPE_NONE if the dentry does not exists.
     75 */
     76static dentry_type_t get_type(const char *path)
     77{
     78        struct stat s;
     79
     80        int r = stat(path, &s);
     81
     82        if (r)
     83                return TYPE_NONE;
     84        else if (s.is_directory)
     85                return TYPE_DIR;
     86        else if (s.is_file)
     87                return TYPE_FILE;
     88
     89        return TYPE_NONE;
     90}
     91
    5792static int strtoint(const char *s1)
    5893{
     
    67102        return (int) t1;
    68103}
     104
     105/** Get the last component of a path.
     106 *
     107 * e.g. /data/a  ---> a
     108 *
     109 * @param path  Pointer to the path.
     110 *
     111 * @return      Pointer to the last component or to the path itself.
     112 */
     113static char *get_last_path_component(char *path)
     114{
     115        char *ptr;
     116
     117        ptr = str_rchr(path, '/');
     118        if (!ptr)
     119                return path;
     120        else
     121                return ptr + 1;
     122}
     123
     124/** Merge two paths together.
     125 *
     126 * e.g. (path1 = /data/dir, path2 = a/b) --> /data/dir/a/b
     127 *
     128 * @param path1         Path to which path2 will be appended.
     129 * @param path1_size    Size of the path1 buffer.
     130 * @param path2         Path that will be appended to path1.
     131 */
     132static void merge_paths(char *path1, size_t path1_size, char *path2)
     133{
     134        const char *delim = "/";
     135
     136        str_rtrim(path1, '/');
     137        str_append(path1, path1_size, delim);
     138        str_append(path1, path1_size, path2);
     139}
     140
     141static int64_t do_copy(const char *src, const char *dest,
     142    size_t blen, int vb, int recursive, int force)
     143{
     144        int r = -1;
     145        char dest_path[PATH_MAX];
     146        char src_path[PATH_MAX];
     147        DIR *dir = NULL;
     148        struct dirent *dp;
     149
     150        dentry_type_t src_type = get_type(src);
     151        dentry_type_t dest_type = get_type(dest);
     152
     153        const size_t src_len = str_size(src);
     154
     155        if (src_type == TYPE_FILE) {
     156                char *src_fname;
     157
     158                /* Initialize the src_path with the src argument */
     159                str_cpy(src_path, src_len + 1, src);
     160                str_rtrim(src_path, '/');
     161               
     162                /* Get the last component name from the src path */
     163                src_fname = get_last_path_component(src_path);
     164               
     165                /* Initialize dest_path with the dest argument */
     166                str_cpy(dest_path, PATH_MAX, dest);
     167
     168                if (dest_type == TYPE_DIR) {
     169                        /* e.g. cp file_name /data */
     170                        /* e.g. cp file_name /data/ */
     171                       
     172                        /* dest is a directory,
     173                         * append the src filename to it.
     174                         */
     175                        merge_paths(dest_path, PATH_MAX, src_fname);
     176                        dest_type = get_type(dest_path);
     177                } else if (dest_type == TYPE_NONE) {
     178                        if (dest_path[str_size(dest_path) - 1] == '/') {
     179                                /* e.g. cp /textdemo /data/dirnotexists/ */
     180
     181                                printf("The dest directory %s does not exists",
     182                                    dest_path);
     183                                goto exit;
     184                        }
     185                }
     186
     187                if (dest_type == TYPE_DIR) {
     188                        printf("Cannot overwrite existing directory %s\n",
     189                            dest_path);
     190                        goto exit;
     191                } else if (dest_type == TYPE_FILE) {
     192                        /* e.g. cp file_name existing_file */
     193
     194                        /* dest already exists, if force is set we will
     195                         * try to remove it.
     196                         */
     197                        if (force) {
     198                                if (unlink(dest_path)) {
     199                                        printf("Unable to remove %s\n",
     200                                            dest_path);
     201                                        goto exit;
     202                                }
     203                        } else {
     204                                printf("file already exists: %s\n", dest_path);
     205                                goto exit;
     206                        }
     207                }
     208
     209                /* call copy_file and exit */
     210                r = (copy_file(src, dest_path, blen, vb) < 0);
     211
     212        } else if (src_type == TYPE_DIR) {
     213                /* e.g. cp -r /x/srcdir /y/destdir/ */
     214
     215                if (!recursive) {
     216                        printf("Cannot copy the %s directory without the "
     217                            "-r option\n", src);
     218                        goto exit;
     219                } else if (dest_type == TYPE_FILE) {
     220                        printf("Cannot overwrite a file with a directory\n");
     221                        goto exit;
     222                }
     223
     224                char *src_dirname;
     225
     226                /* Initialize src_path with the content of src */
     227                str_cpy(src_path, src_len + 1, src);
     228                str_rtrim(src_path, '/');
     229
     230                src_dirname = get_last_path_component(src_path);
     231
     232                str_cpy(dest_path, PATH_MAX, dest);
     233
     234                switch (dest_type) {
     235                case TYPE_DIR:
     236                        if (str_cmp(src_dirname, "..") &&
     237                            str_cmp(src_dirname, ".")) {
     238                                /* The last component of src_path is
     239                                 * not '.' or '..'
     240                                 */
     241                                merge_paths(dest_path, PATH_MAX, src_dirname);
     242
     243                                if (mkdir(dest_path, 0) == -1) {
     244                                        printf("Unable to create "
     245                                            "dest directory %s\n", dest_path);
     246                                        goto exit;
     247                                }
     248                        }
     249                        break;
     250                default:
     251                case TYPE_NONE:
     252                        /* dest does not exists, this means the user wants
     253                         * to specify the name of the destination directory
     254                         *
     255                         * e.g. cp -r /src /data/new_dir_src
     256                         */
     257                        if (mkdir(dest_path, 0)) {
     258                                printf("Unable to create "
     259                                    "dest directory %s\n", dest_path);
     260                                goto exit;
     261                        }
     262                        break;
     263                }
     264
     265                dir = opendir(src);
     266                if (!dir) {
     267                        /* Something strange is happening... */
     268                        printf("Unable to open src %s directory\n", src);
     269                        goto exit;
     270                }
     271
     272                /* Copy every single directory entry of src into the
     273                 * destination directory.
     274                 */
     275                while ((dp = readdir(dir))) {
     276                        struct stat src_s;
     277                        struct stat dest_s;
     278
     279                        char src_dent[PATH_MAX];
     280                        char dest_dent[PATH_MAX];
     281
     282                        str_cpy(src_dent, PATH_MAX, src);
     283                        merge_paths(src_dent, PATH_MAX, dp->d_name);
     284
     285                        str_cpy(dest_dent, PATH_MAX, dest_path);
     286                        merge_paths(dest_dent, PATH_MAX, dp->d_name);
     287
     288                        /* Check if we are copying a directory into itself */
     289                        stat(src_dent, &src_s);
     290                        stat(dest_path, &dest_s);
     291
     292                        if (dest_s.index == src_s.index &&
     293                            dest_s.fs_handle == src_s.fs_handle) {
     294                                printf("Cannot copy a directory "
     295                                    "into itself\n");
     296                                goto exit;
     297                        }
     298
     299                        if (vb)
     300                                printf("copy %s %s\n", src_dent, dest_dent);
     301
     302                        /* Recursively call do_copy() */
     303                        r = do_copy(src_dent, dest_dent, blen, vb, recursive,
     304                            force);
     305                        if (r)
     306                                goto exit;
     307
     308                }
     309        } else
     310                printf("Unable to open source file %s\n", src);
     311
     312exit:
     313        if (dir)
     314                closedir(dir);
     315        return r;
     316}
     317
    69318
    70319static int64_t copy_file(const char *src, const char *dest,
     
    127376        static char helpfmt[] =
    128377            "Usage:  %s [options] <source> <dest>\n"
    129             "Options: (* indicates not yet implemented)\n"
     378            "Options:\n"
    130379            "  -h, --help       A short option summary\n"
    131380            "  -v, --version    Print version information and exit\n"
    132             "* -V, --verbose    Be annoyingly noisy about what's being done\n"
    133             "* -f, --force      Do not complain when <dest> exists\n"
    134             "* -r, --recursive  Copy entire directories\n"
    135             "  -b, --buffer ## Set the read buffer size to ##\n"
    136             "Currently, %s is under development, some options may not work.\n";
     381            "  -V, --verbose    Be annoyingly noisy about what's being done\n"
     382            "  -f, --force      Do not complain when <dest> exists\n"
     383            "  -r, --recursive  Copy entire directories\n"
     384            "  -b, --buffer ## Set the read buffer size to ##\n";
    137385        if (level == HELP_SHORT) {
    138386                printf("`%s' copies files and directories\n", cmdname);
    139387        } else {
    140388                help_cmd_cp(HELP_SHORT);
    141                 printf(helpfmt, cmdname, cmdname);
     389                printf(helpfmt, cmdname);
    142390        }
    143391
     
    148396{
    149397        unsigned int argc, verbose = 0;
    150         int buffer = 0;
     398        int buffer = 0, recursive = 0;
     399        int force = 0;
    151400        int c, opt_ind;
    152401        int64_t ret;
     
    167416                        break;
    168417                case 'f':
     418                        force = 1;
    169419                        break;
    170420                case 'r':
     421                        recursive = 1;
    171422                        break;
    172423                case 'b':
     
    194445        }
    195446
    196         ret = copy_file(argv[optind], argv[optind + 1], buffer, verbose);
    197 
    198         if (verbose)
    199                 printf("%" PRId64 " bytes copied\n", ret);
    200 
    201         if (ret >= 0)
     447        ret = do_copy(argv[optind], argv[optind + 1], buffer, verbose,
     448            recursive, force);
     449
     450        if (ret == 0)
    202451                return CMD_SUCCESS;
    203452        else
  • uspace/lib/c/generic/str.c

    rbf9da656 re8ab32f  
    839839       
    840840        return NULL;
     841}
     842
     843/** Removes specified trailing characters from a string.
     844 *
     845 * @param str String to remove from.
     846 * @param ch  Character to remove.
     847 */
     848void str_rtrim(char *str, wchar_t ch)
     849{
     850        size_t off = 0;
     851        size_t pos = 0;
     852        wchar_t c;
     853        bool update_last_chunk = true;
     854        char *last_chunk = NULL;
     855
     856        while ((c = str_decode(str, &off, STR_NO_LIMIT))) {
     857                if (c != ch) {
     858                        update_last_chunk = true;
     859                        last_chunk = NULL;
     860                } else if (update_last_chunk) {
     861                        update_last_chunk = false;
     862                        last_chunk = (str + pos);
     863                }
     864                pos = off;
     865        }
     866
     867        if (last_chunk)
     868                *last_chunk = '\0';
     869}
     870
     871/** Removes specified leading characters from a string.
     872 *
     873 * @param str String to remove from.
     874 * @param ch  Character to remove.
     875 */
     876void str_ltrim(char *str, wchar_t ch)
     877{
     878        wchar_t acc;
     879        size_t off = 0;
     880        size_t pos = 0;
     881        size_t str_sz = str_size(str);
     882
     883        while ((acc = str_decode(str, &off, STR_NO_LIMIT)) != 0) {
     884                if (acc != ch)
     885                        break;
     886                else
     887                        pos = off;
     888        }
     889
     890        if (pos > 0) {
     891                memmove(str, &str[pos], str_sz - pos);
     892                pos = str_sz - pos;
     893                str[str_sz - pos] = '\0';
     894        }
    841895}
    842896
  • uspace/lib/c/include/str.h

    rbf9da656 re8ab32f  
    9191extern char *str_rchr(const char *str, wchar_t ch);
    9292
     93extern void str_rtrim(char *str, wchar_t ch);
     94extern void str_ltrim(char *str, wchar_t ch);
     95
    9396extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
    9497extern bool wstr_remove(wchar_t *str, size_t pos);
Note: See TracChangeset for help on using the changeset viewer.