summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2012-12-22 22:54:27 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2012-12-22 22:54:27 (GMT)
commit0077bc419d34a0341f978fc0e2d5cba8d35d4b28 (patch) (side-by-side diff)
treef5cb831a306e99dce9a8c5af1b4be55cf7dbb658
parent67a64a6a7809c183516740696e15ab88f82d7ef0 (diff)
downloadwydawca-0077bc419d34a0341f978fc0e2d5cba8d35d4b28.tar.gz
wydawca-0077bc419d34a0341f978fc0e2d5cba8d35d4b28.tar.bz2
Fix memory leaks, provide config statements for disabling inotify.
* src/config.c: New statement "inotify" (global and spool-specific). * src/gpg.c (gpg_verify_signature): Free key when no longer needed. (verify_directive_signature): Fix memory leak. * src/job.c (job_queue_runner): Free the unlinked job. * src/triplet.c (triplet_lookup): Free key.name. * src/verify.c (fill_project_name): Return immediately if trp->blurb is not null. * src/watcher.c (create_watcher): Ignore spool if its inotify_enable is false. (watcher_init): Return immediately if inotify_enable is false. * src/wydawca.c (inotify_enable): New global. * src/wydawca.h: Likewise.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/config.c10
-rw-r--r--src/gpg.c107
-rw-r--r--src/job.c7
-rw-r--r--src/triplet.c3
-rw-r--r--src/verify.c3
-rw-r--r--src/watcher.c16
-rw-r--r--src/wydawca.c2
-rw-r--r--src/wydawca.h3
8 files changed, 99 insertions, 52 deletions
diff --git a/src/config.c b/src/config.c
index 66d5fb7..509b0d5 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1149,24 +1149,28 @@ static struct grecs_keyword spool_kw[] = {
NULL, offsetof(struct spool, aliases) },
{ "source", N_("dir"), N_("Source directory"),
grecs_type_string, GRECS_DFLT,
NULL, offsetof(struct spool, source_dir) },
{ "destination", N_("dir"), N_("Destination directory"),
grecs_type_string, GRECS_DFLT,
NULL, offsetof(struct spool, dest_url),
cb_url },
{ "file-sweep-time", N_("interval"), N_("Define file sweep time"),
grecs_type_string, GRECS_DFLT,
NULL, offsetof(struct spool, file_sweep_time),
cb_interval },
+ { "inotify", NULL, N_("Enable or disable inotify for this spool"),
+ grecs_type_bool, GRECS_DFLT,
+ NULL, offsetof(struct spool, inotify_enable), },
+
{ "dictionary", N_("ident"), N_("Define data dictionary"),
grecs_type_section, GRECS_DFLT,
NULL, offsetof(struct spool, dictionary),
cb_dictionary, NULL, dictionary_kw },
{ "archive", N_("type: string"), N_("Set up archivation"),
grecs_type_section, GRECS_DFLT,
NULL, offsetof(struct spool, archive),
cb_archive, NULL, archive_kw },
{ "notify-event", NULL, N_("Configure notification"),
grecs_type_section, GRECS_DFLT,
NULL, offsetof(struct spool, notification),
cb_notify_event, NULL, notify_event_kw },
@@ -1191,24 +1195,25 @@ cb_spool (enum grecs_callback_command cmd,
switch (cmd)
{
case grecs_callback_section_begin:
if (!value || value->type != GRECS_TYPE_STRING)
{
grecs_error (value ? &value->locus : locus, 0,
_("tag must be a string"));
return 1;
}
spool = grecs_zalloc (sizeof (*spool));
spool->tag = grecs_strdup (value->v.string);
spool->file_sweep_time = file_sweep_time;
+ spool->inotify_enable = 1;
for (i = 0; i < NITEMS (spool->dictionary); i++)
spool->dictionary[i] = default_dictionary[i];
spool->archive = default_archive_descr;
*pdata = spool;
break;
case grecs_callback_section_end:
rc = 0;
spool = *pdata;
if (!spool->source_dir)
{
grecs_error (locus, 0, _("source is not given"));
@@ -1409,25 +1414,28 @@ cb_upload_version (enum grecs_callback_command cmd,
static struct grecs_keyword wydawca_kw[] = {
{ "daemon", NULL, N_("Enable daemon mode"),
grecs_type_bool, GRECS_DFLT, &daemon_mode },
{ "foreground", NULL, N_("Start in foreground even in daemon mode"),
grecs_type_bool, GRECS_DFLT, &foreground },
{ "single-process", NULL, N_("Do not spawn subprocesses"),
grecs_type_bool, GRECS_DFLT, &single_process },
{ "wakeup-interval", N_("time"), N_("Set wake-up interval"),
grecs_type_string, GRECS_DFLT, &wakeup_interval, 0, cb_interval },
{ "pidfile", N_("file"), N_("Set pid file name"),
grecs_type_string, GRECS_DFLT, &pidfile },
-
+
+ { "inotify", NULL, N_("Enable or disable inotify support"),
+ grecs_type_bool, GRECS_DFLT, &inotify_enable },
+
{ "user", N_("name"), N_("Run with UID and GID of this user"),
grecs_type_string, GRECS_DFLT, NULL, 0, cb_user },
{ "group", NULL, N_("Retain these supplementary groups"),
grecs_type_string, GRECS_LIST, NULL, 0, cb_supp_groups },
{ "min-version", N_("major.minor"),
N_("Set minimal allowed directive file version"),
grecs_type_string, GRECS_DFLT,
&min_directive_version, 0, cb_upload_version },
{ "max-version", N_("major.minor"),
N_("Set maximal allowed directive file version"),
grecs_type_string, GRECS_DFLT,
diff --git a/src/gpg.c b/src/gpg.c
index 8979e9c..814be6f 100644
--- a/src/gpg.c
+++ b/src/gpg.c
@@ -138,95 +138,105 @@ create_gpg_homedir ()
logmsg (LOG_CRIT, _("cannot create GPG home directory (%s): %s"),
temp_homedir, strerror (errno));
return 1;
}
atexit (remove_homedir);
if (debug_level > 1)
logmsg (LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir);
setenv ("GNUPGHOME", temp_homedir, 1);
return 0;
}
static int
+checksig (gpgme_signature_t sig, const char *uid, struct file_triplet *trp)
+{
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_NO_ERROR:
+ if (debug_level)
+ logmsg (LOG_NOTICE, _("Good signature from %s"), uid);
+ trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr);
+ if (!trp->uploader)
+ {
+ logmsg (LOG_ERR,
+ _("good signature from %s, "
+ "but the uploader info for %s not found"),
+ uid, sig->fpr);
+ return 1;
+ }
+ break;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ UPDATE_STATS (STAT_BAD_SIGNATURE);
+ logmsg (LOG_ERR, _("BAD signature from %s"), uid);
+ return 0;
+
+ case GPG_ERR_NO_PUBKEY:
+ UPDATE_STATS (STAT_ACCESS_VIOLATIONS);
+ logmsg (LOG_ERR, _("No public key"));
+ return 0;
+
+ case GPG_ERR_NO_DATA:
+ UPDATE_STATS (STAT_BAD_TRIPLETS);
+ logmsg (LOG_ERR, _("No signature"));
+ return 0;
+
+ case GPG_ERR_SIG_EXPIRED:
+ UPDATE_STATS (STAT_BAD_SIGNATURE);
+ logmsg (LOG_ERR, _("Expired signature from %s"), uid);
+ return 0;
+
+ case GPG_ERR_KEY_EXPIRED:
+ UPDATE_STATS (STAT_BAD_SIGNATURE);
+ logmsg (LOG_ERR, _("Key expired (%s)"), uid);
+ return 0;
+
+ default:
+ logmsg (LOG_ERR, _("Unknown signature error"));
+ return 0;
+ }
+ return -1;
+}
+
+static int
gpg_verify_signature (gpgme_ctx_t ctx, gpgme_signature_t sig,
struct file_triplet *trp)
{
if (!sig)
return 0;
for (; sig; sig = sig->next)
{
const char *uid;
gpgme_key_t key;
-
+ int rc;
+
if (gpgme_get_key (ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR)
uid = key->uids->uid;
else
uid = sig->fpr;
-
- switch (gpg_err_code (sig->status))
- {
- case GPG_ERR_NO_ERROR:
- if (debug_level)
- logmsg (LOG_NOTICE, _("Good signature from %s"), uid);
- trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr);
- if (!trp->uploader)
- {
- logmsg (LOG_ERR,
- _("good signature from %s, "
- "but the uploader info for %s not found"),
- uid, sig->fpr);
- return 1;
- }
- break;
-
- case GPG_ERR_BAD_SIGNATURE:
- UPDATE_STATS (STAT_BAD_SIGNATURE);
- logmsg (LOG_ERR, _("BAD signature from %s"), uid);
- return 0;
-
- case GPG_ERR_NO_PUBKEY:
- UPDATE_STATS (STAT_ACCESS_VIOLATIONS);
- logmsg (LOG_ERR, _("No public key"));
- return 0;
-
- case GPG_ERR_NO_DATA:
- UPDATE_STATS (STAT_BAD_TRIPLETS);
- logmsg (LOG_ERR, _("No signature"));
- return 0;
-
- case GPG_ERR_SIG_EXPIRED:
- UPDATE_STATS (STAT_BAD_SIGNATURE);
- logmsg (LOG_ERR, _("Expired signature from %s"), uid);
- return 0;
-
- case GPG_ERR_KEY_EXPIRED:
- UPDATE_STATS (STAT_BAD_SIGNATURE);
- logmsg (LOG_ERR, _("Key expired (%s)"), uid);
- return 0;
-
- default:
- logmsg (LOG_ERR, _("Unknown signature error"));
- return 0;
- }
+ rc = checksig (sig, uid, trp);
+ gpgme_key_unref (key);
+ if (rc != -1)
+ return rc;
}
return 1;
}
/* Verify the directive file from TRP using public key PUBKEY */
int
verify_directive_signature (struct file_triplet *trp)
{
gpgme_ctx_t ctx;
- gpgme_data_t key_data, directive_data, plain;
+ gpgme_data_t key_data, directive_data, plain = NULL;
gpgme_error_t ec;
int rc;
struct uploader_info *uptr;
create_gpg_homedir ();
fail_if_err (gpgme_new (&ctx));
for (uptr = trp->uploader_list; uptr; uptr = uptr->next)
{
gpgme_import_result_t res;
gpgme_import_status_t pstat;
@@ -260,24 +270,25 @@ verify_directive_signature (struct file_triplet *trp)
}
else
rc = 0;
}
else
{
rc = 1;
UPDATE_STATS (STAT_BAD_SIGNATURE);
logmsg (LOG_ERR, _("%s: directive verification failed: %s"),
trp->name, gpgme_strerror (ec));
}
+ gpgme_data_release (plain);
gpgme_data_release (directive_data);
gpgme_data_release (key_data);
gpgme_release (ctx);
return rc;
}
/* Verify the detached signature of TRP.
NOTE: It is assumed that the public key is already registered (by
a previous call to verify_directive_signature). */
int
verify_detached_signature (struct file_triplet *trp)
diff --git a/src/job.c b/src/job.c
index 3fae432..315303f 100644
--- a/src/job.c
+++ b/src/job.c
@@ -329,25 +329,30 @@ job_queue_runner ()
{
if (WIFEXITED (job->exit_status)
&& WEXITSTATUS (job->exit_status) == WYDAWCA_EX_AGAIN)
{
time_t interval = lock_timeout;
if (interval == 0)
interval = lock_expire_time;
/* Re-queue the job */
job->state = STATE_QUEUED;
job->timestamp = now + interval;
}
else
- job_remove (job);
+ {
+ job_remove (job);
+ free (job);
+ job = next;
+ continue;
+ }
}
}
if (job->state == STATE_QUEUED)
{
if (job->timestamp >= now)
{
if (job_start (job))
pause (); /* FIXME */
now = time (NULL);
}
else
diff --git a/src/triplet.c b/src/triplet.c
index 05b7536..aa74de0 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -118,27 +118,28 @@ triplet_lookup (struct spool *spool, const char *name)
struct file_triplet key, *ret;
struct file_info finfo;
if (!triplet_table)
return NULL;
parse_file_name (name, &finfo);
key.name = grecs_malloc (finfo.root_len + 1);
memcpy (key.name, finfo.name, finfo.root_len);
key.name[finfo.root_len] = 0;
key.spool = spool;
+ file_info_cleanup (&finfo);
ret = grecs_symtab_lookup_or_install (triplet_table, &key, NULL);
- file_info_cleanup (&finfo);
+ free (key.name);
return ret;
}
/* Return true if any part of the triplet TRP was modified more than
TTL seconds ago */
static int
triplet_expired_p (struct file_triplet *trp, time_t ttl)
{
int i;
time_t now = time (NULL);
diff --git a/src/verify.c b/src/verify.c
index 4a108bc..dee160f 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -87,24 +87,27 @@ extract_plaintext (char *blurb)
return 1;
}
int
fill_project_name (struct file_triplet *trp)
{
char *blurb;
size_t size;
FILE *fp;
char *p;
const char *directory;
int rc;
+
+ if (trp->blurb)
+ return 0;
size = trp->file[file_directive].sb.st_size;
if (size <= MSG_BEGIN_MARKER_LEN)
{
logmsg (LOG_ERR, _("too small directive file %s"),
trp->file[file_directive].name);
return 1;
}
fp = fopen (trp->file[file_directive].name, "r");
if (!fp)
{
diff --git a/src/watcher.c b/src/watcher.c
index f8761ee..c52e3e6 100644
--- a/src/watcher.c
+++ b/src/watcher.c
@@ -74,27 +74,34 @@ dirwatcher_find_wd (int wd)
}
static int
create_watcher (struct spool *sp, void *data)
{
int ifd = *(int*)data;
struct dirwatcher *dwp;
int wd;
const char *path = get_path (sp);
if (!sp)
return 0;
+
+ if (!sp->inotify_enable)
+ {
+ if (debug_level > 1)
+ logmsg (LOG_DEBUG, "disabling inotify support for spool %s", sp->tag);
+ return 0;
+ }
if (debug_level > 1)
- logmsg (LOG_DEBUG, "creating watcher %s", path);
+ logmsg (LOG_DEBUG, "spool %s: creating watcher %s", sp->tag, path);
dwp = malloc (sizeof(*dwp));
if (!dwp)
{
logmsg (LOG_ERR, "not enough memory");
return 1;
}
dwp->spool = sp;
dwp->parent = NULL;
wd = inotify_add_watch (ifd, path, IN_DELETE|IN_CREATE|IN_CLOSE_WRITE|
IN_MOVED_FROM|IN_MOVED_TO);
if (wd == -1)
@@ -104,24 +111,31 @@ create_watcher (struct spool *sp, void *data)
return 1;
}
dwp->wd = wd;
dirwatcher_push (&dirwatcher_list, dwp);
return 0;
}
int
watcher_init ()
{
int ifd, rc;
+
+ if (!inotify_enable)
+ {
+ if (debug_level > 1)
+ logmsg (LOG_DEBUG, "disabling inotify support");
+ return -1;
+ }
if (debug_level > 1)
logmsg (LOG_DEBUG, "setting up inotify");
ifd = inotify_init ();
if (ifd == -1)
{
logmsg (LOG_ERR, "inotify_init: %s", strerror (errno));
return -1;
}
rc = for_each_spool (create_watcher, &ifd);
if (rc)
diff --git a/src/wydawca.c b/src/wydawca.c
index 521d796..45a5cff 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -44,24 +44,26 @@ int foreground;
int single_process;
time_t wakeup_interval;
struct grecs_list *all_spool_aliases;
char *wydawca_gpg_homedir;
char *default_check_script;
struct grecs_sockaddr listen_sockaddr;
unsigned wydawca_stat[MAX_STAT];
unsigned min_directive_version = MIN_DIRECTIVE_VERSION;
unsigned max_directive_version = MAX_DIRECTIVE_VERSION;
+int inotify_enable = 1;
+
void
initstats ()
{
memset (wydawca_stat, 0, sizeof wydawca_stat);
}
/* Logging */
void
syslog_printer (int prio, const char *fmt, va_list ap)
{
if (syslog_include_prio)
diff --git a/src/wydawca.h b/src/wydawca.h
index 722fc9b..323d403 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -217,24 +217,25 @@ struct virt_tab
/* An upload spool. This structure contains all data necessary for releasing
files from source to destination */
struct spool
{
char *tag;
struct grecs_list *aliases;
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 */
+ int inotify_enable;
time_t file_sweep_time; /* Remove invalid/unprocessed files
after this amount of time */
struct dictionary *dictionary[dictionary_count];
int dict_inited;
struct archive_descr archive; /* Archivation data */
struct notification *notification;
char *check_script;
};
#define ASGN_SPOOL(spool, trp, faction) \
do \
@@ -368,24 +369,26 @@ extern struct grecs_sockaddr listen_sockaddr;
extern struct grecs_list *all_spool_aliases;
extern char *wydawca_gpg_homedir;
extern char *default_check_script;
extern char *temp_homedir;
extern unsigned min_directive_version;
extern unsigned max_directive_version;
extern struct spool fake_spool;
extern struct spool inotify_spool;
+extern int inotify_enable;
+
#define UPDATE_STATS(what) \
do \
{ \
if (what >= MAX_STAT) abort(); \
wydawca_stat[what]++; \
} \
while (0)
int stat_mask_p (unsigned long mask);
struct metadef *make_stat_expansion (size_t count);
void initstats (void);
void logstats (void);

Return to:

Send suggestions and report system problems to the System administrator.