diff --git a/CHANGES b/CHANGES index 3312903780..7923d11b31 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1287. [func] isc_file_openunique() now creates file using mode + 0666 rather than 0600. + 1286. [bug] ISC_LINK_INIT, ISC_LINK_UNLINK, ISC_LIST_DEQUEUE, __ISC_LINK_UNLINKUNSAFE and __ISC_LIST_DEQUEUEUNSAFE are not C++ compatible, use *_TYPE versions instead. diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c index c5d4e755a6..1979b21563 100644 --- a/lib/isc/unix/file.c +++ b/lib/isc/unix/file.c @@ -15,21 +15,24 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: file.c,v 1.42 2001/11/30 01:59:42 gson Exp $ */ +/* $Id: file.c,v 1.43 2002/05/09 09:08:56 marka Exp $ */ #include #include +#include #include #include #include /* Required for utimes on some platforms. */ #include /* Required for mkstemp on NetBSD. */ + #include #include #include #include +#include #include #include #include @@ -182,33 +185,60 @@ isc_file_renameunique(const char *file, char *templet) { return (result); } +static char alphnum[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + isc_result_t isc_file_openunique(char *templet, FILE **fp) { int fd; FILE *f; isc_result_t result = ISC_R_SUCCESS; + char *x; + char *cp; + isc_uint32_t which; + int mode; REQUIRE(templet != NULL); REQUIRE(fp != NULL && *fp == NULL); - /* - * Win32 does not have mkstemp. - */ - fd = mkstemp(templet); - - if (fd == -1) - result = isc__errno2result(errno); - if (result == ISC_R_SUCCESS) { - f = fdopen(fd, "w+"); - if (f == NULL) { - result = isc__errno2result(errno); - (void)remove(templet); - (void)close(fd); - - } else - *fp = f; + cp = templet; + while (*cp != '\0') + cp++; + if (cp == templet) + return (ISC_R_FAILURE); + x = cp--; + while (*cp == 'X' && cp >= templet) { + isc_random_get(&which); + *cp = alphnum[which % (sizeof(alphnum) - 1)]; + x = cp--; } + mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; + + while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) { + if (errno != EEXIST) + return (isc__errno2result(errno)); + for (cp = x;;) { + char *t; + if (*cp == '\0') + return (ISC_R_FAILURE); + t = strchr(alphnum, *cp); + if (t == NULL || *++t == '\0') + *cp++ = alphnum[0]; + else { + *cp = *t; + break; + } + } + } + f = fdopen(fd, "w+"); + if (f == NULL) { + result = isc__errno2result(errno); + (void)remove(templet); + (void)close(fd); + } else + *fp = f; + return (result); }