~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/app/bdsh/cmds/modules/mkdir/mkdir.c

  • Committer: Vojtech Horky
  • Date: 2012-05-23 12:03:26 UTC
  • mfrom: (1443.1.19 misc)
  • mto: This revision was merged to the branch mainline in revision 1479.
  • Revision ID: vojtechhorky@users.sourceforge.net-20120523120326-jv50stjymxmh598s
Merge GSOC-originated patches 

Merge from lp:~vojtech-horky/helenos/misc.

The merge includes:
 * Switching to previous directory with `cd -' in Bdsh
 * Interactive mode for cp module in Bdsh
 * Implementation of sleep command
 * printf and echo for Bdsh
 * Rewrite of the mkdir module
 * Ctrl-arrow jumps over words in the editor
 * The scripts work with Python 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <getopt.h>
36
36
#include <stdarg.h>
37
37
#include <str.h>
 
38
#include <errno.h>
 
39
#include <str_error.h>
 
40
#include <vfs/vfs.h>
38
41
 
39
42
#include "config.h"
40
43
#include "errors.h"
82
85
 
83
86
/* This is kind of clunky, but effective for now */
84
87
static unsigned int
85
 
create_directory(const char *path, unsigned int p)
 
88
create_directory(const char *user_path, bool create_parents)
86
89
{
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))) {
 
90
        /* Ensure we would always work with absolute and canonified path. */
 
91
        char *path = absolutize(user_path, NULL);
 
92
        if (path == NULL) {
95
93
                cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
96
94
                return 1;
97
95
        }
98
96
 
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;
 
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
                }
143
107
        } else {
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 ++;
 
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)) {
169
114
                                break;
170
115
                        }
171
 
                }
172
 
                i++;
 
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
                }
173
160
        }
174
 
        goto finit;
175
161
 
176
 
finit:
177
 
        free(wdp);
178
 
        free(tmp);
 
162
leave:
 
163
        free(path);
179
164
        return ret;
180
165
}
181
166
 
182
167
int cmd_mkdir(char **argv)
183
168
{
184
 
        unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
185
 
        unsigned int verbose = 0;
 
169
        unsigned int argc, i, ret = 0;
 
170
        bool create_parents = false, follow = false, verbose = false;
186
171
        int c, opt_ind;
187
 
        char *cwd;
188
172
 
189
173
        argc = cli_count_args(argv);
190
174
 
192
176
                c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
193
177
                switch (c) {
194
178
                case 'p':
195
 
                        create_parents = 1;
 
179
                        create_parents = true;
196
180
                        break;
197
181
                case 'v':
198
 
                        verbose = 1;
 
182
                        verbose = true;
199
183
                        break;
200
184
                case 'h':
201
185
                        help_cmd_mkdir(HELP_LONG);
204
188
                        printf("%s\n", MKDIR_VERSION);
205
189
                        return CMD_SUCCESS;
206
190
                case 'f':
207
 
                        follow = 1;
 
191
                        follow = true;
208
192
                        break;
209
193
                case 'm':
210
194
                        printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
220
204
                return CMD_FAILURE;
221
205
        }
222
206
 
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
 
 
231
207
        for (i = optind; argv[i] != NULL; i++) {
232
 
                if (verbose == 1)
 
208
                if (verbose)
233
209
                        printf("%s: creating %s%s\n",
234
210
                                cmdname, argv[i],
235
211
                                create_parents ? " (and all parents)" : "");
236
212
                ret += create_directory(argv[i], create_parents);
237
213
        }
238
214
 
239
 
        if (follow == 0)
240
 
                chdir(cwd);
241
 
 
242
 
        free(cwd);
 
215
        if (follow && (argv[optind] != NULL)) {
 
216
                chdir(argv[optind]);
 
217
        }
243
218
 
244
219
        if (ret)
245
220
                return CMD_FAILURE;