From e6f8c1ddc5d7d940e89f69860f3015304e60b769 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Fri, 10 Jun 2016 14:58:36 +0900 Subject: [PATCH 01/16] Returns error code when it fails to get the value of tzplatform envrionment variable. - return 0 when succeeded - return 1 when error is occured while getting the value of tzplatform environment variable. - return 2 when tzplatform environment variable is not valid. Change-Id: Ie4530148c43d757f69a3e8457777cbf25cb4dc3d Signed-off-by: shingil.kang --- src/services.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/services.c b/src/services.c index 94558c6..a1c0008 100644 --- a/src/services.c +++ b/src/services.c @@ -219,6 +219,12 @@ void rootshell_service(int fd, void *cookie) sdb_close(fd); } +enum tzplatform_get_env_error_status { + NO_ERROR_TZPLATFORM_ENV = 0, + ERROR_TZPLATFORM_ENV_GENERAL = 1, + ERROR_TZPLATFORM_ENV_INVALID_VARIABLES = 2, +}; + void get_tzplatform_env(int fd, void *cookie) { char buf[PATH_MAX] = { 0, }; char *env_name = (char*) cookie; @@ -228,10 +234,16 @@ void get_tzplatform_env(int fd, void *cookie) { char *env_value = tzplatform_getenv(env_id); if (env_value) { D("environment value : %s\n", env_value); - snprintf(buf, sizeof(buf), env_value); - writex(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "%d%s", NO_ERROR_TZPLATFORM_ENV, env_value); + } else { + D("failed to get environment value using tzplatform_getenv"); + snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_GENERAL); } + } else { + D("environment name (%s) is invalid\n", env_name); + snprintf(buf, sizeof(buf), "%d", ERROR_TZPLATFORM_ENV_INVALID_VARIABLES); } + writex(fd, buf, strlen(buf)); free(env_name); sdb_close(fd); } -- 2.7.4 From 2622cb18c0871fd97c8235d308362fe4b97b05d4 Mon Sep 17 00:00:00 2001 From: Kim Gunsoo Date: Mon, 13 Jun 2016 18:04:58 +0900 Subject: [PATCH 02/16] Remove unnecessary smack label for running sdbd. - The label(User) of the running sdbd no longer needed. Change-Id: I6b4918d332e73d6db71a584c6a1d37906b8f6a8d Signed-off-by: Kim Gunsoo --- packaging/sdbd.spec | 2 +- packaging/sdbd_emulator.service | 1 - packaging/sdbd_tcp.service | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 7bde2d9..6a3da0b 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.11 +Version: 3.0.12 Release: 0 License: Apache-2.0 Summary: SDB daemon diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index 3db25cf..b477d5a 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -9,7 +9,6 @@ Type=forking Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes -SmackProcessLabel=User #ExecStartPre=/bin/bash -c "/bin/echo '10.0.2.15/32 system::debugging_network' >> /smack/netlabel" ExecStart=/bin/sh -c "/usr/sbin/sdbd `/usr/bin/awk '{match($0, /sdb_port=([0-9]+)/,port_match); match($0, /vm_name=([^, ]*)/,vm_match); print \"--emulator=\" vm_match[1] \":\" port_match[1] \" --connect-to=10.0.2.2:26099\" \" --sensors=10.0.2.2:\"port_match[1]+3 }' /proc/cmdline`" diff --git a/packaging/sdbd_tcp.service b/packaging/sdbd_tcp.service index 4ded27c..46b4266 100644 --- a/packaging/sdbd_tcp.service +++ b/packaging/sdbd_tcp.service @@ -7,5 +7,4 @@ Type=forking Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes -SmackProcessLabel=User ExecStart=/usr/sbin/sdbd --listen-port=26101 -- 2.7.4 From 41f7c54b77f54c04078ed9ac28fe247f56cc154b Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Tue, 14 Jun 2016 17:13:22 +0900 Subject: [PATCH 03/16] Added capabilities ralated to sdbd log - sdbd_log_enable : enable or disable sdbd log - sdbd_log_path : the folder location of sdbd log Change-Id: I52b91ba2242536474fe6b6f0e34dd48ddebc8a50 Signed-off-by: shingil.kang --- packaging/sdbd_device.service | 2 ++ packaging/sdbd_emulator.service | 2 ++ src/sdb.c | 70 +++++++++++++++++++++++++++++++++++------ src/sdb.h | 4 +++ src/sdbd_plugin.h | 3 ++ src/services.c | 8 +++++ 6 files changed, 79 insertions(+), 10 deletions(-) diff --git a/packaging/sdbd_device.service b/packaging/sdbd_device.service index 4fe803f..ac0ad44 100644 --- a/packaging/sdbd_device.service +++ b/packaging/sdbd_device.service @@ -5,6 +5,8 @@ After=tmp.mount [Service] Type=forking +#location of SDBD log file +#Environment=SDBD_LOG_PATH=/tmp EnvironmentFile=-/run/tizen-system-env PIDFile=/tmp/.sdbd.pid Restart=on-failure diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index b477d5a..5427780 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -6,6 +6,8 @@ After=tmp.mount dbus.service [Service] Type=forking +#location of SDBD log file +#Environment=SDBD_LOG_PATH=/tmp Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes diff --git a/src/sdb.c b/src/sdb.c index 4c3009f..0120c7b 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -170,6 +170,11 @@ void fatal_errno(const char *fmt, ...) exit(-1); } +static int is_enable_sdbd_log() +{ + return (!strncmp(g_capabilities.log_enable, SDBD_CAP_RET_ENABLED, strlen(SDBD_CAP_RET_ENABLED))); +} + int sdb_trace_mask; /* read a comma/space/colum/semi-column separated list of tags @@ -203,8 +208,12 @@ void sdb_trace_init(void) { NULL, 0 } }; - if (p == NULL) + if (p == NULL) { + if (is_enable_sdbd_log()) + p = "all"; + else return; + } /* use a comma/column/semi-colum/space separated list */ while (*p) { @@ -1018,14 +1027,18 @@ void start_logging(void) } #if !SDB_HOST + void start_device_log(void) { int fd; - char path[PATH_MAX]; + char path[PATH_MAX] = {0, }; + char path_folder[PATH_MAX] = {0, }; + char path_file[PATH_MAX] = {0, }; struct tm now; time_t t; // char value[PROPERTY_VALUE_MAX]; - const char* p = getenv("SDB_TRACE"); + const char* p_trace = getenv("SDB_TRACE"); + const char* p_path = getenv("SDBD_LOG_PATH"); // read the trace mask from persistent property persist.sdb.trace_mask // give up if the property is not set or cannot be parsed #if 0 /* tizen specific */ @@ -1034,16 +1047,28 @@ void start_device_log(void) return; #endif - if (p == NULL) { + if ((p_trace == NULL ) && !is_enable_sdbd_log()) { return; } + + if (p_path) + snprintf(path_folder, sizeof(path_folder), "%s", p_path); + else if (g_capabilities.log_path[0] != '\0') + snprintf(path_folder, sizeof(path_folder), "%s", g_capabilities.log_path); + else + return; + tzset(); time(&t); localtime_r(&t, &now); - strftime(path, sizeof(path), - "/tmp/sdbd-%Y-%m-%d-%H-%M-%S.txt", - &now); - fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640); + + strftime(path_file, sizeof(path_file), + "sdbd-%Y-%m-%d-%H-%M-%S.txt", + &now); + + snprintf(path, sizeof(path), "%s/%s", path_folder, path_file); + + fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { return; } @@ -1592,6 +1617,12 @@ static int get_plugin_capability(const char* in_buf, sdbd_plugin_param out) { } else if (SDBD_CMP_CAP(in_buf, PRODUCT_VER)) { snprintf(out.data, out.len, "%s", UNKNOWN); ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, LOG_ENABLE)) { + snprintf(out.data, out.len, "%s", SDBD_CAP_RET_DISABLED); + ret = SDBD_PLUGIN_RET_SUCCESS; + } else if (SDBD_CMP_CAP(in_buf, LOG_PATH)) { + snprintf(out.data, out.len, "%s", "/tmp"); + ret = SDBD_PLUGIN_RET_SUCCESS; } return ret; @@ -2107,6 +2138,24 @@ static void init_capabilities(void) { snprintf(g_capabilities.sdbd_plugin_version, sizeof(g_capabilities.sdbd_plugin_version), "%s", UNKNOWN); } + + // sdbd log enable + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_LOG_ENABLE, + g_capabilities.log_enable, + sizeof(g_capabilities.log_enable))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_LOG_ENABLE); + snprintf(g_capabilities.log_enable, sizeof(g_capabilities.log_enable), + "%s", DISABLED); + } + + // sdbd log path + if(!request_plugin_cmd(SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_LOG_PATH, + g_capabilities.log_path, + sizeof(g_capabilities.log_path))) { + D("failed to request. (%s:%s) \n", SDBD_CMD_PLUGIN_CAP, SDBD_CAP_TYPE_LOG_PATH); + snprintf(g_capabilities.log_path, sizeof(g_capabilities.log_path), + "%s", UNKNOWN); + } } static int is_support_usbproto() @@ -2149,6 +2198,9 @@ int sdb_main(int is_daemon, int server_port) load_sdbd_plugin(); init_capabilities(); + sdb_trace_init(); + start_device_log(); + init_drop_privileges(); init_sdk_requirements(); if (!request_plugin_verification(SDBD_CMD_VERIFY_LAUNCH, NULL)) { @@ -2615,7 +2667,6 @@ int recovery_mode = 0; int main(int argc, char **argv) { - sdb_trace_init(); /* tizen specific */ #if SDB_HOST sdb_sysdeps_init(); sdb_trace_init(); @@ -2654,7 +2705,6 @@ int main(int argc, char **argv) fatal("daemonize() failed: errno:%d", errno); #endif - start_device_log(); D("Handling main()\n"); //sdbd will never die on emulator! diff --git a/src/sdb.h b/src/sdb.h index 7e3d1f1..c9a9e0c 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -246,6 +246,7 @@ typedef struct platform_info { #define CAPBUF_SIZE 4096 #define CAPBUF_ITEMSIZE 32 #define CAPBUF_L_ITEMSIZE 256 +#define CAPBUF_LL_ITEMSIZE PATH_MAX typedef struct platform_capabilities { char secure_protocol[CAPBUF_ITEMSIZE]; // enabled or disabled @@ -258,6 +259,9 @@ typedef struct platform_capabilities char usbproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled char sockproto_support[CAPBUF_ITEMSIZE]; // enabled or disabled + char log_enable[CAPBUF_ITEMSIZE]; // enabled or disabled + char log_path[CAPBUF_LL_ITEMSIZE]; // path of sdbd log + char cpu_arch[CAPBUF_ITEMSIZE]; // cpu architecture (ex. x86) char profile_name[CAPBUF_ITEMSIZE]; // profile name (ex. mobile) char vendor_name[CAPBUF_ITEMSIZE]; // vendor name (ex. Tizen) diff --git a/src/sdbd_plugin.h b/src/sdbd_plugin.h index 81c590a..9bfc4b9 100644 --- a/src/sdbd_plugin.h +++ b/src/sdbd_plugin.h @@ -36,6 +36,9 @@ #define SDBD_CAP_TYPE_ROOTONOFF "root_onoff_support" #define SDBD_CAP_TYPE_PLUGIN_VER "sdbd_plugin_version" #define SDBD_CAP_TYPE_PRODUCT_VER "product_version" +#define SDBD_CAP_TYPE_LOG_ENABLE "sdbd_log_enable" +#define SDBD_CAP_TYPE_LOG_PATH "sdbd_log_path" + /* capability return string */ #define SDBD_CAP_RET_ENABLED "enabled" #define SDBD_CAP_RET_DISABLED "disabled" diff --git a/src/services.c b/src/services.c index a1c0008..33c5c76 100644 --- a/src/services.c +++ b/src/services.c @@ -951,6 +951,14 @@ static void get_capability(int fd, void *cookie) { offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "syncwinsz_support", g_capabilities.syncwinsz_support); + // Sdbd log enable + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "log_enable", g_capabilities.log_enable); + + // Sdbd log path + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "log_path", g_capabilities.log_path); + offset++; // for '\0' character -- 2.7.4 From bfd54375ee15471f2a6d12f7212f9d13e585c4f5 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Thu, 16 Jun 2016 11:57:30 +0900 Subject: [PATCH 04/16] Disabled OOM killing for SDBD process on TV profile Change-Id: I721285019b58a7f2d1004bac25c52606aa3d3738 Signed-off-by: shingil.kang --- packaging/sdbd.spec | 12 ++++++++++++ packaging/sdbd_device_tv.service | 17 +++++++++++++++++ packaging/sdbd_emulator_tv.service | 20 ++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 packaging/sdbd_device_tv.service create mode 100644 packaging/sdbd_emulator_tv.service diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 6a3da0b..e8539f8 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -12,6 +12,8 @@ Source1001: sdbd_device.service Source1002: sdbd_emulator.service Source1003: %{name}.manifest Source1004: sdbd_tcp.service +Source1005: sdbd_device_tv.service +Source1006: sdbd_emulator_tv.service BuildRequires: capi-system-info-devel >= 0.2.0 BuildRequires: cmake >= 2.8.3 @@ -57,12 +59,22 @@ cp LICENSE %{buildroot}/usr/share/license/%{name} %make_install mkdir -p %{buildroot}%{_libdir}/systemd/system mkdir -p %{buildroot}%{_unitdir} + %ifarch %{ix86} +%if "%{profile}" == "tv" +install -m 0644 %SOURCE1006 %{buildroot}%{_libdir}/systemd/system/sdbd.service +%else install -m 0644 %SOURCE1002 %{buildroot}%{_libdir}/systemd/system/sdbd.service +%endif mkdir -p %{buildroot}/%{_libdir}/systemd/system/emulator_preinit.target.wants ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/emulator_preinit.target.wants/ + +%else +%if "%{profile}" == "tv" +install -m 0644 %SOURCE1005 %{buildroot}%{_unitdir}/sdbd.service %else install -m 0644 %SOURCE1001 %{buildroot}%{_unitdir}/sdbd.service +%endif install -m 0644 %SOURCE1004 %{buildroot}%{_unitdir}/sdbd_tcp.service mkdir -p %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants/ diff --git a/packaging/sdbd_device_tv.service b/packaging/sdbd_device_tv.service new file mode 100644 index 0000000..fe3c965 --- /dev/null +++ b/packaging/sdbd_device_tv.service @@ -0,0 +1,17 @@ +[Unit] +Description=sdbd +Requires=tizen-system-env.service +After=tmp.mount + +[Service] +Type=forking +#location of SDBD log file +#Environment=SDBD_LOG_PATH=/tmp +EnvironmentFile=-/run/tizen-system-env +OOMScoreAdjust=-1000 +PIDFile=/tmp/.sdbd.pid +Restart=on-failure +ExecStart=/usr/sbin/sdbd + +[Install] +WantedBy=multi-user.target diff --git a/packaging/sdbd_emulator_tv.service b/packaging/sdbd_emulator_tv.service new file mode 100644 index 0000000..4d81fd2 --- /dev/null +++ b/packaging/sdbd_emulator_tv.service @@ -0,0 +1,20 @@ +[Unit] +Description=sdbd +Before=sensord.service +After=tmp.mount dbus.service +#DefaultDependencies=false + +[Service] +Type=forking +#location of SDBD log file +#Environment=SDBD_LOG_PATH=/tmp +Environment=DISPLAY=:0 +PIDFile=/tmp/.sdbd.pid +RemainAfterExit=yes +OOMScoreAdjust=-1000 +#ExecStartPre=/bin/bash -c "/bin/echo '10.0.2.15/32 system::debugging_network' >> /smack/netlabel" +ExecStart=/bin/sh -c "/usr/sbin/sdbd `/usr/bin/awk '{match($0, /sdb_port=([0-9]+)/,port_match); match($0, /vm_name=([^, ]*)/,vm_match); print \"--emulator=\" vm_match[1] \":\" port_match[1] \" --connect-to=10.0.2.2:26099\" \" --sensors=10.0.2.2:\"port_match[1]+3 }' /proc/cmdline`" + +[Install] +WantedBy=emulator_preinit.target + -- 2.7.4 From 72613e338788fda68a4a17566fb961bb18b8c3f6 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Tue, 21 Jun 2016 15:47:18 +0900 Subject: [PATCH 05/16] Fixed codes which may occur potential bugs. - check null pointer - fix double close Change-Id: I7baacb4d01d74a883ef969e43a14035ee89307a1 Signed-off-by: shingil.kang --- src/properties.c | 15 ++++++++------- src/services.c | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/properties.c b/src/properties.c index dc76a69..1127655 100644 --- a/src/properties.c +++ b/src/properties.c @@ -69,16 +69,17 @@ static void property_init(void) if(read_line(fd, buffer, PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX+1) < 0) break; tok = strtok_r(buffer, PROPERTY_SEPARATOR, &ptr); - for (i = 0; i < sdbd_config_element_cnt && sdbd_config[i].key ; i++) { - if (!strcmp(tok, sdbd_config[i].key)) { - tok = strtok_r(NULL, PROPERTY_SEPARATOR, &ptr); - if(tok) { - snprintf(sdbd_config[i].value, PROPERTY_VALUE_MAX, "%s", tok); - D("property init key=%s, value=%s\n", sdbd_config[i].key, tok); + if(tok) { + for (i = 0; i < sdbd_config_element_cnt && sdbd_config[i].key ; i++) { + if (!strcmp(tok, sdbd_config[i].key)) { + tok = strtok_r(NULL, PROPERTY_SEPARATOR, &ptr); + if(tok) { + snprintf(sdbd_config[i].value, PROPERTY_VALUE_MAX, "%s", tok); + D("property init key=%s, value=%s\n", sdbd_config[i].key, tok); + } } } } - } sdb_close(fd); D("called property_init\n"); diff --git a/src/services.c b/src/services.c index 33c5c76..e2b5928 100644 --- a/src/services.c +++ b/src/services.c @@ -782,7 +782,6 @@ static int create_sync_subprocess(void (*func)(int, void *), void* cookie) { if(sdb_thread_create( &t, service_bootstrap_func, sti)){ free(sti); sdb_close(s[0]); - sdb_close(s[1]); printf("cannot create service monitor thread\n"); return -1; } -- 2.7.4 From 6409dbabccda8ce8a003dff911051be8f905d99b Mon Sep 17 00:00:00 2001 From: Kim Gunsoo Date: Tue, 28 Jun 2016 14:54:54 +0900 Subject: [PATCH 06/16] Deletes the files that have not been used. - It erased the files of sdb server code and features that are not currently in use. Change-Id: I626ccee4da7d98d85646d56f798dc089ccce2dd6 Signed-off-by: Kim Gunsoo --- src/commandline.c | 1719 --------------------------------------- src/console.c | 61 -- src/file_sync_client.c | 1046 ------------------------ src/get_my_path_darwin.c | 30 - src/get_my_path_freebsd.c | 33 - src/get_my_path_linux.c | 33 - src/get_my_path_windows.c | 34 - src/jdwp_service.c | 749 ----------------- src/sdb.c | 3 - src/sdb_client.c | 343 -------- src/sdb_client.h | 70 -- src/sysdeps_win32.c | 1982 --------------------------------------------- src/transport_usb.c | 4 - src/usb_libusb.c | 654 --------------- src/usb_osx.c | 537 ------------ src/usb_vendors.c | 266 ------ src/usb_vendors.h | 25 - src/usb_windows.c | 515 ------------ test/test_inoti_service.c | 115 --- test/test_track_devices.c | 113 --- test/test_track_jdwp.c | 113 --- 21 files changed, 8445 deletions(-) delete mode 100644 src/commandline.c delete mode 100644 src/console.c delete mode 100644 src/file_sync_client.c delete mode 100644 src/get_my_path_darwin.c delete mode 100644 src/get_my_path_freebsd.c delete mode 100644 src/get_my_path_linux.c delete mode 100644 src/get_my_path_windows.c delete mode 100644 src/jdwp_service.c delete mode 100644 src/sdb_client.c delete mode 100644 src/sdb_client.h delete mode 100644 src/sysdeps_win32.c delete mode 100644 src/usb_libusb.c delete mode 100644 src/usb_osx.c delete mode 100644 src/usb_vendors.c delete mode 100644 src/usb_vendors.h delete mode 100644 src/usb_windows.c delete mode 100644 test/test_inoti_service.c delete mode 100644 test/test_track_devices.c delete mode 100644 test/test_track_jdwp.c diff --git a/src/commandline.c b/src/commandline.c deleted file mode 100644 index 1d88c7a..0000000 --- a/src/commandline.c +++ /dev/null @@ -1,1719 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sysdeps.h" - -#ifdef HAVE_TERMIO_H -#include -#endif - -#define TRACE_TAG TRACE_SDB -#include "sdb.h" -#include "sdb_client.h" -#include "file_sync_service.h" -#include - -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); - -void get_my_path(char *s, size_t maxLen); -int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out); -int install_app(transport_type transport, char* serial, int argc, char** argv); -int uninstall_app_sdb(const char *app_id); -int install_app_sdb(const char *srcpath); -int launch_app(transport_type transport, char* serial, int argc, char** argv); -int uninstall_app(transport_type transport, char* serial, int argc, char** argv); -int sdb_command2(const char* cmd); -void version_sdbd(transport_type ttype, char* serial); - -static const char *gProductOutPath = NULL; - -static char *product_file(const char *extra) -{ - int n; - char *x; - - if (gProductOutPath == NULL) { - fprintf(stderr, "sdb: Product directory not specified; " - "use -p or define ANDROID_PRODUCT_OUT\n"); - exit(1); - } - - n = strlen(gProductOutPath) + strlen(extra) + 2; - x = malloc(n); - if (x == 0) { - fprintf(stderr, "sdb: Out of memory (product_file())\n"); - exit(1); - } - - snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra); - return x; -} - -void version(FILE * out) { - fprintf(out, "Smart Development Bridge version %d.%d.%d\n", - SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_SERVER_VERSION); -} - -void help() -{ - version(stderr); - - fprintf(stderr, - "\n" - " Usage : sdb [option] [parameters]\n" - "\n" - " options:\n" - " -d - direct command to the only connected USB device\n" - " return an error if more than one USB device is present.\n" - " -e - direct command to the only running emulator.\n" - " return an error if more than one emulator is running.\n" - " -s - direct command to the USB device or emulator with\n" - " the given serial number.\n" - " devices - list all connected devices\n" - " connect [:] - connect to a device via TCP/IP\n" - " Port 26101 is used by default if no port number is specified.\n" - " disconnect [[:]] - disconnect from a TCP/IP device.\n" - " Port 26101 is used by default if no port number is specified.\n" - " Using this command with no additional arguments\n" - " will disconnect from all connected TCP/IP devices.\n" - "\n" - " commands:\n" - " sdb push [--with-utf8]\n" - " - copy file/dir to device\n" - " (--with-utf8 means to create the remote file with utf-8 character encoding)\n" - " sdb pull [] - copy file/dir from device\n" - " sdb shell - run remote shell interactively\n" - " sdb shell - run remote shell \n" - " sdb dlog [] - view device log\n" - " sdb install - push tpk package file and install it\n" - " sdb uninstall - uninstall this app from the device\n" - " sdb forward - forward socket connections\n" - - " forward spec is : \n" - " tcp:\n" - " sdb help - show this help message\n" - " sdb version - show version num\n" - "\n" - " sdb start-server - ensure that there is a server running\n" - " sdb kill-server - kill the server if it is running\n" - " sdb get-state - print: offline | bootloader | device\n" - " sdb get-serialno - print: \n" - " sdb status-window - continuously print device status for a specified device\n" -// " sdb usb - restarts the sdbd daemon listing on USB\n" -// " sdb tcpip - restarts the sdbd daemon listing on TCP\n" - " sdb root - switch to root or sdk user account mode\n" - " 'on' means to root mode, and vice versa" - "\n" - ); -} - -int usage() -{ - help(); - return 1; -} - -#ifdef HAVE_TERMIO_H -static struct termios tio_save; - -static void stdin_raw_init(int fd) -{ - struct termios tio; - - if(tcgetattr(fd, &tio)) return; - if(tcgetattr(fd, &tio_save)) return; - - tio.c_lflag = 0; /* disable CANON, ECHO*, etc */ - - /* no timeout but request at least one character per read */ - tio.c_cc[VTIME] = 0; - tio.c_cc[VMIN] = 1; - - tcsetattr(fd, TCSANOW, &tio); - tcflush(fd, TCIFLUSH); -} - -static void stdin_raw_restore(int fd) -{ - tcsetattr(fd, TCSANOW, &tio_save); - tcflush(fd, TCIFLUSH); -} -#endif - -static void read_and_dump(int fd) -{ - char buf[4096]; - int len; - - while(fd >= 0) { - D("read_and_dump(): pre sdb_read(fd=%d)\n", fd); - len = sdb_read(fd, buf, 4096); - D("read_and_dump(): post sdb_read(fd=%d): len=%d\n", fd, len); - if(len == 0) { - break; - } - - if(len < 0) { - if(errno == EINTR) continue; - break; - } - fwrite(buf, 1, len, stdout); - fflush(stdout); - } -} - -static void copy_to_file(int inFd, int outFd) { - const size_t BUFSIZE = 32 * 1024; - char* buf = (char*) malloc(BUFSIZE); - int len; - long total = 0; - - D("copy_to_file(%d -> %d)\n", inFd, outFd); - for (;;) { - len = sdb_read(inFd, buf, BUFSIZE); - if (len == 0) { - D("copy_to_file() : read 0 bytes; exiting\n"); - break; - } - if (len < 0) { - if (errno == EINTR) { - D("copy_to_file() : EINTR, retrying\n"); - continue; - } - D("copy_to_file() : error %d\n", errno); - break; - } - sdb_write(outFd, buf, len); - total += len; - } - D("copy_to_file() finished after %lu bytes\n", total); - free(buf); -} - -static void *stdin_read_thread(void *x) -{ - int fd, fdi; - unsigned char buf[1024]; - int r, n; - int state = 0; - - int *fds = (int*) x; - fd = fds[0]; - fdi = fds[1]; - free(fds); - - for(;;) { - /* fdi is really the client's stdin, so use read, not sdb_read here */ - D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi); - r = unix_read(fdi, buf, 1024); - D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi); - if(r == 0) break; - if(r < 0) { - if(errno == EINTR) continue; - break; - } - for(n = 0; n < r; n++){ - switch(buf[n]) { - case '\n': - state = 1; - break; - case '\r': - state = 1; - break; - case '~': - if(state == 1) state++; - break; - case '.': - if(state == 2) { - fprintf(stderr,"\n* disconnect *\n"); -#ifdef HAVE_TERMIO_H - stdin_raw_restore(fdi); -#endif - exit(0); - } - default: - state = 0; - } - } - r = sdb_write(fd, buf, r); - if(r <= 0) { - break; - } - } - return 0; -} - -int interactive_shell(void) -{ - sdb_thread_t thr; - int fdi, fd; - int *fds; - - fd = sdb_connect("shell:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - fdi = 0; //dup(0); - - fds = malloc(sizeof(int) * 2); - fds[0] = fd; - fds[1] = fdi; - -#ifdef HAVE_TERMIO_H - stdin_raw_init(fdi); -#endif - sdb_thread_create(&thr, stdin_read_thread, fds); - read_and_dump(fd); -#ifdef HAVE_TERMIO_H - stdin_raw_restore(fdi); -#endif - return 0; -} - - -static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial) -{ - if (serial) { - snprintf(buffer, buflen, "host-serial:%s:%s", serial, command); - } else { - const char* prefix = "host"; - if (ttype == kTransportUsb) - prefix = "host-usb"; - else if (ttype == kTransportLocal) - prefix = "host-local"; - - snprintf(buffer, buflen, "%s:%s", prefix, command); - } -} -#if 0 /* tizen specific */ -int sdb_download_buffer(const char *service, const void* data, int sz, - unsigned progress) -{ - char buf[4096]; - unsigned total; - int fd; - const unsigned char *ptr; - - sprintf(buf,"%s:%d", service, sz); - fd = sdb_connect(buf); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return -1; - } - - int opt = CHUNK_SIZE; - opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)); - - total = sz; - ptr = data; - - if(progress) { - char *x = strrchr(service, ':'); - if(x) service = x + 1; - } - - while(sz > 0) { - unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz; - if(writex(fd, ptr, xfer)) { - sdb_status(fd); - fprintf(stderr,"* failed to write data '%s' *\n", sdb_error()); - return -1; - } - sz -= xfer; - ptr += xfer; - if(progress) { - printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total)))); - fflush(stdout); - } - } - if(progress) { - printf("\n"); - } - - if(readx(fd, buf, 4)){ - fprintf(stderr,"* error reading response *\n"); - sdb_close(fd); - return -1; - } - if(memcmp(buf, "OKAY", 4)) { - buf[4] = 0; - fprintf(stderr,"* error response '%s' *\n", buf); - sdb_close(fd); - return -1; - } - - sdb_close(fd); - return 0; -} - -int sdb_download(const char *service, const char *fn, unsigned progress) -{ - void *data; - unsigned sz; - - data = load_file(fn, &sz); - if(data == 0) { - fprintf(stderr,"* cannot read '%s' *\n", service); - return -1; - } - - int status = sdb_download_buffer(service, data, sz, progress); - free(data); - return status; -} -#endif -static void status_window(transport_type ttype, const char* serial) -{ - char command[4096]; - char *state = 0; - char *laststate = 0; - - /* silence stderr */ -#ifdef _WIN32 - /* XXX: TODO */ -#else - int fd; - fd = unix_open("/dev/null", O_WRONLY); - dup2(fd, 2); - sdb_close(fd); -#endif - - format_host_command(command, sizeof command, "get-state", ttype, serial); - - for(;;) { - sdb_sleep_ms(250); - - if(state) { - free(state); - state = 0; - } - - state = sdb_query(command); - - if(state) { - if(laststate && !strcmp(state,laststate)){ - continue; - } else { - if(laststate) free(laststate); - laststate = strdup(state); - } - } - - printf("%c[2J%c[2H", 27, 27); - printf("Samsung Development Bridge\n"); - printf("State: %s\n", state ? state : "offline"); - fflush(stdout); - } -} - -/** duplicate string and quote all \ " ( ) chars + space character. */ -static char * -dupAndQuote(const char *s) -{ - const char *ts; - size_t alloc_len; - char *ret; - char *dest; - - ts = s; - - alloc_len = 0; - - for( ;*ts != '\0'; ts++) { - alloc_len++; - if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { - alloc_len++; - } - } - - ret = (char *)malloc(alloc_len + 1); - - ts = s; - dest = ret; - - for ( ;*ts != '\0'; ts++) { - if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { - *dest++ = '\\'; - } - - *dest++ = *ts; - } - - *dest++ = '\0'; - - return ret; -} - -/** - * Run ppp in "notty" mode against a resource listed as the first parameter - * eg: - * - * ppp dev:/dev/omap_csmi_tty0 - * - */ -int ppp(int argc, char **argv) -{ -#ifdef HAVE_WIN32_PROC - fprintf(stderr, "error: sdb %s not implemented on Win32\n", argv[0]); - return -1; -#else - char *sdb_service_name; - pid_t pid; - int fd; - - if (argc < 2) { - fprintf(stderr, "usage: sdb %s [ppp opts]\n", - argv[0]); - - return 1; - } - - sdb_service_name = argv[1]; - - fd = sdb_connect(sdb_service_name); - - if(fd < 0) { - fprintf(stderr,"Error: Could not open sdb service: %s. Error: %s\n", - sdb_service_name, sdb_error()); - return 1; - } - - pid = fork(); - - if (pid < 0) { - perror("from fork()"); - return 1; - } else if (pid == 0) { - int err; - int i; - const char **ppp_args; - - // copy args - ppp_args = (const char **) alloca(sizeof(char *) * argc + 1); - ppp_args[0] = "pppd"; - for (i = 2 ; i < argc ; i++) { - //argv[2] and beyond become ppp_args[1] and beyond - ppp_args[i - 1] = argv[i]; - } - ppp_args[i-1] = NULL; - - // child side - - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - sdb_close(STDERR_FILENO); - sdb_close(fd); - - err = execvp("pppd", (char * const *)ppp_args); - - if (err < 0) { - perror("execing pppd"); - } - exit(-1); - } else { - // parent side - - sdb_close(fd); - return 0; - } -#endif /* !HAVE_WIN32_PROC */ -} - -static int send_shellcommand(transport_type transport, char* serial, char* buf) -{ - int fd, ret; - - for(;;) { - fd = sdb_connect(buf); - if(fd >= 0) - break; - fprintf(stderr,"- waiting for device -\n"); - sdb_sleep_ms(1000); - do_cmd(transport, serial, "wait-for-device", 0); - } - - read_and_dump(fd); - ret = sdb_close(fd); - if (ret) - perror("close"); - - return ret; -} - -static int logcat(transport_type transport, char* serial, int argc, char **argv) -{ - char buf[4096]; - - snprintf(buf, sizeof(buf), - "shell:/usr/bin/dlogutil"); - -/* - if (!strcmp(argv[0],"longcat")) { - strncat(buf, " -v long", sizeof(buf)-1); - } -*/ - - argc -= 1; - argv += 1; - while(argc-- > 0) { - char *quoted; - - quoted = dupAndQuote (*argv++); - - strncat(buf, " ", sizeof(buf)-1); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - } - - send_shellcommand(transport, serial, buf); - return 0; -} - -static int mkdirs(char *path) -{ - int ret; - char *x = path + 1; - - for(;;) { - x = sdb_dirstart(x); - if(x == 0) return 0; - *x = 0; - ret = sdb_mkdir(path, 0775); - *x = OS_PATH_SEPARATOR; - if((ret < 0) && (errno != EEXIST)) { - return ret; - } - x++; - } - return 0; -} - -static int backup(int argc, char** argv) { - char buf[4096]; - char default_name[32]; - const char* filename = strcpy(default_name, "./backup.ab"); - int fd, outFd; - int i, j; - - /* find, extract, and use any -f argument */ - for (i = 1; i < argc; i++) { - if (!strcmp("-f", argv[i])) { - if (i == argc-1) { - fprintf(stderr, "sdb: -f passed with no filename\n"); - return usage(); - } - filename = argv[i+1]; - for (j = i+2; j <= argc; ) { - argv[i++] = argv[j++]; - } - argc -= 2; - argv[argc] = NULL; - } - } - - /* bare "sdb backup" or "sdb backup -f filename" are not valid invocations */ - if (argc < 2) return usage(); - - sdb_unlink(filename); - mkdirs((char *)filename); - outFd = sdb_creat(filename, 0640); - if (outFd < 0) { - fprintf(stderr, "sdb: unable to open file %s\n", filename); - return -1; - } - - snprintf(buf, sizeof(buf), "backup"); - for (argc--, argv++; argc; argc--, argv++) { - strncat(buf, ":", sizeof(buf) - strlen(buf) - 1); - strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1); - } - - D("backup. filename=%s buf=%s\n", filename, buf); - fd = sdb_connect(buf); - if (fd < 0) { - fprintf(stderr, "sdb: unable to connect for backup\n"); - sdb_close(outFd); - return -1; - } - - printf("Now unlock your device and confirm the backup operation.\n"); - copy_to_file(fd, outFd); - - sdb_close(fd); - sdb_close(outFd); - return 0; -} - -static int restore(int argc, char** argv) { - const char* filename; - int fd, tarFd; - - if (argc != 2) return usage(); - - filename = argv[1]; - tarFd = sdb_open(filename, O_RDONLY); - if (tarFd < 0) { - fprintf(stderr, "sdb: unable to open file %s\n", filename); - return -1; - } - - fd = sdb_connect("restore:"); - if (fd < 0) { - fprintf(stderr, "sdb: unable to connect for backup\n"); - sdb_close(tarFd); - return -1; - } - - printf("Now unlock your device and confirm the restore operation.\n"); - copy_to_file(tarFd, fd); - - sdb_close(fd); - sdb_close(tarFd); - return 0; -} - -#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make" -static int top_works(const char *top) -{ - if (top != NULL && sdb_is_absolute_host_path(top)) { - char path_buf[PATH_MAX]; - snprintf(path_buf, sizeof(path_buf), - "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top); - return access(path_buf, F_OK) == 0; - } - return 0; -} - -static char *find_top_from(const char *indir, char path_buf[PATH_MAX]) -{ - strcpy(path_buf, indir); - while (1) { - if (top_works(path_buf)) { - return path_buf; - } - char *s = sdb_dirstop(path_buf); - if (s != NULL) { - *s = '\0'; - } else { - path_buf[0] = '\0'; - return NULL; - } - } -} - -static char *find_top(char path_buf[PATH_MAX]) -{ - char *top = getenv("ANDROID_BUILD_TOP"); - if (top != NULL && top[0] != '\0') { - if (!top_works(top)) { - fprintf(stderr, "sdb: bad ANDROID_BUILD_TOP value \"%s\"\n", top); - return NULL; - } - } else { - top = getenv("TOP"); - if (top != NULL && top[0] != '\0') { - if (!top_works(top)) { - fprintf(stderr, "sdb: bad TOP value \"%s\"\n", top); - return NULL; - } - } else { - top = NULL; - } - } - - if (top != NULL) { - /* The environment pointed to a top directory that works. - */ - strcpy(path_buf, top); - return path_buf; - } - - /* The environment didn't help. Walk up the tree from the CWD - * to see if we can find the top. - */ - char dir[PATH_MAX]; - top = find_top_from(getcwd(dir, sizeof(dir)), path_buf); - if (top == NULL) { - /* If the CWD isn't under a good-looking top, see if the - * executable is. - */ - get_my_path(dir, PATH_MAX); - top = find_top_from(dir, path_buf); - } - return top; -} - -/* may be: - * - A simple product name - * e.g., "sooner" -TODO: debug? sooner-debug, sooner:debug? - * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir - * e.g., "out/target/product/sooner" - * - An absolute path to the PRODUCT_OUT dir - * e.g., "/src/device/out/target/product/sooner" - * - * Given , try to construct an absolute path to the - * ANDROID_PRODUCT_OUT dir. - */ -static const char *find_product_out_path(const char *hint) -{ - static char path_buf[PATH_MAX]; - - if (hint == NULL || hint[0] == '\0') { - return NULL; - } - - /* If it's already absolute, don't bother doing any work. - */ - if (sdb_is_absolute_host_path(hint)) { - strcpy(path_buf, hint); - return path_buf; - } - - /* If there are any slashes in it, assume it's a relative path; - * make it absolute. - */ - if (sdb_dirstart(hint) != NULL) { - if (getcwd(path_buf, sizeof(path_buf)) == NULL) { - fprintf(stderr, "sdb: Couldn't get CWD: errno:%d\n", errno); - return NULL; - } - if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) { - fprintf(stderr, "sdb: Couldn't assemble path\n"); - return NULL; - } - strcat(path_buf, OS_PATH_SEPARATOR_STR); - strcat(path_buf, hint); - return path_buf; - } - - /* It's a string without any slashes. Try to do something with it. - * - * Try to find the root of the build tree, and build a PRODUCT_OUT - * path from there. - */ - char top_buf[PATH_MAX]; - const char *top = find_top(top_buf); - if (top == NULL) { - fprintf(stderr, "sdb: Couldn't find top of build tree\n"); - return NULL; - } -//TODO: if we have a way to indicate debug, look in out/debug/target/... - snprintf(path_buf, sizeof(path_buf), - "%s" OS_PATH_SEPARATOR_STR - "out" OS_PATH_SEPARATOR_STR - "target" OS_PATH_SEPARATOR_STR - "product" OS_PATH_SEPARATOR_STR - "%s", top_buf, hint); - if (access(path_buf, F_OK) < 0) { - fprintf(stderr, "sdb: Couldn't find a product dir " - "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf); - return NULL; - } - return path_buf; -} - -int sdb_commandline(int argc, char **argv) -{ - char buf[4096]; - int no_daemon = 0; - int is_daemon = 0; - int is_server = 0; - int persist = 0; - int r; - int quote; - transport_type ttype = kTransportAny; - char* serial = NULL; - char* server_port_str = NULL; - - /* If defined, this should be an absolute path to - * the directory containing all of the various system images - * for a particular product. If not defined, and the sdb - * command requires this information, then the user must - * specify the path using "-p". - */ - gProductOutPath = getenv("ANDROID_PRODUCT_OUT"); - if (gProductOutPath == NULL || gProductOutPath[0] == '\0') { - gProductOutPath = NULL; - } - // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint - - serial = getenv("ANDROID_SERIAL"); - - /* Validate and assign the server port */ - server_port_str = getenv("ANDROID_SDB_SERVER_PORT"); - int server_port = DEFAULT_SDB_PORT; - if (server_port_str && strlen(server_port_str) > 0) { - server_port = (int) strtol(server_port_str, NULL, 0); - if (server_port <= 0) { - fprintf(stderr, - "sdb: Env var ANDROID_SDB_SERVER_PORT must be a positive number. Got \"%s\"\n", - server_port_str); - return usage(); - } - } - - /* modifiers and flags */ - while(argc > 0) { - if(!strcmp(argv[0],"server")) { - is_server = 1; - } else if(!strcmp(argv[0],"nodaemon")) { - no_daemon = 1; - } else if (!strcmp(argv[0], "fork-server")) { - /* this is a special flag used only when the SDB client launches the SDB Server */ - is_daemon = 1; - } else if(!strcmp(argv[0],"persist")) { - persist = 1; - } else if(!strncmp(argv[0], "-p", 2)) { - const char *product = NULL; - if (argv[0][2] == '\0') { - if (argc < 2) return usage(); - product = argv[1]; - argc--; - argv++; - } else { - product = argv[1] + 2; - } - gProductOutPath = find_product_out_path(product); - if (gProductOutPath == NULL) { - fprintf(stderr, "sdb: could not resolve \"-p %s\"\n", - product); - return usage(); - } - } else if (argv[0][0]=='-' && argv[0][1]=='s') { - if (isdigit(argv[0][2])) { - serial = argv[0] + 2; - } else { - if(argc < 2 || argv[0][2] != '\0') return usage(); - serial = argv[1]; - argc--; - argv++; - } - } else if (!strcmp(argv[0],"-d")) { - ttype = kTransportUsb; - } else if (!strcmp(argv[0],"-e")) { - ttype = kTransportLocal; - } else { - /* out of recognized modifiers and flags */ - break; - } - argc--; - argv++; - } - - -// sdb_set_transport(ttype, serial); -// sdb_set_tcp_specifics(server_port); - - if (is_server) { - if (no_daemon || is_daemon) { - r = sdb_main(is_daemon, server_port); - } else { - r = launch_server(server_port); - } - if(r) { - fprintf(stderr,"* could not start server *\n"); - } - return r; - } - -top: - if(argc == 0) { - return usage(); - } - - // first, get the uniq device from the partial serial with prefix matching - if (serial) { - char *tmp; - snprintf(buf, sizeof(buf), "host:serial-match:%s", serial); - tmp = sdb_query(buf); - if (tmp) { - //printf("connect to device: %s\n", tmp); - serial = strdup(tmp); - sdb_set_transport(ttype, serial); - sdb_set_tcp_specifics(server_port); - } else { - return 1; - } - } else { - sdb_set_transport(ttype, serial); - sdb_set_tcp_specifics(server_port); - } - /* sdb_connect() commands */ - - if(!strcmp(argv[0], "devices")) { - char *tmp; - snprintf(buf, sizeof buf, "host:%s", argv[0]); - tmp = sdb_query(buf); - if(tmp) { - printf("List of devices attached \n"); - printf("%s", tmp); - return 0; - } else { - return 1; - } - } - - if(!strcmp(argv[0], "connect")) { - char *tmp; - if (argc != 2) { - fprintf(stderr, "Usage: sdb connect [:]\n"); - return 1; - } - snprintf(buf, sizeof buf, "host:connect:%s", argv[1]); - tmp = sdb_query(buf); - if(tmp) { - printf("%s\n", tmp); - return 0; - } else { - return 1; - } - } - - if(!strcmp(argv[0], "disconnect")) { - char *tmp; - if (argc > 2) { - fprintf(stderr, "Usage: sdb disconnect [[:]]\n"); - return 1; - } - if (argc == 2) { - snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]); - } else { - snprintf(buf, sizeof buf, "host:disconnect:"); - } - tmp = sdb_query(buf); - if(tmp) { - printf("%s\n", tmp); - return 0; - } else { - return 1; - } - } - - if (!strcmp(argv[0], "emu")) { - return sdb_send_emulator_command(argc, argv); - } - - if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) { - int r; - int fd; - - char h = (argv[0][0] == 'h'); - - if (h) { - printf("\x1b[41;33m"); - fflush(stdout); - } - - if(argc < 2) { - D("starting interactive shell\n"); - r = interactive_shell(); - if (h) { - printf("\x1b[0m"); - fflush(stdout); - } - return r; - } - - snprintf(buf, sizeof buf, "shell:%s", argv[1]); - argc -= 2; - argv += 2; - while(argc-- > 0) { - strcat(buf, " "); - - /* quote empty strings and strings with spaces */ - quote = (**argv == 0 || strchr(*argv, ' ')); - if (quote) - strcat(buf, "\""); - strcat(buf, *argv++); - if (quote) - strcat(buf, "\""); - } - - for(;;) { - D("interactive shell loop. buff=%s\n", buf); - fd = sdb_connect(buf); - if(fd >= 0) { - D("about to read_and_dump(fd=%d)\n", fd); - read_and_dump(fd); - D("read_and_dump() done.\n"); - sdb_close(fd); - r = 0; - } else { - fprintf(stderr,"error: %s\n", sdb_error()); - r = -1; - } - - if(persist) { - fprintf(stderr,"\n- waiting for device -\n"); - sdb_sleep_ms(1000); - do_cmd(ttype, serial, "wait-for-device", 0); - } else { - if (h) { - printf("\x1b[0m"); - fflush(stdout); - } - D("interactive shell loop. return r=%d\n", r); - return r; - } - } - } - - if(!strcmp(argv[0], "kill-server")) { - int fd; - fd = _sdb_connect("host:kill"); - if(fd == -1) { - fprintf(stderr,"* server not running *\n"); - return 1; - } - return 0; - } -#if 0 /* tizen specific */ - if(!strcmp(argv[0], "sideload")) { - if(argc != 2) return usage(); - if(sdb_download("sideload", argv[1], 1)) { - return 1; - } else { - return 0; - } - } -#endif - if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot") - || !strcmp(argv[0], "reboot-bootloader") - || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb") - || !strcmp(argv[0], "root")) { - char command[100]; - if (!strcmp(argv[0], "reboot-bootloader")) - snprintf(command, sizeof(command), "reboot:bootloader"); - else if (argc > 1) - snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]); - else - snprintf(command, sizeof(command), "%s:", argv[0]); - int fd = sdb_connect(command); - if(fd >= 0) { - read_and_dump(fd); - sdb_close(fd); - return 0; - } - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - if(!strcmp(argv[0], "bugreport")) { - if (argc != 1) return usage(); - do_cmd(ttype, serial, "shell", "bugreport", 0); - return 0; - } - - /* sdb_command() wrapper commands */ - - if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { - char* service = argv[0]; - if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { - if (ttype == kTransportUsb) { - service = "wait-for-usb"; - } else if (ttype == kTransportLocal) { - service = "wait-for-local"; - } else { - service = "wait-for-any"; - } - } - - format_host_command(buf, sizeof buf, service, ttype, serial); - - if (sdb_command(buf)) { - D("failure: %s *\n",sdb_error()); - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - /* Allow a command to be run after wait-for-device, - * e.g. 'sdb wait-for-device shell'. - */ - if(argc > 1) { - argc--; - argv++; - goto top; - } - return 0; - } - - if(!strcmp(argv[0], "forward")) { - if(argc != 3) return usage(); - if (serial) { - snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]); - } else if (ttype == kTransportUsb) { - snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]); - } else if (ttype == kTransportLocal) { - snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]); - } else { - snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]); - } - if(sdb_command(buf)) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - return 0; - } - - /* do_sync_*() commands */ - - if(!strcmp(argv[0], "ls")) { - if(argc != 2) return usage(); - return do_sync_ls(argv[1]); - } - - if(!strcmp(argv[0], "push")) { - int i=0; - int utf8=0; - - if(argc < 3) return usage(); - if (argv[argc-1][0] == '-') { - if (!strcmp(argv[argc-1], "--with-utf8")) { - utf8 = 1; - argc = argc - 1; - } else { - return usage(); - } - } - for (i=1; i= 2 && strcmp(argv[1], "-l") == 0) { - listonly = 1; - if (argc == 3) { - srcarg = argv[2]; - } else { - srcarg = NULL; - } - } else if(argc == 2) { - /* A local path or "android"/"data" arg was specified. */ - srcarg = argv[1]; - } else { - return usage(); - } - ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath); - if(ret != 0) return usage(); - - if(android_srcpath != NULL) - ret = do_sync_sync(android_srcpath, "/system", listonly); - if(ret == 0 && data_srcpath != NULL) - ret = do_sync_sync(data_srcpath, "/data", listonly); - - free(android_srcpath); - free(data_srcpath); - return ret; - } - - /* passthrough commands */ - - if(!strcmp(argv[0],"get-state") || - !strcmp(argv[0],"get-serialno")) - { - char *tmp; - - format_host_command(buf, sizeof buf, argv[0], ttype, serial); - tmp = sdb_query(buf); - if(tmp) { - printf("%s\n", tmp); - return 0; - } else { - return 1; - } - } - - /* other commands */ - - if(!strcmp(argv[0],"status-window")) { - status_window(ttype, serial); - return 0; - } - - if(!strcmp(argv[0],"dlog")) { - return logcat(ttype, serial, argc, argv); - } - - if(!strcmp(argv[0],"ppp")) { - return ppp(argc, argv); - } - - if (!strcmp(argv[0], "start-server")) { - return sdb_connect("host:start-server"); - } - - if (!strcmp(argv[0], "backup")) { - return backup(argc, argv); - } - - if (!strcmp(argv[0], "restore")) { - return restore(argc, argv); - } - - if (!strcmp(argv[0], "jdwp")) { - int fd = sdb_connect("jdwp"); - if (fd >= 0) { - read_and_dump(fd); - sdb_close(fd); - return 0; - } else { - fprintf(stderr, "error: %s\n", sdb_error()); - return -1; - } - } - - /* "sdb /?" is a common idiom under Windows */ - if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) { - help(); - return 0; - } - - if(!strcmp(argv[0], "version")) { - if (ttype == kTransportUsb || ttype == kTransportLocal) { - version_sdbd(ttype, serial); - } else { - version(stdout); - } - return 0; - } - - usage(); - return 1; -} - -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...) -{ - char *argv[16]; - int argc; - va_list ap; - - va_start(ap, cmd); - argc = 0; - - if (serial) { - argv[argc++] = "-s"; - argv[argc++] = serial; - } else if (ttype == kTransportUsb) { - argv[argc++] = "-d"; - } else if (ttype == kTransportLocal) { - argv[argc++] = "-e"; - } - - argv[argc++] = cmd; - while((argv[argc] = va_arg(ap, char*)) != 0) { - argc++; - } - va_end(ap); - -#if 0 - int n; - fprintf(stderr,"argc = %d\n",argc); - for(n = 0; n < argc; n++) { - fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]); - } -#endif - - return sdb_commandline(argc, argv); -} - -int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out) -{ - char *android_srcdir, *data_srcdir; - - if(srcarg == NULL) { - android_srcdir = product_file("system"); - data_srcdir = product_file("data"); - } else { - /* srcarg may be "data", "system" or NULL. - * if srcarg is NULL, then both data and system are synced - */ - if(strcmp(srcarg, "system") == 0) { - android_srcdir = product_file("system"); - data_srcdir = NULL; - } else if(strcmp(srcarg, "data") == 0) { - android_srcdir = NULL; - data_srcdir = product_file("data"); - } else { - /* It's not "system" or "data". - */ - return 1; - } - } - - if(android_srcdir_out != NULL) - *android_srcdir_out = android_srcdir; - else - free(android_srcdir); - - if(data_srcdir_out != NULL) - *data_srcdir_out = data_srcdir; - else - free(data_srcdir); - - return 0; -} - -static int pm_command(transport_type transport, char* serial, - int argc, char** argv) -{ - char buf[4096]; - - snprintf(buf, sizeof(buf), "shell:pm"); - - while(argc-- > 0) { - char *quoted; - - quoted = dupAndQuote(*argv++); - - strncat(buf, " ", sizeof(buf)-1); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - } - - send_shellcommand(transport, serial, buf); - return 0; -} - -int sdb_command2(const char* cmd) { - int result = sdb_connect(cmd); - - if(result < 0) { - return result; - } - - D("about to read_and_dump(fd=%d)\n", result); - read_and_dump(result); - D("read_and_dump() done.\n"); - sdb_close(result); - - return 0; -} - -int install_app_sdb(const char *srcpath) { - D("Install start\n"); - const char * APP_DEST = tzplatform_mkpath(TZ_SYS_RW_APP,"PKGS/%s"); - const char* filename = sdb_dirstop(srcpath); - char destination[PATH_MAX]; - - if (filename) { - filename++; - snprintf(destination, sizeof destination, APP_DEST, filename); - } else { - snprintf(destination, sizeof destination, APP_DEST, srcpath); - } - - D("Push file: %s to %s\n", srcpath, destination); - int result = do_sync_push(srcpath, destination, 0, 0); - - if(result < 0) { - fprintf(stderr, "error: %s\n", sdb_error()); - return -1; - } - - const char* SHELL_INSTALL_CMD ="shell:pkgcmd -i -t tpk -p %s -q"; - char full_cmd[PATH_MAX]; - snprintf(full_cmd, sizeof full_cmd, SHELL_INSTALL_CMD, destination); - D("Install command: %s\n", full_cmd); - result = sdb_command2(full_cmd); - - if(result < 0) { - fprintf(stderr, "error: %s\n", sdb_error()); - return result; - } - - const char* SHELL_REMOVE_CMD = "shell:rm %s"; - snprintf(full_cmd, sizeof full_cmd, SHELL_REMOVE_CMD, destination); - D("Remove file command: %s\n", full_cmd); - result = sdb_command2(full_cmd); - - if(result < 0) { - fprintf(stderr, "error: %s\n", sdb_error()); - return result; - } - - return 0; -} - -int uninstall_app_sdb(const char *appid) { - const char* SHELL_UNINSTALL_CMD ="shell:pkgcmd -u -t tpk -n %s -q"; - char full_cmd[PATH_MAX]; - int result = 0; - snprintf(full_cmd, sizeof full_cmd, SHELL_UNINSTALL_CMD, appid); - result = sdb_command2(full_cmd); - - if(result < 0) { - fprintf(stderr, "error: %s\n", sdb_error()); - return result; - } - - return 0; -} - -int uninstall_app(transport_type transport, char* serial, int argc, char** argv) -{ - /* if the user choose the -k option, we refuse to do it until devices are - out with the option to uninstall the remaining data somehow (sdb/ui) */ - if (argc == 3 && strcmp(argv[1], "-k") == 0) - { - printf( - "The -k option uninstalls the application while retaining the data/cache.\n" - "At the moment, there is no way to remove the remaining data.\n" - "You will have to reinstall the application with the same signature, and fully uninstall it.\n" - "If you truly wish to continue, execute 'sdb shell pm uninstall -k %s'\n", argv[2]); - return -1; - } - - /* 'sdb uninstall' takes the same arguments as 'pm uninstall' on device */ - return pm_command(transport, serial, argc, argv); -} - -static int delete_file(transport_type transport, char* serial, char* filename) -{ - char buf[4096]; - char* quoted; - - snprintf(buf, sizeof(buf), "shell:rm "); - quoted = dupAndQuote(filename); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - - send_shellcommand(transport, serial, buf); - return 0; -} - -const char* get_basename(const char* filename) -{ - const char* basename = sdb_dirstop(filename); - if (basename) { - basename++; - return basename; - } else { - return filename; - } -} - -static int check_file(const char* filename) -{ - struct stat st; - - if (filename == NULL) { - return 0; - } - - if (stat(filename, &st) != 0) { - fprintf(stderr, "can't find '%s' to install\n", filename); - return 1; - } - - if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "can't install '%s' because it's not a file\n", filename); - return 1; - } - - return 0; -} - -int install_app(transport_type transport, char* serial, int argc, char** argv) -{ - static const char *const DATA_DEST = "/data/local/tmp/%s"; - static const char *const SD_DEST = "/sdcard/tmp/%s"; - const char* where = DATA_DEST; - char apk_dest[PATH_MAX]; - char verification_dest[PATH_MAX]; - char* apk_file; - char* verification_file = NULL; - int file_arg = -1; - int err; - int i; - int verify_apk = 1; - - for (i = 1; i < argc; i++) { - if (*argv[i] != '-') { - file_arg = i; - break; - } else if (!strcmp(argv[i], "-i")) { - // Skip the installer package name. - i++; - } else if (!strcmp(argv[i], "-s")) { - where = SD_DEST; - } else if (!strcmp(argv[i], "--algo")) { - verify_apk = 0; - i++; - } else if (!strcmp(argv[i], "--iv")) { - verify_apk = 0; - i++; - } else if (!strcmp(argv[i], "--key")) { - verify_apk = 0; - i++; - } - } - - if (file_arg < 0) { - fprintf(stderr, "can't find filename in arguments\n"); - return 1; - } else if (file_arg + 2 < argc) { - fprintf(stderr, "too many files specified; only takes APK file and verifier file\n"); - return 1; - } - - apk_file = argv[file_arg]; - - if (file_arg != argc - 1) { - verification_file = argv[file_arg + 1]; - } - - if (check_file(apk_file) || check_file(verification_file)) { - return 1; - } - - snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file)); - if (verification_file != NULL) { - snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file)); - - if (!strcmp(apk_dest, verification_dest)) { - fprintf(stderr, "APK and verification file can't have the same name\n"); - return 1; - } - } - - err = do_sync_push(apk_file, apk_dest, verify_apk, 0); - if (err) { - goto cleanup_apk; - } else { - argv[file_arg] = apk_dest; /* destination name, not source location */ - } - - if (verification_file != NULL) { - err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */, 0); - if (err) { - goto cleanup_apk; - } else { - argv[file_arg + 1] = verification_dest; /* destination name, not source location */ - } - } - - pm_command(transport, serial, argc, argv); - -cleanup_apk: - if (verification_file != NULL) { - delete_file(transport, serial, verification_dest); - } - - delete_file(transport, serial, apk_dest); - - return err; -} - -int launch_app(transport_type transport, char* serial, int argc, char** argv) -{ - static const char *const SHELL_LAUNCH_CMD = "shell:/usr/bin/sdk_launch_app "; - char full_cmd[PATH_MAX]; - int i; - int result = 0; - - snprintf(full_cmd, sizeof full_cmd, "%s", SHELL_LAUNCH_CMD); - - //TODO: check argument validation - - for (i=1 ; i - -static int connect_to_console(void) -{ - int fd, port; - - port = sdb_get_emulator_console_port(); - if (port < 0) { - if (port == -2) - fprintf(stderr, "error: more than one emulator detected. use -s option\n"); - else - fprintf(stderr, "error: no emulator detected\n"); - return -1; - } - fd = socket_loopback_client( port, SOCK_STREAM ); - if (fd < 0) { - fprintf(stderr, "error: could not connect to TCP port %d\n", port); - return -1; - } - return fd; -} - - -int sdb_send_emulator_command(int argc, char** argv) -{ - int fd, nn; - - fd = connect_to_console(); - if (fd < 0) - return 1; - -#define QUIT "quit\n" - - for (nn = 1; nn < argc; nn++) { - sdb_write( fd, argv[nn], strlen(argv[nn]) ); - sdb_write( fd, (nn == argc-1) ? "\n" : " ", 1 ); - } - sdb_write( fd, QUIT, sizeof(QUIT)-1 ); - sdb_close(fd); - - return 0; -} diff --git a/src/file_sync_client.c b/src/file_sync_client.c deleted file mode 100644 index 3ba3770..0000000 --- a/src/file_sync_client.c +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -// tizen specific #include - -#include "sysdeps.h" -#include "sdb.h" -#include "sdb_client.h" -#include "file_sync_service.h" - - -static unsigned total_bytes; -static long long start_time; -extern const char* get_basename(const char* filename); - -static long long NOW() -{ - struct timeval tv; - gettimeofday(&tv, 0); - return ((long long) tv.tv_usec) + - 1000000LL * ((long long) tv.tv_sec); -} - -static void BEGIN() -{ - total_bytes = 0; - start_time = NOW(); -} - -static void END(const char* filename) -{ - long long t = NOW() - start_time; - if(total_bytes == 0) return; - - if (t == 0) /* prevent division by 0 :-) */ - t = 1000000; - - fprintf(stderr,"%-30s %lld KB/s (%lld bytes in %lld.%03llds)\n", - filename, - ((((long long) total_bytes) * 1000000LL) / t) / 1024LL, - (long long) total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL); -} - - -void sync_quit(int fd) -{ - syncmsg msg; - - msg.req.id = ID_QUIT; - msg.req.namelen = 0; - - writex(fd, &msg.req, sizeof(msg.req)); -} - -typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie); - -int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie) -{ - syncmsg msg; - char buf[257]; - int len; - - len = strlen(path); - if(len > 1024) goto fail; - - msg.req.id = ID_LIST; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - goto fail; - } - - for(;;) { - if(readx(fd, &msg.dent, sizeof(msg.dent))) break; - if(msg.dent.id == ID_DONE) return 0; - if(msg.dent.id != ID_DENT) break; - - len = ltohl(msg.dent.namelen); - if(len > 256) break; - - if(readx(fd, buf, len)) break; - buf[len] = 0; - - func(ltohl(msg.dent.mode), - ltohl(msg.dent.size), - ltohl(msg.dent.time), - buf, cookie); - } - -fail: - sdb_close(fd); - return -1; -} - -typedef struct syncsendbuf syncsendbuf; - -struct syncsendbuf { - unsigned id; - unsigned size; - char data[SYNC_DATA_MAX]; -}; - -static syncsendbuf send_buffer; - -int sync_readtime(int fd, const char *path, unsigned *timestamp) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - if(readx(fd, &msg.stat, sizeof(msg.stat))) { - return -1; - } - - if(msg.stat.id != ID_STAT) { - return -1; - } - - *timestamp = ltohl(msg.stat.time); - return 0; -} - -static int sync_start_readtime(int fd, const char *path) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - return 0; -} - -static int sync_finish_readtime(int fd, unsigned int *timestamp, - unsigned int *mode, unsigned int *size) -{ - syncmsg msg; - - if(readx(fd, &msg.stat, sizeof(msg.stat))) - return -1; - - if(msg.stat.id != ID_STAT) - return -1; - - *timestamp = ltohl(msg.stat.time); - *mode = ltohl(msg.stat.mode); - *size = ltohl(msg.stat.size); - - return 0; -} - -int sync_readmode(int fd, const char *path, unsigned *mode) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - if(readx(fd, &msg.stat, sizeof(msg.stat))) { - return -1; - } - - if(msg.stat.id != ID_STAT) { - return -1; - } - - *mode = ltohl(msg.stat.mode); - return 0; -} - -static int write_data_file(int fd, const char *path, syncsendbuf *sbuf) -{ - int lfd, err = 0; - - lfd = sdb_open(path, O_RDONLY); - if(lfd < 0) { - fprintf(stderr,"cannot open '%s': errno:%d\n", path, errno); - return -1; - } - - sbuf->id = ID_DATA; - for(;;) { - int ret; - - ret = sdb_read(lfd, sbuf->data, SYNC_DATA_MAX); - if(!ret) - break; - - if(ret < 0) { - if(errno == EINTR) - continue; - fprintf(stderr,"cannot read '%s': errno:%d\n", path, errno); - break; - } - - sbuf->size = htoll(ret); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){ - err = -1; - break; - } - total_bytes += ret; - } - - sdb_close(lfd); - return err; -} - -static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf) -{ - int err = 0; - int total = 0; - - sbuf->id = ID_DATA; - while (total < size) { - int count = size - total; - if (count > SYNC_DATA_MAX) { - count = SYNC_DATA_MAX; - } - - memcpy(sbuf->data, &file_buffer[total], count); - sbuf->size = htoll(count); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){ - err = -1; - break; - } - total += count; - total_bytes += count; - } - - return err; -} - -#ifdef HAVE_SYMLINKS -static int write_data_link(int fd, const char *path, syncsendbuf *sbuf) -{ - int len, ret; - - len = readlink(path, sbuf->data, SYNC_DATA_MAX-1); - if(len < 0) { - fprintf(stderr, "error reading link '%s': errno:%d\n", path, errno); - return -1; - } - sbuf->data[len] = '\0'; - - sbuf->size = htoll(len + 1); - sbuf->id = ID_DATA; - - ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1); - if(ret) - return -1; - - total_bytes += len + 1; - - return 0; -} -#endif - -static int sync_send(int fd, const char *lpath, const char *rpath, - unsigned mtime, mode_t mode, int verifyApk) -{ - syncmsg msg; - int len, r; - syncsendbuf *sbuf = &send_buffer; - char* file_buffer = NULL; - int size = 0; - char tmp[64]; - - len = strlen(rpath); - if(len > 1024) goto fail; - - snprintf(tmp, sizeof(tmp), ",%d", mode); - r = strlen(tmp); -#if 0 /* tizen specific */ - if (verifyApk) { - int lfd; - zipfile_t zip; - zipentry_t entry; - int amt; - - // if we are transferring an APK file, then sanity check to make sure - // we have a real zip file that contains an AndroidManifest.xml - // this requires that we read the entire file into memory. - lfd = sdb_open(lpath, O_RDONLY); - if(lfd < 0) { - fprintf(stderr,"cannot open '%s': errno:%d\n", lpath, errno); - return -1; - } - - size = sdb_lseek(lfd, 0, SEEK_END); - if (size == -1 || -1 == sdb_lseek(lfd, 0, SEEK_SET)) { - fprintf(stderr, "error seeking in file '%s'\n", lpath); - sdb_close(lfd); - return 1; - } - - file_buffer = (char *)malloc(size); - if (file_buffer == NULL) { - fprintf(stderr, "could not allocate buffer for '%s'\n", - lpath); - sdb_close(lfd); - return 1; - } - amt = sdb_read(lfd, file_buffer, size); - if (amt != size) { - fprintf(stderr, "error reading from file: '%s'\n", lpath); - sdb_close(lfd); - free(file_buffer); - return 1; - } - - sdb_close(lfd); - - zip = init_zipfile(file_buffer, size); - if (zip == NULL) { - fprintf(stderr, "file '%s' is not a valid zip file\n", - lpath); - free(file_buffer); - return 1; - } - - entry = lookup_zipentry(zip, "AndroidManifest.xml"); - release_zipfile(zip); - if (entry == NULL) { - fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n", - lpath); - free(file_buffer); - return 1; - } - } -#endif - msg.req.id = ID_SEND; - msg.req.namelen = htoll(len + r); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, rpath, len) || writex(fd, tmp, r)) { - free(file_buffer); - goto fail; - } - - if (file_buffer) { - write_data_buffer(fd, file_buffer, size, sbuf); - free(file_buffer); - } else if (S_ISREG(mode)) - write_data_file(fd, lpath, sbuf); -#ifdef HAVE_SYMLINKS - else if (S_ISLNK(mode)) - write_data_link(fd, lpath, sbuf); -#endif - else - goto fail; - - msg.data.id = ID_DONE; - msg.data.size = htoll(mtime); - if(writex(fd, &msg.data, sizeof(msg.data))) - goto fail; - - if(readx(fd, &msg.status, sizeof(msg.status))) - return -1; - - if(msg.status.id != ID_OKAY) { - if(msg.status.id == ID_FAIL) { - len = ltohl(msg.status.msglen); - if(len > 256) len = 256; - if(readx(fd, sbuf->data, len)) { - return -1; - } - sbuf->data[len] = 0; - } else - strcpy(sbuf->data, "unknown reason"); - - fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); - return -1; - } - - return 0; - -fail: - fprintf(stderr,"protocol failure\n"); - sdb_close(fd); - return -1; -} - -static int mkdirs(char *name) -{ - int ret; - char *x = name + 1; - - for(;;) { - x = sdb_dirstart(x); - if(x == 0) return 0; - *x = 0; - ret = sdb_mkdir(name, 0775); - *x = OS_PATH_SEPARATOR; - if((ret < 0) && (errno != EEXIST)) { - return ret; - } - x++; - } - return 0; -} - -int sync_recv(int fd, const char *rpath, const char *lpath) -{ - syncmsg msg; - int len; - int lfd = -1; - char *buffer = send_buffer.data; - unsigned id; - - len = strlen(rpath); - if(len > 1024) return -1; - - msg.req.id = ID_RECV; - msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, rpath, len)) { - return -1; - } - - if(readx(fd, &msg.data, sizeof(msg.data))) { - return -1; - } - id = msg.data.id; - - if((id == ID_DATA) || (id == ID_DONE)) { - sdb_unlink(lpath); - mkdirs((char *)lpath); - lfd = sdb_creat(lpath, 0644); - if(lfd < 0) { - fprintf(stderr,"cannot create '%s': errno:%d\n", lpath, errno); - return -1; - } - goto handle_data; - } else { - goto remote_error; - } - - for(;;) { - if(readx(fd, &msg.data, sizeof(msg.data))) { - return -1; - } - id = msg.data.id; - - handle_data: - len = ltohl(msg.data.size); - if(id == ID_DONE) break; - if(id != ID_DATA) goto remote_error; - if(len > SYNC_DATA_MAX) { - fprintf(stderr,"data overrun\n"); - sdb_close(lfd); - return -1; - } - - if(readx(fd, buffer, len)) { - sdb_close(lfd); - return -1; - } - - if(writex(lfd, buffer, len)) { - fprintf(stderr,"cannot write '%s': errno:%d\n", rpath, errno); - sdb_close(lfd); - return -1; - } - - total_bytes += len; - } - - sdb_close(lfd); - return 0; - -remote_error: - sdb_close(lfd); - sdb_unlink(lpath); - - if(id == ID_FAIL) { - len = ltohl(msg.data.size); - if(len > 256) len = 256; - if(readx(fd, buffer, len)) { - return -1; - } - buffer[len] = 0; - } else { - memcpy(buffer, &id, 4); - buffer[4] = 0; -// strcpy(buffer,"unknown reason"); - } - fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); - return 0; -} - - - -/* --- */ - - -static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time, - const char *name, void *cookie) -{ - printf("%08x %08x %08x %s\n", mode, size, time, name); -} - -int do_sync_ls(const char *path) -{ - int fd = sdb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - if(sync_ls(fd, path, do_sync_ls_cb, 0)) { - return 1; - } else { - sync_quit(fd); - return 0; - } -} - -typedef struct copyinfo copyinfo; - -struct copyinfo -{ - copyinfo *next; - const char *src; - const char *dst; - unsigned int time; - unsigned int mode; - unsigned int size; - int flag; - //char data[0]; -}; - -copyinfo *mkcopyinfo(const char *spath, const char *dpath, - const char *name, int isdir) -{ - int slen = strlen(spath); - int dlen = strlen(dpath); - int nlen = strlen(name); - int ssize = slen + nlen + 2; - int dsize = dlen + nlen + 2; - - copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize); - if(ci == 0) { - fprintf(stderr,"out of memory\n"); - abort(); - } - - ci->next = 0; - ci->time = 0; - ci->mode = 0; - ci->size = 0; - ci->flag = 0; - ci->src = (const char*)(ci + 1); - ci->dst = ci->src + ssize; - snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name); - snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name); - -// fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst); - return ci; -} - - -static int local_build_list(copyinfo **filelist, - const char *lpath, const char *rpath) -{ - DIR *d; - struct dirent *de; - struct stat st; - copyinfo *dirlist = 0; - copyinfo *ci, *next; - -// fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath); - - d = opendir(lpath); - if(d == 0) { - fprintf(stderr,"cannot open '%s': errno:%d\n", lpath, errno); - return -1; - } - - while((de = readdir(d))) { - char stat_path[PATH_MAX]; - char *name = de->d_name; - - if(name[0] == '.') { - if(name[1] == 0) continue; - if((name[1] == '.') && (name[2] == 0)) continue; - } - - /* - * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs - * always returns DT_UNKNOWN, so we just use stat() for all cases. - */ - if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) - continue; - strcpy(stat_path, lpath); - strcat(stat_path, de->d_name); - stat(stat_path, &st); - - if (S_ISDIR(st.st_mode)) { - ci = mkcopyinfo(lpath, rpath, name, 1); - ci->next = dirlist; - dirlist = ci; - } else { - ci = mkcopyinfo(lpath, rpath, name, 0); - if(lstat(ci->src, &st)) { - fprintf(stderr,"cannot stat '%s': errno:%d\n", ci->src, errno); - closedir(d); - - return -1; - } - if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { - fprintf(stderr, "skipping special file\n"); - free(ci); - } else { - ci->time = st.st_mtime; - ci->mode = st.st_mode; - ci->size = st.st_size; - ci->next = *filelist; - *filelist = ci; - } - } - } - - closedir(d); - - for(ci = dirlist; ci != 0; ci = next) { - next = ci->next; - local_build_list(filelist, ci->src, ci->dst); - free(ci); - } - - return 0; -} - - -static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps, int listonly) -{ - copyinfo *filelist = 0; - copyinfo *ci, *next; - int pushed = 0; - int skipped = 0; - - if((lpath[0] == 0) || (rpath[0] == 0)) return -1; - if(lpath[strlen(lpath) - 1] != '/') { - int tmplen = strlen(lpath)+2; - char *tmp = malloc(tmplen); - if(tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/",lpath); - lpath = tmp; - } - if(rpath[strlen(rpath) - 1] != '/') { - int tmplen = strlen(rpath)+2; - char *tmp = malloc(tmplen); - if(tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/",rpath); - rpath = tmp; - } - - if(local_build_list(&filelist, lpath, rpath)) { - return -1; - } - - if(checktimestamps){ - for(ci = filelist; ci != 0; ci = ci->next) { - if(sync_start_readtime(fd, ci->dst)) { - return 1; - } - } - for(ci = filelist; ci != 0; ci = ci->next) { - unsigned int timestamp, mode, size; - if(sync_finish_readtime(fd, ×tamp, &mode, &size)) - return 1; - if(size == ci->size) { - /* for links, we cannot update the atime/mtime */ - if((S_ISREG(ci->mode & mode) && timestamp == ci->time) || - (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) - ci->flag = 1; - } - } - } - for(ci = filelist; ci != 0; ci = next) { - next = ci->next; - if(ci->flag == 0) { - fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst); - if(!listonly && - sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){ - return 1; - } - pushed++; - } else { - skipped++; - } - free(ci); - } - - fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n", - pushed, (pushed == 1) ? "" : "s", - skipped, (skipped == 1) ? "" : "s"); - - return 0; -} - - -int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int isUtf8) -{ - struct stat st; - unsigned mode; - int fd; - char *tmp = NULL; - char *utf8 = NULL; - int ret = 0; - - fd = sdb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - if(stat(lpath, &st)) { - fprintf(stderr,"cannot stat '%s': errno:%d\n", lpath, errno); - sync_quit(fd); - return 1; - } - - if(S_ISDIR(st.st_mode)) { - BEGIN(); - if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) { - return 1; - } else { - END(get_basename(lpath)); - sync_quit(fd); - } - } else { - if(sync_readmode(fd, rpath, &mode)) { - return 1; - } - - if((mode != 0) && S_ISDIR(mode)) { - /* if we're copying a local file to a remote directory, - ** we *really* want to copy to remotedir + "/" + localfilename - */ - const char *name = sdb_dirstop(lpath); - if(name == 0) { - name = lpath; - } else { - name++; - } - int tmplen = strlen(name) + strlen(rpath) + 2; - tmp = malloc(strlen(name) + strlen(rpath) + 2); - if(tmp == 0) return 1; - snprintf(tmp, tmplen, "%s/%s", rpath, name); - if (isUtf8 != 0) { //ansi to utf8 - utf8 = ansi_to_utf8(tmp); - rpath = utf8; - } else { - rpath = tmp; - } - } - BEGIN(); - if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) { - ret = 1; - goto cleanup; - } else { - END(get_basename(lpath)); - sync_quit(fd); - ret = 0; - goto cleanup; - } - } - return 0; -cleanup: - if (tmp != NULL) { - free(tmp); - } - if (utf8 != NULL) { - free(utf8); - } - return ret; -} - - -typedef struct { - copyinfo **filelist; - copyinfo **dirlist; - const char *rpath; - const char *lpath; -} sync_ls_build_list_cb_args; - -void -sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time, - const char *name, void *cookie) -{ - sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie; - copyinfo *ci; - - if (S_ISDIR(mode)) { - copyinfo **dirlist = args->dirlist; - - /* Don't try recursing down "." or ".." */ - if (name[0] == '.') { - if (name[1] == '\0') return; - if ((name[1] == '.') && (name[2] == '\0')) return; - } - - ci = mkcopyinfo(args->rpath, args->lpath, name, 1); - ci->next = *dirlist; - *dirlist = ci; - } else if (S_ISREG(mode) || S_ISLNK(mode)) { - copyinfo **filelist = args->filelist; - - ci = mkcopyinfo(args->rpath, args->lpath, name, 0); - ci->time = time; - ci->mode = mode; - ci->size = size; - ci->next = *filelist; - *filelist = ci; - } else { - fprintf(stderr, "skipping special file '%s'\n", name); - } -} - -static int remote_build_list(int syncfd, copyinfo **filelist, - const char *rpath, const char *lpath) -{ - copyinfo *dirlist = NULL; - sync_ls_build_list_cb_args args; - - args.filelist = filelist; - args.dirlist = &dirlist; - args.rpath = rpath; - args.lpath = lpath; - - /* Put the files/dirs in rpath on the lists. */ - if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) { - return 1; - } - - /* Recurse into each directory we found. */ - while (dirlist != NULL) { - copyinfo *next = dirlist->next; - if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) { - return 1; - } - free(dirlist); - dirlist = next; - } - - return 0; -} - -static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, - int checktimestamps) -{ - copyinfo *filelist = 0; - copyinfo *ci, *next; - int pulled = 0; - int skipped = 0; - - /* Make sure that both directory paths end in a slash. */ - if (rpath[0] == 0 || lpath[0] == 0) return -1; - if (rpath[strlen(rpath) - 1] != '/') { - int tmplen = strlen(rpath) + 2; - char *tmp = malloc(tmplen); - if (tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/", rpath); - rpath = tmp; - } - if (lpath[strlen(lpath) - 1] != '/') { - int tmplen = strlen(lpath) + 2; - char *tmp = malloc(tmplen); - if (tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/", lpath); - lpath = tmp; - } - - fprintf(stderr, "pull: building file list...\n"); - /* Recursively build the list of files to copy. */ - if (remote_build_list(fd, &filelist, rpath, lpath)) { - return -1; - } - -#if 0 - if (checktimestamps) { - for (ci = filelist; ci != 0; ci = ci->next) { - if (sync_start_readtime(fd, ci->dst)) { - return 1; - } - } - for (ci = filelist; ci != 0; ci = ci->next) { - unsigned int timestamp, mode, size; - if (sync_finish_readtime(fd, ×tamp, &mode, &size)) - return 1; - if (size == ci->size) { - /* for links, we cannot update the atime/mtime */ - if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) || - (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) - ci->flag = 1; - } - } - } -#endif - for (ci = filelist; ci != 0; ci = next) { - next = ci->next; - if (ci->flag == 0) { - fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst); - if (sync_recv(fd, ci->src, ci->dst)) { - return 1; - } - pulled++; - } else { - skipped++; - } - free(ci); - } - - fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n", - pulled, (pulled == 1) ? "" : "s", - skipped, (skipped == 1) ? "" : "s"); - - return 0; -} - -int do_sync_pull(const char *rpath, const char *lpath) -{ - unsigned mode; - struct stat st; - - int fd; - - fd = sdb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - if(sync_readmode(fd, rpath, &mode)) { - return 1; - } - if(mode == 0) { - fprintf(stderr,"'%s': No such file or directory\n", rpath); - sync_quit(fd); - return 1; - } - - if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { - if(stat(lpath, &st) == 0) { - if(S_ISDIR(st.st_mode)) { - /* if we're copying a remote file to a local directory, - ** we *really* want to copy to localdir + "/" + remotefilename - */ - const char *name = sdb_dirstop(rpath); - if(name == 0) { - name = rpath; - } else { - name++; - } - int tmplen = strlen(name) + strlen(lpath) + 2; - char *tmp = malloc(tmplen); - if(tmp == 0) return 1; - snprintf(tmp, tmplen, "%s/%s", lpath, name); - lpath = tmp; - } - } - BEGIN(); - if(sync_recv(fd, rpath, lpath)) { - return 1; - } else { - END(get_basename(rpath)); - sync_quit(fd); - return 0; - } - } else if(S_ISDIR(mode)) { - BEGIN(); - if (copy_remote_dir_local(fd, rpath, lpath, 0)) { - return 1; - } else { - END(get_basename(rpath)); - sync_quit(fd); - return 0; - } - } else { - fprintf(stderr,"'%s': No such file or directory\n", rpath); - return 1; - } -} - -int do_sync_sync(const char *lpath, const char *rpath, int listonly) -{ - fprintf(stderr,"syncing %s...\n",rpath); - - int fd = sdb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", sdb_error()); - return 1; - } - - BEGIN(); - if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){ - return 1; - } else { - END(get_basename(lpath)); - sync_quit(fd); - return 0; - } -} diff --git a/src/get_my_path_darwin.c b/src/get_my_path_darwin.c deleted file mode 100644 index 880ccfd..0000000 --- a/src/get_my_path_darwin.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -#import -#include - -void get_my_path(char *s, size_t maxLen) -{ - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - CFDictionaryRef dict; - dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); - CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict, - CFSTR("CFBundleExecutable")); - CFStringGetCString(value, s, maxLen, kCFStringEncodingUTF8); -} - diff --git a/src/get_my_path_freebsd.c b/src/get_my_path_freebsd.c deleted file mode 100644 index 628a2b0..0000000 --- a/src/get_my_path_freebsd.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include - -void -get_my_path(char *exe, size_t maxLen) -{ - char proc[64]; - - snprintf(proc, sizeof(proc), "/proc/%d/file", getpid()); - - int err = readlink(proc, exe, maxLen - 1); - - exe[err > 0 ? err : 0] = '\0'; -} - diff --git a/src/get_my_path_linux.c b/src/get_my_path_linux.c deleted file mode 100644 index 08ba668..0000000 --- a/src/get_my_path_linux.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include - -void get_my_path(char *exe, size_t maxLen) -{ - char proc[64]; - snprintf(proc, sizeof proc, "/proc/%d/exe", getpid()); - int err = readlink(proc, exe, maxLen - 1); - if(err > 0) { - exe[err] = '\0'; - } else { - exe[0] = '\0'; - } -} - diff --git a/src/get_my_path_windows.c b/src/get_my_path_windows.c deleted file mode 100644 index 630e4d1..0000000 --- a/src/get_my_path_windows.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include - -void get_my_path(char *exe, size_t maxLen) -{ - char *r; - - /* XXX: should be GetModuleFileNameA */ - if (GetModuleFileName(NULL, exe, maxLen) > 0) { - r = strrchr(exe, '\\'); - if (r != NULL) - *r = '\0'; - } else { - exe[0] = '\0'; - } -} - diff --git a/src/jdwp_service.c b/src/jdwp_service.c deleted file mode 100644 index 6a85391..0000000 --- a/src/jdwp_service.c +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ -/* implement the "debug-ports" and "track-debug-ports" device services */ -#include "sysdeps.h" -#define TRACE_TAG TRACE_JDWP -#include "sdb.h" -#include -#include -#include -#include - -/* here's how these things work. - - when sdbd starts, it creates a unix server socket - named @vm-debug-control (@ is a shortcut for "first byte is zero" - to use the private namespace instead of the file system) - - when a new JDWP daemon thread starts in a new VM process, it creates - a connection to @vm-debug-control to announce its availability. - - - JDWP thread @vm-debug-control - | | - |-------------------------------> | - | hello I'm in process | - | | - | | - - the connection is kept alive. it will be closed automatically if - the JDWP process terminates (this allows sdbd to detect dead - processes). - - sdbd thus maintains a list of "active" JDWP processes. it can send - its content to clients through the "device:debug-ports" service, - or even updates through the "device:track-debug-ports" service. - - when a debugger wants to connect, it simply runs the command - equivalent to "sdb forward tcp: jdwp:" - - "jdwp:" is a new forward destination format used to target - a given JDWP process on the device. when sutch a request arrives, - sdbd does the following: - - - first, it calls socketpair() to create a pair of equivalent - sockets. - - - it attaches the first socket in the pair to a local socket - which is itself attached to the transport's remote socket: - - - - it sends the file descriptor of the second socket directly - to the JDWP process with the help of sendmsg() - - - JDWP thread @vm-debug-control - | | - | <----------------------| - | OK, try this file descriptor | - | | - | | - - then, the JDWP thread uses this new socket descriptor as its - pass-through connection to the debugger (and receives the - JDWP-Handshake message, answers to it, etc...) - - this gives the following graphics: - ____________________________________ - | | - | SDB Server (host) | - | | - Debugger <---> LocalSocket <----> RemoteSocket | - | ^^ | - |___________________________||_______| - || - Transport || - (TCP for emulator - USB for device) || - || - ___________________________||_______ - | || | - | SDBD (device) || | - | VV | - JDWP <======> LocalSocket <----> RemoteSocket | - | | - |____________________________________| - - due to the way sdb works, this doesn't need a special socket - type or fancy handling of socket termination if either the debugger - or the JDWP process closes the connection. - - THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN - TO HAVE A BETTER IDEA, LET ME KNOW - Digit - -**********************************************************************/ - -/** JDWP PID List Support Code - ** for each JDWP process, we record its pid and its connected socket - **/ - -#define MAX_OUT_FDS 4 - -#if !SDB_HOST - -#include -#include - -typedef struct JdwpProcess JdwpProcess; -struct JdwpProcess { - JdwpProcess* next; - JdwpProcess* prev; - int pid; - int socket; - fdevent* fde; - - char in_buff[4]; /* input character to read PID */ - int in_len; /* number from JDWP process */ - - int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */ - int out_count; /* to send to the JDWP process */ -}; - -static JdwpProcess _jdwp_list; - -static int -jdwp_process_list( char* buffer, int bufferlen ) -{ - char* end = buffer + bufferlen; - char* p = buffer; - JdwpProcess* proc = _jdwp_list.next; - - for ( ; proc != &_jdwp_list; proc = proc->next ) { - int len; - - /* skip transient connections */ - if (proc->pid < 0) - continue; - - len = snprintf(p, end-p, "%d\n", proc->pid); - if (p + len >= end) - break; - p += len; - } - p[0] = 0; - return (p - buffer); -} - - -static int -jdwp_process_list_msg( char* buffer, int bufferlen ) -{ - char head[5]; - int len = jdwp_process_list( buffer+4, bufferlen-4 ); - snprintf(head, sizeof head, "%04x", len); - memcpy(buffer, head, 4); - return len + 4; -} - - -static void jdwp_process_list_updated(void); - -static void -jdwp_process_free( JdwpProcess* proc ) -{ - if (proc) { - int n; - - proc->prev->next = proc->next; - proc->next->prev = proc->prev; - - if (proc->socket >= 0) { - sdb_shutdown(proc->socket); - sdb_close(proc->socket); - proc->socket = -1; - } - - if (proc->fde != NULL) { - fdevent_destroy(proc->fde); - proc->fde = NULL; - } - proc->pid = -1; - - for (n = 0; n < proc->out_count; n++) { - sdb_close(proc->out_fds[n]); - } - proc->out_count = 0; - - free(proc); - - jdwp_process_list_updated(); - } -} - - -static void jdwp_process_event(int, unsigned, void*); /* forward */ - - -static JdwpProcess* -jdwp_process_alloc( int socket ) -{ - JdwpProcess* proc = calloc(1,sizeof(*proc)); - - if (proc == NULL) { - D("not enough memory to create new JDWP process\n"); - return NULL; - } - - proc->socket = socket; - proc->pid = -1; - proc->next = proc; - proc->prev = proc; - - proc->fde = fdevent_create( socket, jdwp_process_event, proc ); - if (proc->fde == NULL) { - D("could not create fdevent for new JDWP process\n" ); - free(proc); - return NULL; - } - - proc->fde->state |= FDE_DONT_CLOSE; - proc->in_len = 0; - proc->out_count = 0; - - /* append to list */ - proc->next = &_jdwp_list; - proc->prev = proc->next->prev; - - proc->prev->next = proc; - proc->next->prev = proc; - - /* start by waiting for the PID */ - fdevent_add(proc->fde, FDE_READ); - - return proc; -} - - -static void -jdwp_process_event( int socket, unsigned events, void* _proc ) -{ - JdwpProcess* proc = _proc; - - if (events & FDE_READ) { - if (proc->pid < 0) { - /* read the PID as a 4-hexchar string */ - char* p = proc->in_buff + proc->in_len; - int size = 4 - proc->in_len; - char temp[5]; - while (size > 0) { - int len = recv( socket, p, size, 0 ); - if (len < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - return; - /* this can fail here if the JDWP process crashes very fast */ - D("weird unknown JDWP process failure: %s\n", - strerror(errno)); - - goto CloseProcess; - } - if (len == 0) { /* end of stream ? */ - D("weird end-of-stream from unknown JDWP process\n"); - goto CloseProcess; - } - p += len; - proc->in_len += len; - size -= len; - } - /* we have read 4 characters, now decode the pid */ - memcpy(temp, proc->in_buff, 4); - temp[4] = 0; - - if (sscanf( temp, "%04x", &proc->pid ) != 1) { - D("could not decode JDWP %p PID number: '%s'\n", proc, temp); - goto CloseProcess; - } - - /* all is well, keep reading to detect connection closure */ - D("Adding pid %d to jdwp process list\n", proc->pid); - jdwp_process_list_updated(); - } - else - { - /* the pid was read, if we get there it's probably because the connection - * was closed (e.g. the JDWP process exited or crashed) */ - char buf[32]; - - for (;;) { - int len = recv(socket, buf, sizeof(buf), 0); - - if (len <= 0) { - if (len < 0 && errno == EINTR) - continue; - if (len < 0 && errno == EAGAIN) - return; - else { - D("terminating JDWP %d connection: %s\n", proc->pid, - strerror(errno)); - break; - } - } - else { - D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n", - proc->pid, len ); - } - } - - CloseProcess: - if (proc->pid >= 0) - D( "remove pid %d to jdwp process list\n", proc->pid ); - jdwp_process_free(proc); - return; - } - } - - if (events & FDE_WRITE) { - D("trying to write to JDWP pid controli (count=%d first=%d) %d\n", - proc->pid, proc->out_count, proc->out_fds[0]); - if (proc->out_count > 0) { - int fd = proc->out_fds[0]; - int n, ret; - struct cmsghdr* cmsg; - struct msghdr msg; - struct iovec iov; - char dummy = '!'; - char buffer[sizeof(struct cmsghdr) + sizeof(int)]; - int flags; - - iov.iov_base = &dummy; - iov.iov_len = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - msg.msg_control = buffer; - msg.msg_controllen = sizeof(buffer); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = msg.msg_controllen; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - ((int*)CMSG_DATA(cmsg))[0] = fd; - - flags = fcntl(proc->socket,F_GETFL,0); - - if (flags == -1) { - D("failed to get cntl flags for socket %d: %s\n", - proc->pid, strerror(errno)); - goto CloseProcess; - - } - - if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) { - D("failed to remove O_NONBLOCK flag for socket %d: %s\n", - proc->pid, strerror(errno)); - goto CloseProcess; - } - - for (;;) { - ret = sendmsg(proc->socket, &msg, 0); - if (ret >= 0) { - sdb_close(fd); - break; - } - if (errno == EINTR) - continue; - D("sending new file descriptor to JDWP %d failed: %s\n", - proc->pid, strerror(errno)); - goto CloseProcess; - } - - D("sent file descriptor %d to JDWP process %d\n", - fd, proc->pid); - - for (n = 1; n < proc->out_count; n++) - proc->out_fds[n-1] = proc->out_fds[n]; - - if (fcntl(proc->socket, F_SETFL, flags) == -1) { - D("failed to set O_NONBLOCK flag for socket %d: %s\n", - proc->pid, strerror(errno)); - goto CloseProcess; - } - - if (--proc->out_count == 0) - fdevent_del( proc->fde, FDE_WRITE ); - } - } -} - - -int -create_jdwp_connection_fd(int pid) -{ - JdwpProcess* proc = _jdwp_list.next; - - D("looking for pid %d in JDWP process list\n", pid); - for ( ; proc != &_jdwp_list; proc = proc->next ) { - if (proc->pid == pid) { - goto FoundIt; - } - } - D("search failed !!\n"); - return -1; - -FoundIt: - { - int fds[2]; - - if (proc->out_count >= MAX_OUT_FDS) { - D("%s: too many pending JDWP connection for pid %d\n", - __FUNCTION__, pid); - return -1; - } - - if (sdb_socketpair(fds) < 0) { - D("%s: socket pair creation failed: %s\n", - __FUNCTION__, strerror(errno)); - return -1; - } - - proc->out_fds[ proc->out_count ] = fds[1]; - if (++proc->out_count == 1) - fdevent_add( proc->fde, FDE_WRITE ); - - return fds[0]; - } -} - -/** VM DEBUG CONTROL SOCKET - ** - ** we do implement a custom asocket to receive the data - **/ - -/* name of the debug control Unix socket */ -#define JDWP_CONTROL_NAME "\0jdwp-control" -#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME)-1) - -typedef struct { - int listen_socket; - fdevent* fde; - -} JdwpControl; - - -static void -jdwp_control_event(int s, unsigned events, void* user); - - -static int -jdwp_control_init( JdwpControl* control, - const char* sockname, - int socknamelen ) -{ - struct sockaddr_un addr; - socklen_t addrlen; - int s; - int maxpath = sizeof(addr.sun_path); - int pathlen = socknamelen; - - if (pathlen >= maxpath) { - D( "vm debug control socket name too long (%d extra chars)\n", - pathlen+1-maxpath ); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, sockname, socknamelen); - - s = socket( AF_UNIX, SOCK_STREAM, 0 ); - if (s < 0) { - D( "could not create vm debug control socket. %d: %s\n", - errno, strerror(errno)); - return -1; - } - - addrlen = (pathlen + sizeof(addr.sun_family)); - - if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) { - D( "could not bind vm debug control socket: %d: %s\n", - errno, strerror(errno) ); - sdb_close(s); - return -1; - } - - if ( listen(s, 4) < 0 ) { - D("listen failed in jdwp control socket: %d: %s\n", - errno, strerror(errno)); - sdb_close(s); - return -1; - } - - control->listen_socket = s; - - control->fde = fdevent_create(s, jdwp_control_event, control); - if (control->fde == NULL) { - D( "could not create fdevent for jdwp control socket\n" ); - sdb_close(s); - return -1; - } - - /* only wait for incoming connections */ - fdevent_add(control->fde, FDE_READ); - close_on_exec(s); - - D("jdwp control socket started (%d)\n", control->listen_socket); - return 0; -} - - -static void -jdwp_control_event( int s, unsigned events, void* _control ) -{ - JdwpControl* control = (JdwpControl*) _control; - - if (events & FDE_READ) { - struct sockaddr addr; - socklen_t addrlen = sizeof(addr); - int s = -1; - JdwpProcess* proc; - - do { - s = sdb_socket_accept( control->listen_socket, &addr, &addrlen ); - if (s < 0) { - if (errno == EINTR) - continue; - if (errno == ECONNABORTED) { - /* oops, the JDWP process died really quick */ - D("oops, the JDWP process died really quick\n"); - return; - } - /* the socket is probably closed ? */ - D( "weird accept() failed on jdwp control socket: %s\n", - strerror(errno) ); - return; - } - } - while (s < 0); - - proc = jdwp_process_alloc( s ); - if (proc == NULL) - return; - } -} - - -static JdwpControl _jdwp_control; - -/** "jdwp" local service implementation - ** this simply returns the list of known JDWP process pids - **/ - -typedef struct { - asocket socket; - int pass; -} JdwpSocket; - -static void -jdwp_socket_close( asocket* s ) -{ - asocket* peer = s->peer; - - remove_socket(s); - - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - free(s); -} - -static int -jdwp_socket_enqueue( asocket* s, apacket* p ) -{ - /* you can't write to this asocket */ - put_apacket(p); - s->peer->close(s->peer); - return -1; -} - - -static void -jdwp_socket_ready( asocket* s ) -{ - JdwpSocket* jdwp = (JdwpSocket*)s; - asocket* peer = jdwp->socket.peer; - - /* on the first call, send the list of pids, - * on the second one, close the connection - */ - if (jdwp->pass == 0) { - apacket* p = get_apacket(); - p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD); - peer->enqueue(peer, p); - jdwp->pass = 1; - } - else { - peer->close(peer); - } -} - -asocket* -create_jdwp_service_socket( void ) -{ - JdwpSocket* s = calloc(sizeof(*s),1); - - if (s == NULL) - return NULL; - - install_local_socket(&s->socket); - - s->socket.ready = jdwp_socket_ready; - s->socket.enqueue = jdwp_socket_enqueue; - s->socket.close = jdwp_socket_close; - s->pass = 0; - - return &s->socket; -} - -/** "track-jdwp" local service implementation - ** this periodically sends the list of known JDWP process pids - ** to the client... - **/ - -typedef struct JdwpTracker JdwpTracker; - -struct JdwpTracker { - asocket socket; - JdwpTracker* next; - JdwpTracker* prev; - int need_update; -}; - -static JdwpTracker _jdwp_trackers_list; - - -static void -jdwp_process_list_updated(void) -{ - char buffer[1024]; - int len; - JdwpTracker* t = _jdwp_trackers_list.next; - - len = jdwp_process_list_msg(buffer, sizeof(buffer)); - - for ( ; t != &_jdwp_trackers_list; t = t->next ) { - apacket* p = get_apacket(); - asocket* peer = t->socket.peer; - memcpy(p->data, buffer, len); - p->len = len; - peer->enqueue( peer, p ); - } -} - -static void -jdwp_tracker_close( asocket* s ) -{ - JdwpTracker* tracker = (JdwpTracker*) s; - asocket* peer = s->peer; - - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - - remove_socket(s); - - tracker->prev->next = tracker->next; - tracker->next->prev = tracker->prev; - - free(s); -} - -static void -jdwp_tracker_ready( asocket* s ) -{ - JdwpTracker* t = (JdwpTracker*) s; - - if (t->need_update) { - apacket* p = get_apacket(); - t->need_update = 0; - p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data)); - s->peer->enqueue(s->peer, p); - } -} - -static int -jdwp_tracker_enqueue( asocket* s, apacket* p ) -{ - /* you can't write to this socket */ - put_apacket(p); - s->peer->close(s->peer); - return -1; -} - - -asocket* -create_jdwp_tracker_service_socket( void ) -{ - JdwpTracker* t = calloc(sizeof(*t),1); - - if (t == NULL) - return NULL; - - t->next = &_jdwp_trackers_list; - t->prev = t->next->prev; - - t->next->prev = t; - t->prev->next = t; - - install_local_socket(&t->socket); - - t->socket.ready = jdwp_tracker_ready; - t->socket.enqueue = jdwp_tracker_enqueue; - t->socket.close = jdwp_tracker_close; - t->need_update = 1; - - return &t->socket; -} - - -int -init_jdwp(void) -{ - _jdwp_list.next = &_jdwp_list; - _jdwp_list.prev = &_jdwp_list; - - _jdwp_trackers_list.next = &_jdwp_trackers_list; - _jdwp_trackers_list.prev = &_jdwp_trackers_list; - - return jdwp_control_init( &_jdwp_control, - JDWP_CONTROL_NAME, - JDWP_CONTROL_NAME_LEN ); -} - -#endif /* !SDB_HOST */ diff --git a/src/sdb.c b/src/sdb.c index 0120c7b..f8c51fb 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -44,8 +44,6 @@ #if !SDB_HOST #include #define SDB_PIDPATH "/tmp/.sdbd.pid" -#else -#include "usb_vendors.h" #endif #include #include @@ -2224,7 +2222,6 @@ int sdb_main(int is_daemon, int server_port) #if SDB_HOST HOST = 1; - usb_vendors_init(); usb_init(); local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT); diff --git a/src/sdb_client.c b/src/sdb_client.c deleted file mode 100644 index 08766cd..0000000 --- a/src/sdb_client.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include -#include -#include -// tizen specific #include -#include -#include - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_SDB -#include "sdb_client.h" - -static transport_type __sdb_transport = kTransportAny; -static const char* __sdb_serial = NULL; - -static int __sdb_server_port = DEFAULT_SDB_PORT; - -void sdb_set_transport(transport_type type, const char* serial) -{ - __sdb_transport = type; - __sdb_serial = serial; -} - -void sdb_set_tcp_specifics(int server_port) -{ - __sdb_server_port = server_port; -} - -int sdb_get_emulator_console_port(void) -{ - const char* serial = __sdb_serial; - int port; - - if (serial == NULL) { - /* if no specific device was specified, we need to look at */ - /* the list of connected devices, and extract an emulator */ - /* name from it. two emulators is an error */ - char* tmp = sdb_query("host:devices"); - char* p = tmp; - if(!tmp) { - printf("no emulator connected\n"); - return -1; - } - while (*p) { - char* q = strchr(p, '\n'); - if (q != NULL) - *q++ = 0; - else - q = p + strlen(p); - - if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) { - if (serial != NULL) { /* more than one emulator listed */ - free(tmp); - return -2; - } - serial = p; - } - - p = q; - } - free(tmp); - - if (serial == NULL) - return -1; /* no emulator found */ - } - else { - if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0) - return -1; /* not an emulator */ - } - - serial += sizeof(LOCAL_CLIENT_PREFIX)-1; - port = strtol(serial, NULL, 10); - return port; -} - -static char __sdb_error[256] = { 0 }; - -const char *sdb_error(void) -{ - return __sdb_error; -} - -static int switch_socket_transport(int fd) -{ - char service[64]; - char tmp[5]; - int len; - - if (__sdb_serial) - snprintf(service, sizeof service, "host:transport:%s", __sdb_serial); - else { - char* transport_type = "???"; - - switch (__sdb_transport) { - case kTransportUsb: - transport_type = "transport-usb"; - break; - case kTransportLocal: - transport_type = "transport-local"; - break; - case kTransportAny: - transport_type = "transport-any"; - break; - case kTransportHost: - // no switch necessary - return 0; - break; - } - - snprintf(service, sizeof service, "host:%s", transport_type); - } - len = strlen(service); - snprintf(tmp, sizeof tmp, "%04x", len); - - if(writex(fd, tmp, 4) || writex(fd, service, len)) { - strcpy(__sdb_error, "write failure during connection"); - sdb_close(fd); - return -1; - } - D("Switch transport in progress\n"); - - if(sdb_status(fd)) { - sdb_close(fd); - D("Switch transport failed\n"); - return -1; - } - D("Switch transport success\n"); - return 0; -} - -int sdb_status(int fd) -{ - unsigned char buf[5]; - unsigned len; - - if(readx(fd, buf, 4)) { - strcpy(__sdb_error, "protocol fault (no status)"); - return -1; - } - - if(!memcmp(buf, "OKAY", 4)) { - return 0; - } - - if(memcmp(buf, "FAIL", 4)) { - sprintf(__sdb_error, - "protocol fault (status %02x %02x %02x %02x?!)", - buf[0], buf[1], buf[2], buf[3]); - return -1; - } - - if(readx(fd, buf, 4)) { - strcpy(__sdb_error, "protocol fault (status len)"); - return -1; - } - buf[4] = 0; - len = strtoul((char*)buf, 0, 16); - if(len > 255) len = 255; - if(readx(fd, __sdb_error, len)) { - strcpy(__sdb_error, "protocol fault (status read)"); - return -1; - } - __sdb_error[len] = 0; - return -1; -} - -int _sdb_connect(const char *service) -{ - char tmp[5]; - int len; - int fd; - - D("_sdb_connect: %s\n", service); - len = strlen(service); - if((len < 1) || (len > 1024)) { - strcpy(__sdb_error, "service name too long"); - return -1; - } - snprintf(tmp, sizeof tmp, "%04x", len); - - fd = socket_loopback_client(__sdb_server_port, SOCK_STREAM); - if(fd < 0) { - strcpy(__sdb_error, "cannot connect to daemon"); - return -2; - } - - if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) { - return -1; - } - - if(writex(fd, tmp, 4) || writex(fd, service, len)) { - strcpy(__sdb_error, "write failure during connection"); - sdb_close(fd); - return -1; - } - - if(sdb_status(fd)) { - sdb_close(fd); - return -1; - } - - D("_sdb_connect: return fd %d\n", fd); - return fd; -} - -int sdb_connect(const char *service) -{ - // first query the sdb server's version - int fd = _sdb_connect("host:version"); - - D("sdb_connect: service %s\n", service); - if(fd == -2) { - fprintf(stdout,"* daemon not running. starting it now on port %d *\n", - __sdb_server_port); - start_server: - if(launch_server(__sdb_server_port)) { - fprintf(stderr,"* failed to start daemon *\n"); - return -1; - } else { - fprintf(stdout,"* daemon started successfully *\n"); - } - /* give the server some time to start properly and detect devices */ - sdb_sleep_ms(3000); - // fall through to _sdb_connect - } else { - // if server was running, check its version to make sure it is not out of date - char buf[100]; - int n; - int version = SDB_SERVER_VERSION - 1; - - // if we have a file descriptor, then parse version result - if(fd >= 0) { - if(readx(fd, buf, 4)) goto error; - - buf[4] = 0; - n = strtoul(buf, 0, 16); - if(n > (int)sizeof(buf)) goto error; - if(readx(fd, buf, n)) goto error; - sdb_close(fd); - - if (sscanf(buf, "%04x", &version) != 1) goto error; - } else { - // if fd is -1, then check for "unknown host service", - // which would indicate a version of sdb that does not support the version command - if (strcmp(__sdb_error, "unknown host service") != 0) - return fd; - } - - if(version != SDB_SERVER_VERSION) { - printf("sdb server is out of date. killing...\n"); - fd = _sdb_connect("host:kill"); - sdb_close(fd); - - /* XXX can we better detect its death? */ - sdb_sleep_ms(2000); - goto start_server; - } - } - - // if the command is start-server, we are done. - if (!strcmp(service, "host:start-server")) - return 0; - - fd = _sdb_connect(service); - if(fd == -2) { - fprintf(stderr,"** daemon still not running"); - } - D("sdb_connect: return fd %d\n", fd); - - return fd; -error: - sdb_close(fd); - return -1; -} - - -int sdb_command(const char *service) -{ - int fd = sdb_connect(service); - if(fd < 0) { - return -1; - } - - if(sdb_status(fd)) { - sdb_close(fd); - return -1; - } - - return 0; -} - -char *sdb_query(const char *service) -{ - char buf[5]; - unsigned n; - char *tmp; - - D("sdb_query: %s\n", service); - int fd = sdb_connect(service); - if(fd < 0) { - fprintf(stderr,"error: %s\n", __sdb_error); - return 0; - } - - if(readx(fd, buf, 4)) goto oops; - - buf[4] = 0; - n = strtoul(buf, 0, 16); - if(n > 1024) goto oops; - - tmp = malloc(n + 1); - if(tmp == 0) goto oops; - - if(readx(fd, tmp, n) == 0) { - tmp[n] = 0; - sdb_close(fd); - return tmp; - } - free(tmp); - -oops: - sdb_close(fd); - return 0; -} diff --git a/src/sdb_client.h b/src/sdb_client.h deleted file mode 100644 index 86e9ef1..0000000 --- a/src/sdb_client.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -#ifndef _SDB_CLIENT_H_ -#define _SDB_CLIENT_H_ - -#include "sdb.h" - -/* connect to sdb, connect to the named service, and return -** a valid fd for interacting with that service upon success -** or a negative number on failure -*/ -int sdb_connect(const char *service); -int _sdb_connect(const char *service); - -/* connect to sdb, connect to the named service, return 0 if -** the connection succeeded AND the service returned OKAY -*/ -int sdb_command(const char *service); - -/* connect to sdb, connect to the named service, return -** a malloc'd string of its response upon success or NULL -** on failure. -*/ - -char *sdb_query(const char *service); - -/* Set the preferred transport to connect to. -*/ -void sdb_set_transport(transport_type type, const char* serial); - -/* Set TCP specifics of the transport to use -*/ -void sdb_set_tcp_specifics(int server_port); - -/* Return the console port of the currently connected emulator (if any) - * of -1 if there is no emulator, and -2 if there is more than one. - * assumes sdb_set_transport() was alled previously... - */ -int sdb_get_emulator_console_port(void); - -/* send commands to the current emulator instance. will fail if there - * is zero, or more than one emulator connected (or if you use -s - * with a that does not designate an emulator) - */ -int sdb_send_emulator_command(int argc, char** argv); - -/* return verbose error string from last operation */ -const char *sdb_error(void); - -/* read a standard sdb status response (OKAY|FAIL) and -** return 0 in the event of OKAY, -1 in the event of FAIL -** or protocol error -*/ -int sdb_status(int fd); - -#endif diff --git a/src/sysdeps_win32.c b/src/sysdeps_win32.c deleted file mode 100644 index 97399bf..0000000 --- a/src/sysdeps_win32.c +++ /dev/null @@ -1,1982 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 "sysdeps.h" -#include -#include -#include -#include -#define TRACE_TAG TRACE_SYSDEPS -#include "sdb.h" - -extern void fatal(const char *fmt, ...); - -#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0) - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** replaces libs/cutils/load_file.c *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -void *load_file(const char *fn, unsigned *_sz) -{ - HANDLE file; - char *data; - DWORD file_size; - - file = CreateFile( fn, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - 0, - NULL ); - - if (file == INVALID_HANDLE_VALUE) - return NULL; - - file_size = GetFileSize( file, NULL ); - data = NULL; - - if (file_size > 0) { - data = (char*) malloc( file_size + 1 ); - if (data == NULL) { - D("load_file: could not allocate %ld bytes\n", file_size ); - file_size = 0; - } else { - DWORD out_bytes; - - if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) || - out_bytes != file_size ) - { - D("load_file: could not read %ld bytes from '%s'\n", file_size, fn); - free(data); - data = NULL; - file_size = 0; - } - } - } - CloseHandle( file ); - - *_sz = (unsigned) file_size; - return data; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** common file descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -typedef const struct FHClassRec_* FHClass; - -typedef struct FHRec_* FH; - -typedef struct EventHookRec_* EventHook; - -typedef struct FHClassRec_ -{ - void (*_fh_init) ( FH f ); - int (*_fh_close)( FH f ); - int (*_fh_lseek)( FH f, int pos, int origin ); - int (*_fh_read) ( FH f, void* buf, int len ); - int (*_fh_write)( FH f, const void* buf, int len ); - void (*_fh_hook) ( FH f, int events, EventHook hook ); - -} FHClassRec; - -/* used to emulate unix-domain socket pairs */ -typedef struct SocketPairRec_* SocketPair; - -typedef struct FHRec_ -{ - FHClass clazz; - int used; - int eof; - union { - HANDLE handle; - SOCKET socket; - SocketPair pair; - } u; - - HANDLE event; - int mask; - - char name[32]; - -} FHRec; - -#define fh_handle u.handle -#define fh_socket u.socket -#define fh_pair u.pair - -#define WIN32_FH_BASE 100 - -#define WIN32_MAX_FHS 128 - -static sdb_mutex_t _win32_lock; -static FHRec _win32_fhs[ WIN32_MAX_FHS ]; -static int _win32_fh_count; - -static FH -_fh_from_int( int fd ) -{ - FH f; - - fd -= WIN32_FH_BASE; - - if (fd < 0 || fd >= _win32_fh_count) { - D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE ); - errno = EBADF; - return NULL; - } - - f = &_win32_fhs[fd]; - - if (f->used == 0) { - D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE ); - errno = EBADF; - return NULL; - } - - return f; -} - - -static int -_fh_to_int( FH f ) -{ - if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS) - return (int)(f - _win32_fhs) + WIN32_FH_BASE; - - return -1; -} - -static FH -_fh_alloc( FHClass clazz ) -{ - int nn; - FH f = NULL; - - sdb_mutex_lock( &_win32_lock ); - - if (_win32_fh_count < WIN32_MAX_FHS) { - f = &_win32_fhs[ _win32_fh_count++ ]; - goto Exit; - } - - for (nn = 0; nn < WIN32_MAX_FHS; nn++) { - if ( _win32_fhs[nn].clazz == NULL) { - f = &_win32_fhs[nn]; - goto Exit; - } - } - D( "_fh_alloc: no more free file descriptors\n" ); -Exit: - if (f) { - f->clazz = clazz; - f->used = 1; - f->eof = 0; - clazz->_fh_init(f); - } - sdb_mutex_unlock( &_win32_lock ); - return f; -} - - -static int -_fh_close( FH f ) -{ - if ( f->used ) { - f->clazz->_fh_close( f ); - f->used = 0; - f->eof = 0; - f->clazz = NULL; - } - return 0; -} - -/* forward definitions */ -static const FHClassRec _fh_file_class; -static const FHClassRec _fh_socket_class; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** file-based descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -static void -_fh_file_init( FH f ) -{ - f->fh_handle = INVALID_HANDLE_VALUE; -} - -static int -_fh_file_close( FH f ) -{ - CloseHandle( f->fh_handle ); - f->fh_handle = INVALID_HANDLE_VALUE; - return 0; -} - -static int -_fh_file_read( FH f, void* buf, int len ) -{ - DWORD read_bytes; - - if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) { - D( "sdb_read: could not read %d bytes from %s\n", len, f->name ); - errno = EIO; - return -1; - } else if (read_bytes < (DWORD)len) { - f->eof = 1; - } - return (int)read_bytes; -} - -static int -_fh_file_write( FH f, const void* buf, int len ) -{ - DWORD wrote_bytes; - - if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) { - D( "sdb_file_write: could not write %d bytes from %s\n", len, f->name ); - errno = EIO; - return -1; - } else if (wrote_bytes < (DWORD)len) { - f->eof = 1; - } - return (int)wrote_bytes; -} - -static int -_fh_file_lseek( FH f, int pos, int origin ) -{ - DWORD method; - DWORD result; - - switch (origin) - { - case SEEK_SET: method = FILE_BEGIN; break; - case SEEK_CUR: method = FILE_CURRENT; break; - case SEEK_END: method = FILE_END; break; - default: - errno = EINVAL; - return -1; - } - - result = SetFilePointer( f->fh_handle, pos, NULL, method ); - if (result == INVALID_SET_FILE_POINTER) { - errno = EIO; - return -1; - } else { - f->eof = 0; - } - return (int)result; -} - -static void _fh_file_hook( FH f, int event, EventHook eventhook ); /* forward */ - -static const FHClassRec _fh_file_class = -{ - _fh_file_init, - _fh_file_close, - _fh_file_lseek, - _fh_file_read, - _fh_file_write, - _fh_file_hook -}; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** file-based descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -int sdb_open(const char* path, int options) -{ - FH f; - - DWORD desiredAccess = 0; - DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - switch (options) { - case O_RDONLY: - desiredAccess = GENERIC_READ; - break; - case O_WRONLY: - desiredAccess = GENERIC_WRITE; - break; - case O_RDWR: - desiredAccess = GENERIC_READ | GENERIC_WRITE; - break; - default: - D("sdb_open: invalid options (0x%0x)\n", options); - errno = EINVAL; - return -1; - } - - f = _fh_alloc( &_fh_file_class ); - if ( !f ) { - errno = ENOMEM; - return -1; - } - - f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING, - 0, NULL ); - - if ( f->fh_handle == INVALID_HANDLE_VALUE ) { - _fh_close(f); - D( "sdb_open: could not open '%s':", path ); - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: - D( "file not found\n" ); - errno = ENOENT; - return -1; - - case ERROR_PATH_NOT_FOUND: - D( "path not found\n" ); - errno = ENOTDIR; - return -1; - - default: - D( "unknown error\n" ); - errno = ENOENT; - return -1; - } - } - - snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path ); - D( "sdb_open: '%s' => fd %d\n", path, _fh_to_int(f) ); - return _fh_to_int(f); -} - -/* ignore mode on Win32 */ -int sdb_creat(const char* path, int mode) -{ - FH f; - - f = _fh_alloc( &_fh_file_class ); - if ( !f ) { - errno = ENOMEM; - return -1; - } - - f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL ); - - if ( f->fh_handle == INVALID_HANDLE_VALUE ) { - _fh_close(f); - D( "sdb_creat: could not open '%s':", path ); - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: - D( "file not found\n" ); - errno = ENOENT; - return -1; - - case ERROR_PATH_NOT_FOUND: - D( "path not found\n" ); - errno = ENOTDIR; - return -1; - - default: - D( "unknown error\n" ); - errno = ENOENT; - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path ); - D( "sdb_creat: '%s' => fd %d\n", path, _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int sdb_read(int fd, void* buf, int len) -{ - FH f = _fh_from_int(fd); - - if (f == NULL) { - return -1; - } - - return f->clazz->_fh_read( f, buf, len ); -} - - -int sdb_write(int fd, const void* buf, int len) -{ - FH f = _fh_from_int(fd); - - if (f == NULL) { - return -1; - } - - return f->clazz->_fh_write(f, buf, len); -} - - -int sdb_lseek(int fd, int pos, int where) -{ - FH f = _fh_from_int(fd); - - if (!f) { - return -1; - } - - return f->clazz->_fh_lseek(f, pos, where); -} - - -int sdb_shutdown(int fd) -{ - FH f = _fh_from_int(fd); - - if (!f) { - return -1; - } - - D( "sdb_shutdown: %s\n", f->name); - shutdown( f->fh_socket, SD_BOTH ); - return 0; -} - - -int sdb_close(int fd) -{ - FH f = _fh_from_int(fd); - - if (!f) { - return -1; - } - - D( "sdb_close: %s\n", f->name); - _fh_close(f); - return 0; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** socket-based file descriptors *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -static void -_socket_set_errno( void ) -{ - switch (WSAGetLastError()) { - case 0: errno = 0; break; - case WSAEWOULDBLOCK: errno = EAGAIN; break; - case WSAEINTR: errno = EINTR; break; - default: - D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() ); - errno = EINVAL; - } -} - -static void -_fh_socket_init( FH f ) -{ - f->fh_socket = INVALID_SOCKET; - f->event = WSACreateEvent(); - f->mask = 0; -} - -static int -_fh_socket_close( FH f ) -{ - /* gently tell any peer that we're closing the socket */ - shutdown( f->fh_socket, SD_BOTH ); - closesocket( f->fh_socket ); - f->fh_socket = INVALID_SOCKET; - CloseHandle( f->event ); - f->mask = 0; - return 0; -} - -static int -_fh_socket_lseek( FH f, int pos, int origin ) -{ - errno = EPIPE; - return -1; -} - -static int -_fh_socket_read( FH f, void* buf, int len ) -{ - int result = recv( f->fh_socket, buf, len, 0 ); - if (result == SOCKET_ERROR) { - _socket_set_errno(); - result = -1; - } - return result; -} - -static int -_fh_socket_write( FH f, const void* buf, int len ) -{ - int result = send( f->fh_socket, buf, len, 0 ); - if (result == SOCKET_ERROR) { - _socket_set_errno(); - result = -1; - } - return result; -} - -static void _fh_socket_hook( FH f, int event, EventHook hook ); /* forward */ - -static const FHClassRec _fh_socket_class = -{ - _fh_socket_init, - _fh_socket_close, - _fh_socket_lseek, - _fh_socket_read, - _fh_socket_write, - _fh_socket_hook -}; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** replacement for libs/cutils/socket_xxxx.c *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -#include - -static int _winsock_init; - -static void -_cleanup_winsock( void ) -{ - WSACleanup(); -} - -static void -_init_winsock( void ) -{ - if (!_winsock_init) { - WSADATA wsaData; - int rc = WSAStartup( MAKEWORD(2,2), &wsaData); - if (rc != 0) { - fatal( "sdb: could not initialize Winsock\n" ); - } - atexit( _cleanup_winsock ); - _winsock_init = 1; - } -} - -int socket_loopback_client(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) { - D("socket_loopback_client: could not create socket\n" ); - _fh_close(f); - return -1; - } - - f->fh_socket = s; - if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port ); - _fh_close(f); - return -1; - } - snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - -#define LISTEN_BACKLOG 4 - -int socket_loopback_server(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - int n; - - if (!f) { - return -1; - } - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) return -1; - - f->fh_socket = s; - - n = 1; - setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n)); - - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - if (type == SOCK_STREAM) { - int ret; - - ret = listen(s, LISTEN_BACKLOG); - if (ret < 0) { - _fh_close(f); - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int socket_network_client(const char *host, int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct hostent *hp; - struct sockaddr_in addr; - SOCKET s; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - hp = gethostbyname(host); - if(hp == 0) { - _fh_close(f); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = hp->h_addrtype; - addr.sin_port = htons(port); - memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); - - s = socket(hp->h_addrtype, type, 0); - if(s == INVALID_SOCKET) { - _fh_close(f); - return -1; - } - f->fh_socket = s; - - if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - - snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int socket_inaddr_any_server(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - int n; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) { - _fh_close(f); - return -1; - } - - f->fh_socket = s; - n = 1; - setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n)); - - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - - if (type == SOCK_STREAM) { - int ret; - - ret = listen(s, LISTEN_BACKLOG); - if (ret < 0) { - _fh_close(f); - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - -#undef accept -int sdb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) -{ - FH serverfh = _fh_from_int(serverfd); - FH fh; - - if ( !serverfh || serverfh->clazz != &_fh_socket_class ) { - D( "sdb_socket_accept: invalid fd %d\n", serverfd ); - return -1; - } - - fh = _fh_alloc( &_fh_socket_class ); - if (!fh) { - D( "sdb_socket_accept: not enough memory to allocate accepted socket descriptor\n" ); - return -1; - } - - fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen ); - if (fh->fh_socket == INVALID_SOCKET) { - _fh_close( fh ); - D( "sdb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() ); - return -1; - } - - snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name ); - D( "sdb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) ); - return _fh_to_int(fh); -} - - -void disable_tcp_nagle(int fd) -{ - FH fh = _fh_from_int(fd); - int on; - - if ( !fh || fh->clazz != &_fh_socket_class ) - return; - - setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) ); -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** emulated socketpairs *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -/* we implement socketpairs directly in use space for the following reasons: - * - it avoids copying data from/to the Nt kernel - * - it allows us to implement fdevent hooks easily and cheaply, something - * that is not possible with standard Win32 pipes !! - * - * basically, we use two circular buffers, each one corresponding to a given - * direction. - * - * each buffer is implemented as two regions: - * - * region A which is (a_start,a_end) - * region B which is (0, b_end) with b_end <= a_start - * - * an empty buffer has: a_start = a_end = b_end = 0 - * - * a_start is the pointer where we start reading data - * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE, - * then you start writing at b_end - * - * the buffer is full when b_end == a_start && a_end == BUFFER_SIZE - * - * there is room when b_end < a_start || a_end < BUFER_SIZE - * - * when reading, a_start is incremented, it a_start meets a_end, then - * we do: a_start = 0, a_end = b_end, b_end = 0, and keep going on.. - */ - -#define BIP_BUFFER_SIZE 4096 - -#if 0 -#include -# define BIPD(x) D x -# define BIPDUMP bip_dump_hex - -static void bip_dump_hex( const unsigned char* ptr, size_t len ) -{ - int nn, len2 = len; - - if (len2 > 8) len2 = 8; - - for (nn = 0; nn < len2; nn++) - printf("%02x", ptr[nn]); - printf(" "); - - for (nn = 0; nn < len2; nn++) { - int c = ptr[nn]; - if (c < 32 || c > 127) - c = '.'; - printf("%c", c); - } - printf("\n"); - fflush(stdout); -} - -#else -# define BIPD(x) do {} while (0) -# define BIPDUMP(p,l) BIPD(p) -#endif - -typedef struct BipBufferRec_ -{ - int a_start; - int a_end; - int b_end; - int fdin; - int fdout; - int closed; - int can_write; /* boolean */ - HANDLE evt_write; /* event signaled when one can write to a buffer */ - int can_read; /* boolean */ - HANDLE evt_read; /* event signaled when one can read from a buffer */ - CRITICAL_SECTION lock; - unsigned char buff[ BIP_BUFFER_SIZE ]; - -} BipBufferRec, *BipBuffer; - -static void -bip_buffer_init( BipBuffer buffer ) -{ - D( "bit_buffer_init %p\n", buffer ); - buffer->a_start = 0; - buffer->a_end = 0; - buffer->b_end = 0; - buffer->can_write = 1; - buffer->can_read = 0; - buffer->fdin = 0; - buffer->fdout = 0; - buffer->closed = 0; - buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL ); - buffer->evt_read = CreateEvent( NULL, TRUE, FALSE, NULL ); - InitializeCriticalSection( &buffer->lock ); -} - -static void -bip_buffer_close( BipBuffer bip ) -{ - bip->closed = 1; - - if (!bip->can_read) { - SetEvent( bip->evt_read ); - } - if (!bip->can_write) { - SetEvent( bip->evt_write ); - } -} - -static void -bip_buffer_done( BipBuffer bip ) -{ - BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout )); - CloseHandle( bip->evt_read ); - CloseHandle( bip->evt_write ); - DeleteCriticalSection( &bip->lock ); -} - -static int -bip_buffer_write( BipBuffer bip, const void* src, int len ) -{ - int avail, count = 0; - - if (len <= 0) - return 0; - - BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len )); - BIPDUMP( src, len ); - - EnterCriticalSection( &bip->lock ); - - while (!bip->can_write) { - int ret; - LeaveCriticalSection( &bip->lock ); - - if (bip->closed) { - errno = EPIPE; - return -1; - } - /* spinlocking here is probably unfair, but let's live with it */ - ret = WaitForSingleObject( bip->evt_write, INFINITE ); - if (ret != WAIT_OBJECT_0) { /* buffer probably closed */ - D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() ); - return 0; - } - if (bip->closed) { - errno = EPIPE; - return -1; - } - EnterCriticalSection( &bip->lock ); - } - - BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - avail = BIP_BUFFER_SIZE - bip->a_end; - if (avail > 0) - { - /* we can append to region A */ - if (avail > len) - avail = len; - - memcpy( bip->buff + bip->a_end, src, avail ); - src += avail; - count += avail; - len -= avail; - - bip->a_end += avail; - if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) { - bip->can_write = 0; - ResetEvent( bip->evt_write ); - goto Exit; - } - } - - if (len == 0) - goto Exit; - - avail = bip->a_start - bip->b_end; - assert( avail > 0 ); /* since can_write is TRUE */ - - if (avail > len) - avail = len; - - memcpy( bip->buff + bip->b_end, src, avail ); - count += avail; - bip->b_end += avail; - - if (bip->b_end == bip->a_start) { - bip->can_write = 0; - ResetEvent( bip->evt_write ); - } - -Exit: - assert( count > 0 ); - - if ( !bip->can_read ) { - bip->can_read = 1; - SetEvent( bip->evt_read ); - } - - BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", - bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); - LeaveCriticalSection( &bip->lock ); - - return count; - } - -static int -bip_buffer_read( BipBuffer bip, void* dst, int len ) -{ - int avail, count = 0; - - if (len <= 0) - return 0; - - BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - EnterCriticalSection( &bip->lock ); - while ( !bip->can_read ) - { -#if 0 - LeaveCriticalSection( &bip->lock ); - errno = EAGAIN; - return -1; -#else - int ret; - LeaveCriticalSection( &bip->lock ); - - if (bip->closed) { - errno = EPIPE; - return -1; - } - - ret = WaitForSingleObject( bip->evt_read, INFINITE ); - if (ret != WAIT_OBJECT_0) { /* probably closed buffer */ - D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError()); - return 0; - } - if (bip->closed) { - errno = EPIPE; - return -1; - } - EnterCriticalSection( &bip->lock ); -#endif - } - - BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - avail = bip->a_end - bip->a_start; - assert( avail > 0 ); /* since can_read is TRUE */ - - if (avail > len) - avail = len; - - memcpy( dst, bip->buff + bip->a_start, avail ); - dst += avail; - count += avail; - len -= avail; - - bip->a_start += avail; - if (bip->a_start < bip->a_end) - goto Exit; - - bip->a_start = 0; - bip->a_end = bip->b_end; - bip->b_end = 0; - - avail = bip->a_end; - if (avail > 0) { - if (avail > len) - avail = len; - memcpy( dst, bip->buff, avail ); - count += avail; - bip->a_start += avail; - - if ( bip->a_start < bip->a_end ) - goto Exit; - - bip->a_start = bip->a_end = 0; - } - - bip->can_read = 0; - ResetEvent( bip->evt_read ); - -Exit: - assert( count > 0 ); - - if (!bip->can_write ) { - bip->can_write = 1; - SetEvent( bip->evt_write ); - } - - BIPDUMP( (const unsigned char*)dst - count, count ); - BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", - bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); - LeaveCriticalSection( &bip->lock ); - - return count; -} - -typedef struct SocketPairRec_ -{ - BipBufferRec a2b_bip; - BipBufferRec b2a_bip; - FH a_fd; - int used; - -} SocketPairRec; - -void _fh_socketpair_init( FH f ) -{ - f->fh_pair = NULL; -} - -static int -_fh_socketpair_close( FH f ) -{ - if ( f->fh_pair ) { - SocketPair pair = f->fh_pair; - - if ( f == pair->a_fd ) { - pair->a_fd = NULL; - } - - bip_buffer_close( &pair->b2a_bip ); - bip_buffer_close( &pair->a2b_bip ); - - if ( --pair->used == 0 ) { - bip_buffer_done( &pair->b2a_bip ); - bip_buffer_done( &pair->a2b_bip ); - free( pair ); - } - f->fh_pair = NULL; - } - return 0; -} - -static int -_fh_socketpair_lseek( FH f, int pos, int origin ) -{ - errno = ESPIPE; - return -1; -} - -static int -_fh_socketpair_read( FH f, void* buf, int len ) -{ - SocketPair pair = f->fh_pair; - BipBuffer bip; - - if (!pair) - return -1; - - if ( f == pair->a_fd ) - bip = &pair->b2a_bip; - else - bip = &pair->a2b_bip; - - return bip_buffer_read( bip, buf, len ); -} - -static int -_fh_socketpair_write( FH f, const void* buf, int len ) -{ - SocketPair pair = f->fh_pair; - BipBuffer bip; - - if (!pair) - return -1; - - if ( f == pair->a_fd ) - bip = &pair->a2b_bip; - else - bip = &pair->b2a_bip; - - return bip_buffer_write( bip, buf, len ); -} - - -static void _fh_socketpair_hook( FH f, int event, EventHook hook ); /* forward */ - -static const FHClassRec _fh_socketpair_class = -{ - _fh_socketpair_init, - _fh_socketpair_close, - _fh_socketpair_lseek, - _fh_socketpair_read, - _fh_socketpair_write, - _fh_socketpair_hook -}; - - -int sdb_socketpair( int sv[2] ) -{ - FH fa, fb; - SocketPair pair; - - fa = _fh_alloc( &_fh_socketpair_class ); - fb = _fh_alloc( &_fh_socketpair_class ); - - if (!fa || !fb) - goto Fail; - - pair = malloc( sizeof(*pair) ); - if (pair == NULL) { - D("sdb_socketpair: not enough memory to allocate pipes\n" ); - goto Fail; - } - - bip_buffer_init( &pair->a2b_bip ); - bip_buffer_init( &pair->b2a_bip ); - - fa->fh_pair = pair; - fb->fh_pair = pair; - pair->used = 2; - pair->a_fd = fa; - - sv[0] = _fh_to_int(fa); - sv[1] = _fh_to_int(fb); - - pair->a2b_bip.fdin = sv[0]; - pair->a2b_bip.fdout = sv[1]; - pair->b2a_bip.fdin = sv[1]; - pair->b2a_bip.fdout = sv[0]; - - snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] ); - snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] ); - D( "sdb_socketpair: returns (%d, %d)\n", sv[0], sv[1] ); - return 0; - -Fail: - _fh_close(fb); - _fh_close(fa); - return -1; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** fdevents emulation *****/ -/***** *****/ -/***** this is a very simple implementation, we rely on the fact *****/ -/***** that SDB doesn't use FDE_ERROR. *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -#define FATAL(x...) fatal(__FUNCTION__, x) - -#if DEBUG -static void dump_fde(fdevent *fde, const char *info) -{ - fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd, - fde->state & FDE_READ ? 'R' : ' ', - fde->state & FDE_WRITE ? 'W' : ' ', - fde->state & FDE_ERROR ? 'E' : ' ', - info); -} -#else -#define dump_fde(fde, info) do { } while(0) -#endif - -#define FDE_EVENTMASK 0x00ff -#define FDE_STATEMASK 0xff00 - -#define FDE_ACTIVE 0x0100 -#define FDE_PENDING 0x0200 -#define FDE_CREATED 0x0400 - -static void fdevent_plist_enqueue(fdevent *node); -static void fdevent_plist_remove(fdevent *node); -static fdevent *fdevent_plist_dequeue(void); - -static fdevent list_pending = { - .next = &list_pending, - .prev = &list_pending, -}; - -static fdevent **fd_table = 0; -static int fd_table_max = 0; - -typedef struct EventLooperRec_* EventLooper; - -typedef struct EventHookRec_ -{ - EventHook next; - FH fh; - HANDLE h; - int wanted; /* wanted event flags */ - int ready; /* ready event flags */ - void* aux; - void (*prepare)( EventHook hook ); - int (*start) ( EventHook hook ); - void (*stop) ( EventHook hook ); - int (*check) ( EventHook hook ); - int (*peek) ( EventHook hook ); -} EventHookRec; - -static EventHook _free_hooks; - -static EventHook -event_hook_alloc( FH fh ) -{ - EventHook hook = _free_hooks; - if (hook != NULL) - _free_hooks = hook->next; - else { - hook = malloc( sizeof(*hook) ); - if (hook == NULL) - fatal( "could not allocate event hook\n" ); - } - hook->next = NULL; - hook->fh = fh; - hook->wanted = 0; - hook->ready = 0; - hook->h = INVALID_HANDLE_VALUE; - hook->aux = NULL; - - hook->prepare = NULL; - hook->start = NULL; - hook->stop = NULL; - hook->check = NULL; - hook->peek = NULL; - - return hook; -} - -static void -event_hook_free( EventHook hook ) -{ - hook->fh = NULL; - hook->wanted = 0; - hook->ready = 0; - hook->next = _free_hooks; - _free_hooks = hook; -} - - -static void -event_hook_signal( EventHook hook ) -{ - FH f = hook->fh; - int fd = _fh_to_int(f); - fdevent* fde = fd_table[ fd - WIN32_FH_BASE ]; - - if (fde != NULL && fde->fd == fd) { - if ((fde->state & FDE_PENDING) == 0) { - fde->state |= FDE_PENDING; - fdevent_plist_enqueue( fde ); - } - fde->events |= hook->wanted; - } -} - - -#define MAX_LOOPER_HANDLES WIN32_MAX_FHS - -typedef struct EventLooperRec_ -{ - EventHook hooks; - HANDLE htab[ MAX_LOOPER_HANDLES ]; - int htab_count; - -} EventLooperRec; - -static EventHook* -event_looper_find_p( EventLooper looper, FH fh ) -{ - EventHook *pnode = &looper->hooks; - EventHook node = *pnode; - for (;;) { - if ( node == NULL || node->fh == fh ) - break; - pnode = &node->next; - node = *pnode; - } - return pnode; -} - -static void -event_looper_hook( EventLooper looper, int fd, int events ) -{ - FH f = _fh_from_int(fd); - EventHook *pnode; - EventHook node; - - if (f == NULL) /* invalid arg */ { - D("event_looper_hook: invalid fd=%d\n", fd); - return; - } - - pnode = event_looper_find_p( looper, f ); - node = *pnode; - if ( node == NULL ) { - node = event_hook_alloc( f ); - node->next = *pnode; - *pnode = node; - } - - if ( (node->wanted & events) != events ) { - /* this should update start/stop/check/peek */ - D("event_looper_hook: call hook for %d (new=%x, old=%x)\n", - fd, node->wanted, events); - f->clazz->_fh_hook( f, events & ~node->wanted, node ); - node->wanted |= events; - } else { - D("event_looper_hook: ignoring events %x for %d wanted=%x)\n", - events, fd, node->wanted); - } -} - -static void -event_looper_unhook( EventLooper looper, int fd, int events ) -{ - FH fh = _fh_from_int(fd); - EventHook *pnode = event_looper_find_p( looper, fh ); - EventHook node = *pnode; - - if (node != NULL) { - int events2 = events & node->wanted; - if ( events2 == 0 ) { - D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd ); - return; - } - node->wanted &= ~events2; - if (!node->wanted) { - *pnode = node->next; - event_hook_free( node ); - } - } -} - -static EventLooperRec win32_looper; - -static void fdevent_init(void) -{ - win32_looper.htab_count = 0; - win32_looper.hooks = NULL; -} - -static void fdevent_connect(fdevent *fde) -{ - EventLooper looper = &win32_looper; - int events = fde->state & FDE_EVENTMASK; - - if (events != 0) - event_looper_hook( looper, fde->fd, events ); -} - -static void fdevent_disconnect(fdevent *fde) -{ - EventLooper looper = &win32_looper; - int events = fde->state & FDE_EVENTMASK; - - if (events != 0) - event_looper_unhook( looper, fde->fd, events ); -} - -static void fdevent_update(fdevent *fde, unsigned events) -{ - EventLooper looper = &win32_looper; - unsigned events0 = fde->state & FDE_EVENTMASK; - - if (events != events0) { - int removes = events0 & ~events; - int adds = events & ~events0; - if (removes) { - D("fdevent_update: remove %x from %d\n", removes, fde->fd); - event_looper_unhook( looper, fde->fd, removes ); - } - if (adds) { - D("fdevent_update: add %x to %d\n", adds, fde->fd); - event_looper_hook ( looper, fde->fd, adds ); - } - } -} - -static void fdevent_process() -{ - EventLooper looper = &win32_looper; - EventHook hook; - int gotone = 0; - - /* if we have at least one ready hook, execute it/them */ - for (hook = looper->hooks; hook; hook = hook->next) { - hook->ready = 0; - if (hook->prepare) { - hook->prepare(hook); - if (hook->ready != 0) { - event_hook_signal( hook ); - gotone = 1; - } - } - } - - /* nothing's ready yet, so wait for something to happen */ - if (!gotone) - { - looper->htab_count = 0; - - for (hook = looper->hooks; hook; hook = hook->next) - { - if (hook->start && !hook->start(hook)) { - D( "fdevent_process: error when starting a hook\n" ); - return; - } - if (hook->h != INVALID_HANDLE_VALUE) { - int nn; - - for (nn = 0; nn < looper->htab_count; nn++) - { - if ( looper->htab[nn] == hook->h ) - goto DontAdd; - } - looper->htab[ looper->htab_count++ ] = hook->h; - DontAdd: - ; - } - } - - if (looper->htab_count == 0) { - D( "fdevent_process: nothing to wait for !!\n" ); - return; - } - - do - { - int wait_ret; - - D( "sdb_win32: waiting for %d events\n", looper->htab_count ); - if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) { - D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count); - abort(); - } - wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE ); - if (wait_ret == (int)WAIT_FAILED) { - D( "sdb_win32: wait failed, error %ld\n", GetLastError() ); - } else { - D( "sdb_win32: got one (index %d)\n", wait_ret ); - - /* according to Cygwin, some objects like consoles wake up on "inappropriate" events - * like mouse movements. we need to filter these with the "check" function - */ - if ((unsigned)wait_ret < (unsigned)looper->htab_count) - { - for (hook = looper->hooks; hook; hook = hook->next) - { - if ( looper->htab[wait_ret] == hook->h && - (!hook->check || hook->check(hook)) ) - { - D( "sdb_win32: signaling %s for %x\n", hook->fh->name, hook->ready ); - event_hook_signal( hook ); - gotone = 1; - break; - } - } - } - } - } - while (!gotone); - - for (hook = looper->hooks; hook; hook = hook->next) { - if (hook->stop) - hook->stop( hook ); - } - } - - for (hook = looper->hooks; hook; hook = hook->next) { - if (hook->peek && hook->peek(hook)) - event_hook_signal( hook ); - } -} - - -static void fdevent_register(fdevent *fde) -{ - int fd = fde->fd - WIN32_FH_BASE; - - if(fd < 0) { - FATAL("bogus negative fd (%d)\n", fde->fd); - } - - if(fd >= fd_table_max) { - int oldmax = fd_table_max; - if(fde->fd > 32000) { - FATAL("bogus huuuuge fd (%d)\n", fde->fd); - } - if(fd_table_max == 0) { - fdevent_init(); - fd_table_max = 256; - } - while(fd_table_max <= fd) { - fd_table_max *= 2; - } - fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max); - if(fd_table == 0) { - FATAL("could not expand fd_table to %d entries\n", fd_table_max); - } - memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax)); - } - - fd_table[fd] = fde; -} - -static void fdevent_unregister(fdevent *fde) -{ - int fd = fde->fd - WIN32_FH_BASE; - - if((fd < 0) || (fd >= fd_table_max)) { - FATAL("fd out of range (%d)\n", fde->fd); - } - - if(fd_table[fd] != fde) { - FATAL("fd_table out of sync"); - } - - fd_table[fd] = 0; - - if(!(fde->state & FDE_DONT_CLOSE)) { - dump_fde(fde, "close"); - sdb_close(fde->fd); - } -} - -static void fdevent_plist_enqueue(fdevent *node) -{ - fdevent *list = &list_pending; - - node->next = list; - node->prev = list->prev; - node->prev->next = node; - list->prev = node; -} - -static void fdevent_plist_remove(fdevent *node) -{ - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; -} - -static fdevent *fdevent_plist_dequeue(void) -{ - fdevent *list = &list_pending; - fdevent *node = list->next; - - if(node == list) return 0; - - list->next = node->next; - list->next->prev = list; - node->next = 0; - node->prev = 0; - - return node; -} - -fdevent *fdevent_create(int fd, fd_func func, void *arg) -{ - fdevent *fde = (fdevent*) malloc(sizeof(fdevent)); - if(fde == 0) return 0; - fdevent_install(fde, fd, func, arg); - fde->state |= FDE_CREATED; - return fde; -} - -void fdevent_destroy(fdevent *fde) -{ - if(fde == 0) return; - if(!(fde->state & FDE_CREATED)) { - FATAL("fde %p not created by fdevent_create()\n", fde); - } - fdevent_remove(fde); -} - -void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) -{ - memset(fde, 0, sizeof(fdevent)); - fde->state = FDE_ACTIVE; - fde->fd = fd; - fde->func = func; - fde->arg = arg; - - fdevent_register(fde); - dump_fde(fde, "connect"); - fdevent_connect(fde); - fde->state |= FDE_ACTIVE; -} - -void fdevent_remove(fdevent *fde) -{ - if(fde->state & FDE_PENDING) { - fdevent_plist_remove(fde); - } - - if(fde->state & FDE_ACTIVE) { - fdevent_disconnect(fde); - dump_fde(fde, "disconnect"); - fdevent_unregister(fde); - } - - fde->state = 0; - fde->events = 0; -} - - -void fdevent_set(fdevent *fde, unsigned events) -{ - events &= FDE_EVENTMASK; - - if((fde->state & FDE_EVENTMASK) == (int)events) return; - - if(fde->state & FDE_ACTIVE) { - fdevent_update(fde, events); - dump_fde(fde, "update"); - } - - fde->state = (fde->state & FDE_STATEMASK) | events; - - if(fde->state & FDE_PENDING) { - /* if we're pending, make sure - ** we don't signal an event that - ** is no longer wanted. - */ - fde->events &= (~events); - if(fde->events == 0) { - fdevent_plist_remove(fde); - fde->state &= (~FDE_PENDING); - } - } -} - -void fdevent_add(fdevent *fde, unsigned events) -{ - fdevent_set( - fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK)); -} - -void fdevent_del(fdevent *fde, unsigned events) -{ - fdevent_set( - fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK))); -} - -void fdevent_loop() -{ - fdevent *fde; - - for(;;) { -#if DEBUG - fprintf(stderr,"--- ---- waiting for events\n"); -#endif - fdevent_process(); - - while((fde = fdevent_plist_dequeue())) { - unsigned events = fde->events; - fde->events = 0; - fde->state &= (~FDE_PENDING); - dump_fde(fde, "callback"); - fde->func(fde->fd, events, fde->arg); - } - } -} - -/** FILE EVENT HOOKS - **/ - -static void _event_file_prepare( EventHook hook ) -{ - if (hook->wanted & (FDE_READ|FDE_WRITE)) { - /* we can always read/write */ - hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE); - } -} - -static int _event_file_peek( EventHook hook ) -{ - return (hook->wanted & (FDE_READ|FDE_WRITE)); -} - -static void _fh_file_hook( FH f, int events, EventHook hook ) -{ - hook->h = f->fh_handle; - hook->prepare = _event_file_prepare; - hook->peek = _event_file_peek; -} - -/** SOCKET EVENT HOOKS - **/ - -static void _event_socket_verify( EventHook hook, WSANETWORKEVENTS* evts ) -{ - if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) { - if (hook->wanted & FDE_READ) - hook->ready |= FDE_READ; - if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } - if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) { - if (hook->wanted & FDE_WRITE) - hook->ready |= FDE_WRITE; - if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } - if ( evts->lNetworkEvents & FD_OOB ) { - if (hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } -} - -static void _event_socket_prepare( EventHook hook ) -{ - WSANETWORKEVENTS evts; - - /* look if some of the events we want already happened ? */ - if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts )) - _event_socket_verify( hook, &evts ); -} - -static int _socket_wanted_to_flags( int wanted ) -{ - int flags = 0; - if (wanted & FDE_READ) - flags |= FD_READ | FD_ACCEPT | FD_CLOSE; - - if (wanted & FDE_WRITE) - flags |= FD_WRITE | FD_CONNECT | FD_CLOSE; - - if (wanted & FDE_ERROR) - flags |= FD_OOB; - - return flags; -} - -static int _event_socket_start( EventHook hook ) -{ - /* create an event which we're going to wait for */ - FH fh = hook->fh; - long flags = _socket_wanted_to_flags( hook->wanted ); - - hook->h = fh->event; - if (hook->h == INVALID_HANDLE_VALUE) { - D( "_event_socket_start: no event for %s\n", fh->name ); - return 0; - } - - if ( flags != fh->mask ) { - D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags ); - if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) { - D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() ); - CloseHandle( hook->h ); - hook->h = INVALID_HANDLE_VALUE; - exit(1); - return 0; - } - fh->mask = flags; - } - return 1; -} - -static void _event_socket_stop( EventHook hook ) -{ - hook->h = INVALID_HANDLE_VALUE; -} - -static int _event_socket_check( EventHook hook ) -{ - int result = 0; - FH fh = hook->fh; - WSANETWORKEVENTS evts; - - if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) { - _event_socket_verify( hook, &evts ); - result = (hook->ready != 0); - if (result) { - ResetEvent( hook->h ); - } - } - D( "_event_socket_check %s returns %d\n", fh->name, result ); - return result; -} - -static int _event_socket_peek( EventHook hook ) -{ - WSANETWORKEVENTS evts; - FH fh = hook->fh; - - /* look if some of the events we want already happened ? */ - if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) { - _event_socket_verify( hook, &evts ); - if (hook->ready) - ResetEvent( hook->h ); - } - - return hook->ready != 0; -} - - - -static void _fh_socket_hook( FH f, int events, EventHook hook ) -{ - hook->prepare = _event_socket_prepare; - hook->start = _event_socket_start; - hook->stop = _event_socket_stop; - hook->check = _event_socket_check; - hook->peek = _event_socket_peek; - - _event_socket_start( hook ); -} - -/** SOCKETPAIR EVENT HOOKS - **/ - -static void _event_socketpair_prepare( EventHook hook ) -{ - FH fh = hook->fh; - SocketPair pair = fh->fh_pair; - BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; - BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; - - if (hook->wanted & FDE_READ && rbip->can_read) - hook->ready |= FDE_READ; - - if (hook->wanted & FDE_WRITE && wbip->can_write) - hook->ready |= FDE_WRITE; - } - - static int _event_socketpair_start( EventHook hook ) - { - FH fh = hook->fh; - SocketPair pair = fh->fh_pair; - BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; - BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; - - if (hook->wanted == FDE_READ) - hook->h = rbip->evt_read; - - else if (hook->wanted == FDE_WRITE) - hook->h = wbip->evt_write; - - else { - D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" ); - return 0; - } - D( "_event_socketpair_start: hook %s for %x wanted=%x\n", - hook->fh->name, _fh_to_int(fh), hook->wanted); - return 1; -} - -static int _event_socketpair_peek( EventHook hook ) -{ - _event_socketpair_prepare( hook ); - return hook->ready != 0; -} - -static void _fh_socketpair_hook( FH fh, int events, EventHook hook ) -{ - hook->prepare = _event_socketpair_prepare; - hook->start = _event_socketpair_start; - hook->peek = _event_socketpair_peek; -} - - -void -sdb_sysdeps_init( void ) -{ -#define SDB_MUTEX(x) InitializeCriticalSection( & x ); -#include "mutex_list.h" - InitializeCriticalSection( &_win32_lock ); -} diff --git a/src/transport_usb.c b/src/transport_usb.c index e4de29a..0eafc4d 100644 --- a/src/transport_usb.c +++ b/src/transport_usb.c @@ -23,10 +23,6 @@ #define TRACE_TAG TRACE_TRANSPORT #include "sdb.h" -#if SDB_HOST -#include "usb_vendors.h" -#endif - #ifdef HAVE_BIG_ENDIAN #define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) static inline void fix_endians(apacket *p) diff --git a/src/usb_libusb.c b/src/usb_libusb.c deleted file mode 100644 index fc3596f..0000000 --- a/src/usb_libusb.c +++ /dev/null @@ -1,654 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "sdb.h" - -static sdb_mutex_t usb_lock = SDB_MUTEX_INITIALIZER; -static libusb_context *ctx = NULL; - -struct usb_handle -{ - usb_handle *prev; - usb_handle *next; - - libusb_device *dev; - libusb_device_handle *devh; - int interface; - uint8_t dev_bus; - uint8_t dev_addr; - - int zero_mask; - unsigned char end_point_address[2]; - char serial[128]; - - sdb_cond_t notify; - sdb_mutex_t lock; -}; - -static struct usb_handle handle_list = { - .prev = &handle_list, - .next = &handle_list, -}; - -void -usb_cleanup() -{ - libusb_exit(ctx); -} - -void -report_bulk_libusb_error(int r) -{ - switch (r) { - case LIBUSB_ERROR_TIMEOUT: - D("Transfer timeout\n"); - break; - - case LIBUSB_ERROR_PIPE: - D("Control request is not supported\n"); - break; - - case LIBUSB_ERROR_OVERFLOW: - D("Device offered more data\n"); - break; - - case LIBUSB_ERROR_NO_DEVICE : - D("Device was disconnected\n"); - break; - - default: - D("Error %d during transfer\n", r); - break; - }; -} - -static int -usb_bulk_write(usb_handle *uh, const void *data, int len) -{ - int r = 0; - int transferred = 0; - - r = libusb_bulk_transfer(uh->devh, uh->end_point_address[1], (void *)data, len, - &transferred, 0); - - if (r != 0) { - D("usb_bulk_write(): "); - report_bulk_libusb_error(r); - return r; - } - - return (transferred); -} - -static int -usb_bulk_read(usb_handle *uh, void *data, int len) -{ - int r = 0; - int transferred = 0; - - r = libusb_bulk_transfer(uh->devh, uh->end_point_address[0], data, len, - &transferred, 0); - - if (r != 0) { - D("usb_bulk_read(): "); - report_bulk_libusb_error(r); - return r; - } - - return (transferred); -} - -int -usb_write(struct usb_handle *uh, const void *_data, int len) -{ - unsigned char *data = (unsigned char*) _data; - int n; - int need_zero = 0; - - if (uh->zero_mask == 1) { - if (!(len & uh->zero_mask)) { - need_zero = 1; - } - } - - D("usb_write(): %p:%d -> transport %p\n", _data, len, uh); - - while (len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - n = usb_bulk_write(uh, data, xfer); - - if (n != xfer) { - D("usb_write(): failed for transport %p (%d bytes left)\n", uh, len); - return -1; - } - - len -= xfer; - data += xfer; - } - - if (need_zero){ - n = usb_bulk_write(uh, _data, 0); - - if (n < 0) { - D("usb_write(): failed to finish operation for transport %p\n", uh); - } - return n; - } - - return 0; -} - -int -usb_read(struct usb_handle *uh, void *_data, size_t len) -{ - unsigned char *data = (unsigned char*) _data; - int n; - - D("usb_read(): %p:%d <- transport %p\n", _data, len, uh); - - while (len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - n = usb_bulk_read(uh, data, xfer); - - if (n != xfer) { - if (n > 0) { - data += n; - len -= n; - continue; - } - - D("usb_read(): failed for transport %p (%d bytes left)\n", uh, len); - return -1; - } - - len -= xfer; - data += xfer; - } - - return 0; - } - -int -usb_close(struct usb_handle *h) -{ - D("usb_close(): closing transport %p\n", h); - sdb_mutex_lock(&usb_lock); - - h->next->prev = h->prev; - h->prev->next = h->next; - h->prev = NULL; - h->next = NULL; - - libusb_release_interface(h->devh, h->interface); - libusb_close(h->devh); - libusb_unref_device(h->dev); - - sdb_mutex_unlock(&usb_lock); - - free(h); - - return (0); -} - -void usb_kick(struct usb_handle *h) -{ - D("usb_cick(): kicking transport %p\n", h); - - sdb_mutex_lock(&h->lock); - unregister_usb_transport(h); - sdb_mutex_unlock(&h->lock); - - h->next->prev = h->prev; - h->prev->next = h->next; - h->prev = NULL; - h->next = NULL; - - libusb_release_interface(h->devh, h->interface); - libusb_close(h->devh); - libusb_unref_device(h->dev); - free(h); -} - -int -check_usb_interface(libusb_interface *interface, - libusb_device_descriptor *desc, - struct usb_handle *uh) -{ - int e; - - if (interface->num_altsetting == 0) { - D("check_usb_interface(): No interface settings\n"); - return -1; - } - - libusb_interface_descriptor *idesc = &interface->altsetting[0]; - - if (idesc->bNumEndpoints != 2) { - D("check_usb_interface(): Interface have not 2 endpoints, ignoring\n"); - return -1; - } - - for (e = 0; e < idesc->bNumEndpoints; e++) { - libusb_endpoint_descriptor *edesc = &idesc->endpoint[e]; - - if (edesc->bmAttributes != LIBUSB_TRANSFER_TYPE_BULK) { - D("check_usb_interface(): Endpoint (%u) is not bulk (%u), ignoring\n", - edesc->bmAttributes, LIBUSB_TRANSFER_TYPE_BULK); - return -1; - } - - if (edesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) - uh->end_point_address[0] = edesc->bEndpointAddress; - else - uh->end_point_address[1] = edesc->bEndpointAddress; - - /* aproto 01 needs 0 termination */ - if (idesc->bInterfaceProtocol == 0x01) { - uh->zero_mask = edesc->wMaxPacketSize - 1; - D("check_usb_interface(): Forced Android interface protocol v.1\n"); - } - } - - D("check_usb_interface(): Device: %04x:%04x " - "iclass: %x, isclass: %x, iproto: %x ep: %x/%x-> ", - desc->idVendor, desc->idProduct, idesc->bInterfaceClass, - idesc->bInterfaceSubClass, idesc->bInterfaceProtocol, - uh->end_point_address[0], uh->end_point_address[1]); - - if (!is_sdb_interface(desc->idVendor, desc->idProduct, - idesc->bInterfaceClass, idesc->bInterfaceSubClass, - idesc->bInterfaceProtocol)) - { - D("not matches\n"); - return -1; - } - - D("matches\n"); - return 1; -} - -int -check_usb_interfaces(libusb_config_descriptor *config, - libusb_device_descriptor *desc, struct usb_handle *uh) -{ - int i; - - for (i = 0; i < config->bNumInterfaces; ++i) { - if (check_usb_interface(&config->interface[i], desc, uh) != -1) { - /* found some interface and saved information about it */ - D("check_usb_interfaces(): Interface %d of %04x:%04x " - "matches Android device\n", i, desc->idVendor, - desc->idProduct); - - return i; - } - } - - return -1; -} - -int -register_device(struct usb_handle *uh, const char *serial) -{ - D("register_device(): Registering %p [%s] as USB transport\n", - uh, serial); - - struct usb_handle *usb= NULL; - - usb = calloc(1, sizeof(struct usb_handle)); - memcpy(usb, uh, sizeof(struct usb_handle)); - strcpy(usb->serial, uh->serial); - - sdb_cond_init(&usb->notify, 0); - sdb_mutex_init(&usb->lock, 0); - - sdb_mutex_lock(&usb_lock); - - usb->next = &handle_list; - usb->prev = handle_list.prev; - usb->prev->next = usb; - usb->next->prev = usb; - - sdb_mutex_unlock(&usb_lock); - - register_usb_transport(usb, serial, 1); - - return (1); -} - -int -already_registered(usb_handle *uh) -{ - struct usb_handle *usb= NULL; - int exists = 0; - - sdb_mutex_lock(&usb_lock); - - for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { - if ((usb->dev_bus == uh->dev_bus) && - (usb->dev_addr == uh->dev_addr)) - { - exists = 1; - break; - } - } - - sdb_mutex_unlock(&usb_lock); - - return exists; -} - -void -check_device(libusb_device *dev) -{ - struct usb_handle uh; - int i = 0; - int found = -1; - char serial[256] = {0}; - - libusb_device_descriptor desc; - libusb_config_descriptor *config = NULL; - - int r = libusb_get_device_descriptor(dev, &desc); - - if (r != LIBUSB_SUCCESS) { - D("check_device(): Failed to get device descriptor\n"); - return; - } - - if ((desc.idVendor == 0) && (desc.idProduct == 0)) - return; - - D("check_device(): Probing usb device %04x:%04x\n", - desc.idVendor, desc.idProduct); - - if (!is_sdb_interface (desc.idVendor, desc.idProduct, - SDB_CLASS, SDB_SUBCLASS, SDB_PROTOCOL)) - { - D("check_device(): Ignored due unknown vendor id\n"); - return; - } - - uh.dev_bus = libusb_get_bus_number(dev); - uh.dev_addr = libusb_get_device_address(dev); - - if (already_registered(&uh)) { - D("check_device(): Device (bus: %d, address: %d) " - "is already registered\n", uh.dev_bus, uh.dev_addr); - return; - } - - D("check_device(): Device bus: %d, address: %d\n", - uh.dev_bus, uh.dev_addr); - - r = libusb_get_active_config_descriptor(dev, &config); - - if (r != 0) { - if (r == LIBUSB_ERROR_NOT_FOUND) { - D("check_device(): Device %4x:%4x is unconfigured\n", - desc.idVendor, desc.idProduct); - return; - } - - D("check_device(): Failed to get configuration for %4x:%4x\n", - desc.idVendor, desc.idProduct); - return; - } - - if (config == NULL) { - D("check_device(): Sanity check failed after " - "getting active config\n"); - return; - } - - if (config->interface != NULL) { - found = check_usb_interfaces(config, &desc, &uh); - } - - /* not needed anymore */ - libusb_free_config_descriptor(config); - - r = libusb_open(dev, &uh.devh); - uh.dev = dev; - - if (r != 0) { - switch (r) { - case LIBUSB_ERROR_NO_MEM: - D("check_device(): Memory allocation problem\n"); - break; - - case LIBUSB_ERROR_ACCESS: - D("check_device(): Permissions problem, " - "current user priveleges are messed up?\n"); - break; - - case LIBUSB_ERROR_NO_DEVICE: - D("check_device(): Device disconected, bad cable?\n"); - break; - - default: - D("check_device(): libusb triggered error %d\n", r); - } - // skip rest - found = -1; - } - - if (found >= 0) { - D("check_device(): Device matches Android interface\n"); - // read the device's serial number - memset(serial, 0, sizeof(serial)); - uh.interface = found; - - r = libusb_claim_interface(uh.devh, uh.interface); - - if (r < 0) { - D("check_device(): Failed to claim interface %d\n", - uh.interface); - - goto fail; - } - - if (desc.iSerialNumber) { - // reading serial - uint16_t buffer[128] = {0}; - uint16_t languages[128] = {0}; - int languageCount = 0; - - memset(languages, 0, sizeof(languages)); - r = libusb_control_transfer(uh.devh, - LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, - LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, - 0, (uint8_t *)languages, sizeof(languages), 0); - - if (r <= 0) { - D("check_device(): Failed to get languages count\n"); - goto fail; - } - - languageCount = (r - 2) / 2; - - for (i = 1; i <= languageCount; ++i) { - memset(buffer, 0, sizeof(buffer)); - - r = libusb_control_transfer(uh.devh, - LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, - LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber, - languages[i], (uint8_t *)buffer, sizeof(buffer), 0); - - if (r > 0) { /* converting serial */ - int j = 0; - r /= 2; - - for (j = 1; j < r; ++j) - serial[j - 1] = buffer[j]; - - serial[j - 1] = '\0'; - break; /* languagesCount cycle */ - } - } - - if (register_device(&uh, serial) == 0) { - D("check_device(): Failed to register device\n"); - goto fail_interface; - } - - libusb_ref_device(dev); - } - } - - return; - -fail_interface: - libusb_release_interface(uh.devh, uh.interface); - -fail: - libusb_close(uh.devh); - uh.devh = NULL; -} - -int -check_device_connected(struct usb_handle *uh) -{ - int r = libusb_kernel_driver_active(uh->devh, uh->interface); - - if (r == LIBUSB_ERROR_NO_DEVICE) - return 0; - - if (r < 0) - return -1; - - return 1; -} - -void -kick_disconnected() -{ - struct usb_handle *usb= NULL; - - sdb_mutex_lock(&usb_lock); - - for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { - - if (check_device_connected(usb) == 0) { - D("kick_disconnected(): Transport %p is not online anymore\n", - usb); - - usb_kick(usb); - } - } - - sdb_mutex_unlock(&usb_lock); -} - -void -scan_usb_devices() -{ - D("scan_usb_devices(): started\n"); - - libusb_device **devs= NULL; - libusb_device *dev= NULL; - ssize_t cnt = libusb_get_device_list(ctx, &devs); - - if (cnt < 0) { - D("scan_usb_devices(): Failed to get device list (error: %d)\n", - cnt); - - return; - } - - int i = 0; - - while ((dev = devs[i++]) != NULL) { - check_device(dev); - } - - libusb_free_device_list(devs, 1); -} - -void * -device_poll_thread(void* unused) -{ - D("device_poll_thread(): Created USB scan thread\n"); - - for (;;) { - sleep(5); - kick_disconnected(); - scan_usb_devices(); - } - - /* never reaching this point */ - return (NULL); -} - -static void -sigalrm_handler(int signo) -{ - /* nothing */ -} - -void -usb_init() -{ - D("usb_init(): started\n"); - sdb_thread_t tid; - struct sigaction actions; - - int r = libusb_init(&ctx); - - if (r != LIBUSB_SUCCESS) { - err(EX_IOERR, "Failed to init libusb\n"); - } - - memset(&actions, 0, sizeof(actions)); - - sigemptyset(&actions.sa_mask); - - actions.sa_flags = 0; - actions.sa_handler = sigalrm_handler; - - sigaction(SIGALRM, &actions, NULL); - - /* initial device scan */ - scan_usb_devices(); - - /* starting USB event polling thread */ - if (sdb_thread_create(&tid, device_poll_thread, NULL)) { - err(EX_IOERR, "cannot create USB scan thread\n"); - } - - D("usb_init(): finished\n"); -} - diff --git a/src/usb_osx.c b/src/usb_osx.c deleted file mode 100644 index 5fbe1a6..0000000 --- a/src/usb_osx.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 - -#include -#include -#include -#include -#include - -#include "sysdeps.h" - -#include - -#define TRACE_TAG TRACE_USB -#include "sdb.h" -#include "usb_vendors.h" - -#define DBG D - -static IONotificationPortRef notificationPort = 0; -static io_iterator_t* notificationIterators; - -struct usb_handle -{ - UInt8 bulkIn; - UInt8 bulkOut; - IOUSBInterfaceInterface **interface; - io_object_t usbNotification; - unsigned int zero_mask; -}; - -static CFRunLoopRef currentRunLoop = 0; -static pthread_mutex_t start_lock; -static pthread_cond_t start_cond; - - -static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator); -static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator, - natural_t messageType, - void *messageArgument); -static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface, - UInt16 vendor, UInt16 product); - -static int -InitUSB() -{ - CFMutableDictionaryRef matchingDict; - CFRunLoopSourceRef runLoopSource; - SInt32 vendor, if_subclass, if_protocol; - unsigned i; - - //* To set up asynchronous notifications, create a notification port and - //* add its run loop event source to the program's run loop - notificationPort = IONotificationPortCreate(kIOMasterPortDefault); - runLoopSource = IONotificationPortGetRunLoopSource(notificationPort); - CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); - - memset(notificationIterators, 0, sizeof(notificationIterators)); - - //* loop through all supported vendors - for (i = 0; i < vendorIdCount; i++) { - //* Create our matching dictionary to find the Android device's - //* sdb interface - //* IOServiceAddMatchingNotification consumes the reference, so we do - //* not need to release this - matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); - - if (!matchingDict) { - DBG("ERR: Couldn't create USB matching dictionary.\n"); - return -1; - } - - //* Match based on vendor id, interface subclass and protocol - vendor = vendorIds[i]; - if_subclass = SDB_SUBCLASS; - if_protocol = SDB_PROTOCOL; - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), - CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, &vendor)); - CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass), - CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, &if_subclass)); - CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol), - CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, &if_protocol)); - IOServiceAddMatchingNotification( - notificationPort, - kIOFirstMatchNotification, - matchingDict, - AndroidInterfaceAdded, - NULL, - ¬ificationIterators[i]); - - //* Iterate over set of matching interfaces to access already-present - //* devices and to arm the notification - AndroidInterfaceAdded(NULL, notificationIterators[i]); - } - - return 0; -} - -static void -AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) -{ - kern_return_t kr; - io_service_t usbDevice; - io_service_t usbInterface; - IOCFPlugInInterface **plugInInterface = NULL; - IOUSBInterfaceInterface220 **iface = NULL; - IOUSBDeviceInterface197 **dev = NULL; - HRESULT result; - SInt32 score; - UInt16 vendor; - UInt16 product; - UInt8 serialIndex; - char serial[256]; - - while ((usbInterface = IOIteratorNext(iterator))) { - //* Create an intermediate interface plugin - kr = IOCreatePlugInInterfaceForService(usbInterface, - kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, &score); - IOObjectRelease(usbInterface); - if ((kIOReturnSuccess != kr) || (!plugInInterface)) { - DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); - continue; - } - - //* This gets us the interface object - result = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) - &iface); - //* We only needed the plugin to get the interface, so discard it - (*plugInInterface)->Release(plugInInterface); - if (result || !iface) { - DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); - continue; - } - - //* this gets us an ioservice, with which we will find the actual - //* device; after getting a plugin, and querying the interface, of - //* course. - //* Gotta love OS X - kr = (*iface)->GetDevice(iface, &usbDevice); - if (kIOReturnSuccess != kr || !usbDevice) { - DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); - continue; - } - - plugInInterface = NULL; - score = 0; - //* create an intermediate device plugin - kr = IOCreatePlugInInterfaceForService(usbDevice, - kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, &score); - //* only needed this to find the plugin - (void)IOObjectRelease(usbDevice); - if ((kIOReturnSuccess != kr) || (!plugInInterface)) { - DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); - continue; - } - - result = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); - //* only needed this to query the plugin - (*plugInInterface)->Release(plugInInterface); - if (result || !dev) { - DBG("ERR: Couldn't create a device interface (%08x)\n", - (int) result); - continue; - } - - //* Now after all that, we actually have a ref to the device and - //* the interface that matched our criteria - - kr = (*dev)->GetDeviceVendor(dev, &vendor); - kr = (*dev)->GetDeviceProduct(dev, &product); - kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); - - if (serialIndex > 0) { - IOUSBDevRequest req; - UInt16 buffer[256]; - UInt16 languages[128]; - - memset(languages, 0, sizeof(languages)); - - req.bmRequestType = - USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = (kUSBStringDesc << 8) | 0; - req.wIndex = 0; - req.pData = languages; - req.wLength = sizeof(languages); - kr = (*dev)->DeviceRequest(dev, &req); - - if (kr == kIOReturnSuccess && req.wLenDone > 0) { - - int langCount = (req.wLenDone - 2) / 2, lang; - - for (lang = 1; lang <= langCount; lang++) { - - memset(buffer, 0, sizeof(buffer)); - memset(&req, 0, sizeof(req)); - - req.bmRequestType = - USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = (kUSBStringDesc << 8) | serialIndex; - req.wIndex = languages[lang]; - req.pData = buffer; - req.wLength = sizeof(buffer); - kr = (*dev)->DeviceRequest(dev, &req); - - if (kr == kIOReturnSuccess && req.wLenDone > 0) { - int i, count; - - // skip first word, and copy the rest to the serial string, - // changing shorts to bytes. - count = (req.wLenDone - 1) / 2; - for (i = 0; i < count; i++) - serial[i] = buffer[i + 1]; - serial[i] = 0; - break; - } - } - } - } - (*dev)->Release(dev); - - DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, - serial); - - usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, - vendor, product); - if (handle == NULL) { - DBG("ERR: Could not find device interface: %08x\n", kr); - (*iface)->Release(iface); - continue; - } - - DBG("AndroidDeviceAdded calling register_usb_transport\n"); - register_usb_transport(handle, (serial[0] ? serial : NULL), 1); - - // Register for an interest notification of this device being removed. - // Pass the reference to our private data as the refCon for the - // notification. - kr = IOServiceAddInterestNotification(notificationPort, - usbInterface, - kIOGeneralInterest, - AndroidInterfaceNotify, - handle, - &handle->usbNotification); - - if (kIOReturnSuccess != kr) { - DBG("ERR: Unable to create interest notification (%08x)\n", kr); - } - } -} - -static void -AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) -{ - usb_handle *handle = (usb_handle *)refCon; - - if (messageType == kIOMessageServiceIsTerminated) { - if (!handle) { - DBG("ERR: NULL handle\n"); - return; - } - DBG("AndroidInterfaceNotify\n"); - IOObjectRelease(handle->usbNotification); - usb_kick(handle); - } -} - -//* TODO: simplify this further since we only register to get SDB interface -//* subclass+protocol events -static usb_handle* -CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product) -{ - usb_handle* handle = NULL; - IOReturn kr; - UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; - UInt8 endpoint; - - - //* Now open the interface. This will cause the pipes associated with - //* the endpoints in the interface descriptor to be instantiated - kr = (*interface)->USBInterfaceOpen(interface); - if (kr != kIOReturnSuccess) { - DBG("ERR: Could not open interface: (%08x)\n", kr); - return NULL; - } - - //* Get the number of endpoints associated with this interface - kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); - if (kr != kIOReturnSuccess) { - DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); - goto err_get_num_ep; - } - - //* Get interface class, subclass and protocol - if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || - (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || - (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) { - DBG("ERR: Unable to get interface class, subclass and protocol\n"); - goto err_get_interface_class; - } - - //* check to make sure interface class, subclass and protocol match SDB - //* avoid opening mass storage endpoints - if (!is_sdb_interface(vendor, product, interfaceClass, - interfaceSubClass, interfaceProtocol)) - goto err_bad_sdb_interface; - - handle = calloc(1, sizeof(usb_handle)); - - //* Iterate over the endpoints for this interface and find the first - //* bulk in/out pipes available. These will be our read/write pipes. - for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { - UInt8 transferType; - UInt16 maxPacketSize; - UInt8 interval; - UInt8 number; - UInt8 direction; - - kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, - &number, &transferType, &maxPacketSize, &interval); - - if (kIOReturnSuccess == kr) { - if (kUSBBulk != transferType) - continue; - - if (kUSBIn == direction) - handle->bulkIn = endpoint; - - if (kUSBOut == direction) - handle->bulkOut = endpoint; - - handle->zero_mask = maxPacketSize - 1; - } else { - DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); - goto err_get_pipe_props; - } - } - - handle->interface = interface; - return handle; - -err_get_pipe_props: - free(handle); -err_bad_sdb_interface: -err_get_interface_class: -err_get_num_ep: - (*interface)->USBInterfaceClose(interface); - return NULL; -} - - -void* RunLoopThread(void* unused) -{ - unsigned i; - - InitUSB(); - - currentRunLoop = CFRunLoopGetCurrent(); - - // Signal the parent that we are running - sdb_mutex_lock(&start_lock); - sdb_cond_signal(&start_cond); - sdb_mutex_unlock(&start_lock); - - CFRunLoopRun(); - currentRunLoop = 0; - - for (i = 0; i < vendorIdCount; i++) { - IOObjectRelease(notificationIterators[i]); - } - IONotificationPortDestroy(notificationPort); - - DBG("RunLoopThread done\n"); - return NULL; -} - - -static int initialized = 0; -void usb_init() -{ - if (!initialized) - { - sdb_thread_t tid; - - notificationIterators = (io_iterator_t*)malloc( - vendorIdCount * sizeof(io_iterator_t)); - - sdb_mutex_init(&start_lock, NULL); - sdb_cond_init(&start_cond, NULL); - - if(sdb_thread_create(&tid, RunLoopThread, NULL)) - fatal_errno("cannot create input thread"); - - // Wait for initialization to finish - sdb_mutex_lock(&start_lock); - sdb_cond_wait(&start_cond, &start_lock); - sdb_mutex_unlock(&start_lock); - - sdb_mutex_destroy(&start_lock); - sdb_cond_destroy(&start_cond); - - initialized = 1; - } -} - -void usb_cleanup() -{ - DBG("usb_cleanup\n"); - close_usb_devices(); - if (currentRunLoop) - CFRunLoopStop(currentRunLoop); - - if (notificationIterators != NULL) { - free(notificationIterators); - notificationIterators = NULL; - } -} - -int usb_write(usb_handle *handle, const void *buf, int len) -{ - IOReturn result; - - if (!len) - return 0; - - if (!handle) - return -1; - - if (NULL == handle->interface) { - DBG("ERR: usb_write interface was null\n"); - return -1; - } - - if (0 == handle->bulkOut) { - DBG("ERR: bulkOut endpoint not assigned\n"); - return -1; - } - - result = - (*handle->interface)->WritePipe( - handle->interface, handle->bulkOut, (void *)buf, len); - - if ((result == 0) && (handle->zero_mask)) { - /* we need 0-markers and our transfer */ - if(!(len & handle->zero_mask)) { - result = - (*handle->interface)->WritePipe( - handle->interface, handle->bulkOut, (void *)buf, 0); - } - } - - if (0 == result) - return 0; - - DBG("ERR: usb_write failed with status %d\n", result); - return -1; -} - -int usb_read(usb_handle *handle, void *buf, int len) -{ - IOReturn result; - UInt32 numBytes = len; - - if (!len) { - return 0; - } - - if (!handle) { - return -1; - } - - if (NULL == handle->interface) { - DBG("ERR: usb_read interface was null\n"); - return -1; - } - - if (0 == handle->bulkIn) { - DBG("ERR: bulkIn endpoint not assigned\n"); - return -1; - } - - result = - (*handle->interface)->ReadPipe(handle->interface, - handle->bulkIn, buf, &numBytes); - - if (0 == result) - return 0; - else { - DBG("ERR: usb_read failed with status %d\n", result); - } - - return -1; -} - -int usb_close(usb_handle *handle) -{ - return 0; -} - -void usb_kick(usb_handle *handle) -{ - /* release the interface */ - if (!handle) - return; - - if (handle->interface) - { - (*handle->interface)->USBInterfaceClose(handle->interface); - (*handle->interface)->Release(handle->interface); - handle->interface = 0; - } -} diff --git a/src/usb_vendors.c b/src/usb_vendors.c deleted file mode 100644 index 6364828..0000000 --- a/src/usb_vendors.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 "usb_vendors.h" - -#include - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include "windows.h" -# include "shlobj.h" -#else -# include -# include -#endif - -#include "sysdeps.h" -#include "sdb.h" - -#define ANDROID_PATH ".android" -#define ANDROID_SDB_INI "sdb_usb.ini" - -#define TRACE_TAG TRACE_USB - -// Google's USB Vendor ID -#define VENDOR_ID_GOOGLE 0x18d1 -// Intel's USB Vendor ID -#define VENDOR_ID_INTEL 0x8087 -// HTC's USB Vendor ID -#define VENDOR_ID_HTC 0x0bb4 -// Samsung's USB Vendor ID -#define VENDOR_ID_SAMSUNG 0x04e8 -// Motorola's USB Vendor ID -#define VENDOR_ID_MOTOROLA 0x22b8 -// LG's USB Vendor ID -#define VENDOR_ID_LGE 0x1004 -// Huawei's USB Vendor ID -#define VENDOR_ID_HUAWEI 0x12D1 -// Acer's USB Vendor ID -#define VENDOR_ID_ACER 0x0502 -// Sony Ericsson's USB Vendor ID -#define VENDOR_ID_SONY_ERICSSON 0x0FCE -// Foxconn's USB Vendor ID -#define VENDOR_ID_FOXCONN 0x0489 -// Dell's USB Vendor ID -#define VENDOR_ID_DELL 0x413c -// Nvidia's USB Vendor ID -#define VENDOR_ID_NVIDIA 0x0955 -// Garmin-Asus's USB Vendor ID -#define VENDOR_ID_GARMIN_ASUS 0x091E -// Sharp's USB Vendor ID -#define VENDOR_ID_SHARP 0x04dd -// ZTE's USB Vendor ID -#define VENDOR_ID_ZTE 0x19D2 -// Kyocera's USB Vendor ID -#define VENDOR_ID_KYOCERA 0x0482 -// Pantech's USB Vendor ID -#define VENDOR_ID_PANTECH 0x10A9 -// Qualcomm's USB Vendor ID -#define VENDOR_ID_QUALCOMM 0x05c6 -// On-The-Go-Video's USB Vendor ID -#define VENDOR_ID_OTGV 0x2257 -// NEC's USB Vendor ID -#define VENDOR_ID_NEC 0x0409 -// Panasonic Mobile Communication's USB Vendor ID -#define VENDOR_ID_PMC 0x04DA -// Toshiba's USB Vendor ID -#define VENDOR_ID_TOSHIBA 0x0930 -// SK Telesys's USB Vendor ID -#define VENDOR_ID_SK_TELESYS 0x1F53 -// KT Tech's USB Vendor ID -#define VENDOR_ID_KT_TECH 0x2116 -// Asus's USB Vendor ID -#define VENDOR_ID_ASUS 0x0b05 -// Philips's USB Vendor ID -#define VENDOR_ID_PHILIPS 0x0471 -// Texas Instruments's USB Vendor ID -#define VENDOR_ID_TI 0x0451 -// Funai's USB Vendor ID -#define VENDOR_ID_FUNAI 0x0F1C -// Gigabyte's USB Vendor ID -#define VENDOR_ID_GIGABYTE 0x0414 -// IRiver's USB Vendor ID -#define VENDOR_ID_IRIVER 0x2420 -// Compal's USB Vendor ID -#define VENDOR_ID_COMPAL 0x1219 -// T & A Mobile Phones' USB Vendor ID -#define VENDOR_ID_T_AND_A 0x1BBB -// LenovoMobile's USB Vendor ID -#define VENDOR_ID_LENOVOMOBILE 0x2006 -// Lenovo's USB Vendor ID -#define VENDOR_ID_LENOVO 0x17EF -// Vizio's USB Vendor ID -#define VENDOR_ID_VIZIO 0xE040 -// K-Touch's USB Vendor ID -#define VENDOR_ID_K_TOUCH 0x24E3 -// Pegatron's USB Vendor ID -#define VENDOR_ID_PEGATRON 0x1D4D -// Archos's USB Vendor ID -#define VENDOR_ID_ARCHOS 0x0E79 -// Positivo's USB Vendor ID -#define VENDOR_ID_POSITIVO 0x1662 -// Fujitsu's USB Vendor ID -#define VENDOR_ID_FUJITSU 0x04C5 -// Lumigon's USB Vendor ID -#define VENDOR_ID_LUMIGON 0x25E3 -// Quanta's USB Vendor ID -#define VENDOR_ID_QUANTA 0x0408 -// INQ Mobile's USB Vendor ID -#define VENDOR_ID_INQ_MOBILE 0x2314 -// Sony's USB Vendor ID -#define VENDOR_ID_SONY 0x054C -// Lab126's USB Vendor ID -#define VENDOR_ID_LAB126 0x1949 -// Yulong Coolpad's USB Vendor ID -#define VENDOR_ID_YULONG_COOLPAD 0x1EBF - -/** built-in vendor list */ -int builtInVendorIds[] = { - VENDOR_ID_GOOGLE, - VENDOR_ID_INTEL, - VENDOR_ID_HTC, - VENDOR_ID_SAMSUNG, - VENDOR_ID_MOTOROLA, - VENDOR_ID_LGE, - VENDOR_ID_HUAWEI, - VENDOR_ID_ACER, - VENDOR_ID_SONY_ERICSSON, - VENDOR_ID_FOXCONN, - VENDOR_ID_DELL, - VENDOR_ID_NVIDIA, - VENDOR_ID_GARMIN_ASUS, - VENDOR_ID_SHARP, - VENDOR_ID_ZTE, - VENDOR_ID_KYOCERA, - VENDOR_ID_PANTECH, - VENDOR_ID_QUALCOMM, - VENDOR_ID_OTGV, - VENDOR_ID_NEC, - VENDOR_ID_PMC, - VENDOR_ID_TOSHIBA, - VENDOR_ID_SK_TELESYS, - VENDOR_ID_KT_TECH, - VENDOR_ID_ASUS, - VENDOR_ID_PHILIPS, - VENDOR_ID_TI, - VENDOR_ID_FUNAI, - VENDOR_ID_GIGABYTE, - VENDOR_ID_IRIVER, - VENDOR_ID_COMPAL, - VENDOR_ID_T_AND_A, - VENDOR_ID_LENOVOMOBILE, - VENDOR_ID_LENOVO, - VENDOR_ID_VIZIO, - VENDOR_ID_K_TOUCH, - VENDOR_ID_PEGATRON, - VENDOR_ID_ARCHOS, - VENDOR_ID_POSITIVO, - VENDOR_ID_FUJITSU, - VENDOR_ID_LUMIGON, - VENDOR_ID_QUANTA, - VENDOR_ID_INQ_MOBILE, - VENDOR_ID_SONY, - VENDOR_ID_LAB126, - VENDOR_ID_YULONG_COOLPAD, -}; - -#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) - -/* max number of supported vendor ids (built-in + 3rd party). increase as needed */ -#define VENDOR_COUNT_MAX 128 - -int vendorIds[VENDOR_COUNT_MAX]; -unsigned vendorIdCount = 0; - -int get_sdb_usb_ini(char* buff, size_t len); - -void usb_vendors_init(void) -{ - if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) { - fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n"); - exit(2); - } - - /* add the built-in vendors at the beginning of the array */ - memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds)); - - /* default array size is the number of built-in vendors */ - vendorIdCount = BUILT_IN_VENDOR_COUNT; - - if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT) - return; - - char temp[PATH_MAX]; - if (get_sdb_usb_ini(temp, sizeof(temp)) == 0) { - FILE * f = fopen(temp, "rt"); - - if (f != NULL) { - /* The vendor id file is pretty basic. 1 vendor id per line. - Lines starting with # are comments */ - while (fgets(temp, sizeof(temp), f) != NULL) { - if (temp[0] == '#') - continue; - - long value = strtol(temp, NULL, 0); - if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) { - fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_SDB_INI); - exit(2); - } - - vendorIds[vendorIdCount++] = (int)value; - - /* make sure we don't go beyond the array */ - if (vendorIdCount == VENDOR_COUNT_MAX) { - break; - } - } - } - } -} - -/* Utils methods */ - -/* builds the path to the sdb vendor id file. returns 0 if success */ -int build_path(char* buff, size_t len, const char* format, const char* home) -{ - if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_SDB_INI) >= (signed)len) { - return 1; - } - - return 0; -} - -/* fills buff with the path to the sdb vendor id file. returns 0 if success */ -int get_sdb_usb_ini(char* buff, size_t len) -{ -#ifdef _WIN32 - const char* home = getenv("ANDROID_SDK_HOME"); - if (home != NULL) { - return build_path(buff, len, "%s\\%s\\%s", home); - } else { - char path[MAX_PATH]; - SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path); - return build_path(buff, len, "%s\\%s\\%s", path); - } -#else - const char* home = getenv("HOME"); - if (home == NULL) - home = "/tmp"; - - return build_path(buff, len, "%s/%s/%s", home); -#endif -} diff --git a/src/usb_vendors.h b/src/usb_vendors.h deleted file mode 100644 index 9e09d9a..0000000 --- a/src/usb_vendors.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -#ifndef __USB_VENDORS_H -#define __USB_VENDORS_H - -extern int vendorIds[]; -extern unsigned vendorIdCount; - -void usb_vendors_init(void); - -#endif diff --git a/src/usb_windows.c b/src/usb_windows.c deleted file mode 100644 index 37eef1b..0000000 --- a/src/usb_windows.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include -#include -#include - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "sdb.h" - -/** Structure usb_handle describes our connection to the usb device via - AdbWinApi.dll. This structure is returned from usb_open() routine and - is expected in each subsequent call that is accessing the device. -*/ -struct usb_handle { - /// Previous entry in the list of opened usb handles - usb_handle *prev; - - /// Next entry in the list of opened usb handles - usb_handle *next; - - /// Handle to USB interface - SDBAPIHANDLE sdb_interface; - - /// Handle to USB read pipe (endpoint) - SDBAPIHANDLE sdb_read_pipe; - - /// Handle to USB write pipe (endpoint) - SDBAPIHANDLE sdb_write_pipe; - - /// Interface name - char* interface_name; - - /// Mask for determining when to use zero length packets - unsigned zero_mask; -}; - -/// Class ID assigned to the device by androidusb.sys -static const GUID usb_class_id = ANDROID_USB_CLASS_ID; - -/// List of opened usb handles -static usb_handle handle_list = { - .prev = &handle_list, - .next = &handle_list, -}; - -/// Locker for the list of opened usb handles -SDB_MUTEX_DEFINE( usb_lock ); - -/// Checks if there is opened usb handle in handle_list for this device. -int known_device(const char* dev_name); - -/// Checks if there is opened usb handle in handle_list for this device. -/// usb_lock mutex must be held before calling this routine. -int known_device_locked(const char* dev_name); - -/// Registers opened usb handle (adds it to handle_list). -int register_new_device(usb_handle* handle); - -/// Checks if interface (device) matches certain criteria -int recognized_device(usb_handle* handle); - -/// Enumerates present and available interfaces (devices), opens new ones and -/// registers usb transport for them. -void find_devices(); - -/// Entry point for thread that polls (every second) for new usb interfaces. -/// This routine calls find_devices in infinite loop. -void* device_poll_thread(void* unused); - -/// Initializes this module -void usb_init(); - -/// Cleans up this module -void usb_cleanup(); - -/// Opens usb interface (device) by interface (device) name. -usb_handle* do_usb_open(const wchar_t* interface_name); - -/// Writes data to the opened usb handle -int usb_write(usb_handle* handle, const void* data, int len); - -/// Reads data using the opened usb handle -int usb_read(usb_handle *handle, void* data, int len); - -/// Cleans up opened usb handle -void usb_cleanup_handle(usb_handle* handle); - -/// Cleans up (but don't close) opened usb handle -void usb_kick(usb_handle* handle); - -/// Closes opened usb handle -int usb_close(usb_handle* handle); - -/// Gets interface (device) name for an opened usb handle -const char *usb_name(usb_handle* handle); - -int known_device_locked(const char* dev_name) { - usb_handle* usb; - - if (NULL != dev_name) { - // Iterate through the list looking for the name match. - for(usb = handle_list.next; usb != &handle_list; usb = usb->next) { - // In Windows names are not case sensetive! - if((NULL != usb->interface_name) && - (0 == stricmp(usb->interface_name, dev_name))) { - return 1; - } - } - } - - return 0; -} - -int known_device(const char* dev_name) { - int ret = 0; - - if (NULL != dev_name) { - sdb_mutex_lock(&usb_lock); - ret = known_device_locked(dev_name); - sdb_mutex_unlock(&usb_lock); - } - - return ret; -} - -int register_new_device(usb_handle* handle) { - if (NULL == handle) - return 0; - - sdb_mutex_lock(&usb_lock); - - // Check if device is already in the list - if (known_device_locked(handle->interface_name)) { - sdb_mutex_unlock(&usb_lock); - return 0; - } - - // Not in the list. Add this handle to the list. - handle->next = &handle_list; - handle->prev = handle_list.prev; - handle->prev->next = handle; - handle->next->prev = handle; - - sdb_mutex_unlock(&usb_lock); - - return 1; -} - -void* device_poll_thread(void* unused) { - D("Created device thread\n"); - - while(1) { - find_devices(); - sdb_sleep_ms(1000); - } - - return NULL; -} - -void usb_init() { - sdb_thread_t tid; - - if(sdb_thread_create(&tid, device_poll_thread, NULL)) { - fatal_errno("cannot create input thread"); - } -} - -void usb_cleanup() { -} - -usb_handle* do_usb_open(const wchar_t* interface_name) { - // Allocate our handle - usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle)); - if (NULL == ret) - return NULL; - - // Set linkers back to the handle - ret->next = ret; - ret->prev = ret; - - // Create interface. - ret->sdb_interface = SdbCreateInterfaceByName(interface_name); - - if (NULL == ret->sdb_interface) { - free(ret); - errno = GetLastError(); - return NULL; - } - - // Open read pipe (endpoint) - ret->sdb_read_pipe = - SdbOpenDefaultBulkReadEndpoint(ret->sdb_interface, - SdbOpenAccessTypeReadWrite, - SdbOpenSharingModeReadWrite); - if (NULL != ret->sdb_read_pipe) { - // Open write pipe (endpoint) - ret->sdb_write_pipe = - SdbOpenDefaultBulkWriteEndpoint(ret->sdb_interface, - SdbOpenAccessTypeReadWrite, - SdbOpenSharingModeReadWrite); - if (NULL != ret->sdb_write_pipe) { - // Save interface name - unsigned long name_len = 0; - - // First get expected name length - SdbGetInterfaceName(ret->sdb_interface, - NULL, - &name_len, - true); - if (0 != name_len) { - ret->interface_name = (char*)malloc(name_len); - - if (NULL != ret->interface_name) { - // Now save the name - if (SdbGetInterfaceName(ret->sdb_interface, - ret->interface_name, - &name_len, - true)) { - // We're done at this point - return ret; - } - } else { - SetLastError(ERROR_OUTOFMEMORY); - } - } - } - } - - // Something went wrong. - int saved_errno = GetLastError(); - usb_cleanup_handle(ret); - free(ret); - SetLastError(saved_errno); - - return NULL; -} - -int usb_write(usb_handle* handle, const void* data, int len) { - unsigned long time_out = 5000; - unsigned long written = 0; - int ret; - - D("usb_write %d\n", len); - if (NULL != handle) { - // Perform write - ret = SdbWriteEndpointSync(handle->sdb_write_pipe, - (void*)data, - (unsigned long)len, - &written, - time_out); - int saved_errno = GetLastError(); - - if (ret) { - // Make sure that we've written what we were asked to write - D("usb_write got: %ld, expected: %d\n", written, len); - if (written == (unsigned long)len) { - if(handle->zero_mask && (len & handle->zero_mask) == 0) { - // Send a zero length packet - SdbWriteEndpointSync(handle->sdb_write_pipe, - (void*)data, - 0, - &written, - time_out); - } - return 0; - } - } else { - // assume ERROR_INVALID_HANDLE indicates we are disconnected - if (saved_errno == ERROR_INVALID_HANDLE) - usb_kick(handle); - } - errno = saved_errno; - } else { - D("usb_write NULL handle\n"); - SetLastError(ERROR_INVALID_HANDLE); - } - - D("usb_write failed: %d\n", errno); - - return -1; -} - -int usb_read(usb_handle *handle, void* data, int len) { - unsigned long time_out = 0; - unsigned long read = 0; - int ret; - - D("usb_read %d\n", len); - if (NULL != handle) { - while (len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - ret = SdbReadEndpointSync(handle->sdb_read_pipe, - (void*)data, - (unsigned long)xfer, - &read, - time_out); - int saved_errno = GetLastError(); - D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, saved_errno); - if (ret) { - data += read; - len -= read; - - if (len == 0) - return 0; - } else { - // assume ERROR_INVALID_HANDLE indicates we are disconnected - if (saved_errno == ERROR_INVALID_HANDLE) - usb_kick(handle); - break; - } - errno = saved_errno; - } - } else { - D("usb_read NULL handle\n"); - SetLastError(ERROR_INVALID_HANDLE); - } - - D("usb_read failed: %d\n", errno); - - return -1; -} - -void usb_cleanup_handle(usb_handle* handle) { - if (NULL != handle) { - if (NULL != handle->interface_name) - free(handle->interface_name); - if (NULL != handle->sdb_write_pipe) - SdbCloseHandle(handle->sdb_write_pipe); - if (NULL != handle->sdb_read_pipe) - SdbCloseHandle(handle->sdb_read_pipe); - if (NULL != handle->sdb_interface) - SdbCloseHandle(handle->sdb_interface); - - handle->interface_name = NULL; - handle->sdb_write_pipe = NULL; - handle->sdb_read_pipe = NULL; - handle->sdb_interface = NULL; - } -} - -void usb_kick(usb_handle* handle) { - if (NULL != handle) { - sdb_mutex_lock(&usb_lock); - - usb_cleanup_handle(handle); - - sdb_mutex_unlock(&usb_lock); - } else { - SetLastError(ERROR_INVALID_HANDLE); - errno = ERROR_INVALID_HANDLE; - } -} - -int usb_close(usb_handle* handle) { - D("usb_close\n"); - - if (NULL != handle) { - // Remove handle from the list - sdb_mutex_lock(&usb_lock); - - if ((handle->next != handle) && (handle->prev != handle)) { - handle->next->prev = handle->prev; - handle->prev->next = handle->next; - handle->prev = handle; - handle->next = handle; - } - - sdb_mutex_unlock(&usb_lock); - - // Cleanup handle - usb_cleanup_handle(handle); - free(handle); - } - - return 0; -} - -const char *usb_name(usb_handle* handle) { - if (NULL == handle) { - SetLastError(ERROR_INVALID_HANDLE); - errno = ERROR_INVALID_HANDLE; - return NULL; - } - - return (const char*)handle->interface_name; -} - -int recognized_device(usb_handle* handle) { - if (NULL == handle) - return 0; - - // Check vendor and product id first - USB_DEVICE_DESCRIPTOR device_desc; - - if (!SdbGetUsbDeviceDescriptor(handle->sdb_interface, - &device_desc)) { - return 0; - } - - // Then check interface properties - USB_INTERFACE_DESCRIPTOR interf_desc; - - if (!SdbGetUsbInterfaceDescriptor(handle->sdb_interface, - &interf_desc)) { - return 0; - } - - // Must have two endpoints - if (2 != interf_desc.bNumEndpoints) { - return 0; - } - - if (is_sdb_interface(device_desc.idVendor, device_desc.idProduct, - interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) { - - if(interf_desc.bInterfaceProtocol == 0x01) { - SdbEndpointInformation endpoint_info; - // assuming zero is a valid bulk endpoint ID - if (SdbGetEndpointInformation(handle->sdb_interface, 0, &endpoint_info)) { - handle->zero_mask = endpoint_info.max_packet_size - 1; - } - } - - return 1; - } - - return 0; -} - -void find_devices() { - usb_handle* handle = NULL; - char entry_buffer[2048]; - char interf_name[2048]; - SdbInterfaceInfo* next_interface = (SdbInterfaceInfo*)(&entry_buffer[0]); - unsigned long entry_buffer_size = sizeof(entry_buffer); - char* copy_name; - - // Enumerate all present and active interfaces. - SDBAPIHANDLE enum_handle = - SdbEnumInterfaces(usb_class_id, true, true, true); - - if (NULL == enum_handle) - return; - - while (SdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { - // TODO: FIXME - temp hack converting wchar_t into char. - // It would be better to change AdbNextInterface so it will return - // interface name as single char string. - const wchar_t* wchar_name = next_interface->device_name; - for(copy_name = interf_name; - L'\0' != *wchar_name; - wchar_name++, copy_name++) { - *copy_name = (char)(*wchar_name); - } - *copy_name = '\0'; - - // Lets see if we already have this device in the list - if (!known_device(interf_name)) { - // This seems to be a new device. Open it! - handle = do_usb_open(next_interface->device_name); - if (NULL != handle) { - // Lets see if this interface (device) belongs to us - if (recognized_device(handle)) { - D("adding a new device %s\n", interf_name); - char serial_number[512]; - unsigned long serial_number_len = sizeof(serial_number); - if (SdbGetSerialNumber(handle->sdb_interface, - serial_number, - &serial_number_len, - true)) { - // Lets make sure that we don't duplicate this device - if (register_new_device(handle)) { - register_usb_transport(handle, serial_number, 1); - } else { - D("register_new_device failed for %s\n", interf_name); - usb_cleanup_handle(handle); - free(handle); - } - } else { - D("cannot get serial number\n"); - usb_cleanup_handle(handle); - free(handle); - } - } else { - usb_cleanup_handle(handle); - free(handle); - } - } - } - - entry_buffer_size = sizeof(entry_buffer); - } - - SdbCloseHandle(enum_handle); -} diff --git a/test/test_inoti_service.c b/test/test_inoti_service.c deleted file mode 100644 index b3c63ef..0000000 --- a/test/test_inoti_service.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -/* a simple test program, connects to SDB server, and opens a track-devices session */ -#include -#include -#include -#include -#include -#include - -static void -panic( const char* msg ) -{ - fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno)); - exit(1); -} - -static int -unix_write( int fd, const char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = write(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -static int unix_read( int fd, char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = read(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -int main( void ) -{ - int ret, s; - struct sockaddr_in server; - char buffer[1024]; - const char* transport = "host:transport-a"; - const char* request = "cs:"; - int len; - - memset( &server, 0, sizeof(server) ); - server.sin_family = AF_INET; - server.sin_port = htons(26099); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket( PF_INET, SOCK_STREAM, 0 ); - ret = connect( s, (struct sockaddr*) &server, sizeof(server) ); - if (ret < 0) panic( "could not connect to server" ); - - /* send the transport */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(transport), transport ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - /* send the request */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - printf( "server answer: %.*s\n", 4, buffer ); - - /* now loop */ - for (;;) { - memset(buffer, 0, sizeof(buffer)); - if (unix_read(s, buffer, 30) < 0) - panic("could not read length"); - - printf( "server answer: %s\n",buffer ); - break; - } - close(s); -} diff --git a/test/test_track_devices.c b/test/test_track_devices.c deleted file mode 100644 index 64c484f..0000000 --- a/test/test_track_devices.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -/* a simple test program, connects to SDB server, and opens a track-devices session */ -#include -#include -#include -#include -#include -#include - -static void -panic( const char* msg ) -{ - fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno)); - exit(1); -} - -static int -unix_write( int fd, const char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = write(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -static int -unix_read( int fd, char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = read(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - - -int main( void ) -{ - int ret, s; - struct sockaddr_in server; - char buffer[1024]; - const char* request = "host:track-devices"; - int len; - - memset( &server, 0, sizeof(server) ); - server.sin_family = AF_INET; - server.sin_port = htons(5037); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket( PF_INET, SOCK_STREAM, 0 ); - ret = connect( s, (struct sockaddr*) &server, sizeof(server) ); - if (ret < 0) panic( "could not connect to server" ); - - /* send the request */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - printf( "server answer: %.*s\n", 4, buffer ); - - /* now loop */ - for (;;) { - char head[5] = "0000"; - - if (unix_read(s, head, 4) < 0) - panic("could not read length"); - - if ( sscanf( head, "%04x", &len ) != 1 ) - panic("could not decode length"); - - if (unix_read(s, buffer, len) != len) - panic("could not read data"); - - printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer ); - } - close(s); -} diff --git a/test/test_track_jdwp.c b/test/test_track_jdwp.c deleted file mode 100644 index 5187d5f..0000000 --- a/test/test_track_jdwp.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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. - */ - -/* a simple test program, connects to SDB server, and opens a track-devices session */ -#include -#include -#include -#include -#include -#include - -static void -panic( const char* msg ) -{ - fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno)); - exit(1); -} - -static int -unix_write( int fd, const char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = write(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -static int -unix_read( int fd, char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = read(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - - -int main( void ) -{ - int ret, s; - struct sockaddr_in server; - char buffer[1024]; - const char* request = "track-jdwp"; - int len; - - memset( &server, 0, sizeof(server) ); - server.sin_family = AF_INET; - server.sin_port = htons(5037); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket( PF_INET, SOCK_STREAM, 0 ); - ret = connect( s, (struct sockaddr*) &server, sizeof(server) ); - if (ret < 0) panic( "could not connect to server" ); - - /* send the request */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - printf( "server answer: %.*s\n", 4, buffer ); - - /* now loop */ - for (;;) { - char head[5] = "0000"; - - if (unix_read(s, head, 4) < 0) - panic("could not read length"); - - if ( sscanf( head, "%04x", &len ) != 1 ) - panic("could not decode length"); - - if (unix_read(s, buffer, len) != len) - panic("could not read data"); - - printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer ); - } - close(s); -} -- 2.7.4 From 4d85f757e1b209f30c081b9348f63a155812f657 Mon Sep 17 00:00:00 2001 From: greatim Date: Thu, 30 Jun 2016 17:25:07 +0900 Subject: [PATCH 07/16] Add PATH environment variable definition into script file - To prevent security attack, add PATH environmeent variable into shell script file Change-Id: I58610f40d1d3d8af5de0ad55b1a037e5ef99b02b Signed-off-by: greatim --- script/S06sdbd | 1 + script/profile_command | 1 + script/sdbd | 1 + script/sdk_launch | 1 + 4 files changed, 4 insertions(+) diff --git a/script/S06sdbd b/script/S06sdbd index 6a05d55..a476322 100755 --- a/script/S06sdbd +++ b/script/S06sdbd @@ -1,2 +1,3 @@ #!/bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin /etc/init.d/sdbd start diff --git a/script/profile_command b/script/profile_command index 27efe39..f8abd42 100755 --- a/script/profile_command +++ b/script/profile_command @@ -1,4 +1,5 @@ #!/bin/bash +PATH=/bin:/usr/bin:/sbin:/usr/sbin VERSION="3.0" KILL=/usr/bin/killall diff --git a/script/sdbd b/script/sdbd index 74a8bc0..73335f1 100755 --- a/script/sdbd +++ b/script/sdbd @@ -1,4 +1,5 @@ #! /bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin . /lib/lsb/init-functions diff --git a/script/sdk_launch b/script/sdk_launch index b914363..c5f8a12 100755 --- a/script/sdk_launch +++ b/script/sdk_launch @@ -1,4 +1,5 @@ #!/bin/bash +PATH=/bin:/usr/bin:/sbin:/usr/sbin # Authors: # Kangho Kim , Yoonki Park -- 2.7.4 From 203be3fd3f7699be189b13a0eccd460907ed6aa1 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Tue, 5 Jul 2016 16:22:51 +0900 Subject: [PATCH 08/16] Fixed build warnings Change-Id: I45ea4e8e5321e2d0ebe9dc1e6dc5d7ffe76b48f4 Signed-off-by: shingil.kang --- src/sdb.c | 3 +-- src/services.c | 2 +- src/sockets.c | 2 +- src/transport.c | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/sdb.c b/src/sdb.c index f8c51fb..39b874a 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -647,8 +647,7 @@ void handle_packet(apacket *p, atransport *t) // Verify pointer p int result = access((const char *) p, F_OK); if ((result == -1) && (errno == EFAULT)) { - D("Invalid apacket = [0x%x]", p); - fatal("Invalid apacket = [0x%x]", p); + fatal("Invalid apacket = [0x%p]", p); } asocket *s; diff --git a/src/services.c b/src/services.c index e2b5928..84e959b 100644 --- a/src/services.c +++ b/src/services.c @@ -231,7 +231,7 @@ void get_tzplatform_env(int fd, void *cookie) { D("environment variable name: %s\n", env_name); enum tzplatform_variable env_id = tzplatform_getid(env_name); if (env_id != _TZPLATFORM_VARIABLES_INVALID_) { - char *env_value = tzplatform_getenv(env_id); + const char *env_value = tzplatform_getenv(env_id); if (env_value) { D("environment value : %s\n", env_value); snprintf(buf, sizeof(buf), "%d%s", NO_ERROR_TZPLATFORM_ENV, env_value); diff --git a/src/sockets.c b/src/sockets.c index 16e746e..4f3ec83 100644 --- a/src/sockets.c +++ b/src/sockets.c @@ -316,7 +316,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s) apacket *p = get_apacket(); unsigned char *x = p->data; size_t avail = MAX_PAYLOAD; - int r; + int r = 0; int is_eof = 0; while(avail > 0) { diff --git a/src/transport.c b/src/transport.c index 1fe4b9d..caecd13 100644 --- a/src/transport.c +++ b/src/transport.c @@ -327,8 +327,7 @@ static void *input_thread(void *_t) // Verify pointer p int result = access((const char *) p, F_OK); if ((result == -1) && (errno == EFAULT)) { - D("Invalid apacket = [0x%x]", p); - fatal("Invalid apacket = [0x%x]", p); + fatal("Invalid apacket = [0x%p]", p); } if(p->msg.command == A_SYNC){ -- 2.7.4 From 9e170e7f81c9995e46a2f51652ea6142062ca466 Mon Sep 17 00:00:00 2001 From: Yunjin Lee Date: Thu, 21 Jul 2016 10:48:07 +0900 Subject: [PATCH 09/16] Set SmackProcessLabel to System::Privileged Change-Id: I2420fc1d679607bd2d9b855ec9547a31ee98290e Signed-off-by: Yunjin Lee --- packaging/sdbd_device.service | 1 + packaging/sdbd_emulator.service | 1 + packaging/sdbd_tcp.service | 1 + 3 files changed, 3 insertions(+) diff --git a/packaging/sdbd_device.service b/packaging/sdbd_device.service index ac0ad44..cd60922 100644 --- a/packaging/sdbd_device.service +++ b/packaging/sdbd_device.service @@ -10,6 +10,7 @@ Type=forking EnvironmentFile=-/run/tizen-system-env PIDFile=/tmp/.sdbd.pid Restart=on-failure +SmackProcessLabel=System::Privileged ExecStart=/usr/sbin/sdbd [Install] diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index 5427780..bed8cce 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -12,6 +12,7 @@ Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes #ExecStartPre=/bin/bash -c "/bin/echo '10.0.2.15/32 system::debugging_network' >> /smack/netlabel" +SmackProcessLabel=System::Privileged ExecStart=/bin/sh -c "/usr/sbin/sdbd `/usr/bin/awk '{match($0, /sdb_port=([0-9]+)/,port_match); match($0, /vm_name=([^, ]*)/,vm_match); print \"--emulator=\" vm_match[1] \":\" port_match[1] \" --connect-to=10.0.2.2:26099\" \" --sensors=10.0.2.2:\"port_match[1]+3 }' /proc/cmdline`" [Install] diff --git a/packaging/sdbd_tcp.service b/packaging/sdbd_tcp.service index 46b4266..e360a7c 100644 --- a/packaging/sdbd_tcp.service +++ b/packaging/sdbd_tcp.service @@ -7,4 +7,5 @@ Type=forking Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes +SmackProcessLabel=System::Privileged ExecStart=/usr/sbin/sdbd --listen-port=26101 -- 2.7.4 From fb4847987e9d6a8f462e8af9f8040cd736dcd7a8 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Mon, 25 Jul 2016 16:56:52 +0900 Subject: [PATCH 10/16] Removed that debug-launchpad is started or stopped by sdbd Change-Id: Id6aa4c6d6fee7976b929c33d4b1b4ede0647dff1 Signed-off-by: shingil.kang --- src/sdb.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/sdb.c b/src/sdb.c index 39b874a..5667e73 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -139,9 +139,6 @@ void handle_sig_term(int sig) { if (access(SDB_PIDPATH, F_OK) == 0) sdb_unlink(SDB_PIDPATH); #endif - char * const cmd1_args[] = {"/usr/bin/killall", "/usr/bin/debug_launchpad_preloading_preinitializing_daemon", NULL}; - spawn("/usr/bin/killall", cmd1_args); - sdb_sleep_ms(1000); } static const char *sdb_device_banner = "device"; @@ -1560,12 +1557,6 @@ int set_sdk_user_privileges() { return 0; } -static void execute_required_process() { - char * const cmd_args[] = {"/usr/bin/debug_launchpad_preloading_preinitializing_daemon",NULL}; - - spawn("/usr/bin/debug_launchpad_preloading_preinitializing_daemon", cmd_args); -} - /* default plugin proc */ static int get_plugin_capability(const char* in_buf, sdbd_plugin_param out) { int ret = SDBD_PLUGIN_RET_NOT_SUPPORT; @@ -1910,8 +1901,6 @@ static void init_sdk_requirements() { } } - execute_required_process(); - if (is_emulator()) { register_bootdone_cb(); } -- 2.7.4 From c0ec4a47c302c53b1c27627eb376338457a16a5e Mon Sep 17 00:00:00 2001 From: woojin Date: Wed, 27 Jul 2016 16:54:46 +0900 Subject: [PATCH 11/16] get valgrind binary path from platform configuration get valgrind binary path from /etc/tizen-platform.conf so that valgrind terminates normally Change-Id: I7f88c193cd32a7c347122ce053851eb04b64d1b4 Signed-off-by: woojin --- script/profile_command | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/script/profile_command b/script/profile_command index f8abd42..32c3e80 100755 --- a/script/profile_command +++ b/script/profile_command @@ -8,6 +8,9 @@ FIND=/usr/bin/find GETAPPINSTALLPATH="/usr/bin/pkgcmd -a" PORTFILE=/tmp/port.da +source /etc/tizen-platform.conf +SDK_TOOLS_PATH=${TZ_SDK_TOOLS} + print_usage() { echo "usage: profile_command [options]" @@ -54,7 +57,7 @@ get_version() kill_valgrind() { - /bin/ps ax | /bin/grep "/home/developer/sdk_tools/valgrind/usr/bin/valgrin[d]" | /usr/bin/awk '{print "kill -3 " $1}' | /bin/sh + /bin/ps ax | /bin/grep "$SDK_TOOLS_PATH/valgrind/usr/bin/valgrin[d]" | /usr/bin/awk '{print "kill -3 " $1}' | /bin/sh } if test $# -ne 1 ; then -- 2.7.4 From 53773d3d66f46553c7b94ca8f24b89c2b4236bbf Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Fri, 29 Jul 2016 18:44:24 +0900 Subject: [PATCH 12/16] Added 'environment_variables' capability - Environment variables are applied to sdb shell process environment. - Each environment variable should be separated by new line character('\n'). e.g.) A=B\nC=D - The length of environment string should be less than 4096 byte. - The total number of environment variables should be less than 100. Change-Id: If5b52217b364ecf45eb88f0d8d3644cec40d3d30 Signed-off-by: shingil.kang --- src/sdb.c | 7 +++++++ src/sdbd_plugin.h | 5 +++-- src/services.c | 57 +++++++++++++++++++++++++++++++++++++------------------ src/strutils.c | 7 +++++-- src/strutils.h | 3 ++- 5 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/sdb.c b/src/sdb.c index 5667e73..22d2794 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1687,6 +1687,11 @@ static int verify_root_cmd(const char* in_buf, sdbd_plugin_param out) { return ret; } +static int get_shell_env(const char* in_buf, sdbd_plugin_param out) { + snprintf(out.data, out.len, "%s", ""); + return SDBD_PLUGIN_RET_SUCCESS; +} + int default_cmd_proc(const char* cmd, const char* in_buf, sdbd_plugin_param out) { int ret = SDBD_PLUGIN_RET_NOT_SUPPORT; @@ -1712,6 +1717,8 @@ int default_cmd_proc(const char* cmd, ret = verify_sdbd_launch(in_buf, out); } else if (SDBD_CMP_CMD(cmd, VERIFY_ROOTCMD)) { ret = verify_root_cmd(in_buf, out); + } else if (SDBD_CMP_CMD(cmd, SHELL_ENVVAR)) { + ret = get_shell_env(in_buf, out); } else { D("Not supported command : %s\n", cmd); ret = SDBD_PLUGIN_RET_NOT_SUPPORT; diff --git a/src/sdbd_plugin.h b/src/sdbd_plugin.h index 9bfc4b9..2d94157 100644 --- a/src/sdbd_plugin.h +++ b/src/sdbd_plugin.h @@ -26,6 +26,7 @@ #define SDBD_CMD_VERIFY_PEERIP "verify_peer_ip" #define SDBD_CMD_VERIFY_LAUNCH "verify_sdbd_launch" #define SDBD_CMD_VERIFY_ROOTCMD "verify_root_cmd" +#define SDBD_CMD_SHELL_ENVVAR "sdbd_shell_env_var" /* plugin capabilities */ #define SDBD_CAP_TYPE_SECURE "secure_protocol_support" @@ -36,8 +37,8 @@ #define SDBD_CAP_TYPE_ROOTONOFF "root_onoff_support" #define SDBD_CAP_TYPE_PLUGIN_VER "sdbd_plugin_version" #define SDBD_CAP_TYPE_PRODUCT_VER "product_version" -#define SDBD_CAP_TYPE_LOG_ENABLE "sdbd_log_enable" -#define SDBD_CAP_TYPE_LOG_PATH "sdbd_log_path" +#define SDBD_CAP_TYPE_LOG_ENABLE "sdbd_log_enable" +#define SDBD_CAP_TYPE_LOG_PATH "sdbd_log_path" /* capability return string */ #define SDBD_CAP_RET_ENABLED "enabled" diff --git a/src/services.c b/src/services.c index 84e959b..bc2f35a 100644 --- a/src/services.c +++ b/src/services.c @@ -57,7 +57,6 @@ struct stinfo { void *cookie; }; - void *service_bootstrap_func(void *x) { stinfo *sti = x; @@ -599,22 +598,16 @@ static int create_subproc_thread(const char *name, int lines, int columns) char *trim_value = NULL; char path[PATH_MAX]; memset(path, 0, sizeof(path)); - - char *envp[] = { - "TERM=linux", /* without this, some programs based on screen can't work, e.g. top */ - "DISPLAY=:0", /* without this, some programs based on without launchpad can't work */ - NULL, - NULL, - NULL, - NULL, - NULL - }; + char *envp[MAX_TOKENS]; + int envp_cnt = 0; + envp[envp_cnt++] = strdup("TERM=linux"); + envp[envp_cnt++] = strdup("DISPLAY=:0"); if (should_drop_privileges()) { if (g_sdk_home_dir_env) { - envp[2] = g_sdk_home_dir_env; + envp[envp_cnt++] = strdup(g_sdk_home_dir_env); } else { - envp[2] = "HOME=/home/owner"; + envp[envp_cnt++] = strdup("HOME=/home/owner"); } get_env("ENV_PATH", &value); } else { @@ -622,7 +615,7 @@ static int create_subproc_thread(const char *name, int lines, int columns) if(value == NULL) { get_env("ENV_ROOTPATH", &value); } - envp[2] = "HOME=/root"; + envp[envp_cnt++] = strdup("HOME=/root"); } if (value != NULL) { trim_value = str_trim(value); @@ -633,15 +626,32 @@ static int create_subproc_thread(const char *name, int lines, int columns) } else { snprintf(path, sizeof(path), "%s", trim_value); } - envp[3] = path; + envp[envp_cnt++] = strdup(path); } else { snprintf(path, sizeof(path), "%s", value); - envp[3] = path; + envp[envp_cnt++] = strdup(path); } free(value); } - D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]); + /* get environment variables from plugin */ + char *envp_plugin = NULL; + envp_plugin = malloc(SDBD_PLUGIN_OUTBUF_MAX); + if (envp_plugin == NULL) { + D("Cannot allocate the shell commnad buffer."); + return -1; + } + memset(envp_plugin, 0, SDBD_PLUGIN_OUTBUF_MAX); + if (!request_plugin_cmd(SDBD_CMD_SHELL_ENVVAR, "", envp_plugin, SDBD_PLUGIN_OUTBUF_MAX)) { + D("Failed to convert the shell command. (%s)\n", name); + free(envp_plugin); + return -1; + } else { + if(envp_plugin[0] != '\0') { + envp_cnt = tokenize_append(envp_plugin, "\n", envp, MAX_TOKENS, envp_cnt); + } + } + free(envp_plugin); if(name) { // in case of shell execution directly // Check the shell command validation. @@ -709,6 +719,18 @@ static int create_subproc_thread(const char *name, int lines, int columns) } #endif } + + /* free environment variables */ + int i = 0; + if(envp_cnt > 0) { + for(i = 0; i < envp_cnt; i++) { + if(envp[i]) { + D("envp[%d] = %s\n", i, envp[i]); + free(envp[i]); + } + } + } + D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); if (ret_fd < 0) { @@ -958,7 +980,6 @@ static void get_capability(int fd, void *cookie) { offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "log_path", g_capabilities.log_path); - offset++; // for '\0' character writex(fd, &offset, sizeof(uint16_t)); diff --git a/src/strutils.c b/src/strutils.c index 910e3be..cba6a23 100644 --- a/src/strutils.c +++ b/src/strutils.c @@ -8,9 +8,12 @@ #define PATH_MAX 4096 #endif - size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_tokens ) { - int cnt = 0; + return tokenize_append(str, delim, tokens, max_tokens, 0); +} + +size_t tokenize_append(const char *str, const char *delim, char *tokens[], size_t max_tokens, int append_position) { + int cnt = append_position; char tmp[PATH_MAX+1]; char *ptr; diff --git a/src/strutils.h b/src/strutils.h index 897579f..e101091 100644 --- a/src/strutils.h +++ b/src/strutils.h @@ -1,9 +1,10 @@ #ifndef _STRUTILS_H_ #define _STRUTILS_H_ -#define MAX_TOKENS 30 +#define MAX_TOKENS 100 size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_tokens); +size_t tokenize_append(const char *str, const char *delim, char *tokens[], size_t max_tokens, int append_position); void free_strings(char **array, int n); int read_line(const int fd, char* ptr, const unsigned int maxlen); char *s_strncpy(char *dest, const char *source, size_t n); -- 2.7.4 From dac34aa6a9feae52a3a986ccda169026dfd63c5b Mon Sep 17 00:00:00 2001 From: Kim Gunsoo Date: Mon, 11 Jan 2016 13:39:14 +0900 Subject: [PATCH 13/16] Checks whether socket transport is duplicated. - When connecting with sdb server, to prevent abnormal connection request the check routine is added. Change-Id: Ifd59f87f826dba442aa5af08145a5dcab9fd61c8 Signed-off-by: Kim Gunsoo --- src/transport.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- src/transport_local.c | 3 +++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/transport.c b/src/transport.c index caecd13..2083fbc 100644 --- a/src/transport.c +++ b/src/transport.c @@ -32,6 +32,12 @@ static atransport transport_list = { .prev = &transport_list, }; +static atransport pending_list = { + .next = &pending_list, + .prev = &pending_list, +}; + + SDB_MUTEX_DEFINE( transport_lock ); #if SDB_TRACE @@ -302,7 +308,7 @@ static void *output_thread(void *_t) } oops: - D("%s: transport output thread is exiting\n", t->serial); + D("%s: transport output thread is exiting, fd %d, sfd %d\n", t->serial, t->fd, t->sfd); kick_transport(t); transport_unref(t); return 0; @@ -360,7 +366,7 @@ static void *input_thread(void *_t) // while a client socket is still active. close_all_sockets(t); - D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd); + D("%s: transport input thread is exiting, fd %d, sfd %d\n", t->serial, t->fd, t->sfd); kick_transport(t); transport_unref(t); return 0; @@ -649,8 +655,13 @@ static void transport_registration_func(int _fd, unsigned ev, void *data) } } - /* put us on the master device list */ sdb_mutex_lock(&transport_lock); + if (t->type == kTransportLocal) { + /* remove the transport from pending list */ + t->next->prev = t->prev; + t->prev->next = t->next; + } + /* put us on the master device list */ t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; @@ -709,7 +720,7 @@ static void transport_unref_locked(atransport *t) { t->ref_count--; if (t->ref_count == 0) { - D("transport: %s unref (kicking and closing)\n", t->serial); + D("transport: %s unref (kicking and closing), fd %d, sfd %d\n", t->serial, t->fd, t->sfd); if (!t->kicked) { t->kicked = 1; t->kick(t); @@ -910,9 +921,35 @@ void register_socket_transport(int s, const char *serial, int port, int local, c #endif return; } - if(serial) { - t->serial = strdup(serial); - } + + /* Allow ONLY a single connection with sdb server. */ + sdb_mutex_lock(&transport_lock); + atransport *old_t; + for(old_t = pending_list.next; old_t != &pending_list; old_t = old_t->next) { + if (old_t->serial && !strcmp(serial, old_t->serial)) { + sdb_mutex_unlock(&transport_lock); + sdb_close(s); + free(t); + return; + } + } + + for(old_t = transport_list.next; old_t != &transport_list; old_t = old_t->next) { + if (old_t->serial && !strcmp(serial, old_t->serial)) { + sdb_mutex_unlock(&transport_lock); + sdb_close(s); + free(t); + return; + } + } + + t->next = &pending_list; + t->prev = pending_list.prev; + t->next->prev = t; + t->prev->next = t; + t->serial = strdup(serial); + sdb_mutex_unlock(&transport_lock); + #if SDB_HOST /* tizen specific */ if (device_name) {/* tizen specific */ t->device_name = strdup(device_name); diff --git a/src/transport_local.c b/src/transport_local.c index 527e1f5..ff4aa36 100644 --- a/src/transport_local.c +++ b/src/transport_local.c @@ -296,6 +296,9 @@ static void *server_socket_thread(void * arg) } else { register_socket_transport(fd, "host", port, 1, NULL); } + } else { + D("failed to accept() from sdb server\n"); + //FIXME: implements error handle for EMFILE or ENFILE } } D("transport: server_socket_thread() exiting\n"); -- 2.7.4 From 4523b8e3c98535323865e17d6d53ae183d04b7c3 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Tue, 9 Aug 2016 17:49:14 +0900 Subject: [PATCH 14/16] Fixed the build problem for emulator 64 bit architecture. - modified the way which determines device type (emulator or target) Change-Id: I1742336fcf128649362d4b855777fa6312636b8d Signed-off-by: shingil.kang --- packaging/sdbd.spec | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index e8539f8..a880c80 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.12 +Version: 3.0.13 Release: 0 License: Apache-2.0 Summary: SDB daemon @@ -41,7 +41,7 @@ cp %{SOURCE1003} . %else %define wearable_profile off %endif -%ifarch %{ix86} +%if %{with emulator} %define target_arch x86 %else %define target_arch arm @@ -57,17 +57,16 @@ mkdir -p %{buildroot}/usr/share/license cp LICENSE %{buildroot}/usr/share/license/%{name} %make_install -mkdir -p %{buildroot}%{_libdir}/systemd/system mkdir -p %{buildroot}%{_unitdir} -%ifarch %{ix86} +%if %{with emulator} %if "%{profile}" == "tv" -install -m 0644 %SOURCE1006 %{buildroot}%{_libdir}/systemd/system/sdbd.service +install -m 0644 %SOURCE1006 %{buildroot}%{_unitdir}/sdbd.service %else -install -m 0644 %SOURCE1002 %{buildroot}%{_libdir}/systemd/system/sdbd.service +install -m 0644 %SOURCE1002 %{buildroot}%{_unitdir}/sdbd.service %endif -mkdir -p %{buildroot}/%{_libdir}/systemd/system/emulator_preinit.target.wants -ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/emulator_preinit.target.wants/ +mkdir -p %{buildroot}/%{_unitdir}/emulator_preinit.target.wants +ln -s %{_unitdir}/sdbd.service %{buildroot}/%{_unitdir}/emulator_preinit.target.wants/ %else %if "%{profile}" == "tv" @@ -76,8 +75,8 @@ install -m 0644 %SOURCE1005 %{buildroot}%{_unitdir}/sdbd.service install -m 0644 %SOURCE1001 %{buildroot}%{_unitdir}/sdbd.service %endif install -m 0644 %SOURCE1004 %{buildroot}%{_unitdir}/sdbd_tcp.service -mkdir -p %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants -ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/multi-user.target.wants/ +mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants +ln -s %{_unitdir}/sdbd.service %{buildroot}/%{_unitdir}/multi-user.target.wants/ %endif mkdir -p %{buildroot}%{_prefix}/sbin @@ -105,11 +104,11 @@ fi %{_prefix}/sbin/sdk_launch %attr(0755, root, root) %{_sysconfdir}/init.d/sdbd %{_unitdir}/sdbd.service -%ifarch %{ix86} -%{_libdir}/systemd/system/emulator_preinit.target.wants/sdbd.service +%if %{with emulator} +%{_unitdir}/emulator_preinit.target.wants/sdbd.service %else %{_unitdir}/sdbd_tcp.service -%{_libdir}/systemd/system/multi-user.target.wants/sdbd.service +%{_unitdir}/multi-user.target.wants/sdbd.service %endif /usr/share/license/%{name} %{TZ_SYS_BIN}/profile_command -- 2.7.4 From f17729d36596c1bb347a3ade5d86f6d05bd931e3 Mon Sep 17 00:00:00 2001 From: greatim Date: Thu, 25 Aug 2016 20:05:12 +0900 Subject: [PATCH 15/16] change umask value to 022 from 000 because of security reason change umask value to 022 from 000 because of security reason add S_IWOTH for pushed file to owner's content directory Change-Id: Ie0677c4bfa8c494c13ab0ac32cdb730f90d22864 Signed-off-by: greatim --- src/file_sync_service.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++-- src/sdb.c | 10 +++---- src/sdb.h | 2 ++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/file_sync_service.c b/src/file_sync_service.c index 5fc6642..b0a0f07 100644 --- a/src/file_sync_service.c +++ b/src/file_sync_service.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -58,6 +59,8 @@ struct sync_permit_rule sdk_sync_permit_rule[] = { */ #define DIR_PERMISSION 0777 +static struct tzplatform_context* sdk_user_context = NULL; + void init_sdk_sync_permit_rule_regx(void) { int ret; @@ -334,6 +337,62 @@ static void sync_mediadb(char *path) { return; } +static void deinit_sdk_user_context(void) { + if (sdk_user_context != NULL) { + tzplatform_context_destroy(sdk_user_context); + sdk_user_context = NULL; + } +} + +// return 0 if success to initialize +// return negative value otherwise +static int init_sdk_user_context() { + if (sdk_user_context == NULL) { + int ret = tzplatform_context_create(&sdk_user_context); + if (ret < 0) { + D ("failed to create tzplatform context by error (%d)\n", ret); + return ret; + } + + ret = tzplatform_context_set_user(sdk_user_context, g_sdk_user_id); + if (ret < 0) { + D ("failed to set user to sdk_user_context\n"); + return ret; + } + + atexit(deinit_sdk_user_context); + } + + return 0; +} + +// return 1 if given directory is writable by others +// return 0 otherwise +static int is_writable_by_others(char* path) { + int ret = 0; + + if ( init_sdk_user_context() == 0 ) { + const char* content_path = tzplatform_context_getenv(sdk_user_context, TZ_USER_CONTENT); + char* abpath = realpath(path, NULL); + D ("tzplatform getenv : %s\n", content_path); + + if (abpath != NULL) { + if (strncmp(abpath, content_path, strlen(content_path)) == 0) { + D("path (%s) is writable by others\n", path); + ret = 1; + } + free(abpath); + } else { + D("failed to get realpath of (%s)\n", path); + } + } else { + // do nothing + // no directory is writable by others + } + + return ret; +} + static int handle_send_file(int s, int noti_fd, char *path, mode_t mode, char *buffer) { syncmsg msg; @@ -495,6 +554,8 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) return -1; } + D("send path (%s)\n", path); + tmp = strrchr(path,','); if(tmp) { *tmp = 0; @@ -505,7 +566,6 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) #endif // extracts file permission from stat.mode. (ex 100644 & 0777 = 644); mode &= 0777; // combination of (S_IRWXU | S_IRWXG | S_IRWXO) - mode |= S_IWOTH; // SDK requirement from N_SE-43337 } if(!tmp || errno) { mode = 0644; // set default permission value in most of unix system. @@ -523,7 +583,6 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) // sdb does not allow to check that file exists or not. After deleting old file and creating new file again unconditionally. sdb_unlink(path); - #ifdef HAVE_SYMLINKS if(is_link) ret = handle_send_link(s, noti_fd, path, buffer); @@ -539,6 +598,13 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) //mode |= ((mode >> 3) & 0070); //mode |= ((mode >> 3) & 0007); ret = handle_send_file(s, noti_fd, path, mode, buffer); + if (is_writable_by_others(path)) { + mode_t realmode = mode & ~(SDBD_UMASK); + realmode |= S_IWOTH; + if (chmod(path, realmode) != 0) { + D ("failed to chmod of writable path by others\n"); + } + } } return ret; diff --git a/src/sdb.c b/src/sdb.c index 22d2794..a30b3c4 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1084,9 +1084,6 @@ void start_device_log(void) int daemonize(void) { - // set file creation mask to 0 - umask(0); - switch (fork()) { case -1: return -1; @@ -1095,6 +1092,11 @@ int daemonize(void) { default: _exit(0); } + + // 2016-08-25 : modified umask to 022 from 000 because of security reason + // there is a problem that the file created by sdb shell command could be written by 'others' + umask(SDBD_UMASK); + #ifdef SDB_PIDPATH FILE *f = fopen(SDB_PIDPATH, "w"); @@ -2200,8 +2202,6 @@ int sdb_main(int is_daemon, int server_port) D("sdbd should be launched in develop mode.\n"); return -1; } - - umask(000); #endif atexit(sdb_cleanup); diff --git a/src/sdb.h b/src/sdb.h index c9a9e0c..36f28e1 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -47,6 +47,8 @@ #define SDB_SERVER_VERSION 0 // Increment this when we want to force users to start a new sdb server +#define SDBD_UMASK 0022 // default file creation mask of sdbd + typedef struct amessage amessage; typedef struct apacket apacket; typedef struct asocket asocket; -- 2.7.4 From 6c50e44f5468b1b905a5d8692942361a8e41b103 Mon Sep 17 00:00:00 2001 From: Jaewon Lim Date: Tue, 4 Oct 2016 04:13:51 -0700 Subject: [PATCH 16/16] Revert "change umask value to 022 from 000 because of security reason" This reverts commit f17729d36596c1bb347a3ade5d86f6d05bd931e3. Change-Id: Id9368d876bf0c3cfe068d7e4567dff8b4bec135b --- src/file_sync_service.c | 70 ++----------------------------------------------- src/sdb.c | 10 +++---- src/sdb.h | 2 -- 3 files changed, 7 insertions(+), 75 deletions(-) diff --git a/src/file_sync_service.c b/src/file_sync_service.c index b0a0f07..5fc6642 100644 --- a/src/file_sync_service.c +++ b/src/file_sync_service.c @@ -14,7 +14,6 @@ * limitations under the License. */ -#include #include #include #include @@ -59,8 +58,6 @@ struct sync_permit_rule sdk_sync_permit_rule[] = { */ #define DIR_PERMISSION 0777 -static struct tzplatform_context* sdk_user_context = NULL; - void init_sdk_sync_permit_rule_regx(void) { int ret; @@ -337,62 +334,6 @@ static void sync_mediadb(char *path) { return; } -static void deinit_sdk_user_context(void) { - if (sdk_user_context != NULL) { - tzplatform_context_destroy(sdk_user_context); - sdk_user_context = NULL; - } -} - -// return 0 if success to initialize -// return negative value otherwise -static int init_sdk_user_context() { - if (sdk_user_context == NULL) { - int ret = tzplatform_context_create(&sdk_user_context); - if (ret < 0) { - D ("failed to create tzplatform context by error (%d)\n", ret); - return ret; - } - - ret = tzplatform_context_set_user(sdk_user_context, g_sdk_user_id); - if (ret < 0) { - D ("failed to set user to sdk_user_context\n"); - return ret; - } - - atexit(deinit_sdk_user_context); - } - - return 0; -} - -// return 1 if given directory is writable by others -// return 0 otherwise -static int is_writable_by_others(char* path) { - int ret = 0; - - if ( init_sdk_user_context() == 0 ) { - const char* content_path = tzplatform_context_getenv(sdk_user_context, TZ_USER_CONTENT); - char* abpath = realpath(path, NULL); - D ("tzplatform getenv : %s\n", content_path); - - if (abpath != NULL) { - if (strncmp(abpath, content_path, strlen(content_path)) == 0) { - D("path (%s) is writable by others\n", path); - ret = 1; - } - free(abpath); - } else { - D("failed to get realpath of (%s)\n", path); - } - } else { - // do nothing - // no directory is writable by others - } - - return ret; -} - static int handle_send_file(int s, int noti_fd, char *path, mode_t mode, char *buffer) { syncmsg msg; @@ -554,8 +495,6 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) return -1; } - D("send path (%s)\n", path); - tmp = strrchr(path,','); if(tmp) { *tmp = 0; @@ -566,6 +505,7 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) #endif // extracts file permission from stat.mode. (ex 100644 & 0777 = 644); mode &= 0777; // combination of (S_IRWXU | S_IRWXG | S_IRWXO) + mode |= S_IWOTH; // SDK requirement from N_SE-43337 } if(!tmp || errno) { mode = 0644; // set default permission value in most of unix system. @@ -583,6 +523,7 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) // sdb does not allow to check that file exists or not. After deleting old file and creating new file again unconditionally. sdb_unlink(path); + #ifdef HAVE_SYMLINKS if(is_link) ret = handle_send_link(s, noti_fd, path, buffer); @@ -598,13 +539,6 @@ static int do_send(int s, int noti_fd, char *path, char *buffer) //mode |= ((mode >> 3) & 0070); //mode |= ((mode >> 3) & 0007); ret = handle_send_file(s, noti_fd, path, mode, buffer); - if (is_writable_by_others(path)) { - mode_t realmode = mode & ~(SDBD_UMASK); - realmode |= S_IWOTH; - if (chmod(path, realmode) != 0) { - D ("failed to chmod of writable path by others\n"); - } - } } return ret; diff --git a/src/sdb.c b/src/sdb.c index a30b3c4..22d2794 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1084,6 +1084,9 @@ void start_device_log(void) int daemonize(void) { + // set file creation mask to 0 + umask(0); + switch (fork()) { case -1: return -1; @@ -1092,11 +1095,6 @@ int daemonize(void) { default: _exit(0); } - - // 2016-08-25 : modified umask to 022 from 000 because of security reason - // there is a problem that the file created by sdb shell command could be written by 'others' - umask(SDBD_UMASK); - #ifdef SDB_PIDPATH FILE *f = fopen(SDB_PIDPATH, "w"); @@ -2202,6 +2200,8 @@ int sdb_main(int is_daemon, int server_port) D("sdbd should be launched in develop mode.\n"); return -1; } + + umask(000); #endif atexit(sdb_cleanup); diff --git a/src/sdb.h b/src/sdb.h index 36f28e1..c9a9e0c 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -47,8 +47,6 @@ #define SDB_SERVER_VERSION 0 // Increment this when we want to force users to start a new sdb server -#define SDBD_UMASK 0022 // default file creation mask of sdbd - typedef struct amessage amessage; typedef struct apacket apacket; typedef struct asocket asocket; -- 2.7.4