summaryrefslogtreecommitdiff
path: root/debian/migrate/dma-migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/migrate/dma-migrate.c')
-rw-r--r--debian/migrate/dma-migrate.c413
1 files changed, 0 insertions, 413 deletions
diff --git a/debian/migrate/dma-migrate.c b/debian/migrate/dma-migrate.c
deleted file mode 100644
index 56bfa2adbf87..000000000000
--- a/debian/migrate/dma-migrate.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*-
- * Copyright (c) 2010 Peter Pentchev
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include <dirent.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <regex.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#ifndef __printflike
-#ifdef __GNUC__
-#define __printflike(fmtarg, firstvararg) \
- __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
-#else
-#define __printflike(fmtarg, firstvararg)
-#endif
-#endif
-
-#define DEFAULT_SPOOLDIR "/var/spool/dma"
-
-static int verbose = 0;
-static char copybuf[BUFSIZ];
-
-static int dma_migrate(int, const char *);
-
-static int open_locked(const char *, int, ...);
-static void cleanup_file(int, char *);
-
-static void usage(int);
-static void version(void);
-static void debug(const char *, ...) __printflike(1, 2);
-
-int
-main(int argc, char **argv)
-{
- const char *spooldir;
- int hflag, Vflag, errs, fd, res;
- int ch;
- DIR *d;
- struct dirent *e;
- struct stat sb;
-
- srandom((unsigned long)((time(NULL) ^ getpid()) + ((uintptr_t)argv)));
-
- hflag = Vflag = 0;
- spooldir = DEFAULT_SPOOLDIR;
- while (ch = getopt(argc, argv, "d:hVv"), ch != -1)
- switch (ch) {
- case 'd':
- spooldir = optarg;
- break;
-
- case 'h':
- hflag = 1;
- break;
-
- case 'V':
- Vflag = 1;
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- case '?':
- default:
- usage(1);
- /* NOTREACHED */
- }
- if (Vflag)
- version();
- if (hflag)
- usage(0);
- if (hflag || Vflag)
- exit(0);
-
- argc -= optind;
- argv += optind;
-
- /* Let's roll! */
- if (chdir(spooldir) == -1)
- err(1, "Could not change into spool directory %s", spooldir);
- if (d = opendir("."), d == NULL)
- err(1, "Could not read spool directory %s", spooldir);
- errs = 0;
- while (e = readdir(d), e != NULL) {
- /* Do we care about this entry? */
- debug("Read a directory entry: %s\n", e->d_name);
- if (strncmp(e->d_name, "tmp_", 4) == 0 ||
- e->d_name[0] == 'M' || e->d_name[0] == 'Q' ||
- (e->d_type != DT_REG && e->d_type != DT_UNKNOWN))
- continue;
- if (e->d_type == DT_UNKNOWN)
- if (stat(e->d_name, &sb) == -1 || !S_ISREG(sb.st_mode))
- continue;
- debug("- want to process it\n");
-
- /* Try to lock it - skip it if dma is delivering the message */
- if (fd = open_locked(e->d_name, O_RDONLY|O_NDELAY), fd == -1) {
- debug("- seems to be locked, skipping\n");
- continue;
- }
-
- /* Okay, convert it to the M/Q schema */
- res = dma_migrate(fd, e->d_name);
- close(fd);
- if (res == -1)
- errs++;
- }
- if (errs)
- debug("Finished, %d conversion errors\n", errs);
- else
- debug("Everything seems to be all right\n");
- return (errs && 1);
-}
-
-static int
-dma_migrate(int fd, const char *fname)
-{
- const char *id;
- char *mname, *qname, *tempname, *sender, *recp, *line, *recpline;
- int mfd, qfd, tempfd;
- struct stat sb;
- FILE *fp, *qfp, *mfp;
- size_t sz, len;
- static regex_t *qidreg = NULL;
-
- mfd = tempfd = qfd = -1;
- mname = qname = sender = recp = line = NULL;
- fp = qfp = NULL;
-
- if (fstat(fd, &sb) == -1) {
- warn("Could not fstat(%s)", fname);
- return (-1);
- }
- /*
- * Let's just blithely assume that the queue ID *is* the filename,
- * since that's the way dma did things so far.
- * Well, okay, let's check it.
- */
- if (qidreg == NULL) {
- regex_t *nreg;
-
- if ((nreg = malloc(sizeof(*qidreg))) == NULL) {
- warn("Could not allocate memory for a regex");
- return (-1);
- }
- if (regcomp(nreg, "^[a-fA-F0-9]\\+\\.[a-fA-F0-9]\\+$", 0)
- != 0) {
- warnx("Could not compile a dma queue ID regex");
- free(nreg);
- return (-1);
- }
- qidreg = nreg;
- }
- if (regexec(qidreg, fname, 0, NULL, 0) != 0) {
- warnx("The name '%s' is not a valid dma queue ID", fname);
- return (-1);
- }
- id = fname;
- debug(" - queue ID %s\n", id);
- if (asprintf(&mname, "M%s", id) == -1 ||
- asprintf(&tempname, "tmp_%s", id) == -1 ||
- asprintf(&qname, "Q%s", id) == -1 ||
- mname == NULL || tempname == NULL || qname == NULL)
- goto fail;
-
- /* Create the message placeholder early to avoid races */
- mfd = open_locked(mname, O_CREAT | O_EXCL | O_RDWR, 0600);
- if (mfd == -1) {
- warn("Could not create temporary file %s", mname);
- goto fail;
- }
- if (stat(qname, &sb) != -1 || errno != ENOENT ||
- stat(tempname, &sb) != -1 || errno != ENOENT) {
- warnx("Some of the queue files for %s already exist", fname);
- goto fail;
- }
- debug(" - mfd %d names %s, %s, %s\n", mfd, mname, tempname, qname);
-
- fp = fdopen(fd, "r");
- if (fp == NULL) {
- warn("Could not reopen the descriptor for %s", fname);
- goto fail;
- }
-
- /* Parse the header of the old-format message file */
- /* ...sender... */
- if (getline(&sender, &sz, fp) == -1) {
- warn("Could not read the initial line from %s", fname);
- goto fail;
- }
- sz = strlen(sender);
- while (sz > 0 && (sender[sz - 1] == '\n' || sender[sz - 1] == '\r'))
- sender[--sz] = '\0';
- if (sz == 0) {
- warnx("Empty sender line in %s", fname);
- goto fail;
- }
- debug(" - sender %s\n", sender);
- /* ...recipient(s)... */
- len = strlen(fname);
- recpline = NULL;
- while (1) {
- if (getline(&line, &sz, fp) == -1) {
- warn("Could not read a recipient line from %s", fname);
- goto fail;
- }
- sz = strlen(line);
- while (sz > 0 &&
- (line[sz - 1] == '\n' || line[sz - 1] == '\r'))
- line[--sz] = '\0';
- if (sz == 0) {
- free(line);
- line = NULL;
- break;
- }
- if (recp == NULL &&
- strncmp(line, fname, len) == 0 && line[len] == ' ') {
- recp = line + len + 1;
- recpline = line;
- } else {
- free(line);
- }
- line = NULL;
- }
- if (recp == NULL) {
- warnx("Could not find its own recipient line in %s", fname);
- goto fail;
- }
- /* ..phew, finished with the header. */
-
- tempfd = open_locked(tempname, O_CREAT | O_EXCL | O_RDWR, 0600);
- if (tempfd == -1) {
- warn("Could not create a queue file for %s", fname);
- goto fail;
- }
- qfp = fdopen(tempfd, "w");
- if (qfp == NULL) {
- warn("Could not fdopen(%s) for %s", tempname, fname);
- goto fail;
- }
- mfp = fdopen(mfd, "w");
- if (mfp == NULL) {
- warn("Could not fdopen(%s) for %s", mname, fname);
- goto fail;
- }
- fprintf(qfp, "ID: %s\nSender: %s\nRecipient: %s\n", id, sender, recp);
- fflush(qfp);
- fsync(tempfd);
-
- /* Copy the message file over to mname */
- while ((sz = fread(copybuf, 1, sizeof(copybuf), fp)) > 0)
- if (fwrite(copybuf, 1, sz, mfp) != sz) {
- warn("Could not copy the message from %s to %s",
- fname, mname);
- goto fail;
- }
- if (ferror(fp)) {
- warn("Could not read the full message from %s", fname);
- goto fail;
- }
- fflush(mfp);
- fsync(mfd);
-
- if (rename(tempname, qname) == -1) {
- warn("Could not rename the queue file for %s", fname);
- goto fail;
- }
- qfd = tempfd;
- tempfd = -1;
- if (unlink(fname) == -1) {
- warn("Could not remove the old converted file %s", fname);
- goto fail;
- }
-
- fclose(fp);
- fclose(qfp);
- free(sender);
- free(line);
- free(recpline);
- free(mname);
- free(qname);
- free(tempname);
- return (0);
-
-fail:
- if (fp != NULL)
- fclose(fp);
- if (qfp != NULL)
- fclose(qfp);
- if (sender != NULL)
- free(sender);
- if (line != NULL)
- free(line);
- if (recpline != NULL)
- free(recpline);
- cleanup_file(mfd, mname);
- cleanup_file(qfd, qname);
- cleanup_file(tempfd, tempname);
- return (-1);
-}
-
-static void
-cleanup_file(int fd, char *fname)
-{
- if (fd != -1) {
- close(fd);
- unlink(fname);
- }
- if (fname != NULL)
- free(fname);
-}
-
-static void
-usage(int ferr)
-{
- const char *s =
- "Usage:\tdma-migrate [-hVv] [-d spooldir]\n"
- "\t-d\tspecify the spool directory (" DEFAULT_SPOOLDIR ")\n"
- "\t-h\tdisplay program usage information and exit\n"
- "\t-V\tdisplay program version information and exit\n"
- "\t-v\tverbose operation - display diagnostic messages";
-
- if (ferr)
- errx(1, "%s", s);
- puts(s);
-}
-
-static void
-version(void)
-{
- printf("dma-migrate 0.01 (dma 0.0.2010.06.17)\n");
-}
-
-static void
-debug(const char *fmt, ...)
-{
- va_list v;
-
- if (verbose < 1)
- return;
- va_start(v, fmt);
- vfprintf(stderr, fmt, v);
- va_end(v);
-}
-
-static int
-open_locked(const char *fname, int flags, ...)
-{
- int mode = 0;
-#ifndef O_EXLOCK
- int fd, save_errno;
-#endif
-
- if (flags & O_CREAT) {
- va_list ap;
- va_start(ap, flags);
- mode = va_arg(ap, int);
- va_end(ap);
- }
-
-#ifndef O_EXLOCK
- fd = open(fname, flags, mode);
- if (fd < 0)
- return(fd);
- if (flock(fd, LOCK_EX|((flags & O_NONBLOCK)? LOCK_NB: 0)) < 0) {
- save_errno = errno;
- close(fd);
- errno = save_errno;
- return(-1);
- }
- return(fd);
-#else
- return(open(fname, flags|O_EXLOCK, mode));
-#endif
-}