serval-dna/instance.c
2022-05-31 16:34:52 +09:30

262 lines
7.2 KiB
C

/*
Serval DNA instance paths
Copyright (C) 2012-2015 Serval Project Inc.
Copyright (C) 2016-2018 Flinders University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#ifdef __APPLE__
#include "TargetConditionals.h"
#endif
#include "instance.h"
#include "conf.h"
#include "str.h"
#include "os.h"
#include "strbuf.h"
#include "strbuf_helpers.h"
/*
* A default INSTANCE_PATH can be set on the ./configure command line, eg:
*
* ./configure INSTANCE_PATH=/var/local/serval/node
*
* This will cause servald to never use FHS paths, and always use an instance path, even if the
* SERVALINSTANCE_PATH environment variable is not set.
*
* On Android systems, the INSTANCE_PATH macro is set in Android.mk, so Android builds of servald
* always use an instance path and never fall back to FHS paths.
*/
#ifdef ANDROID
# define SERVAL_ETC_PATH ""
# define SERVAL_RUN_PATH ""
# define SYSTEM_LOG_PATH ""
# define SERVAL_LOG_PATH ""
# define SERVAL_CACHE_PATH ""
# define SERVAL_TMP_PATH ""
# define RHIZOME_STORE_PATH ""
#endif
/* The following paths are based on the Filesystem Hierarchy Standard (FHS) 2.3
* but can be altered using ./configure arguments, eg:
*
* ./configure SERVAL_LOG_PATH=/tmp/serval/log
*/
#ifndef SERVAL_ETC_PATH
#define SERVAL_ETC_PATH SYSCONFDIR "/serval"
#endif
#ifndef SERVAL_RUN_PATH
#define SERVAL_RUN_PATH LOCALSTATEDIR "/run/serval"
#endif
#ifndef SYSTEM_LOG_PATH
#define SYSTEM_LOG_PATH LOCALSTATEDIR "/log"
#endif
#ifndef SERVAL_LOG_PATH
#define SERVAL_LOG_PATH SYSTEM_LOG_PATH "/serval"
#endif
#ifndef SERVAL_CACHE_PATH
#define SERVAL_CACHE_PATH LOCALSTATEDIR "/cache/serval"
#endif
#ifndef SERVAL_TMP_PATH
#define SERVAL_TMP_PATH "/tmp/serval"
#endif
#ifndef RHIZOME_STORE_PATH
#define RHIZOME_STORE_PATH SERVAL_CACHE_PATH
#endif
static int know_instancepath = 0;
static char *instancepath = NULL;
const char *instance_path()
{
if (!know_instancepath) {
instancepath = getenv("SERVALINSTANCE_PATH");
#ifdef INSTANCE_PATH
if (instancepath == NULL)
instancepath = INSTANCE_PATH;
#endif
know_instancepath = 1;
}
return instancepath;
}
void set_instance_path(const char *path)
{
instancepath = strdup(path);
know_instancepath = 1;
}
static int vformf_path(struct __sourceloc __whence, strbuf b, const char *fhs_path, const char *configured_path, const char *fmt, va_list ap)
{
const char *ipath = instance_path();
strbuf_path_join(b, ipath ? ipath : fhs_path, NULL);
if (configured_path)
strbuf_path_join(b, configured_path, NULL);
assert(strbuf_str(b)[0] == '/');
int fmt_overrun = 0;
if (fmt) {
strbuf sb = strbuf_alloca(strbuf_size(b));
strbuf_va_vprintf(sb, fmt, ap);
strbuf_path_join(b, strbuf_str(sb), NULL);
fmt_overrun = strbuf_overrun(sb);
}
if (!strbuf_overrun(b) && !fmt_overrun)
return 1;
WHYF("instance path overflow (strlen %lu, sizeof buffer %lu): %s",
(unsigned long)strbuf_count(b),
(unsigned long)strbuf_size(b),
alloca_str_toprint(strbuf_str(b)));
return 0;
}
int _formf_serval_etc_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
char *base_path = SERVAL_ETC_PATH;
#ifdef __APPLE__
#ifdef TARGET_OS_IPHONE
// iOS device
char containerised_path[8192];
if (getenv("HOME")) {
snprintf(containerised_path,8192,"%s/%s",getenv("HOME"),SERVAL_ETC_PATH);
base_path=containerised_path;
}
#endif
#endif
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), SERVAL_ETC_PATH, NULL, fmt, ap);
va_end(ap);
return ret;
}
int _formf_serval_run_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = _vformf_serval_run_path(__whence, buf, bufsiz, fmt, ap);
va_end(ap);
return ret;
}
int _vformf_serval_run_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, va_list ap)
{
return vformf_path(__whence, strbuf_local(buf, bufsiz), SERVAL_RUN_PATH, NULL, fmt, ap);
}
strbuf strbuf_system_log_path(strbuf sb)
{
const char *ipath = instance_path();
strbuf_puts(sb, ipath ? ipath : SYSTEM_LOG_PATH);
return sb;
}
strbuf strbuf_serval_log_path(strbuf sb)
{
const char *ipath = instance_path();
if (ipath)
strbuf_path_join(sb, ipath, "log", NULL);
else
strbuf_puts(sb, SERVAL_LOG_PATH);
return sb;
}
int _formf_serval_cache_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), SERVAL_CACHE_PATH, NULL, fmt, ap);
va_end(ap);
return ret;
}
int _formf_rhizome_store_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), RHIZOME_STORE_PATH, config.rhizome.datastore_path, fmt, ap);
va_end(ap);
return ret;
}
int _formf_rhizome_store_legacy_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), RHIZOME_STORE_PATH, NULL, fmt, ap);
va_end(ap);
return ret;
}
int _formf_serval_tmp_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), SERVAL_TMP_PATH, NULL, fmt, ap);
va_end(ap);
return ret;
}
int _formf_servald_proc_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int ret = vformf_path(__whence, strbuf_local(buf, bufsiz), SERVAL_RUN_PATH "/proc", NULL, fmt, ap);
va_end(ap);
return ret;
}
int create_serval_instance_dir()
{
int ret = 0;
char path[PATH_MAX];
// emkdire_info can log if paths don't exist, which will also try to create paths...
// so try to create logging folders first
strbuf sb = strbuf_local_buf(path);
strbuf_system_log_path(sb);
if (!strbuf_overrun(sb) && emkdirs_info(path, 0700) == -1)
ret = -1;
strbuf_reset(sb);
strbuf_serval_log_path(sb);
if (!strbuf_overrun(sb) && emkdirs_info(path, 0700) == -1)
ret = -1;
if (FORMF_SERVAL_ETC_PATH(path, NULL) && emkdirs_info(path, 0755) == -1)
ret = -1;
if (FORMF_SERVAL_RUN_PATH(path, NULL) && emkdirs_info(path, 0700) == -1)
ret = -1;
if (FORMF_SERVAL_CACHE_PATH(path, NULL) && emkdirs_info(path, 0700) == -1)
ret = -1;
if (FORMF_SERVAL_TMP_PATH(path, NULL) && emkdirs_info(path, 0700) == -1)
ret = -1;
if (FORMF_SERVALD_PROC_PATH(path, NULL) && emkdirs_info(path, 0755) == -1)
ret = -1;
return ret;
}