Rev 3346 | Rev 3354 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3346 | Rev 3353 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
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 |
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
28 | * POSSIBILITY OF SUCH DAMAGE. |
28 | * POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
29 | */ |
30 | 30 | ||
31 | /* TODO: |
- | |
32 | * Implement -p option when some type of getopt is ported */ |
- | |
33 | 31 | ||
34 | #include <stdio.h> |
32 | #include <stdio.h> |
35 | #include <stdlib.h> |
33 | #include <stdlib.h> |
36 | #include <dirent.h> |
34 | #include <dirent.h> |
37 | #include <fcntl.h> |
35 | #include <fcntl.h> |
38 | #include <sys/types.h> |
36 | #include <sys/types.h> |
39 | #include <sys/stat.h> |
37 | #include <sys/stat.h> |
- | 38 | #include <getopt.h> |
|
- | 39 | #include <stdarg.h> |
|
40 | 40 | ||
41 | #include "config.h" |
41 | #include "config.h" |
42 | #include "errors.h" |
42 | #include "errors.h" |
- | 43 | #include "util.h" |
|
43 | #include "entry.h" |
44 | #include "entry.h" |
44 | #include "mkdir.h" |
45 | #include "mkdir.h" |
45 | #include "cmds.h" |
46 | #include "cmds.h" |
46 | 47 | ||
- | 48 | #define MKDIR_VERSION "0.0.1" |
|
- | 49 | ||
47 | static char *cmdname = "mkdir"; |
50 | static char *cmdname = "mkdir"; |
48 | 51 | ||
49 | /* Dispays help for mkdir in various levels */ |
52 | static struct option long_options[] = { |
- | 53 | {"parents", no_argument, 0, 'p'}, |
|
- | 54 | {"verbose", no_argument, 0, 'v'}, |
|
- | 55 | {"mode", required_argument, 0, 'm'}, |
|
- | 56 | {"help", no_argument, 0, 'h'}, |
|
- | 57 | {"version", no_argument, 0, 'V'}, |
|
- | 58 | {"follow", no_argument, 0, 'f'}, |
|
- | 59 | {0, 0, 0, 0} |
|
- | 60 | }; |
|
- | 61 | ||
- | 62 | ||
50 | void * help_cmd_mkdir(unsigned int level) |
63 | void * help_cmd_mkdir(unsigned int level) |
51 | { |
64 | { |
52 | if (level == HELP_SHORT) { |
65 | if (level == HELP_SHORT) { |
53 | printf("`%s' creates a new directory\n", cmdname); |
66 | printf("`%s' creates a new directory\n", cmdname); |
54 | } else { |
67 | } else { |
55 | help_cmd_mkdir(HELP_SHORT); |
68 | help_cmd_mkdir(HELP_SHORT); |
- | 69 | printf( |
|
- | 70 | "Usage: %s [options] <path>\n" |
|
- | 71 | "Options:\n" |
|
- | 72 | " -h, --help A short option summary\n" |
|
- | 73 | " -V, --version Print version information and exit\n" |
|
- | 74 | " -p, --parents Create needed parents for <path>\n" |
|
- | 75 | " -m, --mode Set permissions to [mode] (UNUSED)\n" |
|
- | 76 | " -v, --verbose Be extremely noisy about what is happening\n" |
|
56 | printf(" `%s' <directory>\n", cmdname); |
77 | " -f, --follow Go to the new directory once created\n" |
- | 78 | "Currently, %s is under development, some options don't work.\n", |
|
- | 79 | cmdname, cmdname); |
|
57 | } |
80 | } |
58 | 81 | ||
59 | return CMD_VOID; |
82 | return CMD_VOID; |
60 | } |
83 | } |
61 | 84 | ||
62 | /* Main entry point for mkdir, accepts an array of arguments */ |
85 | /* This is kind of clunky, but effective for now */ |
- | 86 | unsigned int |
|
63 | int * cmd_mkdir(char **argv) |
87 | create_directory(const char *path, unsigned int p) |
64 | { |
88 | { |
65 | unsigned int argc; |
- | |
66 | DIR *dirp; |
89 | DIR *dirp; |
- | 90 | char *tmp = NULL, *buff = NULL, *wdp = NULL; |
|
- | 91 | char *dirs[255]; |
|
- | 92 | unsigned int absolute = 0, i = 0, ret = 0; |
|
- | 93 | ||
- | 94 | /* Its a good idea to allocate path, plus we (may) need a copy of |
|
- | 95 | * path to tokenize if parents are specified */ |
|
- | 96 | if (NULL == (tmp = cli_strdup(path))) { |
|
- | 97 | cli_error(CL_ENOMEM, "%s: path too big?", cmdname); |
|
- | 98 | return 1; |
|
- | 99 | } |
|
- | 100 | ||
- | 101 | if (NULL == (wdp = (char *) malloc(PATH_MAX))) { |
|
- | 102 | cli_error(CL_ENOMEM, "%s: could not alloc cwd", cmdname); |
|
- | 103 | free(tmp); |
|
- | 104 | return 1; |
|
- | 105 | } |
|
- | 106 | ||
- | 107 | /* The only reason for wdp is to be (optionally) verbose */ |
|
- | 108 | getcwd(wdp, PATH_MAX); |
|
- | 109 | ||
- | 110 | /* Typical use without specifying the creation of parents */ |
|
- | 111 | if (p == 0) { |
|
- | 112 | dirp = opendir(tmp); |
|
- | 113 | if (dirp) { |
|
- | 114 | cli_error(CL_EEXISTS, "%s: can not create %s, try -p", cmdname, path); |
|
- | 115 | closedir(dirp); |
|
- | 116 | goto finit; |
|
- | 117 | } |
|
- | 118 | if (-1 == (mkdir(tmp, 0))) { |
|
- | 119 | cli_error(CL_EFAIL, "%s: could not create %s", cmdname, path); |
|
- | 120 | goto finit; |
|
- | 121 | } |
|
- | 122 | } |
|
- | 123 | ||
- | 124 | /* Parents need to be created, path has to be broken up */ |
|
- | 125 | ||
- | 126 | /* See if path[0] is a slash, if so we have to remember to append it */ |
|
- | 127 | if (tmp[0] == '/') |
|
- | 128 | absolute = 1; |
|
- | 129 | ||
- | 130 | /* TODO: Canonify the path prior to tokenizing it, see below */ |
|
- | 131 | dirs[i] = cli_strtok(tmp, "/"); |
|
- | 132 | while (dirs[i] && i < 255) |
|
- | 133 | dirs[++i] = cli_strtok(NULL, "/"); |
|
- | 134 | ||
- | 135 | if (NULL == dirs[0]) |
|
- | 136 | return 1; |
|
- | 137 | ||
- | 138 | if (absolute == 1) { |
|
- | 139 | asprintf(&buff, "/%s", dirs[0]); |
|
- | 140 | mkdir(buff, 0); |
|
- | 141 | chdir(buff); |
|
- | 142 | free(buff); |
|
- | 143 | getcwd(wdp, PATH_MAX); |
|
- | 144 | i = 1; |
|
- | 145 | } else { |
|
- | 146 | i = 0; |
|
- | 147 | } |
|
- | 148 | ||
- | 149 | while (dirs[i] != NULL) { |
|
- | 150 | /* Rewind to start of relative path */ |
|
- | 151 | while (!strcmp(dirs[i], "..")) { |
|
- | 152 | if (0 != (chdir(dirs[i]))) { |
|
- | 153 | cli_error(CL_EFAIL, "%s: impossible path: %s", |
|
- | 154 | cmdname, path); |
|
- | 155 | ret ++; |
|
- | 156 | goto finit; |
|
- | 157 | } |
|
- | 158 | i++; |
|
- | 159 | } |
|
- | 160 | getcwd(wdp, PATH_MAX); |
|
- | 161 | /* Sometimes make or scripts conjoin odd paths. Account for something |
|
- | 162 | * like this: ../../foo/bar/../foo/foofoo/./bar */ |
|
- | 163 | if (!strcmp(dirs[i], "..") || !strcmp(dirs[i], ".")) { |
|
- | 164 | chdir(dirs[i]); |
|
- | 165 | getcwd(wdp, PATH_MAX); |
|
- | 166 | } else { |
|
- | 167 | if (-1 == (mkdir(dirs[i], 0))) { |
|
- | 168 | cli_error(CL_EFAIL, |
|
- | 169 | "%s: failed at %s/%s", wdp, dirs[i]); |
|
- | 170 | goto finit; |
|
- | 171 | } |
|
- | 172 | if (0 != (chdir(dirs[i]))) { |
|
- | 173 | cli_error(CL_EFAIL, "%s: failed creating %s\n", |
|
- | 174 | cmdname, dirs[i]); |
|
- | 175 | ret ++; |
|
- | 176 | break; |
|
- | 177 | } |
|
- | 178 | } |
|
- | 179 | i++; |
|
- | 180 | } |
|
- | 181 | goto finit; |
|
- | 182 | ||
- | 183 | finit: |
|
- | 184 | free(wdp); |
|
- | 185 | free(tmp); |
|
- | 186 | return ret; |
|
- | 187 | } |
|
- | 188 | ||
- | 189 | int * cmd_mkdir(char **argv) |
|
- | 190 | { |
|
- | 191 | unsigned int argc, create_parents = 0, i, ret = 0, follow = 0; |
|
- | 192 | unsigned int verbose = 0; |
|
- | 193 | int c, opt_ind; |
|
- | 194 | char *cwd; |
|
67 | 195 | ||
68 | /* Count the arguments */ |
- | |
69 | for (argc = 0; argv[argc] != NULL; argc ++); |
196 | for (argc = 0; argv[argc] != NULL; argc ++); |
70 | 197 | ||
- | 198 | for (c = 0, optind = 0, opt_ind = 0; c != -1;) { |
|
- | 199 | c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind); |
|
- | 200 | switch (c) { |
|
- | 201 | case 'p': |
|
- | 202 | create_parents = 1; |
|
- | 203 | break; |
|
- | 204 | case 'v': |
|
- | 205 | verbose = 1; |
|
- | 206 | break; |
|
- | 207 | case 'h': |
|
- | 208 | help_cmd_mkdir(HELP_LONG); |
|
- | 209 | return CMD_SUCCESS; |
|
- | 210 | case 'V': |
|
- | 211 | printf("%s\n", MKDIR_VERSION); |
|
- | 212 | return CMD_SUCCESS; |
|
- | 213 | case 'f': |
|
- | 214 | follow = 1; |
|
- | 215 | break; |
|
- | 216 | case 'm': |
|
- | 217 | printf("%s: [W] Ignoring mode %s\n", cmdname, optarg); |
|
- | 218 | break; |
|
- | 219 | } |
|
- | 220 | } |
|
- | 221 | ||
- | 222 | argc -= optind; |
|
- | 223 | ||
71 | if (argc != 2) { |
224 | if (argc < 1) { |
72 | printf("%s - incorrect number of arguments. Try `help %s extended'\n", |
225 | printf("%s - incorrect number of arguments. Try `%s --help'\n", |
73 | cmdname, cmdname); |
226 | cmdname, cmdname); |
74 | return CMD_FAILURE; |
227 | return CMD_FAILURE; |
75 | } |
228 | } |
76 | 229 | ||
77 | dirp = opendir(argv[1]); |
230 | if (NULL == (cwd = (char *) malloc(PATH_MAX))) { |
78 | if (dirp) { |
- | |
79 | closedir(dirp); |
- | |
80 | cli_error(CL_EEXISTS, "Can not create directory %s", argv[1]); |
231 | cli_error(CL_ENOMEM, "%s: could not allocate cwd", cmdname); |
81 | return CMD_FAILURE; |
232 | return CMD_FAILURE; |
82 | } |
233 | } |
83 | 234 | ||
- | 235 | memset(cwd, 0, sizeof(cwd)); |
|
- | 236 | getcwd(cwd, PATH_MAX); |
|
- | 237 | ||
84 | if (mkdir(argv[1], 0) != 0) { |
238 | for (i = optind; argv[i] != NULL; i++) { |
- | 239 | if (verbose == 1) |
|
85 | cli_error(CL_EFAIL, "Could not create %s", argv[1]); |
240 | printf("%s: creating %s%s\n", |
86 | return CMD_FAILURE; |
241 | cmdname, argv[i], |
- | 242 | create_parents ? " (and all parents)" : ""); |
|
- | 243 | ret += create_directory(argv[i], create_parents); |
|
87 | } |
244 | } |
88 | 245 | ||
- | 246 | if (follow == 0) |
|
- | 247 | chdir(cwd); |
|
- | 248 | ||
- | 249 | free(cwd); |
|
- | 250 | ||
- | 251 | if (ret) |
|
- | 252 | return CMD_FAILURE; |
|
- | 253 | else |
|
89 | return CMD_SUCCESS; |
254 | return CMD_SUCCESS; |
90 | } |
255 | } |
91 | 256 |