/* SPDX-License-Identifier: GPL-2.0 */
-/** \file daemon.c Some helpers for programs that detach from the console. */
-
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include "str.h"
#include "daemon.h"
-/**
- * Do the usual stuff to become a daemon.
- *
- * Fork, become session leader, dup fd 0, 1, 2 to /dev/null.
- *
- * \sa fork(2), setsid(2), dup(2).
+/*
+ * Do the usual stuff to become a daemon: Fork, become session leader, dup fd
+ * 0, 1, 2 to /dev/null.
*/
int daemon_init(void)
{
exit(EXIT_FAILURE);
}
-/**
- * fopen() the given file in append mode.
- *
- * \param logfile_name The name of the file to open.
- *
- * \return Either calls exit() or returns a valid file handle.
+/*
+ * fopen() the given file in append mode. Either calls exit() or returns a
+ * valid file handle.
*/
FILE *open_log(const char *logfile_name)
{
return logfile;
}
-/**
- * Close the log file of the daemon.
- *
- * \param logfile The log file handle.
- *
- * It's OK to call this with logfile == \p NULL.
+/*
+ * It's OK to call this with logfile == NULL.
*/
void close_log(FILE* logfile)
{
fclose(logfile);
}
-/**
- * Log the startup message.
- */
void log_welcome(int loglevel)
{
DSS_INFO_LOG(("***** welcome to dss ******\n"));
/* SPDX-License-Identifier: GPL-2.0 */
-/** \file daemon.h exported symbols from daemon.c */
-
int daemon_init(void);
FILE *open_log(const char *logfile_name);
void close_log(FILE* logfile);
/* SPDX-License-Identifier: GPL-2.0 */
+
struct disk_space {
unsigned total_mb;
unsigned free_mb;
/* SPDX-License-Identifier: GPL-2.0 */
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
*/
static struct lls_parse_result *cmdline_lpr, *lpr;
-/** Parsed subcommand options. */
+/* Parsed subcommand options. */
static struct lls_parse_result *cmdline_sublpr, *sublpr;
/* The executing subcommand (NULL at startup). */
static const struct lls_command *subcmd;
-/** Wether daemon_init() was called. */
+/* Wether daemon_init() was called. */
static bool daemonized;
-/** Non-NULL if we log to a file. */
+/* Non-NULL if we log to a file. */
static FILE *logfile;
/* Realpath of the config file. */
static char *config_file;
/* derived from config file path */
uint32_t ipc_key;
-/** The read end of the signal pipe */
+/* The read end of the signal pipe */
static int signal_pipe;
-/** Process id of current pre-create-hook/rsync/post-create-hook process. */
+/* Process id of current pre-create-hook/rsync/post-create-hook process. */
static pid_t create_pid;
-/** Whether the pre-create-hook/rsync/post-create-hook is currently stopped. */
+/* Whether the pre-create-hook/rsync/post-create-hook is currently stopped. */
static int create_process_stopped;
-/** How many times in a row the rsync command failed. */
+/* How many times in a row the rsync command failed. */
static int num_consecutive_rsync_errors;
-/** Process id of current pre-remove/rm/post-remove process. */
+/* Process id of current pre-remove/rm/post-remove process. */
static pid_t remove_pid;
-/** When the next snapshot is due. */
+/* When the next snapshot is due. */
static int64_t next_snapshot_time;
-/** When to try to remove something. */
+/* When to try to remove something. */
static struct timeval next_removal_check;
-/** Creation time of the snapshot currently being created. */
+/* Creation time of the snapshot currently being created. */
static int64_t current_snapshot_creation_time;
/* Set by the pre-rm hook, cleared by handle_remove_exit(). */
struct snapshot *snapshot_currently_being_removed;
-/** Needed by the post-create hook. */
+/* Needed by the post-create hook. */
static char *path_to_last_complete_snapshot;
static char *name_of_reference_snapshot;
-/** \sa \ref snap.h for details. */
+/* See snap.h for details. */
enum hook_status snapshot_creation_status;
-/** \sa \ref snap.h for details. */
+/* See snap.h for details. */
enum hook_status snapshot_removal_status;
location_func = func;
}
-/**
- * The log function of dss.
- *
- * \param ll Loglevel.
- * \param fml Usual format string.
- *
- * All DSS_XXX_LOG() macros use this function.
- */
+/* All DSS_XXX_LOG() macros use this function. */
__printf_1_2 void dss_log(const char* fmt,...)
{
va_list argp;
va_end(argp);
}
-/**
- * Print a message either to stdout or to the log file.
- */
+/* Print a message either to stdout or to the log file. */
static __printf_1_2 void dss_msg(const char* fmt,...)
{
FILE *outfd = logfile? logfile : stdout;
create_process_stopped = 0;
}
-/**
- * Print a log message about the exit status of a child.
- */
static void log_termination_msg(pid_t pid, int status)
{
if (WIFEXITED(status))
/* SPDX-License-Identifier: GPL-2.0 */
+
extern char *dss_errlist[];
extern char *dss_error_txt;
void dss_log_set_params(int ll, const char *file, int line, const char *func);
__printf_1_2 void dss_log(const char* fmt,...);
-/**
+/*
* This bit indicates whether a number is considered a system error number
* If yes, the system errno is just the result of clearing this bit from
* the given number.
*/
#define SYSTEM_ERROR_BIT 30
-/** Check whether the system error bit is set. */
+/* Check whether the system error bit is set. */
#define IS_SYSTEM_ERROR(num) (!!((num) & (1 << SYSTEM_ERROR_BIT)))
-/** Set the system error bit for the given number. */
+/* Set the system error bit for the given number. */
#define ERRNO_TO_DSS_ERROR(num) ((num) | (1 << SYSTEM_ERROR_BIT))
-/**
- * dss' version of strerror(3).
- *
- * \param num The error number.
- *
- * \return The error text of \a num.
- */
static inline char *dss_strerror(int num)
{
assert(num > 0);
DSS_ERROR(TOO_MANY_RSYNC_ERRORS, "too many consecutive rsync errors"), \
DSS_ERROR(LOPSUB, "lopsub error")
-/**
+/*
* This is temporarily defined to expand to its first argument (prefixed by
- * 'E_') and gets later redefined to expand to the error text only
+ * 'E_') and gets later redefined to expand to the error text only.
*/
#define DSS_ERROR(err, msg) E_ ## err
/* SPDX-License-Identifier: GPL-2.0 */
-/** \file exec.c Helper functions for spawning new processes. */
-
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "str.h"
#include "exec.h"
-/**
- * Spawn a new process using execvp().
- *
- * \param pid Will hold the pid of the created process upon return.
- * \param file Path of the executable to execute.
- * \param args The argument array for the command.
- *
- * \return Standard.
- *
- * \sa fork(2), exec(3).
- */
+/* Spawn a new process using execvp(). */
void dss_exec(pid_t *pid, const char *file, char *const *const args)
{
if ((*pid = fork()) < 0) {
_exit(EXIT_FAILURE);
}
-/**
- * Exec the command given as a command line.
- *
- * \param pid Will hold the pid of the created process upon return.
- * \param cmdline Holds the command and its arguments, separated by spaces.
- *
- * This function uses fork/exec to create a new process.
- *
- * \return Standard.
+/*
+ * Execute the space-separated command line. On return, the pid pointer is
+ * initialized to pid of the newly created process.
*/
void dss_exec_cmdline_pid(pid_t *pid, const char *cmdline)
{
/* SPDX-License-Identifier: GPL-2.0 */
+
void dss_exec(pid_t *pid, const char *file, char *const *const args);
void dss_exec_cmdline_pid(pid_t *pid, const char *cmdline);
#include "str.h"
#include "file.h"
-/**
+/*
* Call a function for each subdirectory of the current working directory.
*
- * \param dirname The directory to traverse.
- * \param func The function to call for each subdirectory.
- * \param private_data Pointer to an arbitrary data structure.
+ * For each top-level directory under dirname, the supplied callback function
+ * is called, passing the full path to the subdirectory and the private_data
+ * pointer.
*
- * For each top-level directory under \a dirname, the supplied function \a func is
- * called. The full path of the subdirectory and the \a private_data pointer
- * are passed to \a func.
- *
- * \return This function returns immediately if \a func returned a negative
- * value. In this case \a func must set error_txt and this negative value is
- * returned to the caller. Otherwise the function returns when all
- * subdirectories have been passed to \a func.
+ * If the callback returns a negative error value, the loop is terminated and
+ * that negative value is returned to the caller. If the iteration completes
+ * with no errors, the function returns non-negative.
*/
-
int for_each_subdir(int (*func)(const char *, void *), void *private_data)
{
struct dirent *entry;
return ret;
}
-/**
- * Set a file descriptor to non-blocking mode.
- *
- * \param fd The file descriptor.
- *
- * \return Standard.
- */
+/* Set a file descriptor to non-blocking mode. */
__must_check int mark_fd_nonblocking(int fd)
{
int flags = fcntl(fd, F_GETFL);
return 1;
}
-/**
- * dss' wrapper for select(2).
- *
- * It calls select(2) (with no exceptfds) and starts over if select() was
- * interrupted by a signal.
- *
- * \param n The highest-numbered descriptor in any of the two sets, plus 1.
- * \param readfds fds that should be checked for readability.
- * \param writefds fds that should be checked for writablility.
- * \param timeout_tv upper bound on the amount of time elapsed before select()
- * returns.
- *
- * \return The return value of the underlying select() call on success, the
- * negative system error code on errors.
- *
- * All arguments are passed verbatim to select(2).
- * \sa select(2) select_tut(2).
+/*
+ * Call select(2) with no exceptfds and start over if the call was interrupted
+ * by a signal. All arguments are passed verbatim to select(2). Returns the
+ * return value of the underlying select call on success, a negative error code
+ * on error.
*/
int dss_select(int n, fd_set *readfds, fd_set *writefds,
struct timeval *timeout_tv)
/* SPDX-License-Identifier: GPL-2.0 */
+
int for_each_subdir(int (*func)(const char *, void *), void *private_data);
__must_check int mark_fd_nonblocking(int fd);
static inline int dss_rename(const char *old_path, const char *new_path)
/* SPDX-License-Identifier: GPL-2.0 */
+
#define HAVE_GNUC(maj, min) \
defined(__GNUC__) && \
(__GNUC__ > maj || (__GNUC__ == maj && __GNUC_MINOR__ >= min))
# define __malloc
#endif
-/*
- * p is the number of the "format string" parameter, and q is
- * the number of the first variadic parameter
+/*
+ * p is the number of the "format string" parameter, and q is
+ * the number of the first variadic parameter.
*/
#if HAVE_GNUC(2,3)
# define __printf(p,q) __attribute__ ((format (printf, p, q)))
/* SPDX-License-Identifier: GPL-2.0 */
+
uint32_t super_fast_hash(const uint8_t *data, uint32_t len, uint32_t hash);
int lock_dss(uint32_t key);
int get_dss_pid(uint32_t key, pid_t *pid);
/* SPDX-License-Identifier: GPL-2.0 */
-/** debug loglevel, gets really noisy */
+/* debug loglevel, gets really noisy */
#define DEBUG 1
-/** still noisy, but won't fill your disk */
+/* still noisy, but won't fill your disk */
#define INFO 2
-/** normal, but significant event */
+/* normal, but significant event */
#define NOTICE 3
-/** unexpected event that can be handled */
+/* unexpected event that can be handled */
#define WARNING 4
-/** unhandled error condition */
+/* unhandled error condition */
#define ERROR 5
-/** system might be unreliable */
+/* system might be unreliable */
#define CRIT 6
-/** last message before exit */
+/* last message before exit */
#define EMERG 7
-/** Not all compilers support __func__ or an equivalent. */
+/* Not all compilers support __func__ or an equivalent. */
#if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(__GNUC__)
# if defined(_MSC_VER) && _MSC_VER >= 1300
# define __func__ __FUNCTION__
static int signal_pipe[2];
-/**
+/*
* Initialize the signal subsystem.
*
* This function creates a pipe, the signal pipe, to deliver pending signals to
- * the application (Bernstein's trick). It should be called during the
- * application's startup part, followed by subsequent calls to
- * install_sighandler() for each signal that should be caught.
+ * the application (Bernstein's trick). It is called at startup, followed by
+ * subsequent calls to install_sighandler() for each signal that should be
+ * caught.
*
* signal_init() installs a generic signal handler which is used for all
* signals simultaneously. When a signal arrives, this generic signal handler
* writes the corresponding signal number to the signal pipe so that the
- * application can test for pending signals simply by checking the signal pipe
- * for reading, e.g. by using the select(2) system call.
+ * application can test for pending signals by checking the signal pipe for
+ * reading, e.g. by using the select(2) system call.
*
- * \return This function either succeeds or calls exit(2) to terminate
- * the current process. On success, the file descriptor of the signal pipe is
- * returned.
+ * This function either succeeds or calls exit(2) to terminate the current
+ * process. On success, the file descriptor of the signal pipe is returned.
*/
int signal_init(void)
{
exit(EXIT_FAILURE);
}
-/**
- * Reap one child.
+/*
+ * If there is a child to reap, return its pid and exit status via the pointer
+ * arguments.
*
- * \param pid In case a child died, its pid is returned here.
- *
- * Call waitpid() and print a log message containing the pid and the cause of
- * the child's death.
- *
- * \return A (negative) error code on errors, zero, if no child died, one
- * otherwise. If and only if the function returns one, the content of \a pid is
- * meaningful.
- *
- * \sa waitpid(2)
+ * Returns a negative error code on errors, zero, if there was no child to
+ * reap, one if a child was reaped successfully. Only if the function returns
+ * one, the contents of pid and status are meaningful.
*/
int reap_child(pid_t *pid, int *status)
{
return 1;
}
-/**
- * Wrapper around signal(2)
- *
- * \param sig The number of the signal to catch.
- *
- * This installs the generic signal handler for the given signal.
- *
- * \return This function returns 1 on success and \p -E_SIGNAL_SIG_ERR on errors.
- * \sa signal(2)
+/*
+ * Install the generic signal handler for the given signal, return 1 on success
+ * and -E_SIGNAL_SIG_ERR on errors.
*/
int install_sighandler(int sig)
{
return -E_SIGNAL_SIG_ERR;
}
-/**
- * Return number of next pending signal.
- *
+/*
* This should be called if the fd for the signal pipe is ready for reading.
- *
- * \return On success, the number of the received signal is returned.
- * If the read was interrupted by another signal the function returns 0.
- * Otherwise a negative error code is returned.
+ * It returns the number of the next pending signal. If the read was
+ * interrupted by another signal, the function returns 0. On errors, a negative
+ * error code is returned.
*/
int next_signal(void)
{
return -ERRNO_TO_DSS_ERROR(err);
}
-/**
- * Close the signal pipe.
- */
+/* Close the signal pipe. */
void signal_shutdown(void)
{
close(signal_pipe[1]);
#include "tv.h"
#include "file.h"
-/**
+/*
* Wrapper for isdigit.
* NetBSD needs this.
*
*/
#define dss_isdigit(c) isdigit((int)(unsigned char)(c))
-
-/**
- * Return the desired number of snapshots of an interval.
- */
unsigned desired_number_of_snapshots(int interval_num, int num_intervals)
{
unsigned n;
struct snapshot_list *sl;
};
-/** Compute the minimum of \a a and \a b. */
#define DSS_MIN(a,b) ((a) < (b) ? (a) : (b))
static int add_snapshot(const char *dirname, void *private)
/* SPDX-License-Identifier: GPL-2.0 */
-/** The possible states for snapshot creation/removal. */
+/* The possible states for snapshot creation/removal. */
#define HOOK_STATUS_ARRAY \
HSA_ITEM(HS_READY, "ready for action"), \
HSA_ITEM(HS_PRE_RUNNING, "pre-hook running"), \
#define HSA_ITEM(x, y) y
-/**
+/*
* The status of a snapshot.
*
* The snapshot directories come in four different flavours, depending
* incomplete, being deleted: 1204565370-incomplete.being_deleted.
*/
enum snapshot_status_flags {
- /** The rsync process terminated successfully. */
+ /* The rsync process terminated successfully. */
SS_COMPLETE = 1,
- /** The rm process is running to remove this snapshot. */
+ /* The rm process is running to remove this snapshot. */
SS_BEING_DELETED = 2
};
-/** Describes one snapshot. */
+/* Describes one snapshot. */
struct snapshot {
- /** The name of the directory, relative to the destination dir. */
+ /* The name of the directory, relative to the destination dir. */
char *name;
- /** Seconds after the epoch when this snapshot was created. */
+ /* Seconds after the epoch when this snapshot was created. */
int64_t creation_time;
- /**
+ /*
* Seconds after the epoch when creation of this snapshot completed.
* Only meaningful if the SS_COMPLETE bit is set.
*/
int64_t completion_time;
- /** See \ref snapshot_status_flags. */
+ /* See snapshot_status_flags. */
enum snapshot_status_flags flags;
- /** The interval this snapshot belongs to. */
+ /* The interval this snapshot belongs to. */
unsigned interval;
};
unsigned num_snapshots;
unsigned array_size;
struct snapshot **snapshots;
- /**
+ /*
* Array of size num_intervals + 1
*
- * It contains the number of snapshots in each interval. interval_count[num_intervals]
- * is the number of snapshots which belong to any interval greater than num_intervals.
+ * It contains the number of snapshots in each interval.
+ * interval_count[num_intervals] is the number of snapshots which
+ * belong to any interval greater than num_intervals.
*/
unsigned *interval_count;
};
-/** Iterate over all snapshots in a snapshot list. */
+/* Iterate over all snapshots in a snapshot list. */
#define FOR_EACH_SNAPSHOT(s, i, sl) \
for ((i) = 0; (i) < (sl)->num_snapshots && ((s) = (sl)->snapshots[(i)]); (i)++)
-/** Iterate backwards over all snapshots in a snapshot list. */
+/* Iterate backwards over all snapshots in a snapshot list. */
#define FOR_EACH_SNAPSHOT_REVERSE(s, i, sl) \
for ((i) = (sl)->num_snapshots; (i) > 0 && ((s) = (sl)->snapshots[(i - 1)]); (i)--)
__malloc char *name_of_newest_complete_snapshot(struct snapshot_list *sl);
int num_complete_snapshots(struct snapshot_list *sl);
-/**
+/*
* Get the newest snapshot in a snapshot list.
*/
static inline struct snapshot *get_newest_snapshot(struct snapshot_list *sl)
/* SPDX-License-Identifier: GPL-2.0 */
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "err.h"
#include "str.h"
-/**
- * dss' version of realloc().
- *
- * \param p Pointer to the memory block, may be \p NULL.
- * \param size The desired new size.
- *
- * A wrapper for realloc(3). It calls \p exit(\p EXIT_FAILURE) on errors,
- * i.e. there is no need to check the return value in the caller.
- *
- * \return A pointer to the newly allocated memory, which is suitably aligned
- * for any kind of variable and may be different from \a p.
- *
- * \sa realloc(3).
+/*
+ * A wrapper for realloc(3) which exits on errors so that there is no need to
+ * check the return value in the caller.
*/
__must_check __malloc void *dss_realloc(void *p, size_t size)
{
/*
* No need to check for NULL pointers: If p is NULL, the call
- * to realloc is equivalent to malloc(size)
+ * to realloc is equivalent to malloc(size).
*/
assert(size);
if (!(p = realloc(p, size))) {
return p;
}
-/**
- * dss' version of malloc().
- *
- * \param size The desired new size.
- *
- * A wrapper for malloc(3) which exits on errors.
- *
- * \return A pointer to the allocated memory, which is suitably aligned for any
- * kind of variable.
- *
- * \sa malloc(3).
- */
+/* A wrapper for malloc(3) which exits on errors. */
__must_check __malloc void *dss_malloc(size_t size)
{
void *p;
return p;
}
-/**
- * dss' version of calloc().
- *
- * \param size The desired new size.
- *
- * A wrapper for calloc(3) which exits on errors.
- *
- * \return A pointer to the allocated and zeroed-out memory, which is suitably
- * aligned for any kind of variable.
- *
- * \sa calloc(3)
- */
+/* Allocate zeroed-out memory. */
__must_check __malloc void *dss_calloc(size_t size)
{
void *ret = dss_malloc(size);
return ret;
}
-/**
- * dss' version of strdup().
- *
- * \param s The string to be duplicated.
- *
- * A wrapper for strdup(3). It calls \p exit(EXIT_FAILURE) on errors, i.e.
- * there is no need to check the return value in the caller.
- *
- * \return A pointer to the duplicated string. If \p s was the NULL pointer,
- * an pointer to an empty string is returned.
- *
- * \sa strdup(3)
+/*
+ * A wrapper for strdup(3) which exits on errors. If NULL is passed as the
+ * string to duplicate, a pointer to an empty string is returned.
*/
-
__must_check __malloc char *dss_strdup(const char *s)
{
char *ret;
exit(EXIT_FAILURE);
}
-/**
- * Allocate a sufficiently large string and print into it.
- *
- * \param fmt A usual format string.
- *
- * Produce output according to \p fmt. No artificial bound on the length of the
- * resulting string is imposed.
- *
- * \return This function either returns a pointer to a string that must be
- * freed by the caller or aborts without returning.
- *
- * \sa printf(3).
+/*
+ * Allocate a sufficiently large string and print into it. No artificial bound
+ * on the length of the resulting string is imposed. Either returns a pointer
+ * to a string which must be freed by the caller, or aborts without returning.
*/
__must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
{
exit(EXIT_FAILURE);
}
-/**
- * Convert a string to a 64-bit signed integer value.
- *
- * \param str The string to be converted.
- * \param value Result pointer.
- *
- * \return Standard.
- *
- * \sa strtol(3), atoi(3).
- */
+/* Convert a string to a 64-bit signed integer value. */
int dss_atoi64(const char *str, int64_t *value)
{
char *endptr;
return dss_strdup(logname);
}
-/**
- * Split string and return pointers to its parts.
- *
- * \param args The string to be split.
- * \param argv_ptr Pointer to the list of substrings.
+/*
+ * Split a string and return pointers to its parts.
*
* This function modifies the string given by the first argument by replacing
* all occurrences of space and '\t' characters by '\0'. A NULL-terminated
* array of pointers to char * is allocated dynamically, and these pointers are
- * initialized to point to the broken-up substrings. A pointer to this array
+ * initialized to point to the broken-up substrings. A pointer to this array
* is returned via the last argument.
*
- * \return The number of substrings found.
+ * Returns the number of substrings found.
*/
unsigned split_args(char *args, char *** const argv_ptr)
{
__must_check __malloc char *dss_logname(void);
unsigned split_args(char *args, char *** const argv_ptr);
-
-/** \cond LLONG_MAX and LLONG_LIN might not be defined. */
#ifndef LLONG_MAX
#define LLONG_MAX (1 << (sizeof(long) - 1))
#endif
#ifndef LLONG_MIN
#define LLONG_MIN (-LLONG_MAX - 1LL)
#endif
-/** \endcond */
-
/* SPDX-License-Identifier: GPL-2.0 */
+
#include <sys/time.h>
#include <time.h>
#include <inttypes.h>
#include "log.h"
#include "time.h"
-/**
- * Compute the difference of two time values.
- *
- * \param b Minuend.
- * \param a Subtrahend.
- * \param diff Result pointer.
- *
- * If \a diff is not \p NULL, it contains the absolute value |\a b - \a a| on
- * return.
- *
- * \return If \a b < \a a, this function returns -1, otherwise it returns 1.
+/*
+ * Compute the difference of two time values. If b < a the function returns
+ * -1, otherwise it returns 1. If diff is not NULL, |b - a| is returned through
+ * this pointer.
*/
int tv_diff(const struct timeval *b, const struct timeval *a, struct timeval *diff)
{