From: Michael Tremer Date: Sat, 30 Jan 2021 16:24:46 +0000 (+0000) Subject: libpakfire: scriptlets: Move them into an own data structure X-Git-Tag: 0.9.28~1285^2~799 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=101264c8ad38e3ed097546c0ff963200c2b06804;p=pakfire.git libpakfire: scriptlets: Move them into an own data structure We deal with scriptlets in several places and carrying them around as loose pointers to some data is not very comfortable. Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 02d1e4c90..4056f3844 100644 --- a/Makefile.am +++ b/Makefile.am @@ -286,6 +286,7 @@ libpakfire_la_SOURCES = \ src/libpakfire/relationlist.c \ src/libpakfire/repo.c \ src/libpakfire/request.c \ + src/libpakfire/scriptlet.c \ src/libpakfire/selector.c \ src/libpakfire/solution.c \ src/libpakfire/step.c \ @@ -315,6 +316,7 @@ pkginclude_HEADERS += \ src/libpakfire/include/pakfire/relationlist.h \ src/libpakfire/include/pakfire/repo.h \ src/libpakfire/include/pakfire/request.h \ + src/libpakfire/include/pakfire/scriptlet.h \ src/libpakfire/include/pakfire/selector.h \ src/libpakfire/include/pakfire/solution.h \ src/libpakfire/include/pakfire/step.h \ diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 6ad230156..a0dce3f36 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #define BLOCKSIZE 1024 * 1024 // 1MB @@ -76,6 +77,10 @@ struct _PakfireArchive { PakfireArchiveSignature* signatures; int signatures_loaded; + // Scriptlets + struct pakfire_scriptlet** scriptlets; + size_t nscriptlets; + int nrefs; }; @@ -354,6 +359,13 @@ static void pakfire_archive_free(PakfireArchive archive) { pakfire_free(archive->signatures); } + // Free scriptlets + if (archive->scriptlets) { + for (unsigned int i = 0; i < archive->nscriptlets; i++) + pakfire_scriptlet_free(archive->scriptlets[i]); + free(archive->scriptlets); + } + pakfire_parser_unref(archive->parser); pakfire_unref(archive->pakfire); pakfire_free(archive); @@ -493,6 +505,34 @@ static int pakfire_archive_parse_entry_checksums(PakfireArchive archive, return 0; } +static int pakfire_archive_parse_entry_scriptlet(PakfireArchive archive, + struct archive* a, struct archive_entry* e, const char* filename) { + // Allocate a scriptlet + struct pakfire_scriptlet* scriptlet = pakfire_scriptlet_create(archive->pakfire); + if (!scriptlet) + return -ENOMEM; + + // Set the type + scriptlet->type = pakfire_scriptlet_type_from_filename(filename); + + int r = archive_read(a, &scriptlet->data, &scriptlet->size); + if (r) + return r; + + // Make space for the new scriptlet + archive->scriptlets = realloc(archive->scriptlets, + sizeof(*archive->scriptlets) * (archive->nscriptlets + 1)); + if (archive->scriptlets) { + pakfire_scriptlet_free(scriptlet); + return -ENOMEM; + } + + // Append the new scriptlet + archive->scriptlets[archive->nscriptlets++] = scriptlet; + + return 0; +} + static int pakfire_archive_walk(PakfireArchive archive, int (*callback)(PakfireArchive archive, struct archive* a, struct archive_entry* e, const char* pathname)) { struct archive_entry* e; @@ -557,6 +597,12 @@ static int pakfire_archive_read_metadata_entry(PakfireArchive archive, struct ar ret = pakfire_archive_parse_entry_checksums(archive, a, e); if (ret) return PAKFIRE_E_PKG_INVALID; + + // Parse the scriptlets + } else if (pakfire_string_startswith(entry_name, "scriptlet/")) { + ret = pakfire_archive_parse_entry_scriptlet(archive, a, e, entry_name); + if (ret) + return PAKFIRE_E_PKG_INVALID; } } @@ -1383,3 +1429,17 @@ PAKFIRE_EXPORT PakfirePackage pakfire_archive_make_package(PakfireArchive archiv return pkg; } + +struct pakfire_scriptlet* pakfire_archive_get_scriptlet( + PakfireArchive archive, pakfire_scriptlet_type type) { + struct pakfire_scriptlet* scriptlet; + + for (unsigned int i = 0; i < archive->nscriptlets; i++) { + scriptlet = archive->scriptlets[i]; + + if (scriptlet->type == type) + return scriptlet; + } + + return NULL; +} diff --git a/src/libpakfire/include/pakfire/archive.h b/src/libpakfire/include/pakfire/archive.h index a2283b8e0..90e966b82 100644 --- a/src/libpakfire/include/pakfire/archive.h +++ b/src/libpakfire/include/pakfire/archive.h @@ -23,6 +23,7 @@ #include +#include #include typedef enum pakfire_archive_verify_status { @@ -82,6 +83,9 @@ PakfirePackage pakfire_archive_make_package(PakfireArchive archive, PakfireRepo #ifdef PAKFIRE_PRIVATE +struct pakfire_scriptlet* pakfire_archive_get_scriptlet( + PakfireArchive archive, pakfire_scriptlet_type type); + typedef enum archive_checksum_algo { PAKFIRE_CHECKSUM_UNKNOWN = 0, PAKFIRE_CHECKSUM_SHA512, diff --git a/src/libpakfire/include/pakfire/scriptlet.h b/src/libpakfire/include/pakfire/scriptlet.h new file mode 100644 index 000000000..75cf8c1ac --- /dev/null +++ b/src/libpakfire/include/pakfire/scriptlet.h @@ -0,0 +1,59 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2021 Pakfire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +# # +#############################################################################*/ + +#ifndef PAKFIRE_SCRIPTLET_H +#define PAKFIRE_SCRIPTLET_H + +// This is an internal data structure + +#ifdef PAKFIRE_PRIVATE + +#include + +typedef enum _pakfire_script_types { + PAKFIRE_SCRIPTLET_UNDEFINED = 0, + PAKFIRE_SCRIPTLET_PREIN, + PAKFIRE_SCRIPTLET_PREUN, + PAKFIRE_SCRIPTLET_PREUP, + PAKFIRE_SCRIPTLET_PRETRANSIN, + PAKFIRE_SCRIPTLET_PRETRANSUN, + PAKFIRE_SCRIPTLET_PRETRANSUP, + PAKFIRE_SCRIPTLET_POSTIN, + PAKFIRE_SCRIPTLET_POSTUN, + PAKFIRE_SCRIPTLET_POSTUP, + PAKFIRE_SCRIPTLET_POSTTRANSIN, + PAKFIRE_SCRIPTLET_POSTTRANSUN, + PAKFIRE_SCRIPTLET_POSTTRANSUP, +} pakfire_scriptlet_type; + +struct pakfire_scriptlet { + pakfire_scriptlet_type type; + void* data; + size_t size; +}; + +struct pakfire_scriptlet* pakfire_scriptlet_create(Pakfire pakfire); +void pakfire_scriptlet_free(struct pakfire_scriptlet* scriptlet); + +pakfire_scriptlet_type pakfire_scriptlet_type_from_filename(const char* filename); + +#endif + +#endif /* PAKFIRE_SCRIPTLET_H */ diff --git a/src/libpakfire/include/pakfire/step.h b/src/libpakfire/include/pakfire/step.h index 433906735..bc588d5b3 100644 --- a/src/libpakfire/include/pakfire/step.h +++ b/src/libpakfire/include/pakfire/step.h @@ -41,21 +41,6 @@ int pakfire_step_needs_download(PakfireStep step); #include -typedef enum _pakfire_script_types { - PAKFIRE_SCRIPT_PREIN, - PAKFIRE_SCRIPT_PREUN, - PAKFIRE_SCRIPT_PREUP, - PAKFIRE_SCRIPT_PRETRANSIN, - PAKFIRE_SCRIPT_PRETRANSUN, - PAKFIRE_SCRIPT_PRETRANSUP, - PAKFIRE_SCRIPT_POSTIN, - PAKFIRE_SCRIPT_POSTUN, - PAKFIRE_SCRIPT_POSTUP, - PAKFIRE_SCRIPT_POSTTRANSIN, - PAKFIRE_SCRIPT_POSTTRANSUN, - PAKFIRE_SCRIPT_POSTTRANSUP, -} pakfire_script_type; - int pakfire_step_run(PakfireStep step, struct pakfire_db* db, pakfire_action_type_t action); #endif diff --git a/src/libpakfire/scriptlet.c b/src/libpakfire/scriptlet.c new file mode 100644 index 000000000..a26704e8f --- /dev/null +++ b/src/libpakfire/scriptlet.c @@ -0,0 +1,120 @@ +/*############################################################################# +# # +# Pakfire - The IPFire package management system # +# Copyright (C) 2021 Pakfire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +# # +#############################################################################*/ + +#include +#include + +#include +#include + +struct pakfire_scriptlet* pakfire_scriptlet_create(Pakfire pakfire) { + struct pakfire_scriptlet* scriptlet = calloc(1, sizeof(*scriptlet)); + if (!scriptlet) + return NULL; + + return scriptlet; +}; + +void pakfire_scriptlet_free(struct pakfire_scriptlet* scriptlet) { + if (scriptlet->data) + free(scriptlet->data); +} + +pakfire_scriptlet_type pakfire_scriptlet_type_from_filename(const char* filename) { + if (strcmp(filename, "scriptlets/prein") == 0) + return PAKFIRE_SCRIPTLET_PREIN; + + else if (strcmp(filename, "scriptlets/preun") == 0) + return PAKFIRE_SCRIPTLET_PREUN; + + else if (strcmp(filename, "scriptlets/preup") == 0) + return PAKFIRE_SCRIPTLET_PREUP; + + else if (strcmp(filename, "scriptlets/postin") == 0) + return PAKFIRE_SCRIPTLET_POSTIN; + + else if (strcmp(filename, "scriptlets/postun") == 0) + return PAKFIRE_SCRIPTLET_POSTUN; + + else if (strcmp(filename, "scriptlets/postup") == 0) + return PAKFIRE_SCRIPTLET_POSTUP; + + else if (strcmp(filename, "scriptlets/pretransin") == 0) + return PAKFIRE_SCRIPTLET_PRETRANSIN; + + else if (strcmp(filename, "scriptlets/pretransun") == 0) + return PAKFIRE_SCRIPTLET_PRETRANSUN; + + else if (strcmp(filename, "scriptlets/pretransup") == 0) + return PAKFIRE_SCRIPTLET_PRETRANSUP; + + else if (strcmp(filename, "scriptlets/posttransin") == 0) + return PAKFIRE_SCRIPTLET_POSTTRANSIN; + + else if (strcmp(filename, "scriptlets/posttransun") == 0) + return PAKFIRE_SCRIPTLET_POSTTRANSUN; + + else if (strcmp(filename, "scriptlets/posttransup") == 0) + return PAKFIRE_SCRIPTLET_POSTTRANSUP; + + return PAKFIRE_SCRIPTLET_UNDEFINED; +} + +static const char* pakfire_step_script_filename(pakfire_scriptlet_type script) { + switch (script) { + case PAKFIRE_SCRIPTLET_PREIN: + return "scriptlets/prein"; + + case PAKFIRE_SCRIPTLET_PREUN: + return "scriptlets/preun"; + + case PAKFIRE_SCRIPTLET_PREUP: + return "scriptlets/preup"; + + case PAKFIRE_SCRIPTLET_PRETRANSIN: + return "scriptlets/pretansin"; + + case PAKFIRE_SCRIPTLET_PRETRANSUN: + return "scriptlets/pretransun"; + + case PAKFIRE_SCRIPTLET_PRETRANSUP: + return "scriptlets/pretransup"; + + case PAKFIRE_SCRIPTLET_POSTIN: + return "scriptlets/postin"; + + case PAKFIRE_SCRIPTLET_POSTUN: + return "scriptlets/postun"; + + case PAKFIRE_SCRIPTLET_POSTUP: + return "scriptlets/postup"; + + case PAKFIRE_SCRIPTLET_POSTTRANSIN: + return "scriptlets/posttransin"; + + case PAKFIRE_SCRIPTLET_POSTTRANSUN: + return "scriptlets/posttransun"; + + case PAKFIRE_SCRIPTLET_POSTTRANSUP: + return "scriptlets/posttransup"; + } + + return NULL; +} diff --git a/src/libpakfire/step.c b/src/libpakfire/step.c index ef2519de8..03edf5ec6 100644 --- a/src/libpakfire/step.c +++ b/src/libpakfire/step.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -47,48 +48,6 @@ struct _PakfireStep { int nrefs; }; -static const char* pakfire_step_script_filename(pakfire_script_type script) { - switch (script) { - case PAKFIRE_SCRIPT_PREIN: - return "scriptlets/prein"; - - case PAKFIRE_SCRIPT_PREUN: - return "scriptlets/preun"; - - case PAKFIRE_SCRIPT_PREUP: - return "scriptlets/preup"; - - case PAKFIRE_SCRIPT_PRETRANSIN: - return "scriptlets/pretansin"; - - case PAKFIRE_SCRIPT_PRETRANSUN: - return "scriptlets/pretransun"; - - case PAKFIRE_SCRIPT_PRETRANSUP: - return "scriptlets/pretransup"; - - case PAKFIRE_SCRIPT_POSTIN: - return "scriptlets/postin"; - - case PAKFIRE_SCRIPT_POSTUN: - return "scriptlets/postun"; - - case PAKFIRE_SCRIPT_POSTUP: - return "scriptlets/postup"; - - case PAKFIRE_SCRIPT_POSTTRANSIN: - return "scriptlets/posttransin"; - - case PAKFIRE_SCRIPT_POSTTRANSUN: - return "scriptlets/posttransun"; - - case PAKFIRE_SCRIPT_POSTTRANSUP: - return "scriptlets/posttransup"; - } - - return NULL; -} - PAKFIRE_EXPORT PakfireStep pakfire_step_create(PakfireTransaction transaction, pakfire_step_type_t type, PakfirePackage pkg) { Pakfire pakfire = pakfire_transaction_get_pakfire(transaction); @@ -260,21 +219,21 @@ static int pakfire_step_verify(PakfireStep step) { return status; } -static int pakfire_script_check_shell(const char* data, const size_t size) { +static int pakfire_script_check_shell(struct pakfire_scriptlet* scriptlet) { const char* interpreter = "#!/bin/sh"; // data must be long enough - if (size <= strlen(interpreter)) + if (scriptlet->size <= strlen(interpreter)) return 0; // If the string begins with the interpreter, this is a match - if (strncmp(data, interpreter, strlen(interpreter)) == 0) + if (strncmp(scriptlet->data, interpreter, strlen(interpreter)) == 0) return 1; return 0; } -static int pakfire_step_run_shell_script(PakfireStep step, const char* data, const size_t size) { +static int pakfire_step_run_shell_script(PakfireStep step, struct pakfire_scriptlet* scriptlet) { const char* root = pakfire_get_path(step->pakfire); // Write the scriptlet to disk @@ -293,8 +252,8 @@ static int pakfire_step_run_shell_script(PakfireStep step, const char* data, con } // Write data - ssize_t bytes_written = write(fd, data, size); - if (bytes_written < (ssize_t)size) { + ssize_t bytes_written = write(fd, scriptlet->data, scriptlet->size); + if (bytes_written < (ssize_t)scriptlet->size) { ERROR(step->pakfire, "Could not write script to file %s: %s\n", path, strerror(errno)); @@ -342,37 +301,23 @@ out: return r; } -static int pakfire_step_run_script(PakfireStep step, pakfire_script_type script) { - const char* script_filename = pakfire_step_script_filename(script); - - DEBUG(step->pakfire, "Looking for script %s\n", script_filename); - - void* data; - size_t size; - - // Read script from archive - int r = pakfire_archive_read(step->archive, script_filename, &data, &size, 0); - if (r == 1) { - DEBUG(step->pakfire, "Could not find script %s\n", script_filename); +static int pakfire_step_run_script(PakfireStep step, pakfire_scriptlet_type type) { + // Fetch scriptlet from archive + struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(step->archive, type); + if (!scriptlet) return 0; - } // Found a script! - DEBUG(step->pakfire, "Found script %s (%zu):\n%.*s", - script_filename, size, (int)size, (const char*)data); - - r = 0; + DEBUG(step->pakfire, "Found scriptlet:\n%.*s", + (int)scriptlet->size, (const char*)scriptlet->data); // Detect what kind of script this is and run it - if (pakfire_script_check_shell(data, size)) { - r = pakfire_step_run_shell_script(step, data, size); + if (pakfire_script_check_shell(scriptlet)) { + pakfire_step_run_shell_script(step, scriptlet); } else { - ERROR(step->pakfire, "Script is of an unknown kind\n"); + ERROR(step->pakfire, "Scriptlet is of an unknown kind\n"); } - // Cleanup - pakfire_free(data); - return 0; } @@ -437,17 +382,17 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, switch (type) { case PAKFIRE_STEP_INSTALL: case PAKFIRE_STEP_REINSTALL: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PRETRANSIN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PRETRANSIN); break; case PAKFIRE_STEP_UPGRADE: case PAKFIRE_STEP_DOWNGRADE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PRETRANSUP); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PRETRANSUP); break; case PAKFIRE_STEP_ERASE: case PAKFIRE_STEP_OBSOLETE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PRETRANSUN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PRETRANSUN); break; case PAKFIRE_STEP_IGNORE: @@ -460,17 +405,17 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, switch (type) { case PAKFIRE_STEP_INSTALL: case PAKFIRE_STEP_REINSTALL: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTTRANSIN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTTRANSIN); break; case PAKFIRE_STEP_UPGRADE: case PAKFIRE_STEP_DOWNGRADE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTTRANSUP); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTTRANSUP); break; case PAKFIRE_STEP_ERASE: case PAKFIRE_STEP_OBSOLETE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTTRANSUN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTTRANSUN); break; case PAKFIRE_STEP_IGNORE: @@ -483,7 +428,7 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, switch (type) { case PAKFIRE_STEP_INSTALL: case PAKFIRE_STEP_REINSTALL: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PREIN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PREIN); if (r) break; @@ -495,12 +440,12 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, if (r) break; - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTIN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTIN); break; case PAKFIRE_STEP_UPGRADE: case PAKFIRE_STEP_DOWNGRADE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PREUP); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PREUP); if (r) break; @@ -512,12 +457,12 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, if (r) break; - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTUP); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTUP); break; case PAKFIRE_STEP_ERASE: case PAKFIRE_STEP_OBSOLETE: - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_PREUN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_PREUN); if (r) break; @@ -529,7 +474,7 @@ PAKFIRE_EXPORT int pakfire_step_run(PakfireStep step, if (r) break; - r = pakfire_step_run_script(step, PAKFIRE_SCRIPT_POSTUN); + r = pakfire_step_run_script(step, PAKFIRE_SCRIPTLET_POSTUN); break; case PAKFIRE_STEP_IGNORE: