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"
39 #include <tzplatform_config.h>
41 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
43 void get_my_path(char *s, size_t maxLen);
44 int find_sync_dirs(const char *srcarg,
45 char **android_srcdir_out, char **data_srcdir_out);
46 int install_app(transport_type transport, char* serial, int argc, char** argv);
47 int uninstall_app_sdb(const char *app_id);
48 int install_app_sdb(const char *srcpath);
49 int launch_app(transport_type transport, char* serial, int argc, char** argv);
50 int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
51 int sdb_command2(const char* cmd);
52 void version_sdbd(transport_type ttype, char* serial);
54 static const char *gProductOutPath = NULL;
56 static char *product_file(const char *extra)
61 if (gProductOutPath == NULL) {
62 fprintf(stderr, "sdb: Product directory not specified; "
63 "use -p or define ANDROID_PRODUCT_OUT\n");
67 n = strlen(gProductOutPath) + strlen(extra) + 2;
70 fprintf(stderr, "sdb: Out of memory (product_file())\n");
74 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
78 void version(FILE * out) {
79 fprintf(out, "Smart Development Bridge version %d.%d.%d\n",
80 SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_SERVER_VERSION);
89 " Usage : sdb [option] <command> [parameters]\n"
92 " -d - direct command to the only connected USB device\n"
93 " return an error if more than one USB device is present.\n"
94 " -e - direct command to the only running emulator.\n"
95 " return an error if more than one emulator is running.\n"
96 " -s <serial number> - direct command to the USB device or emulator with\n"
97 " the given serial number.\n"
98 " devices - list all connected devices\n"
99 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
100 " Port 26101 is used by default if no port number is specified.\n"
101 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
102 " Port 26101 is used by default if no port number is specified.\n"
103 " Using this command with no additional arguments\n"
104 " will disconnect from all connected TCP/IP devices.\n"
107 " sdb push <local> <remote> [--with-utf8]\n"
108 " - copy file/dir to device\n"
109 " (--with-utf8 means to create the remote file with utf-8 character encoding)\n"
110 " sdb pull <remote> [<local>] - copy file/dir from device\n"
111 " sdb shell - run remote shell interactively\n"
112 " sdb shell <command> - run remote shell \n"
113 " sdb dlog [<filter-spec>] - view device log\n"
114 " sdb install <path-to-tpk> - push tpk package file and install it\n"
115 " sdb uninstall <appid> - uninstall this app from the device\n"
116 " sdb forward <local> <remote> - forward socket connections\n"
118 " forward spec is : \n"
120 " sdb help - show this help message\n"
121 " sdb version - show version num\n"
123 " sdb start-server - ensure that there is a server running\n"
124 " sdb kill-server - kill the server if it is running\n"
125 " sdb get-state - print: offline | bootloader | device\n"
126 " sdb get-serialno - print: <serial-number>\n"
127 " sdb status-window - continuously print device status for a specified device\n"
128 // " sdb usb - restarts the sdbd daemon listing on USB\n"
129 // " sdb tcpip - restarts the sdbd daemon listing on TCP\n"
130 " sdb root <on|off> - switch to root or developer account mode\n"
131 " 'on' means to root mode, and vice versa"
143 static struct termios tio_save;
145 static void stdin_raw_init(int fd)
149 if(tcgetattr(fd, &tio)) return;
150 if(tcgetattr(fd, &tio_save)) return;
152 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
154 /* no timeout but request at least one character per read */
158 tcsetattr(fd, TCSANOW, &tio);
159 tcflush(fd, TCIFLUSH);
162 static void stdin_raw_restore(int fd)
164 tcsetattr(fd, TCSANOW, &tio_save);
165 tcflush(fd, TCIFLUSH);
169 static void read_and_dump(int fd)
175 D("read_and_dump(): pre sdb_read(fd=%d)\n", fd);
176 len = sdb_read(fd, buf, 4096);
177 D("read_and_dump(): post sdb_read(fd=%d): len=%d\n", fd, len);
183 if(errno == EINTR) continue;
186 fwrite(buf, 1, len, stdout);
191 static void copy_to_file(int inFd, int outFd) {
192 const size_t BUFSIZE = 32 * 1024;
193 char* buf = (char*) malloc(BUFSIZE);
197 D("copy_to_file(%d -> %d)\n", inFd, outFd);
199 len = sdb_read(inFd, buf, BUFSIZE);
201 D("copy_to_file() : read 0 bytes; exiting\n");
205 if (errno == EINTR) {
206 D("copy_to_file() : EINTR, retrying\n");
209 D("copy_to_file() : error %d\n", errno);
212 sdb_write(outFd, buf, len);
215 D("copy_to_file() finished after %lu bytes\n", total);
219 static void *stdin_read_thread(void *x)
222 unsigned char buf[1024];
232 /* fdi is really the client's stdin, so use read, not sdb_read here */
233 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
234 r = unix_read(fdi, buf, 1024);
235 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
238 if(errno == EINTR) continue;
241 for(n = 0; n < r; n++){
250 if(state == 1) state++;
254 fprintf(stderr,"\n* disconnect *\n");
256 stdin_raw_restore(fdi);
264 r = sdb_write(fd, buf, r);
272 int interactive_shell(void)
278 fd = sdb_connect("shell:");
280 fprintf(stderr,"error: %s\n", sdb_error());
285 fds = malloc(sizeof(int) * 2);
292 sdb_thread_create(&thr, stdin_read_thread, fds);
295 stdin_raw_restore(fdi);
301 static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
304 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
306 const char* prefix = "host";
307 if (ttype == kTransportUsb)
309 else if (ttype == kTransportLocal)
310 prefix = "host-local";
312 snprintf(buffer, buflen, "%s:%s", prefix, command);
315 #if 0 /* tizen specific */
316 int sdb_download_buffer(const char *service, const void* data, int sz,
322 const unsigned char *ptr;
324 sprintf(buf,"%s:%d", service, sz);
325 fd = sdb_connect(buf);
327 fprintf(stderr,"error: %s\n", sdb_error());
331 int opt = CHUNK_SIZE;
332 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
338 char *x = strrchr(service, ':');
339 if(x) service = x + 1;
343 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
344 if(writex(fd, ptr, xfer)) {
346 fprintf(stderr,"* failed to write data '%s' *\n", sdb_error());
352 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
360 if(readx(fd, buf, 4)){
361 fprintf(stderr,"* error reading response *\n");
365 if(memcmp(buf, "OKAY", 4)) {
367 fprintf(stderr,"* error response '%s' *\n", buf);
376 int sdb_download(const char *service, const char *fn, unsigned progress)
381 data = load_file(fn, &sz);
383 fprintf(stderr,"* cannot read '%s' *\n", service);
387 int status = sdb_download_buffer(service, data, sz, progress);
392 static void status_window(transport_type ttype, const char* serial)
403 fd = unix_open("/dev/null", O_WRONLY);
408 format_host_command(command, sizeof command, "get-state", ttype, serial);
418 state = sdb_query(command);
421 if(laststate && !strcmp(state,laststate)){
424 if(laststate) free(laststate);
425 laststate = strdup(state);
429 printf("%c[2J%c[2H", 27, 27);
430 printf("Samsung Development Bridge\n");
431 printf("State: %s\n", state ? state : "offline");
436 /** duplicate string and quote all \ " ( ) chars + space character. */
438 dupAndQuote(const char *s)
449 for( ;*ts != '\0'; ts++) {
451 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
456 ret = (char *)malloc(alloc_len + 1);
461 for ( ;*ts != '\0'; ts++) {
462 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
475 * Run ppp in "notty" mode against a resource listed as the first parameter
478 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
481 int ppp(int argc, char **argv)
483 #ifdef HAVE_WIN32_PROC
484 fprintf(stderr, "error: sdb %s not implemented on Win32\n", argv[0]);
487 char *sdb_service_name;
492 fprintf(stderr, "usage: sdb %s <sdb service name> [ppp opts]\n",
498 sdb_service_name = argv[1];
500 fd = sdb_connect(sdb_service_name);
503 fprintf(stderr,"Error: Could not open sdb service: %s. Error: %s\n",
504 sdb_service_name, sdb_error());
511 perror("from fork()");
513 } else if (pid == 0) {
516 const char **ppp_args;
519 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
520 ppp_args[0] = "pppd";
521 for (i = 2 ; i < argc ; i++) {
522 //argv[2] and beyond become ppp_args[1] and beyond
523 ppp_args[i - 1] = argv[i];
525 ppp_args[i-1] = NULL;
529 dup2(fd, STDIN_FILENO);
530 dup2(fd, STDOUT_FILENO);
531 sdb_close(STDERR_FILENO);
534 err = execvp("pppd", (char * const *)ppp_args);
537 perror("execing pppd");
546 #endif /* !HAVE_WIN32_PROC */
549 static int send_shellcommand(transport_type transport, char* serial, char* buf)
554 fd = sdb_connect(buf);
557 fprintf(stderr,"- waiting for device -\n");
559 do_cmd(transport, serial, "wait-for-device", 0);
570 static int logcat(transport_type transport, char* serial, int argc, char **argv)
574 snprintf(buf, sizeof(buf),
575 "shell:/usr/bin/dlogutil");
578 if (!strcmp(argv[0],"longcat")) {
579 strncat(buf, " -v long", sizeof(buf)-1);
588 quoted = dupAndQuote (*argv++);
590 strncat(buf, " ", sizeof(buf)-1);
591 strncat(buf, quoted, sizeof(buf)-1);
595 send_shellcommand(transport, serial, buf);
599 static int mkdirs(char *path)
608 ret = sdb_mkdir(path, 0775);
609 *x = OS_PATH_SEPARATOR;
610 if((ret < 0) && (errno != EEXIST)) {
618 static int backup(int argc, char** argv) {
620 char default_name[32];
621 const char* filename = strcpy(default_name, "./backup.ab");
625 /* find, extract, and use any -f argument */
626 for (i = 1; i < argc; i++) {
627 if (!strcmp("-f", argv[i])) {
629 fprintf(stderr, "sdb: -f passed with no filename\n");
632 filename = argv[i+1];
633 for (j = i+2; j <= argc; ) {
634 argv[i++] = argv[j++];
641 /* bare "sdb backup" or "sdb backup -f filename" are not valid invocations */
642 if (argc < 2) return usage();
644 sdb_unlink(filename);
645 mkdirs((char *)filename);
646 outFd = sdb_creat(filename, 0640);
648 fprintf(stderr, "sdb: unable to open file %s\n", filename);
652 snprintf(buf, sizeof(buf), "backup");
653 for (argc--, argv++; argc; argc--, argv++) {
654 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
655 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
658 D("backup. filename=%s buf=%s\n", filename, buf);
659 fd = sdb_connect(buf);
661 fprintf(stderr, "sdb: unable to connect for backup\n");
666 printf("Now unlock your device and confirm the backup operation.\n");
667 copy_to_file(fd, outFd);
674 static int restore(int argc, char** argv) {
675 const char* filename;
678 if (argc != 2) return usage();
681 tarFd = sdb_open(filename, O_RDONLY);
683 fprintf(stderr, "sdb: unable to open file %s\n", filename);
687 fd = sdb_connect("restore:");
689 fprintf(stderr, "sdb: unable to connect for backup\n");
694 printf("Now unlock your device and confirm the restore operation.\n");
695 copy_to_file(tarFd, fd);
702 #define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
703 static int top_works(const char *top)
705 if (top != NULL && sdb_is_absolute_host_path(top)) {
706 char path_buf[PATH_MAX];
707 snprintf(path_buf, sizeof(path_buf),
708 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
709 return access(path_buf, F_OK) == 0;
714 static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
716 strcpy(path_buf, indir);
718 if (top_works(path_buf)) {
721 char *s = sdb_dirstop(path_buf);
731 static char *find_top(char path_buf[PATH_MAX])
733 char *top = getenv("ANDROID_BUILD_TOP");
734 if (top != NULL && top[0] != '\0') {
735 if (!top_works(top)) {
736 fprintf(stderr, "sdb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
741 if (top != NULL && top[0] != '\0') {
742 if (!top_works(top)) {
743 fprintf(stderr, "sdb: bad TOP value \"%s\"\n", top);
752 /* The environment pointed to a top directory that works.
754 strcpy(path_buf, top);
758 /* The environment didn't help. Walk up the tree from the CWD
759 * to see if we can find the top.
762 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
764 /* If the CWD isn't under a good-looking top, see if the
767 get_my_path(dir, PATH_MAX);
768 top = find_top_from(dir, path_buf);
774 * - A simple product name
776 TODO: debug? sooner-debug, sooner:debug?
777 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
778 * e.g., "out/target/product/sooner"
779 * - An absolute path to the PRODUCT_OUT dir
780 * e.g., "/src/device/out/target/product/sooner"
782 * Given <hint>, try to construct an absolute path to the
783 * ANDROID_PRODUCT_OUT dir.
785 static const char *find_product_out_path(const char *hint)
787 static char path_buf[PATH_MAX];
789 if (hint == NULL || hint[0] == '\0') {
793 /* If it's already absolute, don't bother doing any work.
795 if (sdb_is_absolute_host_path(hint)) {
796 strcpy(path_buf, hint);
800 /* If there are any slashes in it, assume it's a relative path;
803 if (sdb_dirstart(hint) != NULL) {
804 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
805 fprintf(stderr, "sdb: Couldn't get CWD: errno:%d\n", errno);
808 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
809 fprintf(stderr, "sdb: Couldn't assemble path\n");
812 strcat(path_buf, OS_PATH_SEPARATOR_STR);
813 strcat(path_buf, hint);
817 /* It's a string without any slashes. Try to do something with it.
819 * Try to find the root of the build tree, and build a PRODUCT_OUT
822 char top_buf[PATH_MAX];
823 const char *top = find_top(top_buf);
825 fprintf(stderr, "sdb: Couldn't find top of build tree\n");
828 //TODO: if we have a way to indicate debug, look in out/debug/target/...
829 snprintf(path_buf, sizeof(path_buf),
830 "%s" OS_PATH_SEPARATOR_STR
831 "out" OS_PATH_SEPARATOR_STR
832 "target" OS_PATH_SEPARATOR_STR
833 "product" OS_PATH_SEPARATOR_STR
834 "%s", top_buf, hint);
835 if (access(path_buf, F_OK) < 0) {
836 fprintf(stderr, "sdb: Couldn't find a product dir "
837 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
843 int sdb_commandline(int argc, char **argv)
852 transport_type ttype = kTransportAny;
854 char* server_port_str = NULL;
856 /* If defined, this should be an absolute path to
857 * the directory containing all of the various system images
858 * for a particular product. If not defined, and the sdb
859 * command requires this information, then the user must
860 * specify the path using "-p".
862 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
863 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
864 gProductOutPath = NULL;
866 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
868 serial = getenv("ANDROID_SERIAL");
870 /* Validate and assign the server port */
871 server_port_str = getenv("ANDROID_SDB_SERVER_PORT");
872 int server_port = DEFAULT_SDB_PORT;
873 if (server_port_str && strlen(server_port_str) > 0) {
874 server_port = (int) strtol(server_port_str, NULL, 0);
875 if (server_port <= 0) {
877 "sdb: Env var ANDROID_SDB_SERVER_PORT must be a positive number. Got \"%s\"\n",
883 /* modifiers and flags */
885 if(!strcmp(argv[0],"server")) {
887 } else if(!strcmp(argv[0],"nodaemon")) {
889 } else if (!strcmp(argv[0], "fork-server")) {
890 /* this is a special flag used only when the SDB client launches the SDB Server */
892 } else if(!strcmp(argv[0],"persist")) {
894 } else if(!strncmp(argv[0], "-p", 2)) {
895 const char *product = NULL;
896 if (argv[0][2] == '\0') {
897 if (argc < 2) return usage();
902 product = argv[1] + 2;
904 gProductOutPath = find_product_out_path(product);
905 if (gProductOutPath == NULL) {
906 fprintf(stderr, "sdb: could not resolve \"-p %s\"\n",
910 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
911 if (isdigit(argv[0][2])) {
912 serial = argv[0] + 2;
914 if(argc < 2 || argv[0][2] != '\0') return usage();
919 } else if (!strcmp(argv[0],"-d")) {
920 ttype = kTransportUsb;
921 } else if (!strcmp(argv[0],"-e")) {
922 ttype = kTransportLocal;
924 /* out of recognized modifiers and flags */
932 // sdb_set_transport(ttype, serial);
933 // sdb_set_tcp_specifics(server_port);
936 if (no_daemon || is_daemon) {
937 r = sdb_main(is_daemon, server_port);
939 r = launch_server(server_port);
942 fprintf(stderr,"* could not start server *\n");
952 // first, get the uniq device from the partial serial with prefix matching
955 snprintf(buf, sizeof(buf), "host:serial-match:%s", serial);
956 tmp = sdb_query(buf);
958 //printf("connect to device: %s\n", tmp);
959 serial = strdup(tmp);
960 sdb_set_transport(ttype, serial);
961 sdb_set_tcp_specifics(server_port);
966 sdb_set_transport(ttype, serial);
967 sdb_set_tcp_specifics(server_port);
969 /* sdb_connect() commands */
971 if(!strcmp(argv[0], "devices")) {
973 snprintf(buf, sizeof buf, "host:%s", argv[0]);
974 tmp = sdb_query(buf);
976 printf("List of devices attached \n");
984 if(!strcmp(argv[0], "connect")) {
987 fprintf(stderr, "Usage: sdb connect <host>[:<port>]\n");
990 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
991 tmp = sdb_query(buf);
1000 if(!strcmp(argv[0], "disconnect")) {
1003 fprintf(stderr, "Usage: sdb disconnect [<host>[:<port>]]\n");
1007 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1009 snprintf(buf, sizeof buf, "host:disconnect:");
1011 tmp = sdb_query(buf);
1013 printf("%s\n", tmp);
1020 if (!strcmp(argv[0], "emu")) {
1021 return sdb_send_emulator_command(argc, argv);
1024 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
1028 char h = (argv[0][0] == 'h');
1031 printf("\x1b[41;33m");
1036 D("starting interactive shell\n");
1037 r = interactive_shell();
1045 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1051 /* quote empty strings and strings with spaces */
1052 quote = (**argv == 0 || strchr(*argv, ' '));
1055 strcat(buf, *argv++);
1061 D("interactive shell loop. buff=%s\n", buf);
1062 fd = sdb_connect(buf);
1064 D("about to read_and_dump(fd=%d)\n", fd);
1066 D("read_and_dump() done.\n");
1070 fprintf(stderr,"error: %s\n", sdb_error());
1075 fprintf(stderr,"\n- waiting for device -\n");
1077 do_cmd(ttype, serial, "wait-for-device", 0);
1083 D("interactive shell loop. return r=%d\n", r);
1089 if(!strcmp(argv[0], "kill-server")) {
1091 fd = _sdb_connect("host:kill");
1093 fprintf(stderr,"* server not running *\n");
1098 #if 0 /* tizen specific */
1099 if(!strcmp(argv[0], "sideload")) {
1100 if(argc != 2) return usage();
1101 if(sdb_download("sideload", argv[1], 1)) {
1108 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
1109 || !strcmp(argv[0], "reboot-bootloader")
1110 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
1111 || !strcmp(argv[0], "root")) {
1113 if (!strcmp(argv[0], "reboot-bootloader"))
1114 snprintf(command, sizeof(command), "reboot:bootloader");
1116 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
1118 snprintf(command, sizeof(command), "%s:", argv[0]);
1119 int fd = sdb_connect(command);
1125 fprintf(stderr,"error: %s\n", sdb_error());
1129 if(!strcmp(argv[0], "bugreport")) {
1130 if (argc != 1) return usage();
1131 do_cmd(ttype, serial, "shell", "bugreport", 0);
1135 /* sdb_command() wrapper commands */
1137 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1138 char* service = argv[0];
1139 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1140 if (ttype == kTransportUsb) {
1141 service = "wait-for-usb";
1142 } else if (ttype == kTransportLocal) {
1143 service = "wait-for-local";
1145 service = "wait-for-any";
1149 format_host_command(buf, sizeof buf, service, ttype, serial);
1151 if (sdb_command(buf)) {
1152 D("failure: %s *\n",sdb_error());
1153 fprintf(stderr,"error: %s\n", sdb_error());
1157 /* Allow a command to be run after wait-for-device,
1158 * e.g. 'sdb wait-for-device shell'.
1168 if(!strcmp(argv[0], "forward")) {
1169 if(argc != 3) return usage();
1171 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1172 } else if (ttype == kTransportUsb) {
1173 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1174 } else if (ttype == kTransportLocal) {
1175 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
1177 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
1179 if(sdb_command(buf)) {
1180 fprintf(stderr,"error: %s\n", sdb_error());
1186 /* do_sync_*() commands */
1188 if(!strcmp(argv[0], "ls")) {
1189 if(argc != 2) return usage();
1190 return do_sync_ls(argv[1]);
1193 if(!strcmp(argv[0], "push")) {
1197 if(argc < 3) return usage();
1198 if (argv[argc-1][0] == '-') {
1199 if (!strcmp(argv[argc-1], "--with-utf8")) {
1206 for (i=1; i<argc-1; i++) {
1207 do_sync_push(argv[i], argv[argc-1], 0 /* no verify APK */, utf8);
1212 if(!strcmp(argv[0], "install")) {
1213 if(argc != 2) return usage();
1215 return install_app_sdb(argv[1]);
1218 if(!strcmp(argv[0], "uninstall")) {
1219 if(argc != 2) return usage();
1221 return uninstall_app_sdb(argv[1]);
1224 if(!strcmp(argv[0], "pull")) {
1226 return do_sync_pull(argv[1], ".");
1227 } else if (argc == 3) {
1228 return do_sync_pull(argv[1], argv[2]);
1234 if(!strcmp(argv[0], "install")) {
1235 if (argc < 2) return usage();
1236 return install_app(ttype, serial, argc, argv);
1239 if(!strcmp(argv[0], "uninstall")) {
1240 if (argc < 2) return usage();
1241 return uninstall_app(ttype, serial, argc, argv);
1244 if(!strcmp(argv[0], "launch")) {
1245 //if (argc < 2) return usage();
1246 return launch_app(ttype, serial, argc, argv);
1249 if(!strcmp(argv[0], "sync")) {
1250 char *srcarg, *android_srcpath, *data_srcpath;
1255 /* No local path was specified. */
1257 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1264 } else if(argc == 2) {
1265 /* A local path or "android"/"data" arg was specified. */
1270 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1271 if(ret != 0) return usage();
1273 if(android_srcpath != NULL)
1274 ret = do_sync_sync(android_srcpath, "/system", listonly);
1275 if(ret == 0 && data_srcpath != NULL)
1276 ret = do_sync_sync(data_srcpath, "/data", listonly);
1278 free(android_srcpath);
1283 /* passthrough commands */
1285 if(!strcmp(argv[0],"get-state") ||
1286 !strcmp(argv[0],"get-serialno"))
1290 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1291 tmp = sdb_query(buf);
1293 printf("%s\n", tmp);
1300 /* other commands */
1302 if(!strcmp(argv[0],"status-window")) {
1303 status_window(ttype, serial);
1307 if(!strcmp(argv[0],"dlog")) {
1308 return logcat(ttype, serial, argc, argv);
1311 if(!strcmp(argv[0],"ppp")) {
1312 return ppp(argc, argv);
1315 if (!strcmp(argv[0], "start-server")) {
1316 return sdb_connect("host:start-server");
1319 if (!strcmp(argv[0], "backup")) {
1320 return backup(argc, argv);
1323 if (!strcmp(argv[0], "restore")) {
1324 return restore(argc, argv);
1327 if (!strcmp(argv[0], "jdwp")) {
1328 int fd = sdb_connect("jdwp");
1334 fprintf(stderr, "error: %s\n", sdb_error());
1339 /* "sdb /?" is a common idiom under Windows */
1340 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1345 if(!strcmp(argv[0], "version")) {
1346 if (ttype == kTransportUsb || ttype == kTransportLocal) {
1347 version_sdbd(ttype, serial);
1358 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1368 argv[argc++] = "-s";
1369 argv[argc++] = serial;
1370 } else if (ttype == kTransportUsb) {
1371 argv[argc++] = "-d";
1372 } else if (ttype == kTransportLocal) {
1373 argv[argc++] = "-e";
1377 while((argv[argc] = va_arg(ap, char*)) != 0) {
1384 fprintf(stderr,"argc = %d\n",argc);
1385 for(n = 0; n < argc; n++) {
1386 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1390 return sdb_commandline(argc, argv);
1393 int find_sync_dirs(const char *srcarg,
1394 char **android_srcdir_out, char **data_srcdir_out)
1396 char *android_srcdir, *data_srcdir;
1398 if(srcarg == NULL) {
1399 android_srcdir = product_file("system");
1400 data_srcdir = product_file("data");
1402 /* srcarg may be "data", "system" or NULL.
1403 * if srcarg is NULL, then both data and system are synced
1405 if(strcmp(srcarg, "system") == 0) {
1406 android_srcdir = product_file("system");
1408 } else if(strcmp(srcarg, "data") == 0) {
1409 android_srcdir = NULL;
1410 data_srcdir = product_file("data");
1412 /* It's not "system" or "data".
1418 if(android_srcdir_out != NULL)
1419 *android_srcdir_out = android_srcdir;
1421 free(android_srcdir);
1423 if(data_srcdir_out != NULL)
1424 *data_srcdir_out = data_srcdir;
1431 static int pm_command(transport_type transport, char* serial,
1432 int argc, char** argv)
1436 snprintf(buf, sizeof(buf), "shell:pm");
1441 quoted = dupAndQuote(*argv++);
1443 strncat(buf, " ", sizeof(buf)-1);
1444 strncat(buf, quoted, sizeof(buf)-1);
1448 send_shellcommand(transport, serial, buf);
1452 int sdb_command2(const char* cmd) {
1453 int result = sdb_connect(cmd);
1459 D("about to read_and_dump(fd=%d)\n", result);
1460 read_and_dump(result);
1461 D("read_and_dump() done.\n");
1467 int install_app_sdb(const char *srcpath) {
1468 D("Install start\n");
1469 const char * APP_DEST = tzplatform_mkpath(TZ_SYS_RW_APP,"PKGS/%s");
1470 const char* filename = sdb_dirstop(srcpath);
1471 char destination[PATH_MAX];
1475 snprintf(destination, sizeof destination, APP_DEST, filename);
1477 snprintf(destination, sizeof destination, APP_DEST, srcpath);
1480 D("Push file: %s to %s\n", srcpath, destination);
1481 int result = do_sync_push(srcpath, destination, 0, 0);
1484 fprintf(stderr, "error: %s\n", sdb_error());
1488 const char* SHELL_INSTALL_CMD ="shell:pkgcmd -i -t tpk -p %s -q";
1489 char full_cmd[PATH_MAX];
1490 snprintf(full_cmd, sizeof full_cmd, SHELL_INSTALL_CMD, destination);
1491 D("Install command: %s\n", full_cmd);
1492 result = sdb_command2(full_cmd);
1495 fprintf(stderr, "error: %s\n", sdb_error());
1499 const char* SHELL_REMOVE_CMD = "shell:rm %s";
1500 snprintf(full_cmd, sizeof full_cmd, SHELL_REMOVE_CMD, destination);
1501 D("Remove file command: %s\n", full_cmd);
1502 result = sdb_command2(full_cmd);
1505 fprintf(stderr, "error: %s\n", sdb_error());
1512 int uninstall_app_sdb(const char *appid) {
1513 const char* SHELL_UNINSTALL_CMD ="shell:pkgcmd -u -t tpk -n %s -q";
1514 char full_cmd[PATH_MAX];
1516 snprintf(full_cmd, sizeof full_cmd, SHELL_UNINSTALL_CMD, appid);
1517 result = sdb_command2(full_cmd);
1520 fprintf(stderr, "error: %s\n", sdb_error());
1527 int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1529 /* if the user choose the -k option, we refuse to do it until devices are
1530 out with the option to uninstall the remaining data somehow (sdb/ui) */
1531 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1534 "The -k option uninstalls the application while retaining the data/cache.\n"
1535 "At the moment, there is no way to remove the remaining data.\n"
1536 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1537 "If you truly wish to continue, execute 'sdb shell pm uninstall -k %s'\n", argv[2]);
1541 /* 'sdb uninstall' takes the same arguments as 'pm uninstall' on device */
1542 return pm_command(transport, serial, argc, argv);
1545 static int delete_file(transport_type transport, char* serial, char* filename)
1550 snprintf(buf, sizeof(buf), "shell:rm ");
1551 quoted = dupAndQuote(filename);
1552 strncat(buf, quoted, sizeof(buf)-1);
1555 send_shellcommand(transport, serial, buf);
1559 const char* get_basename(const char* filename)
1561 const char* basename = sdb_dirstop(filename);
1570 static int check_file(const char* filename)
1574 if (filename == NULL) {
1578 if (stat(filename, &st) != 0) {
1579 fprintf(stderr, "can't find '%s' to install\n", filename);
1583 if (!S_ISREG(st.st_mode)) {
1584 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
1591 int install_app(transport_type transport, char* serial, int argc, char** argv)
1593 static const char *const DATA_DEST = "/data/local/tmp/%s";
1594 static const char *const SD_DEST = "/sdcard/tmp/%s";
1595 const char* where = DATA_DEST;
1596 char apk_dest[PATH_MAX];
1597 char verification_dest[PATH_MAX];
1599 char* verification_file = NULL;
1605 for (i = 1; i < argc; i++) {
1606 if (*argv[i] != '-') {
1609 } else if (!strcmp(argv[i], "-i")) {
1610 // Skip the installer package name.
1612 } else if (!strcmp(argv[i], "-s")) {
1614 } else if (!strcmp(argv[i], "--algo")) {
1617 } else if (!strcmp(argv[i], "--iv")) {
1620 } else if (!strcmp(argv[i], "--key")) {
1627 fprintf(stderr, "can't find filename in arguments\n");
1629 } else if (file_arg + 2 < argc) {
1630 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
1634 apk_file = argv[file_arg];
1636 if (file_arg != argc - 1) {
1637 verification_file = argv[file_arg + 1];
1640 if (check_file(apk_file) || check_file(verification_file)) {
1644 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1645 if (verification_file != NULL) {
1646 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1648 if (!strcmp(apk_dest, verification_dest)) {
1649 fprintf(stderr, "APK and verification file can't have the same name\n");
1654 err = do_sync_push(apk_file, apk_dest, verify_apk, 0);
1658 argv[file_arg] = apk_dest; /* destination name, not source location */
1661 if (verification_file != NULL) {
1662 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */, 0);
1666 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1670 pm_command(transport, serial, argc, argv);
1673 if (verification_file != NULL) {
1674 delete_file(transport, serial, verification_dest);
1677 delete_file(transport, serial, apk_dest);
1682 int launch_app(transport_type transport, char* serial, int argc, char** argv)
1684 static const char *const SHELL_LAUNCH_CMD = "shell:/usr/bin/sdk_launch_app ";
1685 char full_cmd[PATH_MAX];
1689 snprintf(full_cmd, sizeof full_cmd, "%s", SHELL_LAUNCH_CMD);
1691 //TODO: check argument validation
1693 for (i=1 ; i<argc ; i++) {
1694 strncat(full_cmd, " ", sizeof(full_cmd)-strlen(" ")-1);
1695 strncat(full_cmd, argv[i], sizeof(full_cmd)-strlen(argv[i])-1);
1698 D("launch command: %s\n", full_cmd);
1699 result = sdb_command2(full_cmd);
1702 fprintf(stderr, "error: %s\n", sdb_error());
1707 fprintf(stderr, "error: %s\n", sdb_error());
1716 void version_sdbd(transport_type ttype, char* serial) {
1717 char* VERSION_QUERY ="shell:rpm -qa | grep sdbd";
1718 send_shellcommand(ttype, serial, VERSION_QUERY);