// Free scriptlets
if (archive->scriptlets) {
for (unsigned int i = 0; i < archive->nscriptlets; i++)
- pakfire_scriptlet_free(archive->scriptlets[i]);
+ pakfire_scriptlet_unref(archive->scriptlets[i]);
free(archive->scriptlets);
}
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, NULL, 0);
- if (!scriptlet)
- return -ENOMEM;
+ struct pakfire_scriptlet* scriptlet;
+ char* data = NULL;
+ size_t size = 0;
+ int r;
- // Set the type
- scriptlet->type = pakfire_scriptlet_type_from_filename(filename);
+ // Check if the filename matches
+ if (!pakfire_string_startswith(filename, "scriptlet/")) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ const char* type = filename + strlen("scriptlet/");
- int r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, e,
- &scriptlet->data, &scriptlet->size);
+ // Fetch scriptlet
+ r = pakfire_archive_copy_data_to_buffer(archive->pakfire, a, e, &data, &size);
if (r)
return r;
+ // Allocate a scriptlet
+ r = pakfire_scriptlet_create(&scriptlet, archive->pakfire, type, data, size);
+ if (r)
+ goto ERROR;
+
// Make space for the new scriptlet
- archive->scriptlets = realloc(archive->scriptlets,
- sizeof(*archive->scriptlets) * (archive->nscriptlets + 1));
+ archive->scriptlets = reallocarray(archive->scriptlets, archive->nscriptlets + 1,
+ sizeof(*archive->scriptlets));
if (!archive->scriptlets) {
- pakfire_scriptlet_free(scriptlet);
- return -ENOMEM;
+ pakfire_scriptlet_unref(scriptlet);
+ r = 1;
+ goto ERROR;
}
// Append the new scriptlet
archive->scriptlets[archive->nscriptlets++] = scriptlet;
- return 0;
+ERROR:
+ if (data)
+ free(data);
+
+ return r;
}
static int pakfire_archive_walk_entries(PakfireArchive archive, struct archive* a,
}
struct pakfire_scriptlet* pakfire_archive_get_scriptlet(
- PakfireArchive archive, pakfire_scriptlet_type type) {
+ PakfireArchive archive, const char* type) {
struct pakfire_scriptlet* scriptlet;
for (unsigned int i = 0; i < archive->nscriptlets; i++) {
scriptlet = archive->scriptlets[i];
- if (scriptlet->type == type)
+ const char* t = pakfire_scriptlet_get_type(scriptlet);
+
+ if (strcmp(t, type) == 0)
return scriptlet;
}
static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
sqlite3_stmt* stmt = NULL;
+ size_t size;
int r = 1;
- const struct pakfire_scriptlet_type* scriptlet_type = PAKFIRE_SCRIPTLET_TYPES;
- struct pakfire_scriptlet* scriptlet;
-
const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
// Prepare the statement
goto END;
}
- while (scriptlet_type->type) {
+ for (const char** type = pakfire_scriptlet_types; *type; type++) {
// Fetch the scriptlet
- scriptlet = pakfire_archive_get_scriptlet(archive, scriptlet_type->type);
-
- // Go to next one if the archive does not have a scriptlet of the given type
- if (!scriptlet) {
- scriptlet_type++;
+ struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
+ if (!scriptlet)
continue;
- }
// Bind package ID
r = sqlite3_bind_int64(stmt, 1, id);
if (r) {
ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
+ pakfire_scriptlet_unref(scriptlet);
goto END;
}
// Bind handle
- r = sqlite3_bind_text(stmt, 2, scriptlet_type->handle, -1, NULL);
+ r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
if (r) {
ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
+ pakfire_scriptlet_unref(scriptlet);
goto END;
}
+ const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
+
// Bind scriptlet
- r = sqlite3_bind_text(stmt, 3, scriptlet->data, scriptlet->size, NULL);
+ r = sqlite3_bind_text(stmt, 3, data, size, NULL);
if (r) {
ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
+ pakfire_scriptlet_unref(scriptlet);
goto END;
}
if (r != SQLITE_DONE) {
ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
sqlite3_errmsg(db->handle));
+ pakfire_scriptlet_unref(scriptlet);
goto END;
}
+ pakfire_scriptlet_unref(scriptlet);
+
// Reset bound values
sqlite3_reset(stmt);
-
- scriptlet_type++;
}
// All okay
}
struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
- PakfirePackage pkg, pakfire_scriptlet_type type) {
+ PakfirePackage pkg, const char* type) {
struct pakfire_scriptlet* scriptlet = NULL;
sqlite3_stmt* stmt = NULL;
int r = 1;
goto ERROR;
}
- // Bind type
- const char* handle = pakfire_scriptlet_handle_from_type(type);
- if (!handle)
- goto ERROR;
-
- r = sqlite3_bind_text(stmt, 2, handle, -1, NULL);
+ r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
if (r) {
ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
goto ERROR;
}
- DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, handle);
+ DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
// Execute query
do {
ssize_t size = sqlite3_column_bytes(stmt, 1);
// Create a scriptlet object
- scriptlet = pakfire_scriptlet_create(db->pakfire, data, size);
- if (!scriptlet)
+ r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
+ if (r)
goto ERROR;
}
#ifdef PAKFIRE_PRIVATE
struct pakfire_scriptlet* pakfire_archive_get_scriptlet(
- PakfireArchive archive, pakfire_scriptlet_type type);
+ PakfireArchive archive, const char* type);
typedef enum archive_checksum_algo {
PAKFIRE_CHECKSUM_UNKNOWN = 0,
int pakfire_db_load(struct pakfire_db* db, PakfireRepo repo);
struct pakfire_scriptlet* pakfire_db_get_scriptlet(
- struct pakfire_db* db, PakfirePackage pkg, pakfire_scriptlet_type type);
+ struct pakfire_db* db, PakfirePackage pkg, const char* type);
#endif
#include <pakfire/types.h>
-typedef enum _pakfire_script_types {
- PAKFIRE_SCRIPTLET_UNDEFINED = 0,
- PAKFIRE_SCRIPTLET_PREIN,
- PAKFIRE_SCRIPTLET_PREUN,
- PAKFIRE_SCRIPTLET_PREUP,
- PAKFIRE_SCRIPTLET_POSTIN,
- PAKFIRE_SCRIPTLET_POSTUN,
- PAKFIRE_SCRIPTLET_POSTUP,
- PAKFIRE_SCRIPTLET_PRETRANSIN,
- PAKFIRE_SCRIPTLET_PRETRANSUN,
- PAKFIRE_SCRIPTLET_PRETRANSUP,
- PAKFIRE_SCRIPTLET_POSTTRANSIN,
- PAKFIRE_SCRIPTLET_POSTTRANSUN,
- PAKFIRE_SCRIPTLET_POSTTRANSUP,
-} pakfire_scriptlet_type;
+const char* pakfire_scriptlet_types[13];
-#define NUM_PAKFIRE_SCRIPTLET_TYPES 13
+struct pakfire_scriptlet;
-struct pakfire_scriptlet_type {
- pakfire_scriptlet_type type;
- const char* filename;
- const char* handle;
-};
+int pakfire_scriptlet_create(struct pakfire_scriptlet** scriptlet, Pakfire pakfire,
+ const char* type, const char* data, size_t size);
+struct pakfire_scriptlet* pakfire_scriptlet_ref(struct pakfire_scriptlet* scriptlet);
+struct pakfire_scriptlet* pakfire_scriptlet_unref(struct pakfire_scriptlet* scriptlet);
-const struct pakfire_scriptlet_type PAKFIRE_SCRIPTLET_TYPES[NUM_PAKFIRE_SCRIPTLET_TYPES + 1];
+const char* pakfire_scriptlet_get_type(struct pakfire_scriptlet* scriptlet);
+const char* pakfire_scriptlet_get_data(struct pakfire_scriptlet* scriptlet, size_t* size);
-struct pakfire_scriptlet {
- pakfire_scriptlet_type type;
- char* data;
- size_t size;
-};
-
-struct pakfire_scriptlet* pakfire_scriptlet_create(Pakfire pakfire, const char* data, size_t size);
-void pakfire_scriptlet_free(struct pakfire_scriptlet* scriptlet);
-
-pakfire_scriptlet_type pakfire_scriptlet_type_from_filename(const char* filename);
-const char* pakfire_scriptlet_handle_from_type(pakfire_scriptlet_type type);
-int pakfire_scriptlet_is_shell_script(struct pakfire_scriptlet* scriptlet);
+int pakfire_scriptlet_execute(struct pakfire_scriptlet* scriptlet);
#endif
# #
#############################################################################*/
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <pakfire/execute.h>
#include <pakfire/logging.h>
#include <pakfire/scriptlet.h>
#include <pakfire/types.h>
+#include <pakfire/util.h>
+
+const char* pakfire_scriptlet_types[] = {
+ "prein",
+ "preun",
+ "preup",
+ "postin",
+ "postun",
+ "postup",
+ "pretransin",
+ "pretransun",
+ "pretransup",
+ "posttransin",
+ "posttransun",
+ "posttransup",
+ NULL,
+};
+
+struct pakfire_scriptlet {
+ Pakfire pakfire;
+ int nrefs;
+
+ // Type
+ char type[NAME_MAX];
-const struct pakfire_scriptlet_type PAKFIRE_SCRIPTLET_TYPES[NUM_PAKFIRE_SCRIPTLET_TYPES + 1] = {
- { PAKFIRE_SCRIPTLET_PREIN, "scriptlets/prein", "prein" },
- { PAKFIRE_SCRIPTLET_PREUN, "scriptlets/preun", "preun" },
- { PAKFIRE_SCRIPTLET_PREUP, "scriptlets/preup", "preup" },
- { PAKFIRE_SCRIPTLET_POSTIN, "scriptlets/postin", "postin" },
- { PAKFIRE_SCRIPTLET_POSTUN, "scriptlets/postun", "postun" },
- { PAKFIRE_SCRIPTLET_POSTUP, "scriptlets/postup", "postup" },
- { PAKFIRE_SCRIPTLET_PRETRANSIN, "scriptlets/pretransin", "pretransin" },
- { PAKFIRE_SCRIPTLET_PRETRANSUN, "scriptlets/pretransun", "pretransun" },
- { PAKFIRE_SCRIPTLET_PRETRANSUP, "scriptlets/pretransup", "pretransup" },
- { PAKFIRE_SCRIPTLET_POSTTRANSIN, "scriptlets/posttransin", "posttransin" },
- { PAKFIRE_SCRIPTLET_POSTTRANSUN, "scriptlets/posttransun", "posttransun" },
- { PAKFIRE_SCRIPTLET_POSTTRANSUP, "scriptlets/posttransup", "posttransup" },
- { PAKFIRE_SCRIPTLET_UNDEFINED, NULL, NULL },
+ // Data and size
+ char* data;
+ size_t size;
};
+static int pakfire_scriptlet_valid_type(const char* type) {
+ for (const char** t = pakfire_scriptlet_types; *t; t++) {
+ if (strcmp(*t, type) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
static int pakfire_scriptlet_set(struct pakfire_scriptlet* scriptlet, const char* data, size_t size) {
if (scriptlet->data)
free(scriptlet->data);
+ // Fill size if unset
+ if (!size)
+ size = strlen(data);
+
// Allocate space for data
scriptlet->data = malloc(size);
if (!scriptlet->data)
// Copy data
memcpy(scriptlet->data, data, size);
+ scriptlet->size = size;
return 0;
}
-struct pakfire_scriptlet* pakfire_scriptlet_create(Pakfire pakfire, const char* data, size_t size) {
- struct pakfire_scriptlet* scriptlet = calloc(1, sizeof(*scriptlet));
- if (!scriptlet)
- return NULL;
-
- if (data && size) {
- int r = pakfire_scriptlet_set(scriptlet, data, size);
- if (r) {
- pakfire_scriptlet_free(scriptlet);
- return NULL;
- }
- }
-
- return scriptlet;
-};
-
-void pakfire_scriptlet_free(struct pakfire_scriptlet* scriptlet) {
+static void pakfire_scriptlet_free(struct pakfire_scriptlet* scriptlet) {
if (scriptlet->data)
free(scriptlet->data);
+ pakfire_unref(scriptlet->pakfire);
free(scriptlet);
}
-pakfire_scriptlet_type pakfire_scriptlet_type_from_filename(const char* filename) {
- const struct pakfire_scriptlet_type* t = PAKFIRE_SCRIPTLET_TYPES;
-
- while (t->type) {
- if (strcmp(t->filename, filename) == 0)
- return t->type;
+int pakfire_scriptlet_create(struct pakfire_scriptlet** scriptlet, Pakfire pakfire,
+ const char* type, const char* data, size_t size) {
+ if (!type || !data) {
+ errno = EINVAL;
+ return 1;
+ }
- t++;
+ // Do we know this type?
+ if (!pakfire_scriptlet_valid_type(type)) {
+ errno = ENOTSUP;
+ return 1;
}
- return PAKFIRE_SCRIPTLET_UNDEFINED;
-}
+ struct pakfire_scriptlet* s = calloc(1, sizeof(*s));
+ if (!s)
+ return 1;
-const char* pakfire_scriptlet_handle_from_type(pakfire_scriptlet_type type) {
- const struct pakfire_scriptlet_type* t = PAKFIRE_SCRIPTLET_TYPES;
+ // Store reference to Pakfire
+ s->pakfire = pakfire_ref(pakfire);
+ s->nrefs = 1;
- while (t->type) {
- if (t->type == type)
- return t->handle;
+ // Set type
+ pakfire_string_set(s->type, type);
- t++;
+ int r = pakfire_scriptlet_set(s, data, size);
+ if (r) {
+ pakfire_scriptlet_free(s);
+ return 1;
}
+ *scriptlet = s;
+ return 0;
+};
+
+struct pakfire_scriptlet* pakfire_scriptlet_ref(struct pakfire_scriptlet* scriptlet) {
+ scriptlet->nrefs++;
+
+ return scriptlet;
+}
+
+struct pakfire_scriptlet* pakfire_scriptlet_unref(struct pakfire_scriptlet* scriptlet) {
+ if (--scriptlet->nrefs > 0)
+ return scriptlet;
+
+ pakfire_scriptlet_free(scriptlet);
return NULL;
}
-int pakfire_scriptlet_is_shell_script(struct pakfire_scriptlet* scriptlet) {
+const char* pakfire_scriptlet_get_type(struct pakfire_scriptlet* scriptlet) {
+ return scriptlet->type;
+}
+
+const char* pakfire_scriptlet_get_data(struct pakfire_scriptlet* scriptlet, size_t* size) {
+ if (size)
+ *size = scriptlet->size;
+
+ return scriptlet->data;
+}
+
+static int pakfire_scriptlet_is_shell_script(struct pakfire_scriptlet* scriptlet) {
const char* interpreter = "#!/bin/sh";
// data must be long enough
return 0;
}
+
+int pakfire_scriptlet_execute(struct pakfire_scriptlet* scriptlet) {
+ // Detect what kind of script this is and run it
+ if (pakfire_scriptlet_is_shell_script(scriptlet))
+ return pakfire_execute_script(scriptlet->pakfire, scriptlet->data, scriptlet->size,
+ NULL, NULL, 0, NULL, NULL);
+
+ ERROR(scriptlet->pakfire, "Scriptlet is of an unknown kind\n");
+ errno = ENOTSUP;
+ return 1;
+}
}
static int pakfire_transaction_run_script(struct pakfire_transaction* transaction,
- struct pakfire_db* db, pakfire_scriptlet_type type, PakfirePackage pkg, PakfireArchive archive) {
+ struct pakfire_db* db, const char* type, PakfirePackage pkg, PakfireArchive archive) {
struct pakfire_scriptlet* scriptlet = NULL;
// Fetch scriptlet from archive if possible
if (!scriptlet)
return 0;
- // Found a script!
- DEBUG(transaction->pakfire, "Found scriptlet:\n%.*s",
- (int)scriptlet->size, (const char*)scriptlet->data);
+ // Execute the scriptlet
+ pakfire_scriptlet_execute(scriptlet);
- // Detect what kind of script this is and run it
- if (pakfire_scriptlet_is_shell_script(scriptlet)) {
- pakfire_execute_script(transaction->pakfire, scriptlet->data, scriptlet->size,
- NULL, NULL, 0, NULL, NULL);
- } else {
- ERROR(transaction->pakfire, "Scriptlet is of an unknown kind\n");
- }
+ pakfire_scriptlet_unref(scriptlet);
return 0;
}
case PAKFIRE_STEP_INSTALL:
case PAKFIRE_STEP_REINSTALL:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PRETRANSIN, pkg, archive);
+ "pretransin", pkg, archive);
break;
case PAKFIRE_STEP_UPGRADE:
case PAKFIRE_STEP_DOWNGRADE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PRETRANSUP, pkg, archive);
+ "pretransup", pkg, archive);
break;
case PAKFIRE_STEP_ERASE:
case PAKFIRE_STEP_OBSOLETE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PRETRANSUN, pkg, archive);
+ "pretransun", pkg, archive);
break;
case PAKFIRE_STEP_IGNORE:
case PAKFIRE_STEP_INSTALL:
case PAKFIRE_STEP_REINSTALL:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTTRANSIN, pkg, archive);
+ "posttransin", pkg, archive);
break;
case PAKFIRE_STEP_UPGRADE:
case PAKFIRE_STEP_DOWNGRADE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTTRANSUP, pkg, archive);
+ "posttransup", pkg, archive);
break;
case PAKFIRE_STEP_ERASE:
case PAKFIRE_STEP_OBSOLETE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTTRANSUN, pkg, archive);
+ "posttransun", pkg, archive);
break;
case PAKFIRE_STEP_IGNORE:
case PAKFIRE_STEP_INSTALL:
case PAKFIRE_STEP_REINSTALL:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PREIN, pkg, archive);
+ "prein", pkg, archive);
if (r)
break;
break;
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTIN, pkg, archive);
+ "postin", pkg, archive);
break;
case PAKFIRE_STEP_UPGRADE:
case PAKFIRE_STEP_DOWNGRADE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PREUP, pkg, archive);
+ "preup", pkg, archive);
if (r)
break;
break;
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTUP, pkg, archive);
+ "postup", pkg, archive);
break;
case PAKFIRE_STEP_ERASE:
case PAKFIRE_STEP_OBSOLETE:
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_PREUN, pkg, archive);
+ "preun", pkg, archive);
if (r)
break;
break;
r = pakfire_transaction_run_script(transaction, db,
- PAKFIRE_SCRIPTLET_POSTUN, pkg, archive);
+ "postun", pkg, archive);
break;
case PAKFIRE_STEP_IGNORE: