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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f3d47c97 was b7fd2a0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 5.9 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 <stdint.h>
32#include <dirent.h>
33#include <getopt.h>
34#include <stdarg.h>
35#include <str.h>
36#include <errno.h>
37#include <str_error.h>
38#include <vfs/vfs.h>
39
40#include "config.h"
41#include "errors.h"
42#include "util.h"
43#include "entry.h"
44#include "mkdir.h"
45#include "cmds.h"
46
47#define MKDIR_VERSION "0.0.1"
48
49static const char *cmdname = "mkdir";
50
51static struct option const long_options[] = {
52 {"parents", no_argument, 0, 'p'},
53 {"verbose", no_argument, 0, 'v'},
54 {"mode", required_argument, 0, 'm'},
55 {"help", no_argument, 0, 'h'},
56 {"version", no_argument, 0, 'V'},
57 {"follow", no_argument, 0, 'f'},
58 {0, 0, 0, 0}
59};
60
61
62void help_cmd_mkdir(unsigned int level)
63{
64 if (level == HELP_SHORT) {
65 printf("`%s' creates a new directory\n", cmdname);
66 } else {
67 help_cmd_mkdir(HELP_SHORT);
68 printf(
69 "Usage: %s [options] <path>\n"
70 "Options:\n"
71 " -h, --help A short option summary\n"
72 " -V, --version Print version information and exit\n"
73 " -p, --parents Create needed parents for <path>\n"
74 " -m, --mode Set permissions to [mode] (UNUSED)\n"
75 " -v, --verbose Be extremely noisy about what is happening\n"
76 " -f, --follow Go to the new directory once created\n"
77 "Currently, %s is under development, some options don't work.\n",
78 cmdname, cmdname);
79 }
80
81 return;
82}
83
84/* This is kind of clunky, but effective for now */
85static unsigned int
86create_directory(const char *user_path, bool create_parents)
87{
88 /* Ensure we would always work with absolute and canonified path. */
89 char *path = vfs_absolutize(user_path, NULL);
90 if (path == NULL) {
91 cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
92 return 1;
93 }
94
95 int ret = 0;
96 errno_t rc;
97
98 if (!create_parents) {
99 rc = vfs_link_path(path, KIND_DIRECTORY, NULL);
100 if (rc != EOK) {
101 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
102 cmdname, path, str_error(rc));
103 ret = 1;
104 }
105 } else {
106 /* Create the parent directories as well. */
107 size_t off = 0;
108 while (1) {
109 size_t prev_off = off;
110 wchar_t cur_char = str_decode(path, &off, STR_NO_LIMIT);
111 if ((cur_char == 0) || (cur_char == U_SPECIAL)) {
112 break;
113 }
114 if (cur_char != '/') {
115 continue;
116 }
117 if (prev_off == 0) {
118 continue;
119 }
120 /*
121 * If we are here, it means that:
122 * - we found /
123 * - it is not the first / (no need to create root
124 * directory)
125 *
126 * We would now overwrite the / with 0 to terminate the
127 * string (that shall be okay because we are
128 * overwriting at the beginning of UTF sequence).
129 * That would allow us to create the directories
130 * in correct nesting order.
131 *
132 * Notice that we ignore EEXIST errors as some of
133 * the parent directories may already exist.
134 */
135 char slash_char = path[prev_off];
136 path[prev_off] = 0;
137
138 rc = vfs_link_path(path, KIND_DIRECTORY, NULL);
139 if (rc != EOK && rc != EEXIST) {
140 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
141 cmdname, path, str_error(rc));
142 ret = 1;
143 goto leave;
144 }
145
146 path[prev_off] = slash_char;
147 }
148 /* Create the final directory. */
149 rc = vfs_link_path(path, KIND_DIRECTORY, NULL);
150 if (rc != EOK) {
151 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
152 cmdname, path, str_error(rc));
153 ret = 1;
154 }
155 }
156
157leave:
158 free(path);
159 return ret;
160}
161
162int cmd_mkdir(char **argv)
163{
164 unsigned int argc, i, ret = 0;
165 bool create_parents = false, follow = false, verbose = false;
166 int c, opt_ind;
167
168 argc = cli_count_args(argv);
169
170 for (c = 0, optreset = 1, optind = 0, opt_ind = 0; c != -1;) {
171 c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
172 switch (c) {
173 case 'p':
174 create_parents = true;
175 break;
176 case 'v':
177 verbose = true;
178 break;
179 case 'h':
180 help_cmd_mkdir(HELP_LONG);
181 return CMD_SUCCESS;
182 case 'V':
183 printf("%s\n", MKDIR_VERSION);
184 return CMD_SUCCESS;
185 case 'f':
186 follow = true;
187 break;
188 case 'm':
189 printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
190 break;
191 }
192 }
193
194 argc -= optind;
195
196 if (argc < 1) {
197 printf("%s - incorrect number of arguments. Try `%s --help'\n",
198 cmdname, cmdname);
199 return CMD_FAILURE;
200 }
201
202 for (i = optind; argv[i] != NULL; i++) {
203 if (verbose)
204 printf("%s: creating %s%s\n",
205 cmdname, argv[i],
206 create_parents ? " (and all parents)" : "");
207 ret += create_directory(argv[i], create_parents);
208 }
209
210 if (follow && (argv[optind] != NULL)) {
211 if (vfs_cwd_set(argv[optind]) != EOK)
212 printf("%s: Error switching to directory.", cmdname);
213 }
214
215 if (ret)
216 return CMD_FAILURE;
217 else
218 return CMD_SUCCESS;
219}
220
Note: See TracBrowser for help on using the repository browser.