From febf5f8b55abb2e6e840488a29a5ef4e20654f67 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Thu, 27 Jul 2000 02:04:36 +0000 Subject: [PATCH] 355. [func] Added isc_dir_createunique(), similar to mkdtemp(). --- CHANGES | 2 + lib/isc/unix/dir.c | 79 +++++++++++++++++++++++++++++++--- lib/isc/unix/include/isc/dir.h | 11 ++++- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 0a433862e0..7ef2a28188 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + 355. [func] Added isc_dir_createunique(), similar to mkdtemp(). + 354. [doc] Man pages for the dnssec tools are now included in the distribution, in doc/man/dnssec. diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c index 33d5742e8b..51d3d59c2f 100644 --- a/lib/isc/unix/dir.c +++ b/lib/isc/unix/dir.c @@ -15,12 +15,16 @@ * SOFTWARE. */ -/* $Id: dir.c,v 1.10 2000/05/11 15:09:27 tale Exp $ */ +/* $Id: dir.c,v 1.11 2000/07/27 02:04:34 tale Exp $ */ /* Principal Authors: DCL */ #include +#include +#include + +#include #include #include @@ -126,10 +130,6 @@ isc_dir_reset(isc_dir_t *dir) { return (ISC_R_SUCCESS); } -/* - * XXX Is there a better place for this? - */ - isc_result_t isc_dir_chdir(const char *dirname) { /* @@ -143,3 +143,72 @@ isc_dir_chdir(const char *dirname) { return (ISC_R_SUCCESS); } + +isc_result_t +isc_dir_createunique(char *templet) { + isc_result_t result; + char *x; + char *p; + int i; + int pid; + + REQUIRE(templet != NULL); + + /* + * mkdtemp is not portable, so this emulates it. + */ + + pid = getpid(); + + /* + * Replace trailing Xs with the process-id, zero-filled. + */ + for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet; + x--, pid /= 10) + *x = pid % 10 + '0'; + + x++; /* Set x to start of ex-Xs. */ + + do { + i = mkdir(templet, 0700); + if (i == 0 || errno != EEXIST) + break; + + /* + * The BSD algorithm. + */ + p = x; + while (*p != '\0') { + if (isdigit(*p)) + *p = 'a'; + else if (*p != 'z') + ++*p; + else { + /* + * Reset character and move to next. + */ + *p++ = 'a'; + continue; + } + + break; + } + + if (*p == '\0') { + /* + * Tried all combinations. errno should already + * be EEXIST, but ensure it is anyway for + * isc__errno2result(). + */ + errno = EEXIST; + break; + } + } while (1); + + if (i == -1) + result = isc__errno2result(errno); + else + result = ISC_R_SUCCESS; + + return (result); +} diff --git a/lib/isc/unix/include/isc/dir.h b/lib/isc/unix/include/isc/dir.h index 3e928b819a..de52231fcc 100644 --- a/lib/isc/unix/include/isc/dir.h +++ b/lib/isc/unix/include/isc/dir.h @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: dir.h,v 1.8 2000/06/23 03:08:18 tale Exp $ */ +/* $Id: dir.h,v 1.9 2000/07/27 02:04:36 tale Exp $ */ /* Principal Authors: DCL */ @@ -73,6 +73,15 @@ isc_dir_close(isc_dir_t *dir); isc_result_t isc_dir_chdir(const char *dirname); +isc_result_t +isc_dir_createunique(char *templet); +/* + * Use a templet (such as from isc_file_mktemplate()) to create a uniquely + * named, empty directory. The templet string is modified in place. + * If result == ISC_R_SUCCESS, it is the name of the directory that was + * created. + */ + ISC_LANG_ENDDECLS #endif /* ISC_DIR_H */