bug-recutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug-recutils] [PATCH 08/13] utils: add recfix -- add-index command.


From: Michał Masłowski
Subject: [bug-recutils] [PATCH 08/13] utils: add recfix -- add-index command.
Date: Mon, 20 Aug 2012 18:21:29 +0200

It's the only recfix command working on a single type only, parts of
recutl.h record selection code are copied for this option.
---
 ChangeLog      |  12 +++
 utils/recfix.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 238 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2df5fca..bef69c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2012-08-18  Michał Masłowski  <address@hidden>
 
+       utils: add recfix --add-index command.
+       * utils/recfix.c (recfix_op): Add RECFIX_OP_ADD_INDEX.
+       (recfix_type): New global variable.
+       (recfix_index_fields): Likewise.
+       (GNU_longOptions): Add --add-index and --type.
+       (recutl_print_help): Document --add-index and --type.
+       (recfix_parse_args): Handle --add-index and --type.
+       (recfix_do_add_index): New function.
+       (main): Handle --add-index.
+
+2012-08-18  Michał Masłowski  <address@hidden>
+
        src: fix index range checks.
        * src/rec-idx-file.c (rec_idx_file_index): Check if the end of the
        index is after the end of buffer, not after the start.
diff --git a/utils/recfix.c b/utils/recfix.c
index 840a52d..bd0c384 100644
--- a/utils/recfix.c
+++ b/utils/recfix.c
@@ -47,6 +47,7 @@ static int recfix_do_crypt (void);
 #endif
 static int recfix_do_auto (void);
 static int recfix_do_build_index (void);
+static int recfix_do_add_index (void);
 
 /*
  * Data types.
@@ -65,7 +66,8 @@ enum recfix_op
 #endif
   RECFIX_OP_SORT,
   RECFIX_OP_AUTO,
-  RECFIX_OP_BUILD_INDEX
+  RECFIX_OP_BUILD_INDEX,
+  RECFIX_OP_ADD_INDEX
 };
 
 /*
@@ -77,6 +79,8 @@ char *recfix_file     = NULL;
 int   recfix_op       = RECFIX_OP_INVALID;
 char *recfix_password = NULL;
 bool  recfix_force    = false;
+char *recfix_type     = NULL;
+rec_fex_t recfix_index_fields = NULL;
 
 /*
  * Command line options management.
@@ -95,7 +99,9 @@ enum
 #endif
   OP_CHECK_ARG,
   OP_AUTO_ARG,
-  OP_BUILD_INDEX_ARG
+  OP_BUILD_INDEX_ARG,
+  OP_ADD_INDEX_ARG,
+  TYPE_ARG
 };
 
 static const struct option GNU_longOptions[] =
@@ -112,6 +118,8 @@ static const struct option GNU_longOptions[] =
 #endif
     {"auto", no_argument, NULL, OP_AUTO_ARG},
     {"build-index", no_argument, NULL, OP_BUILD_INDEX_ARG},
+    {"add-index", required_argument, NULL, OP_ADD_INDEX_ARG},
+    {"type", required_argument, NULL, TYPE_ARG},
     {NULL, 0, NULL, 0}
   };
 
@@ -147,7 +155,8 @@ Operations:\n\
       --check                         check integrity of the specified file.  
Default.\n\
       --sort                          sort the records in the specified 
file.\n\
       --auto                          insert auto-generated fields in records 
missing them.\n\
-      --build-index                   build the index file for the specified 
file.\n"),
+      --build-index                   build the index file for the specified 
file.\n\
+      --add-index=FIELD,...           add an index for specified fields.\n"),
          stdout);
 
 #if defined REC_CRYPT_SUPPORT
@@ -169,6 +178,12 @@ De/Encryption options:\n\
 #endif /* REC_CRYPT_SUPPORT */
 
   puts("");
