From 4b8a0f3f3dcf60dac2ce308ea08d413a535af29f Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 21:12:14 +0200 Subject: Adding upstream version 5.4.4. Signed-off-by: Daniel Baumann --- changes.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 changes.c (limited to 'changes.c') diff --git a/changes.c b/changes.c new file mode 100644 index 0000000..8b4b5c8 --- /dev/null +++ b/changes.c @@ -0,0 +1,335 @@ +/* This file is part of "reprepro" + * Copyright (C) 2003,2004,2005,2006,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 + +#include +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "names.h" +#include "uncompression.h" +#include "checksums.h" +#include "changes.h" + +retvalue changes_parsefileline(const char *fileline, /*@out@*/filetype *result_type, /*@out@*/char **result_basename, /*@out@*/struct hash_data *hash_p, /*@out@*/struct hash_data *size_p, /*@out@*/char **result_section, /*@out@*/char **result_priority, /*@out@*/architecture_t *result_architecture, /*@out@*/char **result_name) { + + const char *p, *md5start, *md5end; + const char *sizestart, *sizeend; + const char *sectionstart, *sectionend; + const char *priostart, *prioend; + const char *filestart, *nameend, *fileend; + const char *archstart, *archend; + const char *versionstart; + filetype type; + char *section, *priority, *basefilename, *name; + architecture_t architecture; + size_t l; + bool checkfilename = false; + + p = fileline; + while (*p !='\0' && xisspace(*p)) + p++; + md5start = p; + while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f')) + p++; + if (*p == '\0') { + fprintf(stderr, "Missing md5sum in '%s'!\n", fileline); + return RET_ERROR; + } + if (!xisspace(*p)) { + fprintf(stderr, "Malformed md5 hash in '%s'!\n", fileline); + return RET_ERROR; + } + md5end = p; + while (*p !='\0' && xisspace(*p)) + p++; + while (*p == '0' && p[1] >= '0' && p[1] <= '9') + p++; + sizestart = p; + while (*p >= '0' && *p <= '9') + p++; + if (*p == '\0') { + fprintf(stderr, +"Missing size (second argument) in '%s'!\n", fileline); + return RET_ERROR; + } + if (!xisspace(*p)) { + fprintf(stderr, +"Malformed size (second argument) in '%s'!\n", fileline); + return RET_ERROR; + } + sizeend = p; + while (*p !='\0' && xisspace(*p)) + p++; + sectionstart = p; + while (*p !='\0' && !xisspace(*p)) + p++; + sectionend = p; + while (*p !='\0' && xisspace(*p)) + p++; + priostart = p; + while (*p !='\0' && !xisspace(*p)) + p++; + prioend = p; + while (*p !='\0' && xisspace(*p)) + p++; + filestart = p; + while (*p !='\0' && !xisspace(*p)) + p++; + fileend = p; + while (*p !='\0' && xisspace(*p)) + p++; + if (*p != '\0') { + fprintf(stderr, +"Unexpected sixth argument in '%s'!\n", fileline); + return RET_ERROR; + } + if (*md5start == '\0' || *sizestart == '\0' || *sectionstart == '\0' + || *priostart == '\0' || *filestart == '\0') { + fprintf(stderr, +"Wrong number of arguments in '%s' (5 expected)!\n", + fileline); + return RET_ERROR; + } + if ((sectionend - sectionstart == 6 && + strncmp(sectionstart, "byhand", 6) == 0) || + (sectionend - sectionstart > 4 && + strncmp(sectionstart, "raw-", 4) == 0)) { + section = strndup(sectionstart, sectionend - sectionstart); + priority = strndup(priostart, prioend - priostart); + basefilename = strndup(filestart, fileend - filestart); + if (FAILEDTOALLOC(section) || FAILEDTOALLOC(priority) || + FAILEDTOALLOC(basefilename)) { + free(section); free(priority); + free(basefilename); + return RET_ERROR_OOM; + } + hash_p->start = md5start; + hash_p->len = md5end - md5start; + size_p->start = sizestart; + size_p->len = sizeend - sizestart; + *result_section = section; + *result_priority = priority; + *result_basename = basefilename; + *result_architecture = atom_unknown; + *result_name = NULL; + *result_type = fe_BYHAND; + return RET_OK; + } + + p = filestart; + while (*p != '\0' && *p != '_' && !xisspace(*p)) + p++; + if (*p != '_') { + if (*p == '\0') + fprintf(stderr, +"No underscore found in file name in '%s'!\n", + fileline); + else + fprintf(stderr, +"Unexpected character '%c' in file name in '%s'!\n", + *p, fileline); + return RET_ERROR; + } + nameend = p; + p++; + versionstart = p; + + /* changing 3.0 format to now also allow _ in source files + * makes this parsing quite more ugly... */ + + while (*p !='\0' && !xisspace(*p)) + p++; + l = p - versionstart; + + /* identify the binary types (they have no compression + * and will need a _ */ + + if (l >= 4 && memcmp(p-4, ".deb", 4) == 0) + type = fe_DEB; + else if (l >= 5 && memcmp(p-5, ".ddeb", 5) == 0) + type = fe_DDEB; + else if (l >= 5 && memcmp(p-5, ".udeb", 5) == 0) + type = fe_UDEB; + else + type = fe_UNKNOWN; + + if (type != fe_UNKNOWN) { + /* a _ should separate the version from the rest */ + p = versionstart; + names_overversion(&p, true); + if (*p != '\0' && *p != '_') { + fprintf(stderr, +"Unexpected character '%c' in file name within '%s'!\n", *p, fileline); + return RET_ERROR; + } + if (*p != '_') { + fprintf(stderr, +"Cannot cope with .[u]deb filename not containing an underscore (in '%s')!", + fileline); + return RET_ERROR; + } + p++; + archstart = p; + if (type == fe_DEB) + archend = versionstart + l - 4; + else { + assert (type == fe_DDEB || type == fe_UDEB); + archend = versionstart + l - 5; + } + if (archend - archstart == 6 && + strncmp(archstart, "source", 6) == 0) { + fprintf(stderr, +"Architecture 'source' not allowed for .[u]debs ('%s')!\n", filestart); + return RET_ERROR; + } + } else { + enum compression c; + const char *eoi; + bool issignature = false; + + /* without those, it gets more complicated. + * It's not .deb, .ddeb or .udeb, so most likely a + * source file (or perhaps a log (reprepro extension)) */ + + /* if it uses a known compression, things are easy, + * so try this first: */ + + if (l > 4 && memcmp(versionstart + l - 4, ".asc", 4) == 0 ) { + issignature = true; + l -= 4; + } + c = compression_by_suffix(versionstart, &l); + p = versionstart + l; + + archstart = "source"; + archend = archstart + 6; + if (l > 9 && strncmp(p-9, ".orig.tar", 9) == 0) { + type = fe_ORIG; + eoi = p - 9; + } else if (l > 4 && strncmp(p-4, ".tar", 4) == 0) { + type = fe_TAR; + eoi = p - 4; + } else if (issignature) { + /* only .tar.* files are allowed to have .asc files: */ + issignature = false; + } else if (l > 5 && strncmp(p-5, ".diff", 5) == 0) { + type = fe_DIFF; + eoi = p - 5; + } else if (l > 4 && strncmp(p-4, ".dsc", 4) == 0 + && c == c_none) { + type = fe_DSC; + eoi = p - 4; + } else if (l > 4 && strncmp(p-4, ".git", 4) == 0 + && c == c_none) { + type = fe_ALTSRC; + eoi = p - 4; + } else if (l > 4 && strncmp(p-4, ".log", 4) == 0) { + type = fe_LOG; + eoi = p - 4; + } else if (l > 6 && strncmp(p-6, ".build", 6) == 0) { + type = fe_LOG; + eoi = p - 6; + } else if (l > 10 && strncmp(p-10, ".buildinfo", 10) == 0) { + type = fe_BUILDINFO; + eoi = p - 10; + } + if (type != fe_UNKNOWN) { + /* check for a proper version */ + p = versionstart; + names_overversion(&p, true); + if (p >= eoi) { + /* all well */ + } else if (type == fe_TAR) { + /* a tar might be a component with ugly + * data between .orig- and the .tar.c */ + const char *o = strstr(versionstart, ".orig-"); + if (o == NULL || o > eoi) { + fprintf(stderr, +"Unexpected character '%c' in file name within '%s'!\n", + *p, fileline); + return RET_ERROR; + } + checkfilename = true; + } else if (type == fe_LOG || type == fe_BUILDINFO) { + if (*p == '_') { + archstart = p + 1; + archend = eoi; + checkfilename = true; + } else { + fprintf(stderr, +"Unexpected character '%c' in file name within '%s'!\n", + *p, fileline); + } + } else { + fprintf(stderr, +"Unexpected character '%c' in file name within '%s'!\n", + *p, fileline); + return RET_ERROR; + + } + if (issignature) + type = fe_SIG; + } else { + /* everything else is assumed to be source */ + checkfilename = true; + fprintf(stderr, +"Unknown file type: '%s', assuming source format...\n", fileline); + } + } + section = strndup(sectionstart, sectionend - sectionstart); + priority = strndup(priostart, prioend - priostart); + basefilename = strndup(filestart, fileend - filestart); + // TODO: this does not make much sense for log files, as they might + // list multiple.. + architecture = architecture_find_l(archstart, archend - archstart); + name = strndup(filestart, nameend - filestart); + if (FAILEDTOALLOC(section) || FAILEDTOALLOC(priority) || + FAILEDTOALLOC(basefilename) || FAILEDTOALLOC(name)) { + free(section); free(priority); + free(basefilename); free(name); + return RET_ERROR_OOM; + } + if (checkfilename || !atom_defined(architecture)) { + retvalue r; + + /* as we no longer run properversion over the whole + * rest of the string, at least make sure nothing evil + * is in this name */ + r = properfilename(basefilename); + if (!RET_IS_OK(r)) { + assert (r != RET_NOTHING); + free(section); free(priority); + free(basefilename); free(name); + return r; + } + } + hash_p->start = md5start; + hash_p->len = md5end - md5start; + size_p->start = sizestart; + size_p->len = sizeend - sizestart; + *result_section = section; + *result_priority = priority; + *result_basename = basefilename; + *result_architecture = architecture; + *result_name = name; + *result_type = type; + return RET_OK; +} -- cgit v1.2.3