1e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall/* 2e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * Copyright 2011, The Android Open Source Project 3e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * 4e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * Licensed under the Apache License, Version 2.0 (the "License"); 5e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * you may not use this file except in compliance with the License. 6e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * You may obtain a copy of the License at 7e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * 8e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * http://www.apache.org/licenses/LICENSE-2.0 9e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * 10e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * Unless required by applicable law or agreed to in writing, software 11e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * distributed under the License is distributed on an "AS IS" BASIS, 12e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * See the License for the specific language governing permissions and 14e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * limitations under the License. 15e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall */ 16e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 17e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <unistd.h> 18e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <sys/reboot.h> 19e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <sys/types.h> 20e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <sys/stat.h> 21e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <fcntl.h> 22e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <stdio.h> 23e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <string.h> 24e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 25e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#include <cutils/android_reboot.h> 26e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 27e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall/* Check to see if /proc/mounts contains any writeable filesystems 28e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * backed by a block device. 29e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * Return true if none found, else return false. 30e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall */ 31e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrallstatic int remount_ro_done(void) 32e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall{ 33e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall FILE *f; 34e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall char mount_dev[256]; 35e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall char mount_dir[256]; 36e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall char mount_type[256]; 37e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall char mount_opts[256]; 38e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int mount_freq; 39e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int mount_passno; 40e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int match; 41e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int found_rw_fs = 0; 42e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 43e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall f = fopen("/proc/mounts", "r"); 44e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall if (! f) { 45e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall /* If we can't read /proc/mounts, just give up */ 46e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall return 1; 47e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } 48e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 49e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall do { 50e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall match = fscanf(f, "%255s %255s %255s %255s %d %d\n", 51e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_dev, mount_dir, mount_type, 52e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_opts, &mount_freq, &mount_passno); 53e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_dev[255] = 0; 54e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_dir[255] = 0; 55e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_type[255] = 0; 56e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall mount_opts[255] = 0; 57e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall if ((match == 6) && !strncmp(mount_dev, "/dev/block", 10) && strstr(mount_opts, "rw")) { 58e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall found_rw_fs = 1; 59e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall break; 60e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } 61e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } while (match != EOF); 62e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 63e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall fclose(f); 64e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 65e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall return !found_rw_fs; 66e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall} 67e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 68e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall/* Remounting filesystems read-only is difficult when there are files 69e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * opened for writing or pending deletes on the filesystem. There is 70e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * no way to force the remount with the mount(2) syscall. The magic sysrq 71e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * 'u' command does an emergency remount read-only on all writable filesystems 72e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * that have a block device (i.e. not tmpfs filesystems) by calling 73e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * emergency_remount(), which knows how to force the remount to read-only. 74e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * Unfortunately, that is asynchronous, and just schedules the work and 75e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * returns. The best way to determine if it is done is to read /proc/mounts 76e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * repeatedly until there are no more writable filesystems mounted on 77e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * block devices. 78e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall */ 79e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrallstatic void remount_ro(void) 80e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall{ 81e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int fd, cnt = 0; 82e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 83e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall /* Trigger the remount of the filesystems as read-only, 84e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall * which also marks them clean. 85e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall */ 86e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall fd = open("/proc/sysrq-trigger", O_WRONLY); 87e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall if (fd < 0) { 88e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall return; 89e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } 90e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall write(fd, "u", 1); 91e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall close(fd); 92e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 93e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 94e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall /* Now poll /proc/mounts till it's done */ 95e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall while (!remount_ro_done() && (cnt < 50)) { 96e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall usleep(100000); 97e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall cnt++; 98e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } 99e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 100e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall return; 101e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall} 102e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 103e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 104e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrallint android_reboot(int cmd, int flags, char *arg) 105e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall{ 106e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall int ret; 107e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 108e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall if (!(flags & ANDROID_RB_FLAG_NO_SYNC)) 109e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall sync(); 110e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 111e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO)) 112e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall remount_ro(); 113e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 114e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall switch (cmd) { 115e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall case ANDROID_RB_RESTART: 116e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall ret = reboot(RB_AUTOBOOT); 117e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall break; 118e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 119e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall case ANDROID_RB_POWEROFF: 120e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall ret = reboot(RB_POWER_OFF); 121e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall break; 122e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 123e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall case ANDROID_RB_RESTART2: 124e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 125e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall LINUX_REBOOT_CMD_RESTART2, arg); 126e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall break; 127e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 128e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall default: 129e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall ret = -1; 130e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall } 131e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 132e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall return ret; 133e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall} 134e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall 135