1 /* 2 * Copyright (c) 1983, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1983, 1992, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 01/25/94"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 21 #include <err.h> 22 #include <errno.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 int build __P((char *)); 29 void usage __P((void)); 30 31 int 32 main(argc, argv) 33 int argc; 34 char *argv[]; 35 { 36 int ch, exitval, oct, omode, pflag; 37 mode_t *set; 38 char *ep, *mode; 39 40 pflag = 0; 41 mode = NULL; 42 while ((ch = getopt(argc, argv, "m:p")) != EOF) 43 switch(ch) { 44 case 'p': 45 pflag = 1; 46 break; 47 case 'm': 48 mode = optarg; 49 break; 50 case '?': 51 default: 52 usage(); 53 } 54 55 argc -= optind; 56 argv += optind; 57 if (argv[0] == NULL) 58 usage(); 59 60 if (mode == NULL) { 61 omode = S_IRWXU | S_IRWXG | S_IRWXO; 62 oct = 1; 63 } else if (*mode >= '0' && *mode <= '7') { 64 omode = (int)strtol(mode, &ep, 8); 65 if (omode < 0 || *ep) 66 errx(1, "invalid file mode: %s", mode); 67 oct = 1; 68 } else { 69 if ((set = setmode(mode)) == NULL) 70 errx(1, "invalid file mode: %s", mode); 71 oct = 0; 72 } 73 74 for (exitval = 0; *argv != NULL; ++argv) { 75 if (pflag && build(*argv)) { 76 exitval = 1; 77 continue; 78 } 79 if (mkdir(*argv, oct ? 80 omode : getmode(set, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { 81 warn("%s", *argv); 82 exitval = 1; 83 } 84 } 85 exit(exitval); 86 } 87 88 int 89 build(path) 90 char *path; 91 { 92 struct stat sb; 93 mode_t numask, oumask; 94 int first; 95 char *p; 96 97 p = path; 98 if (p[0] == '/') /* Skip leading '/'. */ 99 ++p; 100 for (first = 1;; ++p) { 101 if (p[0] == '\0' || p[0] == '/' && p[1] == '\0') 102 break; 103 if (p[0] != '/') 104 continue; 105 *p = '\0'; 106 if (first) { 107 /* 108 * POSIX 1003.2: 109 * For each dir operand that does not name an existing 110 * directory, effects equivalent to those cased by the 111 * following command shall occcur: 112 * 113 * mkdir -p -m $(umask -S),u+wx $(dirname dir) && 114 * mkdir [-m mode] dir 115 * 116 * We change the user's umask and then restore it, 117 * instead of doing chmod's. 118 */ 119 oumask = umask(0); 120 numask = oumask & ~(S_IWUSR | S_IXUSR); 121 (void)umask(numask); 122 first = 0; 123 } 124 if (stat(path, &sb)) { 125 if (errno != ENOENT || 126 mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0) { 127 warn("%s", path); 128 return (1); 129 } 130 } 131 *p = '/'; 132 } 133 if (!first) 134 (void)umask(oumask); 135 return (0); 136 } 137 138 void 139 usage() 140 { 141 (void)fprintf(stderr, "usage: mkdir [-p] [-m mode] directory ...\n"); 142 exit (1); 143 } 144