#include "db_config.h"
#include "db_int.h"
static int __db_fullpath
__P((ENV *, const char *, const char *, int, int, char **));
#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; \
} \
}
static int
__db_fullpath(env, dir, file, check_file, check_dir, namep)
ENV *env;
const char *dir;
const char *file;
int check_file;
int check_dir;
char **namep;
{
size_t len;
const char *home;
char *p, *str;
int isdir, ret, slash;
home = (env == NULL) ? NULL : env->db_home;
len =
(home == NULL ? 0 : strlen(home) + 1) +
(dir == NULL ? 0 : strlen(dir) + 1) +
(file == NULL ? 0 : strlen(file) + 1);
if ((ret = __os_malloc(env, len, &str)) != 0)
return (ret);
slash = 0;
p = str;
DB_ADDSTR(home);
DB_ADDSTR(dir);
*p = '\0';
if (check_dir && (__os_exists(env, str, &isdir) != 0 || !isdir)) {
__os_free(env, str);
return (ENOENT);
}
DB_ADDSTR(file);
*p = '\0';
if (check_file && __os_exists(env, str, NULL) != 0) {
__os_free(env, str);
return (ENOENT);
}
if (namep == NULL)
__os_free(env, str);
else
*namep = str;
return (0);
}
#define DB_CHECKFILE(file, dir, check_file, check_dir, namep, ret_dir) do { \
ret = __db_fullpath(env, dir, file, \
check_file, check_dir, namep); \
if (ret == 0 && (ret_dir) != NULL) \
*(ret_dir) = (dir); \
if (ret != ENOENT) \
return (ret); \
} while (0)
int
__db_appname(env, appname, file, dirp, namep)
ENV *env;
APPNAME appname;
const char *file;
const char **dirp;
char **namep;
{
DB_ENV *dbenv;
char **ddp;
const char *dir;
int ret;
dbenv = env->dbenv;
dir = NULL;
if (namep != NULL)
*namep = NULL;
if (file != NULL && __os_abspath(file))
return (__os_strdup(env, file, namep));
switch (appname) {
case DB_APP_NONE:
break;
case DB_APP_RECOVER:
case DB_APP_DATA:
if (dbenv != NULL && dbenv->db_data_dir != NULL)
for (ddp = dbenv->db_data_dir; *ddp != NULL; ddp++)
DB_CHECKFILE(file, *ddp, 1, 0, namep, dirp);
DB_CHECKFILE(file, NULL, 1, 0, namep, dirp);
if (dirp != NULL && *dirp != NULL)
DB_CHECKFILE(file, *dirp, 0,
appname == DB_APP_RECOVER, namep, dirp);
if (dbenv != NULL && dbenv->db_create_dir != NULL)
dir = dbenv->db_create_dir;
break;
case DB_APP_LOG:
if (dbenv != NULL)
dir = dbenv->db_log_dir;
break;
case DB_APP_TMP:
if (dbenv != NULL)
dir = dbenv->db_tmp_dir;
break;
case DB_APP_META:
if (dbenv != NULL)
dir = dbenv->db_md_dir;
break;
}
DB_CHECKFILE(file, dir, 0, appname == DB_APP_TMP, namep, dirp);
return (ret);
}
int
__db_tmp_open(env, oflags, fhpp)
ENV *env;
u_int32_t oflags;
DB_FH **fhpp;
{
pid_t pid;
int filenum, i, ipid, ret;
char *path;
char *firstx, *trv;
DB_ASSERT(env, fhpp != NULL);
*fhpp = NULL;
#define DB_TRAIL "BDBXXXXX"
if ((ret = __db_appname(env, DB_APP_TMP, DB_TRAIL, NULL, &path)) != 0)
goto done;
__os_id(env->dbenv, &pid, NULL);
ipid = (int)pid;
if (ipid < 0)
ipid = -ipid;
for (trv = path + strlen(path); *--trv == 'X'; ipid /= 10)
*trv = '0' + (u_char)(ipid % 10);
firstx = trv + 1;
for (filenum = 1;; filenum++) {
if ((ret = __os_open(env, path, 0,
oflags | DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP,
DB_MODE_600, fhpp)) == 0) {
ret = 0;
goto done;
}
if (ret != EEXIST) {
__db_err(env, ret, DB_STR_A("1586",
"temporary open: %s", "%s"), path);
goto done;
}
for (i = filenum, trv = firstx; i > 0; i = (i - 1) / 26)
if (*trv++ == '\0') {
ret = EINVAL;
goto done;
}
for (i = filenum; i > 0; i = (i - 1) / 26)
*--trv = 'a' + ((i - 1) % 26);
}
done:
__os_free(env, path);
return (ret);
}