Tizen 2.1 base
[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 <app2sd_internals.h>
25 #include <app2sd_interface.h>
26
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <time.h>
35 #include <dlog.h>
36 #include <sys/statvfs.h>
37 #include <errno.h>
38
39 #define PASSWD_LEN              8
40 #define ASCII_PASSWD_CHAR       94
41
42 /*
43 ########### Internal APIs ##################
44  */
45
46 /*Note: Don't use any printf statement inside this function*/
47 /*This function is similar to Linux's "system()"  for executing a process.*/
48 int _xsystem(const char *argv[])
49 {
50         int status = 0;
51         pid_t pid;
52         pid = fork();
53         switch (pid) {
54         case -1:
55                 perror("fork failed");
56                 return -1;
57         case 0:
58                 /* child */
59                 execvp(argv[0], (char *const *)argv);
60                 _exit(-1);
61         default:
62                 /* parent */
63                 break;
64         }
65         if (waitpid(pid, &status, 0) == -1) {
66                 perror("waitpid failed");
67                 return -1;
68         }
69         if (WIFSIGNALED(status)) {
70                 perror("signal");
71                 return -1;
72         }
73         if (!WIFEXITED(status)) {
74                 /* shouldn't happen */
75                 perror("should not happen");
76                 return -1;
77         }
78         return WEXITSTATUS(status);
79 }
80
81
82 /*
83 * @_app2sd_check_mmc_status
84 * This function checks and returns MMC status
85 */
86 int _app2sd_check_mmc_status(void)
87 {
88         FILE *fp1 = NULL;
89         char line[512];
90         fp1 = fopen("/etc/mtab", "r");
91         if (fp1 == NULL) {
92                 fprintf(stderr, "failed to open file\n");
93                 app2ext_print("failed to open file /etc/mtab\n");
94                 return APP2EXT_ERROR_MMC_STATUS;
95         }
96         while (fgets(line, 512, fp1) != NULL) {
97                 if (strstr(line, MMC_PATH) != NULL) {
98                         fclose(fp1);
99                         return APP2EXT_SUCCESS;
100                 }
101         }
102         fclose(fp1);
103         return APP2EXT_ERROR_MMC_STATUS;
104 }
105
106 /*
107  * @_app2sd_get_available_free_memory
108  * This function returns the available free memory in the SD Card.
109  * param [in]: sd_path: This is sd card access path.
110  * param [out]: free_mem: Result will be available in this.
111  * User has to pass valid memory address.
112  * return: On success, it will return 0.
113  * Else, appropriate error no will be returned.
114  */
115 int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem)
116 {
117         struct statvfs buf;
118         int ret = 0;
119         if (sd_path == NULL || free_mem == NULL) {
120                 app2ext_print("App2Sd Error : Invalid input parameter\n");
121                 return -1;
122         }
123         memset((void *)&buf, '\0', sizeof(struct statvfs));
124         ret = statvfs(sd_path, &buf);
125         if (ret) {
126                 app2ext_print
127                     ("App2SD Error: Unable to get SD Card memory information\n");
128                 return APP2EXT_ERROR_MMC_INFORMATION;
129         }
130         *free_mem = ((buf.f_bfree * buf.f_bsize) / 1024) / 1024;
131         return 0;
132 }
133
134 int _app2sd_delete_directory(char *dirname)
135 {
136         DIR *dp = NULL;
137         struct dirent *ep = NULL;
138         char abs_filename[FILENAME_MAX] = { 0, };
139         int ret = 0;
140         dp = opendir(dirname);
141         if (dp != NULL) {
142                 while ((ep = readdir(dp)) != NULL) {
143                         struct stat stFileInfo;
144
145                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
146                                 ep->d_name);
147
148                         if (lstat(abs_filename, &stFileInfo) < 0) {
149                                 perror(abs_filename);
150                                 return -1;
151                         }
152
153                         if (S_ISDIR(stFileInfo.st_mode)) {
154                                 if (strcmp(ep->d_name, ".")
155                                     && strcmp(ep->d_name, "..")) {
156                                         ret = _app2sd_delete_directory(abs_filename);
157                                         if (ret <0)
158                                                 return -1;
159                                 }
160                         } else {
161                                 ret = remove(abs_filename);
162                                 if (ret <0)
163                                         return -1;
164                         }
165                 }
166                 (void)closedir(dp);
167                 ret = remove(dirname);
168                 if (ret <0)
169                         return -1;
170         } else {
171                 app2ext_print("Couldn't open the directory\n");
172         }
173         return 0;
174 }
175
176 int _app2sd_copy_dir(const char *src, const char *dest)
177 {
178         int ret = APP2EXT_SUCCESS;
179         const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL };
180         ret = _xsystem(argv_bin);
181         if (ret) {
182                 app2ext_print("copy fail\n");
183                 return APP2EXT_ERROR_MOVE;
184         }
185         return ret;
186 }
187
188 int _app2sd_rename_dir(const char *old_name, const char *new_name)
189 {
190         int ret = APP2EXT_SUCCESS;
191         const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL };
192         ret = _xsystem(argv_bin);
193         if (ret) {
194                 app2ext_print("mv/rename fail\n");
195                 return APP2EXT_ERROR_MOVE;
196         }
197         return ret;
198 }
199
200 unsigned long long _app2sd_calculate_dir_size(char *dirname)
201 {
202         static unsigned long long total = 0;
203         DIR *dp = NULL;
204         struct dirent *ep = NULL;
205         char abs_filename[FILENAME_MAX] = { 0, };;
206         dp = opendir(dirname);
207         if (dp != NULL) {
208                 while ((ep = readdir(dp)) != NULL) {
209                         struct stat stFileInfo;
210
211                         snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname,
212                                  ep->d_name);
213
214                         if (stat(abs_filename, &stFileInfo) < 0)
215                                 perror(abs_filename);
216                         else {
217                                 total += stFileInfo.st_size;
218
219                                 if (S_ISDIR(stFileInfo.st_mode)) {
220                                         if (strcmp(ep->d_name, ".")
221                                             && strcmp(ep->d_name, "..")) {
222                                                 _app2sd_calculate_dir_size
223                                                     (abs_filename);
224                                         }
225                                 } else {
226                                         /*Do Nothing */
227                                 }
228                         }
229                 }
230                 (void)closedir(dp);
231         } else {
232                 app2ext_print("\n error in opening directory ");
233         }
234         return total;
235 }
236
237 unsigned long long _app2sd_calculate_file_size(const char *filename)
238 {
239         struct stat stFileInfo;
240         app2ext_print("\n Calculating file size for %s\n", filename);
241
242         if (stat(filename, &stFileInfo) < 0) {
243                 perror(filename);
244                 return 0;
245         } else
246                 return stFileInfo.st_size;
247 }
248
249 /*Note: Don't use any printf statement inside this function*/
250 char *_app2sd_encrypt_device(const char *device, const char *pkgid,
251                               char *passwd)
252 {
253         const char *argv[] =
254             { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL };
255         pid_t pid = 0;
256         int my_pipe[2] = { 0, };
257         char buf[FILENAME_MAX] = { 0, };
258         char *ret_result = NULL;
259         int result = 0;
260         if (pipe(my_pipe) < 0) {
261                 fprintf(stderr, "Unable to create pipe\n");
262                 return NULL;
263         }
264         pid = fork();
265         switch (pid) {
266         case -1:
267                 perror("fork failed");
268                 return NULL;
269         case 0:
270                 /* child */
271                 close(1);
272                 close(2);
273                 result = dup(my_pipe[1]);
274                 result = dup(my_pipe[1]);
275                 if (execvp(argv[0], (char *const *)argv) < 0) {
276                         fprintf(stderr, "execvp failed %d....%s\n", errno, strerror(errno));    /*Don't use d_msg_app2sd */
277                 }
278                 _exit(-1);
279         default:
280                 /* parent */
281                 close(my_pipe[1]);
282                 result = read(my_pipe[0], buf, FILENAME_MAX);
283                 break;
284         }
285
286         ret_result = (char *)malloc(strlen(buf) + 1);
287         if (ret_result == NULL) {
288                 app2ext_print("Malloc failed!\n");
289                 return NULL;
290         }
291         memset(ret_result, '\0', strlen(buf) + 1);
292         memcpy(ret_result, buf, strlen(buf));
293         return ret_result;
294 }
295
296 /*Note: Don't use any printf statement inside this function*/
297 char *_app2sd_detach_loop_device(const char *device)
298 {
299         const char *argv[] = { "/sbin/losetup", "-d", device, NULL };
300         pid_t pid;
301         int my_pipe[2] = { 0, };
302         char buf[FILENAME_MAX] = { 0, };
303         char *ret_result = NULL;
304         int result = 0;
305         if (pipe(my_pipe) < 0) {
306                 fprintf(stderr, "Unable to create pipe\n");
307                 return NULL;
308         }
309         pid = fork();
310         switch (pid) {
311         case -1:
312                 perror("fork failed");
313                 return NULL;
314         case 0:
315                 /* child */
316                 close(1);
317                 close(2);
318                 result = dup(my_pipe[1]);
319                 result = dup(my_pipe[1]);
320                 if (execvp(argv[0], (char *const *)argv) < 0) {
321                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
322                 }
323                 _exit(-1);
324         default:
325                 /* parent */
326                 close(my_pipe[1]);
327                 result = read(my_pipe[0], buf, FILENAME_MAX);
328                 break;
329         }
330
331         ret_result = (char *)malloc(strlen(buf) + 1);
332         if (ret_result == NULL) {
333                 app2ext_print("Malloc failed!\n");
334                 return NULL;
335         }
336         memset(ret_result, '\0', strlen(buf) + 1);
337         memcpy(ret_result, buf, strlen(buf));
338
339         return ret_result;
340 }
341
342 /*Note: Don't use any printf statement inside this function*/
343 char *_app2sd_find_associated_device(const char *mmc_app_path)
344 {
345         const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL };
346         pid_t pid;
347         int my_pipe[2] = { 0, };
348         char buf[FILENAME_MAX] = { 0, };
349         char *ret_result = NULL;
350         int result = 0;
351         if (pipe(my_pipe) < 0) {
352                 fprintf(stderr, "Unable to create pipe\n");
353                 return NULL;
354         }
355         pid = fork();
356         switch (pid) {
357         case -1:
358                 perror("fork failed");
359                 return NULL;
360         case 0:
361                 /* child */
362                 close(1);
363                 close(2);
364                 result = dup(my_pipe[1]);
365                 result = dup(my_pipe[1]);
366                 if (execvp(argv[0], (char *const *)argv) < 0) {
367                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
368                 }
369                 _exit(-1);
370         default:
371                 /* parent */
372                 close(my_pipe[1]);
373                 result = read(my_pipe[0], buf, FILENAME_MAX);
374                 break;
375         }
376
377         ret_result = (char *)malloc(strlen(buf) + 1);
378         if (ret_result == NULL) {
379                 app2ext_print("Malloc failed!\n");
380                 return NULL;
381         }
382         memset(ret_result, '\0', strlen(buf) + 1);
383         memcpy(ret_result, buf, strlen(buf));
384
385         return ret_result;
386 }
387
388 /*Note: Don't use any printf statement inside this function*/
389 char *_app2sd_find_free_device(void)
390 {
391         const char *argv[] = { "/sbin/losetup", "-f", NULL };
392         pid_t pid;
393         int my_pipe[2] = { 0, };
394         char buf[FILENAME_MAX+1] = { 0, };
395         char *ret_result = NULL;
396         int result = 0;
397         if (pipe(my_pipe) < 0) {
398                 fprintf(stderr, "Unable to create pipe\n");
399                 return NULL;
400         }
401         pid = fork();
402         switch (pid) {
403         case -1:
404                 perror("fork failed");
405                 return NULL;
406         case 0:
407                 /* child */
408                 close(1);
409                 close(2);
410                 result = dup(my_pipe[1]);
411                 result = dup(my_pipe[1]);
412                 if (execvp(argv[0], (char *const *)argv) < 0) {
413                         fprintf(stderr, "execvp failed\n");     /*Don't use d_msg_app2sd */
414                 }
415                 _exit(-1);
416         default:
417                 /* parent */
418                 close(my_pipe[1]);
419                 result = read(my_pipe[0], buf, FILENAME_MAX);
420                 break;
421         }
422
423         ret_result = (char *)malloc(strlen(buf) + 1);
424         if (ret_result == NULL) {
425                 app2ext_print("Malloc failed!\n");
426                 return NULL;
427         }
428         memset(ret_result, '\0', strlen(buf) + 1);
429         memcpy(ret_result, buf, strlen(buf));
430
431         return ret_result;
432 }
433
434 /*@_app2sd_generate_password
435 * This is a simple password generator
436 * return: On success, it will return the password, else NULL.
437 */
438 char *_app2sd_generate_password(const char *pkgid)
439 {
440         char passwd[PASSWD_LEN+1] = { 0, };
441         char *ret_result = NULL;
442         char set[ASCII_PASSWD_CHAR+1] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
443         unsigned char char_1;
444         unsigned char char_2;
445         int i = 0;
446         int appname_len = strlen(pkgid);
447         int j = appname_len;
448
449         /* Length of the password */
450         ret_result = (char*)malloc(PASSWD_LEN+1);
451         if (NULL == ret_result) {
452                 app2ext_print("Unable to Allocate memory\n");
453                 return NULL;
454         }
455         memset((void *)ret_result, '\0', PASSWD_LEN+1);
456
457         while(i < PASSWD_LEN) {
458                 char_1 = (rand()+pkgid[j--])%ASCII_PASSWD_CHAR;
459                 char_2 = rand()%ASCII_PASSWD_CHAR;
460                 passwd[i] = set[char_1];
461                 passwd[i+1] = set[(pkgid[j--])*2];
462                 if (i<PASSWD_LEN-3)
463                         passwd[i+2] = set[char_2];
464                 i++;
465         }
466
467         app2ext_print("Password is %s\n", passwd);
468         memcpy(ret_result, passwd, PASSWD_LEN+1);
469         return ret_result;
470 }