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