1
/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* Redistributions of source code must retain the above copyright notice, this
8
* list of conditions and the following disclaimer.
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.
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.
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.
36
#include <sys/types.h>
49
#define MKDIR_VERSION "0.0.1"
51
static char *cmdname = "mkdir";
53
static struct option const long_options[] = {
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'},
64
void help_cmd_mkdir(unsigned int level)
66
if (level == HELP_SHORT) {
67
printf("`%s' creates a new directory\n", cmdname);
69
help_cmd_mkdir(HELP_SHORT);
71
"Usage: %s [options] <path>\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",
86
/* This is kind of clunky, but effective for now */
88
create_directory(const char *path, unsigned int p)
91
char *tmp = NULL, *buff = NULL, *wdp = NULL;
93
unsigned int absolute = 0, i = 0, ret = 0;
95
/* Its a good idea to allocate path, plus we (may) need a copy of
96
* path to tokenize if parents are specified */
97
if (NULL == (tmp = str_dup(path))) {
98
cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
102
if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
103
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
108
/* The only reason for wdp is to be (optionally) verbose */
109
getcwd(wdp, PATH_MAX);
111
/* Typical use without specifying the creation of parents */
115
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
119
if (-1 == (mkdir(tmp, 0))) {
120
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
125
/* Parents need to be created, path has to be broken up */
127
/* See if path[0] is a slash, if so we have to remember to append it */
131
/* TODO: Canonify the path prior to tokenizing it, see below */
132
dirs[i] = strtok(tmp, "/");
133
while (dirs[i] && i < 255)
134
dirs[++i] = strtok(NULL, "/");
140
asprintf(&buff, "/%s", dirs[0]);
144
getcwd(wdp, PATH_MAX);
150
while (dirs[i] != NULL) {
151
/* Sometimes make or scripts conjoin odd paths. Account for something
152
* like this: ../../foo/bar/../foo/foofoo/./bar */
153
if (!str_cmp(dirs[i], "..") || !str_cmp(dirs[i], ".")) {
154
if (0 != (chdir(dirs[i]))) {
155
cli_error(CL_EFAIL, "%s: impossible path: %s",
160
getcwd(wdp, PATH_MAX);
162
if (-1 == (mkdir(dirs[i], 0))) {
164
"%s: failed at %s/%s", wdp, dirs[i]);
168
if (0 != (chdir(dirs[i]))) {
169
cli_error(CL_EFAIL, "%s: failed creating %s\n",
185
int cmd_mkdir(char **argv)
187
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
188
unsigned int verbose = 0;
192
argc = cli_count_args(argv);
194
for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
195
c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind);
204
help_cmd_mkdir(HELP_LONG);
207
printf("%s\n", MKDIR_VERSION);
213
printf("%s: [W] Ignoring mode %s\n", cmdname, optarg);
221
printf("%s - incorrect number of arguments. Try `%s --help'\n",
226
if (NULL == (cwd = (char *) malloc(PATH_MAX))) {
227
cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname);
231
memset(cwd, 0, sizeof(cwd));
232
getcwd(cwd, PATH_MAX);
234
for (i = optind; argv[i] != NULL; i++) {
236
printf("%s: creating %s%s\n",
238
create_parents ? " (and all parents)" : "");
239
ret += create_directory(argv[i], create_parents);