/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "fdm.h"
struct cleanent {
char *path;
TAILQ_ENTRY(cleanent) entry;
};
TAILQ_HEAD(, cleanent) cleanlist;
void
cleanup_check(void)
{
struct cleanent *cent;
if (!TAILQ_EMPTY(&cleanlist)) {
TAILQ_FOREACH(cent, &cleanlist, entry)
log_debug("cleanup: %s", cent->path);
fatalx("list not empty");
}
}
void
cleanup_purge(void)
{
struct cleanent *cent;
int saved_errno;
/*
* This must be signal safe.
*/
saved_errno = errno;
TAILQ_FOREACH(cent, &cleanlist, entry) {
if (unlink(cent->path) != 0) {
write(STDERR_FILENO, "unlink failed\n", 14);
_exit(1);
}
}
errno = saved_errno;
}
void
cleanup_flush(void)
{
sigset_t set, oset;
struct cleanent *cent;
sigfillset(&set);
if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
fatal("sigprocmask failed");
while (!TAILQ_EMPTY(&cleanlist)) {
cent = TAILQ_FIRST(&cleanlist);
TAILQ_REMOVE(&cleanlist, cent, entry);
xfree(cent->path);
xfree(cent);
}
if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
fatal("sigprocmask failed");
}
void
cleanup_register(const char *path)
{
sigset_t set, oset;
struct cleanent *cent;
#if 0
log_debug("cleanup_register: %s by %ld", path, (long) getpid());
#endif
if (path == NULL || *path == '\0')
fatalx("empty path");
cent = xmalloc(sizeof *cent);
cent->path = xstrdup(path);
sigfillset(&set);
if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
fatal("sigprocmask failed");
TAILQ_INSERT_HEAD(&cleanlist, cent, entry);
if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
fatal("sigprocmask failed");
}
void
cleanup_deregister(const char *path)
{
sigset_t set, oset;
struct cleanent *cent;
#if 0
log_debug("cleanup_deregister: %s by %ld", path, (long) getpid());
#endif
if (path == NULL || *path == '\0')
fatalx("empty path");
sigfillset(&set);
if (sigprocmask(SIG_BLOCK, &set, &oset) < 0)
fatal("sigprocmask failed");
TAILQ_FOREACH(cent, &cleanlist, entry) {
if (strcmp(cent->path, path) == 0) {
TAILQ_REMOVE(&cleanlist, cent, entry);
xfree(cent->path);
xfree(cent);
goto out;
}
}
fatalx("entry not found");
out:
if (sigprocmask(SIG_SETMASK, &oset, NULL) < 0)
fatal("sigprocmask failed");
}