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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since dba3e2c was 738b549, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

Rewrote bdsh/mkdir (includes #357)

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