X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=lib_internal%2Fmkdir.c;fp=lib_internal%2Fmkdir.c;h=717de0ece4e70e0c86d0b1c8606cd09184b5897d;hb=4415d2a7377be61789eb5a6e35222962cbe7a146;hp=0000000000000000000000000000000000000000;hpb=b0a62d195efca12c5cb9e7c0b3bea3be2cd57fc9;p=util-vserver.git diff --git a/lib_internal/mkdir.c b/lib_internal/mkdir.c new file mode 100644 index 0000000..717de0e --- /dev/null +++ b/lib_internal/mkdir.c @@ -0,0 +1,84 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2005 Enrico Scholz +// +// 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; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include + +static enum { mkdirFAIL, mkdirSUCCESS, mkdirSKIP } +mkdirSingle(char const *path, char *end_ptr, int good_err) +{ + *end_ptr = '\0'; + if (mkdir(path, 0700)!=-1 || errno==EEXIST) { + *end_ptr = '/'; + return mkdirSUCCESS; + } + else if (errno==good_err) { + *end_ptr = '/'; + return mkdirSKIP; + } + else + return mkdirFAIL; +} + +static char * +rstrchr(char *str, char c) +{ + while (*str!=c) --str; + return str; +} + +bool +mkdirRecursive(char const *path) +{ + char buf[strlen(path)+1]; + char * ptr = buf + sizeof(buf) - 2; + + if (path[0]!='/') return false; // only absolute paths + + strcpy(buf, path); + + while (ptr>buf && (ptr = rstrchr(ptr, '/'))!=0) { + switch (mkdirSingle(buf, ptr, ENOENT)) { + case mkdirSUCCESS : break; + case mkdirSKIP : --ptr; continue; + case mkdirFAIL : return false; + } + + break; // implied by mkdirSUCCESS + } + + assert(ptr!=0); + ++ptr; + + while ((ptr=strchr(ptr, '/'))!=0) { + switch (mkdirSingle(buf, ptr, 0)) { + case mkdirSKIP : + case mkdirFAIL : return false; + case mkdirSUCCESS : ++ptr; continue; + } + } + + return true; +}