diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:12:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:12:14 +0000 |
commit | 4b8a0f3f3dcf60dac2ce308ea08d413a535af29f (patch) | |
tree | 0f09c0ad2a4d0f535d89040a63dc3a866a6606e6 /donefile.c | |
parent | Initial commit. (diff) | |
download | reprepro-4b8a0f3f3dcf60dac2ce308ea08d413a535af29f.tar.xz reprepro-4b8a0f3f3dcf60dac2ce308ea08d413a535af29f.zip |
Adding upstream version 5.4.4.upstream/5.4.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'donefile.c')
-rw-r--r-- | donefile.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/donefile.c b/donefile.c new file mode 100644 index 0000000..bea1e62 --- /dev/null +++ b/donefile.c @@ -0,0 +1,242 @@ +/* This file is part of "reprepro" + * Copyright (C) 2008 Bernhard R. Link + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301 USA + */ +#include <config.h> + +#include <assert.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "donefile.h" +#include "names.h" +#include "checksums.h" +#include "remoterepository.h" + +/* This stores what an distribution that is updated from remote repositories + * has already processed, so that things already processed do not have to be + * downloaded or processed again. */ + +struct markdonefile { + char *finalfilename; + char *tempfilename; + FILE *file; +}; + + +static inline char *donefilename(const char *codename) { + return genlistsfilename("lastseen", 2, "", codename, NULL); +} + +retvalue markdone_create(const char *codename, struct markdonefile **done_p) { + struct markdonefile *done; + + done = NEW(struct markdonefile); + if (FAILEDTOALLOC(done)) + return RET_ERROR_OOM; + done->finalfilename = donefilename(codename); + if (FAILEDTOALLOC(done->finalfilename)) { + free(done); + return RET_ERROR_OOM; + } + done->tempfilename = calc_addsuffix(done->finalfilename, "new"); + if (FAILEDTOALLOC(done->tempfilename)) { + free(done->finalfilename); + free(done); + return RET_ERROR_OOM; + } + done->file = fopen(done->tempfilename, "w+"); + if (done->file == NULL) { + int e = errno; + fprintf(stderr, "Error %d creating '%s': %s\n", + e, done->tempfilename, strerror(e)); + free(done->finalfilename); + free(done->tempfilename); + free(done); + return RET_ERROR; + } + fprintf(done->file, "Updates already processed for %s:\n", codename); + *done_p = done; + return RET_OK; +} + +void markdone_finish(struct markdonefile *done) { + bool error = false; + + if (done == NULL) + return; + if (done->file == NULL) + error = true; + else { + if (ferror(done->file) != 0) { + fprintf(stderr, "An error occurred writing to '%s'!\n", + done->tempfilename); + (void)fclose(done->file); + error = true; + } else if (fclose(done->file) != 0) { + int e = errno; + fprintf(stderr, +"Error %d occurred writing to '%s': %s!\n", + e, done->tempfilename, strerror(e)); + error = true; + } + done->file = NULL; + } + if (error) + (void)unlink(done->tempfilename); + else { + int i; + + i = rename(done->tempfilename, done->finalfilename); + if (i != 0) { + int e = errno; + fprintf(stderr, "Error %d moving '%s' to '%s': %s!\n", + e, done->tempfilename, + done->finalfilename, strerror(e)); + } + } + free(done->finalfilename); + free(done->tempfilename); + free(done); +} + +void markdone_target(struct markdonefile *done, const char *identifier) { + fprintf(done->file, "Target %s\n", identifier); +} + +void markdone_index(struct markdonefile *done, const char *file, const struct checksums *checksums) { + retvalue r; + size_t s; + const char *data; + + r = checksums_getcombined(checksums, &data, &s); + if (!RET_IS_OK(r)) + return; + fprintf(done->file, "Index %s %s\n", file, data); +} + +void markdone_cleaner(struct markdonefile *done) { + fprintf(done->file, "Delete\n"); +} + +/* the same for reading */ + +struct donefile { + char *filename; + char *linebuffer; + size_t linebuffer_size; + FILE *file; +}; + +retvalue donefile_open(const char *codename, struct donefile **done_p) { + struct donefile *done; + ssize_t s; + + done = zNEW(struct donefile); + if (FAILEDTOALLOC(done)) + return RET_ERROR_OOM; + + done->filename = donefilename(codename); + if (FAILEDTOALLOC(done->filename)) { + free(done); + return RET_ERROR_OOM; + } + + done->file = fopen(done->filename, "r"); + if (done->file == NULL) { + donefile_close(done); + return RET_NOTHING; + } + s = getline(&done->linebuffer, &done->linebuffer_size, done->file); + if (s <= 0 || done->linebuffer[s-1] != '\n') { + /* if it cannot be read or is empty or not a text file, + * delete it, and do as if it never existed... */ + unlink(done->filename); + donefile_close(done); + return RET_NOTHING; + } + done->linebuffer[s-1] = '\0'; + // TODO: check the first line? + *done_p = done; + return RET_OK; +} + +void donefile_close(struct donefile *done) { + if (done == NULL) + return; + // TODO: check return, only print a warning, though, + // no need to interrupt anything. + if (done->file != NULL) + fclose(done->file); + free(done->linebuffer); + free(done->filename); + free(done); +} + +retvalue donefile_nexttarget(struct donefile *done, const char **identifier_p) { + ssize_t s; + + while (strncmp(done->linebuffer, "Target ", 7) != 0) { + s = getline(&done->linebuffer, &done->linebuffer_size, + done->file); + if (s <= 0 || done->linebuffer[s-1] != '\n') + /* Malformed line, ignore the rest... */ + return RET_NOTHING; + done->linebuffer[s-1] = '\0'; + } + /* do not process a second time */ + done->linebuffer[0] = '\0'; + /* and return the identifier part */ + *identifier_p = done->linebuffer + 7; + return RET_OK; +} + +bool donefile_nextindex(struct donefile *done, const char **filename_p, struct checksums **checksums_p) { + char *p; + ssize_t s; + retvalue r; + + s = getline(&done->linebuffer, &done->linebuffer_size, done->file); + if (s <= 0 || done->linebuffer[s-1] != '\n') { + done->linebuffer[0] = '\0'; + return false; + } + done->linebuffer[s-1] = '\0'; + if (strncmp(done->linebuffer, "Index ", 6) != 0) + return false; + p = done->linebuffer + 6; + *filename_p = p; + p = strchr(p, ' '); + if (p == NULL) + return false; + *(p++) = '\0'; + r = checksums_parse(checksums_p, p); + return RET_IS_OK(r); +} + +bool donefile_iscleaner(struct donefile *done) { + ssize_t s; + + s = getline(&done->linebuffer, &done->linebuffer_size, done->file); + if (s <= 0 || done->linebuffer[s-1] != '\n') { + done->linebuffer[0] = '\0'; + return false; + } + done->linebuffer[s-1] = '\0'; + return strcmp(done->linebuffer, "Delete") == 0; +} |