11e72d8d2Sderaadt /* mkrmdir.c -- BSD compatible directory functions for System V
21e72d8d2Sderaadt Copyright (C) 1988, 1990 Free Software Foundation, Inc.
31e72d8d2Sderaadt
41e72d8d2Sderaadt This program is free software; you can redistribute it and/or modify
51e72d8d2Sderaadt it under the terms of the GNU General Public License as published by
61e72d8d2Sderaadt the Free Software Foundation; either version 2, or (at your option)
71e72d8d2Sderaadt any later version.
81e72d8d2Sderaadt
91e72d8d2Sderaadt This program is distributed in the hope that it will be useful,
101e72d8d2Sderaadt but WITHOUT ANY WARRANTY; without even the implied warranty of
111e72d8d2Sderaadt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*461cc63eStholo GNU General Public License for more details. */
131e72d8d2Sderaadt
141e72d8d2Sderaadt #ifdef HAVE_CONFIG_H
151e72d8d2Sderaadt #include "config.h"
161e72d8d2Sderaadt #endif
171e72d8d2Sderaadt
181e72d8d2Sderaadt #include <sys/types.h>
191e72d8d2Sderaadt #include <sys/stat.h>
201e72d8d2Sderaadt #include <errno.h>
211e72d8d2Sderaadt #ifndef STDC_HEADERS
221e72d8d2Sderaadt extern int errno;
231e72d8d2Sderaadt #endif
241e72d8d2Sderaadt
251e72d8d2Sderaadt /* mkdir and rmdir adapted from GNU tar. */
261e72d8d2Sderaadt
271e72d8d2Sderaadt /* Make directory DPATH, with permission mode DMODE.
281e72d8d2Sderaadt
291e72d8d2Sderaadt Written by Robert Rother, Mariah Corporation, August 1985
301e72d8d2Sderaadt (sdcsvax!rmr or rmr@uscd). If you want it, it's yours.
311e72d8d2Sderaadt
321e72d8d2Sderaadt Severely hacked over by John Gilmore to make a 4.2BSD compatible
331e72d8d2Sderaadt subroutine. 11Mar86; hoptoad!gnu
341e72d8d2Sderaadt
351e72d8d2Sderaadt Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
361e72d8d2Sderaadt subroutine didn't return EEXIST. It does now. */
371e72d8d2Sderaadt
381e72d8d2Sderaadt int
mkdir(dpath,dmode)391e72d8d2Sderaadt mkdir (dpath, dmode)
401e72d8d2Sderaadt char *dpath;
411e72d8d2Sderaadt int dmode;
421e72d8d2Sderaadt {
431e72d8d2Sderaadt int cpid, status;
441e72d8d2Sderaadt struct stat statbuf;
451e72d8d2Sderaadt
461e72d8d2Sderaadt if (stat (dpath, &statbuf) == 0)
471e72d8d2Sderaadt {
481e72d8d2Sderaadt errno = EEXIST; /* stat worked, so it already exists. */
491e72d8d2Sderaadt return -1;
501e72d8d2Sderaadt }
511e72d8d2Sderaadt
521e72d8d2Sderaadt /* If stat fails for a reason other than non-existence, return error. */
5313571821Stholo if (! existence_error (errno))
541e72d8d2Sderaadt return -1;
551e72d8d2Sderaadt
561e72d8d2Sderaadt cpid = fork ();
571e72d8d2Sderaadt switch (cpid)
581e72d8d2Sderaadt {
591e72d8d2Sderaadt case -1: /* Cannot fork. */
601e72d8d2Sderaadt return -1; /* errno is set already. */
611e72d8d2Sderaadt
621e72d8d2Sderaadt case 0: /* Child process. */
631e72d8d2Sderaadt /* Cheap hack to set mode of new directory. Since this child
641e72d8d2Sderaadt process is going away anyway, we zap its umask.
651e72d8d2Sderaadt This won't suffice to set SUID, SGID, etc. on this
661e72d8d2Sderaadt directory, so the parent process calls chmod afterward. */
671e72d8d2Sderaadt status = umask (0); /* Get current umask. */
681e72d8d2Sderaadt umask (status | (0777 & ~dmode)); /* Set for mkdir. */
691e72d8d2Sderaadt execl ("/bin/mkdir", "mkdir", dpath, (char *) 0);
701e72d8d2Sderaadt _exit (1);
711e72d8d2Sderaadt
721e72d8d2Sderaadt default: /* Parent process. */
731e72d8d2Sderaadt while (wait (&status) != cpid) /* Wait for kid to finish. */
741e72d8d2Sderaadt /* Do nothing. */ ;
751e72d8d2Sderaadt
761e72d8d2Sderaadt if (status & 0xFFFF)
771e72d8d2Sderaadt {
781e72d8d2Sderaadt errno = EIO; /* /bin/mkdir failed. */
791e72d8d2Sderaadt return -1;
801e72d8d2Sderaadt }
811e72d8d2Sderaadt return chmod (dpath, dmode);
821e72d8d2Sderaadt }
831e72d8d2Sderaadt }
841e72d8d2Sderaadt
851e72d8d2Sderaadt /* Remove directory DPATH.
861e72d8d2Sderaadt Return 0 if successful, -1 if not. */
871e72d8d2Sderaadt
881e72d8d2Sderaadt int
rmdir(dpath)891e72d8d2Sderaadt rmdir (dpath)
901e72d8d2Sderaadt char *dpath;
911e72d8d2Sderaadt {
921e72d8d2Sderaadt int cpid, status;
931e72d8d2Sderaadt struct stat statbuf;
941e72d8d2Sderaadt
951e72d8d2Sderaadt if (stat (dpath, &statbuf) != 0)
961e72d8d2Sderaadt return -1; /* stat set errno. */
971e72d8d2Sderaadt
981e72d8d2Sderaadt if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
991e72d8d2Sderaadt {
1001e72d8d2Sderaadt errno = ENOTDIR;
1011e72d8d2Sderaadt return -1;
1021e72d8d2Sderaadt }
1031e72d8d2Sderaadt
1041e72d8d2Sderaadt cpid = fork ();
1051e72d8d2Sderaadt switch (cpid)
1061e72d8d2Sderaadt {
1071e72d8d2Sderaadt case -1: /* Cannot fork. */
1081e72d8d2Sderaadt return -1; /* errno is set already. */
1091e72d8d2Sderaadt
1101e72d8d2Sderaadt case 0: /* Child process. */
1111e72d8d2Sderaadt execl ("/bin/rmdir", "rmdir", dpath, (char *) 0);
1121e72d8d2Sderaadt _exit (1);
1131e72d8d2Sderaadt
1141e72d8d2Sderaadt default: /* Parent process. */
1151e72d8d2Sderaadt while (wait (&status) != cpid) /* Wait for kid to finish. */
1161e72d8d2Sderaadt /* Do nothing. */ ;
1171e72d8d2Sderaadt
1181e72d8d2Sderaadt if (status & 0xFFFF)
1191e72d8d2Sderaadt {
1201e72d8d2Sderaadt errno = EIO; /* /bin/rmdir failed. */
1211e72d8d2Sderaadt return -1;
1221e72d8d2Sderaadt }
1231e72d8d2Sderaadt return 0;
1241e72d8d2Sderaadt }
1251e72d8d2Sderaadt }
126