source: mainline/uspace/app/bdsh/cmds/modules/mkdir/mkdir.c@ 36ab7c7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 36ab7c7 was 36ab7c7, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Standardize formatting of copyright headers in Bdsh and add some that were
missing.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2008 Tim Post
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <dirent.h>
32#include <fcntl.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <getopt.h>
36#include <stdarg.h>
37#include <str.h>
38
39#include "config.h"
40#include "errors.h"
41#include "util.h"
42#include "entry.h"
43#include "mkdir.h"
44#include "cmds.h"
45
46#define MKDIR_VERSION "0.0.1"
47
48static const char *cmdname = "mkdir";
49
50static struct option const long_options[] = {
51 {"parents", no_argument, 0, 'p'},
52 {"verbose", no_argument, 0, 'v'},
53 {"mode", required_argument, 0, 'm'},
54 {"help", no_argument, 0, 'h'},
55 {"version", no_argument, 0, 'V'},
56 {"follow", no_argument, 0, 'f'},
57 {0, 0, 0, 0}
58};
59
60
61void help_cmd_mkdir(unsigned int level)
62{
63 if (level == HELP_SHORT) {
64 printf("`%s' creates a new directory\n", cmdname);
65 } else {
66 help_cmd_mkdir(HELP_SHORT);
67 printf(
68 "Usage: %s [options] <path>\n"
69 "Options:\n"
70 " -h, --help A short option summary\n"
71 " -V, --version Print version information and exit\n"
72 " -p, --parents Create needed parents for <path>\n"
73 " -m, --mode Set permissions to [mode] (UNUSED)\n"
74 " -v, --verbose Be extremely noisy about what is happening\n"
75 " -f, --follow Go to the new directory once created\n"
76 "Currently, %s is under development, some options don't work.\n",
77 cmdname, cmdname);
78 }
79
80 return;
81}
82
83/* This is kind of clunky, but effective for now */
84static unsigned int
85create_directory(const char *path, unsigned int p)
86{
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))) {
95 cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
96 return 1;
97 }
98
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;
143 } 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 ++;
169 break;
170 }
171 }
172 i++;
173 }
174 goto finit;
175
176finit:
177 free(wdp);
178 free(tmp);
179 return ret;
180}
181
182int cmd_mkdir(char **argv)
183{
184 unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
185 unsigned int verbose = 0;
186 int c, opt_ind;
187 char *cwd;
188
189 argc = cli_count_args(argv);
190
191 for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
192 c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
193 switch (c) {
194 case 'p':
195 create_parents = 1;
196 break;
197 case 'v':
198 verbose = 1;
199 break;
200 case 'h':
201 help_cmd_mkdir(HELP_LONG);
202 return CMD_SUCCESS;
203 case 'V':
204 printf("%s\n", MKDIR_VERSION);
205 return CMD_SUCCESS;
206 case 'f':
207 follow = 1;
208 break;
209 case 'm':
210 printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
211 break;
212 }
213 }
214
215 argc -= optind;
216
217 if (argc < 1) {
218 printf("%s - incorrect number of arguments. Try `%s --help'\n",
219 cmdname, cmdname);
220 return CMD_FAILURE;
221 }
222
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 for (i = optind; argv[i] != NULL; i++) {
232 if (verbose == 1)
233 printf("%s: creating %s%s\n",
234 cmdname, argv[i],
235 create_parents ? " (and all parents)" : "");
236 ret += create_directory(argv[i], create_parents);
237 }
238
239 if (follow == 0)
240 chdir(cwd);
241
242 free(cwd);
243
244 if (ret)
245 return CMD_FAILURE;
246 else
247 return CMD_SUCCESS;
248}
249
Note: See TracBrowser for help on using the repository browser.