40ae9e4d0e28c32711e6a6fd4d394f6769aedb9f
[apps/core/preloaded/print-service.git] / libptdb / ptdb.c
1 /*
2 *       Printservice
3 *
4 * Copyright 2012  Samsung Electronics Co., Ltd
5
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://floralicense.org/license/
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <alloca.h>
23 #include <libgen.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <pt_debug.h>
27
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <stdbool.h>
34
35 #include <pt_db.h>
36
37 #define TEMPLATE "/tmp/mobileprint/printXXXXXX"
38 #define FILE_NAME "printXXXXXX"
39 #define FILE_BASE_DIR "mobileprint/"
40 #define MASK_MODE 022
41 #define BUFF_SIZE 512
42 #define STR_PAR "Invalid parameters: "
43 #define STR_PTR "Invalid pointers: "
44
45 enum {
46         PIPE_READ = 0,
47         PIPE_WRITE = 1
48 };
49
50 typedef enum {
51         PT_MODELNAME = 0,
52         PT_PRODUCTNAME
53 } pt_search_key;
54
55 typedef enum {
56         PT_FILE_TMP = 0
57 } pt_file_type;
58
59 typedef enum {
60         PT_FREE_FILE_CLOSE = 0, /** Close file descriptor and free memory\
61                                                                 allocated for structure */
62         PT_FREE_FILE_DEL                /** The same as PT_FREE_FILE_CLOSE, plus delete file\
63                                                                 from file-system */
64 } pt_free_file_type;
65
66 typedef struct {
67         uint32_t *buffer;
68         uint32_t len;
69 } info;
70
71 typedef struct {
72         uint32_t *buffer;
73         uint32_t len;
74 } prod;
75
76 typedef struct {
77         uint32_t name;
78         prod product;
79         info inform;
80 } model;
81
82 typedef struct {
83         char *value;
84         char *modified;
85 } outstr;
86
87 typedef struct {
88         pt_file_type file_type;
89         char *file_dir;
90         char *file_name;
91 } pt_file_info;
92
93 typedef struct {
94         FILE *ptfile;
95         const char *ptpath;
96 } pt_file;
97
98 /* Create file */
99 static pt_file *pt_create_file(pt_file_info *file_info);
100
101 /* Set information of file */
102 static pt_file_info *pt_create_file_info(char *name, char *dir, pt_file_type type);
103
104 /* Synchronize a file's in-core state with storage device. */
105 static int pt_sync_file(pt_file *file);
106
107 /* Execute ppdc command with predefined set of parameters */
108 static char *pt_exec_ppdc(pt_file *file);
109
110 /* Read and parse drv file */
111 /* Return parsed structure */
112 static drvm *read_drv(FILE *FD);
113
114 static pt_dbconfig *pt_tune_db(FILE *file, const char *path);
115
116 /* Extract specific drv file from database by modelname */
117 static pt_file *extract_drv_by_model(drvm drv, const char *modelname);
118
119 /* Extract specific drv file from database by product */
120 static pt_file *extract_drv_by_product(drvm drv, const char *product);
121
122 /* Extract specific drv file from database by specified key */
123 static pt_file *extract_drv_by_key(drvm drv, const char *key, pt_search_key type);
124
125 /* Read and parse drv file */
126 /* Return model structure */
127 static model *read_model(FILE* FD);
128
129 /* Extract value of search key accordingly    */
130 /* specification of drv file */
131 static char *filter(char *string, pt_search_key key);
132
133 /* Return value of a string, deleting quotes */
134 static outstr *filter_string(const char *original);
135
136 /* Extraction value of Product */
137 /* accordingly specification of drv file */
138 static char *filter_product(char *original, pt_search_key key);
139
140 /* Read all data from file/pipe */
141 static char *reliable_read(int fd);
142
143 /* Get size of file in bytes */
144 static int get_file_size(const char *path);
145
146 static void pt_free_dbconfig(pt_dbconfig *dbconfig);
147
148 static void pt_free_config(pt_dbconfig *config);
149
150 /* Free memory allocated by drvm structure */
151 static void pt_free_drvm(drvm *drv);
152
153 /* Clean resources linked with file */
154 static int pt_free_file(pt_file *file, pt_free_file_type free_type);
155
156 /* Free memory allocated by pt_file_info structure */
157 static void pt_free_file_info(pt_file_info *file_info);
158
159 /* Free memory allocated by prod structure */
160 static void pt_free_prod(prod *product);
161
162 /* Free memory allocated by string */
163 static void pt_free_strings(gpointer data);
164
165 /* Free memory allocated by model structure */
166 static void pt_free_model(gpointer data);
167
168 /* Free memory allocated by info structure */
169 static void pt_free_info(info *inf);
170
171 /* Clean memory of allocated outstr structure */
172 static void clean_outstr(outstr *ostr);
173
174 int get_file_size(const char *path)
175 {
176         struct stat statbuff;
177         if(stat(path, &statbuff)) {
178                 return -1;
179         }
180         return statbuff.st_size;
181 }
182
183 void pt_free_file_info(pt_file_info *file_info)
184 {
185         if(file_info) {
186                 if(file_info->file_dir) {
187                         free(file_info->file_dir);
188                 }
189
190                 if(file_info->file_name) {
191                         free(file_info->file_name);
192                 }
193
194                 free(file_info);
195         }
196 }
197
198 pt_file_info *pt_create_file_info(char *name, char *dir, pt_file_type type)
199 {
200         pt_file_info *info = (pt_file_info*)malloc(sizeof(pt_file_info));
201         if(!info) {
202                 return NULL;
203         }
204         memset(info, '\0', sizeof(pt_file_info));
205         char *tmp_name = NULL;
206         if(name) {
207                 tmp_name = strdup(name);
208                 if(!tmp_name) {
209                         fprintf(stderr, "String duplicating fails\n");
210                         pt_free_file_info(info);
211                         return NULL;
212                 }
213                 info->file_name = tmp_name;
214         } else {
215                 info->file_name = NULL;
216         }
217
218         char *tmp_dir = NULL;
219         if(dir) {
220                 tmp_dir = strdup(dir);
221                 if(!tmp_dir) {
222                         fprintf(stderr, "String duplicating fails\n");
223                         pt_free_file_info(info);
224                         free(tmp_name);
225                         return NULL;
226                 }
227                 info->file_dir = tmp_dir;
228         } else {
229                 info->file_dir = NULL;
230         }
231
232         info->file_type = type;
233         return info;
234 }
235
236 int pt_sync_file(pt_file *file)
237 {
238         if(!file) {
239                 return -1;
240         }
241
242         if(!file->ptfile) {
243                 return -1;
244         }
245
246         int res = fflush(file->ptfile);
247         return res;
248 }
249
250 int pt_free_file(pt_file *file, pt_free_file_type free_type)
251 {
252         if(!file) {
253                 return -1;
254         }
255         if(!file->ptpath) {
256                 return -1;
257         }
258         if(!file->ptfile) {
259                 return -1;
260         }
261
262         if(free_type == PT_FREE_FILE_CLOSE) {
263                 if(fclose(file->ptfile)) {
264                         return -1;
265                 }
266                 free((void *)file->ptpath);
267                 free(file);
268         } else if(free_type == PT_FREE_FILE_DEL) {
269                 if(fclose(file->ptfile)) {
270                         return -1;
271                 }
272                 if(unlink(file->ptpath)) {
273                         return -1;
274                 }
275                 free((void *)file->ptpath);
276                 free(file);
277         }
278         return 0;
279 }
280
281 pt_file *pt_create_file(pt_file_info *file_info)
282 {
283         FILE *fd = NULL;
284         char *file = NULL;
285
286         if(!file_info) {
287                 return NULL;
288         }
289
290         if(file_info->file_type == PT_FILE_TMP) {
291                 char *string = strdup(TEMPLATE);
292                 if(!string) {
293                         perror("Can't duplicate string with strdup()");
294                         return NULL;
295                 }
296
297                 char *drname = dirname(string);
298                 if(g_mkdir_with_parents(drname, S_IRWXU | S_IRWXG) == -1) {
299                         perror("Can't create nested directory path");
300                         PT_IF_FREE_MEM(string);
301                         return NULL;
302                 }
303                 PT_IF_FREE_MEM(string);
304
305                 file = strdup(TEMPLATE);
306                 if (!file) {
307                         fprintf(stderr, "Can't duplicate string with strdup()\n");
308                         return NULL;
309                 }
310
311                 umask(MASK_MODE);
312                 int filedesc = mkstemp(file);
313                 if (filedesc == -1) {
314                         perror("Can't create temp file");
315                         PT_IF_FREE_MEM(file);
316                         return NULL;
317                 }
318
319                 fd = fdopen(filedesc, "w");
320                 if(!fd) {
321                         fprintf(stderr, "Call fdopen() failed\n");
322                         if(close(filedesc)) {
323                                 fprintf(stderr, "Closing file descriptor fails\n");
324                         }
325                         int rst = unlink(file);
326                         if(rst) {
327                                 fprintf(stderr, "Unlink temporary file fails\n");
328                         }
329                         PT_IF_FREE_MEM(file);
330                         return NULL;
331                 }
332
333         } else {
334                 fprintf(stderr, "pt_create_file: Not yet fully supported\n");
335                 return NULL;
336         }
337
338         pt_file *ptfile = (pt_file *)malloc(sizeof(pt_file));
339         if(!ptfile) {
340                 fprintf(stderr, "Allocating memory fails\n");
341                 if(fclose(fd)) {
342                         PT_ERROR("File error: %s", strerror(errno));
343                 }
344                 PT_IF_FREE_MEM(file);
345                 return NULL;
346         }
347         memset(ptfile, '\0', sizeof(pt_file));
348
349         ptfile->ptfile = fd;
350         ptfile->ptpath = file;
351         return ptfile;
352 }
353
354 char *reliable_read(int fd)
355 {
356         char *new_buffer;
357         char *buffer = malloc(BUFF_SIZE);
358         if (!buffer) {
359                 fprintf(stderr, "call malloc() failed: %s\n", strerror(errno));
360                 return NULL;
361         }
362         memset(buffer, '\0', BUFF_SIZE);
363
364         new_buffer = buffer;
365         ssize_t rst = 0;
366         ssize_t global = 0;
367         size_t count = BUFF_SIZE;
368         size_t new_size = count;
369         while((rst = read(fd, buffer, count)) != -1) {
370                 if(rst > 0) {
371                         global += rst;
372                         count -= rst;
373                         continue;
374                 } else if(rst == 0) {
375                         if (global == new_size) {
376                                 // we didn't read all data
377                                 new_size = BUFF_SIZE + BUFF_SIZE;
378                                 if (!(new_buffer = malloc(new_size))) {
379                                         free(buffer);
380                                         return NULL;
381                                 }
382                                 memset(new_buffer, '\0', new_size);
383                                 strncpy(new_buffer, buffer, BUFF_SIZE);
384                                 free(buffer);
385                                 buffer = new_buffer;
386                         }
387                         break;
388                 }
389         }
390         return buffer;
391 }
392
393 char *pt_exec_ppdc(pt_file *file)
394 {
395         int pipefd[2];
396         char *buffer = NULL;
397
398         if(!file) {
399                 return NULL;
400         }
401
402         if (pipe(pipefd))
403         {
404                 PT_ERROR("pipe fail");
405                 return NULL;
406         }
407
408         pid_t pid;
409         if((pid = fork()) < 0) {
410                 PT_ERROR("Forking process fail");
411                 return NULL;
412         } else if (pid == 0) {
413
414                         if (dup2(pipefd[PIPE_READ], STDIN_FILENO) == -1) {
415                                 return NULL;
416                         }
417
418                         if (dup2(pipefd[PIPE_WRITE], STDOUT_FILENO) == -1) {
419                                 return NULL;
420                         }
421
422                         if (dup2(pipefd[PIPE_WRITE], STDERR_FILENO) == -1) {
423                                 return NULL;
424                         }
425
426                         if(close(pipefd[PIPE_READ])) {
427                                 return NULL;
428                         }
429
430                         // First we remove all locale variables
431                         if(unsetenv("LANG") || unsetenv("LANGUAGE") || unsetenv("LC_ALL")) {
432                                 PT_ERROR("Unsetting locale variables fails");
433                                 return NULL;
434                         }
435
436                         if(!setenv("LC_ALL", "POSIX", true)) {
437                                 PT_INFO("Successfully adjust environment for ppdc");
438                         } else {
439                                 PT_ERROR("Adjust environment for ppdc fails");
440                                 return NULL;
441                         }
442
443                         if (execl("/usr/bin/ppdc", "ppdc", "-v",\
444                                 "-d", ".", file->ptpath, (const char*) NULL)) {
445
446                                 if (execl("/bin/ppdc", "ppdc", "-v",\
447                                         "-d", ".", file->ptpath, (const char*) NULL)) {
448
449                                         PT_ERROR("Executing process fail");
450                                         return NULL;
451                                 }
452                         }
453                         PT_ERROR("Executing process fail");
454                         return NULL;
455         }
456
457         close(pipefd[PIPE_WRITE]);
458
459         int status;
460         pid_t child = wait(&status);
461         if (child != pid) {
462                 return NULL;
463         }
464
465         if(WIFEXITED(status)) {
466                 if (WEXITSTATUS(status) != 0) {
467                         return NULL;
468                 } else {
469                         buffer = reliable_read(pipefd[PIPE_READ]);
470                 }
471         } else {
472                 return NULL;
473         }
474
475         return buffer;
476 }
477
478 pt_file *extract_drv_by_key(drvm drv, const char *key, pt_search_key type)
479 {
480         pt_file *file = NULL;
481         GPtrArray *strings = drv.strings;
482         GPtrArray *models = drv.models;
483
484         guint len = models->len;
485
486         char *name;
487         model *mod;
488         for (int i = 0; i < len; ++i) {
489                 bool correct = false;
490                 mod = g_ptr_array_index(models, i);
491                 if (type == PT_MODELNAME) {
492                         name = g_ptr_array_index(strings, mod->name);
493                         name = filter(name, PT_MODELNAME);
494                         if(name) {
495                                 if(!strcasecmp(key, name)) {
496                                         free(name);
497                                         correct = true;
498                                 } else {
499                                         free(name);
500                                         continue;
501                                 }
502                         } else {
503                                 continue;
504                         }
505                 } else if (type == PT_PRODUCTNAME) {
506                         uint32_t value;
507                         uint32_t prod_len  = (mod->product).len;
508                         int *counter = (mod->product).buffer;
509                         for (int k = 0; k < prod_len; ++k) {
510                                 value = *counter++;
511                                 name = g_ptr_array_index(strings, value);
512                                 name = filter_product(name, PT_PRODUCTNAME);
513                                 if (!name) {
514                                         continue;
515                                 }
516
517                                 if (strcasecmp(key, name)) {
518                                         free(name);
519                                         continue;
520                                 }
521                                 free(name);
522                                 correct = true;
523                                 break;
524                         }
525                 }
526
527                 if (!correct) {
528                         continue;
529                 }
530
531                 pt_file_info *file_info = pt_create_file_info(NULL, NULL, PT_FILE_TMP);
532                 if(!file_info) {
533                         fprintf(stderr, "Setting file mode fails\n");
534                         return NULL;
535                 }
536
537                 file = pt_create_file(file_info);
538                 if(!file) {
539                         pt_free_file_info(file_info);
540                         fprintf(stderr, "Creating file fails\n");
541                         return NULL;
542                 }
543
544                 char *numstr;
545                 int line = (mod->inform).len;
546                 for (int i = 0; i < line; ++i) {
547                         uint32_t num = (mod->inform).buffer[i];
548                         numstr = g_ptr_array_index(strings, num);
549                         if(fputs(numstr, file->ptfile) == EOF) {
550                                 fprintf(stderr, "Writing data to temp file failed\n");
551                                 // FIXME: Here we should free memory
552                                 pt_free_file_info(file_info);
553                                 if(pt_free_file(file, PT_FREE_FILE_DEL)) {
554                                         fprintf(stderr, "Deleting temporary file fails\n");
555                                 }
556                                 return NULL;
557                         }
558                 }
559
560                 pt_free_file_info(file_info);
561                 if(pt_sync_file(file)) {
562                         fprintf(stderr, "Synchronize file with storage device fails\n");
563                         if(pt_free_file(file, PT_FREE_FILE_DEL)) {
564                                 fprintf(stderr, "Deleting temporary file fails\n");
565                         }
566                         return NULL;
567                 }
568                 break;
569         }
570         return file;
571 }
572
573 pt_file *extract_drv_by_model(drvm drv, const char *modelname)
574 {
575         pt_file *file;
576         file = extract_drv_by_key(drv, modelname, PT_MODELNAME);
577         return file;
578 }
579
580 pt_file *extract_drv_by_product(drvm drv, const char *product)
581 {
582         pt_file *file;
583         file = extract_drv_by_key(drv, product, PT_PRODUCTNAME);
584         return file;
585 }
586
587 void pt_free_drvm(drvm *drv)
588 {
589         if(drv)
590         {
591                 if(drv->models) {
592                         GPtrArray *models = drv->models;
593
594                         g_ptr_array_set_free_func(models, pt_free_model);
595                         g_ptr_array_free(models, TRUE);
596                 }
597
598                 if(drv->strings) {
599                         GPtrArray *strings = drv->strings;
600
601                         g_ptr_array_set_free_func(strings, pt_free_strings);
602                         g_ptr_array_free(strings, TRUE);
603                 }
604                 free((void*)drv);
605         }
606 }
607
608 void clean_outstr(outstr *ostr)
609 {
610         if(ostr) {
611                 if(ostr->value) {
612                         free(ostr->value);
613                 }
614         }
615 }
616
617 outstr *filter_string(const char *original)
618 {
619         char *value = NULL;
620         char *begin = NULL, *end = NULL, *word = NULL;
621
622         if(!original) {
623                 PT_ERROR("Argument is NULL");
624                 return NULL;
625         }
626
627         outstr *string = (outstr*)malloc(sizeof(outstr));
628         if(!string) {
629                 fprintf(stderr, "Allocating memory fails\n");
630                 return NULL;
631         }
632         memset(string, '\0', sizeof(outstr));
633
634         ptrdiff_t strln = 0;
635         begin = (char *)original;
636
637         unsigned char count = 0;
638
639         while(isblank(*begin)) {
640                 begin++;
641         }
642
643         word = begin;
644
645         while(*begin != '\0') {
646                 if (*begin == '"') {
647                         count++;
648                         begin++;
649                         break;
650                 } else if ((isblank(*begin)) && (count == 0)) {
651                         end = begin;
652                         begin = word;
653                         strln = end - begin;
654                         value = malloc(strln+1);
655                         if (!value) {
656                                 clean_outstr(string);
657                                 free(string);
658                                 fprintf(stderr, "Can't allocate memory\n");
659                                 return NULL;
660                         }
661                         memset(value, '\0', strln+1);
662                         strncpy(value, begin, strln);
663                         string->value = value;
664                         string->modified = end;
665                         return string;
666                 } else {
667                         begin++;
668                 }
669         }
670
671         if (count == 0) {
672                 end = begin;
673                 begin = word;
674                 value = malloc(strln+1);
675                 if (!value) {
676                         clean_outstr(string);
677                         free(string);
678                         fprintf(stderr, "Can't allocate memory\n");
679                         return NULL;
680                 }
681                 memset(value, '\0', strln+1);
682                 strncpy(value, begin, strln);
683                 string->value = value;
684                 string->modified = end;
685                 return string;
686         } else {
687                 end = begin;
688         }
689
690         while(*end != '\0') {
691                 if (*end == '"') {
692                         count--;
693                         break;
694                 }
695                 end++;
696         }
697
698         strln = end - begin;
699         value = malloc(strln+1);
700         if (!value) {
701                 clean_outstr(string);
702                 free(string);
703                 fprintf(stderr, "Can't allocate memory\n");
704                 return NULL;
705         }
706         memset(value, '\0', strln+1);
707         strncpy(value, begin, strln);
708         string->value = value;
709         end++;
710         string->modified = end;
711         return string;
712 }
713
714 char *filter_product(char *original, pt_search_key key)
715 {
716         const char *pname = "Product";
717         const char *attr = "Attribute";
718         outstr *result = NULL;
719
720         if (!original) {
721                 fprintf(stderr, "original is null\n");
722                 return NULL;
723         }
724         char *copied = malloc(strlen(original)+1);
725         if (!copied) {
726                 fprintf(stderr, "Can't allocate memory\n");
727                 return NULL;
728         }
729
730         char *full_string = copied;
731         char *modified = NULL;
732         char *value = NULL;
733
734         strcpy(copied, original);
735         result = filter_string(copied);
736         if(!result) {
737                 PT_ERROR("Error in processing string");
738                 free(full_string);
739                 return NULL;
740         }
741         modified = result->modified;
742         value = result->value;
743         free(result);
744
745         if (!strncmp(value, attr, strlen(attr))) {
746                 result = filter_string(modified);
747                 if(!result) {
748                         PT_ERROR("Error in processing string");
749                         free(value);
750                         free(full_string);
751                         return NULL;
752                 }
753                 free(value);
754                 modified = result->modified;
755                 value = result->value;
756                 free(result);
757
758                 if(!strncmp(value, pname, strlen(pname))) {
759                         result = filter_string(modified);
760                         if(!result) {
761                                 PT_ERROR("Error in processing string");
762                                 free(value);
763                                 free(full_string);
764                                 return NULL;
765                         }
766                         free(value);
767                         modified = result->modified;
768                         value = result->value;
769                         free(result);
770
771                         result = filter_string(modified);
772                         free(value);
773                         value = result->value;
774                         free(result);
775                 } else {
776                         free(value);
777                         free(full_string);
778                         return NULL;
779                 }
780         } else {
781                 free(value);
782                 free(full_string);
783                 return NULL;
784         }
785
786         free(full_string);
787         return value;
788 }
789
790 char *filter(char *original, pt_search_key key)
791 {
792         static const char *mname = "ModelName";
793         static const char *delim = " \t";
794         static const char *delim_str = "\"";
795         static const char *end = "\n";
796
797         char *value = NULL;
798         char *token = NULL;
799         char *copied = malloc(strlen(original)+1);
800         if (!copied) {
801                 fprintf(stderr, "Can't allocate memory\n");
802                 return NULL;
803         }
804         char *full_string = copied;
805
806         strcpy(copied, original);
807         while(isblank(*copied)) {
808                 copied++;
809                 continue;
810         }
811
812         token = strsep(&copied, delim);
813         if (!strcmp(token, mname)) {
814                 token = strsep(&copied, delim_str);
815                 if(!strcmp(token, "")) {
816                         token = strsep(&copied, delim_str);
817                         value = malloc(strlen(token)+1);
818                         if (!value) {
819                                 free(full_string);
820                                 fprintf(stderr, "Can't allocate memory\n");
821                                 return NULL;
822                         }
823                         strcpy(value, token);
824                         token = strsep(&copied, end);
825                         while(*token != '\0') {
826                                 if(isblank(*token)) {
827                                         token++;
828                                         continue;
829                                 } else {
830                                         free(full_string);
831                                         free(value);
832                                         printf("String contains unexpected symbols:\n");
833                                         printf("%s\n", original);
834                                         return NULL;
835                                 }
836                         }
837                 } else {
838                         free(full_string);
839                         printf("String which contains %s is not correct", original);
840                         return NULL;
841                 }
842         }
843         free(full_string);
844         return value;
845 }
846
847 void pt_free_prod(prod *product)
848 {
849         if(product) {
850                 if(product->buffer) {
851                         free(product->buffer);
852                 }
853         }
854 }
855
856 void pt_free_strings(gpointer data)
857 {
858         if(data) {
859                 free((char*)data);
860         }
861 }
862
863 void pt_free_model(gpointer data)
864 {
865         if(data)
866         {
867                 model *mod = (model *)data;
868                 pt_free_prod(&(mod->product));
869                 pt_free_info(&(mod->inform));
870                 free(mod);
871         }
872 }
873
874 drvm *read_drv(FILE *fd)
875 {
876         size_t result;
877         drvm *drv;
878         GPtrArray *models;
879         GPtrArray *strings;
880
881         drv = (drvm *)calloc(1, sizeof(drvm));
882         if (!drv) {
883                 fprintf(stderr, "Can't allocate memory\n");
884                 return NULL;
885         }
886
887         uint32_t len;
888
889         result = fread(&len, sizeof(uint32_t), 1, fd);
890         if (result != 1) {
891                 fprintf(stderr, "Can't read data from file\n");
892                 pt_free_drvm(drv);
893                 return NULL;
894         }
895
896         if(len == 0 || len > UINT32_MAX) {
897                 fprintf(stderr, "Invalid length(%d)\n", len);
898                 pt_free_drvm(drv);
899                 return NULL;
900         }
901
902         size_t elm_size = sizeof(model*);
903         uint32_t length = len;
904         size_t res_size = length * elm_size;
905
906         models = g_ptr_array_sized_new(length);
907         drv->models = models;
908
909         model *mod;
910         for (int i = 0; i < length; ++i) {
911                 mod = read_model(fd);
912                 g_ptr_array_add(models, mod);
913         }
914
915         g_ptr_array_set_free_func(models, pt_free_model);
916
917         result = fread(&len, sizeof(uint32_t), 1, fd);
918         if (result != 1) {
919                 fprintf(stderr, "Can't read data from file\n");
920                 void *ptr = g_ptr_array_free(models, TRUE);
921                 if(ptr) {
922                         perror("freeing memory fails");
923                 }
924                 free(drv);
925                 return NULL;
926         }
927
928         if (len == 0 || len > UINT32_MAX) {
929                 fprintf(stderr, "Invalid length(%d)\n", len);
930                 pt_free_drvm(drv);
931                 return NULL;
932         }
933
934         elm_size = sizeof(char *);
935         length = len;
936         res_size = length * elm_size;
937         strings = g_ptr_array_sized_new(length);
938         g_ptr_array_set_free_func(strings, pt_free_strings);
939         drv->strings = strings;
940
941         char *string;
942         size_t size_buffer;
943         ssize_t read;
944         for (int i = 0; i < length; ++i) {
945                 string = NULL;
946                 if((read = getline(&string, &size_buffer, fd)) == -1) {
947                         fprintf(stderr, "Can't read line from file\n");
948                         void *ptr = g_ptr_array_free(strings, TRUE);
949                         if(ptr) {
950                                 perror("freeing memory fails");
951                         }
952                         ptr = g_ptr_array_free(models, TRUE);
953                         if(ptr) {
954                                 perror("freeing memory fails");
955                         }
956                         free(drv);
957                         return NULL;
958                 }
959                 g_ptr_array_add(strings, string);
960         }
961
962         return drv;
963 }
964
965 model *read_model(FILE *fd)
966 {
967         model *mod;
968         size_t result;
969         uint32_t length;
970
971         mod = malloc(sizeof(model));
972         uint32_t len;
973         if (!mod) {
974                 fprintf(stderr, "Can't allocate memory\n");
975                 return NULL;
976         }
977
978         result = fread(&len, sizeof(uint32_t), 1, fd);
979         if(result != 1) {
980                 fprintf(stderr, "Can't read data from file\n");
981                 pt_free_model(mod);
982                 return NULL;
983         }
984
985         length = len;
986         mod->name = length;
987
988         result = fread(&len, sizeof(uint32_t), 1, fd);
989         if(result != 1) {
990                 fprintf(stderr, "Can't read data from file\n");
991                 pt_free_model(mod);
992                 return NULL;
993         }
994
995         if(len == 0 || len > UINT32_MAX) {
996                 fprintf(stderr, "Invalid length(%d)\n", len);
997                 pt_free_model(mod);
998                 return NULL;
999         }
1000
1001         length = len;
1002         if ((length >> 30) > 0)
1003         {
1004                 fprintf(stderr, "Integer overflow\n");
1005                 pt_free_model(mod);
1006                 return NULL;
1007         }
1008
1009         uint32_t size_buffer = length * sizeof(uint32_t);
1010
1011         if(!((mod->product).buffer = malloc(size_buffer))) {
1012                 fprintf(stderr, "Can't allocate memory\n");
1013                 pt_free_model(mod);
1014                 return NULL;
1015         }
1016         (mod->product).len = length;
1017
1018         result = fread((mod->product).buffer, size_buffer, 1, fd);
1019         if(result != 1) {
1020                 fprintf(stderr, "Can't read data from file\n");
1021                 pt_free_model(mod);
1022                 return NULL;
1023         }
1024
1025         // Parse part related to product
1026
1027         result = fread(&len, sizeof(uint32_t), 1, fd);
1028         if(result != 1) {
1029                 fprintf(stderr, "Can't read data from file\n");
1030                 pt_free_model(mod);
1031                 return NULL;
1032         }
1033
1034         if(len == 0 || len > UINT32_MAX) {
1035                 fprintf(stderr, "Invalid length(%d)\n", len);
1036                 pt_free_model(mod);
1037                 return NULL;
1038         }
1039
1040         length = len;
1041         if ((length>>(32 - sizeof(uint32_t))) > 0)
1042         {
1043                 fprintf(stderr, "Integer overflow\n");
1044                 pt_free_model(mod);
1045                 return NULL;
1046         }
1047
1048         size_buffer = length * sizeof(uint32_t);
1049         if(!(mod->inform.buffer = malloc(size_buffer))) {
1050                 fprintf(stderr, "Can't allocate memory\n");
1051                 pt_free_model(mod);
1052                 return NULL;
1053         }
1054         mod->inform.len = length;
1055         result = fread(mod->inform.buffer, size_buffer, 1, fd);
1056         if(result != 1) {
1057                 fprintf(stderr, "Can't read data from file\n");
1058                 pt_free_model(mod);
1059                 return NULL;
1060         }
1061
1062         return mod;
1063 }
1064
1065 void pt_free_info(info *inf)
1066 {
1067         if(inf) {
1068                 if(inf->buffer) {
1069                         free(inf->buffer);
1070                 }
1071         }
1072 }
1073
1074 pt_dbconfig *pt_tune_db(FILE *file, const char *path)
1075 {
1076         if(!file) {
1077                 PT_ERROR(STR_PAR "%p", file);
1078                 return NULL;
1079         }
1080
1081         if(!path) {
1082                 PT_ERROR(STR_PAR "%p", path);
1083                 return NULL;
1084         }
1085
1086         char *copied_path = strdup(path);
1087         if(!copied_path) {
1088                 PT_ERROR("Allocating memory fail");
1089                 return NULL;
1090         }
1091
1092         int size = get_file_size(copied_path);
1093         if(size == -1) {
1094                 PT_ERROR("Getting info about file fail");
1095                 free(copied_path);
1096                 return NULL;
1097         }
1098
1099         char *buffer = malloc(size);
1100         if (!buffer) {
1101                 PT_ERROR("Allocating memory fail");
1102                 free(copied_path);
1103                 return NULL;
1104         }
1105
1106         int result = setvbuf(file, buffer, _IOFBF,  size);
1107         if (result) {
1108                 PT_ERROR("Tuning buffering operations fail");
1109                 free(copied_path);
1110                 free(buffer);
1111                 return NULL;
1112         }
1113
1114         pt_dbconfig *config;
1115         config = (pt_dbconfig*)malloc(sizeof(pt_dbconfig));
1116         if(!config) {
1117                 PT_ERROR("Allocating memory fail");
1118                 free(copied_path);
1119                 free(buffer);
1120                 return NULL;
1121         }
1122         memset(config, '\0', sizeof(pt_dbconfig));
1123         config->dbfile = file;
1124         config->dbpath = copied_path;
1125         config->dbbuffer = buffer;
1126         return config;
1127 }
1128
1129 void pt_free_config(pt_dbconfig *config)
1130 {
1131         if(!config) {
1132                 PT_ERROR(STR_PTR "%p", config);
1133         } else {
1134                 if(config->dbbuffer) {
1135                         free((void *)config->dbbuffer);
1136                 }
1137                 if(config->dbpath) {
1138                         free((void *)config->dbpath);
1139                 }
1140                 free(config);
1141         }
1142 }
1143
1144 char* pt_extract_ppd(pt_db *database, const char *search, pt_search type)
1145 {
1146         if(!database || !search) {
1147                 PT_ERROR(STR_PAR "%p, %p", database, search);
1148                 return NULL;
1149         }
1150
1151         drvm* dbstruct = database->dbstruct;
1152
1153         if(!dbstruct) {
1154                 PT_ERROR(STR_PTR "%p", dbstruct);
1155                 return NULL;
1156         }
1157
1158         pt_file *file = NULL;
1159         if(type == PT_SEARCH_MODEL) {
1160                 file = extract_drv_by_model(*dbstruct, search);
1161         } else if(type == PT_SEARCH_PROD) {
1162                 file = extract_drv_by_product(*dbstruct, search);
1163         } else if(type == PT_SEARCH_ALL) {
1164                 file = extract_drv_by_model(*dbstruct, search);
1165                 if(!file) {
1166                         file = extract_drv_by_product(*dbstruct, search);
1167                 }
1168         } else {
1169                 PT_ERROR(STR_PAR "%d", type);
1170                 return NULL;
1171         }
1172
1173         if(!file) {
1174                 PT_ERROR("Didn't find \"%s\" in database", search);
1175                 return NULL;
1176         }
1177
1178         char *output = pt_exec_ppdc(file);
1179         if(!output) {
1180                 // Handle error
1181                 PT_ERROR("Executing ppdc fails\n");
1182                 if(pt_free_file(file, PT_FREE_FILE_DEL)) {
1183                         fprintf(stderr, "Freeing memory fails\n");
1184                 }
1185                 return NULL;
1186         }
1187
1188         if(pt_free_file(file, PT_FREE_FILE_DEL)) {
1189                 fprintf(stderr, "Freeing memory fails\n");
1190                 free(output);
1191                 return NULL;
1192         }
1193         return output;
1194 }
1195
1196 void pt_free_dbconfig(pt_dbconfig *dbconfig)
1197 {
1198         if(dbconfig) {
1199                 if(dbconfig->dbbuffer) {
1200                         free((void*)dbconfig->dbbuffer);
1201                 }
1202                 if(dbconfig->dbpath) {
1203                         free((void*)dbconfig->dbpath);
1204                 }
1205                 if(dbconfig->dbfile) {
1206                         fclose(dbconfig->dbfile);
1207                 }
1208         }
1209 }
1210
1211 void pt_free_db(pt_db *database)
1212 {
1213         if(database) {
1214                 if(database->dbconfig) {
1215                         pt_free_dbconfig(database->dbconfig);
1216                 }
1217                 if(database->dbstruct) {
1218                         pt_free_drvm(database->dbstruct);
1219                 }
1220         }
1221 }
1222
1223 pt_db *pt_create_db(const char *path)
1224 {
1225         if(!path) {
1226                 return NULL;
1227         }
1228
1229         FILE *dbfile = fopen(path, "rb");
1230         if (!dbfile) {
1231                 return NULL;
1232         }
1233
1234         pt_dbconfig *config;
1235         config = pt_tune_db(dbfile, path);
1236         if(!config) {
1237                 PT_ERROR("Tuning database fail");
1238                 fclose(dbfile);
1239                 return NULL;
1240         }
1241
1242         drvm *dbstruct = read_drv(dbfile);
1243         if(!dbstruct) {
1244                 pt_free_config(config);
1245                 fclose(dbfile);
1246                 return NULL;
1247         }
1248
1249         pt_db *database = (pt_db*)malloc(sizeof(pt_db));
1250         if(!database) {
1251                 pt_free_config(config);
1252                 pt_free_drvm(dbstruct);
1253                 fclose(dbfile);
1254                 return NULL;
1255         }
1256
1257         database->dbstruct = dbstruct;
1258         database->dbconfig = config;
1259         return database;
1260 }