void keychord_init() { int fd, ret; service_for_each(add_service_keycodes); /* nothing to do if no services require keychords */ if (!keychords) return; fd = open("/dev/keychord", O_RDWR | O_CLOEXEC); if (fd < 0) { ERROR("could not open /dev/keychord\n"); return; } ret = write(fd, keychords, keychords_length); if (ret != keychords_length) { ERROR("could not configure /dev/keychord %d: %s\n", ret, strerror(errno)); close(fd); fd = -1; } free(keychords); keychords = 0; keychord_fd = fd; }
static void unmount_and_fsck(const struct mntent *entry) { #ifndef UMOUNT_AND_FSCK_IS_UNSAFE if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4")) return; /* First, lazily unmount the directory. This unmount request finishes when * all processes that open a file or directory in |entry->mnt_dir| exit. */ TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH)); /* Next, kill all processes except init, kthreadd, and kthreadd's * children to finish the lazy unmount. Killing all processes here is okay * because this callback function is only called right before reboot(). * It might be cleaner to selectively kill processes that actually use * |entry->mnt_dir| rather than killing all, probably by reusing a function * like killProcessesWithOpenFiles() in vold/, but the selinux policy does * not allow init to scan /proc/<pid> files which the utility function * heavily relies on. The policy does not allow the process to execute * killall/pkill binaries either. Note that some processes might * automatically restart after kill(), but that is not really a problem * because |entry->mnt_dir| is no longer visible to such new processes. */ service_for_each(service_stop); TEMP_FAILURE_RETRY(kill(-1, SIGKILL)); int count = 0; while (count++ < UNMOUNT_CHECK_TIMES) { int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL)); if (fd >= 0) { /* |entry->mnt_dir| has sucessfully been unmounted. */ close(fd); break; } else if (errno == EBUSY) { /* Some processes using |entry->mnt_dir| are still alive. Wait for a * while then retry. */ TEMP_FAILURE_RETRY( usleep(UNMOUNT_CHECK_MS * 1000 / UNMOUNT_CHECK_TIMES)); continue; } else { /* Cannot open the device. Give up. */ return; } } int st; if (!strcmp(entry->mnt_type, "f2fs")) { const char *f2fs_argv[] = { "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname, }; android_fork_execvp_ext(ARRAY_SIZE(f2fs_argv), (char **)f2fs_argv, &st, true, LOG_KLOG, true, NULL); } else if (!strcmp(entry->mnt_type, "ext4")) { const char *ext4_argv[] = { "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname, }; android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv, &st, true, LOG_KLOG, true, NULL); } #endif }