upload tizen1.0 source
[pkgs/n/native-installer.git] / backend-lib / src / libdebinternals.c
1 /*
2  * rpm-installer
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23
24
25
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <stdarg.h>
31 #include <unistd.h>
32 #include <sys/wait.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <regex.h>
36 #include <dlog.h>
37 #include "libdebinternals.h"
38
39 /* This is backend lib's filter string for dlogutil*/
40 #define LOCAL_LOG_TAG    "libdeb"
41 int logging = 0x0004;
42 #ifdef LOG_IN_FILE
43 #define NATIVE_INSTALLER_LIBDEB_LOG_FILE "/tmp/libdeb"
44 FILE *logfile = NULL;
45 #endif
46
47 void _libdeb_print_msg(int type, int exetype, char *format, ...)
48 {
49         char buffer[FILENAME_MAX] = { 0 };
50         char tbuffer[FILENAME_MAX] = { 0 };
51
52         int nbuffer;
53         va_list args;
54         va_start(args, format);
55         nbuffer = vsnprintf(tbuffer, FILENAME_MAX, format, args);
56         va_end(args);
57
58         switch (type) {
59         case DEBUG_ERR:
60                 LOG(LOG_ERROR, LOCAL_LOG_TAG, tbuffer);
61                 break;
62         case DEBUG_RESULT:
63                 LOG(LOG_WARN, LOCAL_LOG_TAG, tbuffer);
64                 break;
65         case DEBUG_INFO:
66                 LOG(LOG_DEBUG, LOCAL_LOG_TAG, tbuffer);
67         default:
68                 break;
69         }
70
71         if (logging == 0)
72                 return;
73
74         if (DEBUG_ERR == (logging & type)) {
75                 nbuffer = snprintf(buffer, FILENAME_MAX, "ERROR:%s", tbuffer);
76                 vfprintf(stderr, format, args);
77         } else if (DEBUG_INFO == (logging & type)) {
78                 nbuffer = snprintf(buffer, FILENAME_MAX, "INFO:%s", tbuffer);
79                 vfprintf(stdout, format, args);
80         } else if (DEBUG_RESULT == (logging & type)) {
81                 nbuffer = snprintf(buffer, FILENAME_MAX, "RESULT:%s", tbuffer);
82                 vfprintf(stdout, format, args);
83         } else {
84                 return;
85         }
86
87 #ifdef LOG_IN_FILE
88         if (logfile != NULL)
89                 fwrite(buffer, sizeof(char), strlen(buffer), logfile);
90 #endif                          /*LOG_IN_FILE */
91 }
92
93 int _libdeb_xsystem(const char *argv[])
94 {
95         int status = 0;
96         pid_t pid;
97         pid = vfork();
98         switch (pid) {
99         case -1:
100                 perror("fork failed");
101                 return LIBDEB_ERROR;
102         case 0:
103                 /* child */
104                 execvp(argv[0], (char *const *)argv);
105                 _exit(-1);
106         default:
107                 /* parent */
108                 break;
109         }
110
111         _libdeb_print(DEBUG_INFO, "parent\n");
112         if (waitpid(pid, &status, 0) == -1) {
113                 perror("waitpid failed");
114                 return LIBDEB_ERROR;
115         }
116
117         if (WIFSIGNALED(status)) {
118                 perror("signal");
119                 return LIBDEB_ERROR;
120         }
121
122         if (!WIFEXITED(status)) {
123                 /* shouldn't happen */
124                 perror("should not happen");
125                 return LIBDEB_ERROR;
126         }
127
128         return WEXITSTATUS(status);
129 }
130
131 char *_libdeb_substring(const char *str, size_t begin, size_t len)
132 {
133         if (str == 0 || strlen(str) == 0 || strlen(str) < begin ||
134             strlen(str) < (begin + len))
135                 return LIBDEB_SUCCESS;
136         return strndup(str + begin, len);
137 }
138
139 char *_libdeb_get_filename(const char *packagefilepath)
140 {
141         regex_t re;
142         regmatch_t mached[5];
143         int ret = 0;
144         char *package_file_name = NULL;
145         if (packagefilepath == NULL) {
146                 _libdeb_print(DEBUG_ERR,
147                               "[_libdeb_get_filename] invalid arguments\n");
148                 return NULL;
149         }
150
151         ret =
152             regcomp(&re, "[/]*([.a-z_A-Z0-9-]+\\.([aA][pP][kK]|[dD][eE][bB]))",
153                     REG_EXTENDED);
154         if (ret != 0) {
155                 _libdeb_print(DEBUG_ERR,
156                               "[_libdeb_get_filename] regcomp failed(%d)\n",
157                               ret);
158                 return NULL;
159         }
160         ret = regexec(&re, packagefilepath, 5, mached, 0);
161         if (ret != 0) {
162                 _libdeb_print(DEBUG_ERR,
163                               "[_libdeb_get_filename] regexec failed(%s)(%d)\n",
164                               packagefilepath, ret);
165                 regfree(&re);
166                 return NULL;
167         }
168
169         package_file_name = _libdeb_substring(packagefilepath, mached[1].rm_so,
170                                               mached[1].rm_eo -
171                                               mached[1].rm_so);
172
173         _libdeb_print(DEBUG_INFO,
174                       "[_libdeb_get_filename][%s] -> [%s] \n", packagefilepath,
175                       package_file_name);
176         regfree(&re);
177         return package_file_name;
178 }
179
180 int _libdeb_fill_pkginfo_from_control_file(package_manager_pkg_detail_info_t
181                                            *pkg_detail_info, char *line)
182 {
183         regex_t re;
184         regmatch_t mached[5];
185         int ret = 0;
186         char *retstr;
187         /* Package Name */
188         ret = regcomp(&re, "[Pp]ackage[\\ ]*:[\\ ]*([.A-Z0-9a-z_\\-]+)",
189                       REG_EXTENDED);
190         if (ret != 0) {
191                 _libdeb_print
192                     (DEBUG_ERR,
193                      "[_libdeb_fill_pkginfo_from_control_file]"
194                      " regcomp failed(%d)", ret);
195                 return LIBDEB_ERROR;
196         }
197         ret = regexec(&re, line, 5, mached, 0);
198         if (ret != 0)
199                 regfree(&re);
200         else {
201                 retstr = _libdeb_substring(line, mached[1].rm_so,
202                                            mached[1].rm_eo - mached[1].rm_so);
203                 _libdeb_print
204                     (DEBUG_INFO,
205                      "[_libdeb_fill_pkginfo_from_control_file] PackageName=%s\n",
206                      retstr);
207                 strncpy(pkg_detail_info->pkg_name, retstr,
208                         sizeof(pkg_detail_info->pkg_name) - 1);
209                 free(retstr);
210                 regfree(&re);
211                 return LIBDEB_SUCCESS;
212         }
213         /* Version */
214         ret = regcomp(&re,
215                       "Version[\\ ]*:[\\ ]*([0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3})",
216                       REG_EXTENDED);
217         if (ret != 0) {
218                 _libdeb_print
219                     (DEBUG_ERR,
220                      "[_libdeb_fill_pkginfo_from_control_file] "
221                      "regcomp failed(%d)", ret);
222                 return LIBDEB_ERROR;
223         }
224         ret = regexec(&re, line, 5, mached, 0);
225         if (ret != 0)
226                 regfree(&re);
227         else {
228                 retstr = _libdeb_substring(line, mached[1].rm_so,
229                                            mached[1].rm_eo - mached[1].rm_so);
230                 _libdeb_print
231                     (DEBUG_INFO,
232                      "[_libdeb_fill_pkginfo_from_control_file] Version=%s\n",
233                      retstr);
234                 strncpy(pkg_detail_info->version, retstr,
235                         sizeof(pkg_detail_info->version) - 1);
236                 regfree(&re);
237                 free(retstr);
238                 return LIBDEB_SUCCESS;
239         }
240
241         /* Description */
242         ret = regcomp(&re, "[Dd]escription[\\ ]*:[\\ ]*([.A-Z0-9a-z_\\-]+)",
243                       REG_EXTENDED);
244         if (ret != 0) {
245                 _libdeb_print
246                     (DEBUG_ERR,
247                      "[_libdeb_fill_pkginfo_from_control_file]"
248                      " regcomp failed(%d)", ret);
249                 return LIBDEB_ERROR;
250         }
251         ret = regexec(&re, line, 5, mached, 0);
252         if (ret != 0)
253                 regfree(&re);
254         else {
255                 retstr = _libdeb_substring(line, mached[1].rm_so,
256                                            mached[1].rm_eo - mached[1].rm_so);
257                 _libdeb_print
258                     (DEBUG_INFO,
259                      "[_libdeb_fill_pkginfo_from_control_file] Description=%s\n",
260                      retstr);
261                 strncpy(pkg_detail_info->pkg_description, retstr,
262                         sizeof(pkg_detail_info->pkg_description) - 1);
263                 free(retstr);
264                 regfree(&re);
265                 return LIBDEB_SUCCESS;
266         }
267
268         /* Installed Size */
269         ret = regcomp(&re,
270                       "[Ii]nstalled-[Ss]ize[\\ ]*:[\\ ]*([.A-Z0-9a-z_\\-]+)",
271                       REG_EXTENDED);
272         if (ret != 0) {
273                 _libdeb_print
274                     (DEBUG_ERR,
275                      "[_libdeb_fill_pkginfo_from_control_file] "
276                      "regcomp failed(%d)", ret);
277                 return LIBDEB_ERROR;
278         }
279         ret = regexec(&re, line, 5, mached, 0);
280         if (ret != 0)
281                 regfree(&re);
282         else {
283                 retstr = _libdeb_substring(line, mached[1].rm_so,
284                                            mached[1].rm_eo - mached[1].rm_so);
285                 _libdeb_print
286                     (DEBUG_INFO,
287                      "[_libdeb_fill_pkginfo_from_control_file] "
288                      "Installed Size=%s\n", retstr);
289                 pkg_detail_info->app_size = atoi(retstr);
290                 free(retstr);
291                 regfree(&re);
292                 return LIBDEB_SUCCESS;
293         }
294
295         return LIBDEB_SUCCESS;
296 }
297
298
299 int _libdeb_populate_control_info(const char *pkgname,
300                                   package_manager_pkg_detail_info_t
301                                   *pkg_detail_info, char *controlfilepath)
302 {
303         FILE *fp = NULL;
304         char *lineptr = NULL;
305         size_t len = 512;
306         ssize_t read;
307         char buff[512] = { 0, };
308         int flag;
309         int ret = 0;
310         if (strncmp(controlfilepath, PKGMETAINFO, strlen(PKGMETAINFO)))
311                 flag = 1;       /*directly read from control file of pkg */
312         else
313                 flag = 0;       /* read from dpkg available file */
314         _libdeb_print(DEBUG_INFO, "flag value is %d\n", flag);
315         fp = fopen(controlfilepath, "r");
316         if (fp == NULL) {
317                 _libdeb_print(DEBUG_ERR,
318                               "failed to open file(%s)\n", controlfilepath);
319                 return LIBDEB_ERROR;
320         }
321         if (pkgname)
322                 snprintf(buff, 512, "Package: %s", pkgname);
323         /*allocate memory for lineptr. If it is less
324            getline will realloc it */
325         lineptr = (char *)malloc(sizeof(char) * 512);
326         if (UNLIKELY(lineptr == NULL)) {
327                 _libdeb_print(DEBUG_ERR,
328                               "malloc failed\n");
329                 fclose(fp);
330                 return LIBDEB_ERROR;
331         }
332         memset(lineptr, 0x00, sizeof(char) * 512);
333         clearerr(fp);
334         do {
335                 memset(lineptr, 0x00, sizeof(char) * 512);
336                 read = getline(&lineptr, &len, fp);
337                 if (lineptr == NULL)
338                         return LIBDEB_ERROR;
339                 if (read == -1) {
340                         if (feof(fp)) {
341                                 fclose(fp);
342                                 return LIBDEB_SUCCESS;
343                         }
344                         _libdeb_print(DEBUG_ERR, "getline failed\n");
345                         fclose(fp);
346                         return LIBDEB_ERROR;
347                 }
348                 if (flag == 1) {
349                         /*got the entry in available file. Now read till
350                            next empty line and break */
351                         /*10 is ASCII of newline \n */
352                         if (*lineptr == 10)
353                                 break;
354                         ret =
355                             _libdeb_fill_pkginfo_from_control_file
356                             (pkg_detail_info, lineptr);
357                         if (ret) {
358                                 fclose(fp);
359                                 return LIBDEB_ERROR;
360                         }
361                 } else {
362                         if ((strncmp(lineptr, buff, strlen(buff)) == 0) &&
363                                     (strlen(lineptr) == strlen(buff) + 1)) {
364                                 flag = 1;
365                                 /*Parse the fields now */
366                                 ret =
367                                     _libdeb_fill_pkginfo_from_control_file
368                                     (pkg_detail_info, lineptr);
369                                 if (ret) {
370                                         fclose(fp);
371                                         return LIBDEB_ERROR;
372                                 }
373
374                         } else {
375                                 continue;
376                         }
377                 }
378         } while (lineptr != NULL);
379         fclose(fp);
380         if (lineptr) {
381                 free(lineptr);
382                 lineptr = NULL;
383         }
384
385         return LIBDEB_SUCCESS;
386
387 }
388
389
390 long long _libdeb_calculate_dir_size(char *dirname)
391 {
392         long long total = 0;
393         long long ret = 0;
394         int q = 0; /*quotient*/
395         int r = 0; /*remainder*/
396         DIR *dp = NULL;
397         struct dirent *ep = NULL;
398         struct stat fileinfo;
399         char abs_filename[FILENAME_MAX] = { 0, };
400         if (dirname == NULL) {
401                 _libdeb_print(DEBUG_ERR,
402                                 "dirname is NULL");
403                 return LIBDEB_ERROR;
404         }
405         dp = opendir(dirname);
406         if (dp != NULL) {
407                 while ((ep = readdir(dp)) != NULL) {
408                         if (!strcmp(ep->d_name, ".") || 
409                                 !strcmp(ep->d_name, "..")) {
410                                 continue;
411                         }
412                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
413                                  ep->d_name);
414                         if (stat(abs_filename, &fileinfo) < 0)
415                                 perror(abs_filename);
416                         else {
417                                 if (S_ISDIR(fileinfo.st_mode)) {
418                                         total += fileinfo.st_size;
419                                         if (strcmp(ep->d_name, ".")
420                                             && strcmp(ep->d_name, "..")) {
421                                                 ret = _libdeb_calculate_dir_size
422                                                     (abs_filename);
423                                                 total = total + ret;
424                                         }
425                                 } else {
426                                         /*It is a file. Calculate the actual
427                                         size occupied (in terms of 4096 blocks)*/
428                                 q = (fileinfo.st_size / BLOCK_SIZE);
429                                 r = (fileinfo.st_size % BLOCK_SIZE);    
430                                 if (r) {
431                                         q = q + 1;
432                                 }
433                                 total += q * BLOCK_SIZE;
434                                 }
435                         }
436                 }
437                 (void)closedir(dp);
438         } else {
439                 _libdeb_print(DEBUG_ERR,
440                              "Couldn't open the directory\n");
441                 return -1;
442         }
443         return total;
444
445 }