aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gconf/gconf-gram.y19
-rw-r--r--src/Makefile.am5
-rw-r--r--src/config.c93
-rw-r--r--src/directive.c2
-rw-r--r--src/diskio.c43
-rw-r--r--src/mail.c11
-rw-r--r--src/null.c58
-rw-r--r--src/process.c11
-rw-r--r--src/timer.c255
-rw-r--r--src/triplet.c26
-rw-r--r--src/vtab.c80
-rw-r--r--src/wydawca.c24
-rw-r--r--src/wydawca.h140
-rw-r--r--tests/upload-dry.at2
14 files changed, 681 insertions, 88 deletions
diff --git a/gconf/gconf-gram.y b/gconf/gconf-gram.y
index ed685d0..a1d9f2a 100644
--- a/gconf/gconf-gram.y
+++ b/gconf/gconf-gram.y
@@ -377,17 +377,26 @@ stmt_begin (struct gconf_keyword *kwp, gconf_value_t tag)
static void
stmt_end (struct gconf_keyword *kwp)
{
+ gconf_callback_fn callback = NULL;
+ void *dataptr = NULL;
+
if (cursect && cursect->callback)
- cursect->callback (gconf_callback_section_end,
- &gconf_current_locus, /* FIXME */
- kwp ? target_ptr(kwp) : NULL,
- NULL,
- &cursect->callback_data);
+ {
+ callback = cursect->callback;
+ dataptr = &cursect->callback_data;
+ }
if (gl_list_size (sections) == 0)
abort ();
cursect = (struct gconf_keyword *) gl_list_get_at (sections, 0);
gl_list_remove_at (sections, 0);
+ if (callback)
+ callback (gconf_callback_section_end,
+ &gconf_current_locus, /* FIXME */
+ kwp ? target_ptr(kwp) : NULL,
+ NULL,
+ dataptr);
+
}
static struct gconf_keyword *
diff --git a/src/Makefile.am b/src/Makefile.am
index b5e5040..110bd07 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,7 +35,10 @@ wydawca_SOURCES=\
wydawca.c\
wydawca.h\
mail.h\
- mail.c
+ mail.c\
+ vtab.c\
+ null.c\
+ timer.c
BUILT_SOURCES=cmdline.h
EXTRA_DIST=cmdline.opt getopt.m4 pp-setup
diff --git a/src/config.c b/src/config.c
index c22074f..b8c31f7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -268,11 +268,6 @@ cb_mailer (enum gconf_callback_command cmd,
gconf_error (locus, 0, _("Unexpected block statement"));
return 1;
}
- if (!value || value->type != GCONF_TYPE_STRING)
- {
- gconf_error (locus, 0, _("expected scalar value"));
- return 1;
- }
rc = mu_mailer_create (&mailer, value->v.string);
if (rc)
gconf_error (locus, 0, _("cannot create mailer `%s': %s"),
@@ -1089,13 +1084,49 @@ cb_access_method (enum gconf_callback_command cmd,
return 0;
}
+static int
+cb_destination_url (enum gconf_callback_command cmd,
+ gconf_locus_t *locus,
+ void *varptr,
+ gconf_value_t *value,
+ void *cb_data)
+{
+ mu_url_t *purl = varptr, url;
+ int rc;
+
+ if (assert_string_arg (locus, cmd, value))
+ return 1;
+ if (cmd != gconf_callback_set_value)
+ {
+ gconf_error (locus, 0, _("Unexpected block statement"));
+ return 1;
+ }
+ rc = mu_url_create (&url, value->v.string);
+ if (rc)
+ {
+ gconf_error (locus, 0, _("cannot create URL `%s': %s"),
+ value->v.string, mu_strerror (rc));
+ return rc;
+ }
+ rc = mu_url_parse (url);
+ if (rc)
+ {
+ gconf_error (locus, 0, _("cannot parse URL `%s': %s"),
+ value->v.string, mu_strerror (rc));
+ mu_url_destroy (&url);
+ return rc;
+ }
+ *purl = url;
+ return 0;
+}
static struct gconf_keyword directory_kw[] = {
{ "source", N_("dir"), N_("Source directory"),
gconf_type_string, NULL, offsetof(struct directory_pair, source_dir) },
{ "destination", N_("dir"), N_("Destination directory"),
- gconf_type_string, NULL, offsetof(struct directory_pair, dest_dir) },
+ gconf_type_string, NULL, offsetof(struct directory_pair, dest_url),
+ cb_destination_url },
{ "file-sweep-time", N_("interval"), N_("Define file sweep time"),
gconf_type_string, NULL, offsetof(struct directory_pair, file_sweep_time),
cb_interval },
@@ -1121,7 +1152,8 @@ cb_directory (enum gconf_callback_command cmd,
{
struct directory_pair *dpair;
void **pdata = cb_data;
- int ec, i;
+ int rc, ec, i;
+ const char *ep = NULL;
switch (cmd)
{
@@ -1141,11 +1173,13 @@ cb_directory (enum gconf_callback_command cmd,
break;
case gconf_callback_section_end:
+ rc = 0;
dpair = *pdata;
if (!dpair->source_dir)
- gconf_error (locus, 0, _("source is not given"));
- else if (!dpair->dest_dir)
- gconf_error (locus, 0, _("destination is not given"));
+ {
+ gconf_error (locus, 0, _("source is not given"));
+ rc = 1;
+ }
else if (test_dir (dpair->source_dir, &ec))
{
if (ec)
@@ -1153,29 +1187,38 @@ cb_directory (enum gconf_callback_command cmd,
else
gconf_error (locus, 0, _("%s is not a directory"),
dpair->source_dir);
+ rc = 1;
}
- else if (test_dir (dpair->dest_dir, &ec))
+
+ if (!dpair->dest_url)
{
- if (ec)
- gconf_error (locus, ec, _("cannot access %s"), dpair->dest_dir);
- else
- gconf_error (locus, ec, _("%s is not a directory"),
- dpair->dest_dir);
+ gconf_error (locus, 0, _("destination is not given"));
+ rc = 1;
}
- else if (dpair->access_method[verify_method]->type != method_none
- && dpair->access_method[gpg_key_method]->type != method_none)
+ else if (url_to_vtab (dpair->dest_url, &dpair->vtab))
{
- int i;
-
- for (i = 0; i < access_method_count; i++)
- if (dpair->access_method[i]->type == method_external)
- gconf_error (locus, 0,
- _("Sorry, method type `external' is not yet supported"));
+ gconf_error (locus, 0, _("unsupported url: %s"),
+ mu_url_to_string (dpair->dest_url));
+ rc = 1;
}
+ else if (dpair->vtab.test_url
+ && dpair->vtab.test_url (dpair->dest_url, locus))
+ rc = 1;
+ for (i = 0; i < access_method_count; i++)
+ if (dpair->access_method[i]->type == method_external)
+ {
+ gconf_error (locus, 0,
+ _("Sorry, method type `external' is not yet supported"));
+ rc = 1;
+ }
+
+ if (rc)
+ return rc;
+
if (!dpair->notification)
dpair->notification = default_notification;
-
+ mu_url_sget_path (dpair->dest_url, &dpair->dest_dir);
register_directory_pair (dpair);
free (dpair);
*pdata = NULL;
diff --git a/src/directive.c b/src/directive.c
index d99f65b..b050ffb 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -308,6 +308,7 @@ process_directives (struct file_triplet *trp, struct directory_pair *dpair)
const char *key, *val;
char *relative_dir;
+ timer_start ("triplet");
UPDATE_STATS (STAT_COMPLETE_TRIPLETS);
for (n = directive_first (trp, &key, &val); n;
n = directive_next (trp, n, &key, &val))
@@ -400,6 +401,7 @@ process_directives (struct file_triplet *trp, struct directory_pair *dpair)
free (relative_dir);
UPDATE_STATS (STAT_TRIPLET_SUCCESS);
+ timer_stop ("triplet");
notify (dpair->notification, trp, ev_success);
return 0;
}
diff --git a/src/diskio.c b/src/diskio.c
index e30b215..0548972 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -26,7 +26,7 @@
/* Return true if ARG is NULL or is a sub-directory of DIR */
int
-sub_dir_p (char *arg, char *dir)
+sub_dir_p (const char *arg, const char *dir)
{
int dlen;
@@ -441,8 +441,8 @@ do_archive_file (const char *dst_file, const char *dst_dir, const char *file,
Do nothing if dry_run_mode is set. */
int
-move_file (struct file_triplet *trp, struct directory_pair *dpair,
- enum file_type file_id, const char *reldir)
+dir_move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir)
{
char *dst_file;
int rc = 0;
@@ -548,8 +548,8 @@ make_signame (const char *file_name)
Do nothing if dry_run_mode is set.
*/
int
-archive_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *reldir, const char *file_name)
+dir_archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name)
{
int rc;
char *signame;
@@ -568,9 +568,9 @@ archive_file (struct file_triplet *trp, struct directory_pair *dpair,
Do nothing if dry_run_mode is set. */
int
-symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *reldir,
- const char *wanted_src, const char *wanted_dst)
+dir_symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst)
{
int rc = 0;
struct saved_cwd cwd;
@@ -728,8 +728,8 @@ do_rmsymlink_file (const char *dst_file, int noentok)
Do nothing if dry_run_mode is set. */
int
-rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *reldir, const char *file_name)
+dir_rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name)
{
char *dst_file;
int rc = 0;
@@ -763,3 +763,26 @@ rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
return rc;
}
+int
+dir_test_url (mu_url_t url, gconf_locus_t *locus)
+{
+ int rc;
+ const char *dest_dir;
+
+ rc = mu_url_sget_path (url, &dest_dir);
+ if (rc)
+ {
+ gconf_error (locus, 0, _("cannot extract directory part from URL: %s"),
+ mu_strerror (rc));
+ return rc;
+ }
+ if (test_dir (dest_dir, &rc))
+ {
+ if (rc)
+ gconf_error (locus, rc, _("cannot access %s"), dest_dir);
+ else
+ gconf_error (locus, 0, _("%s is not a directory"), dest_dir);
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/mail.c b/src/mail.c
index 37bb493..5449fc8 100644
--- a/src/mail.c
+++ b/src/mail.c
@@ -202,10 +202,11 @@ resolve_message_template (const char *name)
void
mail_stats ()
{
- struct metadef exp[MAX_STAT + 2];
+ struct metadef *exp;
time_t t;
const char *tmpl;
char *text;
+ size_t tc;
if (!admin_stat_message || !stat_mask_p (mail_admin_mask) || !mailer)
return;
@@ -230,13 +231,13 @@ mail_stats ()
if (dry_run_mode)
return;
+ tc = timer_get_count () * 3;
+ exp = make_stat_expansion (tc + 1);
time (&t);
- memset (exp, 0, sizeof (exp));
exp[0].kw = "date";
exp[0].value = exp[0].storage = xstrdup (ctime (&t));
exp[0].value [strlen (exp[0].value) - 1] = 0;
-
- make_stat_expansion (exp + 1);
+ timer_fill_meta (exp + 1, tc);
tmpl = resolve_message_template (admin_stat_message);
if (!tmpl)
@@ -251,6 +252,8 @@ mail_stats ()
free (text);
meta_free (exp);
+ timer_free_meta (exp + 1, tc);
+ free (exp);
}
mu_address_t
diff --git a/src/null.c b/src/null.c
new file mode 100644
index 0000000..3c17361
--- /dev/null
+++ b/src/null.c
@@ -0,0 +1,58 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2009 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+int
+null_move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir)
+{
+ if (debug_level)
+ logmsg (LOG_DEBUG, "%s: installing file `%s/%s'",
+ dpair->url, reldir, trp->file[file_id].name);
+ return 0;
+}
+
+int
+null_archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *file_name, const char *reldir)
+{
+ if (debug_level)
+ logmsg (LOG_DEBUG, "%s: archiving `%s'", dpair->url, file_name);
+ return 0;
+}
+
+int
+null_symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst)
+{
+ if (debug_level)
+ logmsg (LOG_DEBUG, "%s: symlinking `%s' to `%s'",
+ dpair->url, wanted_src, wanted_dst);
+ return 0;
+}
+
+int
+null_rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name)
+{
+ if (debug_level)
+ logmsg (LOG_DEBUG, "%s: removing symlink `%s/%s'",
+ dpair->url, reldir, file_name);
+ return 0;
+}
+
diff --git a/src/process.c b/src/process.c
index 645d987..dd499bd 100644
--- a/src/process.c
+++ b/src/process.c
@@ -109,7 +109,8 @@ scan_directory_pair (struct directory_pair *dpair)
struct dirent *ent;
if (debug_level)
- logmsg (LOG_DEBUG, "%s -> %s", dpair->source_dir, dpair->dest_dir);
+ logmsg (LOG_DEBUG, "%s -> %s", dpair->source_dir,
+ mu_url_to_string (dpair->dest_url));
if (chdir (dpair->source_dir))
{
@@ -126,6 +127,8 @@ scan_directory_pair (struct directory_pair *dpair)
return;
}
+ timer_start ("directory");
+ timer_start (dpair->url);
while ((ent = readdir (dir)))
{
struct stat st;
@@ -179,6 +182,8 @@ scan_directory_pair (struct directory_pair *dpair)
}
enumerate_triplets (dpair);
}
+ timer_stop (dpair->url);
+ timer_stop ("directory");
}
static void
@@ -194,10 +199,14 @@ void
scan_directories ()
{
struct directory_list *dp;
+
+ timer_start ("wydawca");
+
for (dp = dlist; dp; dp = dp->next)
scan_directory_pair (&dp->pair);
for (dp = dlist; dp; dp = dp->next)
close_methods (&dp->pair);
+ timer_stop ("wydawca");
}
diff --git a/src/timer.c b/src/timer.c
new file mode 100644
index 0000000..7078f4f
--- /dev/null
+++ b/src/timer.c
@@ -0,0 +1,255 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2008, 2009 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <wydawca.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <string.h>
+#include <hash.h>
+#include <ctype.h>
+#include <xalloc.h>
+
+struct timer_slot
+{
+ char *name;
+ double real;
+ double self_user; /* user time in sec */
+ double self_system; /* system time in sec */
+ double children_user; /* user time in sec */
+ double children_system; /* system time in sec */
+ struct timeval real_mark;
+ struct rusage self_mark;
+ struct rusage children_mark;
+};
+
+static Hash_table *timer_table;
+static size_t _timer_count;
+
+static size_t
+hash_string_ci (const char *string, size_t n_buckets)
+{
+ size_t value = 0;
+ unsigned char ch;
+
+ for (; (ch = *string); string++)
+ value = (value * 31 + tolower (ch)) % n_buckets;
+ return value;
+}
+
+/* Calculate the hash of a string. */
+static size_t
+timer_hasher (void const *data, unsigned n_buckets)
+{
+ const struct timer_slot *t = data;
+ return hash_string_ci (t->name, n_buckets);
+}
+
+/* Compare two strings for equality. */
+static bool
+timer_compare (void const *data1, void const *data2)
+{
+ const struct timer_slot *t1 = data1;
+ const struct timer_slot *t2 = data2;
+ return strcasecmp (t1->name, t2->name) == 0;
+}
+
+/* Allocate a timer structure */
+static wydawca_timer_t
+timer_alloc (const char *name)
+{
+ wydawca_timer_t t = xmalloc (sizeof (*t) + strlen (name) + 1);
+ memset (t, 0, sizeof (*t));
+ t->name = (char *) (t + 1);
+ strcpy (t->name, name);
+ return t;
+}
+
+/* Lookup a timer by its name. If it does not exist, create it. */
+wydawca_timer_t
+timer_get (const char *name)
+{
+ wydawca_timer_t tp, ret;
+
+ tp = timer_alloc (name);
+
+ if (!((timer_table
+ || (timer_table = hash_initialize (0, 0,
+ timer_hasher,
+ timer_compare, 0)))
+ && (ret = hash_insert (timer_table, tp))))
+ xalloc_die ();
+
+ if (ret != tp)
+ free (tp);
+ else
+ _timer_count++;
+ return ret;
+}
+
+wydawca_timer_t
+timer_start (const char *name)
+{
+ wydawca_timer_t t = timer_get (name);
+
+ gettimeofday (&t->real_mark, NULL);
+ getrusage (RUSAGE_SELF, &t->self_mark);
+ getrusage (RUSAGE_CHILDREN, &t->children_mark);
+ return t;
+}
+
+#define DIFFTIME(now,then)\
+ (((now).tv_sec - (then).tv_sec) \
+ + ((double)((now).tv_usec - (then).tv_usec))/1000000)
+
+static void
+_timer_compute (wydawca_timer_t t)
+{
+ struct timeval real;
+ struct rusage rusage;
+
+ gettimeofday (&real, NULL);
+ t->real = DIFFTIME (real, t->real_mark);
+ getrusage (RUSAGE_SELF, &rusage);
+ t->self_user = DIFFTIME (rusage.ru_utime, t->self_mark.ru_utime);
+ t->self_system = DIFFTIME (rusage.ru_stime, t->self_mark.ru_stime);
+
+ getrusage (RUSAGE_CHILDREN, &rusage);
+ t->children_user = DIFFTIME (rusage.ru_utime, t->children_mark.ru_utime);
+ t->children_system = DIFFTIME (rusage.ru_stime, t->children_mark.ru_stime);
+}
+
+wydawca_timer_t
+timer_stop (const char *name)
+{
+ wydawca_timer_t t = timer_get (name);
+ _timer_compute (t);
+ return t;
+}
+
+wydawca_timer_t
+timer_reset (const char *name)
+{
+ wydawca_timer_t t = timer_get (name);
+ t->real = 0.0;
+ t->self_user = 0.0;
+ t->self_system = 0.0;
+ t->children_user = 0.0;
+ t->children_system = 0.0;
+ return t;
+}
+
+double
+timer_get_real (wydawca_timer_t t)
+{
+ return t->real;
+}
+
+double
+timer_get_user (wydawca_timer_t t)
+{
+ return t->self_user + t->children_user;
+}
+
+double
+timer_get_system (wydawca_timer_t t)
+{
+ return t->self_system + t->children_system;
+}
+
+char *
+timer_format_time (double t)
+{
+ char *str = NULL;
+ if (t < 600)
+ asprintf (&str, "%0.3f", t);
+ else
+ {
+ long int s, m, h, d;
+
+ s = (long int) t;
+ d = s / (3600 * 24);
+ s -= d * 3600 * 24;
+ h = s / 3600;
+ s -= h * 3600;
+ m = s / 60;
+ s -= m * 60;
+
+ if (d)
+ asprintf (&str, "%ld+%02ld:%02ld:%02ld", d, h, m, s);
+ else if (h)
+ asprintf (&str, "%02ld:%02ld:%02ld", h, m, s);
+ else
+ asprintf (&str, "%02ld:%02ld", m, s);
+ }
+ return str;
+}
+
+size_t
+timer_get_count ()
+{
+ return _timer_count;
+}
+
+struct timer_data
+{
+ struct metadef *def;
+ size_t num;
+};
+
+bool
+_fill_meta (void *data, void *proc_data)
+{
+ struct timer_slot *slot = data;
+ struct timer_data *tp = proc_data;
+#define CREATE_DEF(arg) \
+ if (tp->num) \
+ { \
+ asprintf (&tp->def->kw, "timer:%s:%s", slot->name, #arg); \
+ tp->def->storage = timer_format_time (__cat2__(timer_get_,arg) (slot)); \
+ tp->def->value = tp->def->storage; \
+ tp->def->expand = NULL; \
+ tp->def++; \
+ tp->num--; \
+ }
+
+ CREATE_DEF(system);
+ CREATE_DEF(real);
+ CREATE_DEF(user);
+
+ return tp->num > 0;
+}
+
+void
+timer_fill_meta (struct metadef *def, size_t num)
+{
+ struct timer_data td;
+ if (!timer_table)
+ return;
+ td.def = def;
+ td.num = num;
+ hash_do_for_each (timer_table, _fill_meta, &td);
+}
+
+void
+timer_free_meta (struct metadef *def, size_t num)
+{
+ while (num--)
+ {
+ free (def->kw);
+ def++;
+ }
+}
diff --git a/src/triplet.c b/src/triplet.c
index 03aa4cc..6ebc142 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -229,7 +229,8 @@ void
enumerate_triplets (struct directory_pair *dpair)
{
if (debug_level)
- logmsg (LOG_DEBUG, "Processing files for %s", dpair->dest_dir);
+ logmsg (LOG_DEBUG, "Processing files for %s (%s)",
+ dpair->url, mu_url_to_string (dpair->dest_url));
if (triplet_table)
{
hash_do_for_each (triplet_table, triplet_processor, dpair);
@@ -542,6 +543,26 @@ expand_user_email (struct metadef *def, void *data)
return def->value;
}
+#define DECL_EXPAND_TIMER(what) \
+static const char * \
+__cat2__(expand_timer_,what) (struct metadef *def, void *data) \
+{ \
+ wydawca_timer_t t = timer_stop ((char*)def->data); \
+ def->storage = timer_format_time (__cat2__(timer_get_,what) (t)); \
+ def->value = def->storage; \
+}
+
+DECL_EXPAND_TIMER(real)
+DECL_EXPAND_TIMER(user)
+DECL_EXPAND_TIMER(system)
+
+#define DECL_TIMER(name,t) \
+ { "timer:" #name ":" #t, NULL, __cat2__(expand_timer_,t), NULL, #name }
+#define DECL_FULL_TIMER(name) \
+ DECL_TIMER(name, real), \
+ DECL_TIMER(name, user), \
+ DECL_TIMER(name, system)
+
struct metadef triplet_meta[] = {
{ "project", NULL, expand_project_base, NULL },
{ "url", NULL, expand_url, NULL },
@@ -557,6 +578,9 @@ struct metadef triplet_meta[] = {
{ "user:name", NULL, expand_user_name, NULL },
{ "user:real-name", NULL, expand_user_real_name, NULL },
{ "user:email", NULL, expand_user_email, NULL },
+ DECL_FULL_TIMER(wydawca),
+ DECL_FULL_TIMER(triplet),
+ DECL_FULL_TIMER(directory),
{ NULL }
};
diff --git a/src/vtab.c b/src/vtab.c
new file mode 100644
index 0000000..66d8ecd
--- /dev/null
+++ b/src/vtab.c
@@ -0,0 +1,80 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2009 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+struct virt_tab_reg
+{
+ char *scheme;
+ struct virt_tab vtab;
+};
+
+static struct virt_tab_reg reg[] = {
+ { "file",
+ { dir_test_url, dir_move_file, dir_archive_file, dir_symlink_file,
+ dir_rmsymlink_file } },
+ { "null",
+ { NULL, null_move_file, null_archive_file, null_symlink_file,
+ null_rmsymlink_file } },
+ { NULL }
+};
+
+int
+url_to_vtab (mu_url_t url, struct virt_tab *vtab)
+{
+ const char *scheme;
+ int i;
+
+ if (mu_url_sget_scheme (url, &scheme))
+ return 1;
+ for (i = 0; reg[i].scheme; i++)
+ if (strcmp (reg[i].scheme, scheme) == 0)
+ {
+ *vtab = reg[i].vtab;
+ return 0;
+ }
+ return 1;
+}
+
+
+int
+move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir)
+{
+ return dpair->vtab.move_file (trp, dpair, file_id, reldir);
+}
+
+int
+archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name)
+{
+ return dpair->vtab.archive_file (trp, dpair, reldir, file_name);
+}
+
+int
+symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst)
+{
+ return dpair->vtab.symlink_file (trp, dpair, reldir, wanted_src, wanted_dst);
+}
+
+int
+rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name)
+{
+ return dpair->vtab.rmsymlink_file (trp, dpair, reldir, file_name);
+}
diff --git a/src/wydawca.c b/src/wydawca.c
index 1d953b9..5df2638 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -215,19 +215,23 @@ stat_expand (struct metadef *def, void *data)
return def->value;
}
-void
-make_stat_expansion (struct metadef *def)
+struct metadef *
+make_stat_expansion (size_t count)
{
int i;
- for (i = 0; i < MAX_STAT; i++)
+ struct metadef *def, *p;
+ def = xcalloc (MAX_STAT + count + 1, sizeof (def[0]));
+ p = def + count;
+ for (i = 0; i < MAX_STAT; i++, p++)
{
- def[i].kw = stat_kwname[i];
- def[i].value = NULL;
- def[i].storage = NULL;
- def[i].expand = stat_expand;
- def[i].data = (void*) i;
+ p->kw = stat_kwname[i];
+ p->value = NULL;
+ p->storage = NULL;
+ p->expand = stat_expand;
+ p->data = (void*) i;
}
- def[i].kw = NULL;
+ p->kw = NULL;
+ return def;
}
void
@@ -308,7 +312,7 @@ main (int argc, char **argv)
logmsg (LOG_NOTICE, "wydawca (%s) finished", PACKAGE_STRING);
logstats ();
-
+
mail_finish ();
exit (0);
diff --git a/src/wydawca.h b/src/wydawca.h
index d990a97..2e00f65 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -33,6 +33,11 @@
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
+
+#include <mailutils/types.h>
+#include <mailutils/url.h>
+#include <mailutils/errno.h>
+
#include "error.h"
#include "xalloc.h"
#include "progname.h"
@@ -60,6 +65,8 @@
#define SUF_DIR ".directive.asc"
#define SUF_DIR_LEN (sizeof (SUF_DIR) - 1)
+#define __cat2__(a,b) a ## b
+#define __cat3__(a,b,c) a ## b ## c
#define NITEMS(a) (sizeof(a)/sizeof((a)[0]))
enum access_method_id {
@@ -122,22 +129,6 @@ struct archive_descr
};
-
-/* A source/destination directory pair. This structure contains all the
- data necessary for releasing files from source to destination */
-struct directory_pair
-{
- char *url; /* Download URL */
- char *source_dir; /* Source directory */
- char *dest_dir; /* Destination directory */
- time_t file_sweep_time; /* Remove invalid/unprocessed files
- after this amount of time */
- struct access_method *access_method[access_method_count];
- struct archive_descr archive; /* Archivation data */
- struct notification *notification;
-};
-
-
/* Type of file in a triplet */
enum file_type
{
@@ -179,6 +170,48 @@ struct file_triplet
/* GID is filled in after the triplet is finalized and verified */
#define TRIPLET_GID(t) ((t)->gid)
+
+
+struct virt_tab
+{
+ int (*test_url) (mu_url_t url, gconf_locus_t *loc);
+ int (*move_file) (struct file_triplet *trp,
+ struct directory_pair *dpair,
+ enum file_type file_id,
+ const char *reldir);
+ int (*archive_file) (struct file_triplet *trp,
+ struct directory_pair *dpair,
+ const char *reldir,
+ const char *file_name);
+ int (*symlink_file) (struct file_triplet *trp,
+ struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src,
+ const char *wanted_dst);
+ int (*rmsymlink_file)(struct file_triplet *trp,
+ struct directory_pair *dpair,
+ const char *reldir,
+ const char *file_name);
+};
+
+/* A source/destination directory pair. This structure contains all the
+ data necessary for releasing files from source to destination */
+struct directory_pair
+{
+ char *url; /* Download URL */
+ char *source_dir; /* Source directory */
+ mu_url_t dest_url; /* Destination URL */
+ const char *dest_dir; /* Directory part of the above */
+ struct virt_tab vtab; /* Virtual method table */
+
+ time_t file_sweep_time; /* Remove invalid/unprocessed files
+ after this amount of time */
+ struct access_method *access_method[access_method_count];
+ struct archive_descr archive; /* Archivation data */
+ struct notification *notification;
+};
+
+
enum wydawca_stat
{
STAT_ERRORS,
@@ -280,7 +313,7 @@ extern char *admin_stat_message;
while (0)
int stat_mask_p (unsigned long mask);
-void make_stat_expansion (struct metadef *def);
+struct metadef *make_stat_expansion (size_t count);
/* Utility functions */
@@ -358,22 +391,69 @@ int process_directives (struct file_triplet *trp,
struct directory_pair *dpair);
-/* Actions */
-
-int move_file (struct file_triplet *trp, struct directory_pair *dpair,
- enum file_type file_id, const char *reldir);
-int archive_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *file_name, const char *reldir);
-int symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *reldir,
- const char *wanted_src, const char *wanted_dst);
-int rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
- const char *reldir, const char *file_name);
-
-
int parse_time_interval (const char *str, time_t *pint, const char **endp);
/* config.c */
void config_init (void);
void config_help (void);
+
+
+/* vtab.c */
+int url_to_vtab (mu_url_t url, struct virt_tab *vtab);
+
+int
+move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir);
+int
+archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name);
+int
+symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst);
+int
+rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name);
+
+
+/* diskio.c */
+
+int dir_test_url (mu_url_t url, gconf_locus_t *locus);
+int dir_move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir);
+int dir_archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *file_name, const char *reldir);
+int dir_symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst);
+int dir_rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir, const char *file_name);
+
+/* null.c */
+int null_move_file (struct file_triplet *trp, struct directory_pair *dpair,
+ enum file_type file_id, const char *reldir);
+int null_archive_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *file_name, const char *reldir);
+int null_symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
+ const char *reldir,
+ const char *wanted_src, const char *wanted_dst);