mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
Filesystem Heirarchy Standard (FHS) paths
If no instance directory specified, then use paths like /etc/serval/serval.conf /var/cache/serval /var/log/serval /var/run/serval etc. for files, instead of all in a single directory. Log all directory creation as INFO messages. Interpretation of log.file.directory_path has changed slightly. Updated servald configuration tech doc.
This commit is contained in:
parent
d228165814
commit
53c1b1c04c
@ -2,6 +2,8 @@ prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
sbindir=@sbindir@
|
||||
sysconfdir=@sysconfdir@
|
||||
localstatedir=@localstatedir@
|
||||
|
||||
NACL_BASE= nacl/src
|
||||
include $(NACL_BASE)/nacl.mk
|
||||
@ -42,6 +44,7 @@ MDP_CLIENT_OBJS= $(MDP_CLIENT_SRCS:.c=.o)
|
||||
LDFLAGS=@LDFLAGS@ @LIBS@ @PORTAUDIO_LIBS@ @SRC_LIBS@ @SPANDSP_LIBS@ @CODEC2_LIBS@ @PTHREAD_LIBS@
|
||||
|
||||
CFLAGS= -Isqlite-amalgamation-3070900 @CPPFLAGS@ @CFLAGS@ @PORTAUDIO_CFLAGS@ @SRC_CFLAGS@ @SPANDSP_CFLAGS@ @PTHREAD_CFLAGS@ $(VOIPTEST_CFLAGS) -Inacl/include
|
||||
CFLAGS+=-DSYSCONFDIR="\"$(sysconfdir)\"" -DLOCALSTATEDIR="\"$(localstatedir)\""
|
||||
CFLAGS+=-fPIC
|
||||
CFLAGS+=-Wall -Wno-unused-value
|
||||
# Solaris magic
|
||||
|
@ -932,8 +932,13 @@ int app_server_start(const struct cli_parsed *parsed, struct cli_context *contex
|
||||
RETURN(WHY("Server process did not start"));
|
||||
ret = 0;
|
||||
}
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, serval_instancepath(), "\n");
|
||||
const char *ipath = instance_path();
|
||||
if (ipath) {
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, ipath, "\n");
|
||||
}
|
||||
cli_field_name(context, "pidfile", ":");
|
||||
cli_put_string(context, server_pidfile_path(), "\n");
|
||||
cli_field_name(context, "pid", ":");
|
||||
cli_put_long(context, pid, "\n");
|
||||
char buff[256];
|
||||
@ -968,9 +973,13 @@ int app_server_stop(const struct cli_parsed *parsed, struct cli_context *context
|
||||
DEBUG_cli_parsed(parsed);
|
||||
int pid, tries, running;
|
||||
time_ms_t timeout;
|
||||
const char *instancepath = serval_instancepath();
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, instancepath, "\n");
|
||||
const char *ipath = instance_path();
|
||||
if (ipath) {
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, ipath, "\n");
|
||||
}
|
||||
cli_field_name(context, "pidfile", ":");
|
||||
cli_put_string(context, server_pidfile_path(), "\n");
|
||||
pid = server_pid();
|
||||
/* Not running, nothing to stop */
|
||||
if (pid <= 0)
|
||||
@ -983,8 +992,8 @@ int app_server_stop(const struct cli_parsed *parsed, struct cli_context *context
|
||||
running = pid;
|
||||
while (running == pid) {
|
||||
if (tries >= 5) {
|
||||
WHYF("Servald pid=%d for instance '%s' did not stop after %d SIGHUP signals",
|
||||
pid, instancepath, tries);
|
||||
WHYF("Servald pid=%d (pidfile=%s) did not stop after %d SIGHUP signals",
|
||||
pid, server_pidfile_path(), tries);
|
||||
return 253;
|
||||
}
|
||||
++tries;
|
||||
@ -999,7 +1008,7 @@ int app_server_stop(const struct cli_parsed *parsed, struct cli_context *context
|
||||
break;
|
||||
}
|
||||
WHY_perror("kill");
|
||||
WHYF("Error sending SIGHUP to Servald pid=%d for instance '%s'", pid, instancepath);
|
||||
WHYF("Error sending SIGHUP to Servald pid=%d (pidfile %s)", pid, server_pidfile_path());
|
||||
return 252;
|
||||
}
|
||||
/* Allow a few seconds for the process to die. */
|
||||
@ -1019,8 +1028,13 @@ int app_server_status(const struct cli_parsed *parsed, struct cli_context *conte
|
||||
if (config.debug.verbose)
|
||||
DEBUG_cli_parsed(parsed);
|
||||
int pid = server_pid();
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, serval_instancepath(), "\n");
|
||||
const char *ipath = instance_path();
|
||||
if (ipath) {
|
||||
cli_field_name(context, "instancepath", ":");
|
||||
cli_put_string(context, ipath, "\n");
|
||||
}
|
||||
cli_field_name(context, "pidfile", ":");
|
||||
cli_put_string(context, server_pidfile_path(), "\n");
|
||||
cli_field_name(context, "status", ":");
|
||||
cli_put_string(context, pid > 0 ? "running" : "stopped", "\n");
|
||||
if (pid > 0) {
|
||||
@ -1426,6 +1440,52 @@ int app_config_get(const struct cli_parsed *parsed, struct cli_context *context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_config_paths(const struct cli_parsed *parsed, struct cli_context *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_cli_parsed(parsed);
|
||||
if (cf_om_reload() == -1)
|
||||
return -1;
|
||||
char path[1024];
|
||||
if (FORMF_SERVAL_ETC_PATH(path, NULL)) {
|
||||
cli_field_name(context, "SERVAL_ETC_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
if (FORMF_SERVAL_RUN_PATH(path, NULL)) {
|
||||
cli_field_name(context, "SERVAL_RUN_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
if (FORMF_SERVAL_CACHE_PATH(path, NULL)) {
|
||||
cli_field_name(context, "SERVAL_CACHE_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
strbuf sb = strbuf_local(path, sizeof path);
|
||||
strbuf_system_log_path(sb);
|
||||
if (!strbuf_overrun(sb)) {
|
||||
cli_field_name(context, "SYSTEM_LOG_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
strbuf_reset(sb);
|
||||
strbuf_serval_log_path(sb);
|
||||
if (!strbuf_overrun(sb)) {
|
||||
cli_field_name(context, "SERVAL_LOG_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
if (FORMF_SERVAL_TMP_PATH(path, NULL)) {
|
||||
cli_field_name(context, "SERVAL_TMP_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
if (FORMF_SERVALD_PROC_PATH(path, NULL)) {
|
||||
cli_field_name(context, "SERVALD_PROC_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
if (FORMF_RHIZOME_STORE_PATH(path, NULL)) {
|
||||
cli_field_name(context, "RHIZOME_STORE_PATH", ":");
|
||||
cli_put_string(context, path, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_rhizome_hash_file(const struct cli_parsed *parsed, struct cli_context *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
@ -3019,6 +3079,8 @@ struct cli_schema command_line_options[]={
|
||||
"Del and set specified configuration variables."},
|
||||
{app_config_get,{"config","get","[<variable>]",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Get specified configuration variable."},
|
||||
{app_config_paths,{"config","paths",NULL},CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Dump file and directory paths."},
|
||||
{app_vomp_console,{"console",NULL}, 0,
|
||||
"Test phone call life-cycle from the console"},
|
||||
{app_meshms_conversations,{"meshms","list","conversations" KEYRING_PIN_OPTIONS, "<sid>","[<offset>]","[<count>]",NULL},0,
|
||||
|
4
conf.c
4
conf.c
@ -44,7 +44,7 @@ static struct file_meta config_meta = FILE_META_UNKNOWN;
|
||||
static const char *conffile_path()
|
||||
{
|
||||
static char path[1024] = "";
|
||||
if (!path[0] && !FORM_SERVAL_INSTANCE_PATH(path, CONFFILE_NAME))
|
||||
if (!path[0] && !FORMF_SERVAL_ETC_PATH(path, CONFFILE_NAME))
|
||||
abort();
|
||||
return path;
|
||||
}
|
||||
@ -144,7 +144,7 @@ int cf_om_save()
|
||||
const char *path = conffile_path();
|
||||
char tempfile[1024];
|
||||
FILE *outf = NULL;
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(tempfile, "serval.conf.temp"))
|
||||
if (!FORMF_SERVAL_ETC_PATH(tempfile, CONFFILE_NAME ".temp"))
|
||||
return -1;
|
||||
if ((outf = fopen(tempfile, "w")) == NULL)
|
||||
return WHYF_perror("fopen(%s, \"w\")", tempfile);
|
||||
|
@ -292,7 +292,7 @@ LOG_FORMAT_OPTIONS
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(log_format_file)
|
||||
STRING(256, directory_path, "log", str_nonempty,, "Path of directory for log files, either absolute or relative to instance directory")
|
||||
STRING(256, directory_path, "", str,, "Path of directory for log files, either absolute or relative to instance log directory")
|
||||
STRING(256, path, "", str_nonempty,, "Path of single log file, either absolute or relative to directory_path")
|
||||
ATOM(unsigned short, rotate, 12, ushort,, "Number of log files to rotate, zero means no deletion")
|
||||
ATOM(uint32_t, duration, 3600, uint32_time_interval,, "Time duration of each log file, zero means one file per invocation")
|
||||
|
24
configure.in
24
configure.in
@ -14,6 +14,30 @@ dnl Specify default instance path
|
||||
AC_ARG_VAR([INSTANCE_PATH], [default instance path for servald])
|
||||
AS_IF([test "x$INSTANCE_PATH" != x], [AC_DEFINE_UNQUOTED([INSTANCE_PATH], ["$INSTANCE_PATH"], [default instance path])])
|
||||
|
||||
dnl Specify default Serval config directory
|
||||
AC_ARG_VAR([SERVAL_ETC_PATH], [default Serval config directory])
|
||||
AS_IF([test "x$SERVAL_ETC_PATH" != x], [AC_DEFINE_UNQUOTED([SERVAL_ETC_PATH], ["$SERVAL_ETC_PATH"], [default config directory])])
|
||||
|
||||
dnl Specify default Serval run directory
|
||||
AC_ARG_VAR([SERVAL_RUN_PATH], [default Serval run directory])
|
||||
AS_IF([test "x$SERVAL_RUN_PATH" != x], [AC_DEFINE_UNQUOTED([SERVAL_RUN_PATH], ["$SERVAL_RUN_PATH"], [default run directory])])
|
||||
|
||||
dnl Specify default Serval log directory
|
||||
AC_ARG_VAR([SERVAL_LOG_PATH], [default Serval log directory])
|
||||
AS_IF([test "x$SERVAL_LOG_PATH" != x], [AC_DEFINE_UNQUOTED([SERVAL_LOG_PATH], ["$SERVAL_LOG_PATH"], [default log directory])])
|
||||
|
||||
dnl Specify default system log directory
|
||||
AC_ARG_VAR([SYSTEM_LOG_PATH], [default system log directory])
|
||||
AS_IF([test "x$SYSTEM_LOG_PATH" != x], [AC_DEFINE_UNQUOTED([SYSTEM_LOG_PATH], ["$SYSTEM_LOG_PATH"], [default system log directory])])
|
||||
|
||||
dnl Specify default Serval tmp directory
|
||||
AC_ARG_VAR([SERVAL_TMP_PATH], [default Serval tmp directory])
|
||||
AS_IF([test "x$SERVAL_TMP_PATH" != x], [AC_DEFINE_UNQUOTED([SERVAL_TMP_PATH], ["$SERVAL_TMP_PATH"], [default Serval tmp directory])])
|
||||
|
||||
dnl Specify default Rhizome store directory
|
||||
AC_ARG_VAR([RHIZOME_STORE_PATH], [default Rhizome store directory])
|
||||
AS_IF([test "x$RHIZOME_STORE_PATH" != x], [AC_DEFINE_UNQUOTED([RHIZOME_STORE_PATH], ["$RHIZOME_STORE_PATH"], [default Rhizome store directory])])
|
||||
|
||||
dnl VoIP test app
|
||||
AC_ARG_ENABLE(voiptest,
|
||||
AS_HELP_STRING([--enable-voiptest], [Require VoIP test program (default: only build if dependencies are present)])
|
||||
|
@ -38,23 +38,6 @@ An option **VALUE** is a string of [US-ASCII][] characters, excluding newline
|
||||
|
||||
If a VALUE does not parse correctly, it is *invalid*.
|
||||
|
||||
Instance directory
|
||||
------------------
|
||||
|
||||
By default, **servald** stores its configuration, keyring, and other temporary
|
||||
files in its *instance directory*. The instance directory is set at run time
|
||||
by the `SERVALINSTANCE_PATH` environment variable. If this is not set, then
|
||||
**servald** uses a built-in default path which depends on its build-time option
|
||||
and target platform:
|
||||
|
||||
* as specified by the `./configure INSTANCE_PATH=<path>` option when **servald**
|
||||
was built from source
|
||||
* on Android `/data/data/org.servalproject/var/serval-node`
|
||||
* on other platforms `/var/serval-node`
|
||||
|
||||
**servald** will create its instance directory (and all enclosing parent
|
||||
directories) if it does not already exist.
|
||||
|
||||
Configuration persistence
|
||||
-------------------------
|
||||
|
||||
@ -115,22 +98,152 @@ defective file. This means that **servald** may always be used to inspect and
|
||||
correct the configuration, and to stop a running daemon, despite a defective
|
||||
configuration file.
|
||||
|
||||
Daemon processes
|
||||
Configuration reloading
|
||||
-----------------------
|
||||
|
||||
A running daemon re-loads its configuration whenever the `serval.conf` file is
|
||||
changed. It does this by periodically checking the file's size and
|
||||
modification time, and if they have changed, parses the file and updates its
|
||||
own internal copy of the configuration settings.
|
||||
|
||||
As described above, the **servald** `start` command will not start a daemon
|
||||
process if the `serval.conf` file is defective. However, the file may become
|
||||
defective *after* the daemon has started.
|
||||
|
||||
In this case, the daemon will not terminate, nor load the defective file, but
|
||||
will log an error and continue execution with its internal configuration
|
||||
unchanged. The daemon's internal configuration will no longer be consistent
|
||||
with the contents of the file. If the daemon is stopped or killed, it cannot
|
||||
be re-started while `serval.conf` remains defective.
|
||||
|
||||
Despite detecting a defective configuration file, the daemon continues to check
|
||||
for changes to the file, and attempts to re-load whenever it changes. As soon
|
||||
as the defective `serval.conf` is fixed, the running daemon will load it
|
||||
successfully and continue execution with the new configuration. The internal
|
||||
configuration and the file contents will once again be consistent.
|
||||
|
||||
Daemon instances
|
||||
----------------
|
||||
|
||||
To run more than one **servald** daemon process on the same device, each daemon
|
||||
must have its own instance path (and hence its own `serval.conf`). Set the
|
||||
`SERVALINSTANCE_PATH` environment variable to a different directory path before
|
||||
starting each daemon.
|
||||
It order to support more than one daemon running on the same host, each daemon
|
||||
can be configured to use its own *instance directory*, as follows:
|
||||
|
||||
As described above, a defective `serval.conf` will prevent the **servald**
|
||||
`start` command from starting a daemon process. Once the daemon is running, it
|
||||
periodically checks whether `serval.conf` has changed (by comparing size and
|
||||
modification time) and attempts to re-load it if it detects a change. If the
|
||||
re-loaded file is defective, the daemon rejects it, logs an error, and
|
||||
continues execution with its prior configuration unchanged. If the daemon is
|
||||
stopped or killed, it cannot be re-started while `serval.conf` remains
|
||||
defective.
|
||||
* A daemon's instance directory can be set at run time by setting the
|
||||
`SERVALINSTANCE_PATH` environment variable prior to starting the daemon.
|
||||
This overrides all default paths. Once a daemon is running, the only way
|
||||
to change its instance directory is to stop it and start another daemon
|
||||
with a different value for the environment variable.
|
||||
|
||||
* If the instance directory is not set at run time, then if **servald** was
|
||||
built with the `./configure INSTANCE_PATH=DIR` option, then the **servald**
|
||||
executable will use the instance directory in `DIR` by default. The FHS
|
||||
paths will never be used.
|
||||
|
||||
* On an Android system, if none of the above are used, then **servald** will
|
||||
use the instance directory `/data/data/org.servalproject/var/serval-node`
|
||||
by default. The FHS paths will never be used.
|
||||
|
||||
* If none of the above apply, then there is no *instance directory*.
|
||||
Instead, [FHS][] paths are used (see below). Only one daemon can run in
|
||||
this situation on the same host, since the single, common PID file will
|
||||
prevent more than one being started.
|
||||
|
||||
The main use for multiple instances on a single host is for testing, and this
|
||||
is used extensively in the automated test suite. Deployments other than
|
||||
Android are unlikely to use an instance path, so the FHS paths are most likely
|
||||
to be used in practice.
|
||||
|
||||
FHS paths
|
||||
---------
|
||||
|
||||
By default, **servald** locates its files such as configuration, logs, Rhizome
|
||||
storage, etc. in accordance with the [Filesystem Heirarchy Standard][FHS] 2.3:
|
||||
|
||||
* the **servald** executable is installed in `/usr/local/bin/servald`
|
||||
* the configuration is stored in `/etc/serval/serval.conf`
|
||||
* the keyring is stored in `/etc/serval/serval.keyring`
|
||||
* the PID file is `/var/run/serval/servald.pid`
|
||||
* the daemon creates its process information files under
|
||||
`/var/run/serval/proc/`
|
||||
* the daemon creates and rotates log files files under
|
||||
`/var/log/serval/`
|
||||
* the daemon creates and updates a symbolic link to the latest log file in
|
||||
`/var/log/servald.log`
|
||||
* the Rhizome store is in `/var/cache/serval/` (unless overridden by
|
||||
configuration):
|
||||
* the SQLite database is `/var/cache/serval/rhizome.db`
|
||||
* large payloads are stored under `/var/cache/serval/blob/`
|
||||
* the SQLite temporary directory is `/tmp/serval/sqlite3tmp/`
|
||||
* dummy interface files are created under `/tmp/serval/` (unless overridden
|
||||
by configuration)
|
||||
|
||||
The **servald** `start` command will create all sub-directories within the
|
||||
standard FHS paths as needed, and any failure will cause the daemon not to
|
||||
start.
|
||||
|
||||
The following build-time configuration options are available to alter the paths
|
||||
described above, which can help adapt **servald** to systems which use a
|
||||
different software installation convention (eg, all packages are installed
|
||||
under `/opt/packagename`) or which have a volatile `/var` directory (eg, on
|
||||
OpenWRT, `/var` is a symlink to `/tmp`):
|
||||
|
||||
* If **servald** is built with the `./configure --prefix=DIR` option, then
|
||||
the executable is installed in `DIR/bin` instead of `/usr/local/bin`
|
||||
|
||||
* If **servald** is built with the `./configure --sysconfdir=DIR` option,
|
||||
then it will use `DIR` in place of `/etc`
|
||||
|
||||
* If **servald** is built with the `./configure --localstatedir=DIR` option,
|
||||
then it will use `DIR` in place of `/var`
|
||||
|
||||
* If **servald** is built with the `./configure SERVAL_ETC_PATH=DIR` option,
|
||||
then it will use `DIR` in place of `/etc/serval`
|
||||
|
||||
* If **servald** is built with the `./configure SERVAL_RUN_PATH=DIR` option,
|
||||
then it will use `DIR` in place of `/var/run/serval`
|
||||
|
||||
* If **servald** is built with the `./configure SYSTEM_LOG_PATH=DIR` option,
|
||||
then it will use `DIR` in place of `/var/log`
|
||||
|
||||
* If **servald** is built with the `./configure SERVAL_LOG_PATH=DIR` option,
|
||||
then it will use `DIR` in place of `/var/log/serval`
|
||||
|
||||
* If **servald** is built with the `./configure RHIZOME_STORE_PATH=DIR`
|
||||
option, then it will use `DIR` in place of `/var/cache/serval` for the
|
||||
Rhizome store
|
||||
|
||||
* If **servald** is built with the `./configure SERVAL_TMP_PATH=DIR` option,
|
||||
then it will use `DIR` in place of `/tmp/serval`
|
||||
|
||||
The **servald** `config paths` command will display all the paths in use, based
|
||||
on the built-in defaults as overridden by configuration settings and run-time
|
||||
environment variables available to the command. This command will work even if
|
||||
configuration is defective, so is a useful diagnostic tool.
|
||||
|
||||
Instance directory paths
|
||||
------------------------
|
||||
|
||||
If **servald** is started with an *instance directory*, then all configuration,
|
||||
state, and temporary files are stored in or beneath that directory, denoted
|
||||
`IDIR`:
|
||||
|
||||
* the configuration is stored in `IDIR/serval.conf`
|
||||
* the keyring is stored in `IDIR/serval.keyring`
|
||||
* the PID file is `IDIR/servald.pid`
|
||||
* the daemon creates its process information files under `IDIR/proc/`
|
||||
* the daemon creates and rotates log files files under `IDIR/log/`
|
||||
* the daemon creates and updates a symbolic link to the latest log file in
|
||||
`IDIR/servald.log`
|
||||
* the Rhizome store is in `IDIR/` (unless overridden by configuration):
|
||||
* the SQLite database is `IDIR/rhizome.db`
|
||||
* large payloads are stored under `IDIR/blob/`
|
||||
* the SQLite temporary directory is `IDIR/sqlite3tmp/`
|
||||
* dummy interface files are created under `IDIR/` (unless overridden by
|
||||
configuration)
|
||||
|
||||
The **servald** `start` command will create its instance directory (and all
|
||||
enclosing parent directories) if it does not already exist. Failure will cause
|
||||
the daemon not to start.
|
||||
|
||||
About the examples
|
||||
------------------
|
||||
@ -300,8 +413,10 @@ All log destinations support the following configuration options:
|
||||
In addition, the *file* destination has these extra configuration options:
|
||||
|
||||
* `log.file.directory_path` If set, log files are created in this directory,
|
||||
which is created if it does not exist. This defaults to the `log`
|
||||
directory within the instance directory.
|
||||
which is created if it does not exist. Relative paths are interpreted
|
||||
relative to the `log` sub-directory of the instance directory. The default
|
||||
setting (empty string) causes log files to be created within the `log`
|
||||
sub-directory of the instance directory.
|
||||
|
||||
* `log.file.path` If set, all log messages are appended directly to the file
|
||||
at the given path. If the path is not absolute, it is interpreted relative
|
||||
|
215
instance.c
215
instance.c
@ -24,46 +24,207 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "strbuf.h"
|
||||
#include "strbuf_helpers.h"
|
||||
|
||||
static char *thisinstancepath = NULL;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifdef INSTANCE_PATH
|
||||
#define DEFAULT_INSTANCE_PATH INSTANCE_PATH
|
||||
#else
|
||||
|
||||
const char *serval_instancepath()
|
||||
/* On Android systems, always use an instance path (no FHS paths).
|
||||
*/
|
||||
#ifdef ANDROID
|
||||
#define DEFAULT_INSTANCE_PATH "/data/data/org.servalproject/var/serval-node"
|
||||
#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 ""
|
||||
#else
|
||||
#define DEFAULT_INSTANCE_PATH NULL
|
||||
#endif
|
||||
#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 (thisinstancepath)
|
||||
return thisinstancepath;
|
||||
const char *instancepath = getenv("SERVALINSTANCE_PATH");
|
||||
if (!instancepath)
|
||||
instancepath = DEFAULT_INSTANCE_PATH;
|
||||
if (!know_instancepath) {
|
||||
instancepath = getenv("SERVALINSTANCE_PATH");
|
||||
if (instancepath == NULL)
|
||||
instancepath = DEFAULT_INSTANCE_PATH;
|
||||
know_instancepath = 1;
|
||||
}
|
||||
return instancepath;
|
||||
}
|
||||
|
||||
int formf_serval_instance_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, ...)
|
||||
static int vformf_path(struct __sourceloc __whence, strbuf b, const char *syspath, const char *fmt, va_list ap)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = vformf_serval_instance_path(__whence, buf, bufsiz, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vformf_serval_instance_path(struct __sourceloc __whence, char *buf, size_t bufsiz, const char *fmt, va_list ap)
|
||||
{
|
||||
strbuf b = strbuf_local(buf, bufsiz);
|
||||
strbuf_va_vprintf(b, fmt, ap);
|
||||
if (!strbuf_overrun(b) && strbuf_len(b) && buf[0] != '/') {
|
||||
strbuf_reset(b);
|
||||
strbuf_puts(b, serval_instancepath());
|
||||
strbuf_putc(b, '/');
|
||||
if (fmt)
|
||||
strbuf_va_vprintf(b, fmt, ap);
|
||||
if (!strbuf_overrun(b) && (strbuf_len(b) == 0 || strbuf_str(b)[0] != '/')) {
|
||||
strbuf_reset(b);
|
||||
const char *ipath = instance_path();
|
||||
#ifdef ANDROID
|
||||
assert(ipath != NULL);
|
||||
#endif
|
||||
strbuf_puts(b, ipath ? ipath : syspath);
|
||||
if (fmt) {
|
||||
if (strbuf_substr(b, -1)[0] != '/')
|
||||
strbuf_putc(b, '/');
|
||||
strbuf_va_vprintf(b, fmt, ap);
|
||||
}
|
||||
}
|
||||
if (!strbuf_overrun(b))
|
||||
return 1;
|
||||
WHYF("instance path overflow (strlen %lu, sizeof buffer %lu): %s",
|
||||
(unsigned long)strbuf_count(b),
|
||||
(unsigned long)bufsiz,
|
||||
alloca_str_toprint(buf));
|
||||
(unsigned long)strbuf_size(b),
|
||||
alloca_str_toprint(strbuf_str(b)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int create_serval_instance_dir() {
|
||||
return emkdirs(serval_instancepath(), 0700);
|
||||
int _formf_serval_etc_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_ETC_PATH, 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, 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, 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, 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, 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", fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int create_serval_instance_dir()
|
||||
{
|
||||
int ret = 0;
|
||||
char path[PATH_MAX];
|
||||
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;
|
||||
strbuf sb = strbuf_local(path, sizeof 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_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;
|
||||
if (FORMF_RHIZOME_STORE_PATH(path, NULL) && emkdirs_info(path, 0700) == -1)
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
60
instance.h
60
instance.h
@ -21,34 +21,40 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define __SERVAL_DNA__INSTANCE_H
|
||||
|
||||
#include "log.h"
|
||||
#include "strbuf.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.
|
||||
*/
|
||||
#ifdef INSTANCE_PATH
|
||||
#define DEFAULT_INSTANCE_PATH INSTANCE_PATH
|
||||
#else
|
||||
#ifdef ANDROID
|
||||
#define DEFAULT_INSTANCE_PATH "/data/data/org.servalproject/var/serval-node"
|
||||
#else
|
||||
#define DEFAULT_INSTANCE_PATH NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Handy statement for forming a path to an instance file in a char buffer whose declaration
|
||||
* is in scope (so that sizeof(buf) will work). Evaluates to true if the pathname fitted into
|
||||
* the provided buffer, false (0) otherwise (after logging an error).
|
||||
*/
|
||||
#define FORM_SERVAL_INSTANCE_PATH(buf, path) (formf_serval_instance_path(__WHENCE__, buf, sizeof(buf), "%s", (path)))
|
||||
|
||||
const char *serval_instancepath();
|
||||
const char *instance_path(); // returns NULL if not using an instance path
|
||||
int create_serval_instance_dir();
|
||||
int formf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int vformf_serval_instance_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, va_list);
|
||||
|
||||
int _formf_serval_etc_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int _formf_serval_run_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int _vformf_serval_run_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, va_list);
|
||||
int _formf_serval_cache_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int _formf_serval_tmp_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int _formf_servald_proc_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
int _formf_rhizome_store_path(struct __sourceloc, char *buf, size_t bufsiz, const char *fmt, ...) __attribute__((format(printf,4,5)));
|
||||
|
||||
#define formf_serval_etc_path(buf,bufsz,fmt,...) _formf_serval_etc_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
#define formf_serval_run_path(buf,bufsz,fmt,...) _formf_serval_run_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
#define vformf_serval_run_path(buf,bufsz,fmt,ap) _vformf_serval_run_path(__WHENCE__, buf, bufsz, fmt, ap)
|
||||
#define formf_serval_cache_path(buf,bufsz,fmt,...) _formf_serval_cache_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
#define formf_serval_tmp_path(buf,bufsz,fmt,...) _formf_serval_tmp_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
#define formf_servald_proc_path(buf,bufsz,fmt,...) _formf_servald_proc_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
#define formf_rhizome_store_path(buf,bufsz,fmt,...) _formf_rhizome_store_path(__WHENCE__, buf, bufsz, fmt, ##__VA_ARGS__)
|
||||
|
||||
/* Handy macros for forming the absolute paths of various files, using a char[]
|
||||
* buffer whose declaration is in scope (so that sizeof(buf) will work).
|
||||
* Evaluates to true if the pathname fits into the provided buffer, false (0)
|
||||
* otherwise (after logging an error).
|
||||
*/
|
||||
#define FORMF_SERVAL_ETC_PATH(buf,fmt,...) formf_serval_etc_path(buf, sizeof(buf), fmt, ##__VA_ARGS__)
|
||||
#define FORMF_SERVAL_RUN_PATH(buf,fmt,...) formf_serval_run_path(buf, sizeof(buf), fmt, ##__VA_ARGS__)
|
||||
#define FORMF_SERVAL_CACHE_PATH(buf,fmt,...) formf_serval_cache_path(buf, sizeof(buf), fmt, ##__VA_ARGS__)
|
||||
#define FORMF_SERVAL_TMP_PATH(buf,fmt,...) formf_serval_tmp_path(buf, sizeof(buf), fmt, ##__VA_ARGS__)
|
||||
#define FORMF_SERVALD_PROC_PATH(buf,fmt,...) formf_servald_proc_path(buf, sizeof(buf), fmt, ##__VA_ARGS__)
|
||||
#define FORMF_RHIZOME_STORE_PATH(buf,fmt,...) formf_rhizome_store_path((buf), sizeof(buf), (fmt), ##__VA_ARGS__)
|
||||
|
||||
strbuf strbuf_system_log_path(strbuf sb);
|
||||
strbuf strbuf_serval_log_path(strbuf sb);
|
||||
|
||||
#endif // __SERVAL_DNA__INSTANCE_H
|
||||
|
@ -2020,7 +2020,7 @@ keyring_file *keyring_open_instance()
|
||||
if (!env)
|
||||
env = "serval.keyring";
|
||||
char keyringFile[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(keyringFile, env))
|
||||
if (!FORMF_SERVAL_ETC_PATH(keyringFile, "%s", env))
|
||||
RETURN(NULL);
|
||||
// Work out if the keyring file is writeable.
|
||||
int writeable = 0;
|
||||
|
60
log.c
60
log.c
@ -95,9 +95,12 @@ static FILE *_log_file = NULL;
|
||||
static void _open_log_file(_log_iterator *);
|
||||
static void _rotate_log_file(_log_iterator *it);
|
||||
static void _flush_log_file();
|
||||
struct _log_state state_file;
|
||||
struct config_log_format config_file;
|
||||
time_t _log_file_start_time;
|
||||
static struct _log_state state_file;
|
||||
static struct config_log_format config_file;
|
||||
static struct { size_t len; mode_t mode; } mkdir_trace[10];
|
||||
static mode_t mkdir_trace_latest_mode;
|
||||
static unsigned mkdir_count;
|
||||
static time_t _log_file_start_time;
|
||||
static char _log_file_buf[8192];
|
||||
static struct strbuf _log_file_strbuf = STRUCT_STRBUF_EMPTY;
|
||||
|
||||
@ -424,11 +427,6 @@ static void _logs_printf_nl(int level, struct __sourceloc whence, const char *fm
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
const char *log_file_directory_path()
|
||||
{
|
||||
return config.log.file.directory_path;
|
||||
}
|
||||
|
||||
static void _compute_file_start_time(_log_iterator *it)
|
||||
{
|
||||
if (it->file_start_time == 0) {
|
||||
@ -440,6 +438,27 @@ static void _compute_file_start_time(_log_iterator *it)
|
||||
}
|
||||
}
|
||||
|
||||
static void trace_mkdir(struct __sourceloc UNUSED(whence), const char *path, mode_t mode)
|
||||
{
|
||||
if (mkdir_count < NELS(mkdir_trace)) {
|
||||
mkdir_trace[mkdir_count].len = strlen(path);
|
||||
mkdir_trace[mkdir_count].mode = mode;
|
||||
}
|
||||
++mkdir_count;
|
||||
mkdir_trace_latest_mode = mode;
|
||||
}
|
||||
|
||||
static void log_mkdir_trace(const char *dir)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < mkdir_count && i < NELS(mkdir_trace); ++i)
|
||||
_logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Created %s (mode %04o)", alloca_toprint(-1, dir, mkdir_trace[i].len), mkdir_trace[i].mode);
|
||||
if (mkdir_count > NELS(mkdir_trace) + 1)
|
||||
_logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Created ...");
|
||||
if (mkdir_count > NELS(mkdir_trace))
|
||||
_logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Created %s (mode %04o)", alloca_str_toprint(dir), mkdir_trace_latest_mode);
|
||||
}
|
||||
|
||||
static void _open_log_file(_log_iterator *it)
|
||||
{
|
||||
assert(it->state == &state_file);
|
||||
@ -448,14 +467,15 @@ static void _open_log_file(_log_iterator *it)
|
||||
_log_file_path = getenv("SERVALD_LOG_FILE");
|
||||
if (_log_file_path == NULL && !cf_limbo) {
|
||||
strbuf sbfile = strbuf_local(_log_file_path_buf, sizeof _log_file_path_buf);
|
||||
strbuf_path_join(sbfile, serval_instancepath(), log_file_directory_path(), NULL);
|
||||
strbuf_serval_log_path(sbfile);
|
||||
strbuf_path_join(sbfile, config.log.file.directory_path, "", NULL); // with trailing '/'
|
||||
_compute_file_start_time(it);
|
||||
if (config.log.file.path[0]) {
|
||||
strbuf_path_join(sbfile, config.log.file.path, NULL);
|
||||
} else {
|
||||
struct tm tm;
|
||||
(void)localtime_r(&it->file_start_time, &tm);
|
||||
strbuf_append_strftime(sbfile, "/serval-%Y%m%d%H%M%S.log", &tm);
|
||||
strbuf_append_strftime(sbfile, "serval-%Y%m%d%H%M%S.log", &tm);
|
||||
}
|
||||
if (strbuf_overrun(sbfile)) {
|
||||
_log_file = NO_FILE;
|
||||
@ -477,16 +497,27 @@ static void _open_log_file(_log_iterator *it)
|
||||
char _dir[dirsiz];
|
||||
strcpy(_dir, _log_file_path);
|
||||
const char *dir = dirname(_dir); // modifies _dir[]
|
||||
if (mkdirs(dir, 0700) != -1 && (_log_file = fopen(_log_file_path, "a"))) {
|
||||
mkdir_count = 0;
|
||||
if (mkdirs_log(dir, 0700, trace_mkdir) == -1) {
|
||||
_log_file = NO_FILE;
|
||||
log_mkdir_trace(dir);
|
||||
_logs_printf_nl(LOG_LEVEL_WARN, __HERE__, "Cannot mkdir %s - %s [errno=%d]", alloca_str_toprint(dir), strerror(errno), errno);
|
||||
} else if ((_log_file = fopen(_log_file_path, "a")) == NULL) {
|
||||
_log_file = NO_FILE;
|
||||
log_mkdir_trace(dir);
|
||||
_logs_printf_nl(LOG_LEVEL_WARN, __HERE__, "Cannot create-append %s - %s [errno=%d]", _log_file_path, strerror(errno), errno);
|
||||
} else {
|
||||
setlinebuf(_log_file);
|
||||
memset(it->state, 0, sizeof *it->state);
|
||||
// The first line in every log file must be the starting time stamp. (After that, it is up
|
||||
// to _log_update() to insert other mandatory messages in any suitable order.)
|
||||
_log_current_datetime(it, LOG_LEVEL_INFO);
|
||||
log_mkdir_trace(dir);
|
||||
_logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Logging to %s (fd %d)", _log_file_path, fileno(_log_file));
|
||||
// Update the log symlink to point to the latest log file.
|
||||
strbuf sbsymlink = strbuf_alloca(400);
|
||||
strbuf_path_join(sbsymlink, serval_instancepath(), "serval.log", NULL);
|
||||
strbuf_system_log_path(sbsymlink);
|
||||
strbuf_path_join(sbsymlink, "serval.log", NULL);
|
||||
if (strbuf_overrun(sbsymlink))
|
||||
_logs_printf_nl(LOG_LEVEL_ERROR, __HERE__, "Cannot form log symlink name - buffer overrun");
|
||||
else {
|
||||
@ -556,9 +587,6 @@ static void _open_log_file(_log_iterator *it)
|
||||
_logs_printf_nl(LOG_LEVEL_INFO, __NOWHERE__, "Unlink %s", path);
|
||||
unlink(path);
|
||||
}
|
||||
} else {
|
||||
_log_file = NO_FILE;
|
||||
_logs_printf_nl(LOG_LEVEL_WARN, __HERE__, "Cannot create/append %s - %s [errno=%d]", _log_file_path, strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -741,7 +769,7 @@ int log_backtrace(int level, struct __sourceloc whence)
|
||||
if (get_self_executable_path(execpath, sizeof execpath) == -1)
|
||||
return WHY("cannot log backtrace: own executable path unknown");
|
||||
char tempfile[MAXPATHLEN];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(tempfile, "servalgdb.XXXXXX"))
|
||||
if (!FORMF_SERVAL_TMP_PATH(tempfile, "servalgdb.XXXXXX"))
|
||||
return -1;
|
||||
int tmpfd = mkstemp(tempfile);
|
||||
if (tmpfd == -1)
|
||||
|
1
log.h
1
log.h
@ -92,7 +92,6 @@ extern const struct __sourceloc __whence; // see above
|
||||
|
||||
extern int serverMode;
|
||||
|
||||
const char *log_file_directory_path();
|
||||
int create_log_file_directory();
|
||||
|
||||
void close_log_file();
|
||||
|
43
os.c
43
os.c
@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define __SERVAL_DNA__OS_INLINE
|
||||
#include "constants.h"
|
||||
#include "os.h"
|
||||
#include "str.h"
|
||||
#include "log.h"
|
||||
@ -31,39 +32,52 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
int mkdirs(const char *path, mode_t mode)
|
||||
void log_info_mkdir(struct __sourceloc __whence, const char *path, mode_t mode)
|
||||
{
|
||||
return mkdirsn(path, strlen(path), mode);
|
||||
INFOF("mkdir %s (mode %04o)", alloca_str_toprint(path), mode);
|
||||
}
|
||||
|
||||
int _emkdirs(struct __sourceloc __whence, const char *path, mode_t mode)
|
||||
int _mkdirs(struct __sourceloc __whence, const char *path, mode_t mode, MKDIR_LOG_FUNC *logger)
|
||||
{
|
||||
if (mkdirs(path, mode) == -1)
|
||||
return _mkdirsn(__whence, path, strlen(path), mode, logger);
|
||||
}
|
||||
|
||||
int _emkdirs(struct __sourceloc __whence, const char *path, mode_t mode, MKDIR_LOG_FUNC *logger)
|
||||
{
|
||||
if (_mkdirs(__whence, path, mode, logger) == -1)
|
||||
return WHYF_perror("mkdirs(%s,%o)", alloca_str_toprint(path), mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _emkdirsn(struct __sourceloc __whence, const char *path, size_t len, mode_t mode)
|
||||
int _emkdirsn(struct __sourceloc __whence, const char *path, size_t len, mode_t mode, MKDIR_LOG_FUNC *logger)
|
||||
{
|
||||
if (mkdirsn(path, len, mode) == -1)
|
||||
if (_mkdirsn(__whence, path, len, mode, logger) == -1)
|
||||
return WHYF_perror("mkdirsn(%s,%lu,%o)", alloca_toprint(-1, path, len), (unsigned long)len, mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This variant must not log anything, because it is used by the logging subsystem itself!
|
||||
/* This variant must not log anything itself, because it is called by the logging subsystem, and
|
||||
* that would cause infinite recursion!
|
||||
*
|
||||
* The path need not be NUL terminated.
|
||||
*
|
||||
* The logger function pointer is usually NULL, for no logging, but may be any function the caller
|
||||
* supplies (for example, log_info_mkdir).
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int mkdirsn(const char *path, size_t len, mode_t mode)
|
||||
int _mkdirsn(struct __sourceloc whence, const char *path, size_t len, mode_t mode, MKDIR_LOG_FUNC *logger)
|
||||
{
|
||||
if (len == 0)
|
||||
errno = EINVAL;
|
||||
else {
|
||||
char *pathfrag = alloca(len + 1);
|
||||
strncpy(pathfrag, path, len);
|
||||
pathfrag[len] = '\0';
|
||||
if (mkdir(pathfrag, mode) != -1)
|
||||
strncpy(pathfrag, path, len)[len] = '\0';
|
||||
if (mkdir(pathfrag, mode) != -1) {
|
||||
if (logger)
|
||||
logger(whence, pathfrag, mode);
|
||||
return 0;
|
||||
}
|
||||
if (errno == EEXIST) {
|
||||
DIR *d = opendir(pathfrag);
|
||||
if (d) {
|
||||
@ -78,10 +92,13 @@ int mkdirsn(const char *path, size_t len, mode_t mode)
|
||||
while (lastsep != path && *--lastsep == '/')
|
||||
;
|
||||
if (lastsep != path) {
|
||||
if (mkdirsn(path, lastsep - path + 1, mode) == -1)
|
||||
if (_mkdirsn(whence, path, lastsep - path + 1, mode, logger) == -1)
|
||||
return -1;
|
||||
if (mkdir(pathfrag, mode) != -1)
|
||||
if (mkdir(pathfrag, mode) != -1) {
|
||||
if (logger)
|
||||
logger(whence, pathfrag, mode);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
os.h
26
os.h
@ -103,13 +103,27 @@ __SERVAL_DNA__OS_INLINE off64_t lseek64(int fd, off64_t offset, int whence) {
|
||||
|
||||
/* The "e" variants log the error before returning -1.
|
||||
*/
|
||||
int mkdirs(const char *path, mode_t mode);
|
||||
int mkdirsn(const char *path, size_t len, mode_t mode);
|
||||
int _emkdirs(struct __sourceloc, const char *path, mode_t mode);
|
||||
int _emkdirsn(struct __sourceloc, const char *path, size_t len, mode_t mode);
|
||||
typedef void MKDIR_LOG_FUNC(struct __sourceloc, const char *, mode_t);
|
||||
MKDIR_LOG_FUNC log_info_mkdir;
|
||||
int _mkdirs(struct __sourceloc, const char *path, mode_t mode, MKDIR_LOG_FUNC *);
|
||||
int _mkdirsn(struct __sourceloc, const char *path, size_t len, mode_t mode, MKDIR_LOG_FUNC *);
|
||||
int _emkdirs(struct __sourceloc, const char *path, mode_t mode, MKDIR_LOG_FUNC *);
|
||||
int _emkdirsn(struct __sourceloc, const char *path, size_t len, mode_t mode, MKDIR_LOG_FUNC *);
|
||||
|
||||
#define emkdirs(path, mode) _emkdirs(__WHENCE__, (path), (mode))
|
||||
#define emkdirsn(path, len, mode) _emkdirsn(__WHENCE__, (path), (len), (mode))
|
||||
#define mkdirs_log(path, mode, func) _mkdirs(__WHENCE__, (path), (mode), (func))
|
||||
#define mkdirsn_log(path, len, mode, func) _mkdirsn(__WHENCE__, (path), (len), (mode), (func))
|
||||
#define emkdirs_log(path, mode, func) _emkdirs(__WHENCE__, (path), (mode), (func))
|
||||
#define emkdirsn_log(path, len, mode, func) _emkdirsn(__WHENCE__, (path), (len), (mode), (func))
|
||||
|
||||
#define mkdirs(path, mode) mkdirs_log((path), (mode), NULL)
|
||||
#define mkdirsn(path, len, mode) mkdirsn_log((path), (len), (mode), NULL)
|
||||
#define emkdirs(path, mode) emkdirs_log((path), (mode), NULL)
|
||||
#define emkdirsn(path, len, mode) emkdirsn_log((path), (len), (mode), NULL)
|
||||
|
||||
#define mkdirs_info(path, mode) mkdirs_log((path), (mode), log_info_mkdir)
|
||||
#define mkdirsn_info(path, len, mode) mkdirsn_log((path), (len), (mode), log_info_mkdir)
|
||||
#define emkdirs_info(path, mode) emkdirs_log((path), (mode), log_info_mkdir)
|
||||
#define emkdirsn_info(path, len, mode) emkdirsn_log((path), (len), (mode), log_info_mkdir)
|
||||
|
||||
void srandomdev();
|
||||
int urandombytes(unsigned char *buf, size_t len);
|
||||
|
@ -497,14 +497,9 @@ overlay_interface_init(const char *name, struct socket_address *addr,
|
||||
return WHY("overlay_interface_init_socket() failed");
|
||||
}else{
|
||||
char read_file[1024];
|
||||
|
||||
interface->local_echo = interface->point_to_point?0:1;
|
||||
|
||||
strbuf d = strbuf_local(read_file, sizeof read_file);
|
||||
strbuf_path_join(d, serval_instancepath(), config.server.interface_path, ifconfig->file, NULL);
|
||||
if (strbuf_overrun(d))
|
||||
return WHYF("interface file name overrun: %s", alloca_str_toprint(strbuf_str(d)));
|
||||
|
||||
if (!FORMF_SERVAL_TMP_PATH(read_file, "%s/%s", config.server.interface_path, ifconfig->file))
|
||||
return -1;
|
||||
if ((interface->alarm.poll.fd = open(read_file, O_APPEND|O_RDWR)) == -1) {
|
||||
if (errno == ENOENT && ifconfig->socket_type == SOCK_FILE) {
|
||||
cleanup_ret = 1;
|
||||
@ -1071,10 +1066,7 @@ void overlay_interface_discover(struct sched_ent *alarm)
|
||||
{
|
||||
// use a local dgram socket
|
||||
// no abstract sockets for now
|
||||
strbuf d = strbuf_local(addr.local.sun_path, sizeof addr.local.sun_path);
|
||||
strbuf_path_join(d, serval_instancepath(), config.server.interface_path, ifconfig->file, NULL);
|
||||
if (strbuf_overrun(d)){
|
||||
WHYF("interface file name overrun: %s", alloca_str_toprint(strbuf_str(d)));
|
||||
if (!FORMF_SERVAL_RUN_PATH(addr.local.sun_path, "%s/%s", config.server.interface_path, ifconfig->file)) {
|
||||
// TODO set ifconfig->exclude to prevent spam??
|
||||
break;
|
||||
}
|
||||
|
@ -97,26 +97,28 @@ static int mdp_send2(const struct socket_address *client, const struct mdp_heade
|
||||
/* Delete all UNIX socket files in instance directory. */
|
||||
void overlay_mdp_clean_socket_files()
|
||||
{
|
||||
const char *instance_path = serval_instancepath();
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
if ((dir = opendir(instance_path)) == NULL) {
|
||||
WARNF_perror("opendir(%s)", alloca_str_toprint(instance_path));
|
||||
return;
|
||||
}
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
char path[PATH_MAX];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(path, dp->d_name))
|
||||
continue;
|
||||
struct stat st;
|
||||
if (lstat(path, &st)) {
|
||||
WARNF_perror("stat(%s)", alloca_str_toprint(path));
|
||||
continue;
|
||||
char path[PATH_MAX];
|
||||
if (FORMF_SERVAL_RUN_PATH(path, NULL)) {
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
if ((dir = opendir(path)) == NULL) {
|
||||
WARNF_perror("opendir(%s)", alloca_str_toprint(path));
|
||||
return;
|
||||
}
|
||||
if (S_ISSOCK(st.st_mode))
|
||||
unlink(path);
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
path[0] = '\0';
|
||||
if (!FORMF_SERVAL_RUN_PATH(path, "%s", dp->d_name))
|
||||
continue;
|
||||
struct stat st;
|
||||
if (lstat(path, &st)) {
|
||||
WARNF_perror("stat(%s)", alloca_str_toprint(path));
|
||||
continue;
|
||||
}
|
||||
if (S_ISSOCK(st.st_mode))
|
||||
unlink(path);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
static void overlay_mdp_fill_legacy(
|
||||
|
10
rhizome.h
10
rhizome.h
@ -395,16 +395,6 @@ int rhizome_configure();
|
||||
int rhizome_enabled();
|
||||
int rhizome_fetch_delay_ms();
|
||||
|
||||
int rhizome_set_datastore_path(const char *path);
|
||||
|
||||
const char *rhizome_datastore_path();
|
||||
int form_rhizome_datastore_path(struct __sourceloc, char * buf, size_t bufsiz, const char *fmt, ...);
|
||||
|
||||
/* Handy statement for forming the path of a rhizome store file in a char buffer whose declaration
|
||||
* is in scope (so that sizeof(buf) will work). Evaluates to true if the pathname fitted into
|
||||
* the provided buffer, false (0) otherwise (after logging an error). */
|
||||
#define FORM_RHIZOME_DATASTORE_PATH(buf,fmt,...) (form_rhizome_datastore_path(__WHENCE__, (buf), sizeof(buf), (fmt), ##__VA_ARGS__))
|
||||
|
||||
#define RHIZOME_BLOB_SUBDIR "blob"
|
||||
|
||||
extern sqlite3 *rhizome_db;
|
||||
|
@ -30,51 +30,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "str.h"
|
||||
#include "keyring.h"
|
||||
|
||||
static char rhizome_thisdatastore_path[256];
|
||||
|
||||
static int rhizome_delete_manifest_retry(sqlite_retry_state *retry, const rhizome_bid_t *bidp);
|
||||
static int rhizome_delete_file_retry(sqlite_retry_state *retry, const rhizome_filehash_t *hashp);
|
||||
static int rhizome_delete_payload_retry(sqlite_retry_state *retry, const rhizome_bid_t *bidp);
|
||||
|
||||
const char *rhizome_datastore_path()
|
||||
{
|
||||
if (!rhizome_thisdatastore_path[0])
|
||||
rhizome_set_datastore_path(NULL);
|
||||
return rhizome_thisdatastore_path;
|
||||
}
|
||||
|
||||
int rhizome_set_datastore_path(const char *path)
|
||||
{
|
||||
strbuf b = strbuf_local(rhizome_thisdatastore_path, sizeof rhizome_thisdatastore_path);
|
||||
strbuf_path_join(b, serval_instancepath(), config.rhizome.datastore_path, path, NULL);
|
||||
INFOF("Rhizome datastore path = %s", alloca_str_toprint(rhizome_thisdatastore_path));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int form_rhizome_datastore_path(struct __sourceloc __whence, char * buf, size_t bufsiz, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
strbuf b = strbuf_local(buf, bufsiz);
|
||||
strbuf_puts(b, rhizome_datastore_path());
|
||||
if (fmt) {
|
||||
va_start(ap, fmt);
|
||||
if (*strbuf_substr(b, -1) != '/')
|
||||
strbuf_putc(b, '/');
|
||||
strbuf_vsprintf(b, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
if (strbuf_overrun(b)) {
|
||||
WHY("Path buffer overrun");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int create_rhizome_datastore_dir()
|
||||
static int create_rhizome_store_dir()
|
||||
{
|
||||
char rdpath[1024];
|
||||
if (!formf_rhizome_store_path(rdpath, sizeof rdpath, "%s", config.rhizome.datastore_path))
|
||||
return -1;
|
||||
INFOF("Rhizome datastore path = %s", alloca_str_toprint(rdpath));
|
||||
if (config.debug.rhizome)
|
||||
DEBUGF("mkdirs(%s, 0700)", rhizome_datastore_path());
|
||||
return emkdirs(rhizome_datastore_path(), 0700);
|
||||
DEBUGF("mkdirs(%s, 0700)", alloca_str_toprint(rdpath));
|
||||
return emkdirs_info(rdpath, 0700);
|
||||
}
|
||||
|
||||
sqlite3 *rhizome_db = NULL;
|
||||
@ -239,23 +207,23 @@ int rhizome_opendb()
|
||||
|
||||
IN();
|
||||
|
||||
if (create_rhizome_datastore_dir() == -1)
|
||||
if (create_rhizome_store_dir() == -1)
|
||||
RETURN(-1);
|
||||
char dbpath[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(dbpath, RHIZOME_BLOB_SUBDIR))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(dbpath, RHIZOME_BLOB_SUBDIR))
|
||||
RETURN(-1);
|
||||
if (emkdirs(dbpath, 0700) == -1)
|
||||
if (emkdirs_info(dbpath, 0700) == -1)
|
||||
RETURN(-1);
|
||||
if (!sqlite3_temp_directory) {
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(dbpath, "sqlite3tmp"))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(dbpath, "sqlite3tmp"))
|
||||
RETURN(-1);
|
||||
if (emkdirs(dbpath, 0700) == -1)
|
||||
if (emkdirs_info(dbpath, 0700) == -1)
|
||||
RETURN(-1);
|
||||
sqlite3_temp_directory = sqlite3_mprintf("%s", dbpath);
|
||||
}
|
||||
sqlite3_config(SQLITE_CONFIG_LOG,sqlite_log,NULL);
|
||||
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(dbpath, "rhizome.db"))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(dbpath, "rhizome.db"))
|
||||
RETURN(-1);
|
||||
if (sqlite3_open(dbpath,&rhizome_db)){
|
||||
RETURN(WHYF("SQLite could not open database %s: %s", dbpath, sqlite3_errmsg(rhizome_db)));
|
||||
@ -1191,7 +1159,7 @@ static int rhizome_delete_external(const char *id)
|
||||
{
|
||||
// attempt to remove any external blob
|
||||
char blob_path[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(blob_path, "%s/%s", RHIZOME_BLOB_SUBDIR, id))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(blob_path, "%s/%s", RHIZOME_BLOB_SUBDIR, id))
|
||||
return -1;
|
||||
if (unlink(blob_path) == -1) {
|
||||
if (errno != ENOENT)
|
||||
|
@ -204,9 +204,7 @@ static int rhizome_direct_addfile_end(struct http_request *hr)
|
||||
char manifestTemplate[1024];
|
||||
manifestTemplate[0] = '\0';
|
||||
if (config.rhizome.api.addfile.manifest_template_file[0]) {
|
||||
strbuf b = strbuf_local(manifestTemplate, sizeof manifestTemplate);
|
||||
strbuf_path_join(b, serval_instancepath(), config.rhizome.api.addfile.manifest_template_file, NULL);
|
||||
if (strbuf_overrun(b)) {
|
||||
if (!FORMF_SERVAL_ETC_PATH(manifestTemplate, "%s", config.rhizome.api.addfile.manifest_template_file)) {
|
||||
rhizome_direct_clear_temporary_files(r);
|
||||
http_request_simple_response(&r->http, 500, "Internal Error: Template path too long");
|
||||
return 0;
|
||||
|
@ -105,7 +105,7 @@ enum rhizome_payload_status rhizome_open_write(struct rhizome_write *write, cons
|
||||
}
|
||||
char blob_path[1024];
|
||||
if (file_length == RHIZOME_SIZE_UNSET || file_length > config.rhizome.max_blob_size) {
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(blob_path, "%s/%"PRIu64, RHIZOME_BLOB_SUBDIR, write->temp_id))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(blob_path, "%s/%"PRIu64, RHIZOME_BLOB_SUBDIR, write->temp_id))
|
||||
return RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
if (config.debug.rhizome_store)
|
||||
DEBUGF("Attempting to put blob for id='%"PRIu64"' in %s", write->temp_id, blob_path);
|
||||
@ -473,7 +473,7 @@ enum rhizome_payload_status rhizome_finish_write(struct rhizome_write *write)
|
||||
SHA512_End(&write->sha512_context, NULL);
|
||||
|
||||
char blob_path[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(blob_path, "%s/%"PRIu64, RHIZOME_BLOB_SUBDIR, write->temp_id)) {
|
||||
if (!FORMF_RHIZOME_STORE_PATH(blob_path, "%s/%"PRIu64, RHIZOME_BLOB_SUBDIR, write->temp_id)) {
|
||||
WHYF("Failed to generate external blob path");
|
||||
status = RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
goto failure;
|
||||
@ -549,7 +549,7 @@ enum rhizome_payload_status rhizome_finish_write(struct rhizome_write *write)
|
||||
|
||||
if (external) {
|
||||
char dest_path[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(dest_path, "%s/%s", RHIZOME_BLOB_SUBDIR, alloca_tohex_rhizome_filehash_t(write->id)))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(dest_path, "%s/%s", RHIZOME_BLOB_SUBDIR, alloca_tohex_rhizome_filehash_t(write->id)))
|
||||
goto dbfailure;
|
||||
if (rename(blob_path, dest_path) == -1) {
|
||||
WHYF_perror("rename(%s, %s)", blob_path, dest_path);
|
||||
@ -776,7 +776,7 @@ enum rhizome_payload_status rhizome_open_read(struct rhizome_read *read, const r
|
||||
} else {
|
||||
// No row in FILEBLOBS, look for an external blob file.
|
||||
char blob_path[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(blob_path, "%s/%s", RHIZOME_BLOB_SUBDIR, alloca_tohex_rhizome_filehash_t(read->id)))
|
||||
if (!FORMF_RHIZOME_STORE_PATH(blob_path, "%s/%s", RHIZOME_BLOB_SUBDIR, alloca_tohex_rhizome_filehash_t(read->id)))
|
||||
return RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
read->blob_fd = open(blob_path, O_RDONLY);
|
||||
if (read->blob_fd == -1) {
|
||||
|
3
serval.h
3
serval.h
@ -206,7 +206,6 @@ extern char *gatewayspec;
|
||||
|
||||
int rhizome_enabled();
|
||||
int rhizome_http_server_running();
|
||||
const char *rhizome_datastore_path();
|
||||
|
||||
#define MAX_PEERS 1024
|
||||
extern int peer_count;
|
||||
@ -279,6 +278,8 @@ struct slip_decode_state{
|
||||
|
||||
|
||||
int server_pid();
|
||||
const char *_server_pidfile_path(struct __sourceloc);
|
||||
#define server_pidfile_path() (_server_pidfile_path(__WHENCE__))
|
||||
void server_save_argv(int argc, const char *const *argv);
|
||||
int server(const struct cli_parsed *parsed);
|
||||
int server_write_pid();
|
||||
|
105
server.c
105
server.c
@ -31,9 +31,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "strbuf_helpers.h"
|
||||
#include "overlay_interface.h"
|
||||
|
||||
#define PROC_SUBDIR "proc"
|
||||
#define PIDFILE_NAME "servald.pid"
|
||||
#define STOPFILE_NAME "servald.stop"
|
||||
|
||||
static char pidfile_path[256];
|
||||
|
||||
#define EXEC_NARGS 20
|
||||
char *exec_args[EXEC_NARGS + 1];
|
||||
unsigned exec_argc = 0;
|
||||
@ -49,31 +52,45 @@ void crash_handler(int signal);
|
||||
*/
|
||||
int server_pid()
|
||||
{
|
||||
const char *instancepath = serval_instancepath();
|
||||
struct stat st;
|
||||
if (stat(instancepath, &st) == -1)
|
||||
return WHYF_perror("stat(%s)", alloca_str_toprint(instancepath));
|
||||
if ((st.st_mode & S_IFMT) != S_IFDIR)
|
||||
return WHYF("Instance path '%s' is not a directory", instancepath);
|
||||
char filename[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME))
|
||||
char dirname[1024];
|
||||
if (!FORMF_SERVAL_RUN_PATH(dirname, NULL))
|
||||
return -1;
|
||||
FILE *f = fopen(filename, "r");
|
||||
struct stat st;
|
||||
if (stat(dirname, &st) == -1)
|
||||
return WHYF_perror("stat(%s)", alloca_str_toprint(dirname));
|
||||
if ((st.st_mode & S_IFMT) != S_IFDIR)
|
||||
return WHYF("Not a directory: %s", dirname);
|
||||
const char *ppath = server_pidfile_path();
|
||||
if (ppath == NULL)
|
||||
return -1;
|
||||
const char *p = strrchr(ppath, '/');
|
||||
assert(p != NULL);
|
||||
|
||||
FILE *f = fopen(ppath, "r");
|
||||
if (f == NULL) {
|
||||
if (errno != ENOENT)
|
||||
return WHYF_perror("fopen(%s,\"r\")", alloca_str_toprint(filename));
|
||||
return WHYF_perror("fopen(%s,\"r\")", alloca_str_toprint(ppath));
|
||||
} else {
|
||||
char buf[20];
|
||||
int pid = (fgets(buf, sizeof buf, f) != NULL) ? atoi(buf) : -1;
|
||||
fclose(f);
|
||||
if (pid > 0 && kill(pid, 0) != -1)
|
||||
return pid;
|
||||
INFOF("Unlinking stale pidfile %s", filename);
|
||||
unlink(filename);
|
||||
INFOF("Unlinking stale pidfile %s", ppath);
|
||||
unlink(ppath);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *_server_pidfile_path(struct __sourceloc __whence)
|
||||
{
|
||||
if (!pidfile_path[0]) {
|
||||
if (!FORMF_SERVAL_RUN_PATH(pidfile_path, PIDFILE_NAME))
|
||||
return NULL;
|
||||
}
|
||||
return pidfile_path;
|
||||
}
|
||||
|
||||
void server_save_argv(int argc, const char *const *argv)
|
||||
{
|
||||
/* Save our argv[] to use for relaunching */
|
||||
@ -123,26 +140,22 @@ int server(const struct cli_parsed *parsed)
|
||||
int server_write_pid()
|
||||
{
|
||||
/* Record PID to advertise that the server is now running */
|
||||
char filename[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(filename, PIDFILE_NAME))
|
||||
const char *ppath = server_pidfile_path();
|
||||
if (ppath == NULL)
|
||||
return -1;
|
||||
FILE *f=fopen(filename,"w");
|
||||
if (!f) {
|
||||
WHY_perror("fopen");
|
||||
return WHYF("Could not write to PID file %s", filename);
|
||||
}
|
||||
FILE *f = fopen(ppath, "w");
|
||||
if (!f)
|
||||
return WHYF_perror("fopen(%s,\"w\")", alloca_str_toprint(ppath));
|
||||
server_getpid = getpid();
|
||||
fprintf(f,"%d\n", server_getpid);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_proc_path(const char *path, char *buff, size_t buff_len)
|
||||
static int get_proc_path(const char *path, char *buf, size_t bufsiz)
|
||||
{
|
||||
strbuf sbname = strbuf_local(buff, buff_len);
|
||||
strbuf_path_join(sbname, serval_instancepath(), "proc", path, NULL);
|
||||
if (strbuf_overrun(sbname))
|
||||
return WHY("Buffer overrun building proc filename");
|
||||
if (!formf_serval_run_path(buf, bufsiz, PROC_SUBDIR "/%s", path))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -156,7 +169,7 @@ int server_write_proc_state(const char *path, const char *fmt, ...)
|
||||
char dir_buf[dirsiz];
|
||||
strcpy(dir_buf, path_buf);
|
||||
const char *dir = dirname(dir_buf); // modifies dir_buf[]
|
||||
if (mkdirs(dir, 0700) == -1)
|
||||
if (mkdirs_info(dir, 0700) == -1)
|
||||
return WHY_perror("mkdirs()");
|
||||
|
||||
FILE *f = fopen(path_buf, "w");
|
||||
@ -249,7 +262,7 @@ void server_shutdown_check(struct sched_ent *alarm)
|
||||
int server_create_stopfile()
|
||||
{
|
||||
char stopfile[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, STOPFILE_NAME))
|
||||
if (!FORMF_SERVAL_RUN_PATH(stopfile, STOPFILE_NAME))
|
||||
return -1;
|
||||
FILE *f;
|
||||
if ((f = fopen(stopfile, "w")) == NULL) {
|
||||
@ -263,7 +276,7 @@ int server_create_stopfile()
|
||||
int server_remove_stopfile()
|
||||
{
|
||||
char stopfile[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, STOPFILE_NAME))
|
||||
if (!FORMF_SERVAL_RUN_PATH(stopfile, STOPFILE_NAME))
|
||||
return -1;
|
||||
if (unlink(stopfile) == -1) {
|
||||
if (errno == ENOENT)
|
||||
@ -277,7 +290,7 @@ int server_remove_stopfile()
|
||||
int server_check_stopfile()
|
||||
{
|
||||
char stopfile[1024];
|
||||
if (!FORM_SERVAL_INSTANCE_PATH(stopfile, STOPFILE_NAME))
|
||||
if (!FORMF_SERVAL_RUN_PATH(stopfile, STOPFILE_NAME))
|
||||
return -1;
|
||||
int r = access(stopfile, F_OK);
|
||||
if (r == 0)
|
||||
@ -292,27 +305,23 @@ int server_check_stopfile()
|
||||
static void clean_proc()
|
||||
{
|
||||
char path_buf[400];
|
||||
strbuf sbname = strbuf_local(path_buf, sizeof path_buf);
|
||||
strbuf_path_join(sbname, serval_instancepath(), "proc", NULL);
|
||||
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
if ((dir = opendir(path_buf)) == NULL) {
|
||||
WARNF_perror("opendir(%s)", alloca_str_toprint(path_buf));
|
||||
return;
|
||||
}
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
strbuf_reset(sbname);
|
||||
strbuf_path_join(sbname, serval_instancepath(), "proc", dp->d_name, NULL);
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path_buf, &st)) {
|
||||
WARNF_perror("stat(%s)", path_buf);
|
||||
continue;
|
||||
if (FORMF_SERVAL_RUN_PATH(path_buf, PROC_SUBDIR)) {
|
||||
DIR *dir;
|
||||
struct dirent *dp;
|
||||
if ((dir = opendir(path_buf)) == NULL) {
|
||||
WARNF_perror("opendir(%s)", alloca_str_toprint(path_buf));
|
||||
return;
|
||||
}
|
||||
|
||||
if (S_ISREG(st.st_mode))
|
||||
unlink(path_buf);
|
||||
while ((dp = readdir(dir)) != NULL) {
|
||||
if (FORMF_SERVAL_RUN_PATH(path_buf, PROC_SUBDIR "/%s", dp->d_name)) {
|
||||
struct stat st;
|
||||
if (lstat(path_buf, &st) == -1)
|
||||
WARNF_perror("stat(%s)", path_buf);
|
||||
else if (S_ISREG(st.st_mode))
|
||||
unlink(path_buf);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
9
socket.c
9
socket.c
@ -27,9 +27,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "strbuf_helpers.h"
|
||||
#include "socket.h"
|
||||
|
||||
/* Form the name of an AF_UNIX (local) socket in the instance directory as an absolute path.
|
||||
* Under Linux, this will create a socket name in the abstract namespace. This permits us to use
|
||||
* local sockets on Android despite its lack of a shared writeable directory on a UFS partition.
|
||||
/* Form the name of an AF_UNIX (local) socket in the /var/run/serval (or instance) directory as an
|
||||
* absolute path. Under Linux, this will create a socket name in the abstract namespace. This
|
||||
* permits us to use local sockets on Android despite its lack of a shared writeable directory on a
|
||||
* UFS partition.
|
||||
*
|
||||
* The absolute file name is resolved to its real path using realpath(3), to ensure that name
|
||||
* comparisons of addresses returned by recvmsg(2) can reliably be used on systems where the
|
||||
@ -47,7 +48,7 @@ int _make_local_sockaddr(struct __sourceloc __whence, struct socket_address *add
|
||||
addr->local.sun_family = AF_UNIX;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int r = vformf_serval_instance_path(__WHENCE__, addr->local.sun_path, sizeof addr->local.sun_path, fmt, ap);
|
||||
int r = vformf_serval_run_path(addr->local.sun_path, sizeof addr->local.sun_path, fmt, ap);
|
||||
va_end(ap);
|
||||
if (!r)
|
||||
return WHY("socket name overflow");
|
||||
|
@ -172,7 +172,7 @@ doc_LogFileDirectoryRelative="Relative log file directory path"
|
||||
test_LogFileDirectoryRelative() {
|
||||
executeOk_servald config \
|
||||
set debug.verbose true \
|
||||
set log.file.directory_path "blah"
|
||||
set log.file.directory_path "../blah"
|
||||
executeOk_servald echo one
|
||||
assert --message="exactly one log file" [ $(ls -d "$SERVALINSTANCE_PATH/blah/"*.log | wc -l) -eq 1 ]
|
||||
assertGrep "$SERVALINSTANCE_PATH/blah/"*.log '^DEBUG:.*echo:argv\[1\]="one"$'
|
||||
|
Loading…
x
Reference in New Issue
Block a user