diff options
Diffstat (limited to 'libcutils')
-rw-r--r-- | libcutils/Android.mk | 2 | ||||
-rw-r--r-- | libcutils/android_reboot.c | 134 | ||||
-rw-r--r-- | libcutils/atomic-android-sh.c | 12 | ||||
-rw-r--r-- | libcutils/properties.c | 40 |
4 files changed, 136 insertions, 52 deletions
diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 03e6e9a..283a6bf 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -110,7 +110,7 @@ else #!sim # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE := libcutils -LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c uevent.c qtaguid.c +LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c android_reboot.c uevent.c qtaguid.c ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += arch-arm/memset32.S diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c new file mode 100644 index 0000000..33a7358 --- /dev/null +++ b/libcutils/android_reboot.c @@ -0,0 +1,134 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <unistd.h> +#include <sys/reboot.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> + +#include <cutils/android_reboot.h> + +/* Check to see if /proc/mounts contains any writeable filesystems + * backed by a block device. + * Return true if none found, else return false. + */ +static int remount_ro_done(void) +{ + FILE *f; + char mount_dev[256]; + char mount_dir[256]; + char mount_type[256]; + char mount_opts[256]; + int mount_freq; + int mount_passno; + int match; + int found_rw_fs = 0; + + f = fopen("/proc/mounts", "r"); + if (! f) { + /* If we can't read /proc/mounts, just give up */ + return 1; + } + + do { + match = fscanf(f, "%255s %255s %255s %255s %d %d\n", + mount_dev, mount_dir, mount_type, + mount_opts, &mount_freq, &mount_passno); + mount_dev[255] = 0; + mount_dir[255] = 0; + mount_type[255] = 0; + mount_opts[255] = 0; + if ((match == 6) && !strncmp(mount_dev, "/dev/block", 10) && strstr(mount_opts, "rw")) { + found_rw_fs = 1; + break; + } + } while (match != EOF); + + fclose(f); + + return !found_rw_fs; +} + +/* Remounting filesystems read-only is difficult when there are files + * opened for writing or pending deletes on the filesystem. There is + * no way to force the remount with the mount(2) syscall. The magic sysrq + * 'u' command does an emergency remount read-only on all writable filesystems + * that have a block device (i.e. not tmpfs filesystems) by calling + * emergency_remount(), which knows how to force the remount to read-only. + * Unfortunately, that is asynchronous, and just schedules the work and + * returns. The best way to determine if it is done is to read /proc/mounts + * repeatedly until there are no more writable filesystems mounted on + * block devices. + */ +static void remount_ro(void) +{ + int fd, cnt = 0; + + /* Trigger the remount of the filesystems as read-only, + * which also marks them clean. + */ + fd = open("/proc/sysrq-trigger", O_WRONLY); + if (fd < 0) { + return; + } + write(fd, "u", 1); + close(fd); + + + /* Now poll /proc/mounts till it's done */ + while (!remount_ro_done() && (cnt < 50)) { + usleep(100000); + cnt++; + } + + return; +} + + +int android_reboot(int cmd, int flags, char *arg) +{ + int ret; + + if (!(flags & ANDROID_RB_FLAG_NO_SYNC)) + sync(); + + if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO)) + remount_ro(); + + switch (cmd) { + case ANDROID_RB_RESTART: + ret = reboot(RB_AUTOBOOT); + break; + + case ANDROID_RB_POWEROFF: + ret = reboot(RB_POWER_OFF); + break; + + case ANDROID_RB_RESTART2: + ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, arg); + break; + + default: + ret = -1; + } + + return ret; +} + diff --git a/libcutils/atomic-android-sh.c b/libcutils/atomic-android-sh.c index f8f1f57..8bac68a 100644 --- a/libcutils/atomic-android-sh.c +++ b/libcutils/atomic-android-sh.c @@ -113,18 +113,6 @@ int32_t android_atomic_or(int32_t value, volatile int32_t* addr) { return oldValue; } -int32_t android_atomic_acquire_swap(int32_t value, volatile int32_t* addr) { - return android_atomic_release_swap(value, addr); -} - -int32_t android_atomic_release_swap(int32_t value, volatile int32_t* addr) { - int32_t oldValue; - do { - oldValue = *addr; - } while (android_atomic_cmpxchg(oldValue, value, addr)); - return oldValue; -} - int android_atomic_acquire_cmpxchg(int32_t oldvalue, int32_t newvalue, volatile int32_t* addr) { return android_atomic_release_cmpxchg(oldValue, newValue, addr); diff --git a/libcutils/properties.c b/libcutils/properties.c index 547cc6d..98f356b 100644 --- a/libcutils/properties.c +++ b/libcutils/properties.c @@ -31,47 +31,9 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> -static int send_prop_msg(prop_msg *msg) -{ - int s; - int r; - - s = socket_local_client(PROP_SERVICE_NAME, - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM); - if(s < 0) return -1; - - while((r = send(s, msg, sizeof(prop_msg), 0)) < 0) { - if((errno == EINTR) || (errno == EAGAIN)) continue; - break; - } - - if(r == sizeof(prop_msg)) { - r = 0; - } else { - r = -1; - } - - close(s); - return r; -} - int property_set(const char *key, const char *value) { - prop_msg msg; - unsigned resp; - - if(key == 0) return -1; - if(value == 0) value = ""; - - if(strlen(key) >= PROP_NAME_MAX) return -1; - if(strlen(value) >= PROP_VALUE_MAX) return -1; - - msg.cmd = PROP_MSG_SETPROP; - strcpy((char*) msg.name, key); - strcpy((char*) msg.value, value); - - return send_prop_msg(&msg); + return __system_property_set(key, value); } int property_get(const char *key, char *value, const char *default_value) |