Subversion Repositories HelenOS

Rev

Rev 3346 | Rev 3354 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3346 Rev 3353
Line 26... Line 26...
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
/* TODO:
-
 
32
 * Implement -p option when some type of getopt is ported */
-
 
33
 
31
 
34
#include <stdio.h>
32
#include <stdio.h>
35
#include <stdlib.h>
33
#include <stdlib.h>
36
#include <dirent.h>
34
#include <dirent.h>
37
#include <fcntl.h>
35
#include <fcntl.h>
38
#include <sys/types.h>
36
#include <sys/types.h>
39
#include <sys/stat.h>
37
#include <sys/stat.h>
-
 
38
#include <getopt.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 "entry.h"
44
#include "entry.h"
44
#include "mkdir.h"
45
#include "mkdir.h"
45
#include "cmds.h"
46
#include "cmds.h"
46
 
47
 
-
 
48
#define MKDIR_VERSION "0.0.1"
-
 
49
 
47
static char *cmdname = "mkdir";
50
static char *cmdname = "mkdir";
48
 
51
 
49
/* Dispays help for mkdir in various levels */
52
static struct option long_options[] = {
-
 
53
    {"parents", no_argument, 0, 'p'},
-
 
54
    {"verbose", no_argument, 0, 'v'},
-
 
55
    {"mode", required_argument, 0, 'm'},
-
 
56
    {"help", no_argument, 0, 'h'},
-
 
57
    {"version", no_argument, 0, 'V'},
-
 
58
    {"follow", no_argument, 0, 'f'},
-
 
59
    {0, 0, 0, 0}
-
 
60
};
-
 
61
 
-
 
62
 
50
void * help_cmd_mkdir(unsigned int level)
63
void * help_cmd_mkdir(unsigned int level)
51
{
64
{
52
    if (level == HELP_SHORT) {
65
    if (level == HELP_SHORT) {
53
        printf("`%s' creates a new directory\n", cmdname);
66
        printf("`%s' creates a new directory\n", cmdname);
54
    } else {
67
    } else {
55
        help_cmd_mkdir(HELP_SHORT);
68
        help_cmd_mkdir(HELP_SHORT);
-
 
69
        printf(
-
 
70
        "Usage:  %s [options] <path>\n"
-
 
71
        "Options:\n"
-
 
72
        "  -h, --help       A short option summary\n"
-
 
73
        "  -V, --version    Print version information and exit\n"
-
 
74
        "  -p, --parents    Create needed parents for <path>\n"
-
 
75
        "  -m, --mode       Set permissions to [mode] (UNUSED)\n"
-
 
76
        "  -v, --verbose    Be extremely noisy about what is happening\n"
56
        printf("  `%s' <directory>\n", cmdname);
77
        "  -f, --follow     Go to the new directory once created\n"
-
 
78
        "Currently, %s is under development, some options don't work.\n",
-
 
79
        cmdname, cmdname);
57
    }
80
    }
58
 
81
 
59
    return CMD_VOID;
82
    return CMD_VOID;
60
}
83
}
61
 
84
 
62
/* Main entry point for mkdir, accepts an array of arguments */
85
/* This is kind of clunky, but effective for now */
-
 
86
unsigned int
63
int * cmd_mkdir(char **argv)
87
create_directory(const char *path, unsigned int p)
64
{
88
{
65
    unsigned int argc;
-
 
66
    DIR *dirp;
89
    DIR *dirp;
-
 
90
    char *tmp = NULL, *buff = NULL, *wdp = NULL;
-
 
91
    char *dirs[255];
-
 
92
    unsigned int absolute = 0, i = 0, ret = 0;
-
 
93
 
-
 
94
    /* Its a good idea to allocate path, plus we (may) need a copy of
-
 
95
     * path to tokenize if parents are specified */
-
 
96
    if (NULL == (tmp = cli_strdup(path))) {
-
 
97
        cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
-
 
98
        return 1;
-
 
99
    }
-
 
100
 
-
 
101
    if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
-
 
102
        cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
-
 
103
        free(tmp);
-
 
104
        return 1;
-
 
105
    }
-
 
106
 
-
 
107
    /* The only reason for wdp is to be (optionally) verbose */
-
 
108
    getcwd(wdp, PATH_MAX);
-
 
109
 
-
 
110
    /* Typical use without specifying the creation of parents */
-
 
111
    if (p == 0) {
-
 
112
        dirp = opendir(tmp);
-
 
113
        if (dirp) {
-
 
114
            cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
-
 
115
            closedir(dirp);
-
 
116
            goto finit;
-
 
117
        }
-
 
118
        if (-1 == (mkdir(tmp, 0))) {
-
 
119
            cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
-
 
120
            goto finit;
-
 
121
        }
-
 
122
    }
-
 
123
 
-
 
124
    /* Parents need to be created, path has to be broken up */
-
 
125
 
-
 
126
    /* See if path[0] is a slash, if so we have to remember to append it */
-
 
127
    if (tmp[0] == '/')
-
 
128
        absolute = 1;
-
 
129
 
-
 
130
    /* TODO: Canonify the path prior to tokenizing it, see below */
-
 
131
    dirs[i] = cli_strtok(tmp, "/");
-
 
132
    while (dirs[i] && i < 255)
-
 
133
        dirs[++i] = cli_strtok(NULL, "/");
-
 
134
 
-
 
135
    if (NULL == dirs[0])
-
 
136
        return 1;
-
 
137
 
-
 
138
    if (absolute == 1) {
-
 
139
        asprintf(&buff, "/%s", dirs[0]);
-
 
140
        mkdir(buff, 0);
-
 
141
        chdir(buff);
-
 
142
        free(buff);
-
 
143
        getcwd(wdp, PATH_MAX);
-
 
144
        i = 1;
-
 
145
    } else {
-
 
146
        i = 0;
-
 
147
    }
-
 
148
 
-
 
149
    while (dirs[i] != NULL) {
-
 
150
        /* Rewind to start of relative path */
-
 
151
        while (!strcmp(dirs[i], "..")) {
-
 
152
            if (0 != (chdir(dirs[i]))) {
-
 
153
                cli_error(CL_EFAIL, "%s: impossible path: %s",
-
 
154
                    cmdname, path);
-
 
155
                ret ++;
-
 
156
                goto finit;
-
 
157
            }
-
 
158
            i++;
-
 
159
        }
-
 
160
        getcwd(wdp, PATH_MAX);
-
 
161
        /* Sometimes make or scripts conjoin odd paths. Account for something
-
 
162
         * like this: ../../foo/bar/../foo/foofoo/./bar */
-
 
163
        if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) {
-
 
164
            chdir(dirs[i]);
-
 
165
            getcwd(wdp, PATH_MAX);
-
 
166
        } else {
-
 
167
            if (-1 == (mkdir(dirs[i], 0))) {
-
 
168
                cli_error(CL_EFAIL,
-
 
169
                    "%s: failed at %s/%s", wdp, dirs[i]);
-
 
170
                goto finit;
-
 
171
            }
-
 
172
            if (0 != (chdir(dirs[i]))) {
-
 
173
                cli_error(CL_EFAIL, "%s: failed creating %s\n",
-
 
174
                    cmdname, dirs[i]);
-
 
175
                ret ++;
-
 
176
                break;
-
 
177
            }
-
 
178
        }
-
 
179
        i++;
-
 
180
    }
