~galfy/helenos/bird-port-mainline

« back to all changes in this revision

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

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
 
2
 * All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
7
 * Redistributions of source code must retain the above copyright notice, this
 
8
 * list of conditions and the following disclaimer.
 
9
 *
 
10
 * Redistributions in binary form must reproduce the above copyright notice,
 
11
 * this list of conditions and the following disclaimer in the documentation
 
12
 * and/or other materials provided with the distribution.
 
13
 *
 
14
 * Neither the name of the original program's authors nor the names of its
 
15
 * contributors may be used to endorse or promote products derived from this
 
16
 * software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
28
 * POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <dirent.h>
 
35
#include <fcntl.h>
 
36
#include <sys/types.h>
 
37
#include <sys/stat.h>
 
38
#include <getopt.h>
 
39
#include <stdarg.h>
 
40
#include <string.h>
 
41
 
 
42
#include "config.h"
 
43
#include "errors.h"
 
44
#include "util.h"
 
45
#include "entry.h"
 
46
#include "mkdir.h"
 
47
#include "cmds.h"
 
48
 
 
49
#define MKDIR_VERSION "0.0.1"
 
50
 
 
51
static char *cmdname = "mkdir";
 
52
 
 
53
static struct option const long_options[] = {
 
54
        {"parents", no_argument, 0, 'p'},
 
55
        {"verbose", no_argument, 0, 'v'},
 
56
        {"mode", required_argument, 0, 'm'},
 
57
        {"help", no_argument, 0, 'h'},
 
58
        {"version", no_argument, 0, 'V'},
 
59
        {"follow", no_argument, 0, 'f'},
 
60
        {0, 0, 0, 0}
 
61
};
 
62
 
 
63
 
 
64
void help_cmd_mkdir(unsigned int level)
 
65
{
 
66
        if (level == HELP_SHORT) {
 
67
                printf("`%s' creates a new directory\n", cmdname);
 
68
        } else {
 
69
                help_cmd_mkdir(HELP_SHORT);
 
70
                printf(
 
71
                "Usage:  %s [options] <path>\n"
 
72
                "Options:\n"
 
73
                "  -h, --help       A short option summary\n"
 
74
                "  -V, --version    Print version information and exit\n"
 
75
                "  -p, --parents    Create needed parents for <path>\n"
 
76
                "  -m, --mode       Set permissions to [mode] (UNUSED)\n"
 
77
                "  -v, --verbose    Be extremely noisy about what is happening\n"
 
78
                "  -f, --follow     Go to the new directory once created\n"
 
79
                "Currently, %s is under development, some options don't work.\n",
 
80
                cmdname, cmdname);
 
81
        }
 
82
 
 
83
        return;
 
84
}
 
85
 
 
86
/* This is kind of clunky, but effective for now */
 
87
static unsigned int
 
88
create_directory(const char *path, unsigned int p)
 
89
{
 
90
        DIR *dirp;
 
91
        char *tmp = NULL, *buff = NULL, *wdp = NULL;
 
92
        char *dirs[255];
 
93
        unsigned int absolute = 0, i = 0, ret = 0;
 
94
 
 
95
        /* Its a good idea to allocate path, plus we (may) need a copy of
 
96
         * path to tokenize if parents are specified */
 
97
        if (NULL == (tmp = str_dup(path))) {
 
98
                cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
 
99
                return 1;
 
100
        }
 
101
 
 
102
        if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
 
103
                cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
 
104
                free(tmp);
 
105
                return 1;
 
106
        }
 
107
 
 
108
        /* The only reason for wdp is to be (optionally) verbose */
 
109
        getcwd(wdp, PATH_MAX);
 
110
 
 
111
        /* Typical use without specifying the creation of parents */
 
112
        if (p == 0) {
 
113
                dirp = opendir(tmp);
 
114
                if (dirp) {
 
115
                        cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
 
116
                        closedir(dirp);
 
117
                        goto finit;
 
118
                }
 
119
                if (-1 == (mkdir(tmp, 0))) {
 
120
                        cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
 
121
                        goto finit;
 
122
                }
 
123
        }
 
124
 
 
125
        /* Parents need to be created, path has to be broken up */
 
126
 
 
127
        /* See if path[0] is a slash, if so we have to remember to append it */
 
128
        if (tmp[0] == '/')
 
129
                absolute = 1;
 
