source: mainline/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c@ 3771a6e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3771a6e was 3771a6e, checked in by Tim Post <echo@…>, 17 years ago

long_options[] should be const where implemented

  • Property mode set to 100644
File size: 6.4 KB
Line 
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
41#include "config.h"
42#include "errors.h"
43#include "util.h"
44#include "entry.h"
45#include "mkdir.h"
46#include "cmds.h"
47
48#define MKDIR_VERSION "0.0.1"
49
50static char *cmdname = "mkdir";
51
52static struct option const 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
63void * help_cmd_mkdir(unsigned int level)
64{
65 if (level == HELP_SHORT) {
66 printf("`%s' creates a new directory\n", cmdname);
67 } else {
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"
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);
80 }
81
82 return CMD_VOID;
83}
84
85/* This is kind of clunky, but effective for now */
86static unsigned int
87create_directory(const char *path, unsigned int p)
88{
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 /* Sometimes make or scripts conjoin odd paths. Account for something
151 * like this: ../../foo/bar/../foo/foofoo/./bar */
152 if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) {
153 if (0 != (chdir(dirs[i]))) {
154 cli_error(CL_EFAIL, "%s: impossible path: %s",
155 cmdname, path);
156 ret ++;
157 goto finit;
158 }
159 getcwd(wdp, PATH_MAX);
160 } else {
161 if (-1 == (mkdir(dirs[i], 0))) {
162 cli_error(CL_EFAIL,
163 "%s: failed at %s/%s", wdp, dirs[i]);
164 ret ++;
165 goto finit;
166 }
167 if (0 != (chdir(dirs[i]))) {
168 cli_error(CL_EFAIL, "%s: failed creating %s\n",
169 cmdname, dirs[i]);
170 ret ++;
171 break;
172 }
173 }
174 i++;
175 }
176 goto finit;
177
178finit:
179 free(wdp);
180 free(tmp);
181 return ret;
182}
183
184int * cmd_mkdir(char **argv)
185{
186 unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
187 unsigned int verbose = 0;
188 int c, opt_ind;
189 char *cwd;
190
191 for (argc = 0; argv[argc] != NULL; argc ++);
192
193 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
194 c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
195 switch (c) {
196 case 'p':
197 create_parents = 1;
198 break;
199 case 'v':
200 verbose = 1;
201 break;
202 case 'h':
203 help_cmd_mkdir(HELP_LONG);
204 return CMD_SUCCESS;
205 case 'V':
206 printf("%s\n", MKDIR_VERSION);
207 return CMD_SUCCESS;
208 case 'f':
209 follow = 1;
210 break;
211 case 'm':
212 printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
213 break;
214 }
215 }
216
217 argc -= optind;
218
219 if (argc < 1) {
220 printf("%s - incorrect number of arguments. Try `%s --help'\n",
221 cmdname, cmdname);
222 return CMD_FAILURE;
223 }
224
225 if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
226 cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
227 return CMD_FAILURE;
228 }
229
230 memset(cwd, 0, sizeof(cwd));
231 getcwd(cwd, PATH_MAX);
232
233 for (i = optind; argv[i] != NULL; i++) {
234 if (verbose == 1)
235 printf("%s: creating %s%s\n",
236 cmdname, argv[i],
237 create_parents ? " (and all parents)" : "");
238 ret += create_directory(argv[i], create_parents);
239 }
240
241 if (follow == 0)
242 chdir(cwd);
243
244 free(cwd);
245
246 if (ret)
247 return CMD_FAILURE;
248 else
249 return CMD_SUCCESS;
250}
251
Note: See TracBrowser for help on using the repository browser.