Update.
[glibc.git] / db2 / common / db_appinit.c
blob6ec007be0a0d335c52f08abfe2128372345ff5f2
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "@(#)db_appinit.c 10.52 (Sleepycat) 6/2/98";
12 #endif /* not lint */
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #endif
25 #include "db_int.h"
26 #include "shqueue.h"
27 #include "db_page.h"
28 #include "btree.h"
29 #include "hash.h"
30 #include "log.h"
31 #include "txn.h"
32 #include "clib_ext.h"
33 #include "common_ext.h"
35 static int __db_home __P((DB_ENV *, const char *, u_int32_t));
36 static int __db_parse __P((DB_ENV *, char *));
37 static int __db_tmp_dir __P((DB_ENV *, u_int32_t));
38 static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, int *));
41 * db_version --
42 * Return version information.
44 char *
45 db_version(majverp, minverp, patchp)
46 int *majverp, *minverp, *patchp;
48 if (majverp != NULL)
49 *majverp = DB_VERSION_MAJOR;
50 if (minverp != NULL)
51 *minverp = DB_VERSION_MINOR;
52 if (patchp != NULL)
53 *patchp = DB_VERSION_PATCH;
54 return ((char *)DB_VERSION_STRING);
58 * db_appinit --
59 * Initialize the application environment.
61 int
62 db_appinit(db_home, db_config, dbenv, flags)
63 const char *db_home;
64 char * const *db_config;
65 DB_ENV *dbenv;
66 u_int32_t flags;
68 FILE *fp;
69 int mode, ret;
70 char * const *p;
71 char *lp, buf[MAXPATHLEN * 2];
73 /* Validate arguments. */
74 if (dbenv == NULL)
75 return (EINVAL);
78 #ifdef HAVE_SPINLOCKS
79 #define OKFLAGS \
80 (DB_CREATE | DB_NOMMAP | DB_THREAD | DB_INIT_LOCK | DB_INIT_LOG | \
81 DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_RECOVER | \
82 DB_RECOVER_FATAL | DB_TXN_NOSYNC | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
83 #else
84 #define OKFLAGS \
85 (DB_CREATE | DB_NOMMAP | DB_INIT_LOCK | DB_INIT_LOG | \
86 DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_RECOVER | \
87 DB_RECOVER_FATAL | DB_TXN_NOSYNC | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT)
88 #endif
89 if ((ret = __db_fchk(dbenv, "db_appinit", flags, OKFLAGS)) != 0)
90 return (ret);
92 /* Transactions imply logging. */
93 if (LF_ISSET(DB_INIT_TXN))
94 LF_SET(DB_INIT_LOG);
96 /* Convert the db_appinit(3) flags. */
97 if (LF_ISSET(DB_THREAD))
98 F_SET(dbenv, DB_ENV_THREAD);
100 fp = NULL;
102 /* Set the database home. */
103 if ((ret = __db_home(dbenv, db_home, flags)) != 0)
104 goto err;
106 /* Parse the config array. */
107 for (p = db_config; p != NULL && *p != NULL; ++p)
108 if ((ret = __db_parse(dbenv, *p)) != 0)
109 goto err;
112 * Parse the config file.
114 * XXX
115 * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
116 * the latter isn't standard, and we're manipulating strings handed
117 * us by the application.
119 if (dbenv->db_home != NULL) {
120 #define CONFIG_NAME "/DB_CONFIG"
121 if (strlen(dbenv->db_home) +
122 strlen(CONFIG_NAME) + 1 > sizeof(buf)) {
123 ret = ENAMETOOLONG;
124 goto err;
126 (void)strcpy(buf, dbenv->db_home);
127 (void)strcat(buf, CONFIG_NAME);
128 if ((fp = fopen(buf, "r")) != NULL) {
129 while (fgets(buf, sizeof(buf), fp) != NULL) {
130 if ((lp = strchr(buf, '\n')) != NULL)
131 *lp = '\0';
132 if ((ret = __db_parse(dbenv, buf)) != 0)
133 goto err;
135 (void)fclose(fp);
136 fp = NULL;
140 /* Set up the tmp directory path. */
141 if (dbenv->db_tmp_dir == NULL &&
142 (ret = __db_tmp_dir(dbenv, flags)) != 0)
143 goto err;
145 /* Indicate that the path names have been set. */
146 F_SET(dbenv, DB_ENV_APPINIT);
149 * If we are doing recovery, remove all the old shared memory
150 * regions.
152 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) {
153 if ((ret = log_unlink(NULL, 1, dbenv)) != 0)
154 goto err;
155 if ((ret = memp_unlink(NULL, 1, dbenv)) != 0)
156 goto err;
157 if ((ret = lock_unlink(NULL, 1, dbenv)) != 0)
158 goto err;
159 if ((ret = txn_unlink(NULL, 1, dbenv)) != 0)
160 goto err;
164 * Create the new shared regions.
166 * Default permissions are read-write for both owner and group.
168 mode = __db_omode("rwrw--");
169 if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL,
170 LF_ISSET(DB_CREATE | DB_THREAD),
171 mode, dbenv, &dbenv->lk_info)) != 0)
172 goto err;
173 if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL,
174 LF_ISSET(DB_CREATE | DB_THREAD),
175 mode, dbenv, &dbenv->lg_info)) != 0)
176 goto err;
177 if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL,
178 LF_ISSET(DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD),
179 mode, dbenv, &dbenv->mp_info)) != 0)
180 goto err;
181 if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL,
182 LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC),
183 mode, dbenv, &dbenv->tx_info)) != 0)
184 goto err;
187 * If the application is running with transactions, initialize the
188 * function tables. Once that's done, do recovery for any previous
189 * run.
191 if (LF_ISSET(DB_INIT_TXN)) {
192 if ((ret = __bam_init_recover(dbenv)) != 0)
193 goto err;
194 if ((ret = __db_init_recover(dbenv)) != 0)
195 goto err;
196 if ((ret = __ham_init_recover(dbenv)) != 0)
197 goto err;
198 if ((ret = __log_init_recover(dbenv)) != 0)
199 goto err;
200 if ((ret = __txn_init_recover(dbenv)) != 0)
201 goto err;
203 if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) &&
204 (ret = __db_apprec(dbenv,
205 LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0)
206 goto err;
209 return (ret);
211 err: if (fp != NULL)
212 (void)fclose(fp);
214 (void)db_appexit(dbenv);
215 return (ret);
219 * db_appexit --
220 * Close down the default application environment.
223 db_appexit(dbenv)
224 DB_ENV *dbenv;
226 int ret, t_ret;
227 char **p;
229 ret = 0;
231 /* Close subsystems. */
232 if (dbenv->tx_info && (t_ret = txn_close(dbenv->tx_info)) != 0)
233 if (ret == 0)
234 ret = t_ret;
235 if (dbenv->mp_info && (t_ret = memp_close(dbenv->mp_info)) != 0)
236 if (ret == 0)
237 ret = t_ret;
238 if (dbenv->lg_info && (t_ret = log_close(dbenv->lg_info)) != 0)
239 if (ret == 0)
240 ret = t_ret;
241 if (dbenv->lk_info && (t_ret = lock_close(dbenv->lk_info)) != 0)
242 if (ret == 0)
243 ret = t_ret;
245 /* Free allocated memory. */
246 if (dbenv->db_home != NULL)
247 FREES(dbenv->db_home);
248 if ((p = dbenv->db_data_dir) != NULL) {
249 for (; *p != NULL; ++p)
250 FREES(*p);
251 FREE(dbenv->db_data_dir, dbenv->data_cnt * sizeof(char **));
253 if (dbenv->db_log_dir != NULL)
254 FREES(dbenv->db_log_dir);
255 if (dbenv->db_tmp_dir != NULL)
256 FREES(dbenv->db_tmp_dir);
258 return (ret);
261 #define DB_ADDSTR(str) { \
262 if ((str) != NULL) { \
263 /* If leading slash, start over. */ \
264 if (__db_abspath(str)) { \
265 p = start; \
266 slash = 0; \
268 /* Append to the current string. */ \
269 len = strlen(str); \
270 if (slash) \
271 *p++ = PATH_SEPARATOR[0]; \
272 memcpy(p, str, len); \
273 p += len; \
274 slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \
279 * __db_appname --
280 * Given an optional DB environment, directory and file name and type
281 * of call, build a path based on the db_appinit(3) rules, and return
282 * it in allocated space.
284 * PUBLIC: int __db_appname __P((DB_ENV *,
285 * PUBLIC: APPNAME, const char *, const char *, u_int32_t, int *, char **));
288 __db_appname(dbenv, appname, dir, file, tmp_oflags, fdp, namep)
289 DB_ENV *dbenv;
290 APPNAME appname;
291 const char *dir, *file;
292 u_int32_t tmp_oflags;
293 int *fdp;
294 char **namep;
296 DB_ENV etmp;
297 size_t len;
298 int data_entry, ret, slash, tmp_create, tmp_free;
299 const char *a, *b, *c;
300 char *p, *start;
302 a = b = c = NULL;
303 data_entry = -1;
304 tmp_create = tmp_free = 0;
307 * We don't return a name when creating temporary files, just an fd.
308 * Default to error now.
310 if (fdp != NULL)
311 *fdp = -1;
312 if (namep != NULL)
313 *namep = NULL;
316 * Absolute path names are never modified. If the file is an absolute
317 * path, we're done. If the directory is, simply append the file and
318 * return.
320 if (file != NULL && __db_abspath(file))
321 return ((*namep =
322 (char *)__db_strdup(file)) == NULL ? ENOMEM : 0);
323 if (dir != NULL && __db_abspath(dir)) {
324 a = dir;
325 goto done;
329 * DB_ENV DIR APPNAME RESULT
330 * -------------------------------------------
331 * null null none <tmp>/file
332 * null set none DIR/file
333 * set null none DB_HOME/file
334 * set set none DB_HOME/DIR/file
336 * DB_ENV FILE APPNAME RESULT
337 * -------------------------------------------
338 * null null DB_APP_DATA <tmp>/<create>
339 * null set DB_APP_DATA ./file
340 * set null DB_APP_DATA <tmp>/<create>
341 * set set DB_APP_DATA DB_HOME/DB_DATA_DIR/file
343 * DB_ENV DIR APPNAME RESULT
344 * -------------------------------------------
345 * null null DB_APP_LOG <tmp>/file
346 * null set DB_APP_LOG DIR/file
347 * set null DB_APP_LOG DB_HOME/DB_LOG_DIR/file
348 * set set DB_APP_LOG DB_HOME/DB_LOG_DIR/DIR/file
350 * DB_ENV APPNAME RESULT
351 * -------------------------------------------
352 * null DB_APP_TMP* <tmp>/<create>
353 * set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create>
355 retry: switch (appname) {
356 case DB_APP_NONE:
357 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
358 if (dir == NULL)
359 goto tmp;
360 a = dir;
361 } else {
362 a = dbenv->db_home;
363 b = dir;
365 break;
366 case DB_APP_DATA:
367 if (dir != NULL) {
368 __db_err(dbenv,
369 "DB_APP_DATA: illegal directory specification");
370 return (EINVAL);
373 if (file == NULL) {
374 tmp_create = 1;
375 goto tmp;
377 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
378 a = PATH_DOT;
379 else {
380 a = dbenv->db_home;
381 if (dbenv->db_data_dir != NULL &&
382 (b = dbenv->db_data_dir[++data_entry]) == NULL) {
383 data_entry = -1;
384 b = dbenv->db_data_dir[0];
387 break;
388 case DB_APP_LOG:
389 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
390 if (dir == NULL)
391 goto tmp;
392 a = dir;
393 } else {
394 a = dbenv->db_home;
395 b = dbenv->db_log_dir;
396 c = dir;
398 break;
399 case DB_APP_TMP:
400 if (dir != NULL || file != NULL) {
401 __db_err(dbenv,
402 "DB_APP_TMP: illegal directory or file specification");
403 return (EINVAL);
406 tmp_create = 1;
407 if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT))
408 goto tmp;
409 else {
410 a = dbenv->db_home;
411 b = dbenv->db_tmp_dir;
413 break;
416 /* Reference a file from the appropriate temporary directory. */
417 if (0) {
418 tmp: if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) {
419 memset(&etmp, 0, sizeof(etmp));
420 if ((ret = __db_tmp_dir(&etmp, DB_USE_ENVIRON)) != 0)
421 return (ret);
422 tmp_free = 1;
423 a = etmp.db_tmp_dir;
424 } else
425 a = dbenv->db_tmp_dir;
428 done: len =
429 (a == NULL ? 0 : strlen(a) + 1) +
430 (b == NULL ? 0 : strlen(b) + 1) +
431 (c == NULL ? 0 : strlen(c) + 1) +
432 (file == NULL ? 0 : strlen(file) + 1);
435 * Allocate space to hold the current path information, as well as any
436 * temporary space that we're going to need to create a temporary file
437 * name.
439 #define DB_TRAIL "XXXXXX"
440 if ((start =
441 (char *)__db_malloc(len + sizeof(DB_TRAIL) + 10)) == NULL) {
442 __db_err(dbenv, "%s", strerror(ENOMEM));
443 if (tmp_free)
444 FREES(etmp.db_tmp_dir);
445 return (ENOMEM);
448 slash = 0;
449 p = start;
450 DB_ADDSTR(a);
451 DB_ADDSTR(b);
452 DB_ADDSTR(file);
453 *p = '\0';
456 * If we're opening a data file, see if it exists. If it does,
457 * return it, otherwise, try and find another one to open.
459 if (data_entry != -1 && __db_exists(start, NULL) != 0) {
460 FREES(start);
461 a = b = c = NULL;
462 goto retry;
465 /* Discard any space allocated to find the temp directory. */
466 if (tmp_free)
467 FREES(etmp.db_tmp_dir);
469 /* Create the file if so requested. */
470 if (tmp_create &&
471 (ret = __db_tmp_open(dbenv, tmp_oflags, start, fdp)) != 0) {
472 FREES(start);
473 return (ret);
476 if (namep != NULL)
477 *namep = start;
478 return (0);
482 * __db_home --
483 * Find the database home.
485 static int
486 __db_home(dbenv, db_home, flags)
487 DB_ENV *dbenv;
488 const char *db_home;
489 u_int32_t flags;
491 const char *p;
493 p = db_home;
495 /* Use the environment if it's permitted and initialized. */
496 #ifdef HAVE_GETUID
497 if (LF_ISSET(DB_USE_ENVIRON) ||
498 (LF_ISSET(DB_USE_ENVIRON_ROOT) && getuid() == 0)) {
499 #else
500 if (LF_ISSET(DB_USE_ENVIRON)) {
501 #endif
502 if ((p = getenv("DB_HOME")) == NULL)
503 p = db_home;
504 else if (p[0] == '\0') {
505 __db_err(dbenv,
506 "illegal DB_HOME environment variable");
507 return (EINVAL);
511 if (p == NULL)
512 return (0);
514 if ((dbenv->db_home = (char *)__db_strdup(p)) == NULL) {
515 __db_err(dbenv, "%s", strerror(ENOMEM));
516 return (ENOMEM);
518 return (0);
522 * __db_parse --
523 * Parse a single NAME VALUE pair.
525 static int
526 __db_parse(dbenv, s)
527 DB_ENV *dbenv;
528 char *s;
530 int ret;
531 char *local_s, *name, *value, **p, *tp;
533 ret = 0;
536 * We need to strdup the argument in case the caller passed us
537 * static data.
539 if ((local_s = (char *)__db_strdup(s)) == NULL)
540 return (ENOMEM);
542 tp = local_s;
543 while ((name = strsep(&tp, " \t")) != NULL && *name == '\0')
545 if (name == NULL)
546 goto illegal;
547 while ((value = strsep(&tp, " \t")) != NULL && *value == '\0')
549 if (value == NULL) {
550 illegal: ret = EINVAL;
551 __db_err(dbenv, "illegal name-value pair: %s", s);
552 goto err;
555 #define DATA_INIT_CNT 20 /* Start with 20 data slots. */
556 if (!strcmp(name, "DB_DATA_DIR")) {
557 if (dbenv->db_data_dir == NULL) {
558 if ((dbenv->db_data_dir =
559 (char **)__db_calloc(DATA_INIT_CNT,
560 sizeof(char **))) == NULL)
561 goto nomem;
562 dbenv->data_cnt = DATA_INIT_CNT;
563 } else if (dbenv->data_next == dbenv->data_cnt - 1) {
564 dbenv->data_cnt *= 2;
565 if ((dbenv->db_data_dir =
566 (char **)__db_realloc(dbenv->db_data_dir,
567 dbenv->data_cnt * sizeof(char **))) == NULL)
568 goto nomem;
570 p = &dbenv->db_data_dir[dbenv->data_next++];
571 } else if (!strcmp(name, "DB_LOG_DIR")) {
572 if (dbenv->db_log_dir != NULL)
573 FREES(dbenv->db_log_dir);
574 p = &dbenv->db_log_dir;
575 } else if (!strcmp(name, "DB_TMP_DIR")) {
576 if (dbenv->db_tmp_dir != NULL)
577 FREES(dbenv->db_tmp_dir);
578 p = &dbenv->db_tmp_dir;
579 } else
580 goto err;
582 if ((*p = (char *)__db_strdup(value)) == NULL) {
583 nomem: ret = ENOMEM;
584 __db_err(dbenv, "%s", strerror(ENOMEM));
587 err: FREES(local_s);
588 return (ret);
591 #ifdef macintosh
592 #include <TFileSpec.h>
594 static char *sTempFolder;
595 #endif
598 * tmp --
599 * Set the temporary directory path.
601 static int
602 __db_tmp_dir(dbenv, flags)
603 DB_ENV *dbenv;
604 u_int32_t flags;
606 static const char * list[] = { /* Ordered: see db_appinit(3). */
607 "/var/tmp",
608 "/usr/tmp",
609 "/temp", /* WIN32. */
610 "/tmp",
611 "C:/temp", /* WIN32. */
612 "C:/tmp", /* WIN32. */
613 NULL
615 const char **lp, *p;
617 /* Use the environment if it's permitted and initialized. */
618 p = NULL;
619 #ifdef HAVE_GETEUID
620 if (LF_ISSET(DB_USE_ENVIRON) ||
621 (LF_ISSET(DB_USE_ENVIRON_ROOT) && getuid() == 0)) {
622 #else
623 if (LF_ISSET(DB_USE_ENVIRON)) {
624 #endif
625 if ((p = getenv("TMPDIR")) != NULL && p[0] == '\0') {
626 __db_err(dbenv, "illegal TMPDIR environment variable");
627 return (EINVAL);
629 /* WIN32 */
630 if (p == NULL && (p = getenv("TEMP")) != NULL && p[0] == '\0') {
631 __db_err(dbenv, "illegal TEMP environment variable");
632 return (EINVAL);
634 /* WIN32 */
635 if (p == NULL && (p = getenv("TMP")) != NULL && p[0] == '\0') {
636 __db_err(dbenv, "illegal TMP environment variable");
637 return (EINVAL);
639 /* Macintosh */
640 if (p == NULL &&
641 (p = getenv("TempFolder")) != NULL && p[0] == '\0') {
642 __db_err(dbenv,
643 "illegal TempFolder environment variable");
644 return (EINVAL);
648 #ifdef macintosh
649 /* Get the path to the temporary folder. */
650 if (p == NULL) {
651 FSSpec spec;
653 if (!Special2FSSpec(kTemporaryFolderType,
654 kOnSystemDisk, 0, &spec)) {
655 p = FSp2FullPath(&spec);
656 sTempFolder = __db_malloc(strlen(p) + 1);
657 strcpy(sTempFolder, p);
658 p = sTempFolder;
661 #endif
663 /* Step through the list looking for a possibility. */
664 if (p == NULL)
665 for (lp = list; *lp != NULL; ++lp)
666 if (__db_exists(p = *lp, NULL) == 0)
667 break;
669 if (p == NULL)
670 return (0);
672 if ((dbenv->db_tmp_dir = (char *)__db_strdup(p)) == NULL) {
673 __db_err(dbenv, "%s", strerror(ENOMEM));
674 return (ENOMEM);
676 return (0);
680 * __db_tmp_open --
681 * Create a temporary file.
683 static int
684 __db_tmp_open(dbenv, flags, path, fdp)
685 DB_ENV *dbenv;
686 u_int32_t flags;
687 char *path;
688 int *fdp;
690 #ifdef HAVE_SIGFILLSET
691 sigset_t set, oset;
692 #endif
693 u_long pid;
694 int mode, isdir, ret;
695 const char *p;
696 char *trv;
699 * Check the target directory; if you have six X's and it doesn't
700 * exist, this runs for a *very* long time.
702 if ((ret = __db_exists(path, &isdir)) != 0) {
703 __db_err(dbenv, "%s: %s", path, strerror(ret));
704 return (ret);
706 if (!isdir) {
707 __db_err(dbenv, "%s: %s", path, strerror(EINVAL));
708 return (EINVAL);
711 /* Build the path. */
712 for (trv = path; *trv != '\0'; ++trv)
714 *trv = PATH_SEPARATOR[0];
715 for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p)
719 * Replace the X's with the process ID. Pid should be a pid_t,
720 * but we use unsigned long for portability.
722 for (pid = getpid(); *--trv == 'X'; pid /= 10)
723 switch (pid % 10) {
724 case 0: *trv = '0'; break;
725 case 1: *trv = '1'; break;
726 case 2: *trv = '2'; break;
727 case 3: *trv = '3'; break;
728 case 4: *trv = '4'; break;
729 case 5: *trv = '5'; break;
730 case 6: *trv = '6'; break;
731 case 7: *trv = '7'; break;
732 case 8: *trv = '8'; break;
733 case 9: *trv = '9'; break;
735 ++trv;
737 /* Set up open flags and mode. */
738 LF_SET(DB_CREATE | DB_EXCL);
739 mode = __db_omode("rw----");
742 * Try to open a file. We block every signal we can get our hands
743 * on so that, if we're interrupted at the wrong time, the temporary
744 * file isn't left around -- of course, if we drop core in-between
745 * the calls we'll hang forever, but that's probably okay. ;-}
747 #ifdef HAVE_SIGFILLSET
748 if (LF_ISSET(DB_TEMPORARY))
749 (void)sigfillset(&set);
750 #endif
751 for (;;) {
752 #ifdef HAVE_SIGFILLSET
753 if (LF_ISSET(DB_TEMPORARY))
754 (void)sigprocmask(SIG_BLOCK, &set, &oset);
755 #endif
756 ret = __db_open(path, flags, flags, mode, fdp);
757 #ifdef HAVE_SIGFILLSET
758 if (LF_ISSET(DB_TEMPORARY))
759 (void)sigprocmask(SIG_SETMASK, &oset, NULL);
760 #endif
761 if (ret == 0)
762 return (0);
765 * XXX:
766 * If we don't get an EEXIST error, then there's something
767 * seriously wrong. Unfortunately, if the implementation
768 * doesn't return EEXIST for O_CREAT and O_EXCL regardless
769 * of other possible errors, we've lost.
771 if (ret != EEXIST) {
772 __db_err(dbenv,
773 "tmp_open: %s: %s", path, strerror(ret));
774 return (ret);
778 * Tricky little algorithm for backward compatibility.
779 * Assumes the ASCII ordering of lower-case characters.
781 for (;;) {
782 if (*trv == '\0')
783 return (EINVAL);
784 if (*trv == 'z')
785 *trv++ = 'a';
786 else {
787 if (isdigit(*trv))
788 *trv = 'a';
789 else
790 ++*trv;
791 break;
795 /* NOTREACHED */