diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-07-19 15:16:16 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-07-19 15:16:16 +0300 |
commit | dd9d9c1240774e21c7eb50052225ff1e4cc376ee (patch) | |
tree | a06490ee30ab5bee2e707ffd6f0ab07a4e4ebd60 | |
parent | af538cc27228edf816edea1bf52c84b5bb4f8720 (diff) | |
download | wydawca-dd9d9c1240774e21c7eb50052225ff1e4cc376ee.tar.gz wydawca-dd9d9c1240774e21c7eb50052225ff1e4cc376ee.tar.bz2 |
Create destination directories if necessary
* src/config.c (spool_kw): New statements: destination-mode and
destination-owner. See the description of the similar source-*
statements in the previous commit.
* src/diskio.c (create_hierarchy): First argument is const.
* src/vtab.c (wy_url) <local>: New member.
(wy_url_is_local): New function.
* src/wydawca.h (spool) <dest_metadata>: New member.
(create_hierarchy): Change signature.
-rw-r--r-- | src/config.c | 83 | ||||
-rw-r--r-- | src/diskio.c | 2 | ||||
-rw-r--r-- | src/vtab.c | 9 | ||||
-rw-r--r-- | src/wydawca.h | 4 |
4 files changed, 65 insertions, 33 deletions
diff --git a/src/config.c b/src/config.c index eb5f7f5..ca0d750 100644 --- a/src/config.c +++ b/src/config.c @@ -1135,12 +1135,24 @@ static struct grecs_keyword spool_kw[] = { NULL, offsetof(struct spool, source_metadata), cb_metadata_owner }, { "destination", N_("dir"), N_("Destination directory"), grecs_type_string, GRECS_CONST, NULL, offsetof(struct spool, dest_url), cb_url }, + { "destination-mode", + N_("mode: octal"), + N_("mode for the destination directory (if local)"), + grecs_type_string, GRECS_CONST, + NULL, offsetof(struct spool, dest_metadata), + cb_metadata_mode }, + { "destination-owner", + N_("uid: name-or-uid> <gid: name-or-gid"), + N_("owner user and group for the destination directory (if local)"), + grecs_type_string, GRECS_CONST, + NULL, offsetof(struct spool, dest_metadata), + cb_metadata_owner }, { "file-sweep-time", N_("interval"), N_("Define file sweep time"), grecs_type_string, GRECS_CONST, NULL, offsetof(struct spool, file_sweep_time), cb_interval }, { "inotify", NULL, N_("Enable or disable inotify for this spool"), grecs_type_bool, GRECS_DFLT, @@ -1549,61 +1561,70 @@ config_init() for (i = 0; i < dictionary_count; i++) default_dictionary[i] = dictionary_new(i, dictionary_builtin); } static int -create_source(struct spool *spool, void *data) +create_spool_dir(struct spool *spool, char const *dir, + struct directory_metadata *meta, + char const *descr) { struct stat st; int rc; - if ((rc = stat(spool->source_dir, &st)) != 0) { + if ((rc = stat(dir, &st)) != 0) { if (errno != ENOENT) { - grecs_error(NULL, errno, _("%s: cannot stat %s"), - spool->tag, spool->source_dir); - *(int*)data = 1; - return 0; + grecs_error(NULL, errno, _("%s: cannot stat %s %s"), + spool->tag, descr, dir); + return 1; } else { - wy_debug(1, (_("creating spool source directory %s"), - spool->source_dir)); - if (create_hierarchy(spool->source_dir, 0)) { - *(int*)data = 1; - return 0; + wy_debug(1, (_("%s: creating %s"), spool->tag, descr)); + if (create_hierarchy(dir, 0)) { + return 1; } } } else if (!S_ISDIR(st.st_mode)) { grecs_error(NULL, errno, _("%s: %s is not a directory"), - spool->tag, spool->source_dir); - *(int*)data = 1; - return 0; + spool->tag, dir); + return 1; } - if ((spool->source_metadata.flags & METADATA_OWNER) + if ((meta->flags & METADATA_OWNER) && (rc - || st.st_uid != spool->source_metadata.uid - || st.st_gid != spool->source_metadata.gid) - && chown(spool->source_dir, - spool->source_metadata.uid, - spool->source_metadata.gid)) { - grecs_error(NULL, errno, _("%s: can't chown %s"), - spool->tag, spool->source_dir); - *(int*)data = 1; - return 0; + || st.st_uid != meta->uid + || st.st_gid != meta->gid) + && chown(dir, meta->uid, meta->gid)) { + grecs_error(NULL, errno, _("%s: can't chown %s %s"), + spool->tag, descr, dir); + return 1; } - if ((spool->source_metadata.flags & METADATA_MODE) - && (rc || (st.st_mode & 07777) != spool->source_metadata.mode) - && chmod(spool->source_dir, spool->source_metadata.mode)) { - grecs_error(NULL, errno, _("%s: can't chmod %s"), - spool->tag, spool->source_dir); - *(int*)data = 1; + if ((meta->flags & METADATA_MODE) + && (rc || (st.st_mode & 07777) != meta->mode) + && chmod(dir, meta->mode)) { + grecs_error(NULL, errno, _("%s: can't chmod %s %s"), + spool->tag, descr, dir); + return 1; } return 0; } +static int +create_spool_dirs(struct spool *spool, void *data) +{ + if (create_spool_dir(spool, spool->source_dir, &spool->source_metadata, + _("source directory"))) + *(int*)data = 1; + if (!wy_url_is_local(spool->dest_url) + && create_spool_dir(spool, spool->dest_dir, + &spool->dest_metadata, + _("destination directory"))) + *(int*)data = 1; + return 0; +} + void config_finish(struct grecs_node *tree) { struct grecs_node *p; int err; @@ -1619,9 +1640,9 @@ config_finish(struct grecs_node *tree) grecs_error(&p->v.value->locus, 0, _("unknown module")); } } err = 0; - if (for_each_spool(create_source, &err) || err) + if (for_each_spool(create_spool_dirs, &err) || err) exit(EX_CONFIG); } diff --git a/src/diskio.c b/src/diskio.c index 1d072d4..6bed916 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -56,13 +56,13 @@ concat_dir(const char *base, const char *name, size_t * pbaselen) return dir; } /* Create the directory DIR, eventually creating all intermediate directories starting from DIR + BASELEN. */ int -create_hierarchy(char *dir, size_t baselen) +create_hierarchy(char const *dir, size_t baselen) { int rc; struct stat st; char *p; if (stat(dir, &st) == 0) { @@ -18,24 +18,26 @@ #include "wydawca.h" struct wy_url { char *printable; char *scheme; char *path; + int local:1; }; wy_url_t wy_url_create(const char *str) { wy_url_t url; url = grecs_zalloc(sizeof(url[0])); url->printable = grecs_strdup(str); if (*str == '/') { url->scheme = grecs_strdup("file"); url->path = grecs_strdup(str); + url->local = 1; } else { size_t len = strcspn(str, ":"); if (!str[len]) { wy_url_free(url); errno = EINVAL; return NULL; @@ -47,12 +49,13 @@ wy_url_create(const char *str) if (str[len + 1] && strncmp(str + len + 1, "//", 2) == 0) len += 2; if (str[len + 1]) url->path = grecs_strdup(str + len + 1); else url->path = NULL; + url->local = 0; } return url; } void wy_url_free(wy_url_t url) @@ -78,12 +81,18 @@ wy_url_scheme(wy_url_t url) const char * wy_url_printable(wy_url_t url) { return url->printable; } +int +wy_url_is_local(wy_url_t url) +{ + return url && url->local; +} + struct virt_tab_reg { char *scheme; struct virt_tab vtab; }; diff --git a/src/wydawca.h b/src/wydawca.h index 1001694..cfd3ae2 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -201,12 +201,13 @@ typedef struct wy_url *wy_url_t; wy_url_t wy_url_create(const char *str); void wy_url_free(wy_url_t url); const char *wy_url_path(wy_url_t url); const char *wy_url_scheme(wy_url_t url); const char *wy_url_printable(wy_url_t url); +int wy_url_is_local(wy_url_t url); struct virt_tab { int (*test_url) (wy_url_t url, grecs_locus_t * loc); int (*move_file) (struct wy_triplet * trp, enum file_type file_id); int (*archive_file) (struct wy_triplet * trp, const char *file_name); int (*symlink_file) (struct wy_triplet * trp, @@ -233,12 +234,13 @@ struct spool { struct grecs_list *aliases; char *url; /* Download URL */ char *source_dir; /* Source directory */ struct directory_metadata source_metadata; wy_url_t dest_url; /* Destination URL */ const char *dest_dir; /* Directory part of the above */ + struct directory_metadata dest_metadata; 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]; @@ -395,13 +397,13 @@ char *safe_file_name(char *file_name); char *safe_file_name_alloc(const char *file_name); size_t trim_length(const char *str); size_t trim(char *str); int test_dir(const char *name, int *ec); char *create_directory(const char *base, const char *name); -int create_hierarchy(char *dir, size_t baselen); +int create_hierarchy(char const *dir, size_t baselen); void parse_config(void); void log_output(int prio, const char *prog, FILE * fp); enum exec_result { exec_success, /* Command executed and returned 0 */ exec_fail, /* Command executed and returned not 0 */ |