130
 
 
131
        /* TODO: Canonify the path prior to tokenizing it, see below */
 
132
        dirs[i] = strtok(tmp, "/");
 
133
        while (dirs[i] && i < 255)
 
134
                dirs[++i] = strtok(NULL, "/");
 
135
 
 
136
        if (NULL == dirs[0])
 
137
                return 1;
 
138
 
 
139
        if (absolute == 1) {
 
140
                asprintf(&buff, "/%s", dirs[0]);
 
141
                mkdir(buff, 0);
 
142
                chdir(buff);
 
143
                free(buff);
 
144
                getcwd(wdp, PATH_MAX);
 
145
                i = 1;
 
146
        } else {
 
147
                i = 0;
 
148
        }
 
149
 
 
150
        while (dirs[i] != NULL) {
 
151
                /* Sometimes make or scripts conjoin odd paths. Account for something
 
152
                 * like this: ../../foo/bar/../foo/foofoo/./bar */
 
153
                if (!str_cmp(dirs[i], "..") || !str_cmp(dirs[i], ".")) {
 
154
                        if (0 != (chdir(dirs[i]))) {
 
155
                                cli_error(CL_EFAIL, "%s: impossible path: %s",
 
156
                                        cmdname, path);
 
157
                                ret ++;
 
158
                                goto finit;
 
159
                        }
 
160
                        getcwd(wdp, PATH_MAX);
 
161
                } else {
 
162
                        if (-1 == (mkdir(dirs[i], 0))) {
 
163
                                cli_error(CL_EFAIL,
 
164
                                        "%s: failed at %s/%s", wdp, dirs[i]);
 
165
                                ret ++;
 
166
                                goto finit;
 
167
                        }
 
168
                        if (0 != (chdir(dirs[i]))) {
 
169
                                cli_error(CL_EFAIL, "%s: failed creating %s\n",
 
170
                                        cmdname, dirs[i]);
 
171
                                ret ++;
 
172
                                break;
 
173
                        }
 
174
                }
 
175
                i++;
 
176
        }
 
177
        goto finit;
 
178
 
 
179
finit:
 
180
        free(wdp);
 
181
        free(tmp);
 
182
        return ret;
 
183
}
 
184
 
 
185
int cmd_mkdir(char **argv)
 
186
{
 
187
        unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
 
188
        unsigned int verbose = 0;
 
189
        int c, opt_ind;
 
190
        char *cwd;
 
191
 
 
192
        argc = cli_count_args(argv);
 
193
 
 
194
        for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
 
195
                c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
 
196
                switch (c) {
 
197
                case 'p':
 
198
                        create_parents = 1;
 
199
                        break;
 
200
                case 'v':
 
201
                        verbose = 1;
 
202
                        break;
 
203
                case 'h':
 
204
                        help_cmd_mkdir(HELP_LONG);
 
205
                        return CMD_SUCCESS;
 
206
                case 'V':
 
207
                        printf("%s\n", MKDIR_VERSION);
 
208
                        return CMD_SUCCESS;
 
209
                case 'f':
 
210
                        follow = 1;
 
211
                        break;
 
212
                case 'm':
 
213
                        printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
 
214
                        break;
 
215
                }
 
216
        }
 
217
 
 
218
        argc -= optind;
 
219
 
 
220
        if (argc < 1) {
 
221
                printf("%s - incorrect number of arguments. Try `%s --help'\n",
 
222
                        cmdname, cmdname);
 
223
                return CMD_FAILURE;
 
224
        }
 
225
 
 
226
        if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
 
227
                cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
 
228
                return CMD_FAILURE;
 
229
        }
 
230
 
 
231
        memset(cwd, 0, sizeof(cwd));
 
232
        getcwd(cwd, PATH_MAX);
 
233
 
 
234
        for (i = optind; argv[i] != NULL; i++) {
 
235
                if (verbose == 1)
 
236
                        printf("%s: creating %s%s\n",
 
237
                                cmdname, argv[i],
 
238
                                create_parents ? " (and all parents)" : "");
 
239
                ret += create_directory(argv[i], create_parents);
 
240
        }
 
241
 
 
242
        if (follow == 0)
 
243
                chdir(cwd);
 
244
 
 
245
        free(cwd);
 
246
 
 
247
        if (ret)
 
248
                return CMD_FAILURE;
 
249
        else
 
250
                return CMD_SUCCESS;
 
251
}
 
252