4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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>
38 #include <system_info.h>
39 #include <sys/mount.h>
45 #define APP_ATTR_PATH "/proc/%d/attr/current"
47 int get_cmdline_name(pid_t pid, char *cmdline, size_t cmdline_size)
50 char buf[PATH_MAX + 1];
53 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
54 fd = open(buf, O_RDONLY);
60 ret = read(fd, buf, PATH_MAX);
67 filename = strrchr(buf, '/');
71 filename = filename + 1;
73 if (cmdline_size < strlen(filename) + 1) {
78 strncpy(cmdline, filename, cmdline_size - 1);
79 cmdline[cmdline_size - 1] = '\0';
89 ret = get_privilege(pid, attr, sizeof(attr));
91 _E("Failed to get privilege of PID(%d).", pid);
95 len = strlen(attr) + 1;
97 if (!strncmp("System", attr, len))
100 if (!strncmp("User", attr, len))
103 if (!strncmp("System::Privileged", attr, len))
111 * - Read from sysfs entry
112 * - Write to sysfs entry
114 int sys_check_node(char *path)
118 fd = open(path, O_RDONLY);
126 int get_systemd_reboot_param(char *buf, unsigned bufsize)
128 int r = sys_read_buf("/run/systemd/reboot-param", buf, bufsize);
132 if (r > 0 && buf[r - 1] == '\n') {
140 static int terminate_processes_on_partition(const char *partition, bool force)
142 const char *argv[7] = {"/usr/bin/fuser", "-m", "-k", "-s", NULL, NULL, NULL};
146 argv[4] = "-SIGKILL";
148 argv[4] = "-SIGTERM";
151 argc = sizeof(argv) / sizeof(argv[0]);
153 return run_child(argc, argv);
156 int mount_check(const char *path)
160 const char *table = "/etc/mtab";
164 fp = setmntent(table, "r");
168 len = strlen(path) + 1;
173 if (!strncmp(mnt->mnt_dir, path, len)) {
182 static int get_num_processes_on_partition(const char *part_path)
188 int num_processes = 0;
191 ret = asprintf(&cmd, "fuser -m %s | grep -o '[0-9]*'", part_path);
195 printf("cmd=%s\n", cmd);
196 fp = popen(cmd, "r");
201 while (getline(&line, &len, fp) != -1)
207 return num_processes;
210 void umount_partition_by_kill(const char *path, const int max_retry)
213 char *part_path = NULL;
215 int ret = 0, retry = 0;
219 /* if the path is not a mountpoint, do not perform umounting and killing */
220 if (!mount_check(path))
223 ret = asprintf(&cmd, "mount | grep \" on %s \" | awk '{print $1}'", path);
227 fp = popen(cmd, "r");
232 ret = getline(&part_path, &len, fp);
233 if (ret == -1 || !part_path) {
237 } else if (ret > 0 && *(part_path + ret - 1) == '\n') {
238 *(part_path + ret -1) = '\0';
242 umount2(path, MNT_DETACH);
245 /* Kill processes with SIGTERM */
246 terminate_processes_on_partition(part_path, false);
247 usleep((useconds_t)MSEC_TO_USEC(500));
249 /* Kill processes with SIGKILL */
250 terminate_processes_on_partition(part_path, true);
251 usleep((useconds_t)MSEC_TO_USEC(200));
253 remain = get_num_processes_on_partition(part_path);
257 } while (remain > 0 && retry < max_retry);
265 #define CMD_FROZEN "FROZEN"
266 #define CMD_THAWED "THAWED"
267 static int freeze_processes_on_path(const char *frz_name, const char *part_path)
269 char *fuser_cmd = NULL;
279 ret = asprintf(&fuser_cmd, "fuser -m %s | grep -o '[0-9]*'", part_path);
283 fuser_fp = popen(fuser_cmd, "r");
285 if (fuser_fp == NULL)
288 ret = asprintf(&freezer_procs, "/sys/fs/cgroup/freezer/%s/cgroup.procs", frz_name);
294 task_fd = open(freezer_procs, O_RDWR);
301 while (getline(&line, &len, fuser_fp) != -1) {
303 int str_len = strlen(line);
307 ret = write(task_fd, line, str_len-1);
316 ret = asprintf(&freezer_state, "/sys/fs/cgroup/freezer/%s/freezer.state", frz_name);
320 freezer_fd = open(freezer_state, O_RDWR);
325 ret = write(freezer_fd, CMD_FROZEN, strlen(CMD_FROZEN));
333 static bool check_frozen(const char *frz_name)
335 char *state_path = NULL;
342 ret = asprintf(&state_path, "/sys/fs/cgroup/freezer/%s/freezer.state", frz_name);
346 fd = fopen(state_path, "r");
351 ret = getline(&line, &len, fd);
352 if (ret != -1 && line) {
353 if (!strncmp(line, CMD_FROZEN, strlen(CMD_FROZEN)))
366 static int thaw_processes_on_path(const char *frz_name)
372 ret = asprintf(&freezer_state, "/sys/fs/cgroup/freezer/%s/freezer.state", frz_name);
376 freezer_fd = open(freezer_state, O_RDWR);
381 ret = write(freezer_fd, CMD_THAWED, strlen(CMD_THAWED));
389 void suspend_path(const char *frz_name, const char *path, const int max_retry)
394 freeze_processes_on_path(frz_name, path);
397 usleep((useconds_t)MSEC_TO_USEC(500));
399 frozen = check_frozen(frz_name);
403 } while (!frozen && retry < max_retry);
406 void resume_path(const char *frz_name, const char *path)
408 thaw_processes_on_path(frz_name);
411 int get_privilege(pid_t pid, char *name, size_t len)
418 snprintf(path, sizeof(path), APP_ATTR_PATH, pid);
420 fp = fopen(path, "r");
424 attr_len = fread(attr, 1, sizeof(attr) - 1, fp);
429 attr[attr_len] = '\0';
431 snprintf(name, len, "%s", attr);
435 #define MODEL_NAME "http://tizen.org/system/model_name"
436 #define MODEL_EMULATOR "Emulator"
438 bool is_emulator(void)
441 char *model_name = NULL;
442 static bool emul = false;
448 ret = system_info_get_platform_string(MODEL_NAME, &model_name);
450 _E("Cannot get model name: %d", ret);
454 if (!strncmp(MODEL_EMULATOR, model_name, strlen(model_name) + 1))
463 int do_mkdir(const char *path, mode_t mode)
473 for (p = 0, s = 0; p < l; p += s + 1) {
474 s = strcspn(path + p, "/");
478 assert(PATH_MAX > p + s + 1);
480 r = snprintf(d, p + s + 1, "%s", path);
485 if (r < 0 && errno != EEXIST)
492 static int do_copy_internal(const char *src, const char *dst, mode_t mode, bool force)
494 _cleanup_close_ int rfd = -1, wfd = -1;
503 r = access(dst, F_OK);
506 else if (errno != ENOENT)
510 wfd = open(dst, O_CREAT | O_WRONLY | O_TRUNC, mode);
514 rfd = open(src, O_RDONLY);
518 while ((red = read(rfd, buf, 1024)) > 0)
519 if (write(wfd, buf, red) != red)
528 int do_copy_force(const char *src, const char *dst)
533 return do_copy_internal(src, dst, 0644, true);