X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fmkdir.c;h=67f29d456c6f0e0ba93270113d880f6c94d933c4;hb=fa1db0dd22768f09a507674a30beb5b8a87bb35f;hp=efde52e055abb31396d596a310b94b621af85226;hpb=47a70ed9f7a874deda74aff3c33fc61376775860;p=gnulib.git diff --git a/lib/mkdir.c b/lib/mkdir.c index efde52e05..67f29d456 100644 --- a/lib/mkdir.c +++ b/lib/mkdir.c @@ -1,10 +1,12 @@ -/* mkdir.c -- BSD compatible make directory function for System V - Copyright (C) 1988, 1990 Free Software Foundation, Inc. +/* On some systems, mkdir ("foo/", 0700) fails because of the trailing + slash. On those systems, this wrapper removes the trailing slash. - This program is free software; you can redistribute it and/or modify + Copyright (C) 2001, 2003, 2006, 2008-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -12,86 +14,80 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + along with this program. If not, see . */ + +/* written by Jim Meyering */ -#ifdef HAVE_CONFIG_H #include -#endif -#include +/* Specification. */ #include -#include -#ifndef errno -extern int errno; -#endif - -#ifdef STAT_MACROS_BROKEN -#undef S_ISDIR -#endif -#if !defined(S_ISDIR) && defined(S_IFDIR) -#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#include +#include +#include +#include + +#include "dirname.h" + +/* Disable the definition of mkdir to rpl_mkdir (from the + substitute) in this file. Otherwise, we'd get an endless recursion. */ +#undef mkdir + +/* mingw's _mkdir() function has 1 argument, but we pass 2 arguments. + Additionally, it declares _mkdir (and depending on compile flags, an + alias mkdir), only in the nonstandard includes and , + which are included in the override. */ +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# define mkdir(name,mode) _mkdir (name) +# define maybe_unused _GL_UNUSED +#else +# define maybe_unused /* empty */ #endif -/* mkdir adapted from GNU tar. */ - -/* Make directory DPATH, with permission mode DMODE. - - Written by Robert Rother, Mariah Corporation, August 1985 - (sdcsvax!rmr or rmr@uscd). If you want it, it's yours. - - Severely hacked over by John Gilmore to make a 4.2BSD compatible - subroutine. 11Mar86; hoptoad!gnu - - Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir, - subroutine didn't return EEXIST. It does now. */ +/* This function is required at least for NetBSD 1.5.2. */ int -mkdir (dpath, dmode) - char *dpath; - int dmode; +rpl_mkdir (char const *dir, mode_t mode maybe_unused) { - int cpid, status; - struct stat statbuf; + int ret_val; + char *tmp_dir; + size_t len = strlen (dir); - if (stat (dpath, &statbuf) == 0) + if (len && dir[len - 1] == '/') { - errno = EEXIST; /* stat worked, so it already exists. */ - return -1; + tmp_dir = strdup (dir); + if (!tmp_dir) + { + /* Rather than rely on strdup-posix, we set errno ourselves. */ + errno = ENOMEM; + return -1; + } + strip_trailing_slashes (tmp_dir); } - - /* If stat fails for a reason other than non-existence, return error. */ - if (errno != ENOENT) - return -1; - - cpid = fork (); - switch (cpid) + else { - case -1: /* Cannot fork. */ - return -1; /* errno is already set. */ - - case 0: /* Child process. */ - /* Cheap hack to set mode of new directory. Since this child - process is going away anyway, we zap its umask. - This won't suffice to set SUID, SGID, etc. on this - directory, so the parent process calls chmod afterward. */ - status = umask (0); /* Get current umask. */ - umask (status | (0777 & ~dmode)); /* Set for mkdir. */ - execl ("/bin/mkdir", "mkdir", dpath, (char *) 0); - _exit (1); - - default: /* Parent process. */ - /* Wait for kid to finish. */ - while (wait (&status) != cpid) - /* Do nothing. */ ; - - if (status & 0xFFFF) - { - /* /bin/mkdir failed. */ - errno = EIO; - return -1; - } - return chmod (dpath, dmode); + tmp_dir = (char *) dir; } +#if FUNC_MKDIR_DOT_BUG + /* Additionally, cygwin 1.5 mistakenly creates a directory "d/./". */ + { + char *last = last_component (tmp_dir); + if (*last == '.' && (last[1] == '\0' + || (last[1] == '.' && last[2] == '\0'))) + { + struct stat st; + if (stat (tmp_dir, &st) == 0) + errno = EEXIST; + return -1; + } + } +#endif /* FUNC_MKDIR_DOT_BUG */ + + ret_val = mkdir (tmp_dir, mode); + + if (tmp_dir != dir) + free (tmp_dir); + + return ret_val; }