libexplain  1.4.D001
libexplain/mkdtemp_on_error.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2010-2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 3 of the License, or (at
00008  * your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/errno.h>
00020 #include <libexplain/ac/limits.h> /* for PATH_MAX on Solaris */
00021 #include <libexplain/ac/stdlib.h>
00022 #include <libexplain/ac/stdio.h> /* for TMP_MAX */
00023 #include <libexplain/ac/string.h>
00024 #include <libexplain/ac/sys/param.h> /* for PATH_MAX everywhere else */
00025 #include <libexplain/ac/sys/stat.h>
00026 
00027 #include <libexplain/is_efault.h>
00028 #include <libexplain/mkdtemp.h>
00029 #include <libexplain/output.h>
00030 
00031 
00032 #ifndef HAVE_MKDTEMP
00033 
00034 static char *
00035 mkdtemp(char *template)
00036 {
00037     char            stash[PATH_MAX + 1];
00038     size_t          template_size;
00039     int             n;
00040     int             save_errno;
00041 
00042     save_errno = errno;
00043     if (explain_is_efault_string(template))
00044     {
00045         errno = EFAULT;
00046         return NULL;
00047     }
00048     template_size = strlen(template) + 1;
00049     if (template_size > sizeof(stash))
00050     {
00051         errno = ENAMETOOLONG;
00052         return NULL;
00053     }
00054     memcpy(stash, template, template_size);
00055     for (n = 0; n < TMP_MAX; ++n)
00056     {
00057         if (!mkstemp(template))
00058             return NULL;
00059         if (mkdir(template, 0700) >= 0)
00060         {
00061             errno = save_errno;
00062             return template;
00063         }
00064         if (errno != EEXIST)
00065             return NULL;
00066         memcpy(template, stash, template_size);
00067     }
00068 
00069     /*
00070      * This is the defined error in the case where when we run out of
00071      * combinations to try.  "Everything we tried already existed."
00072      */
00073     errno = EEXIST;
00074     return NULL;
00075 }
00076 
00077 #endif
00078 
00079 char *
00080 explain_mkdtemp_on_error(char *pathname)
00081 {
00082     char            *result;
00083 
00084     result = mkdtemp(pathname);
00085     if (!result)
00086     {
00087         int             hold_errno;
00088 
00089         hold_errno = errno;
00090         explain_output_error("%s", explain_errno_mkdtemp(hold_errno,
00091             pathname));
00092         errno = hold_errno;
00093     }
00094     return result;
00095 }
00096 
00097 
00098 /* vim: set ts=8 sw=4 et : */