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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a6fc88a was a6fc88a, checked in by Jakub Jermar <jakub@…>, 9 years ago

Let vfs_link() and vfs_link_path() return the linked file handle

Add an output argument to both vfs_link() and vfs_link_path() so that the
client may receive the file handle of the linked file or directory. This
makes it easy to work with the new file or directory as it is ready to be
opened or in case of a directory to use it as a parent for further
operations without the need for additional vfs_lookup().

  • 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 <dirent.h>
32#include <sys/types.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
97 if (!create_parents) {
98 ret = vfs_link_path(path, KIND_DIRECTORY, NULL);
99 if (ret != EOK) {
100 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
101 cmdname, path, str_error(ret));
102 ret = 1;
103 }
104 } else {
105 /* Create the parent directories as well. */
106 size_t off = 0;
107 while (1) {
108 size_t prev_off = off;
109 wchar_t cur_char = str_decode(path, &off, STR_NO_LIMIT);
110 if ((cur_char == 0) || (cur_char == U_SPECIAL)) {
111 break;
112 }
113 if (cur_char != '/') {
114 continue;
115 }
116 if (prev_off == 0) {
117 continue;
118 }
119 /*
120 * If we are here, it means that:
121 * - we found /
122 * - it is not the first / (no need to create root
123 * directory)
124 *
125 * We would now overwrite the / with 0 to terminate the
126 * string (that shall be okay because we are
127 * overwriting at the beginning of UTF sequence).
128 * That would allow us to create the directories
129 * in correct nesting order.
130 *
131 * Notice that we ignore EEXIST errors as some of
132 * the parent directories may already exist.
133 */
134 char slash_char = path[prev_off];
135 path[prev_off] = 0;
136
137 ret = vfs_link_path(path, KIND_DIRECTORY, NULL);
138 if (ret != EOK && ret != EEXIST) {
139 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
140 cmdname, path, str_error(ret));
141 ret = 1;
142 goto leave;
143 }
144
145 path[prev_off] = slash_char;
146 }
147 /* Create the final directory. */
148 ret = vfs_link_path(path, KIND_DIRECTORY, NULL);
149 if (ret != EOK) {
150 cli_error(CL_EFAIL, "%s: could not create %s (%s)",
151 cmdname, path, str_error(ret));
152 ret = 1;
153 }
154 }
155
156leave:
157 free(path);
158 return ret;
159}
160
161int cmd_mkdir(char **argv)
162{
163 unsigned int argc, i, ret = 0;
164 bool create_parents = false, follow = false, verbose = false;
165 int c, opt_ind;
166
167 argc = cli_count_args(argv);
168
169 for (c = 0, optreset = 1, optind = 0, opt_ind = 0; c != -1;) {
170 c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
171 switch (c) {
172 case 'p':
173 create_parents = true;
174 break;
175 case 'v':
176 verbose = true;
177 break;
178 case 'h':
179 help_cmd_mkdir(HELP_LONG);
180 return CMD_SUCCESS;
181 case 'V':
182 printf("%s\n", MKDIR_VERSION);
183 return CMD_SUCCESS;
184 case 'f':
185 follow = true;
186 break;
187 case 'm':
188 printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
189 break;
190 }
191 }
192
193 argc -= optind;
194
195 if (argc < 1) {
196 printf("%s - incorrect number of arguments. Try `%s --help'\n",
197 cmdname, cmdname);
198 return CMD_FAILURE;
199 }
200
201 for (i = optind; argv[i] != NULL; i++) {
202 if (verbose)
203 printf("%s: creating %s%s\n",
204 cmdname, argv[i],
205 create_parents ? " (and all parents)" : "");
206 ret += create_directory(argv[i], create_parents);
207 }
208
209 if (follow && (argv[optind] != NULL)) {
210 if (vfs_cwd_set(argv[optind]) != EOK)
211 printf("%s: Error switching to directory.", cmdname);
212 }
213
214 if (ret)
215 return CMD_FAILURE;
216 else
217 return CMD_SUCCESS;
218}
219
Note: See TracBrowser for help on using the repository browser.