diff options
Diffstat (limited to 'src/triplet.c')
-rw-r--r-- | src/triplet.c | 1270 |
1 files changed, 619 insertions, 651 deletions
diff --git a/src/triplet.c b/src/triplet.c index a327b43..c4dc576 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 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 @@ -28,510 +28,489 @@ static struct file_triplet *triplet_list; /* Functions for building the ordered doubly-linked list of triplets */ static time_t -triplet_timestamp (struct file_triplet *tp) +triplet_timestamp(struct file_triplet *tp) { - int i; - time_t t = 0; + int i; + time_t t = 0; - if (!tp) - return 0; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (tp->file[i].name && - (t == 0 || t > tp->file[i].sb.st_mtime)) - t = tp->file[i].sb.st_mtime; - } - return t; + if (!tp) + return 0; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (tp->file[i].name && + (t == 0 || t > tp->file[i].sb.st_mtime)) + t = tp->file[i].sb.st_mtime; + } + return t; } static time_t -triplet_ttl (struct file_triplet *tp) +triplet_ttl(struct file_triplet *tp) { - time_t t; + time_t t; - if (!tp) - return 0; - t = time (NULL) - triplet_timestamp (tp); - if (t < tp->spool->file_sweep_time) - return tp->spool->file_sweep_time - t; - return 0; + if (!tp) + return 0; + t = time(NULL) - triplet_timestamp(tp); + if (t < tp->spool->file_sweep_time) + return tp->spool->file_sweep_time - t; + return 0; } void -triplet_list_unlink (struct file_triplet *tp) +triplet_list_unlink(struct file_triplet *tp) { - if (tp->prev) - tp->prev->next = tp->next; - else - triplet_list = tp->next; + if (tp->prev) + tp->prev->next = tp->next; + else + triplet_list = tp->next; - if (tp->next) - tp->next->prev = tp->prev; - - tp->next = tp->prev = NULL; + if (tp->next) + tp->next->prev = tp->prev; + + tp->next = tp->prev = NULL; } static void -triplet_list_insert_before (struct file_triplet *newp, - struct file_triplet *anchor) +triplet_list_insert_before(struct file_triplet *newp, + struct file_triplet *anchor) { - if (!anchor) - { - triplet_list = newp; - return; - } + if (!anchor) { + triplet_list = newp; + return; + } - if (anchor->prev) - anchor->prev->next = newp; - else - triplet_list = newp; - newp->prev = anchor->prev; + if (anchor->prev) + anchor->prev->next = newp; + else + triplet_list = newp; + newp->prev = anchor->prev; - anchor->prev = newp; - newp->next = anchor; + anchor->prev = newp; + newp->next = anchor; } void -triplet_list_ordered_insert (struct file_triplet *tp) -{ - time_t t = triplet_timestamp (tp); - struct file_triplet *p, *prev = NULL; - - for (p = triplet_list; p && triplet_timestamp (p) < t; prev = p, p = p->next) - ; - if (p) - triplet_list_insert_before (tp, p); - else if (prev) - { - prev->next = tp; - tp->prev = prev; - tp->next = NULL; - } - else - { - tp->next = tp->prev = NULL; - triplet_list = tp; - } +triplet_list_ordered_insert(struct file_triplet *tp) +{ + time_t t = triplet_timestamp(tp); + struct file_triplet *p, *prev = NULL; + + for (p = triplet_list; p && triplet_timestamp(p) < t; + prev = p, p = p->next) ; + if (p) + triplet_list_insert_before(tp, p); + else if (prev) { + prev->next = tp; + tp->prev = prev; + tp->next = NULL; + } else { + tp->next = tp->prev = NULL; + triplet_list = tp; + } } - /* Functions for operation on a symtab of triplets. */ static unsigned -hash_triplet_hasher (void *data, unsigned long n_buckets) +hash_triplet_hasher(void *data, unsigned long n_buckets) { - struct file_triplet const *t = data; - return grecs_hash_string (t->name, n_buckets); + struct file_triplet const *t = data; + return grecs_hash_string(t->name, n_buckets); } /* Compare two strings for equality. */ static int -hash_triplet_compare (void const *data1, void const *data2) +hash_triplet_compare(void const *data1, void const *data2) { - struct file_triplet const *t1 = data1; - struct file_triplet const *t2 = data2; - return t1->spool == t2->spool && strcmp (t1->name, t2->name); + struct file_triplet const *t1 = data1; + struct file_triplet const *t2 = data2; + return t1->spool == t2->spool && strcmp(t1->name, t2->name); } /* Reclaim memory storage associated with a table entry */ void -hash_triplet_free (void *data) -{ - int i; - struct file_triplet *tp = data; - struct uploader_info *up; - - free (tp->name); - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (tp->file[i].name) - free (tp->file[i].name); - } - - free (tp->directive); - free (tp->blurb); - free (tp->tmp); - txtacc_free (tp->acc); - - /* Free uploader list */ - for (up = tp->uploader_list; up; ) - { - struct uploader_info *next = up->next; - free (up->fpr); - free (up); - up = next; - } - - free (tp); +hash_triplet_free(void *data) +{ + int i; + struct file_triplet *tp = data; + struct uploader_info *up; + + free(tp->name); + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (tp->file[i].name) + free(tp->file[i].name); + } + + free(tp->directive); + free(tp->blurb); + free(tp->tmp); + txtacc_free(tp->acc); + + /* Free uploader list */ + for (up = tp->uploader_list; up;) { + struct uploader_info *next = up->next; + free(up->fpr); + free(up); + up = next; + } + + free(tp); } char * -triplet_strdup (struct file_triplet *tp, const char *str) +triplet_strdup(struct file_triplet *tp, const char *str) { - size_t len = strlen (str); - txtacc_grow (tp->acc, str, len + 1); - return txtacc_finish (tp->acc, 0); + size_t len = strlen(str); + txtacc_grow(tp->acc, str, len + 1); + return txtacc_finish(tp->acc, 0); } /* Register a file in the triplet table */ void -register_file (struct file_info *finfo, const struct spool *spool) -{ - struct file_triplet key, *ret; - int install = 1; - - if (!triplet_table) - { - triplet_table = grecs_symtab_create (sizeof (struct file_triplet), - hash_triplet_hasher, - hash_triplet_compare, - NULL, - NULL, - hash_triplet_free); - if (!triplet_table) - grecs_alloc_die (); - } - - 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; - - ret = grecs_symtab_lookup_or_install (triplet_table, &key, &install); - if (!ret) - grecs_alloc_die (); - free (key.name); - if (install) - { - ret->spool = spool; - ret->acc = txtacc_create (); - } - ret->file[finfo->type] = *finfo; - triplet_list_unlink (ret); - triplet_list_ordered_insert (ret); +register_file(struct file_info *finfo, const struct spool *spool) +{ + struct file_triplet key, *ret; + int install = 1; + + if (!triplet_table) { + triplet_table = + grecs_symtab_create(sizeof(struct file_triplet), + hash_triplet_hasher, + hash_triplet_compare, + NULL, + NULL, + hash_triplet_free); + if (!triplet_table) + grecs_alloc_die(); + } + + 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; + + ret = grecs_symtab_lookup_or_install(triplet_table, &key, &install); + if (!ret) + grecs_alloc_die(); + free(key.name); + if (install) { + ret->spool = spool; + ret->acc = txtacc_create(); + } + ret->file[finfo->type] = *finfo; + triplet_list_unlink(ret); + triplet_list_ordered_insert(ret); } struct file_triplet * -triplet_lookup (struct spool *spool, const char *name) +triplet_lookup(struct spool *spool, const char *name) { - struct file_triplet key, *ret; - struct file_info finfo; - - if (!triplet_table) - return NULL; + struct file_triplet key, *ret; + struct file_info finfo; - parse_file_name (name, &finfo); + if (!triplet_table) + return NULL; - 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); + parse_file_name(name, &finfo); - ret = grecs_symtab_lookup_or_install (triplet_table, &key, NULL); - free (key.name); + 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); - return ret; + ret = grecs_symtab_lookup_or_install(triplet_table, &key, NULL); + 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) -{ - int i; - time_t now = time (NULL); - time_t ttl = trp->spool->file_sweep_time; - - if (ttl == 0) - return 0; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (trp->file[i].name - && (now - trp->file[i].sb.st_mtime) >= ttl) - { - if (debug_level) - logmsg (LOG_DEBUG, _("file %s expired"), trp->file[i].name); - return 1; +triplet_expired_p(struct file_triplet *trp) +{ + int i; + time_t now = time(NULL); + time_t ttl = trp->spool->file_sweep_time; + + if (ttl == 0) + return 0; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (trp->file[i].name + && (now - trp->file[i].sb.st_mtime) >= ttl) { + if (debug_level) + logmsg(LOG_DEBUG, _("file %s expired"), + trp->file[i].name); + return 1; + } } - } - return 0; -} - -enum triplet_state - { - triplet_directive, /* Short triplet: only a directive is present, - but nothing more is required */ - triplet_complete, /* A complete triplet: all three files are present - and have the same owner */ - triplet_incomplete, /* Incomplete triplet: some files are missing */ - triplet_bad, /* Bad triplet. Should be removed immediately. */ - }; - + return 0; +} + +enum triplet_state { + triplet_directive, /* Short triplet: only a directive is present, + but nothing more is required */ + triplet_complete, /* A complete triplet: all three files are + present and have the same owner */ + triplet_incomplete, /* Incomplete triplet: some files are + missing */ + triplet_bad, /* Bad triplet. Should be removed + immediately. */ +}; static enum triplet_state -check_triplet_state (struct file_triplet *trp, int noauth) -{ - if (trp->file[file_directive].name) - { - if (verify_directive_file (trp, noauth)) - return triplet_bad; - - if (trp->file[file_dist].name == 0 - && trp->file[file_signature].name == 0) - { - if (directive_get_value (trp, "filename", NULL)) - return triplet_directive; - } - else if (trp->file[file_dist].name && trp->file[file_signature].name) - { - if (trp->file[file_dist].sb.st_uid == - trp->file[file_signature].sb.st_uid - && trp->file[file_dist].sb.st_uid == - trp->file[file_directive].sb.st_uid) - return triplet_complete; - else - { - if (debug_level) - logmsg (LOG_DEBUG, _("%s: invalid triplet: UIDs differ"), - trp->name); - return triplet_bad; - } +check_triplet_state(struct file_triplet *trp, int noauth) +{ + if (trp->file[file_directive].name) { + if (verify_directive_file(trp, noauth)) + return triplet_bad; + + if (trp->file[file_dist].name == 0 && + trp->file[file_signature].name == 0) { + if (directive_get_value(trp, "filename", NULL)) + return triplet_directive; + } else if (trp->file[file_dist].name && + trp->file[file_signature].name) { + if (trp->file[file_dist].sb.st_uid == + trp->file[file_signature].sb.st_uid && + trp->file[file_dist].sb.st_uid == + trp->file[file_directive].sb.st_uid) + return triplet_complete; + else { + if (debug_level) + logmsg(LOG_DEBUG, + _("%s: invalid triplet: " + "UIDs differ"), + trp->name); + return triplet_bad; + } + } } - } - return triplet_incomplete; + return triplet_incomplete; } /* Unlink all parts of the triplet TRP */ static void -remove_triplet (struct file_triplet *trp) -{ - int i; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (trp->file[i].name) - { - logmsg (LOG_NOTICE, _("removing %s"), trp->file[i].name); - if (!dry_run_mode && unlink (trp->file[i].name)) - logmsg (LOG_ERR, _("cannot remove %s: %s"), - trp->file[i].name, strerror (errno)); +remove_triplet(struct file_triplet *trp) +{ + int i; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (trp->file[i].name) { + logmsg(LOG_NOTICE, _("removing %s"), + trp->file[i].name); + if (!dry_run_mode && unlink(trp->file[i].name)) + logmsg(LOG_ERR, _("cannot remove %s: %s"), + trp->file[i].name, strerror(errno)); + } } - } - triplet_list_unlink (trp); - grecs_symtab_remove (triplet_table, trp); + triplet_list_unlink(trp); + grecs_symtab_remove(triplet_table, trp); } time_t -triplet_sweep (void) +triplet_sweep(void) { - while (triplet_list && triplet_expired_p (triplet_list)) - remove_triplet (triplet_list); + while (triplet_list && triplet_expired_p(triplet_list)) + remove_triplet(triplet_list); - return triplet_ttl (triplet_list); + return triplet_ttl(triplet_list); } /* Process a single triplet from the table */ static int -triplet_processor (void *data, void *proc_data) -{ - struct file_triplet *trp = data; - - if (debug_level) - logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", - trp->name, - SP (trp->file[file_dist].name), - SP (trp->file[file_signature].name), - SP (trp->file[file_directive].name)); - - switch (check_triplet_state (trp, 0)) - { - case triplet_directive: - case triplet_complete: - if (debug_level) - logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name); - if (process_directives (trp)) - remove_triplet (trp); - return 0; - - case triplet_incomplete: - if (debug_level) - logmsg (LOG_DEBUG, _("%s: incomplete triplet"), trp->name); - /* ignore unless expired (see below); */ - UPDATE_STATS (STAT_INCOMPLETE_TRIPLETS); - break; - - case triplet_bad: - UPDATE_STATS (STAT_BAD_TRIPLETS); - remove_triplet (trp); - return 0; - } - - if (triplet_expired_p (trp)) - { - UPDATE_STATS (STAT_EXPIRED_TRIPLETS); - remove_triplet (trp); - } - - return 0; +triplet_processor(void *data, void *proc_data) +{ + struct file_triplet *trp = data; + + if (debug_level) + logmsg(LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", + trp->name, + SP(trp->file[file_dist].name), + SP(trp->file[file_signature].name), + SP(trp->file[file_directive].name)); + + switch (check_triplet_state(trp, 0)) { + case triplet_directive: + case triplet_complete: + if (debug_level) + logmsg(LOG_DEBUG, _("processing triplet `%s'"), + trp->name); + if (process_directives(trp)) + remove_triplet(trp); + return 0; + + case triplet_incomplete: + if (debug_level) + logmsg(LOG_DEBUG, _("%s: incomplete triplet"), + trp->name); + /* ignore unless expired (see below); */ + UPDATE_STATS(STAT_INCOMPLETE_TRIPLETS); + break; + + case triplet_bad: + UPDATE_STATS(STAT_BAD_TRIPLETS); + remove_triplet(trp); + return 0; + } + + if (triplet_expired_p(trp)) { + UPDATE_STATS(STAT_EXPIRED_TRIPLETS); + remove_triplet(trp); + } + + return 0; } /* Process all triplets from the table according to the SPOOL */ void -spool_commit_triplets (struct spool *spool) -{ - if (debug_level) - logmsg (LOG_DEBUG, _("processing spool %s (%s)"), - spool->tag, mu_url_to_string (spool->dest_url)); - if (spool_open_dictionaries (spool)) - return; - if (triplet_table) - { - grecs_symtab_enumerate (triplet_table, triplet_processor, NULL); - grecs_symtab_clear (triplet_table); - } +spool_commit_triplets(struct spool *spool) +{ + if (debug_level) + logmsg(LOG_DEBUG, _("processing spool %s (%s)"), + spool->tag, mu_url_to_string(spool->dest_url)); + if (spool_open_dictionaries(spool)) + return; + if (triplet_table) { + grecs_symtab_enumerate(triplet_table, triplet_processor, NULL); + grecs_symtab_clear(triplet_table); + } } size_t -count_collected_triplets () +count_collected_triplets() { - return triplet_table ? grecs_symtab_count_entries (triplet_table) : 0; + return triplet_table ? grecs_symtab_count_entries(triplet_table) : 0; } static int -triplet_counter (void *data, void *proc_data) -{ - struct file_triplet *trp = data; - size_t *cp = proc_data; - - if (debug_level) - logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", - trp->name, - SP (trp->file[file_dist].name), - SP (trp->file[file_signature].name), - SP (trp->file[file_directive].name)); - - switch (check_triplet_state (trp, 1)) - { - case triplet_directive: - case triplet_complete: - if (triplet_expired_p (trp)) - remove_triplet (trp); - else - ++*cp; - break; - case triplet_incomplete: - break; - case triplet_bad: - remove_triplet (trp); - } - - return 0; +triplet_counter(void *data, void *proc_data) +{ + struct file_triplet *trp = data; + size_t *cp = proc_data; + + if (debug_level) + logmsg(LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", + trp->name, + SP(trp->file[file_dist].name), + SP(trp->file[file_signature].name), + SP(trp->file[file_directive].name)); + + switch (check_triplet_state(trp, 1)) { + case triplet_directive: + case triplet_complete: + if (triplet_expired_p(trp)) + remove_triplet(trp); + else + ++*cp; + break; + case triplet_incomplete: + break; + case triplet_bad: + remove_triplet(trp); + } + + return 0; } size_t -count_processable_triplets () +count_processable_triplets() { - size_t count = 0; - if (triplet_table) - grecs_symtab_enumerate (triplet_table, triplet_counter, &count); - return count; + size_t count = 0; + if (triplet_table) + grecs_symtab_enumerate(triplet_table, triplet_counter, &count); + return count; } void -triplet_remove_file (struct spool *spool, const char *name) -{ - struct file_triplet *tp = triplet_lookup (spool, name); - int i, n = 0; - - if (!tp) - return; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (!tp->file[i].name) - /* nothing */; - else if (strcmp (tp->file[i].name, name) == 0) - file_info_cleanup (&tp->file[i]); - else - n++; - } - - if (!n) - { - if (debug_level > 0) - logmsg (LOG_DEBUG, "deleting empty triplet (%s/%s)", - spool->source_dir, name); - remove_triplet (tp); - } -} +triplet_remove_file(struct spool *spool, const char *name) +{ + struct file_triplet *tp = triplet_lookup(spool, name); + int i, n = 0; + + if (!tp) + return; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (!tp->file[i].name) + /* nothing */ ; + else if (strcmp(tp->file[i].name, name) == 0) + file_info_cleanup(&tp->file[i]); + else + n++; + } + if (!n) { + if (debug_level > 0) + logmsg(LOG_DEBUG, "deleting empty triplet (%s/%s)", + spool->source_dir, name); + remove_triplet(tp); + } +} static const char * -expand_project_base (struct metadef *def, void *data) +expand_project_base(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->project; + struct file_triplet *trp = data; + return trp->project; } static const char * -expand_tag (struct metadef *def, void *data) +expand_tag(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->tag; + struct file_triplet *trp = data; + return trp->spool->tag; } static const char * -expand_url (struct metadef *def, void *data) +expand_url(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->url; + struct file_triplet *trp = data; + return trp->spool->url; } static const char * -expand_relative_dir (struct metadef *def, void *data) +expand_relative_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - directive_get_value (trp, "directory", (const char**) &def->value); - return def->value; + struct file_triplet *trp = data; + directive_get_value(trp, "directory", (const char **)&def->value); + return def->value; } static const char * -expand_dest_dir (struct metadef *def, void *data) +expand_dest_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->dest_dir; + struct file_triplet *trp = data; + return trp->spool->dest_dir; } static const char * -expand_source_dir (struct metadef *def, void *data) +expand_source_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->source_dir; + struct file_triplet *trp = data; + return trp->spool->source_dir; } static void -decode_file_mode (mode_t mode, char *string) -{ - *string++ = mode & S_IRUSR ? 'r' : '-'; - *string++ = mode & S_IWUSR ? 'w' : '-'; - *string++ = (mode & S_ISUID - ? (mode & S_IXUSR ? 's' : 'S') - : (mode & S_IXUSR ? 'x' : '-')); - *string++ = mode & S_IRGRP ? 'r' : '-'; - *string++ = mode & S_IWGRP ? 'w' : '-'; - *string++ = (mode & S_ISGID - ? (mode & S_IXGRP ? 's' : 'S') - : (mode & S_IXGRP ? 'x' : '-')); - *string++ = mode & S_IROTH ? 'r' : '-'; - *string++ = mode & S_IWOTH ? 'w' : '-'; - *string++ = (mode & S_ISVTX - ? (mode & S_IXOTH ? 't' : 'T') - : (mode & S_IXOTH ? 'x' : '-')); - *string = '\0'; +decode_file_mode(mode_t mode, char *string) +{ + *string++ = mode & S_IRUSR ? 'r' : '-'; + *string++ = mode & S_IWUSR ? 'w' : '-'; + *string++ = (mode & S_ISUID ? (mode & S_IXUSR ? 's' : 'S') + : (mode & S_IXUSR ? 'x' : '-')); + *string++ = mode & S_IRGRP ? 'r' : '-'; + *string++ = mode & S_IWGRP ? 'w' : '-'; + *string++ = (mode & S_ISGID ? (mode & S_IXGRP ? 's' : 'S') + : (mode & S_IXGRP ? 'x' : '-')); + *string++ = mode & S_IROTH ? 'r' : '-'; + *string++ = mode & S_IWOTH ? 'w' : '-'; + *string++ = (mode & S_ISVTX ? (mode & S_IXOTH ? 't' : 'T') + : (mode & S_IXOTH ? 'x' : '-')); + *string = '\0'; } /* Width of "user/group size", with initial value chosen @@ -542,360 +521,349 @@ decode_file_mode (mode_t mode, char *string) static int ugswidth = 19; static int -format_file_data (struct file_triplet *trp, enum file_type type, char **pret) -{ - char modes[11]; - struct file_info *info = trp->file + type; - char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"]; - struct passwd *pw; - struct group *grp; - char *sptr = NULL; - size_t slen = 0; - int pad; - char *user_name; - char *group_name; - struct tm *tm; - char *buf = NULL; - size_t size = 0; - - if (!info->name) - return 1; - - /* MODE OWNER GROUP SIZE MTIME FILE_NAME MD5SUM? */ - - modes[0] = '-'; /* Only regular files are allowed */ - decode_file_mode (info->sb.st_mode, modes + 1); - - /* File time */ - tm = localtime (&info->sb.st_mtime); - strftime (timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z", tm); - - pw = getpwuid (TRIPLET_UID (trp)); - if (!pw) - user_name = "unknown"; - else - user_name = pw->pw_name; - - grp = getgrgid (TRIPLET_GID (trp)); - if (!grp) - group_name = "unknown"; /* should not happen */ - else - group_name = grp->gr_name; - - /* Size */ - if (grecs_asprintf (&sptr, &slen, "%lu", (unsigned long) info->sb.st_size)) - grecs_alloc_die (); - - /* Figure out padding and format the buffer */ - slen = strlen (sptr); - pad = strlen (user_name) + 1 + strlen (group_name) + 1 + slen; - if (pad > ugswidth) - ugswidth = pad; - - if (grecs_asprintf (&buf, &size, - "%s %s %s %*s %s %s", - modes, user_name, group_name, ugswidth - pad + slen, - sptr, - timebuf, info->name)) - grecs_alloc_die (); - free (sptr); - *pret = buf; - return 0; +format_file_data(struct file_triplet *trp, enum file_type type, char **pret) +{ + char modes[11]; + struct file_info *info = trp->file + type; + char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"]; + struct passwd *pw; + struct group *grp; + char *sptr = NULL; + size_t slen = 0; + int pad; + char *user_name; + char *group_name; + struct tm *tm; + char *buf = NULL; + size_t size = 0; + + if (!info->name) + return 1; + + /* MODE OWNER GROUP SIZE MTIME FILE_NAME MD5SUM? */ + + modes[0] = '-'; /* Only regular files are allowed */ + decode_file_mode(info->sb.st_mode, modes + 1); + + /* File time */ + tm = localtime(&info->sb.st_mtime); + strftime(timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z", tm); + + pw = getpwuid(TRIPLET_UID(trp)); + if (!pw) + user_name = "unknown"; + else + user_name = pw->pw_name; + + grp = getgrgid(TRIPLET_GID(trp)); + if (!grp) + group_name = "unknown"; /* should not happen */ + else + group_name = grp->gr_name; + + /* Size */ + if (grecs_asprintf + (&sptr, &slen, "%lu", (unsigned long)info->sb.st_size)) + grecs_alloc_die(); + + /* Figure out padding and format the buffer */ + slen = strlen(sptr); + pad = strlen(user_name) + 1 + strlen(group_name) + 1 + slen; + if (pad > ugswidth) + ugswidth = pad; + + if (grecs_asprintf(&buf, &size, + "%s %s %s %*s %s %s", + modes, user_name, group_name, ugswidth - pad + slen, + sptr, timebuf, info->name)) + grecs_alloc_die(); + free(sptr); + *pret = buf; + return 0; } static const char * -expand_triplet_ls_full (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL }; - size_t size = 0; - - if (format_file_data (trp, file_dist, &buf[file_dist]) == 0) - size += strlen (buf[file_dist]) + 1; - if (format_file_data (trp, file_signature, &buf[file_signature]) == 0) - size += strlen (buf[file_signature]) + 1; - if (format_file_data (trp, file_directive, &buf[file_directive]) == 0) - size += strlen (buf[file_directive]) + 1; - - def->value = def->storage = grecs_malloc (size + 1); - def->value[0] = 0; - if (buf[file_dist]) - { - strcat (def->value, buf[file_dist]); - strcat (def->value, "\n"); - } - if (buf[file_signature]) - { - strcat (def->value, buf[file_signature]); - strcat (def->value, "\n"); - } - if (buf[file_directive]) - { - strcat (def->value, buf[file_directive]); - strcat (def->value, "\n"); - } - free (buf[file_dist]); - free (buf[file_signature]); - free (buf[file_directive]); - return def->value; +expand_triplet_ls_full(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL }; + size_t size = 0; + + if (format_file_data(trp, file_dist, &buf[file_dist]) == 0) + size += strlen(buf[file_dist]) + 1; + if (format_file_data(trp, file_signature, &buf[file_signature]) == 0) + size += strlen(buf[file_signature]) + 1; + if (format_file_data(trp, file_directive, &buf[file_directive]) == 0) + size += strlen(buf[file_directive]) + 1; + + def->value = def->storage = grecs_malloc(size + 1); + def->value[0] = 0; + if (buf[file_dist]) { + strcat(def->value, buf[file_dist]); + strcat(def->value, "\n"); + } + if (buf[file_signature]) { + strcat(def->value, buf[file_signature]); + strcat(def->value, "\n"); + } + if (buf[file_directive]) { + strcat(def->value, buf[file_directive]); + strcat(def->value, "\n"); + } + free(buf[file_dist]); + free(buf[file_signature]); + free(buf[file_directive]); + return def->value; } static const char * -expand_triplet_ls_upload (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - char *buf[2] = { NULL, NULL }; - size_t size = 0; - - if (format_file_data (trp, file_dist, &buf[file_dist]) == 0) - size += strlen (buf[file_dist]) + 1; - if (format_file_data (trp, file_signature, &buf[file_signature]) == 0) - size += strlen (buf[file_signature]) + 1; - - def->value = def->storage = grecs_malloc (size + 1); - def->value[0] = 0; - if (buf[file_dist]) - { - strcat (def->value, buf[file_dist]); - strcat (def->value, "\n"); - } - if (buf[file_signature]) - { - strcat (def->value, buf[file_signature]); - strcat (def->value, "\n"); - } +expand_triplet_ls_upload(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + char *buf[2] = { NULL, NULL }; + size_t size = 0; + + if (format_file_data(trp, file_dist, &buf[file_dist]) == 0) + size += strlen(buf[file_dist]) + 1; + if (format_file_data(trp, file_signature, &buf[file_signature]) == 0) + size += strlen(buf[file_signature]) + 1; + + def->value = def->storage = grecs_malloc(size + 1); + def->value[0] = 0; + if (buf[file_dist]) { + strcat(def->value, buf[file_dist]); + strcat(def->value, "\n"); + } + if (buf[file_signature]) { + strcat(def->value, buf[file_signature]); + strcat(def->value, "\n"); + } - free (buf[file_dist]); - free (buf[file_signature]); + free(buf[file_dist]); + free(buf[file_signature]); - return def->value; + return def->value; } static const char * -expand_triplet_dist (struct metadef *def, void *data) +expand_triplet_dist(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_dist].name; + struct file_triplet *trp = data; + return trp->file[file_dist].name; } static const char * -expand_triplet_sig (struct metadef *def, void *data) +expand_triplet_sig(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_signature].name; + struct file_triplet *trp = data; + return trp->file[file_signature].name; } static const char * -expand_triplet_dir (struct metadef *def, void *data) +expand_triplet_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_directive].name; + struct file_triplet *trp = data; + return trp->file[file_directive].name; } static const char * -expand_triplet_ls_dist (struct metadef *def, void *data) +expand_triplet_ls_dist(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_dist, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_dist, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_triplet_ls_sig (struct metadef *def, void *data) +expand_triplet_ls_sig(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_signature, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_signature, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_triplet_ls_directive (struct metadef *def, void *data) +expand_triplet_ls_directive(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_directive, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_directive, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_user_name (struct metadef *def, void *data) +expand_user_name(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (trp->uploader) - return trp->uploader->name; - def->value = "UNKNOWN"; - return def->value; + struct file_triplet *trp = data; + if (trp->uploader) + return trp->uploader->name; + def->value = "UNKNOWN"; + return def->value; } static const char * -expand_user_real_name (struct metadef *def, void *data) +expand_user_real_name(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (trp->uploader) - return trp->uploader->realname; - def->value = "UNKNOWN"; - return def->value; + struct file_triplet *trp = data; + if (trp->uploa |