]> git.ipfire.org Git - people/stevee/pakfire.git/commitdiff
build: Implement marking configuration files in archives
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 11 Mar 2023 16:24:08 +0000 (16:24 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 11 Mar 2023 16:24:08 +0000 (16:24 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/build.c
src/libpakfire/file.c
src/libpakfire/include/pakfire/file.h
src/libpakfire/include/pakfire/parser.h
src/libpakfire/parser.c

index 5e28e5c4ec0d001f1564a6e80ab0e16ee5735a94..82c37e9a08d1abb9e480eb0fec575fc89ac85dec 100644 (file)
@@ -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);
index f89bbe2b7643b3c31b4239f9398ea416d5781588..94d8ff045dc1e004221952f41f343b233959ede1 100644 (file)
@@ -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))
 
index 9aa6dd5c90c1790faded274dddd0463679382d90..9d9b68eeaff921442811df6180f9fd4889c27dc8 100644 (file)
@@ -30,11 +30,18 @@ struct pakfire_file;
 #include <pakfire/digest.h>
 #include <pakfire/pakfire.h>
 
+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);
index dbfc632a39297875f7f306feeffe9f5df95b5ca4..5caa1f125cb1dbdc44a2f7c00a7a1740592b5912 100644 (file)
@@ -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);
index 44308427def06762d7f2d00865f94870ff211567..0a185081185d36f50c22c6c2633ad83ced65e377 100644 (file)
@@ -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);