swid-gen: Share SWID generator between sw-collector, imc-swima and imc-swid
[strongswan.git] / src / libimcv / swid / swid_inventory.c
index 7b05e83..4adbb39 100644 (file)
 #include "swid_inventory.h"
 #include "swid_tag.h"
 #include "swid_tag_id.h"
+#include "swid_gen/swid_gen.h"
 
 #include <collections/linked_list.h>
-#include <bio/bio_writer.h>
+#include <utils/lexparser.h>
 #include <utils/debug.h>
 
 #include <stdio.h>
@@ -52,186 +53,92 @@ struct private_swid_inventory_t {
        linked_list_t *list;
 };
 
-/**
- * Read SWID tags issued by the swid_generator tool
- */
-static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
+static status_t generate_tags(private_swid_inventory_t *this,
+                                                         swid_inventory_t *targets, bool pretty, bool full)
 {
+       swid_gen_t *swid_gen;
        swid_tag_t *tag;
-       bio_writer_t *writer;
-       chunk_t tag_encoding, tag_file_path = chunk_empty;
-       bool more_tags = TRUE, last_newline;
-       char line[8192];
-       size_t len;
-
-       while (more_tags)
-       {
-               last_newline = TRUE;
-               writer = bio_writer_create(512);
-               while (TRUE)
-               {
-                       if (!fgets(line, sizeof(line), file))
-                       {
-                               more_tags = FALSE;
-                               break;
-                       }
-                       len = strlen(line);
-
-                       if (last_newline && line[0] == '\n')
-                       {
-                               break;
-                       }
-                       else
-                       {
-                               last_newline = (line[len-1] == '\n');
-                               writer->write_data(writer, chunk_create(line, len));
-                       }
-               }
-
-               tag_encoding = writer->get_buf(writer);
-
-               if (tag_encoding.len > 1)
-               {
-                       /* remove trailing newline if present */
-                       if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
-                       {
-                               tag_encoding.len--;
-                       }
-                       DBG3(DBG_IMC, "  %.*s", tag_encoding.len, tag_encoding.ptr);
-
-                       tag = swid_tag_create(tag_encoding, tag_file_path);
-                       this->list->insert_last(this->list, tag);
-               }
-               writer->destroy(writer);
-       }
-
-       return SUCCESS;
-}
-
-/**
- * Read SWID tag or software IDs issued by the swid_generator tool
- */
-static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
-{
        swid_tag_id_t *tag_id;
-       chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
-       char line[BUF_LEN];
-
-       while (TRUE)
-       {
-               char *separator;
-               size_t len;
-
-               if (!fgets(line, sizeof(line), file))
-               {
-                       return SUCCESS;
-               }
-               len = strlen(line);
-
-               /* remove trailing newline if present */
-               if (len > 0 && line[len - 1] == '\n')
-               {
-                       len--;
-               }
-               DBG3(DBG_IMC, "  %.*s", len, line);
-
-               separator = strchr(line, '_');
-               if (!separator)
-               {
-                       DBG1(DBG_IMC, "separation of regid from unique software ID failed");
-                       return FAILED;
-               }
-               tag_creator = chunk_create(line, separator - line);
-               separator++;
-
-               unique_sw_id = chunk_create(separator, len - (separator - line));
-               tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
-               this->list->insert_last(this->list, tag_id);
-       }
-}
-
-static status_t generate_tags(private_swid_inventory_t *this, char *generator,
-                                                         swid_inventory_t *targets, bool pretty, bool full)
-{
-       FILE *file;
-       char command[BUF_LEN];
-       char doc_separator[] = "'\n\n'";
-
+       enumerator_t *enumerator;
        status_t status = SUCCESS;
+       chunk_t out;
+
+       swid_gen = swid_gen_create();
 
        if (targets->get_count(targets) == 0)
        {
-               /* Assemble the SWID generator command */
-               if (this->full_tags)
-               {
-                       snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
-                                        generator, doc_separator, pretty ? " --pretty" : "",
-                                                                                          full   ? " --full"   : "");
-               }
-               else
-               {
-                       snprintf(command, BUF_LEN, "%s software-id", generator);
-               }
+               DBG2(DBG_IMC, "SWID tag%s generation by package manager",
+                                          this->full_tags ? "" : " ID");
 
-               /* Open a pipe stream for reading the SWID generator output */
-               file = popen(command, "r");
-               if (!file)
+               enumerator = swid_gen->create_tag_enumerator(swid_gen, !this->full_tags,
+                                                                                                        full, pretty);
+               if (enumerator)
                {
-                       DBG1(DBG_IMC, "failed to run swid_generator command");
-                       return NOT_SUPPORTED;
-               }
+                       while (enumerator->enumerate(enumerator, &out))
+                       {
+                               if (this->full_tags)
+                               {
+                                       chunk_t swid_tag = out;
 
-               if (this->full_tags)
-               {
-                       DBG2(DBG_IMC, "SWID tag generation by package manager");
-                       status = read_swid_tags(this, file);
+                                       tag = swid_tag_create(swid_tag, chunk_empty);
+                                       this->list->insert_last(this->list, tag);
+                               }
+                               else
+                               {
+                                       chunk_t tag_creator, sw_id = out;
+
+                                       if (extract_token_str(&tag_creator, "__", &sw_id))
+                                       {
+                                               tag_id = swid_tag_id_create(tag_creator, sw_id,
+                                                                                                       chunk_empty);
+                                               this->list->insert_last(this->list, tag_id);
+                                       }
+                                       else
+                                       {
+                                               DBG1(DBG_IMC, "separation of regid from unique "
+                                                                         "software ID failed");
+                                               status = FAILED;
+                                               chunk_free(&out);
+                                               break;
+                                       }
+                               }
+                               chunk_free(&out);
+                       }
+                       enumerator->destroy(enumerator);
                }
                else
                {
-                       DBG2(DBG_IMC, "SWID tag ID generation by package manager");
-                       status = read_swid_tag_ids(this, file);
+                       status = NOT_SUPPORTED;
                }
-               pclose(file);
        }
        else if (this->full_tags)
        {
-               swid_tag_id_t *tag_id;
-               enumerator_t *enumerator;
+               DBG2(DBG_IMC, "targeted SWID tag generation");
 
                enumerator = targets->create_enumerator(targets);
                while (enumerator->enumerate(enumerator, &tag_id))
                {
-                       char software_id[BUF_LEN];
-                       chunk_t tag_creator, unique_sw_id;
+                       char software_id[BUF_LEN], *swid_tag;
+                       chunk_t tag_creator, sw_id;
 
+                       /* Construct software ID from tag creator and unique software ID */
                        tag_creator  = tag_id->get_tag_creator(tag_id);
-                       unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
-                       snprintf(software_id, BUF_LEN, "%.*s_%.*s",
-                                        tag_creator.len, tag_creator.ptr,
-                                        unique_sw_id.len, unique_sw_id.ptr);
-
-                       /* Assemble the SWID generator command */
-                       snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
-                                        generator, software_id, pretty ? " --pretty" : "",
-                                                                                        full   ? " --full"   : "");
-
-                       /* Open a pipe stream for reading the SWID generator output */
-                       file = popen(command, "r");
-                       if (!file)
-                       {
-                               DBG1(DBG_IMC, "failed to run swid_generator command");
-                               return NOT_SUPPORTED;
-                       }
-                       status = read_swid_tags(this, file);
-                       pclose(file);
+                       sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
+                       snprintf(software_id, BUF_LEN, "%.*s__%.*s",
+                                        tag_creator.len, tag_creator.ptr, sw_id.len, sw_id.ptr);
 
-                       if (status != SUCCESS)
+                       swid_tag = swid_gen->generate_tag(swid_gen, software_id, NULL, NULL,
+                                                                                full, pretty);
+                       if (swid_tag)
                        {
-                               break;
+                               tag = swid_tag_create(chunk_from_str(swid_tag), chunk_empty);
+                               this->list->insert_last(this->list, tag);
+                               free(swid_tag);
                        }
                }
                enumerator->destroy(enumerator);
        }
