83
86
/* This is kind of clunky, but effective for now */
84
87
static unsigned int
85
create_directory(const char *path, unsigned int p)
88
create_directory(const char *user_path, bool create_parents)
88
char *tmp = NULL, *buff = NULL, *wdp = NULL;
90
unsigned int absolute = 0, i = 0, ret = 0;
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))) {
90
/* Ensure we would always work with absolute and canonified path. */
91
char *path = absolutize(user_path, NULL);
95
93
cli_error(CL_ENOMEM, "%s: path too big?", cmdname);
99
if (NULL == (wdp = (char *) malloc(PATH_MAX))) {
100
cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname);
105
/* The only reason for wdp is to be (optionally) verbose */
106
getcwd(wdp, PATH_MAX);
108
/* Typical use without specifying the creation of parents */
112
cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path);
116
if (-1 == (mkdir(tmp, 0))) {
117
cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path);
122
/* Parents need to be created, path has to be broken up */
124
/* See if path[0] is a slash, if so we have to remember to append it */
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, "/");
137
asprintf(&buff, "/%s", dirs[0]);
141
getcwd(wdp, PATH_MAX);
100
if (!create_parents) {
103
cli_error(CL_EFAIL, "%s: could not create %s (%s)",
104
cmdname, path, str_error(rc));
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",
157
getcwd(wdp, PATH_MAX);
159
if (-1 == (mkdir(dirs[i], 0))) {
161
"%s: failed at %s/%s", wdp, dirs[i]);
165
if (0 != (chdir(dirs[i]))) {
166
cli_error(CL_EFAIL, "%s: failed creating %s\n",
108
/* Create the parent directories as well. */
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)) {
116
if (cur_char != '/') {
123
* If we are here, it means that:
125
* - it is not the first / (no need to create root
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.
134
* Notice that we ignore EEXIST errors as some of
135
* the parent directories may already exist.
137
char slash_char = path[prev_off];
145
cli_error(CL_EFAIL, "%s: could not create %s (%s)",
146
cmdname, path, str_error(rc));
151
path[prev_off] = slash_char;
153
/* Create the final directory. */
156
cli_error(CL_EFAIL, "%s: could not create %s (%s)",
157
cmdname, path, str_error(rc));
182
167
int cmd_mkdir(char **argv)
184
unsigned int argc, create_parents = 0, i, ret = 0, follow = 0;
185
unsigned int verbose = 0;
169
unsigned int argc, i, ret = 0;
170
bool create_parents = false, follow = false, verbose = false;
189
173
argc = cli_count_args(argv);