fix missing encoded_id related change & code clearing.
[platform/core/appfw/app2sd.git] / plugin / app2sd / src / app2sd_internals_utils.c
1 /*
2  * app2ext
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Garima Shrivastava<garima.s@samsung.com>
7  *      Jyotsna Dhumale <jyotsna.a@samsung.com>
8  *      Venkatesha Sarpangala <sarpangala.v@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <dirent.h>
25 #include <time.h>
26
27 #include "app2sd_internals.h"
28
29 #define PASSWD_LEN              21
30 #define ASCII_PASSWD_CHAR       93
31
32 /*
33 ########### Internal APIs ##################
34  */
35
36 /*Note: Don't use any printf statement inside this function*/
37 /*This function is similar to Linux's "system()"  for executing a process.*/
38 int _xsystem(const char *argv[])
39 {
40         int status = 0;
41         pid_t pid;
42         char err_buf[1024] = {0,};
43
44         pid = fork();
45         switch (pid) {
46         case -1:
47                 perror("fork failed");
48                 return -1;
49         case 0:
50                 /* child */
51                 strerror_r(errno, err_buf, sizeof(err_buf));
52                 if (execvp(argv[0], (char *const *)argv) < 0)
53                         fprintf(stderr, "execvp failed %d....%s\n",
54                                 errno, err_buf);
55                 _exit(-1);
56         default:
57                 /* parent */
58                 break;
59         }
60         if (waitpid(pid, &status, 0) == -1) {
61                 perror("waitpid failed");
62                 return -1;
63         }
64         if (WIFSIGNALED(status)) {
65                 perror("signal");
66                 return -1;
67         }
68         if (!WIFEXITED(status)) {
69                 /* shouldn't happen */
70                 perror("should not happen");
71                 return -1;
72         }
73         return WEXITSTATUS(status);
74 }
75
76
77 /*
78  * @_app2sd_check_mmc_status
79  * This function checks and returns MMC status
80  */
81 /* TODO : another possible way ? */
82 int _app2sd_check_mmc_status(void)
83 {
84         FILE *fp1 = NULL;
85         char line[512];
86         fp1 = fopen("/etc/mtab", "r");
87         if (fp1 == NULL) {
88                 fprintf(stderr, "failed to open file\n");
89                 _E("failed to open file /etc/mtab");
90                 return APP2EXT_ERROR_MMC_STATUS;
91         }
92         while (fgets(line, 512, fp1) != NULL) {
93                 if (strstr(line, MMC_PATH) != NULL) {
94                         fclose(fp1);
95                         return APP2EXT_SUCCESS;
96                 }
97         }
98         fclose(fp1);
99         return APP2EXT_ERROR_MMC_STATUS;
100 }
101
102 /*
103  * @_app2sd_get_available_free_memory
104  * This function returns the available free memory in the SD Card.
105  * param [in]: sd_path: This is sd card access path.
106  * param [out]: free_mem: Result will be available in this.
107  * User has to pass valid memory address.
108  * return: On success, it will return 0.
109  * Else, appropriate error no will be returned.
110  */
111 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
112 {
113         struct statvfs buf;
114         int ret = 0;
115         unsigned long long temp = 0;
116
117         if (sd_path == NULL || free_mem == NULL) {
118                 _E("invalid input parameter");
119                 return -1;
120         }
121
122         memset((void *)&buf, '\0', sizeof(struct statvfs));
123
124         ret = statvfs(sd_path, &buf);
125         if (ret) {
126                 _E("unable to get SD Card memory information");
127                 return APP2EXT_ERROR_MMC_INFORMATION;
128         }
129
130         temp = (unsigned long long)buf.f_bsize*buf.f_bavail;
131         *free_mem = (int)(temp/(1024*1024));
132
133         return 0;
134 }
135
136 int _app2sd_delete_directory(const char *dirname)
137 {
138         DIR *dp = NULL;
139         struct dirent ep;
140         struct dirent *er = NULL;
141         char abs_filename[FILENAME_MAX] = { 0, };
142         int ret = 0;
143
144         dp = opendir(dirname);
145         if (dp != NULL) {
146                 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
147                         struct stat stFileInfo;
148
149                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
150                                 ep.d_name);
151
152                         if (lstat(abs_filename, &stFileInfo) < 0) {
153                                 perror(abs_filename);
154                                 (void)closedir(dp);
155                                 return -1;
156                         }
157
158                         if (S_ISDIR(stFileInfo.st_mode)) {
159                                 if (strcmp(ep.d_name, ".")
160                                     && strcmp(ep.d_name, "..")) {
161                                         ret = _app2sd_delete_directory(abs_filename);
162                                         if (ret <0) {
163                                                 (void)closedir(dp);
164                                                 return -1;
165                                         }
166                                 }
167                         } else {
168                                 ret = remove(abs_filename);
169                                 if (ret <0) {
170                                         (void)closedir(dp);
171                                         return -1;
172                                 }
173                         }
174                 }
175                 (void)closedir(dp);
176                 ret = remove(dirname);
177                 if (ret <0)
178                         return -1;
179         } else {
180                 _E("couldn't open the directory[%s]", dirname);
181         }
182         return 0;
183 }
184
185 void _app2sd_delete_symlink(const char *dirname)
186 {
187         int ret = 0;
188         DIR *dp = NULL;
189         struct dirent ep;
190         struct dirent *er = NULL;
191         char abs_filename[FILENAME_MAX] = { 0, };
192
193         _D("start clean_symlink [%s]", dirname);
194
195         dp = opendir(dirname);
196         if (dp != NULL) {
197                 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
198                         char mmc_path[PATH_MAX] = {0};
199
200                         if (!strcmp(ep.d_name, ".") || !strcmp(ep.d_name, ".."))
201                                 continue;
202
203                         /*get realpath find symlink to ".mmc" and unlink it*/
204                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, ep.d_name);
205                         char *path = realpath(abs_filename, mmc_path);
206                         if(!path){
207                                 _E("realpath failed");
208                         }
209
210                         if (strstr(mmc_path,".mmc")) {
211                                 _E("force unlink [%s]", abs_filename);
212                                 if (unlink(abs_filename)) {
213                                         if (errno == ENOENT) {
214                                                 _E("Unable to access file %s", abs_filename);
215                                         } else {
216                                                 _E("Unable to delete %s", abs_filename);
217                                         }
218                                 }
219                         }
220
221                 }
222                 (void)closedir(dp);
223
224                 /*delete ".mmc" folder*/
225                 snprintf(abs_filename, FILENAME_MAX, "%s/.mmc", dirname);
226                 ret = remove(abs_filename);
227                 if (ret == -1) {
228                         return;
229                 }
230         } else {
231                 _E("couldn't open the directory[%s]", dirname);
232         }
233
234         _D("finish clean_symlink");
235 }
236
237 int _app2sd_copy_dir(const char *src, const char *dest)
238 {
239         int ret = APP2EXT_SUCCESS;
240         const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
241         ret = _xsystem(argv_bin);
242         if (ret) {
243                 _E("copy fail");
244                 return APP2EXT_ERROR_MOVE;
245         }
246         return ret;
247 }
248
249 int _app2sd_rename_dir(const char *old_name, const char *new_name)
250 {
251         int ret = APP2EXT_SUCCESS;
252         const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
253         ret = _xsystem(argv_bin);
254         if (ret) {
255                 _E("mv/rename fail");
256                 return APP2EXT_ERROR_MOVE;
257         }
258         return ret;
259 }
260
261 unsigned long long _app2sd_calculate_dir_size(char *dirname)
262 {
263         static unsigned long long total = 0;
264         DIR *dp = NULL;
265         struct dirent ep;
266         struct dirent *er = NULL;
267         char abs_filename[FILENAME_MAX] = { 0, };;
268
269         dp = opendir(dirname);
270         if (dp != NULL) {
271                 while (readdir_r(dp, &ep, &er) == 0 && er != NULL) {
272                         struct stat stFileInfo;
273
274                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
275                                  ep.d_name);
276
277                         if (stat(abs_filename, &stFileInfo) < 0)
278                                 perror(abs_filename);
279                         else {
280                                 total += stFileInfo.st_size;
281
282                                 if (S_ISDIR(stFileInfo.st_mode)) {
283                                         if (strcmp(ep.d_name, ".")
284                                             && strcmp(ep.d_name, "..")) {
285                                                 _app2sd_calculate_dir_size
286                                                     (abs_filename);
287                                         }
288                                 } else {
289                                         /*Do Nothing */
290                                 }
291                         }
292                 }
293                 (void)closedir(dp);
294         } else {
295                 _E("error in opening directory");
296         }
297         return total;
298 }
299
300 unsigned long long _app2sd_calculate_file_size(const char *filename)
301 {
302         struct stat stFileInfo;
303         _D("calculating file size for (%s)", filename);
304
305         if (stat(filename, &stFileInfo) < 0) {
306                 perror(filename);
307                 return 0;
308         } else
309                 return stFileInfo.st_size;
310 }
311
312 /*Note: Don't use any printf statement inside this function*/
313 char *_app2sd_encrypt_device(const char *device,
314         const char *loopback_device, char *passwd)
315 {
316         /* TODO : change to dm-crypt */
317         const char *argv[] =
318             { "/sbin/losetup", device, loopback_device, NULL };
319         pid_t pid = 0;
320         int my_pipe[2] = { 0, };
321         char buf[FILENAME_MAX] = { 0, };
322         char *ret_result = NULL;
323         int result = 0;
324         char err_buf[1024] = {0,};
325
326         if (pipe(my_pipe) < 0) {
327                 fprintf(stderr, "Unable to create pipe\n");
328                 return NULL;
329         }
330         pid = fork();
331         switch (pid) {
332         case -1:
333                 perror("fork failed");
334                 return NULL;
335         case 0:
336                 /* child */
337                 close(1);
338                 close(2);
339                 result = dup(my_pipe[1]);
340                 if (result < 0) {
341                         strerror_r(errno, err_buf, sizeof(err_buf));
342                         fprintf(stderr, "dup failed %d....%s\n",
343                                 errno, err_buf);
344                         _exit(-1);
345                 }
346                 result = dup(my_pipe[1]);
347                 if (result < 0) {
348                         strerror_r(errno, err_buf, sizeof(err_buf));
349                         fprintf(stderr, "dup failed %d....%s\n",
350                                 errno, err_buf);
351                         _exit(-1);
352                 }
353                 if (execvp(argv[0], (char *const *)argv) < 0) {
354                         strerror_r(errno, err_buf, sizeof(err_buf));
355                         fprintf(stderr, "execvp failed %d....%s\n",
356                                 errno, err_buf); /*Don't use d_msg_app2sd */
357                 }
358                 _exit(-1);
359         default:
360                 /* parent */
361                 close(my_pipe[1]);
362                 result = read(my_pipe[0], buf, FILENAME_MAX);
363                 if (result < 0) {
364                         strerror_r(errno, err_buf, sizeof(err_buf));
365                         fprintf(stderr, "read failed %d....%s\n",
366                                 errno, err_buf);
367                 }
368                 break;
369         }
370
371         ret_result = (char *)malloc(strlen(buf) + 1);
372         if (ret_result == NULL) {
373                 _E("malloc failed");
374                 return NULL;
375         }
376         memset(ret_result, '\0', strlen(buf) + 1);
377         memcpy(ret_result, buf, strlen(buf));
378
379         return ret_result;
380 }
381
382 /*Note: Don't use any printf statement inside this function*/
383 char *_app2sd_detach_loop_device(const char *device)
384 {
385         const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
386         pid_t pid;
387         int my_pipe[2] = { 0, };
388         char buf[FILENAME_MAX] = { 0, };
389         char *ret_result = NULL;
390         int result = 0;
391         char err_buf[1024] = {0,};
392
393         if (pipe(my_pipe) < 0) {
394                 fprintf(stderr, "Unable to create pipe\n");
395                 return NULL;
396         }
397         pid = fork();
398         switch (pid) {
399         case -1:
400                 perror("fork failed");
401                 return NULL;
402         case 0:
403                 /* child */
404                 close(1);
405                 close(2);
406                 result = dup(my_pipe[1]);
407                 if (result < 0) {
408                         strerror_r(errno, err_buf, sizeof(err_buf));
409                         fprintf(stderr, "dup failed %d....%s\n",
410                                 errno, err_buf);
411                         _exit(-1);
412                 }
413                 result = dup(my_pipe[1]);
414                 if (result < 0) {
415                         strerror_r(errno, err_buf, sizeof(err_buf));
416                         fprintf(stderr, "dup failed %d....%s\n",
417                                 errno, err_buf);
418                         _exit(-1);
419                 }
420                 if (execvp(argv[0], (char *const *)argv) < 0) {
421                         fprintf(stderr, "execvp failed\n");
422                                 /* Don't use d_msg_app2sd */
423                 }
424                 _exit(-1);
425         default:
426                 /* parent */
427                 close(my_pipe[1]);
428                 result = read(my_pipe[0], buf, FILENAME_MAX);
429                 if (result < 0) {
430                         strerror_r(errno, err_buf, sizeof(err_buf));
431                         fprintf(stderr, "read failed %d....%s\n",
432                                 errno, err_buf);
433                 }
434                 break;
435         }
436
437         ret_result = (char *)malloc(strlen(buf) + 1);
438         if (ret_result == NULL) {
439                 _E("malloc failed");
440                 return NULL;
441         }
442         memset(ret_result, '\0', strlen(buf) + 1);
443         memcpy(ret_result, buf, strlen(buf));
444
445         return ret_result;
446 }
447
448 /* Note: Don't use any printf statement inside this function*/
449 char *_app2sd_find_associated_device(const char *loopback_device)
450 {
451         const char *argv[] = { "/sbin/losetup", "-a", NULL };
452         pid_t pid;
453         int my_pipe[2] = { 0, };
454         char buf[FILENAME_MAX] = { 0, };
455         char *ret_result_temp = NULL;
456         char *ret_result = NULL;
457         char *line = NULL;;
458         char *save_str = NULL;
459         int result = 0;
460         char err_buf[1024] = {0,};
461
462         if (pipe(my_pipe) < 0) {
463                 fprintf(stderr, "Unable to create pipe\n");
464                 return NULL;
465         }
466         pid = fork();
467         switch (pid) {
468         case -1:
469                 perror("fork failed");
470                 return NULL;
471         case 0:
472                 /* child */
473                 close(1);
474                 close(2);
475                 result = dup(my_pipe[1]);
476                 if (result < 0) {
477                         strerror_r(errno, err_buf, sizeof(err_buf));
478                         fprintf(stderr, "dup failed %d....%s\n",
479                                 errno, err_buf);
480                         _exit(-1);
481                 }
482                 result = dup(my_pipe[1]);
483                 if (result < 0) {
484                         strerror_r(errno, err_buf, sizeof(err_buf));
485                         fprintf(stderr, "dup failed %d....%s\n",
486                                 errno, err_buf);
487                         _exit(-1);
488                 }
489                 if (execvp(argv[0], (char *const *)argv) < 0) {
490                         fprintf(stderr, "execvp failed\n");
491                                 /* Don't use d_msg_app2sd */
492                 }
493                 _exit(-1);
494         default:
495                 /* parent */
496                 close(my_pipe[1]);
497                 result = read(my_pipe[0], buf, FILENAME_MAX);
498                 if (result < 0) {
499                         strerror_r(errno, err_buf, sizeof(err_buf));
500                         fprintf(stderr, "read failed %d....%s\n",
501                                 errno, err_buf);
502                 }
503                 break;
504         }
505
506         ret_result_temp = (char *)malloc(strlen(buf) + 1);
507         if (ret_result_temp == NULL) {
508                 _E("malloc failed");
509                 return NULL;
510         }
511         memset(ret_result_temp, '\0', strlen(buf) + 1);
512         memcpy(ret_result_temp, buf, strlen(buf));
513
514         line = strtok_r(ret_result_temp, "\n", &save_str);
515         while (line) {
516                 if (strstr(line, loopback_device) != NULL) {
517                         _D("found: (%s)", line);
518                         if (ret_result) {
519                                 _D("duplicated device");
520                         } else {
521                                 ret_result = strdup(line);
522                         }
523                 }
524                 line = strtok_r(NULL, "\n", &save_str);
525         }
526         free(ret_result_temp);
527
528         return ret_result;
529 }
530
531 /*Note: Don't use any printf statement inside this function*/
532 char *_app2sd_find_free_device(void)
533 {
534         const char *argv[] = { "/sbin/losetup", "-f", NULL };
535         pid_t pid;
536         int my_pipe[2] = { 0, };
537         char buf[FILENAME_MAX + 1] = { 0, };
538         char *ret_result = NULL;
539         int result = 0;
540         char err_buf[1024] = {0,};
541
542         if (pipe(my_pipe) < 0) {
543                 fprintf(stderr, "Unable to create pipe\n");
544                 return NULL;
545         }
546         pid = fork();
547         switch (pid) {
548         case -1:
549                 perror("fork failed");
550                 return NULL;
551         case 0:
552                 /* child */
553                 close(1);
554                 close(2);
555                 result = dup(my_pipe[1]);
556                 if (result < 0) {
557                         strerror_r(errno, err_buf, sizeof(err_buf));
558                         fprintf(stderr, "dup failed %d....%s\n",
559                                 errno, err_buf);
560                         _exit(-1);
561                 }
562                 result = dup(my_pipe[1]);
563                 if (result < 0) {
564                         strerror_r(errno, err_buf, sizeof(err_buf));
565                         fprintf(stderr, "dup failed %d....%s\n",
566                                 errno, err_buf);
567                         _exit(-1);
568                 }
569                 if (execvp(argv[0], (char *const *)argv) < 0) {
570                         fprintf(stderr, "execvp failed\n");
571                                 /* Don't use d_msg_app2sd */
572                 }
573                 _exit(-1);
574         default:
575                 /* parent */
576                 close(my_pipe[1]);
577                 result = read(my_pipe[0], buf, FILENAME_MAX);
578                 if (result < 0) {
579                         strerror_r(errno, err_buf, sizeof(err_buf));
580                         fprintf(stderr, "read failed %d....%s\n",
581                                 errno, err_buf);
582                 }
583                 break;
584         }
585
586         ret_result = (char *)malloc(strlen(buf) + 1);
587         if (ret_result == NULL) {
588                 _E("malloc failed");
589                 return NULL;
590         }
591         memset(ret_result, '\0', strlen(buf) + 1);
592         memcpy(ret_result, buf, strlen(buf));
593
594         return ret_result;
595 }
596
597 /*@_app2sd_generate_password
598 * This is a simple password generator
599 * return: On success, it will return the password, else NULL.
600 */
601 char *_app2sd_generate_password(const char *pkgid)
602 {
603         char passwd[PASSWD_LEN + 1] = { 0, };
604         char *ret_result = NULL;
605         char set[ASCII_PASSWD_CHAR + 1] =
606                 "!\"#$%&()*+,-./0123456789:;<=>?@ABCDE" \
607                 "FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
608         unsigned char char_1;
609         unsigned char char_2;
610         int i = 0;
611         int appname_len = strlen(pkgid);
612         int j = appname_len;
613         unsigned int seed;
614
615         /* Length of the password */
616         ret_result = (char*)malloc(PASSWD_LEN + 1);
617         if (NULL == ret_result) {
618                 _E("unable to allocate memory");
619                 return NULL;
620         }
621         memset((void *)ret_result, '\0', PASSWD_LEN + 1);
622
623         while (i < PASSWD_LEN) {
624                 seed = time(NULL);
625                 char_1 = (rand_r(&seed) + pkgid[j--]) % ASCII_PASSWD_CHAR;
626                 char_2 = rand_r(&seed) % ASCII_PASSWD_CHAR;
627                 passwd[i] = set[char_1];
628                 passwd[i + 1] = set[(pkgid[j--]) * 2];
629                 if (i < PASSWD_LEN - 3)
630                         passwd[i + 2] = set[char_2];
631                 i++;
632         }
633
634         memcpy(ret_result, passwd, PASSWD_LEN + 1);
635
636         return ret_result;
637 }