From: Michael Tremer Date: Sat, 11 Mar 2023 16:24:08 +0000 (+0000) Subject: build: Implement marking configuration files in archives X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2f3563b99a139f28912026141dc77e0f6744446f;p=people%2Fstevee%2Fpakfire.git build: Implement marking configuration files in archives Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/build.c b/src/libpakfire/build.c index 5e28e5c4..82c37e9a 100644 --- a/src/libpakfire/build.c +++ b/src/libpakfire/build.c @@ -545,64 +545,72 @@ ERROR: return r; } -static int append_to_array(char*** array, const char* s) { - unsigned int length = 0; +static int __pakfire_build_package_mark_config_files( + struct pakfire* pakfire, struct pakfire_file* file, void* data) { + char** configfiles = (char**)data; + int r; - // Determine the length of the existing array - if (*array) { - for (char** element = *array; *element; element++) - length++; - } + // Skip anything that isn't a regular file + if (pakfire_file_get_type(file) == S_IFREG) + return 0; - // Allocate space - *array = reallocarray(*array, length + 2, sizeof(**array)); - if (!*array) - return 1; + // Fetch path + const char* path = pakfire_file_get_path(file); - // Copy the string to the heap - char* p = strdup(s); - if (!p) - return 1; + // Check if any configfile entry matches against this + for (char** configfile = configfiles; *configfile; configfile++) { + if (pakfire_string_startswith(path, *configfile)) { + r = pakfire_file_set_flags(file, PAKFIRE_FILE_CONFIG); + if (r) + return r; - // Append p and terminate the array - (*array)[length] = p; - (*array)[length + 1] = NULL; + // Done + break; + } + } return 0; } +static int pakfire_build_package_mark_config_files(struct pakfire_build* build, + struct pakfire_filelist* filelist, struct pakfire_parser* makefile, const char* namespace) { + char** configfiles = NULL; + int r; + + // Fetch configfiles from makefile + r = pakfire_parser_get_filelist(makefile, namespace, "configfiles", &configfiles, NULL); + + // If configfiles is not set, there is nothing to do + if (!configfiles) + return 0; + + r = pakfire_filelist_walk(filelist, __pakfire_build_package_mark_config_files, configfiles); + + // Cleanup + if (configfiles) { + for (char** configfile = configfiles; *configfile; configfile++) + free(*configfile); + free(configfiles); + } + + return r; +} + static int pakfire_build_package_add_files(struct pakfire_build* build, struct pakfire_parser* makefile, const char* buildroot, const char* namespace, struct pakfire_package* pkg, struct pakfire_packager* packager) { struct pakfire_filelist* filelist = NULL; - int r = 1; - char** includes = NULL; char** excludes = NULL; - char* p = NULL; + int r; // Fetch filelist from makefile - char* files = pakfire_parser_get(makefile, namespace, "files"); + r = pakfire_parser_get_filelist(makefile, namespace, "files", &includes, &excludes); // No files to package? - if (!files) + if (!includes && !excludes) return 0; - const char* file = strtok_r(files, " \n", &p); - - // Split into includes and excludes - while (file) { - if (*file == '!') - r = append_to_array(&excludes, file + 1); - else - r = append_to_array(&includes, file); - if (r) - goto ERROR; - - // Move on to the next token - file = strtok_r(NULL, " \n", &p); - } - // Allocate a new filelist r = pakfire_filelist_create(&filelist, build->pakfire); if (r) @@ -630,6 +638,11 @@ static int pakfire_build_package_add_files(struct pakfire_build* build, goto ERROR; } + // Mark configuration files + r = pakfire_build_package_mark_config_files(build, filelist, makefile, namespace); + if (r) + goto ERROR; + // Add all files to the package r = pakfire_packager_add_files(packager, filelist); if (r) @@ -638,8 +651,6 @@ static int pakfire_build_package_add_files(struct pakfire_build* build, ERROR: if (filelist) pakfire_filelist_unref(filelist); - if (files) - free(files); if (includes) { for (char** include = includes; *include; include++) free(*include); diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index f89bbe2b..94d8ff04 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -72,6 +72,9 @@ struct pakfire_file { // Stat struct stat st; + // Flags + int flags; + // Link destinations char hardlink[PATH_MAX]; char symlink[PATH_MAX]; @@ -92,9 +95,8 @@ struct pakfire_file { int hardening_issues; int hardening_check_done:1; - #warning TODO capabilities, config, data + #warning TODO capabilities, data // capabilities - //int is_configfile; //int is_datafile; }; @@ -167,8 +169,14 @@ static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct arc // Read any extended attributes while (archive_entry_xattr_next(entry, &attr, &value, &size) == ARCHIVE_OK) { + // Config Files + if (strcmp(attr, "PAKFIRE.config") == 0) { + r = pakfire_file_set_flags(file, PAKFIRE_FILE_CONFIG); + if (r) + goto ERROR; + // MIME type - if (strcmp(attr, "PAKFIRE.mimetype") == 0) { + } else if (strcmp(attr, "PAKFIRE.mimetype") == 0) { // Copy the value into a NULL-terminated buffer r = asprintf(&buffer, "%.*s", (int)size, (const char*)value); if (r < 0) @@ -349,6 +357,12 @@ struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int archive_entry_set_ctime(entry, pakfire_file_get_ctime(file), 0); archive_entry_set_mtime(entry, pakfire_file_get_mtime(file), 0); + // Flags + if (pakfire_file_has_flag(file, PAKFIRE_FILE_CONFIG)) { + archive_entry_xattr_add_entry(entry, + "PAKFIRE.config", "1", strlen("1")); + } + // Set MIME type const char* mimetype = pakfire_file_get_mimetype(file); if (mimetype) { @@ -427,6 +441,20 @@ PAKFIRE_EXPORT struct pakfire_file* pakfire_file_unref(struct pakfire_file* file return NULL; } +/* + Flags +*/ + +int pakfire_file_has_flag(struct pakfire_file* file, int flag) { + return file->flags & flag; +} + +int pakfire_file_set_flags(struct pakfire_file* file, int flag) { + file->flags |= flag; + + return 0; +} + #define pakfire_file_strmode(file, buffer) \ __pakfire_file_strmode(file, buffer, sizeof(buffer)) diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index 9aa6dd5c..9d9b68ee 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -30,11 +30,18 @@ struct pakfire_file; #include #include +enum pakfire_file_flags { + PAKFIRE_FILE_CONFIG = (1 << 0), +}; + int pakfire_file_create(struct pakfire_file** file, struct pakfire* pakfire); struct pakfire_file* pakfire_file_ref(struct pakfire_file* file); struct pakfire_file* pakfire_file_unref(struct pakfire_file* file); +int pakfire_file_has_flag(struct pakfire_file* file, int flag); +int pakfire_file_set_flags(struct pakfire_file* file, int flag); + int pakfire_file_cmp(struct pakfire_file* file1, struct pakfire_file* file2); const char* pakfire_file_get_path(struct pakfire_file* file); diff --git a/src/libpakfire/include/pakfire/parser.h b/src/libpakfire/include/pakfire/parser.h index dbfc632a..5caa1f12 100644 --- a/src/libpakfire/include/pakfire/parser.h +++ b/src/libpakfire/include/pakfire/parser.h @@ -54,6 +54,8 @@ int pakfire_parser_append(struct pakfire_parser* parser, char* pakfire_parser_expand(struct pakfire_parser* parser, const char* namespace, const char* value); char* pakfire_parser_get(struct pakfire_parser* parser, const char* namespace, const char* name); +int pakfire_parser_get_filelist(struct pakfire_parser* parser, const char* namespace, + const char* name, char*** includes, char*** excludes); char** pakfire_parser_get_split(struct pakfire_parser* parser, const char* namespace, const char* name, char delim); char** pakfire_parser_list_namespaces(struct pakfire_parser* parser, const char* filter); diff --git a/src/libpakfire/parser.c b/src/libpakfire/parser.c index 44308427..0a185081 100644 --- a/src/libpakfire/parser.c +++ b/src/libpakfire/parser.c @@ -667,6 +667,69 @@ char* pakfire_parser_get(struct pakfire_parser* parser, const char* namespace, c return pakfire_parser_expand(parser, namespace, value); } +static int append_to_array(char*** array, const char* s) { + unsigned int length = 0; + + // Determine the length of the existing array + if (*array) { + for (char** element = *array; *element; element++) + length++; + } + + // Allocate space + *array = reallocarray(*array, length + 2, sizeof(**array)); + if (!*array) + return 1; + + // Copy the string to the heap + char* p = strdup(s); + if (!p) + return 1; + + // Append p and terminate the array + (*array)[length] = p; + (*array)[length + 1] = NULL; + + return 0; +} + +int pakfire_parser_get_filelist(struct pakfire_parser* parser, const char* namespace, + const char* name, char*** includes, char*** excludes) { + char* p = NULL; + int r = 0; + + // Fetch the list + char* list = pakfire_parser_get(parser, namespace, name); + + // Nothing to do for empty lists + if (!list) + return 0; + + const char* file = strtok_r(list, " \n", &p); + + // Split into includes and excludes + while (file) { + if (excludes && *file == '!') { + r = append_to_array(excludes, file + 1); + if (r) + goto ERROR; + } else { + r = append_to_array(includes, file); + if (r) + goto ERROR; + } + + // Move on to the next token + file = strtok_r(NULL, " \n", &p); + } + +ERROR: + if (list) + free(list); + + return r; +} + char** pakfire_parser_get_split(struct pakfire_parser* parser, const char* namespace, const char* name, char delim) { char* value = pakfire_parser_get(parser, namespace, name);