-
 
181
    goto finit;
-
 
182
 
-
 
183
finit:
-
 
184
    free(wdp);
-
 
185
    free(tmp);
-
 
186
    return ret;
-
 
187
}
-
 
188
 
-
 
189
int * cmd_mkdir(char **argv)
-
 
190
{
-
 
191
    unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
-
 
192
    unsigned int verbose = 0;
-
 
193
    int c, opt_ind;
-
 
194
    char *cwd;
67
 
195
 
68
    /* Count the arguments */
-
 
69
    for (argc = 0; argv[argc] != NULL; argc ++);
196
    for (argc = 0; argv[argc] != NULL; argc ++);
70
 
197
 
-
 
198
    for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-
 
199
        c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
-
 
200
        switch (c) {
-
 
201
        case 'p':
-
 
202
            create_parents = 1;
-
 
203
            break;
-
 
204
        case 'v':
-
 
205
            verbose = 1;
-
 
206
            break;
-
 
207
        case 'h':
-
 
208
            help_cmd_mkdir(HELP_LONG);
-
 
209
            return CMD_SUCCESS;
-
 
210
        case 'V':
-
 
211
            printf("%s\n", MKDIR_VERSION);
-
 
212
            return CMD_SUCCESS;
-
 
213
        case 'f':
-
 
214
            follow = 1;
-
 
215
            break;
-
 
216
        case 'm':
-
 
217
            printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
-
 
218
            break;
-
 
219
        }
-
 
220
    }
-
 
221
 
-
 
222
    argc -= optind;
-
 
223
 
71
    if (argc != 2) {
224
    if (argc < 1) {
72
        printf("%s - incorrect number of arguments. Try `help %s extended'\n",
225
        printf("%s - incorrect number of arguments. Try `%s --help'\n",
73
            cmdname, cmdname);
226
            cmdname, cmdname);
74
        return CMD_FAILURE;
227
        return CMD_FAILURE;
75
    }
228
    }
76
 
229
 
77
    dirp = opendir(argv[1]);
230
    if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
78
    if (dirp) {
-
 
79
        closedir(dirp);
-
 
80
        cli_error(CL_EEXISTS, "Can not create directory %s", argv[1]);
231
        cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
81
        return CMD_FAILURE;
232
        return CMD_FAILURE;
82
    }
233
    }
83
 
234
 
-
 
235
    memset(cwd, 0, sizeof(cwd));
-
 
236
    getcwd(cwd, PATH_MAX);
-
 
237
 
84
    if (mkdir(argv[1], 0) != 0) {
238
    for (i = optind; argv[i] != NULL; i++) {
-
 
239
        if (verbose == 1)
85
        cli_error(CL_EFAIL, "Could not create %s", argv[1]);
240
            printf("%s: creating %s%s\n",
86
        return CMD_FAILURE;
241
                cmdname, argv[i],
-
 
242
                create_parents ? " (and all parents)" : "");
-
 
243
        ret += create_directory(argv[i], create_parents);
87
    }
244
    }
88
 
245
 
-
 
246
    if (follow == 0)
-
 
247
        chdir(cwd);
-
 
248
 
-
 
249
    free(cwd);
-
 
250
 
-
 
251
    if (ret)
-
 
252
        return CMD_FAILURE;
-
 
253
    else
89
    return CMD_SUCCESS;
254
        return CMD_SUCCESS;
90
}
255
}
91
 
256