4 * Copyright 2013 Samsung Electronics Co., Ltd
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
10 * http://floralicense.org/license/
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.
24 #include <sys/types.h>
37 #define TEMPLATE "/tmp/mobileprint/printXXXXXX"
38 #define FILE_NAME "printXXXXXX"
39 #define FILE_BASE_DIR "mobileprint/"
42 #define STR_PAR "Invalid parameters: "
43 #define STR_PTR "Invalid pointers: "
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\
88 pt_file_type file_type;
99 static pt_file *pt_create_file(pt_file_info *file_info);
101 /* Set information of file */
102 static pt_file_info *pt_create_file_info(char *name, char *dir, pt_file_type type);
104 /* Synchronize a file's in-core state with storage device. */
105 static int pt_sync_file(pt_file *file);
107 /* Execute ppdc command with predefined set of parameters */
108 static char *pt_exec_ppdc(pt_file *file);
110 /* Read and parse drv file */
111 /* Return parsed structure */
112 static drvm *read_drv(FILE *FD);
114 static pt_dbconfig *pt_tune_db(FILE *file, const char *path);
116 /* Extract specific drv file from database by modelname */
117 static pt_file *extract_drv_by_model(drvm drv, const char *modelname);
119 /* Extract specific drv file from database by product */
120 static pt_file *extract_drv_by_product(drvm drv, const char *product);
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);
125 /* Read and parse drv file */
126 /* Return model structure */
127 static model *read_model(FILE* FD);
129 /* Extract value of search key accordingly */
130 /* specification of drv file */
131 static char *filter(char *string, pt_search_key key);
133 /* Return value of a string, deleting quotes */
134 static outstr *filter_string(const char *original);
136 /* Extraction value of Product */
137 /* accordingly specification of drv file */
138 static char *filter_product(char *original, pt_search_key key);
140 /* Read all data from file/pipe */
141 static char *reliable_read(int fd);
143 /* Get size of file in bytes */
144 static int get_file_size(const char *path);
146 static void pt_free_dbconfig(pt_dbconfig *dbconfig);
148 static void pt_free_config(pt_dbconfig *config);
150 /* Free memory allocated by drvm structure */
151 static void pt_free_drvm(drvm *drv);
153 /* Clean resources linked with file */
154 static int pt_free_file(pt_file *file, pt_free_file_type free_type);
156 /* Free memory allocated by pt_file_info structure */
157 static void pt_free_file_info(pt_file_info *file_info);
159 /* Free memory allocated by prod structure */
160 static void pt_free_prod(prod *product);
162 /* Free memory allocated by string */
163 static void pt_free_strings(gpointer data);
165 /* Free memory allocated by model structure */
166 static void pt_free_model(gpointer data);
168 /* Free memory allocated by info structure */
169 static void pt_free_info(info *inf);
171 /* Clean memory of allocated outstr structure */
172 static void clean_outstr(outstr *ostr);
174 int get_file_size(const char *path)
176 struct stat statbuff;
177 if(stat(path, &statbuff)) {
180 return statbuff.st_size;
183 void pt_free_file_info(pt_file_info *file_info)
186 if(file_info->file_dir) {
187 free(file_info->file_dir);
190 if(file_info->file_name) {
191 free(file_info->file_name);
198 pt_file_info *pt_create_file_info(char *name, char *dir, pt_file_type type)
200 pt_file_info *info = (pt_file_info*)malloc(sizeof(pt_file_info));
204 memset(info, '\0', sizeof(pt_file_info));
205 char *tmp_name = NULL;
207 tmp_name = strdup(name);
209 PT_ERROR("String duplicating fails");
210 pt_free_file_info(info);
213 info->file_name = tmp_name;
215 info->file_name = NULL;
218 char *tmp_dir = NULL;
220 tmp_dir = strdup(dir);
222 PT_ERROR("String duplicating fails");
223 pt_free_file_info(info);
227 info->file_dir = tmp_dir;
229 info->file_dir = NULL;
232 info->file_type = type;
236 int pt_sync_file(pt_file *file)
246 int res = fflush(file->ptfile);
250 int pt_free_file(pt_file *file, pt_free_file_type free_type)
262 if(free_type == PT_FREE_FILE_CLOSE) {
263 if(fclose(file->ptfile)) {
266 free((void *)file->ptpath);
268 } else if(free_type == PT_FREE_FILE_DEL) {
269 if(fclose(file->ptfile)) {
272 if(unlink(file->ptpath)) {
275 free((void *)file->ptpath);
281 pt_file *pt_create_file(pt_file_info *file_info)
290 if(file_info->file_type == PT_FILE_TMP) {
291 char *string = strdup(TEMPLATE);
293 PT_ERROR("Can't duplicate string with strdup()");
297 char *drname = dirname(string);
298 if(g_mkdir_with_parents(drname, S_IRWXU | S_IRWXG) == -1) {
299 PT_ERROR("Can't create nested directory path");
300 PT_IF_FREE_MEM(string);
303 PT_IF_FREE_MEM(string);
305 file = strdup(TEMPLATE);
307 PT_ERROR("Can't duplicate string with strdup()");
312 int filedesc = mkstemp(file);
313 if (filedesc == -1) {
314 PT_ERROR("Can't create temp file");
315 PT_IF_FREE_MEM(file);
319 fd = fdopen(filedesc, "w");
321 PT_ERROR("Call fdopen() failed");
322 if(close(filedesc)) {
323 PT_ERROR("Closing file descriptor fails");
325 int rst = unlink(file);
327 PT_ERROR("Unlink temporary file fails");
329 PT_IF_FREE_MEM(file);
334 PT_ERROR("pt_create_file: Not yet fully supported");
338 pt_file *ptfile = (pt_file *)malloc(sizeof(pt_file));
340 PT_ERROR("Allocating memory fails");
342 PT_ERROR("File error: %s", strerror(errno));
344 PT_IF_FREE_MEM(file);
347 memset(ptfile, '\0', sizeof(pt_file));
350 ptfile->ptpath = file;
354 char *reliable_read(int fd)
357 char *buffer = malloc(BUFF_SIZE);
359 PT_ERROR("call malloc() failed: %s", strerror(errno));
362 memset(buffer, '\0', BUFF_SIZE);
367 size_t count = BUFF_SIZE;
368 size_t new_size = count;
369 while((rst = read(fd, buffer, count)) != -1) {
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))) {
382 memset(new_buffer, '\0', new_size);
383 strncpy(new_buffer, buffer, BUFF_SIZE);
393 char *pt_exec_ppdc(pt_file *file)
404 PT_ERROR("pipe fail");
409 if((pid = fork()) < 0) {
410 PT_ERROR("Forking process fail");
412 } else if (pid == 0) {
414 if (dup2(pipefd[PIPE_READ], STDIN_FILENO) == -1) {
418 if (dup2(pipefd[PIPE_WRITE], STDOUT_FILENO) == -1) {
422 if (dup2(pipefd[PIPE_WRITE], STDERR_FILENO) == -1) {
426 if(close(pipefd[PIPE_READ])) {
430 // First we remove all locale variables
431 if(unsetenv("LANG") || unsetenv("LANGUAGE") || unsetenv("LC_ALL")) {
432 PT_ERROR("Unsetting locale variables fails");
436 if(!setenv("LC_ALL", "POSIX", true)) {
437 PT_INFO("Successfully adjust environment for ppdc");
439 PT_ERROR("Adjust environment for ppdc fails");
443 if (execl("/usr/bin/ppdc", "ppdc", "-v",\
444 "-d", ".", file->ptpath, (const char*) NULL)) {
446 if (execl("/bin/ppdc", "ppdc", "-v",\
447 "-d", ".", file->ptpath, (const char*) NULL)) {
449 PT_ERROR("Executing process fail");
453 PT_ERROR("Executing process fail");
457 close(pipefd[PIPE_WRITE]);
460 pid_t child = wait(&status);
465 if(WIFEXITED(status)) {
466 if (WEXITSTATUS(status) != 0) {
469 buffer = reliable_read(pipefd[PIPE_READ]);
478 pt_file *extract_drv_by_key(drvm drv, const char *key, pt_search_key type)
480 pt_file *file = NULL;
481 GPtrArray *strings = drv.strings;
482 GPtrArray *models = drv.models;
484 guint len = models->len;
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);
495 if(!strcasecmp(key, name)) {
505 } else if (type == PT_PRODUCTNAME) {
507 uint32_t prod_len = (mod->product).len;
508 int *counter = (mod->product).buffer;
509 for (int k = 0; k < prod_len; ++k) {
511 name = g_ptr_array_index(strings, value);
512 name = filter_product(name, PT_PRODUCTNAME);
517 if (strcasecmp(key, name)) {
531 pt_file_info *file_info = pt_create_file_info(NULL, NULL, PT_FILE_TMP);
533 PT_ERROR("Setting file mode fails");
537 file = pt_create_file(file_info);
539 pt_free_file_info(file_info);
540 PT_ERROR("Creating file fails");
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 PT_ERROR("Writing data to temp file failed");
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 PT_ERROR("Deleting temporary file fails");
560 pt_free_file_info(file_info);
561 if(pt_sync_file(file)) {
562 PT_ERROR("Synchronize file with storage device fails");
563 if(pt_free_file(file, PT_FREE_FILE_DEL)) {
564 PT_ERROR("Deleting temporary file fails");
573 pt_file *extract_drv_by_model(drvm drv, const char *modelname)
576 file = extract_drv_by_key(drv, modelname, PT_MODELNAME);
580 pt_file *extract_drv_by_product(drvm drv, const char *product)
583 file = extract_drv_by_key(drv, product, PT_PRODUCTNAME);
587 void pt_free_drvm(drvm *drv)
592 GPtrArray *models = drv->models;
594 g_ptr_array_set_free_func(models, pt_free_model);
595 g_ptr_array_free(models, TRUE);
599 GPtrArray *strings = drv->strings;
601 g_ptr_array_set_free_func(strings, pt_free_strings);
602 g_ptr_array_free(strings, TRUE);
608 void clean_outstr(outstr *ostr)
617 outstr *filter_string(const char *original)
620 char *begin = NULL, *end = NULL, *word = NULL;
623 PT_ERROR("Argument is NULL");
627 outstr *string = (outstr*)malloc(sizeof(outstr));
629 PT_ERROR("Allocating memory fails");
632 memset(string, '\0', sizeof(outstr));
635 begin = (char *)original;
637 unsigned char count = 0;
639 while(isblank(*begin)) {
645 while(*begin != '\0') {
650 } else if ((isblank(*begin)) && (count == 0)) {
654 value = malloc(strln+1);
656 clean_outstr(string);
658 PT_ERROR("Can't allocate memory");
661 memset(value, '\0', strln+1);
662 strncpy(value, begin, strln);
663 string->value = value;
664 string->modified = end;
674 value = malloc(strln+1);
676 clean_outstr(string);
678 PT_ERROR("Can't allocate memory");
681 memset(value, '\0', strln+1);
682 strncpy(value, begin, strln);
683 string->value = value;
684 string->modified = end;
690 while(*end != '\0') {
699 value = malloc(strln+1);
701 clean_outstr(string);
703 PT_ERROR("Can't allocate memory");
706 memset(value, '\0', strln+1);
707 strncpy(value, begin, strln);
708 string->value = value;
710 string->modified = end;
714 char *filter_product(char *original, pt_search_key key)
716 const char *pname = "Product";
717 const char *attr = "Attribute";
718 outstr *result = NULL;
721 PT_ERROR("original is null");
724 char *copied = malloc(strlen(original)+1);
726 PT_ERROR("Can't allocate memory");
730 char *full_string = copied;
731 char *modified = NULL;
734 strcpy(copied, original);
735 result = filter_string(copied);
737 PT_ERROR("Error in processing string");
741 modified = result->modified;
742 value = result->value;
745 if (!strncmp(value, attr, strlen(attr))) {
746 result = filter_string(modified);
748 PT_ERROR("Error in processing string");
754 modified = result->modified;
755 value = result->value;
758 if(!strncmp(value, pname, strlen(pname))) {
759 result = filter_string(modified);
761 PT_ERROR("Error in processing string");
767 modified = result->modified;
768 value = result->value;
771 result = filter_string(modified);
773 value = result->value;
790 char *filter(char *original, pt_search_key key)
792 static const char *mname = "ModelName";
793 static const char *delim = " \t";
794 static const char *delim_str = "\"";
795 static const char *end = "\n";
799 char *copied = malloc(strlen(original)+1);
801 PT_ERROR("Can't allocate memory");
804 char *full_string = copied;
806 strcpy(copied, original);
807 while(isblank(*copied)) {
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);
820 PT_ERROR("Can't allocate memory");
823 strcpy(value, token);
824 token = strsep(&copied, end);
825 while(*token != '\0') {
826 if(isblank(*token)) {
832 PT_DEBUG("String contains unexpected symbols: %s", original);
838 PT_DEBUG("String which contains %s is not correct", original);
846 void pt_free_prod(prod *product)
849 if(product->buffer) {
850 free(product->buffer);
855 void pt_free_strings(gpointer data)
862 void pt_free_model(gpointer data)
866 model *mod = (model *)data;
867 pt_free_prod(&(mod->product));
868 pt_free_info(&(mod->inform));
873 drvm *read_drv(FILE *fd)
880 drv = (drvm *)calloc(1, sizeof(drvm));
882 PT_ERROR("Can't allocate memory");
888 result = fread(&len, sizeof(uint32_t), 1, fd);
890 PT_ERROR("Can't read data from file");
895 if(len == 0 || len > UINT32_MAX) {
896 PT_ERROR("Invalid length(%d)", len);
901 size_t elm_size = sizeof(model*);
902 uint32_t length = len;
903 size_t res_size = length * elm_size;
905 models = g_ptr_array_sized_new(length);
906 drv->models = models;
909 for (int i = 0; i < length; ++i) {
910 mod = read_model(fd);
911 g_ptr_array_add(models, mod);
914 g_ptr_array_set_free_func(models, pt_free_model);
916 result = fread(&len, sizeof(uint32_t), 1, fd);
918 PT_ERROR("Can't read data from file");
919 void *ptr = g_ptr_array_free(models, TRUE);
921 PT_ERROR("freeing memory fails");
927 if (len == 0 || len > UINT32_MAX) {
928 PT_ERROR("Invalid length(%d)", len);
933 elm_size = sizeof(char *);
935 res_size = length * elm_size;
936 strings = g_ptr_array_sized_new(length);
937 g_ptr_array_set_free_func(strings, pt_free_strings);
938 drv->strings = strings;
943 for (int i = 0; i < length; ++i) {
945 if((read = getline(&string, &size_buffer, fd)) == -1) {
946 PT_ERROR("Can't read line from file");
947 void *ptr = g_ptr_array_free(strings, TRUE);
949 PT_ERROR("freeing memory fails");
951 ptr = g_ptr_array_free(models, TRUE);
953 PT_ERROR("freeing memory fails");
958 g_ptr_array_add(strings, string);
964 model *read_model(FILE *fd)
970 mod = malloc(sizeof(model));
973 PT_ERROR("Can't allocate memory");
977 result = fread(&len, sizeof(uint32_t), 1, fd);
979 PT_ERROR("Can't read data from file");
987 result = fread(&len, sizeof(uint32_t), 1, fd);
989 PT_ERROR("Can't read data from file");
994 if(len == 0 || len > UINT32_MAX) {
995 PT_ERROR("Invalid length(%d)", len);
1001 if ((length >> 30) > 0)
1003 PT_ERROR("Integer overflow");
1008 uint32_t size_buffer = length * sizeof(uint32_t);
1010 if(!((mod->product).buffer = malloc(size_buffer))) {
1011 PT_ERROR("Can't allocate memory");
1015 (mod->product).len = length;
1017 result = fread((mod->product).buffer, size_buffer, 1, fd);
1019 PT_ERROR("Can't read data from file");
1024 // Parse part related to product
1026 result = fread(&len, sizeof(uint32_t), 1, fd);
1028 PT_ERROR("Can't read data from file");
1033 if(len == 0 || len > UINT32_MAX) {
1034 PT_ERROR("Invalid length(%d)", len);
1040 if ((length>>(32 - sizeof(uint32_t))) > 0)
1042 PT_ERROR("Integer overflow");
1047 size_buffer = length * sizeof(uint32_t);
1048 if(!(mod->inform.buffer = malloc(size_buffer))) {
1049 PT_ERROR("Can't allocate memory");
1053 mod->inform.len = length;
1054 result = fread(mod->inform.buffer, size_buffer, 1, fd);
1056 PT_ERROR("Can't read data from file");
1064 void pt_free_info(info *inf)
1073 pt_dbconfig *pt_tune_db(FILE *file, const char *path)
1076 PT_ERROR(STR_PAR "%p", file);
1081 PT_ERROR(STR_PAR "%p", path);
1085 char *copied_path = strdup(path);
1087 PT_ERROR("Allocating memory fail");
1091 int size = get_file_size(copied_path);
1093 PT_ERROR("Getting info about file fail");
1098 char *buffer = malloc(size);
1100 PT_ERROR("Allocating memory fail");
1105 int result = setvbuf(file, buffer, _IOFBF, size);
1107 PT_ERROR("Tuning buffering operations fail");
1113 pt_dbconfig *config;
1114 config = (pt_dbconfig*)malloc(sizeof(pt_dbconfig));
1116 PT_ERROR("Allocating memory fail");
1121 memset(config, '\0', sizeof(pt_dbconfig));
1122 config->dbfile = file;
1123 config->dbpath = copied_path;
1124 config->dbbuffer = buffer;
1128 void pt_free_config(pt_dbconfig *config)
1131 PT_ERROR(STR_PTR "%p", config);
1133 if(config->dbbuffer) {
1134 free((void *)config->dbbuffer);
1136 if(config->dbpath) {
1137 free((void *)config->dbpath);
1143 char* pt_extract_ppd(pt_db *database, const char *search, pt_search type)
1145 if(!database || !search) {
1146 PT_ERROR(STR_PAR "%p, %p", database, search);
1150 drvm* dbstruct = database->dbstruct;
1153 PT_ERROR(STR_PTR "%p", dbstruct);
1157 pt_file *file = NULL;
1158 if(type == PT_SEARCH_MODEL) {
1159 file = extract_drv_by_model(*dbstruct, search);
1160 } else if(type == PT_SEARCH_PROD) {
1161 file = extract_drv_by_product(*dbstruct, search);
1162 } else if(type == PT_SEARCH_ALL) {
1163 file = extract_drv_by_model(*dbstruct, search);
1165 file = extract_drv_by_product(*dbstruct, search);
1168 PT_ERROR(STR_PAR "%d", type);
1173 PT_ERROR("Didn't find \"%s\" in database", search);
1177 char *output = pt_exec_ppdc(file);
1180 PT_ERROR("Executing ppdc fails");
1181 if(pt_free_file(file, PT_FREE_FILE_DEL)) {
1182 PT_ERROR("[%s] Can't free memory", search);
1187 if(pt_free_file(file, PT_FREE_FILE_DEL)) {
1188 PT_ERROR("Freeing memory fails");
1195 void pt_free_dbconfig(pt_dbconfig *dbconfig)
1198 if(dbconfig->dbbuffer) {
1199 free((void*)dbconfig->dbbuffer);
1201 if(dbconfig->dbpath) {
1202 free((void*)dbconfig->dbpath);
1204 if(dbconfig->dbfile) {
1205 fclose(dbconfig->dbfile);
1210 void pt_free_db(pt_db *database)
1213 if(database->dbconfig) {
1214 pt_free_dbconfig(database->dbconfig);
1216 if(database->dbstruct) {
1217 pt_free_drvm(database->dbstruct);
1222 pt_db *pt_create_db(const char *path)
1228 FILE *dbfile = fopen(path, "rb");
1233 pt_dbconfig *config;
1234 config = pt_tune_db(dbfile, path);
1236 PT_ERROR("Tuning database fail");
1241 drvm *dbstruct = read_drv(dbfile);
1243 pt_free_config(config);
1248 pt_db *database = (pt_db*)malloc(sizeof(pt_db));
1250 pt_free_config(config);
1251 pt_free_drvm(dbstruct);
1256 database->dbstruct = dbstruct;
1257 database->dbconfig = config;