Subversion Repositories HelenOS

Rev

Rev 3397 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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