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 | ||