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