+       swid_gen->destroy(swid_gen);
 
        return status;
 }
@@ -284,16 +191,16 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
                }
 
                /* parse the swidtag filename into its components */
-               separator = strchr(rel_name, '_');
+               separator = strstr(rel_name, "__");
                if (!separator)
                {
                        DBG1(DBG_IMC, "  %s", rel_name);
-                       DBG1(DBG_IMC, "  '_' separator not found");
+                       DBG1(DBG_IMC, "  '__' separator not found");
                        goto end;
                }
                tag_creator = chunk_create(rel_name, separator-rel_name);
 
-               unique_sw_id = chunk_create(separator+1, suffix-separator-1);
+               unique_sw_id = chunk_create(separator+2, suffix-separator-2);
                tag_file_path = chunk_from_str(abs_name);
 
                /* In case of a targeted request */
@@ -364,13 +271,13 @@ end:
 }
 
 METHOD(swid_inventory_t, collect, bool,
-       private_swid_inventory_t *this, char *directory, char *generator,
-       swid_inventory_t *targets, bool pretty, bool full)
+       private_swid_inventory_t *this, char *directory, swid_inventory_t *targets,
+       bool pretty, bool full)
 {
        /**
         * Tags are generated by a package manager
         */
-       generate_tags(this, generator, targets, pretty, full);
+       generate_tags(this, targets, pretty, full);
 
        /**
         * Collect swidtag files by iteratively entering all directories in