Merge change 20039
* changes:
adb: add "adb reboot" command.
diff --git a/adb/adb.c b/adb/adb.c
index 956df54..e8d2c8f 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -30,6 +30,8 @@
#if !ADB_HOST
#include <private/android_filesystem_config.h>
+#include <linux/capability.h>
+#include <linux/prctl.h>
#else
#include "usb_vendors.h"
#endif
@@ -879,6 +881,11 @@
/* don't listen on port 5037 if we are running in secure mode */
/* don't run as root if we are running in secure mode */
if (secure) {
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct cap;
+
+ prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
/* add extra groups:
** AID_ADB to access the USB driver
** AID_LOG to read system logs (adb logcat)
@@ -896,6 +903,13 @@
setgid(AID_SHELL);
setuid(AID_SHELL);
+ /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = 0;
+ cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
+ cap.inheritable = 0;
+ capset(&header, &cap);
+
D("Local port 5037 disabled\n");
} else {
if(install_listener("tcp:5037", "*smartsocket*", NULL)) {
diff --git a/adb/adb.h b/adb/adb.h
index 95610a7..8d57bf2 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -33,7 +33,7 @@
#define ADB_VERSION_MAJOR 1 // Used for help/version information
#define ADB_VERSION_MINOR 0 // Used for help/version information
-#define ADB_SERVER_VERSION 21 // Increment this when we want to force users to start a new adb server
+#define ADB_SERVER_VERSION 22 // Increment this when we want to force users to start a new adb server
typedef struct amessage amessage;
typedef struct apacket apacket;
diff --git a/adb/commandline.c b/adb/commandline.c
index ad1021c..4ec5c8b 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -148,6 +148,7 @@
" adb get-serialno - prints: <serial-number>\n"
" adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system partition on the device read-write\n"
+ " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
" adb root - restarts adb with root permissions\n"
"\n"
"networking:\n"
@@ -918,6 +919,22 @@
return 1;
}
+ if(!strcmp(argv[0], "reboot")) {
+ int fd;
+ if (argc > 1)
+ snprintf(buf, sizeof(buf), "reboot:%s", argv[1]);
+ else
+ snprintf(buf, sizeof(buf), "reboot:");
+ fd = adb_connect(buf);
+ if(fd >= 0) {
+ read_and_dump(fd);
+ adb_close(fd);
+ return 0;
+ }
+ fprintf(stderr,"error: %s\n", adb_error());
+ return 1;
+ }
+
if(!strcmp(argv[0], "root")) {
int fd = adb_connect("root:");
if(fd >= 0) {
diff --git a/adb/services.c b/adb/services.c
index 78d092b..517da55 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -33,6 +33,7 @@
# endif
#else
#include <sys/poll.h>
+#include <sys/reboot.h>
#endif
typedef struct stinfo stinfo;
@@ -133,6 +134,20 @@
}
}
+void reboot_service(int fd, char *arg)
+{
+ char buf[100];
+ int ret;
+
+ sync();
+ ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, arg);
+ if (ret < 0) {
+ snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
+ writex(fd, buf, strlen(buf));
+ }
+ adb_close(fd);
+}
+
#endif
#if 0
@@ -399,6 +414,11 @@
ret = create_service_thread(file_sync_service, NULL);
} else if(!strncmp(name, "remount:", 8)) {
ret = create_service_thread(remount_service, NULL);
+ } else if(!strncmp(name, "reboot:", 7)) {
+ char* arg = name + 7;
+ if (*name == 0)
+ arg = NULL;
+ ret = create_service_thread(reboot_service, arg);
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread(restart_root_service, NULL);
#endif