c12ece7a5e0fffac05eb24fe78d44339193af31d
[platform/core/system/storaged.git] / src / block / utils.c
1 /*
2  * storaged
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 <stdlib.h>
22 #include <stdbool.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <fcntl.h>
28 #include <signal.h>
29 #include <dirent.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <errno.h>
34 #include <poll.h>
35 #include <mntent.h>
36 #include <system_info.h>
37 #include <sys/mount.h>
38 #include <sys/time.h>
39 #include "log.h"
40 #include "common.h"
41
42 int print_open_files(const char *mount_point)
43 {
44         DIR *dp;
45         struct dirent *dentry;
46
47         DIR *dp_child;
48         struct dirent *dentry_child;
49
50         int pid = -1, fd;
51         int ret;
52         char buf[PATH_MAX];
53         char buf2[PATH_MAX];
54
55         char cmdline[PATH_MAX];
56         char check_path[PATH_MAX];
57
58         int len = strlen(mount_point);
59
60         dp = opendir("/proc");
61         if (!dp) {
62                 _E("FAIL: open /proc");
63                 return -1;
64         }
65
66         while (1) {
67                 dentry = readdir(dp);
68                 if (dentry == NULL)
69                         break;
70
71                 if (!isdigit(dentry->d_name[0]))
72                         continue;
73
74                 pid = atoi(dentry->d_name);
75                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
76
77                 fd = open(buf, O_RDONLY);
78                 if (fd < 0)
79                         continue;
80                 ret = read(fd, cmdline, PATH_MAX);
81                 close(fd);
82
83                 if (ret < 0 || ret >= PATH_MAX)
84                         continue;
85                 cmdline[ret] = '\0';
86
87                 snprintf(buf, PATH_MAX, "/proc/%d/fd", pid);
88                 dp_child = opendir(buf);
89                 if (!dp_child)
90                         continue;
91                 while (1) {
92                         dentry_child = readdir(dp_child);
93                         if (dentry_child == NULL)
94                                 break;
95
96                         snprintf(check_path, PATH_MAX, "%s/%s", buf, dentry_child->d_name);
97
98                         if (readlink(check_path, buf2, PATH_MAX) < 0)
99                                 continue;
100
101                         if (strncmp(buf2, mount_point, len) == 0)
102                                 _D("Process %s : Opened files - %s", cmdline, buf2);
103                 }
104                 closedir(dp_child);
105         }
106
107         closedir(dp);
108         return 0;
109 }
110
111 int terminate_process(const char *partition, bool force)
112 {
113         const char *argv[7] = {"/usr/bin/fuser", "-m", "-k", "-s", NULL, NULL, NULL};
114         int argc;
115
116         if (force)
117                 argv[4] = "-SIGKILL";
118         else
119                 argv[4] = "-SIGTERM";
120         argv[5] = partition;
121         argc = sizeof(argv) / sizeof(argv[0]);
122         return run_child(argc, argv);
123 }
124
125 int mount_check(const char *path)
126 {
127         int ret = false;
128         struct mntent *mnt;
129         const char *table = "/etc/mtab";
130         FILE *fp;
131         int len;
132
133         fp = setmntent(table, "r");
134         if (!fp)
135                 return ret;
136
137         len = strlen(path) + 1;
138         while (1) {
139                 mnt = getmntent(fp);
140                 if (mnt == NULL)
141                         break;
142                 if (!strncmp(mnt->mnt_dir, path, len)) {
143                         ret = true;
144                         break;
145                 }
146         }
147         endmntent(fp);
148         return ret;
149 }
150
151 int umount_partition(const char *path, const bool force)
152 {
153         int retry = 0, ret = -1;
154         struct timespec time = {0,};
155
156         sync();
157         while (ret && retry < 2) {
158                 switch (retry++) {
159                 case 0:
160                         /* Second, kill app with SIGTERM */
161                         _I("Kill app with SIGTERM");
162                         terminate_process(path, false);
163                         time.tv_nsec = 500 * NANO_SECOND_MULTIPLIER;
164                         nanosleep(&time, NULL);
165                         ret = umount2(path, 0);
166                         break;
167                 case 1:
168                         /* Last time, kill app with SIGKILL */
169                         _I("Kill app with SIGKILL");
170                         terminate_process(path, true);
171                         time.tv_nsec = 200 * NANO_SECOND_MULTIPLIER;
172                         nanosleep(&time, NULL);
173                         ret = umount2(path, 0);
174                         break;
175                 }
176                 _I("ret %d retry %d", ret, retry);
177         }
178         if (ret) {
179                 if (force)
180                         ret = umount2(path, MNT_DETACH);
181                 else
182                         ret = umount2(path, 0);
183         }
184         if (ret)
185                 _I("Failed to unmount %s", path);
186         else
187                 _I("%s unmounted successfully", path);
188         return ret;
189 }