1 /*
2  * ffindex_order
3  * written by Milot Mirdita <milot@mirdita.de>.
4  * Please add your name here if you distribute modified versions.
5  *
6  * FFindex is provided under the Create Commons license "Attribution-ShareAlike
7  * 4.0", which basically captures the spirit of the Gnu Public License (GPL).
8  *
9  * See:
10  * http://creativecommons.org/licenses/by-sa/4.0/
11  *
12  * ffindex_order
13  * Reorders the entries in a FFindex data file by the order given by file
14  * Each line of the order file must contain a key from the FFindex index.
15  * The FFindex data file entries will have the same order as the order file.
16 */
17 
18 #define _GNU_SOURCE 1
19 #define _LARGEFILE64_SOURCE 1
20 #define _FILE_OFFSET_BITS 64
21 
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 
28 #include "ffindex.h"
29 #include "ffutil.h"
30 
31 
main(int argc,char ** argv)32 int main(int argc, char **argv)
33 {
34   if(argc < 6)
35   {
36     fprintf(stderr, "USAGE: %s ORDER_FILENAME DATA_FILENAME INDEX_FILENAME SORTED_DATA_OUT_FILE SORTED_INDEX_OUT_FILE\n"
37                     "\nDesigned and implemented by Milot Mirdita <milot@mirdita.de>.\n",
38                     argv[0]);
39     return -1;
40   }
41 
42   char *order_filename = argv[1];
43 
44   char *data_filename  = argv[2];
45   char *index_filename = argv[3];
46 
47   char *sorted_data_filename  = argv[4];
48   char *sorted_index_filename = argv[5];
49 
50   FILE *order_file = fopen(order_filename, "r");
51 
52   FILE *data_file  = fopen(data_filename,  "r");
53   FILE *index_file = fopen(index_filename, "r");
54 
55   FILE *sorted_data_file  = fopen(sorted_data_filename,  "w+");
56   FILE *sorted_index_file = fopen(sorted_index_filename, "w+");
57 
58   if(order_file == NULL) { fferror_print(__FILE__, __LINE__, argv[0], order_filename);  exit(EXIT_FAILURE); }
59 
60   if( data_file == NULL) { fferror_print(__FILE__, __LINE__, argv[0], data_filename);  exit(EXIT_FAILURE); }
61   if(index_file == NULL) { fferror_print(__FILE__, __LINE__, argv[0], index_filename);  exit(EXIT_FAILURE); }
62 
63   if( sorted_data_file == NULL) { fferror_print(__FILE__, __LINE__, argv[0], sorted_data_filename);  exit(EXIT_FAILURE); }
64   if(sorted_index_file == NULL) { fferror_print(__FILE__, __LINE__, argv[0], sorted_index_filename);  exit(EXIT_FAILURE); }
65 
66   size_t data_size;
67   char *data = ffindex_mmap_data(data_file, &data_size);
68 
69   size_t entries = ffcount_lines(index_filename);
70   ffindex_index_t* index = ffindex_index_parse(index_file, entries);
71   if(index == NULL)  {
72     perror("ffindex_index_parse failed");
73     exit(EXIT_FAILURE);
74   }
75 
76 
77   char message[LINE_MAX];
78   char line[LINE_MAX];
79   int i = 0;
80   size_t offset = 0;
81   while (fgets(line, sizeof(line), order_file)) {
82     size_t len = strlen(line);
83     if (len && (line[len - 1] != '\n')) {
84       // line is incomplete
85       snprintf(message, LINE_MAX, "Warning: Line %d of order file %s was too long and cut-off.", i, order_filename);
86       fferror_print(__FILE__, __LINE__, argv[0], message);
87     }
88 
89     // remove new line
90     char *name = ffnchomp(line, len);
91     ffindex_entry_t* entry = ffindex_get_entry_by_name(index, name);
92 
93     if (entry != NULL) {
94       char* filedata = ffindex_get_data_by_entry(data, entry);
95       size_t entryLength = (entry->length == 0 ) ? 0 : entry->length - 1;
96       ffindex_insert_memory(sorted_data_file, sorted_index_file, &offset, filedata, entryLength, name);
97     }
98 
99     i++;
100   }
101 
102   // cleanup
103   fclose(sorted_data_file);
104   fclose(index_file);
105   fclose(data_file);
106   fclose(order_file);
107 
108   // sort FFindex index
109   fclose(sorted_index_file);
110   sorted_index_file = fopen(sorted_index_filename, "r+");
111   entries = ffcount_lines(index_filename);
112   index = ffindex_index_parse(sorted_index_file, entries);
113   if(index == NULL)  {
114     perror("ffindex_index_parse failed");
115     exit(EXIT_FAILURE);
116   }
117   fclose(sorted_index_file);
118 
119   ffindex_sort_index_file(index);
120   sorted_index_file = fopen(sorted_index_filename, "w");
121   if(sorted_index_file == NULL) {
122     perror(sorted_index_filename);
123     return EXIT_FAILURE;
124   }
125   int err = ffindex_write(index, sorted_index_file);
126   fclose(sorted_index_file);
127 
128   return err;
129 }
130 
131 /* vim: ts=2 sw=2 et
132  */
133