1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*34f9b3eeSRoland Mainz * Copyright (c) 1992-2009 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 77c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12da2e3ebdSchin * * 13da2e3ebdSchin * Information and Software Systems Research * 14da2e3ebdSchin * AT&T Research * 15da2e3ebdSchin * Florham Park NJ * 16da2e3ebdSchin * * 17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18da2e3ebdSchin * David Korn <dgk@research.att.com> * 19da2e3ebdSchin * * 20da2e3ebdSchin ***********************************************************************/ 21da2e3ebdSchin #pragma prototyped 22da2e3ebdSchin /* 23da2e3ebdSchin * David Korn 24da2e3ebdSchin * AT&T Bell Laboratories 25da2e3ebdSchin * 26da2e3ebdSchin * mkdir 27da2e3ebdSchin */ 28da2e3ebdSchin 29da2e3ebdSchin static const char usage[] = 307c2fbfb3SApril Chin "[-?\n@(#)$Id: mkdir (AT&T Research) 2007-04-25 $\n]" 31da2e3ebdSchin USAGE_LICENSE 32da2e3ebdSchin "[+NAME?mkdir - make directories]" 33da2e3ebdSchin "[+DESCRIPTION?\bmkdir\b creates one or more directories. By " 34da2e3ebdSchin "default, the mode of created directories is \ba=rwx\b minus the " 35da2e3ebdSchin "bits set in the \bumask\b(1).]" 36da2e3ebdSchin "[m:mode]:[mode?Set the mode of created directories to \amode\a. " 37da2e3ebdSchin "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative " 38da2e3ebdSchin "modes assume an initial mode of \ba=rwx\b.]" 39da2e3ebdSchin "[p:parents?Create any missing intermediate pathname components. For " 40da2e3ebdSchin "each dir operand that does not name an existing directory, effects " 41da2e3ebdSchin "equivalent to those caused by the following command shall occur: " 42da2e3ebdSchin "\vmkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]] " 43da2e3ebdSchin "dir\v where the \b-m\b mode option represents that option supplied to " 44da2e3ebdSchin "the original invocation of \bmkdir\b, if any. Each dir operand that " 45da2e3ebdSchin "names an existing directory shall be ignored without error.]" 46da2e3ebdSchin "\n" 47da2e3ebdSchin "\ndirectory ...\n" 48da2e3ebdSchin "\n" 49da2e3ebdSchin "[+EXIT STATUS?]{" 50da2e3ebdSchin "[+0?All directories created successfully, or the \b-p\b option " 51da2e3ebdSchin "was specified and all the specified directories now exist.]" 52da2e3ebdSchin "[+>0?An error occurred.]" 53da2e3ebdSchin "}" 54da2e3ebdSchin "[+SEE ALSO?\bchmod\b(1), \brmdir\b(1), \bumask\b(1)]" 55da2e3ebdSchin ; 56da2e3ebdSchin 57da2e3ebdSchin #include <cmd.h> 58da2e3ebdSchin #include <ls.h> 59da2e3ebdSchin 60da2e3ebdSchin #define DIRMODE (S_IRWXU|S_IRWXG|S_IRWXO) 61da2e3ebdSchin 62da2e3ebdSchin int 63da2e3ebdSchin b_mkdir(int argc, char** argv, void* context) 64da2e3ebdSchin { 65da2e3ebdSchin register char* arg; 66da2e3ebdSchin register int n; 67da2e3ebdSchin register mode_t mode = DIRMODE; 68da2e3ebdSchin register mode_t mask = 0; 69da2e3ebdSchin register int mflag = 0; 70da2e3ebdSchin register int pflag = 0; 71da2e3ebdSchin char* name; 72da2e3ebdSchin mode_t dmode; 737c2fbfb3SApril Chin struct stat st; 74da2e3ebdSchin 75da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0); 76*34f9b3eeSRoland Mainz for (;;) 77da2e3ebdSchin { 78*34f9b3eeSRoland Mainz switch (optget(argv, usage)) 79*34f9b3eeSRoland Mainz { 80*34f9b3eeSRoland Mainz case 0: 81*34f9b3eeSRoland Mainz break; 82da2e3ebdSchin case 'p': 83da2e3ebdSchin pflag = 1; 84*34f9b3eeSRoland Mainz continue; 85da2e3ebdSchin case 'm': 86da2e3ebdSchin mflag = 1; 87da2e3ebdSchin mode = strperm(arg = opt_info.arg, &opt_info.arg, mode); 88da2e3ebdSchin if (*opt_info.arg) 89da2e3ebdSchin error(ERROR_exit(0), "%s: invalid mode", arg); 90*34f9b3eeSRoland Mainz continue; 91da2e3ebdSchin case ':': 92da2e3ebdSchin error(2, "%s", opt_info.arg); 93*34f9b3eeSRoland Mainz continue; 94da2e3ebdSchin case '?': 95da2e3ebdSchin error(ERROR_usage(2), "%s", opt_info.arg); 96*34f9b3eeSRoland Mainz continue; 97*34f9b3eeSRoland Mainz } 98da2e3ebdSchin break; 99da2e3ebdSchin } 100da2e3ebdSchin argv += opt_info.index; 101da2e3ebdSchin if (error_info.errors || !*argv) 102da2e3ebdSchin error(ERROR_usage(2), "%s", optusage(NiL)); 103da2e3ebdSchin mask = umask(0); 104da2e3ebdSchin if (mflag || pflag) 105da2e3ebdSchin { 106da2e3ebdSchin dmode = DIRMODE & ~mask; 107da2e3ebdSchin if (!mflag) 108da2e3ebdSchin mode = dmode; 109da2e3ebdSchin dmode |= S_IWUSR | S_IXUSR; 110da2e3ebdSchin } 111da2e3ebdSchin else 112da2e3ebdSchin { 113da2e3ebdSchin mode &= ~mask; 114da2e3ebdSchin umask(mask); 115da2e3ebdSchin mask = 0; 116da2e3ebdSchin } 117da2e3ebdSchin while (arg = *argv++) 118da2e3ebdSchin { 119da2e3ebdSchin if (mkdir(arg, mode) < 0) 120da2e3ebdSchin { 121da2e3ebdSchin if (!pflag || !(errno == ENOENT || errno == EEXIST || errno == ENOTDIR)) 122da2e3ebdSchin { 123da2e3ebdSchin error(ERROR_system(0), "%s:", arg); 124da2e3ebdSchin continue; 125da2e3ebdSchin } 126da2e3ebdSchin if (errno == EEXIST) 127da2e3ebdSchin continue; 128da2e3ebdSchin 129da2e3ebdSchin /* 130da2e3ebdSchin * -p option, preserve intermediates 131da2e3ebdSchin * first eliminate trailing /'s 132da2e3ebdSchin */ 133da2e3ebdSchin 134da2e3ebdSchin n = strlen(arg); 135da2e3ebdSchin while (n > 0 && arg[--n] == '/'); 136da2e3ebdSchin arg[n + 1] = 0; 137da2e3ebdSchin for (name = arg, n = *arg; n;) 138da2e3ebdSchin { 139da2e3ebdSchin /* skip over slashes */ 140da2e3ebdSchin while (*arg == '/') 141da2e3ebdSchin arg++; 142da2e3ebdSchin /* skip to next component */ 143da2e3ebdSchin while ((n = *arg) && n != '/') 144da2e3ebdSchin arg++; 145da2e3ebdSchin *arg = 0; 146da2e3ebdSchin if (mkdir(name, n ? dmode : mode) < 0 && errno != EEXIST && access(name, F_OK) < 0) 147da2e3ebdSchin { 148da2e3ebdSchin *arg = n; 149da2e3ebdSchin error(ERROR_system(0), "%s:", name); 150da2e3ebdSchin break; 151da2e3ebdSchin } 1527c2fbfb3SApril Chin if (!(*arg = n) && (mode & (S_ISVTX|S_ISUID|S_ISGID))) 1537c2fbfb3SApril Chin { 1547c2fbfb3SApril Chin if (stat(name, &st)) 1557c2fbfb3SApril Chin { 1567c2fbfb3SApril Chin error(ERROR_system(0), "%s: cannot stat", name); 1577c2fbfb3SApril Chin break; 1587c2fbfb3SApril Chin } 1597c2fbfb3SApril Chin if ((st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)) != (mode & (S_ISVTX|S_ISUID|S_ISGID)) && chmod(name, mode)) 1607c2fbfb3SApril Chin { 1617c2fbfb3SApril Chin error(ERROR_system(0), "%s: cannot change mode from %s to %s", name, fmtperm(st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)), fmtperm(mode)); 1627c2fbfb3SApril Chin break; 1637c2fbfb3SApril Chin } 1647c2fbfb3SApril Chin } 165da2e3ebdSchin } 166da2e3ebdSchin } 167da2e3ebdSchin } 168da2e3ebdSchin if (mask) 169da2e3ebdSchin umask(mask); 170da2e3ebdSchin return error_info.errors != 0; 171da2e3ebdSchin } 172