+  fputs (_("\
+Index options:\n\
+  -t, --type=TYPE                     add the index for records of the 
specified type.\n"),
+         stdout);
+
+  puts("");
   /* TRANSLATORS: --help output, notes on recfix.
      no-wrap */
   fputs (_("\
@@ -188,7 +203,7 @@ recfix_parse_args (int argc,
 
   while ((ret = getopt_long (argc,
                              argv,
-                             ENCRYPTION_SHORT_ARGS,
+                             ENCRYPTION_SHORT_ARGS "t:",
                              GNU_longOptions,
                              NULL)) != -1)
     {
@@ -270,6 +285,39 @@ recfix_parse_args (int argc,
             recfix_op = RECFIX_OP_BUILD_INDEX;
             break;
           }
+        case TYPE_ARG:
+        case 't':
+          {
+            recfix_type = xstrdup (optarg);
+            if (!rec_field_name_p (recfix_type))
+              {
+                recutl_fatal ("invalid record type %s\n",
+                              recfix_type);
+              }
+            break;
+          }
+        case OP_ADD_INDEX_ARG:
+          {
+            if (recfix_op != RECFIX_OP_INVALID)
+              {
+                recutl_fatal (_("please specify just one operation.\n"));
+              }
+
+            recfix_op = RECFIX_OP_ADD_INDEX;
+
+            /* Parse the field names.  */
+            if (!rec_fex_check (optarg, REC_FEX_CSV))
+              {
+                recutl_fatal (_("invalid field names in --add-index.\n"));
+              }
+
+            recfix_index_fields = rec_fex_new (optarg, REC_FEX_CSV);
+            if (!recfix_index_fields)
+              {
+                recutl_fatal (_("internal error creating fex.\n"));
+              }
+            break;
+          }
 #if defined REC_CRYPT_SUPPORT
         case OP_ENCRYPT_ARG:
           {
@@ -790,6 +838,175 @@ recfix_do_build_index (void)
   return res ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
+static int
+recfix_do_add_index (void)
+{
+  FILE *recfile, *idx = NULL;
+  rec_db_t db;
+  int64_t time, index_type;
+  size_t size, index_size, n_fields, n, rset_number;
+  char *index_name;
+  rec_idx_file_t idx_file = NULL;
+  bool res = true;
+  uint8_t *index_data = NULL;
+  rec_rset_t rset;
+  const char **field_names, *rset_type;
+  rec_idx_tree_key_t *field_types;
+  rec_fex_elem_t fex_elem;
+
+  if (!recfix_file)
+    {
+      recutl_fatal (_("a file name is required"));
+    }
+
+  /* Read the database.  */
+  db = rec_db_new ();
+  if (!db)
+    {
+      return EXIT_FAILURE;
+    }
+
+  recfile = fopen (recfix_file, "r");
+  if (!recfile || !recutl_parse_db_from_file (recfile, recfix_file, db))
+    {
+      res = false;
+    }
+
+  /* Get its metadata. */
+  if (res && !rec_idx_get_time_size (recfile, &time, &size))
+    {
+      res = false;
+    }
+
+  if (recfile)
+    {
+      fclose (recfile);
+    }
+
+  /* Get the rset. */
+  if (recfix_type)
+    {
+      for (rset_number = 0; rset_number < rec_db_size (db); rset_number++)
+        {
+          rset = rec_db_get_rset (db, rset_number);
+          rset_type = rec_rset_type (rset);
+          if ((rset_type != NULL) && !strcmp (rset_type, recfix_type))
+            {
+              break;
+            }
+        }
+
+      if (rset_number == rec_db_size (db))
+        {
+          recutl_fatal (_("unknown record type: %s.\n"), recfix_type);
+        }
+    }
+  else if (rec_db_size (db) == 1)
+    {
+      rset_number = 0;
+      rset = rec_db_get_rset (db, 0);
+    }
+  else
+    {
+      recutl_fatal (_("several record types found.  Please use -t to specify 
one.\n"));
+    }
+
+  /* Get the index file name. */
+  if (res)
+    {
+      index_name = rec_idx_get_file_name (recfix_file);
+      if (!index_name)
+        {
+          res = false;
+        }
+    }
+
+  /* Open the index file for read and write.  */
+  if (res)
+    {
+      idx = fopen (index_name, "r+b");
+      if (idx)
+        {
+          idx_file = rec_idx_file_new (idx);
+        }
+    }
+
+  if (!idx_file)
+    {
+      res = false;
+    }
+
+  /* Construct key type data. */
+  if (res)
+    {
+      n_fields = rec_fex_size (recfix_index_fields);
+      field_names = malloc (sizeof (*field_names) * n_fields);
+      field_types = malloc (sizeof (*field_types) * n_fields);
+
+      if (!field_names || !field_types)
+        {
+          res = false;
+        }
+    }
+
+  if (res)
+    {
+      for (n = 0; n < n_fields; n++)
+        {
+          fex_elem = rec_fex_get (recfix_index_fields, n);
+          field_names[n] = rec_fex_elem_field_name (fex_elem);
+          field_types[n] = REC_IDX_KEY_STRING;
+        }
+    }
+
+  /* Build the new index. */
+  if (res)
+    {
+      res = rec_idx_tree_build (rset, rset_number, n_fields,
+                                field_names, field_types,
+                                &index_data, &index_size, &index_type);
+    }
+
+  if (res)
+    {
+      res = rec_idx_build_add_index (idx, index_type, index_size,
+                                     (char *) index_data);
+      free (index_data);
+    }
+
+  if (field_names)
+    {
+      free (field_names);
+    }
+
+  if (field_types)
+    {
+      free (field_types);
+    }
+
+  if (res)
+    {
+      rec_idx_build_num_indices (idx, rec_idx_file_num_indices (idx_file) + 1);
+    }
+
+  if (db)
+    {
+      rec_db_destroy (db);
+    }
+
+  if (idx_file)
+    {
+      rec_idx_file_destroy (idx_file);
+    }
+
+  if (idx)
+    {
+      fclose (idx);
+    }
+
+  return res ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -826,6 +1043,11 @@ main (int argc, char *argv[])
         res = recfix_do_build_index ();
         break;
       }
+    case RECFIX_OP_ADD_INDEX:
+      {
+        res = recfix_do_add_index ();
+        break;
+      }
 #if defined REC_CRYPT_SUPPORT
     case RECFIX_OP_ENCRYPT:
     case RECFIX_OP_DECRYPT:
-- 
1.7.11.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]