#include "db_config.h"
#include "db_int.h"
static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, DB_FH **));
#define DB_ADDSTR(add) { \
\
if ((add) != NULL && (add)[0] != '\0') { \
\
if (__os_abspath(add)) { \
p = str; \
slash = 0; \
} \
\
len = strlen(add); \
if (slash) \
*p++ = PATH_SEPARATOR[0]; \
memcpy(p, add, len); \
p += len; \
slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \
} \
}
int
__db_appname(dbenv, appname, file, tmp_oflags, fhpp, namep)
DB_ENV *dbenv;
APPNAME appname;
const char *file;
u_int32_t tmp_oflags;
DB_FH **fhpp;
char **namep;
{
enum { TRY_NOTSET, TRY_DATA_DIR, TRY_ENV_HOME, TRY_CREATE } try_state;
size_t len, str_len;
int data_entry, ret, slash, tmp_create;
const char *a, *b;
char *p, *str;
try_state = TRY_NOTSET;
a = b = NULL;
data_entry = 0;
tmp_create = 0;
if (fhpp != NULL)
*fhpp = NULL;
if (namep != NULL)
*namep = NULL;
if (file != NULL && __os_abspath(file))
return (__os_strdup(dbenv, file, namep));
if (dbenv != NULL)
a = dbenv->db_home;
retry:
switch (appname) {
case DB_APP_NONE:
break;
case DB_APP_DATA:
if (dbenv == NULL || dbenv->db_data_dir == NULL) {
try_state = TRY_CREATE;
break;
}
if ((b = dbenv->db_data_dir[data_entry]) != NULL) {
++data_entry;
try_state = TRY_DATA_DIR;
break;
}
if (try_state != TRY_ENV_HOME) {
try_state = TRY_ENV_HOME;
break;
}
try_state = TRY_CREATE;
b = dbenv->db_data_dir[0];
break;
case DB_APP_LOG:
if (dbenv != NULL)
b = dbenv->db_log_dir;
break;
case DB_APP_TMP:
if (dbenv != NULL)
b = dbenv->db_tmp_dir;
tmp_create = 1;
break;
}
len =
(a == NULL ? 0 : strlen(a) + 1) +
(b == NULL ? 0 : strlen(b) + 1) +
(file == NULL ? 0 : strlen(file) + 1);
#define DB_TRAIL "BDBXXXXX"
str_len = len + sizeof(DB_TRAIL) + 10;
if ((ret = __os_malloc(dbenv, str_len, &str)) != 0)
return (ret);
slash = 0;
p = str;
DB_ADDSTR(a);
DB_ADDSTR(b);
DB_ADDSTR(file);
*p = '\0';
if (appname == DB_APP_DATA &&
__os_exists(dbenv, str, NULL) != 0 && try_state != TRY_CREATE) {
__os_free(dbenv, str);
b = NULL;
goto retry;
}
if (tmp_create &&
(ret = __db_tmp_open(dbenv, tmp_oflags, str, fhpp)) != 0) {
__os_free(dbenv, str);
return (ret);
}
if (namep == NULL)
__os_free(dbenv, str);
else
*namep = str;
return (0);
}
static int
__db_tmp_open(dbenv, tmp_oflags, path, fhpp)
DB_ENV *dbenv;
u_int32_t tmp_oflags;
char *path;
DB_FH **fhpp;
{
pid_t pid;
int filenum, i, isdir, ret;
char *firstx, *trv;
if ((ret = __os_exists(dbenv, path, &isdir)) != 0) {
__db_err(dbenv, ret, "%s", path);
return (ret);
}
if (!isdir) {
__db_err(dbenv, EINVAL, "%s", path);
return (EINVAL);
}
(void)strncat(path, PATH_SEPARATOR, 1);
(void)strcat(path, DB_TRAIL);
__os_id(dbenv, &pid, NULL);
for (trv = path + strlen(path); *--trv == 'X'; pid /= 10)
*trv = '0' + (u_char)(pid % 10);
firstx = trv + 1;
for (filenum = 1;; filenum++) {
if ((ret = __os_open(dbenv, path, 0,
tmp_oflags | DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP,
__db_omode(OWNER_RW), fhpp)) == 0)
return (0);
if (ret != EEXIST) {
__db_err(dbenv, ret, "temporary open: %s", path);
return (ret);
}
for (i = filenum, trv = firstx; i > 0; i = (i - 1) / 26)
if (*trv++ == '\0')
return (EINVAL);
for (i = filenum; i > 0; i = (i - 1) / 26)
*--trv = 'a' + ((i - 1) % 26);
}
}