xref: /openbsd-src/gnu/usr.bin/cvs/lib/mkdir.c (revision 461cc63e7458ce60db55037c1a7656349538b52f)
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