diff --git a/CHANGES b/CHANGES index a7109f25a0..31c2948d0c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +2555. [port] Solaris: mkdir(2) on tmpfs filesystems does not do the + error checks in the correct order resulting in the + wrong error code sometimes being returned. [RT #19249] + 2554. [bug] Validation of uppercase queries from NSEC3 zones could fail. [RT #19297] diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c index d3b2ff3a1d..fe51d0a3b1 100644 --- a/bin/named/unix/os.c +++ b/bin/named/unix/os.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.89 2008/11/14 05:08:48 marka Exp $ */ +/* $Id: os.c,v 1.89.12.1 2009/02/16 00:16:20 marka Exp $ */ /*! \file */ @@ -657,6 +657,44 @@ cleanup_pidfile(void) { pidfile = NULL; } +static int +mkdirpath(char *filename, void (*report)(const char *, ...)) { + char *slash = strrchr(filename, '/'); + char strbuf[ISC_STRERRORSIZE]; + unsigned int mode; + + if (slash != NULL && slash != filename) { + struct stat sb; + *slash = '\0'; + + if (stat(filename, &sb) == -1) { + if (errno != ENOENT) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't stat '%s': %s", filename, + strbuf); + goto error; + } + if (mkdirpath(filename, report) == -1) + goto error; + mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ + mode |= S_IRGRP | S_IXGRP; /* g=rx */ + mode |= S_IROTH | S_IXOTH; /* o=rx */ + if (mkdir(filename, mode) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't mkdir '%s': %s", filename, + strbuf); + goto error; + } + } + *slash = '/'; + } + return (0); + + error: + *slash = '/'; + return (-1); +} + void ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { int fd; @@ -665,9 +703,6 @@ ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { pid_t pid; char strbuf[ISC_STRERRORSIZE]; void (*report)(const char *, ...); - unsigned int mode; - char *slash; - int n; /* * The caller must ensure any required synchronization. @@ -687,28 +722,17 @@ ns_os_writepidfile(const char *filename, isc_boolean_t first_time) { (*report)("couldn't malloc '%s': %s", filename, strbuf); return; } + /* This is safe. */ strcpy(pidfile, filename); /* * Make the containing directory if it doesn't exist. */ - slash = strrchr(pidfile, '/'); - if (slash != NULL && slash != pidfile) { - *slash = '\0'; - mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ - mode |= S_IRGRP | S_IXGRP; /* g=rx */ - mode |= S_IROTH | S_IXOTH; /* o=rx */ - n = mkdir(pidfile, mode); - if (n == -1 && errno != EEXIST) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - (*report)("couldn't mkdir %s': %s", filename, - strbuf); - free(pidfile); - pidfile = NULL; - return; - } - *slash = '/'; + if (mkdirpath(pidfile, report) == -1) { + free(pidfile); + pidfile = NULL; + return; } fd = safe_open(filename, ISC_FALSE);