2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <sys/types.h>
35 #define TRACE_TAG TRACE_SDB
37 #include "sdb_client.h"
38 #include "file_sync_service.h"
40 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
42 void get_my_path(char *s, size_t maxLen);
43 int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45 int install_app(transport_type transport, char* serial, int argc, char** argv);
46 int uninstall_app_sdb(const char *app_id);
47 int install_app_sdb(const char *srcpath);
48 int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
49 int sdb_command2(const char* cmd);
51 static const char *gProductOutPath = NULL;
53 static char *product_file(const char *extra)
58 if (gProductOutPath == NULL) {
59 fprintf(stderr, "sdb: Product directory not specified; "
60 "use -p or define ANDROID_PRODUCT_OUT\n");
64 n = strlen(gProductOutPath) + strlen(extra) + 2;
67 fprintf(stderr, "sdb: Out of memory (product_file())\n");
71 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
75 void version(FILE * out) {
76 fprintf(out, "Smart Development Bridge version %d.%d.%d\n",
77 SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_SERVER_VERSION);
86 " Usage : sdb [option] <command> [parameters]\n"
89 " -d - directs command to the only connected USB device\n"
90 " returns an error if more than one USB device is present.\n"
91 " -e - directs command to the only running emulator.\n"
92 " returns an error if more than one emulator is running.\n"
93 " -s <serial number> - directs command to the USB device or emulator with\n"
94 " the given serial number.\n"
95 " devices - list all connected devices\n"
96 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
97 " Port 26101 is used by default if no port number is specified.\n"
98 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
99 " Port 26101 is used by default if no port number is specified.\n"
100 " Using this command with no additional arguments\n"
101 " will disconnect from all connected TCP/IP devices.\n"
104 " sdb push <local> <remote> [-with-utf8]\n"
105 " - copy file/dir to device\n"
106 " (-with-utf8 means to create the remote file with utf8 character encoding)\n"
107 " sdb pull <remote> [<local>] - copy file/dir from device\n"
108 " sdb shell - run remote shell interactively\n"
109 " sdb shell <command> - run remote shell \n"
110 " sdb dlog [ <filter-spec> ] - view device log\n"
111 " sdb install <path_to_tpk> - push tpk package file and install it\n"
112 " sdb uninstall <appid> - uninstall this app from the device\n"
113 " sdb forward <local> <remote> - forward socket connections\n"
115 " forward spec is : \n"
117 " sdb help - show this help message\n"
118 " sdb version - show version num\n"
120 " sdb start-server - ensure that there is a server running\n"
121 " sdb kill-server - kill the server if it is running\n"
122 " sdb get-state - prints: offline | bootloader | device\n"
123 " sdb get-serialno - prints: <serial-number>\n"
124 " sdb status-window - continuously print device status for a specified device\n"
125 " sdb usb - restarts the sdbd daemon listing on USB\n"
126 // " sdb tcpip <port> - restarts the sdbd daemon listing on TCP on the specified port"
127 " sdb tcpip - restarts the sdbd daemon listing on TCP"
139 static struct termios tio_save;
141 static void stdin_raw_init(int fd)
145 if(tcgetattr(fd, &tio)) return;
146 if(tcgetattr(fd, &tio_save)) return;
148 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
150 /* no timeout but request at least one character per read */
154 tcsetattr(fd, TCSANOW, &tio);
155 tcflush(fd, TCIFLUSH);
158 static void stdin_raw_restore(int fd)
160 tcsetattr(fd, TCSANOW, &tio_save);
161 tcflush(fd, TCIFLUSH);
165 static void read_and_dump(int fd)
171 D("read_and_dump(): pre sdb_read(fd=%d)\n", fd);
172 len = sdb_read(fd, buf, 4096);
173 D("read_and_dump(): post sdb_read(fd=%d): len=%d\n", fd, len);
179 if(errno == EINTR) continue;
182 fwrite(buf, 1, len, stdout);
187 static void copy_to_file(int inFd, int outFd) {
188 const size_t BUFSIZE = 32 * 1024;
189 char* buf = (char*) malloc(BUFSIZE);
193 D("copy_to_file(%d -> %d)\n", inFd, outFd);
195 len = sdb_read(inFd, buf, BUFSIZE);
197 D("copy_to_file() : read 0 bytes; exiting\n");
201 if (errno == EINTR) {
202 D("copy_to_file() : EINTR, retrying\n");
205 D("copy_to_file() : error %d\n", errno);
208 sdb_write(outFd, buf, len);
211 D("copy_to_file() finished after %lu bytes\n", total);
215 static void *stdin_read_thread(void *x)
218 unsigned char buf[1024];
228 /* fdi is really the client's stdin, so use read, not sdb_read here */
229 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
230 r = unix_read(fdi, buf, 1024);
231 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
234 if(errno == EINTR) continue;
237 for(n = 0; n < r; n++){
246 if(state == 1) state++;
250 fprintf(stderr,"\n* disconnect *\n");
252 stdin_raw_restore(fdi);
260 r = sdb_write(fd, buf, r);
268 int interactive_shell(void)
274 fd = sdb_connect("shell:");
276 fprintf(stderr,"error: %s\n", sdb_error());
281 fds = malloc(sizeof(int) * 2);
288 sdb_thread_create(&thr, stdin_read_thread, fds);
291 stdin_raw_restore(fdi);
297 static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
300 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
302 const char* prefix = "host";
303 if (ttype == kTransportUsb)
305 else if (ttype == kTransportLocal)
306 prefix = "host-local";
308 snprintf(buffer, buflen, "%s:%s", prefix, command);
311 #if 0 /* tizen specific */
312 int sdb_download_buffer(const char *service, const void* data, int sz,
318 const unsigned char *ptr;
320 sprintf(buf,"%s:%d", service, sz);
321 fd = sdb_connect(buf);
323 fprintf(stderr,"error: %s\n", sdb_error());
327 int opt = CHUNK_SIZE;
328 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
334 char *x = strrchr(service, ':');
335 if(x) service = x + 1;
339 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
340 if(writex(fd, ptr, xfer)) {
342 fprintf(stderr,"* failed to write data '%s' *\n", sdb_error());
348 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
356 if(readx(fd, buf, 4)){
357 fprintf(stderr,"* error reading response *\n");
361 if(memcmp(buf, "OKAY", 4)) {
363 fprintf(stderr,"* error response '%s' *\n", buf);
372 int sdb_download(const char *service, const char *fn, unsigned progress)
377 data = load_file(fn, &sz);
379 fprintf(stderr,"* cannot read '%s' *\n", service);
383 int status = sdb_download_buffer(service, data, sz, progress);
388 static void status_window(transport_type ttype, const char* serial)
399 fd = unix_open("/dev/null", O_WRONLY);
404 format_host_command(command, sizeof command, "get-state", ttype, serial);
414 state = sdb_query(command);
417 if(laststate && !strcmp(state,laststate)){
420 if(laststate) free(laststate);
421 laststate = strdup(state);
425 printf("%c[2J%c[2H", 27, 27);
426 printf("Samsung Development Bridge\n");
427 printf("State: %s\n", state ? state : "offline");
432 /** duplicate string and quote all \ " ( ) chars + space character. */
434 dupAndQuote(const char *s)
445 for( ;*ts != '\0'; ts++) {
447 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
452 ret = (char *)malloc(alloc_len + 1);
457 for ( ;*ts != '\0'; ts++) {
458 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
471 * Run ppp in "notty" mode against a resource listed as the first parameter
474 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
477 int ppp(int argc, char **argv)
479 #ifdef HAVE_WIN32_PROC
480 fprintf(stderr, "error: sdb %s not implemented on Win32\n", argv[0]);
483 char *sdb_service_name;
488 fprintf(stderr, "usage: sdb %s <sdb service name> [ppp opts]\n",
494 sdb_service_name = argv[1];
496 fd = sdb_connect(sdb_service_name);
499 fprintf(stderr,"Error: Could not open sdb service: %s. Error: %s\n",
500 sdb_service_name, sdb_error());
507 perror("from fork()");
509 } else if (pid == 0) {
512 const char **ppp_args;
515 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
516 ppp_args[0] = "pppd";
517 for (i = 2 ; i < argc ; i++) {
518 //argv[2] and beyond become ppp_args[1] and beyond
519 ppp_args[i - 1] = argv[i];
521 ppp_args[i-1] = NULL;
525 dup2(fd, STDIN_FILENO);
526 dup2(fd, STDOUT_FILENO);
527 sdb_close(STDERR_FILENO);
530 err = execvp("pppd", (char * const *)ppp_args);
533 perror("execing pppd");
542 #endif /* !HAVE_WIN32_PROC */
545 static int send_shellcommand(transport_type transport, char* serial, char* buf)
550 fd = sdb_connect(buf);
553 fprintf(stderr,"- waiting for device -\n");
555 do_cmd(transport, serial, "wait-for-device", 0);
566 static int logcat(transport_type transport, char* serial, int argc, char **argv)
571 char *quoted_log_tags;
573 log_tags = getenv("ANDROID_LOG_TAGS");
574 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
576 snprintf(buf, sizeof(buf),
577 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
580 free(quoted_log_tags);
582 if (!strcmp(argv[0],"longcat")) {
583 strncat(buf, " -v long", sizeof(buf)-1);
591 quoted = dupAndQuote (*argv++);
593 strncat(buf, " ", sizeof(buf)-1);
594 strncat(buf, quoted, sizeof(buf)-1);
598 send_shellcommand(transport, serial, buf);
602 static int mkdirs(char *path)
611 ret = sdb_mkdir(path, 0775);
612 *x = OS_PATH_SEPARATOR;
613 if((ret < 0) && (errno != EEXIST)) {
621 static int backup(int argc, char** argv) {
623 char default_name[32];
624 const char* filename = strcpy(default_name, "./backup.ab");
628 /* find, extract, and use any -f argument */
629 for (i = 1; i < argc; i++) {
630 if (!strcmp("-f", argv[i])) {
632 fprintf(stderr, "sdb: -f passed with no filename\n");
635 filename = argv[i+1];
636 for (j = i+2; j <= argc; ) {
637 argv[i++] = argv[j++];
644 /* bare "sdb backup" or "sdb backup -f filename" are not valid invocations */
645 if (argc < 2) return usage();
647 sdb_unlink(filename);
648 mkdirs((char *)filename);
649 outFd = sdb_creat(filename, 0640);
651 fprintf(stderr, "sdb: unable to open file %s\n", filename);
655 snprintf(buf, sizeof(buf), "backup");
656 for (argc--, argv++; argc; argc--, argv++) {
657 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
658 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
661 D("backup. filename=%s buf=%s\n", filename, buf);
662 fd = sdb_connect(buf);
664 fprintf(stderr, "sdb: unable to connect for backup\n");
669 printf("Now unlock your device and confirm the backup operation.\n");
670 copy_to_file(fd, outFd);
677 static int restore(int argc, char** argv) {
678 const char* filename;
681 if (argc != 2) return usage();
684 tarFd = sdb_open(filename, O_RDONLY);
686 fprintf(stderr, "sdb: unable to open file %s\n", filename);
690 fd = sdb_connect("restore:");
692 fprintf(stderr, "sdb: unable to connect for backup\n");
697 printf("Now unlock your device and confirm the restore operation.\n");
698 copy_to_file(tarFd, fd);
705 #define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
706 static int top_works(const char *top)
708 if (top != NULL && sdb_is_absolute_host_path(top)) {
709 char path_buf[PATH_MAX];
710 snprintf(path_buf, sizeof(path_buf),
711 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
712 return access(path_buf, F_OK) == 0;
717 static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
719 strcpy(path_buf, indir);
721 if (top_works(path_buf)) {
724 char *s = sdb_dirstop(path_buf);
734 static char *find_top(char path_buf[PATH_MAX])
736 char *top = getenv("ANDROID_BUILD_TOP");
737 if (top != NULL && top[0] != '\0') {
738 if (!top_works(top)) {
739 fprintf(stderr, "sdb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
744 if (top != NULL && top[0] != '\0') {
745 if (!top_works(top)) {
746 fprintf(stderr, "sdb: bad TOP value \"%s\"\n", top);
755 /* The environment pointed to a top directory that works.
757 strcpy(path_buf, top);
761 /* The environment didn't help. Walk up the tree from the CWD
762 * to see if we can find the top.
765 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
767 /* If the CWD isn't under a good-looking top, see if the
770 get_my_path(dir, PATH_MAX);
771 top = find_top_from(dir, path_buf);
777 * - A simple product name
779 TODO: debug? sooner-debug, sooner:debug?
780 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
781 * e.g., "out/target/product/sooner"
782 * - An absolute path to the PRODUCT_OUT dir
783 * e.g., "/src/device/out/target/product/sooner"
785 * Given <hint>, try to construct an absolute path to the
786 * ANDROID_PRODUCT_OUT dir.
788 static const char *find_product_out_path(const char *hint)
790 static char path_buf[PATH_MAX];
792 if (hint == NULL || hint[0] == '\0') {
796 /* If it's already absolute, don't bother doing any work.
798 if (sdb_is_absolute_host_path(hint)) {
799 strcpy(path_buf, hint);
803 /* If there are any slashes in it, assume it's a relative path;
806 if (sdb_dirstart(hint) != NULL) {
807 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
808 fprintf(stderr, "sdb: Couldn't get CWD: %s\n", strerror(errno));
811 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
812 fprintf(stderr, "sdb: Couldn't assemble path\n");
815 strcat(path_buf, OS_PATH_SEPARATOR_STR);
816 strcat(path_buf, hint);
820 /* It's a string without any slashes. Try to do something with it.
822 * Try to find the root of the build tree, and build a PRODUCT_OUT
825 char top_buf[PATH_MAX];
826 const char *top = find_top(top_buf);
828 fprintf(stderr, "sdb: Couldn't find top of build tree\n");
831 //TODO: if we have a way to indicate debug, look in out/debug/target/...
832 snprintf(path_buf, sizeof(path_buf),
833 "%s" OS_PATH_SEPARATOR_STR
834 "out" OS_PATH_SEPARATOR_STR
835 "target" OS_PATH_SEPARATOR_STR
836 "product" OS_PATH_SEPARATOR_STR
837 "%s", top_buf, hint);
838 if (access(path_buf, F_OK) < 0) {
839 fprintf(stderr, "sdb: Couldn't find a product dir "
840 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
846 int sdb_commandline(int argc, char **argv)
855 transport_type ttype = kTransportAny;
857 char* server_port_str = NULL;
859 /* If defined, this should be an absolute path to
860 * the directory containing all of the various system images
861 * for a particular product. If not defined, and the sdb
862 * command requires this information, then the user must
863 * specify the path using "-p".
865 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
866 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
867 gProductOutPath = NULL;
869 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
871 serial = getenv("ANDROID_SERIAL");
873 /* Validate and assign the server port */
874 server_port_str = getenv("ANDROID_SDB_SERVER_PORT");
875 int server_port = DEFAULT_SDB_PORT;
876 if (server_port_str && strlen(server_port_str) > 0) {
877 server_port = (int) strtol(server_port_str, NULL, 0);
878 if (server_port <= 0) {
880 "sdb: Env var ANDROID_SDB_SERVER_PORT must be a positive number. Got \"%s\"\n",
886 /* modifiers and flags */
888 if(!strcmp(argv[0],"server")) {
890 } else if(!strcmp(argv[0],"nodaemon")) {
892 } else if (!strcmp(argv[0], "fork-server")) {
893 /* this is a special flag used only when the SDB client launches the SDB Server */
895 } else if(!strcmp(argv[0],"persist")) {
897 } else if(!strncmp(argv[0], "-p", 2)) {
898 const char *product = NULL;
899 if (argv[0][2] == '\0') {
900 if (argc < 2) return usage();
905 product = argv[1] + 2;
907 gProductOutPath = find_product_out_path(product);
908 if (gProductOutPath == NULL) {
909 fprintf(stderr, "sdb: could not resolve \"-p %s\"\n",
913 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
914 if (isdigit(argv[0][2])) {
915 serial = argv[0] + 2;
917 if(argc < 2 || argv[0][2] != '\0') return usage();
922 } else if (!strcmp(argv[0],"-d")) {
923 ttype = kTransportUsb;
924 } else if (!strcmp(argv[0],"-e")) {
925 ttype = kTransportLocal;
927 /* out of recognized modifiers and flags */
934 sdb_set_transport(ttype, serial);
935 sdb_set_tcp_specifics(server_port);
938 if (no_daemon || is_daemon) {
939 r = sdb_main(is_daemon, server_port);
941 r = launch_server(server_port);
944 fprintf(stderr,"* could not start server *\n");
954 /* sdb_connect() commands */
956 if(!strcmp(argv[0], "devices")) {
958 snprintf(buf, sizeof buf, "host:%s", argv[0]);
959 tmp = sdb_query(buf);
961 printf("List of devices attached \n");
969 if(!strcmp(argv[0], "connect")) {
972 fprintf(stderr, "Usage: sdb connect <host>[:<port>]\n");
975 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
976 tmp = sdb_query(buf);
985 if(!strcmp(argv[0], "disconnect")) {
988 fprintf(stderr, "Usage: sdb disconnect [<host>[:<port>]]\n");
992 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
994 snprintf(buf, sizeof buf, "host:disconnect:");
996 tmp = sdb_query(buf);
1005 if (!strcmp(argv[0], "emu")) {
1006 return sdb_send_emulator_command(argc, argv);
1009 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
1013 char h = (argv[0][0] == 'h');
1016 printf("\x1b[41;33m");
1021 D("starting interactive shell\n");
1022 r = interactive_shell();
1030 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1036 /* quote empty strings and strings with spaces */
1037 quote = (**argv == 0 || strchr(*argv, ' '));
1040 strcat(buf, *argv++);
1046 D("interactive shell loop. buff=%s\n", buf);
1047 fd = sdb_connect(buf);
1049 D("about to read_and_dump(fd=%d)\n", fd);
1051 D("read_and_dump() done.\n");
1055 fprintf(stderr,"error: %s\n", sdb_error());
1060 fprintf(stderr,"\n- waiting for device -\n");
1062 do_cmd(ttype, serial, "wait-for-device", 0);
1068 D("interactive shell loop. return r=%d\n", r);
1074 if(!strcmp(argv[0], "kill-server")) {
1076 fd = _sdb_connect("host:kill");
1078 fprintf(stderr,"* server not running *\n");
1083 #if 0 /* tizen specific */
1084 if(!strcmp(argv[0], "sideload")) {
1085 if(argc != 2) return usage();
1086 if(sdb_download("sideload", argv[1], 1)) {
1093 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
1094 || !strcmp(argv[0], "reboot-bootloader")
1095 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
1096 || !strcmp(argv[0], "root")) {
1098 if (!strcmp(argv[0], "reboot-bootloader"))
1099 snprintf(command, sizeof(command), "reboot:bootloader");
1101 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
1103 snprintf(command, sizeof(command), "%s:", argv[0]);
1104 int fd = sdb_connect(command);
1110 fprintf(stderr,"error: %s\n", sdb_error());
1114 if(!strcmp(argv[0], "bugreport")) {
1115 if (argc != 1) return usage();
1116 do_cmd(ttype, serial, "shell", "bugreport", 0);
1120 /* sdb_command() wrapper commands */
1122 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1123 char* service = argv[0];
1124 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1125 if (ttype == kTransportUsb) {
1126 service = "wait-for-usb";
1127 } else if (ttype == kTransportLocal) {
1128 service = "wait-for-local";
1130 service = "wait-for-any";
1134 format_host_command(buf, sizeof buf, service, ttype, serial);
1136 if (sdb_command(buf)) {
1137 D("failure: %s *\n",sdb_error());
1138 fprintf(stderr,"error: %s\n", sdb_error());
1142 /* Allow a command to be run after wait-for-device,
1143 * e.g. 'sdb wait-for-device shell'.
1153 if(!strcmp(argv[0], "forward")) {
1154 if(argc != 3) return usage();
1156 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1157 } else if (ttype == kTransportUsb) {
1158 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1159 } else if (ttype == kTransportLocal) {
1160 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
1162 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
1164 if(sdb_command(buf)) {
1165 fprintf(stderr,"error: %s\n", sdb_error());
1171 /* do_sync_*() commands */
1173 if(!strcmp(argv[0], "ls")) {
1174 if(argc != 2) return usage();
1175 return do_sync_ls(argv[1]);
1178 if(!strcmp(argv[0], "push")) {
1182 if(argc < 3) return usage();
1183 if (argv[argc-1][0] == '-') {
1184 if (!strcmp(argv[argc-1], "-with-utf8")) {
1191 for (i=1; i<argc-1; i++) {
1192 do_sync_push(argv[i], argv[argc-1], 0 /* no verify APK */, utf8);
1197 if(!strcmp(argv[0], "install")) {
1198 if(argc != 2) return usage();
1200 return install_app_sdb(argv[1]);
1203 if(!strcmp(argv[0], "uninstall")) {
1204 if(argc != 2) return usage();
1206 return uninstall_app_sdb(argv[1]);
1209 if(!strcmp(argv[0], "pull")) {
1211 return do_sync_pull(argv[1], ".");
1212 } else if (argc == 3) {
1213 return do_sync_pull(argv[1], argv[2]);
1219 if(!strcmp(argv[0], "install")) {
1220 if (argc < 2) return usage();
1221 return install_app(ttype, serial, argc, argv);
1224 if(!strcmp(argv[0], "uninstall")) {
1225 if (argc < 2) return usage();
1226 return uninstall_app(ttype, serial, argc, argv);
1229 if(!strcmp(argv[0], "sync")) {
1230 char *srcarg, *android_srcpath, *data_srcpath;
1235 /* No local path was specified. */
1237 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1244 } else if(argc == 2) {
1245 /* A local path or "android"/"data" arg was specified. */
1250 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1251 if(ret != 0) return usage();
1253 if(android_srcpath != NULL)
1254 ret = do_sync_sync(android_srcpath, "/system", listonly);
1255 if(ret == 0 && data_srcpath != NULL)
1256 ret = do_sync_sync(data_srcpath, "/data", listonly);
1258 free(android_srcpath);
1263 /* passthrough commands */
1265 if(!strcmp(argv[0],"get-state") ||
1266 !strcmp(argv[0],"get-serialno"))
1270 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1271 tmp = sdb_query(buf);
1273 printf("%s\n", tmp);
1280 /* other commands */
1282 if(!strcmp(argv[0],"status-window")) {
1283 status_window(ttype, serial);
1287 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
1288 return logcat(ttype, serial, argc, argv);
1291 if(!strcmp(argv[0],"ppp")) {
1292 return ppp(argc, argv);
1295 if (!strcmp(argv[0], "start-server")) {
1296 return sdb_connect("host:start-server");
1299 if (!strcmp(argv[0], "backup")) {
1300 return backup(argc, argv);
1303 if (!strcmp(argv[0], "restore")) {
1304 return restore(argc, argv);
1307 if (!strcmp(argv[0], "jdwp")) {
1308 int fd = sdb_connect("jdwp");
1314 fprintf(stderr, "error: %s\n", sdb_error());
1319 /* "sdb /?" is a common idiom under Windows */
1320 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1325 if(!strcmp(argv[0], "version")) {
1334 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1344 argv[argc++] = "-s";
1345 argv[argc++] = serial;
1346 } else if (ttype == kTransportUsb) {
1347 argv[argc++] = "-d";
1348 } else if (ttype == kTransportLocal) {
1349 argv[argc++] = "-e";
1353 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1358 fprintf(stderr,"argc = %d\n",argc);
1359 for(n = 0; n < argc; n++) {
1360 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1364 return sdb_commandline(argc, argv);
1367 int find_sync_dirs(const char *srcarg,
1368 char **android_srcdir_out, char **data_srcdir_out)
1370 char *android_srcdir, *data_srcdir;
1372 if(srcarg == NULL) {
1373 android_srcdir = product_file("system");
1374 data_srcdir = product_file("data");
1376 /* srcarg may be "data", "system" or NULL.
1377 * if srcarg is NULL, then both data and system are synced
1379 if(strcmp(srcarg, "system") == 0) {
1380 android_srcdir = product_file("system");
1382 } else if(strcmp(srcarg, "data") == 0) {
1383 android_srcdir = NULL;
1384 data_srcdir = product_file("data");
1386 /* It's not "system" or "data".
1392 if(android_srcdir_out != NULL)
1393 *android_srcdir_out = android_srcdir;
1395 free(android_srcdir);
1397 if(data_srcdir_out != NULL)
1398 *data_srcdir_out = data_srcdir;
1405 static int pm_command(transport_type transport, char* serial,
1406 int argc, char** argv)
1410 snprintf(buf, sizeof(buf), "shell:pm");
1415 quoted = dupAndQuote(*argv++);
1417 strncat(buf, " ", sizeof(buf)-1);
1418 strncat(buf, quoted, sizeof(buf)-1);
1422 send_shellcommand(transport, serial, buf);
1426 int sdb_command2(const char* cmd) {
1427 int result = sdb_connect(cmd);
1433 D("about to read_and_dump(fd=%d)\n", result);
1434 read_and_dump(result);
1435 D("read_and_dump() done.\n");
1441 int install_app_sdb(const char *srcpath) {
1442 D("Install start\n");
1443 const char * APP_DEST = "/opt/apps/PKGS/%s";
1444 const char* filename = sdb_dirstop(srcpath);
1445 char destination[PATH_MAX];
1449 snprintf(destination, sizeof destination, APP_DEST, filename);
1451 snprintf(destination, sizeof destination, APP_DEST, srcpath);
1454 D("Push file: %s to %s\n", srcpath, destination);
1455 int result = do_sync_push(srcpath, destination, 0, 0);
1458 fprintf(stderr, "error: %s\n", sdb_error());
1462 const char* SHELL_INSTALL_CMD ="shell:pkgcmd -i -t tpk -p %s -q";
1463 char full_cmd[PATH_MAX];
1464 snprintf(full_cmd, sizeof full_cmd, SHELL_INSTALL_CMD, destination);
1465 D("Install command: %s\n", full_cmd);
1466 result = sdb_command2(full_cmd);
1469 fprintf(stderr, "error: %s\n", sdb_error());
1473 const char* SHELL_REMOVE_CMD = "shell:rm %s";
1474 snprintf(full_cmd, sizeof full_cmd, SHELL_REMOVE_CMD, destination);
1475 D("Remove file command: %s\n", full_cmd);
1476 result = sdb_command2(full_cmd);
1479 fprintf(stderr, "error: %s\n", sdb_error());
1486 int uninstall_app_sdb(const char *appid) {
1487 const char* SHELL_UNINSTALL_CMD ="shell:pkgcmd -u -t tpk -n %s -q";
1488 char full_cmd[PATH_MAX];
1489 snprintf(full_cmd, sizeof full_cmd, SHELL_UNINSTALL_CMD, appid);
1490 return sdb_command(full_cmd);
1493 int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1495 /* if the user choose the -k option, we refuse to do it until devices are
1496 out with the option to uninstall the remaining data somehow (sdb/ui) */
1497 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1500 "The -k option uninstalls the application while retaining the data/cache.\n"
1501 "At the moment, there is no way to remove the remaining data.\n"
1502 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1503 "If you truly wish to continue, execute 'sdb shell pm uninstall -k %s'\n", argv[2]);
1507 /* 'sdb uninstall' takes the same arguments as 'pm uninstall' on device */
1508 return pm_command(transport, serial, argc, argv);
1511 static int delete_file(transport_type transport, char* serial, char* filename)
1516 snprintf(buf, sizeof(buf), "shell:rm ");
1517 quoted = dupAndQuote(filename);
1518 strncat(buf, quoted, sizeof(buf)-1);
1521 send_shellcommand(transport, serial, buf);
1525 const char* get_basename(const char* filename)
1527 const char* basename = sdb_dirstop(filename);
1536 static int check_file(const char* filename)
1540 if (filename == NULL) {
1544 if (stat(filename, &st) != 0) {
1545 fprintf(stderr, "can't find '%s' to install\n", filename);
1549 if (!S_ISREG(st.st_mode)) {
1550 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
1557 int install_app(transport_type transport, char* serial, int argc, char** argv)
1559 static const char *const DATA_DEST = "/data/local/tmp/%s";
1560 static const char *const SD_DEST = "/sdcard/tmp/%s";
1561 const char* where = DATA_DEST;
1562 char apk_dest[PATH_MAX];
1563 char verification_dest[PATH_MAX];
1565 char* verification_file = NULL;
1571 for (i = 1; i < argc; i++) {
1572 if (*argv[i] != '-') {
1575 } else if (!strcmp(argv[i], "-i")) {
1576 // Skip the installer package name.
1578 } else if (!strcmp(argv[i], "-s")) {
1580 } else if (!strcmp(argv[i], "--algo")) {
1583 } else if (!strcmp(argv[i], "--iv")) {
1586 } else if (!strcmp(argv[i], "--key")) {
1593 fprintf(stderr, "can't find filename in arguments\n");
1595 } else if (file_arg + 2 < argc) {
1596 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
1600 apk_file = argv[file_arg];
1602 if (file_arg != argc - 1) {
1603 verification_file = argv[file_arg + 1];
1606 if (check_file(apk_file) || check_file(verification_file)) {
1610 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1611 if (verification_file != NULL) {
1612 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1614 if (!strcmp(apk_dest, verification_dest)) {
1615 fprintf(stderr, "APK and verification file can't have the same name\n");
1620 err = do_sync_push(apk_file, apk_dest, verify_apk, 0);
1624 argv[file_arg] = apk_dest; /* destination name, not source location */
1627 if (verification_file != NULL) {
1628 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */, 0);
1632 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1636 pm_command(transport, serial, argc, argv);
1639 if (verification_file != NULL) {
1640 delete_file(transport, serial, verification_dest);
1643 delete_file(transport, serial, apk_dest);