Ignore:
File:
1 edited

Legend:

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

    r738b549 r36ab7c7  
    3636#include <stdarg.h>
    3737#include <str.h>
    38 #include <errno.h>
    39 #include <str_error.h>
    40 #include <vfs/vfs.h>
    4138
    4239#include "config.h"
     
    8683/* This is kind of clunky, but effective for now */
    8784static unsigned int
    88 create_directory(const char *user_path, bool create_parents)
     85create_directory(const char *path, unsigned int p)
    8986{
    90         /* Ensure we would always work with absolute and canonified path. */
    91         char *path = absolutize(user_path, NULL);
    92         if (path == NULL) {
     87        DIR *dirp;
     88        char *tmp = NULL, *buff = NULL, *wdp = NULL;
     89        char *dirs[255];
     90        unsigned int absolute = 0, i = 0, ret = 0;
     91
     92        /* Its a good idea to allocate path, plus we (may) need a copy of
     93         * path to tokenize if parents are specified */
     94        if (NULL == (tmp = str_dup(path))) {
    9395                cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
    9496                return 1;
    9597        }
    9698
    97         int rc;
    98         int ret = 0;
    99 
    100         if (!create_parents) {
    101                 rc = mkdir(path, 0);
    102                 if (rc != EOK) {
    103                         cli_error(CL_EFAIL, "%s: could not create %s (%s)",
    104                             cmdname, path, str_error(rc));
    105                         ret = 1;
    106                 }
     99        if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
     100                cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
     101                free(tmp);
     102                return 1;
     103        }
     104
     105        /* The only reason for wdp is to be (optionally) verbose */
     106        getcwd(wdp, PATH_MAX);
     107
     108        /* Typical use without specifying the creation of parents */
     109        if (p == 0) {
     110                dirp = opendir(tmp);
     111                if (dirp) {
     112                        cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
     113                        closedir(dirp);
     114                        goto finit;
     115                }
     116                if (-1 == (mkdir(tmp, 0))) {
     117                        cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
     118                        goto finit;
     119                }
     120        }
     121
     122        /* Parents need to be created, path has to be broken up */
     123
     124        /* See if path[0] is a slash, if so we have to remember to append it */
     125        if (tmp[0] == '/')
     126                absolute = 1;
     127
     128        /* TODO: Canonify the path prior to tokenizing it, see below */
     129        dirs[i] = strtok(tmp, "/");
     130        while (dirs[i] && i < 255)
     131                dirs[++i] = strtok(NULL, "/");
     132
     133        if (NULL == dirs[0])
     134                return 1;
     135
     136        if (absolute == 1) {
     137                asprintf(&buff, "/%s", dirs[0]);
     138                mkdir(buff, 0);
     139                chdir(buff);
     140                free(buff);
     141                getcwd(wdp, PATH_MAX);
     142                i = 1;
    107143        } else {
    108                 /* Create the parent directories as well. */
    109                 size_t off = 0;
    110                 while (1) {
    111                         size_t prev_off = off;
    112                         wchar_t cur_char = str_decode(path, &off, STR_NO_LIMIT);
    113                         if ((cur_char == 0) || (cur_char == U_SPECIAL)) {
     144                i = 0;
     145        }
     146
     147        while (dirs[i] != NULL) {
     148                /* Sometimes make or scripts conjoin odd paths. Account for something
     149                 * like this: ../../foo/bar/../foo/foofoo/./bar */
     150                if (!str_cmp(dirs[i], "..") || !str_cmp(dirs[i], ".")) {
     151                        if (0 != (chdir(dirs[i]))) {
     152                                cli_error(CL_EFAIL, "%s: impossible path: %s",
     153                                        cmdname, path);
     154                                ret ++;
     155                                goto finit;
     156                        }
     157                        getcwd(wdp, PATH_MAX);
     158                } else {
     159                        if (-1 == (mkdir(dirs[i], 0))) {
     160                                cli_error(CL_EFAIL,
     161                                        "%s: failed at %s/%s", wdp, dirs[i]);
     162                                ret ++;
     163                                goto finit;
     164                        }
     165                        if (0 != (chdir(dirs[i]))) {
     166                                cli_error(CL_EFAIL, "%s: failed creating %s\n",
     167                                        cmdname, dirs[i]);
     168                                ret ++;
    114169                                break;
    115170                        }
    116                         if (cur_char != '/') {
    117                                 continue;
    118                         }
    119                         if (prev_off == 0) {
    120                                 continue;
    121                         }
    122                         /*
    123                          * If we are here, it means that:
    124                          * - we found /
    125                          * - it is not the first / (no need to create root
    126                          *   directory)
    127                          *
    128                          * We would now overwrite the / with 0 to terminate the
    129                          * string (that shall be okay because we are
    130                          * overwriting at the beginning of UTF sequence).
    131                          * That would allow us to create the directories
    132                          * in correct nesting order.
    133                          *
    134                          * Notice that we ignore EEXIST errors as some of
    135                          * the parent directories may already exist.
    136                          */
    137                         char slash_char = path[prev_off];
    138                         path[prev_off] = 0;
    139                         rc = mkdir(path, 0);
    140                         if (rc == EEXIST) {
    141                                 rc = EOK;
    142                         }
    143 
    144                         if (rc != EOK) {
    145                                 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
    146                                     cmdname, path, str_error(rc));
    147                                 ret = 1;
    148                                 goto leave;
    149                         }
    150 
    151                         path[prev_off] = slash_char;
    152                 }
    153                 /* Create the final directory. */
    154                 rc = mkdir(path, 0);
    155                 if (rc != EOK) {
    156                         cli_error(CL_EFAIL, "%s: could not create %s (%s)",
    157                             cmdname, path, str_error(rc));
    158                         ret = 1;
    159                 }
    160         }
    161 
    162 leave:
    163         free(path);
     171                }
     172                i++;
     173        }
     174        goto finit;
     175
     176finit:
     177        free(wdp);
     178        free(tmp);
    164179        return ret;
    165180}
     
    167182int cmd_mkdir(char **argv)
    168183{
    169         unsigned int argc, i, ret = 0;
    170         bool create_parents = false, follow = false, verbose = false;
     184        unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
     185        unsigned int verbose = 0;
    171186        int c, opt_ind;
     187        char *cwd;
    172188
    173189        argc = cli_count_args(argv);
     
    177193                switch (c) {
    178194                case 'p':
    179                         create_parents = true;
     195                        create_parents = 1;
    180196                        break;
    181197                case 'v':
    182                         verbose = true;
     198                        verbose = 1;
    183199                        break;
    184200                case 'h':
     
    189205                        return CMD_SUCCESS;
    190206                case 'f':
    191                         follow = true;
     207                        follow = 1;
    192208                        break;
    193209                case 'm':
     
    205221        }
    206222
     223        if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
     224                cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
     225                return CMD_FAILURE;
     226        }
     227
     228        memset(cwd, 0, sizeof(cwd));
     229        getcwd(cwd, PATH_MAX);
     230
    207231        for (i = optind; argv[i] != NULL; i++) {
    208                 if (verbose)
     232                if (verbose == 1)
    209233                        printf("%s: creating %s%s\n",
    210234                                cmdname, argv[i],
     
    213237        }
    214238
    215         if (follow && (argv[optind] != NULL)) {
    216                 chdir(argv[optind]);
    217         }
     239        if (follow == 0)
     240                chdir(cwd);
     241
     242        free(cwd);
    218243
    219244        if (ret)
Note: See TracChangeset for help on using the changeset viewer.