mkdir.c revision 41842
143725Syokota/* 243725Syokota * Copyright (c) 1983, 1992, 1993 343725Syokota * The Regents of the University of California. All rights reserved. 443725Syokota * 543725Syokota * Redistribution and use in source and binary forms, with or without 643725Syokota * modification, are permitted provided that the following conditions 743725Syokota * are met: 843725Syokota * 1. Redistributions of source code must retain the above copyright 943725Syokota * notice, this list of conditions and the following disclaimer. 1043725Syokota * 2. Redistributions in binary form must reproduce the above copyright 1143725Syokota * notice, this list of conditions and the following disclaimer in the 1243725Syokota * documentation and/or other materials provided with the distribution. 1343725Syokota * 3. All advertising materials mentioning features or use of this software 1443725Syokota * must display the following acknowledgement: 1543725Syokota * This product includes software developed by the University of 1643725Syokota * California, Berkeley and its contributors. 1743725Syokota * 4. Neither the name of the University nor the names of its contributors 1843725Syokota * may be used to endorse or promote products derived from this software 1943725Syokota * without specific prior written permission. 2043725Syokota * 2143725Syokota * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2243725Syokota * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2343725Syokota * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2443725Syokota * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2543725Syokota * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2643725Syokota * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2750476Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2843725Syokota * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29222793Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3053200Sphantom * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3179538Sru * SUCH DAMAGE. 3243725Syokota */ 3343725Syokota 3453200Sphantom#ifndef lint 3543725Syokotastatic char const copyright[] = 3647571Syokota"@(#) Copyright (c) 1983, 1992, 1993\n\ 3756188Sasmodai The Regents of the University of California. All rights reserved.\n"; 3847571Syokota#endif /* not lint */ 3984877Syokota 4084877Syokota#ifndef lint 4184877Syokota#if 0 4284877Syokotastatic char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94"; 4384877Syokota#endif 4484877Syokotastatic const char rcsid[] = 4543725Syokota "$Id: mkdir.c,v 1.15 1998/10/23 06:28:40 msmith Exp $"; 4643725Syokota#endif /* not lint */ 4743725Syokota 4843725Syokota#include <sys/types.h> 4943725Syokota#include <sys/stat.h> 5043725Syokota 5143725Syokota#include <err.h> 5243725Syokota#include <errno.h> 53158687Sphk#include <stdio.h> 54162404Sru#include <stdlib.h> 5543725Syokota#include <string.h> 5643844Syokota#include <unistd.h> 5743725Syokota 58117011Sruint build __P((char *, mode_t)); 59117011Sruvoid usage __P((void)); 6043725Syokota 6143844Syokotaint 6243844Syokotamain(argc, argv) 6343844Syokota int argc; 6443844Syokota char *argv[]; 6548634Syokota{ 6648634Syokota int ch, exitval, success, omode, pflag; 6748634Syokota mode_t *set = (mode_t *)NULL; 6848634Syokota char *mode; 6948634Syokota 7048634Syokota omode = pflag = 0; 71175799Strhodes mode = NULL; 72175799Strhodes while ((ch = getopt(argc, argv, "m:p")) != -1) 73175799Strhodes switch(ch) { 74175799Strhodes case 'p': 75175799Strhodes pflag = 1; 7648634Syokota break; 7770466Sru case 'm': 7849282Smpp mode = optarg; 7949282Smpp break; 8049282Smpp case '?': 81131530Sru default: 8249282Smpp usage(); 83131530Sru } 8449282Smpp 85131530Sru argc -= optind; 8649282Smpp argv += optind; 87131530Sru if (argv[0] == NULL) 8849282Smpp usage(); 8949282Smpp 9049282Smpp if (mode == NULL) { 9149282Smpp omode = S_IRWXU | S_IRWXG | S_IRWXO; 9249282Smpp } else { 9349282Smpp if ((set = setmode(mode)) == NULL) 9449282Smpp errx(1, "invalid file mode: %s", mode); 9549282Smpp omode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO); 9649282Smpp free(set); 9749282Smpp } 9849282Smpp 9949282Smpp for (exitval = 0; *argv != NULL; ++argv) { 10049282Smpp success = 1; 10149282Smpp if (pflag) { 10249282Smpp if (build(*argv, omode)) 10379727Sschweikh success = 0; 10449282Smpp } else if (mkdir(*argv, omode) < 0) { 10549282Smpp warn("%s", *argv); 10649282Smpp success = 0; 10749282Smpp } 10849282Smpp if (!success) 10949282Smpp exitval = 1; 11049282Smpp /* 11149282Smpp * The mkdir() and umask() calls both honor only the low 11249282Smpp * nine bits, so if you try to set a mode including the 11349282Smpp * sticky, setuid, setgid bits you lose them. Don't do 11449282Smpp * this unless the user has specifically requested a mode, 11549282Smpp * as chmod will (obviously) ignore the umask. 11649282Smpp */ 11749282Smpp if (success && mode != NULL && chmod(*argv, omode) == -1) { 11849282Smpp warn("%s", *argv); 11949282Smpp exitval = 1; 120175799Strhodes } 121175799Strhodes } 12249282Smpp exit(exitval); 12348634Syokota} 12448634Syokota 12548634Syokotaint 12648634Syokotabuild(path, omode) 12743725Syokota char *path; 12847571Syokota mode_t omode; 12947571Syokota{ 13047571Syokota struct stat sb; 13147571Syokota mode_t numask, oumask; 13247571Syokota int first, last, retval; 13347571Syokota char *p; 13489610Smpp 13547571Syokota p = path; 13647571Syokota oumask = 0; 13747571Syokota retval = 0; 13868854Sru if (p[0] == '/') /* Skip leading '/'. */ 13947571Syokota ++p; 14047571Syokota for (first = 1, last = 0; !last ; ++p) { 14147571Syokota if (p[0] == '\0') 14247571Syokota last = 1; 14347571Syokota else if (p[0] != '/') 14447571Syokota continue; 14547571Syokota *p = '\0'; 14647571Syokota if (p[1] == '\0') 14743725Syokota last = 1; 14843725Syokota if (first) { 14943725Syokota /* 15084877Syokota * POSIX 1003.2: 15184877Syokota * For each dir operand that does not name an existing 15284877Syokota * directory, effects equivalent to those cased by the 15384877Syokota * following command shall occcur: 15481251Sru * 15584877Syokota * mkdir -p -m $(umask -S),u+wx $(dirname dir) && 15643844Syokota * mkdir [-m mode] dir 15743844Syokota * 15843725Syokota * We change the user's umask and then restore it, 15943725Syokota * instead of doing chmod's. 16043725Syokota */ 16143725Syokota oumask = umask(0); 16243844Syokota numask = oumask & ~(S_IWUSR | S_IXUSR); 16343844Syokota (void)umask(numask); 16443725Syokota first = 0; 16543725Syokota } 16643725Syokota if (last) 16743725Syokota (void)umask(oumask); 16843844Syokota if (stat(path, &sb)) { 16943725Syokota if (errno != ENOENT || 17043844Syokota mkdir(path, last ? omode : 17179727Sschweikh S_IRWXU | S_IRWXG | S_IRWXO) < 0) { 17243725Syokota warn("%s", path); 173138901Sjhb retval = 1; 174138901Sjhb break; 175138901Sjhb } 176138901Sjhb } 177138901Sjhb else if ((sb.st_mode & S_IFMT) != S_IFDIR) { 17843725Syokota if (last) 17943725Syokota errno = EEXIST; 18068854Sru else 18179727Sschweikh errno = ENOTDIR; 18247571Syokota warn("%s", path); 18347571Syokota retval = 1; 18447571Syokota break; 18547571Syokota } 18647571Syokota if (!last) 18784877Syokota *p = '/'; 18884877Syokota } 18947571Syokota if (!first && !last) 19047571Syokota (void)umask(oumask); 19147571Syokota return (retval); 19247571Syokota} 19347571Syokota 19484877Syokotavoid 19547571Syokotausage() 19656188Sasmodai{ 19784877Syokota (void)fprintf(stderr, "usage: mkdir [-p] [-m mode] directory ...\n"); 19847571Syokota exit (1); 19984877Syokota} 20084877Syokota