--- /dev/null
+Kangho Kim <kh5325.kim@samsung.com>
+Ho Namkoong <ho.namkoong@samsung.com>
+Yoonki Park <yoonki.park@samsung.com>
+HyunGoo Kang <hyungoo1.kang@samsung.com>
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
-SDB_SRC_FILES := \
- src/sdb.c \
- src/console.c \
- src/transport.c \
- src/transport_local.c \
- src/transport_usb.c \
- src/commandline.c \
- src/sdb_client.c \
- src/sockets.c \
- src/services.c \
- src/file_sync_client.c \
- src/usb_linux.c \
- src/get_my_path_linux.c \
- src/utils.c \
- src/usb_vendors.c \
- src/fdevent.c \
- src/socket_inaddr_any_server.c \
- src/socket_local_client.c \
- src/socket_local_server.c \
- src/socket_loopback_client.c \
- src/socket_loopback_server.c \
- src/socket_network_client.c
+#
+#
+# Makefile for sdbd
+#
-SDB_CFLAGS := -O2 -g -DSDB_HOST=1 -Wall -Wno-unused-parameter
-SDB_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
-SDB_CFLAGS += -DHAVE_FORKEXEC
-SDB_LFLAGS := -lrt -lncurses
+#
+HOST_OS := $(shell uname -s | tr A-Z a-z)
+
+# sdb host tool
+# =========================================================
SDBD_SRC_FILES := \
src/sdb.c \
src/sockets.c \
src/services.c \
src/file_sync_service.c \
- src/jdwp_service.c \
- src/framebuffer_service.c \
- src/remount_service.c \
src/usb_linux_client.c \
src/utils.c \
src/socket_inaddr_any_server.c \
src/socket_local_server.c \
src/socket_loopback_client.c \
src/socket_loopback_server.c \
- src/socket_network_client.c
+ src/socket_network_client.c \
+ src/sdktools.c \
+ src/strutils.c \
+ src/fileutils.c
SDBD_CFLAGS := -O2 -g -DSDB_HOST=0 -Wall -Wno-unused-parameter
SDBD_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
-SDBD_CFLAGS += -DHAVE_FORKEXEC -fPIE
-
-IFLAGS := -Iinclude -Isrc
+SDBD_CFLAGS += -DHAVE_FORKEXEC -fPIE -D_DROP_PRIVILEGE -D_FILE_OFFSET_BITS=64
+SDBD_LFLAGS := -lcapi-system-info -lvconf -lsmack
+IFLAGS := -Iinclude -Isrc -I/usr/include/system -I/usr/include/vconf
OBJDIR := bin
INSTALLDIR := usr/sbin
-INITSCRIPTDIR := etc/init.d
-RCSCRIPTDIR := etc/rc.d/rc3.d
UNAME := $(shell uname -sm)
ifneq (,$(findstring 86,$(UNAME)))
all : $(MODULE)
-sdb : $(SDB_SRC_FILES)
- mkdir -p $(OBJDIR)
- $(CC) -pthread -o $(OBJDIR)/$(MODULE) $(SDB_CFLAGS) $(SDB_LFLAGS) $(IFLAGS) $(SDB_SRC_FILES)
-
sdbd : $(SDBD_SRC_FILES)
mkdir -p $(OBJDIR)
- $(CC) -pthread -o $(OBJDIR)/$(MODULE) $(SDBD_CFLAGS) $(IFLAGS) $(SDBD_SRC_FILES)
+ $(CC) -pthread -o $(OBJDIR)/$(MODULE) $(SDBD_CFLAGS) $(IFLAGS) $(SDBD_SRC_FILES) $(SDBD_LFLAGS)
install :
mkdir -p $(DESTDIR)/$(INSTALLDIR)
install $(OBJDIR)/$(MODULE) $(DESTDIR)/$(INSTALLDIR)/$(MODULE)
-ifeq ($(MODULE),sdbd)
- mkdir -p $(DESTDIR)/$(INITSCRIPTDIR)
- install script/sdbd $(DESTDIR)/$(INITSCRIPTDIR)/sdbd
-endif
-ifeq ($(TARGET_ARCH),x86)
- mkdir -p $(DESTDIR)/$(RCSCRIPTDIR)
- install script/S06sdbd $(DESTDIR)/$(RCSCRIPTDIR)/S06sdbd
-endif
clean :
rm -rf $(OBJDIR)/*
--- /dev/null
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
--- /dev/null
+* Thu Nov 27 2014 Sanghoon Hong <sanghoon.hong@samsung.com>
+ - added a notify thread for emulator detection
+ - fixed a broken connection issue while 'pull'ing files
+* Wed Nov 27 2013 Yoonki Park <yoonki.park@samsung.com>
+ - changed port redirection to usb0 instead of loopback
+* Wed Apr 04 2013 Ho Namkoong <ho.namkoong@samsung.com>
+ - supports platform gdbserver
+* Mon Dec 02 2012 Yoonki Park <yoonki.park@samsung.com>
+ - supports cs report service using inotify
+* Mon Dec 02 2012 Yoonki Park <yoonki.park@samsung.com>
+ - sdb code dropped from adb (Ice Cream Samdwich 4.1.1)
+* Wed Apr 18 2012 Yoonki Park <yoonki.park@samsung.com>
+ - set dir permission to 777
+* Sat Mar 31 2012 Yoonki Park <yoonki.park@samsung.com>
+ - let sshd be daemon and create sshd.pid file
--- /dev/null
+[Unit]
+Description=sdbd
+
+[Service]
+Type=forking
+PIDFile=/tmp/.sdbd.pid
+RemainAfterExit=yes
+ExecStart=/usr/sbin/sdbd
Name: sdbd
+Version: 2.2.23
+Release: 1
+License: Apache-2.0
Summary: SDB daemon
-Version: 0.0.2
-Release: 2
-Group: TO_BE/FILLED_IN
-License: TO BE FILLED IN
+Group: System/Utilities
Source0: %{name}-%{version}.tar.gz
+Source1001: sdbd_device.service
+Source1002: sdbd_emulator.service
-%description
-Description: SDB daemon
+BuildRequires: capi-system-info-devel
+BuildRequires: vconf-devel
+BuildRequires: smack-devel
+Requires: default-files-tizen
+Requires: sys-assert
+Requires: debug-launchpad
+Requires: dbus
+%description
+Description: SDB daemon.
%prep
%setup -q
%build
make %{?jobs:-j%jobs}
-
%install
-rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+
%make_install
+mkdir -p %{buildroot}%{_libdir}/systemd/system
+%ifarch %{ix86}
+install -m 0644 %SOURCE1002 %{buildroot}%{_libdir}/systemd/system/sdbd.service
+mkdir -p %{buildroot}/%{_libdir}/systemd/system/emulator.target.wants
+ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}/%{_libdir}/systemd/system/emulator.target.wants/
+mkdir -p %{buildroot}%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/
+ln -s %{_libdir}/systemd/system/sdbd.service %{buildroot}%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/
+
+%else
+install -m 0644 %SOURCE1001 %{buildroot}%{_libdir}/systemd/system/sdbd.service
+%endif
+
+mkdir -p %{buildroot}%{_prefix}/sbin
+install -m 755 script/sdk_launch %{buildroot}%{_prefix}/sbin/
+
+mkdir -p %{buildroot}/usr/bin
+install -m 755 script/profile_command %{buildroot}/usr/bin/
+
+%post
+chsmack -a sdbd::home /home/developer
+chsmack -t /home/developer
%files
-%defattr(-,root,root,-)
+%manifest sdbd.manifest
+%defattr(-,root,root,-)
%{_prefix}/sbin/sdbd
-%{_sysconfdir}/init.d/sdbd
-
+%{_prefix}/sbin/sdk_launch
+%{_libdir}/systemd/system/sdbd.service
%ifarch %{ix86}
-%{_sysconfdir}/rc.d/rc3.d
+%{_libdir}/systemd/system/emulator.target.wants/sdbd.service
+%{_sysconfdir}/systemd/default-extra-dependencies/ignore-units.d/sdbd.service
%endif
+/usr/share/license/%{name}
+/usr/bin/profile_command
%changelog
-* Wed Apr 18 2012 Yoonki Park <yoonki.park@samsung.com>
- - set dir permission to 777
-* Sat Mar 31 2012 Yoonki Park <yoonki.park@samsung.com>
- - let sshd be daemon and create sshd.pid file
+
--- /dev/null
+[Unit]
+Description=sdbd
+
+[Service]
+Type=forking
+Environment=DISPLAY=:0
+PIDFile=/tmp/.sdbd.pid
+RemainAfterExit=yes
+ExecStart=/usr/sbin/sdbd
--- /dev/null
+[Unit]
+Description=sdbd
+
+[Service]
+Type=forking
+Environment=DISPLAY=:0
+PIDFile=/tmp/.sdbd.pid
+RemainAfterExit=yes
+ExecStartPre=/bin/bash -c "/bin/echo `/bin/sed 's/^.*sdb_port=\([^, ]*\).*$/\1/g' /proc/cmdline` > /opt/home/sdb_port.txt"
+ExecStart=/usr/sbin/sdbd
+
+[Install]
+WantedBy=emulator.target
+
+++ /dev/null
-#!/bin/sh
-/etc/init.d/sdbd start
--- /dev/null
+#!/bin/bash
+
+VERSION="3.0"
+KILL=/usr/bin/killall
+MANAGER=/usr/bin/da_manager
+FIND=/usr/bin/find
+GETAPPINSTALLPATH="/usr/bin/pkgcmd -a"
+PORTFILE=/tmp/port.da
+READLINK=/usr/bin/readlink
+
+print_usage()
+{
+ echo "usage: profile_command [options]"
+ echo "Options:"
+ echo "getprobemap get da_api_map"
+ echo "killmanager terminate da_manager"
+ echo "runmanager execute da_manager"
+ echo "findunittest find unittest project"
+ echo "getversion get version"
+ echo "killvalgrind kill valgrind process"
+ echo "readlink filepath get value of given symbolic link or canonical file name"
+}
+
+get_probe_map()
+{
+ /bin/cat /usr/lib/da_api_map
+}
+
+kill_manager()
+{
+ $KILL $MANAGER
+ /bin/rm -f $PORTFILE
+}
+
+run_manager()
+{
+ kill_manager
+ $MANAGER
+}
+
+find_unittest()
+{
+ $FIND `$GETAPPINSTALLPATH | /usr/bin/awk '{if (FNR==1) printf $NF}'` -name *.unittest
+}
+
+process_list()
+{
+ /bin/ps -eo pid,cmd
+}
+
+get_version()
+{
+ echo $VERSION
+}
+
+read_link()
+{
+ $READLINK -f $FILEPATH
+}
+
+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
+}
+
+if test $# -gt 2 -o $# -lt 1; then
+ print_usage
+ exit 1
+fi
+
+if test -n "$2"; then
+ case "$1" in
+ readlink)
+ FILEPATH=$2
+ ;;
+ *)
+ print_usage
+ exit 1
+ ;;
+ esac
+fi
+
+case "$1" in
+ killmanager)
+ kill_manager
+ ;;
+ runmanager)
+ run_manager
+ ;;
+ findunittest)
+ find_unittest
+ ;;
+ process)
+ process_list
+ ;;
+ getversion)
+ get_version
+ ;;
+ readlink)
+ read_link
+ ;;
+ killvalgrind)
+ kill_valgrind
+ ;;
+ getprobemap)
+ get_probe_map
+ ;;
+ *)
+ echo "Unknown option!"
+ print_usage
+ ;;
+esac
+++ /dev/null
-#! /bin/sh
-
-. /lib/lsb/init-functions
-
-export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
-
-case "$1" in
- start)
- log_daemon_msg "Starting SDB Daemon..." "sdbd"
- if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sdbd.pid --exec /usr/sbin/sdbd; then
- log_end_msg 0
- else
- log_end_msg 1
- fi
- ;;
- stop)
- log_daemon_msg "Stopping SDB Daemon..." "sdbd"
- if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sdbd.pid; then
- log_end_msg 0
- else
- log_end_msg 1
- fi
- ;;
- restart)
- log_daemon_msg "Restarting SDB Daemon..." "sdbd"
- start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sdbd.pid
- sleep 1
- if start-stop-daemon --start --quiet --pidfile /var/run/sdbd.pid --exec /usr/sbin/sdbd; then
- log_end_msg 0
- else
- log_end_msg 1
- fi
- ;;
- *)
- log_action_msg "Usage: /etc/init.d/sdbd {start|stop|restart}"
- exit 1
-esac
-
-exit 0
--- /dev/null
+#!/bin/bash
+
+# Authors:
+# Kangho Kim <kh5325.kim@samsung.com>, Yoonki Park <yoonki.park@samsung.com>
+#
+# Description: front hand of app launcher
+
+APP_PATH_PREFIX=/opt/apps
+SDK_TOOLS_PATH=/home/developer/sdk_tools
+
+print_usage()
+{
+ echo "usage: $0 [-a <appid>] [-p <pkgid>] [-e <executable>] -m <run|debug|da|oprofile> [-P <port>] [-attach <pid>] -t <gtest,gcov> [<args...>]"
+}
+
+first="true"
+
+until [ -z "$1" ]; do
+ case "$1" in
+ -a)
+ if [ -z "$2" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ appid=$2
+ shift 2;
+ ;;
+ -p)
+ if [ -z "$2" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ pkgid=$2
+ shift 2;
+ ;;
+ -e)
+ if [ -z "$2" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ exe=${2/%.exe/}
+ shift 2;
+ ;;
+ -m)
+ if [ "$2" != "run" ] && [ "$2" != "debug" ] && [ "$2" != "da" ] && [ "$2" != "oprofile" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ mode=$2
+ shift 2;
+ ;;
+ -P)
+ if [ -z "$2" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ port=$2
+ shift 2;
+ ;;
+ -attach)
+ if [ -z "$2" ]
+ then
+ print_usage
+ exit 1;
+ fi
+ attach_id=$2
+ shift 2;
+ ;;
+ -t)
+ if [ "$2" = "" ] || [ ${2:0:1} = "-" ]
+ then
+ shift 1;
+ else
+# parse -t option
+ OLD_IFS=$IFS;IFS=,;
+ for type in $2;do
+ if [ "$type" = "gtest" ]
+ then
+ COV_TEST_PREFIX="export LD_LIBRARY_PATH=%s/gtest/usr/lib && $COV_TEST_PREFIX"
+ if [ "" != "$result_mode" ]
+ then
+ result_mode="$result_mode,UNIT_TEST"
+ else
+ launch_app_mode="__LAUNCH_APP_MODE__ SYNC"
+ result_mode="UNIT_TEST"
+ fi
+ fi
+ if [ "$type" = "gcov" ]
+ then
+ COV_TEST_PREFIX="export GCOV_PREFIX=/tmp/%s/data && export GCOV_PREFIX_STRIP=0 && $COV_TEST_PREFIX"
+ if [ "" != "$result_mode" ]
+ then
+ result_mode="$result_mode,CODE_COVERAGE"
+ else
+ launch_app_mode="__LAUNCH_APP_MODE__ SYNC"
+ result_mode="CODE_COVERAGE"
+ fi
+ fi
+ done;
+ IFS=$OLD_IFS
+
+ shift 2;
+ fi
+ ;;
+ *)
+ if [ "$first" = "true" ]
+ then
+ first="false"
+ args="__DLP_UNIT_TEST_ARG__ $1"
+ else
+ args="$args","$1"
+ fi
+ shift 1;
+ esac
+done
+
+if [ "" != "$appid" ]
+then
+ launch_app_arg1=$appid
+else
+ launch_app_arg1=$pkgid.$exe
+fi
+
+if [ "$mode" = "debug" ]
+then
+ if [ "" != "$attach_id" ]
+ #debug attach
+ then
+ cmd="$COV_TEST_PREFIX /home/developer/sdk_tools/gdbserver/gdbserver :$port --attach $attach_id"
+ #debug
+ else
+ if [ "" != "$result_mode" ]
+ then
+ result_mode="DEBUG,$result_mode"
+ else
+ result_mode="DEBUG"
+ fi
+ cmd="/usr/bin/launch_app $launch_app_arg1 __AUL_SDK__ $result_mode __DLP_DEBUG_ARG__ :$port $launch_app_mode $args"
+# cmd="$COV_TEST_PREFIX /home/developer/sdk_tools/gdbserver/gdbserver :$port /opt/apps/$pkgid/bin/$exe"
+ fi
+else
+ if [ "$mode" = "run" ]
+ then
+ if [ "" != "$result_mode" ]
+ then
+ cmd="/usr/bin/launch_app $launch_app_arg1 __AUL_SDK__ $result_mode $launch_app_mode $args"
+ else
+ cmd="/usr/bin/launch_app $launch_app_arg1"
+ fi
+ else
+ if [ "$mode" = "da" ]
+ then
+ if [ "" != "$result_mode" ]
+ then
+ result_mode="DYNAMIC_ANALYSIS,$result_mode"
+ else
+ result_mode="DYNAMIC_ANALYSIS"
+ fi
+ fi
+ if [ "$mode" = "oprofile" ]
+ then
+ if [ "" == "$result_mode" ]
+ then
+ result_mode="OPROFILE"
+ fi
+ fi
+ cmd="/usr/bin/launch_app $launch_app_arg1 __AUL_SDK__ $result_mode"
+ fi
+fi
+
+# execute command
+$cmd $args
--- /dev/null
+<manifest>
+ <define>
+ <domain name="sdbd" policy="shared" />
+ <provide>
+ <label name="sdbd::home" />
+ </provide>
+ <request>
+ <smack request="sys-assert::core" type="rwxat" />
+ <smack request="device::app_logging" type="rwxat" />
+ <smack request="device::sys_logging" type="rwxat" />
+ <smack request="pkgmgr" type="rx" />
+ <smack request="pkgmgr::svc" type="rx" />
+ <smack request="pkgmgr::info" type="r" />
+ <smack request="pkgmgr-server" type="r" />
+ <smack request="pkgmgr-client" type="r" />
+ <smack request="aul" type="rx" />
+ <smack request="wrt::wrt-launcher" type="rx" />
+ <smack request="system::media" type="rwxat" />
+ <smack request="sdbd::home" type="rwxat" />
+ <smack request="dbus" type="rwx" />
+ <smack request="system::use_internet" type="w" />
+ <smack request="system::debugging_network" type="w" />
+ <smack request="device::input" type="rwx" />
+ <smack request="*" type="rwxat" />
+ </request>
+ <permit>
+ <smack permit="system::use_internet" type="w" />
+ <smack permit="system::debugging_network" type="w" />
+ <smack permit="aul" type="rx" />
+ <smack permit="wrt::wrt-launcher" type="rw" />
+ </permit>
+ </define>
+ <request>
+ <domain name="sdbd" />
+ </request>
+</manifest>
--- /dev/null
+/*
+ * 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.
+ */
+
+/*
+ * Android config -- "CYGWIN_NT-5.1".
+ *
+ * Cygwin has pthreads, but GDB seems to get confused if you use it to
+ * create threads. By "confused", I mean it freezes up the first time the
+ * debugged process creates a thread, even if you use CreateThread. The
+ * mere presence of pthreads linkage seems to cause problems.
+ */
+#ifndef _ANDROID_CONFIG_H
+#define _ANDROID_CONFIG_H
+
+/*
+ * ===========================================================================
+ * !!! IMPORTANT !!!
+ * ===========================================================================
+ *
+ * This file is included by ALL C/C++ source files. Don't put anything in
+ * here unless you are absolutely certain it can't go anywhere else.
+ *
+ * Any C++ stuff must be wrapped with "#ifdef __cplusplus". Do not use "//"
+ * comments.
+ */
+
+/*
+ * Threading model. Choose one:
+ *
+ * HAVE_PTHREADS - use the pthreads library.
+ * HAVE_WIN32_THREADS - use Win32 thread primitives.
+ */
+#define HAVE_WIN32_THREADS
+
+/*
+ * Do we have the futex syscall?
+ */
+
+/* #define HAVE_FUTEX */
+
+
+/*
+ * Process creation model. Choose one:
+ *
+ * HAVE_FORKEXEC - use fork() and exec()
+ * HAVE_WIN32_PROC - use CreateProcess()
+ */
+#ifdef __CYGWIN__
+# define HAVE_FORKEXEC
+#else
+# define HAVE_WIN32_PROC
+#endif
+
+/*
+ * Process out-of-memory adjustment. Set if running on Linux,
+ * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory
+ * badness adjustment.
+ */
+/* #define HAVE_OOM_ADJ */
+
+/*
+ * IPC model. Choose one:
+ *
+ * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget).
+ * HAVE_MACOSX_IPC - use Macintosh IPC mechanisms (sem_open, mmap).
+ * HAVE_WIN32_IPC - use Win32 IPC (CreateSemaphore, CreateFileMapping).
+ * HAVE_ANDROID_IPC - use Android versions (?, mmap).
+ */
+#define HAVE_WIN32_IPC
+
+/*
+ * Memory-mapping model. Choose one:
+ *
+ * HAVE_POSIX_FILEMAP - use the Posix sys/mmap.h
+ * HAVE_WIN32_FILEMAP - use Win32 filemaps
+ */
+#ifdef __CYGWIN__
+#define HAVE_POSIX_FILEMAP
+#else
+#define HAVE_WIN32_FILEMAP
+#endif
+
+/*
+ * Define this if you have <termio.h>
+ */
+#ifdef __CYGWIN__
+# define HAVE_TERMIO_H
+#endif
+
+/*
+ * Define this if you have <sys/sendfile.h>
+ */
+#ifdef __CYGWIN__
+# define HAVE_SYS_SENDFILE_H 1
+#endif
+
+/*
+ * Define this if you build against MSVCRT.DLL
+ */
+#ifndef __CYGWIN__
+# define HAVE_MS_C_RUNTIME
+#endif
+
+/*
+ * Define this if you have sys/uio.h
+ */
+#ifdef __CYGWIN__
+#define HAVE_SYS_UIO_H
+#endif
+
+
+/*
+ * Define this if we have localtime_r().
+ */
+/* #define HAVE_LOCALTIME_R */
+
+/*
+ * Define this if we have gethostbyname_r().
+ */
+/* #define HAVE_GETHOSTBYNAME_R */
+
+/*
+ * Define this if we have ioctl().
+ */
+/* #define HAVE_IOCTL */
+
+/*
+ * Define this if we want to use WinSock.
+ */
+#ifndef __CYGWIN__
+#define HAVE_WINSOCK
+#endif
+
+/*
+ * Define this if your platforms implements symbolic links
+ * in its filesystems
+ */
+/* #define HAVE_SYMLINKS */
+
+/*
+ * Define this if have clock_gettime() and friends
+ */
+/* #define HAVE_POSIX_CLOCKS */
+
+/*
+ * Endianness of the target machine. Choose one:
+ *
+ * HAVE_ENDIAN_H -- have endian.h header we can include.
+ * HAVE_LITTLE_ENDIAN -- we are little endian.
+ * HAVE_BIG_ENDIAN -- we are big endian.
+ */
+#ifdef __CYGWIN__
+#define HAVE_ENDIAN_H
+#endif
+
+#define HAVE_LITTLE_ENDIAN
+
+/*
+ * We need to choose between 32-bit and 64-bit off_t. All of our code should
+ * agree on the same size. For desktop systems, use 64-bit values,
+ * because some of our libraries (e.g. wxWidgets) expect to be built that way.
+ */
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+
+/*
+ * Defined if we have the backtrace() call for retrieving a stack trace.
+ * Needed for CallStack to operate; if not defined, CallStack is
+ * non-functional.
+ */
+#define HAVE_BACKTRACE 0
+
+/*
+ * Defined if we have the dladdr() call for retrieving the symbol associated
+ * with a memory address. If not defined, stack crawls will not have symbolic
+ * information.
+ */
+#define HAVE_DLADDR 0
+
+/*
+ * Defined if we have the cxxabi.h header for demangling C++ symbols. If
+ * not defined, stack crawls will be displayed with raw mangled symbols
+ */
+#define HAVE_CXXABI 0
+
+/*
+ * Define if tm struct has tm_gmtoff field
+ */
+/* #define HAVE_TM_GMTOFF 1 */
+
+/*
+ * Define if dirent struct has d_type field
+ */
+/* #define HAVE_DIRENT_D_TYPE 1 */
+
+/*
+ * Define if libc includes Android system properties implementation.
+ */
+/* #define HAVE_LIBC_SYSTEM_PROPERTIES */
+
+/*
+ * Define if system provides a system property server (should be
+ * mutually exclusive with HAVE_LIBC_SYSTEM_PROPERTIES).
+ */
+/* #define HAVE_SYSTEM_PROPERTY_SERVER */
+
+/*
+ * Define if we have madvise() in <sys/mman.h>
+ */
+/*#define HAVE_MADVISE 1*/
+
+/*
+ * Add any extra platform-specific defines here.
+ */
+#define WIN32 1 /* stock Cygwin doesn't define these */
+#define _WIN32 1
+#define _WIN32_WINNT 0x0500 /* admit to using >= Win2K */
+
+#define HAVE_WINDOWS_PATHS /* needed by simulator */
+
+/*
+ * What CPU architecture does this platform use?
+ */
+#define ARCH_X86
+
+/*
+ * sprintf() format string for shared library naming.
+ */
+#define OS_SHARED_LIB_FORMAT_STR "lib%s.dll"
+
+/*
+ * type for the third argument to mincore().
+ */
+#define MINCORE_POINTER_TYPE unsigned char *
+
+/*
+ * The default path separator for the platform
+ */
+#define OS_PATH_SEPARATOR '\\'
+
+/*
+ * Is the filesystem case sensitive?
+ */
+/* #define OS_CASE_SENSITIVE */
+
+/*
+ * Define if <sys/socket.h> exists.
+ * Cygwin has it, but not MinGW.
+ */
+#ifdef USE_MINGW
+/* #define HAVE_SYS_SOCKET_H */
+#else
+#define HAVE_SYS_SOCKET_H 1
+#endif
+
+/*
+ * Define if the strlcpy() function exists on the system.
+ */
+/* #define HAVE_STRLCPY 1 */
+
+/*
+ * Define if the open_memstream() function exists on the system.
+ */
+/* #define HAVE_OPEN_MEMSTREAM 1 */
+
+/*
+ * Define if the BSD funopen() function exists on the system.
+ */
+/* #define HAVE_FUNOPEN 1 */
+
+/*
+ * Define if <winsock2.h> exists.
+ * Only MinGW has it.
+ */
+#ifdef USE_MINGW
+#define HAVE_WINSOCK2_H 1
+#else
+/* #define HAVE_WINSOCK2_H */
+#endif
+
+/*
+ * Various definitions missing in MinGW
+ */
+#ifdef USE_MINGW
+#define S_IRGRP 0
+#endif
+
+/*
+ * Define if writev() exists.
+ */
+/* #define HAVE_WRITEV */
+
+/*
+ * Define if <stdint.h> exists.
+ */
+/* #define HAVE_STDINT_H */
+
+/*
+ * Define if <stdbool.h> exists.
+ */
+#define HAVE_STDBOOL_H
+
+/*
+ * Define if <sched.h> exists.
+ */
+/* #define HAVE_SCHED_H */
+
+/*
+ * Define if pread() exists
+ */
+/* #define HAVE_PREAD 1 */
+
+/*
+ * Define if we have st_mtim in struct stat
+ */
+/* #define HAVE_STAT_ST_MTIM 1 */
+
+/*
+ * Define if printf() supports %zd for size_t arguments
+ */
+/* #define HAVE_PRINTF_ZD 1 */
+
+#endif /*_ANDROID_CONFIG_H*/
--- /dev/null
+###########################################################
+## Clear out values of all variables used by rule templates.
+###########################################################
+
+LOCAL_MODULE:=
+LOCAL_MODULE_PATH:=
+LOCAL_MODULE_STEM:=
+LOCAL_DONT_CHECK_MODULE:=
+LOCAL_CHECKED_MODULE:=
+LOCAL_BUILT_MODULE:=
+LOCAL_BUILT_MODULE_STEM:=
+OVERRIDE_BUILT_MODULE_PATH:=
+LOCAL_INSTALLED_MODULE:=
+LOCAL_UNINSTALLABLE_MODULE:=
+LOCAL_INTERMEDIATE_TARGETS:=
+LOCAL_UNSTRIPPED_PATH:=
+LOCAL_MODULE_CLASS:=
+LOCAL_MODULE_SUFFIX:=
+LOCAL_PACKAGE_NAME:=
+LOCAL_OVERRIDES_PACKAGES:=
+LOCAL_EXPORT_PACKAGE_RESOURCES:=
+LOCAL_MANIFEST_PACKAGE_NAME:=
+LOCAL_REQUIRED_MODULES:=
+LOCAL_ACP_UNAVAILABLE:=
+LOCAL_MODULE_TAGS:=
+LOCAL_SRC_FILES:=
+LOCAL_PREBUILT_OBJ_FILES:=
+LOCAL_STATIC_JAVA_LIBRARIES:=
+LOCAL_STATIC_LIBRARIES:=
+LOCAL_WHOLE_STATIC_LIBRARIES:=
+LOCAL_SHARED_LIBRARIES:=
+LOCAL_IS_HOST_MODULE:=
+LOCAL_CC:=
+LOCAL_CXX:=
+LOCAL_CPP_EXTENSION:=
+LOCAL_NO_DEFAULT_COMPILER_FLAGS:=
+LOCAL_NO_FDO_SUPPORT :=
+LOCAL_ARM_MODE:=
+LOCAL_YACCFLAGS:=
+LOCAL_ASFLAGS:=
+LOCAL_CFLAGS:=
+LOCAL_CPPFLAGS:=
+LOCAL_C_INCLUDES:=
+LOCAL_LDFLAGS:=
+LOCAL_LDLIBS:=
+LOCAL_AAPT_FLAGS:=
+LOCAL_SYSTEM_SHARED_LIBRARIES:=none
+LOCAL_PREBUILT_LIBS:=
+LOCAL_PREBUILT_EXECUTABLES:=
+LOCAL_PREBUILT_JAVA_LIBRARIES:=
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
+LOCAL_PREBUILT_STRIP_COMMENTS:=
+LOCAL_INTERMEDIATE_SOURCES:=
+LOCAL_INTERMEDIATE_SOURCE_DIR:=
+LOCAL_JAVACFLAGS:=
+LOCAL_JAVA_LIBRARIES:=
+LOCAL_NO_STANDARD_LIBRARIES:=
+LOCAL_CLASSPATH:=
+LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
+LOCAL_DROIDDOC_SOURCE_PATH:=
+LOCAL_DROIDDOC_TEMPLATE_DIR:=
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=
+LOCAL_DROIDDOC_ASSET_DIR:=
+LOCAL_DROIDDOC_CUSTOM_ASSET_DIR:=
+LOCAL_DROIDDOC_OPTIONS:=
+LOCAL_DROIDDOC_HTML_DIR:=
+LOCAL_ASSET_FILES:=
+LOCAL_ASSET_DIR:=
+LOCAL_RESOURCE_DIR:=
+LOCAL_JAVA_RESOURCE_DIRS:=
+LOCAL_JAVA_RESOURCE_FILES:=
+LOCAL_GENERATED_SOURCES:=
+LOCAL_COPY_HEADERS_TO:=
+LOCAL_COPY_HEADERS:=
+LOCAL_FORCE_STATIC_EXECUTABLE:=
+LOCAL_ADDITIONAL_DEPENDENCIES:=
+LOCAL_PRELINK_MODULE:=
+LOCAL_COMPRESS_MODULE_SYMBOLS:=
+LOCAL_STRIP_MODULE:=
+LOCAL_POST_PROCESS_COMMAND:=true
+LOCAL_JNI_SHARED_LIBRARIES:=
+LOCAL_JAR_MANIFEST:=
+LOCAL_INSTRUMENTATION_FOR:=
+LOCAL_MANIFEST_INSTRUMENTATION_FOR:=
+LOCAL_AIDL_INCLUDES:=
+LOCAL_JARJAR_RULES:=
+LOCAL_ADDITIONAL_JAVA_DIR:=
+LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
+LOCAL_DX_FLAGS:=
+LOCAL_CERTIFICATE:=
+LOCAL_SDK_VERSION:=
+LOCAL_NDK_VERSION:=
+LOCAL_NO_EMMA_INSTRUMENT:=
+LOCAL_NO_EMMA_COMPILE:=
+LOCAL_PROGUARD_ENABLED:= # '',optonly,full,custom
+LOCAL_PROGUARD_FLAGS:=
+LOCAL_PROGUARD_FLAG_FILES:=
+LOCAL_EMMA_COVERAGE_FILTER:=
+LOCAL_MANIFEST_FILE:=
+LOCAL_BUILD_HOST_DEX:=
+LOCAL_DEX_PREOPT:=
+
+# Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
+# iterate over thousands of entries every time.
+# Leave the current makefile to make sure we don't break anything
+# that expects to be able to find the name of the current makefile.
+MAKEFILE_LIST := $(lastword $(MAKEFILE_LIST))
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 "sdb_client.h"
#include "file_sync_service.h"
-enum {
- IGNORE_DATA,
- WIPE_DATA,
- FLASH_DATA
-};
-
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); eric
+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;
version(stderr);
fprintf(stderr,
- "\n"
- " Usage : sdb [option] <command> [parameters]\n"
- "\n"
- " options:\n"
- " -d - directs command to the only connected USB device\n"
- " returns an error if more than one USB device is present.\n"
- " -e - directs command to the only running emulator.\n"
- " returns an error if more than one emulator is running.\n"
- " -s <serial number> - directs command to the USB device or emulator with\n"
- " the given serial number.\n"
- " devices - list all connected devices\n"
- "\n"
- " commands:\n"
- " sdb push <local> <remote> - copy file/dir to device\n"
- " sdb pull <remote> [<local>] - copy file/dir from device\n"
- " sdb shell - run remote shell interactively\n"
- " sdb shell <command> - run remote shell command\n"
- " sdb dlog [ <filter-spec> ] - view device log\n"
- " sdb forward <local> <remote> - forward socket connections\n"
- " forward spec is : \n"
- " tcp:<port>\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 - prints: offline | bootloader | device\n"
- " sdb get-serialno - prints: <serial-number>\n"
- " sdb status-window - continuously print device status for a specified device\n"
+ "\n"
+ " Usage : sdb [option] <command> [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 <serial number> - direct command to the USB device or emulator with\n"
+ " the given serial number.\n"
+ " devices - list all connected devices\n"
+ " connect <host>[:<port>] - connect to a device via TCP/IP\n"
+ " Port 26101 is used by default if no port number is specified.\n"
+ " disconnect [<host>[:<port>]] - 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 <local> <remote> [--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 <remote> [<local>] - copy file/dir from device\n"
+ " sdb shell - run remote shell interactively\n"
+ " sdb shell <command> - run remote shell \n"
+ " sdb dlog [<filter-spec>] - view device log\n"
+ " sdb install <path-to-tpk> - push tpk package file and install it\n"
+ " sdb uninstall <appid> - uninstall this app from the device\n"
+ " sdb forward <local> <remote> - forward socket connections\n"
+
+ " forward spec is : \n"
+ " tcp:<port>\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: <serial-number>\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 <on|off> - switch to root or developer account mode\n"
+ " 'on' means to root mode, and vice versa"
+ "\n"
);
}
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;
}
}
}
+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;
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;
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 buf[4096];
- char *log_tags;
- char *quoted_log_tags;
-
- log_tags = getenv("ANDROID_LOG_TAGS");
- quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
-
snprintf(buf, sizeof(buf),
- "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec dlogutil",
- //"shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
- quoted_log_tags);
+ "shell:/usr/bin/dlogutil");
- free(quoted_log_tags);
+/*
+ if (!strcmp(argv[0],"longcat")) {
+ strncat(buf, " -v long", sizeof(buf)-1);
+ }
+*/
argc -= 1;
argv += 1;
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)
{
char buf[4096];
int no_daemon = 0;
int is_daemon = 0;
+ int is_server = 0;
int persist = 0;
int r;
int quote;
/* modifiers and flags */
while(argc > 0) {
- if(!strcmp(argv[0],"nodaemon")) {
+ 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 */
argv++;
}
- sdb_set_transport(ttype, serial);
- sdb_set_tcp_specifics(server_port);
- if ((argc > 0) && (!strcmp(argv[0],"server"))) {
+// 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 {
return r;
}
-//top:
+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")) {
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 <host>[:<port>]\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 {
}
}
- if(!strcmp(argv[0], "test")) {
+ if(!strcmp(argv[0], "disconnect")) {
char *tmp;
- snprintf(buf, sizeof buf, "host:emulator:26101");
+ if (argc > 2) {
+ fprintf(stderr, "Usage: sdb disconnect [<host>[:<port>]]\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], "connect")) {
-// char *tmp;
-// if (argc != 2) {
-// fprintf(stderr, "Usage: sdb connect <host>[:<port>]\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 [<host>[:<port>]]\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")) {
+ 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) {
- return interactive_shell();
+ 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]);
}
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 {
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;
}
}
}
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], "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;
-// }
+ 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(!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(!strcmp(argv[0], "push")) {
- if(argc != 3) return usage();
- return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
+ 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<argc-1; i++) {
+ do_sync_push(argv[i], argv[argc-1], 0 /* no verify APK */, utf8);
+ }
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "install")) {
+ if(argc != 2) return usage();
+
+ return install_app_sdb(argv[1]);
+ }
+
+ if(!strcmp(argv[0], "uninstall")) {
+ if(argc != 2) return usage();
+
+ return uninstall_app_sdb(argv[1]);
}
if(!strcmp(argv[0], "pull")) {
}
}
-// if(!strcmp(argv[0], "install")) {
-// if (argc < 2) return usage();
-// return install_app(ttype, serial, argc, argv);
-// }
-//
-// if(!strcmp(argv[0], "uninstall")) {
-// if (argc < 2) return usage();
-// return uninstall_app(ttype, serial, argc, argv);
-// }
-
-// if(!strcmp(argv[0], "sync")) {
-// char *srcarg, *android_srcpath, *data_srcpath;
-// int listonly = 0;
-//
-// int ret;
-// if(argc < 2) {
-// /* No local path was specified. */
-// srcarg = NULL;
-// } else if (argc >= 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;
-// }
+ if(!strcmp(argv[0], "install")) {
+ if (argc < 2) return usage();
+ return install_app(ttype, serial, argc, argv);
+ }
+
+ if(!strcmp(argv[0], "uninstall")) {
+ if (argc < 2) return usage();
+ return uninstall_app(ttype, serial, argc, argv);
+ }
+
+ if(!strcmp(argv[0], "launch")) {
+ //if (argc < 2) return usage();
+ return launch_app(ttype, serial, argc, argv);
+ }
+
+ if(!strcmp(argv[0], "sync")) {
+ char *srcarg, *android_srcpath, *data_srcpath;
+ int listonly = 0;
+
+ int ret;
+ if(argc < 2) {
+ /* No local path was specified. */
+ srcarg = NULL;
+ } else if (argc >= 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 */
return logcat(ttype, serial, argc, argv);
}
-// if(!strcmp(argv[0],"ppp")) {
-// return ppp(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], "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;
-// }
-// }
+ 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], "/?")) {
}
if(!strcmp(argv[0], "version")) {
- version(stdout);
+ if (ttype == kTransportUsb || ttype == kTransportLocal) {
+ version_sdbd(ttype, serial);
+ } else {
+ version(stdout);
+ }
return 0;
}
}
argv[argc++] = cmd;
- while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
+ while((argv[argc] = va_arg(ap, char*)) != 0) {
+ argc++;
+ }
va_end(ap);
#if 0
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 = "/opt/apps/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
return pm_command(transport, serial, argc, argv);
}
-#if 0 //eric
static int delete_file(transport_type transport, char* serial, char* filename)
{
char buf[4096];
return 0;
}
-int install_app(transport_type transport, char* serial, int argc, char** argv)
+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;
- int err;
- const char *const DATA_DEST = "/data/local/tmp/%s";
- const char *const SD_DEST = "/sdcard/tmp/%s";
+
+ 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 to[PATH_MAX];
- char* filename = argv[argc - 1];
- const char* p;
+ 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 = 0; i < argc; i++) {
- if (!strcmp(argv[i], "-s"))
+ 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++;
+ }
}
- p = sdb_dirstop(filename);
- if (p) {
- p++;
- snprintf(to, sizeof to, where, p);
- } else {
- snprintf(to, sizeof to, where, filename);
+ 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;
}
- if (p[0] == '\0') {
+
+ apk_file = argv[file_arg];
+
+ if (file_arg != argc - 1) {
+ verification_file = argv[file_arg + 1];
}
- err = stat(filename, &st);
- if (err != 0) {
- fprintf(stderr, "can't find '%s' to install\n", filename);
+ if (check_file(apk_file) || check_file(verification_file)) {
return 1;
}
- if (!S_ISREG(st.st_mode)) {
- fprintf(stderr, "can't install '%s' because it's not a file\n",
- filename);
- 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 (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
- /* file in place; tell the Package Manager to install it */
- argv[argc - 1] = to; /* destination name, not source location */
- pm_command(transport, serial, argc, argv);
- delete_file(transport, serial, to);
+ 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;
}
-#endif
+
+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<argc ; i++) {
+ strncat(full_cmd, " ", sizeof(full_cmd)-strlen(" ")-1);
+ strncat(full_cmd, argv[i], sizeof(full_cmd)-strlen(argv[i])-1);
+ }
+
+ D("launch command: %s\n", full_cmd);
+ result = sdb_command2(full_cmd);
+
+ if(result < 0) {
+ fprintf(stderr, "error: %s\n", sdb_error());
+ return result;
+ }
+
+ if(result < 0) {
+ fprintf(stderr, "error: %s\n", sdb_error());
+ return result;
+ }
+ sdb_close(result);
+ return 0;
+
+}
+
+
+void version_sdbd(transport_type ttype, char* serial) {
+ char* VERSION_QUERY ="shell:rpm -qa | grep sdbd";
+ send_shellcommand(ttype, serial, VERSION_QUERY);
+}
+/*
+ * 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 "sdb.h"
#include "sdb_client.h"
-/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
-**
-** Copyright 2006, Brian Swetland <swetland@frotz.net>
-**
-** 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.
-*/
+/*
+ * 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 <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include "fdevent.h"
+#include "transport.h"
+#include "sysdeps.h"
+
-#define TRACE(x...) fprintf(stderr,x)
+/* !!! Do not enable DEBUG for the sdb that will run as the server:
+** both stdout and stderr are used to communicate between the client
+** and server. Any extra output will cause failures.
+*/
+#define DEBUG 0 /* non-0 will break sdb server */
-#define DEBUG 0
+// This socket is used when a subproc shell service exists.
+// It wakes up the fdevent_loop() and cause the correct handling
+// of the shell's pseudo-tty master. I.e. force close it.
+int SHELL_EXIT_NOTIFY_FD = -1;
static void fatal(const char *fn, const char *fmt, ...)
{
#define FATAL(x...) fatal(__FUNCTION__, x)
#if DEBUG
+#define D(...) \
+ do { \
+ sdb_mutex_lock(&D_lock); \
+ int save_errno = errno; \
+ fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__); \
+ errno = save_errno; \
+ fprintf(stderr, __VA_ARGS__); \
+ sdb_mutex_unlock(&D_lock); \
+ errno = save_errno; \
+ } while(0)
static void dump_fde(fdevent *fde, const char *info)
{
+ sdb_mutex_lock(&D_lock);
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);
+ sdb_mutex_unlock(&D_lock);
}
#else
+#define D(...) ((void)0)
#define dump_fde(fde, info) do { } while(0)
#endif
static void fdevent_plist_enqueue(fdevent *node);
static void fdevent_plist_remove(fdevent *node);
static fdevent *fdevent_plist_dequeue(void);
+static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
static fdevent list_pending = {
.next = &list_pending,
FD_CLR(fde->fd, &error_fds);
}
- fde->state = (fde->state & FDE_STATEMASK) | events;
+ fde->state = (fde->state & FDE_STATEMASK) | events;
}
-static void fdevent_process()
+/* Looks at fd_table[] for bad FDs and sets bit in fds.
+** Returns the number of bad FDs.
+*/
+static int fdevent_fd_check(fd_set *fds)
+{
+ int i, n = 0;
+ fdevent *fde;
+
+ for(i = 0; i < select_n; i++) {
+ fde = fd_table[i];
+ if(fde == 0) continue;
+ if(fcntl(i, F_GETFL, NULL) < 0) {
+ FD_SET(i, fds);
+ n++;
+ // fde->state |= FDE_DONT_CLOSE;
+
+ }
+ }
+ return n;
+}
+
+#if !DEBUG
+static inline void dump_all_fds(const char *extra_msg) {}
+#else
+static void dump_all_fds(const char *extra_msg)
+{
+int i;
+ fdevent *fde;
+ // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
+ char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
+ size_t max_chars = FD_SETSIZE * 6 + 1;
+ int printed_out;
+#define SAFE_SPRINTF(...) \
+ do { \
+ printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
+ if (printed_out <= 0) { \
+ D("... snprintf failed.\n"); \
+ return; \
+ } \
+ if (max_chars < (unsigned int)printed_out) { \
+ D("... snprintf out of space.\n"); \
+ return; \
+ } \
+ pb += printed_out; \
+ max_chars -= printed_out; \
+ } while(0)
+
+ for(i = 0; i < select_n; i++) {
+ fde = fd_table[i];
+ SAFE_SPRINTF("%d", i);
+ if(fde == 0) {
+ SAFE_SPRINTF("? ");
+ continue;
+ }
+ if(fcntl(i, F_GETFL, NULL) < 0) {
+ SAFE_SPRINTF("b");
+ }
+ SAFE_SPRINTF(" ");
+ }
+ D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
+}
+#endif
+
+static int fdevent_process()
{
int i, n;
fdevent *fde;
memcpy(&wfd, &write_fds, sizeof(fd_set));
memcpy(&efd, &error_fds, sizeof(fd_set));
- n = select(select_n, &rfd, &wfd, &efd, 0);
+ dump_all_fds("pre select()");
+
+ n = select(select_n, &rfd, &wfd, &efd, NULL);
+ int saved_errno = errno;
+ D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
+
+ dump_all_fds("post select()");
if(n < 0) {
- if(errno == EINTR) return;
- perror("select");
- return;
+ switch(saved_errno) {
+ case EINTR: return -1;
+ case EBADF:
+ // Can't trust the FD sets after an error.
+ FD_ZERO(&wfd);
+ FD_ZERO(&efd);
+ FD_ZERO(&rfd);
+ break;
+ default:
+ D("Unexpected select() error=%d\n", saved_errno);
+ return 0;
+ }
+ }
+ if(n <= 0) {
+ // We fake a read, as the rest of the code assumes
+ // that errors will be detected at that point.
+ n = fdevent_fd_check(&rfd);
}
for(i = 0; (i < select_n) && (n > 0); i++) {
events = 0;
- if(FD_ISSET(i, &rfd)) events |= FDE_READ;
- if(FD_ISSET(i, &wfd)) events |= FDE_WRITE;
- if(FD_ISSET(i, &efd)) events |= FDE_ERROR;
+ if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
+ if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
+ if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
if(events) {
- n--;
-
fde = fd_table[i];
- if(fde == 0) FATAL("missing fde for fd %d\n", i);
+ if(fde == 0)
+ FATAL("missing fde for fd %d\n", i);
fde->events |= events;
+ D("got events fde->fd=%d events=%04x, state=%04x\n",
+ fde->fd, fde->events, fde->state);
if(fde->state & FDE_PENDING) continue;
fde->state |= FDE_PENDING;
fdevent_plist_enqueue(fde);
}
}
+
+ return 0;
}
#endif
}
if(fd_table[fde->fd] != fde) {
- FATAL("fd_table out of sync");
+ FATAL("fd_table out of sync [%d]\n", fde->fd);
}
fd_table[fde->fd] = 0;
if(!(fde->state & FDE_DONT_CLOSE)) {
dump_fde(fde, "close");
- close(fde->fd);
+ sdb_close(fde->fd);
}
}
return node;
}
+static void fdevent_call_fdfunc(fdevent* fde)
+{
+ unsigned events = fde->events;
+ fde->events = 0;
+ if(!(fde->state & FDE_PENDING)) return;
+ fde->state &= (~FDE_PENDING);
+ dump_fde(fde, "callback");
+ fde->func(fde->fd, events, fde->arg);
+}
+
+static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
+{
+
+ D("subproc handling on fd=%d ev=%04x\n", fd, ev);
+
+ // Hook oneself back into the fde's suitable for select() on read.
+ if((fd < 0) || (fd >= fd_table_max)) {
+ FATAL("fd %d out of range for fd_table \n", fd);
+ }
+ fdevent *fde = fd_table[fd];
+ fdevent_add(fde, FDE_READ);
+
+ if(ev & FDE_READ){
+ int subproc_fd;
+
+ if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
+ FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
+ }
+ if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
+ D("subproc_fd %d out of range 0, fd_table_max=%d\n",
+ subproc_fd, fd_table_max);
+ return;
+ }
+ fdevent *subproc_fde = fd_table[subproc_fd];
+ if(!subproc_fde) {
+ D("subproc_fd %d cleared from fd_table\n", subproc_fd);
+ return;
+ }
+ if(subproc_fde->fd != subproc_fd) {
+ // Already reallocated?
+ D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
+ return;
+ }
+
+ subproc_fde->force_eof = 1;
+
+ int rcount = 0;
+ ioctl(subproc_fd, FIONREAD, &rcount);
+ D("subproc with fd=%d has rcount=%d err=%d\n",
+ subproc_fd, rcount, errno);
+
+ if(rcount) {
+ // If there is data left, it will show up in the select().
+ // This works because there is no other thread reading that
+ // data when in this fd_func().
+ return;
+ }
+
+ D("subproc_fde.state=%04x\n", subproc_fde->state);
+ subproc_fde->events |= FDE_READ;
+ if(subproc_fde->state & FDE_PENDING) {
+ return;
+ }
+ subproc_fde->state |= FDE_PENDING;
+ fdevent_call_fdfunc(subproc_fde);
+ }
+}
+
fdevent *fdevent_create(int fd, fd_func func, void *arg)
{
fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
fdevent_remove(fde);
}
-void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
+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->force_eof = 0;
fde->func = func;
fde->arg = arg;
#ifndef HAVE_WINSOCK
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ D("failed to close fd exec:%d\n",fd);
+ }
#endif
fdevent_register(fde);
dump_fde(fde, "connect");
if(fde->state & FDE_ACTIVE) {
fdevent_disconnect(fde);
- dump_fde(fde, "disconnect");
+ dump_fde(fde, "disconnect");
fdevent_unregister(fde);
}
fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
}
+void fdevent_subproc_setup()
+{
+ int s[2];
+
+ if(sdb_socketpair(s)) {
+ FATAL("cannot create shell-exit socket-pair\n");
+ }
+ SHELL_EXIT_NOTIFY_FD = s[0];
+ fdevent *fde;
+ fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
+ if(!fde)
+ FATAL("cannot create fdevent for shell-exit handler\n");
+ fdevent_add(fde, FDE_READ);
+}
+
void fdevent_loop()
{
fdevent *fde;
+ fdevent_subproc_setup();
for(;;) {
-#if DEBUG
- fprintf(stderr,"--- ---- waiting for events\n");
-#endif
- fdevent_process();
+ D("--- ---- waiting for events\n");
+
+ if (fdevent_process() < 0) {
+ return;
+ }
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);
+ fdevent_call_fdfunc(fde);
}
}
}
-
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
fdevent *prev;
int fd;
+ int force_eof;
+
unsigned short state;
unsigned short events;
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <dirent.h>
#include <limits.h>
#include <sys/types.h>
-#if 0 //eric
-#include <zipfile/zipfile.h>
-#endif
+// tizen specific #include <zipfile/zipfile.h>
+
#include "sysdeps.h"
#include "sdb.h"
#include "sdb_client.h"
static unsigned total_bytes;
static long long start_time;
+extern const char* get_basename(const char* filename);
static long long NOW()
{
start_time = NOW();
}
-static void END()
+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,"%lld KB/s (%d bytes in %lld.%03llds)\n",
+ fprintf(stderr,"%-30s %lld KB/s (%lld bytes in %lld.%03llds)\n",
+ filename,
((((long long) total_bytes) * 1000000LL) / t) / 1024LL,
- total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
+ (long long) total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
}
+
void sync_quit(int fd)
{
syncmsg msg;
snprintf(tmp, sizeof(tmp), ",%d", mode);
r = strlen(tmp);
-
+#if 0 /* tizen specific */
if (verifyApk) {
-#if 0 //eric
int lfd;
zipfile_t zip;
zipentry_t entry;
free(file_buffer);
return 1;
}
-#endif
}
-
+#endif
msg.req.id = ID_SEND;
msg.req.namelen = htoll(len + r);
} else {
ci = mkcopyinfo(lpath, rpath, name, 0);
if(lstat(ci->src, &st)) {
- closedir(d);
fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
+ closedir(d);
+
return -1;
}
if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- fprintf(stderr, "skipping special file '%s'\n", ci->src);
+ fprintf(stderr, "skipping special file\n");
free(ci);
} else {
ci->time = st.st_mtime;
}
-int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
+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) {
if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
return 1;
} else {
- END();
+ 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
name++;
}
int tmplen = strlen(name) + strlen(rpath) + 2;
- char *tmp = malloc(strlen(name) + strlen(rpath) + 2);
+ tmp = malloc(strlen(name) + strlen(rpath) + 2);
if(tmp == 0) return 1;
snprintf(tmp, tmplen, "%s/%s", rpath, name);
- rpath = tmp;
+ 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)) {
- return 1;
+ ret = 1;
+ goto cleanup;
} else {
- END();
+ END(get_basename(lpath));
sync_quit(fd);
- return 0;
+ ret = 0;
+ goto cleanup;
}
}
-
return 0;
+cleanup:
+ if (tmp != NULL) {
+ free(tmp);
+ }
+ if (utf8 != NULL) {
+ free(utf8);
+ }
+ return ret;
}
return 1;
}
if(mode == 0) {
- fprintf(stderr,"remote object '%s' does not exist\n", rpath);
+ fprintf(stderr,"'%s': No such file or directory\n", rpath);
+ sync_quit(fd);
return 1;
}
if(sync_recv(fd, rpath, lpath)) {
return 1;
} else {
- END();
+ END(get_basename(rpath));
sync_quit(fd);
return 0;
}
if (copy_remote_dir_local(fd, rpath, lpath, 0)) {
return 1;
} else {
- END();
+ END(get_basename(rpath));
sync_quit(fd);
return 0;
}
} else {
- fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
+ fprintf(stderr,"'%s': No such file or directory\n", rpath);
return 1;
}
}
if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
return 1;
} else {
- END();
+ END(get_basename(lpath));
sync_quit(fd);
return 0;
}
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <sys/types.h>
#include <dirent.h>
#include <utime.h>
-
+#include <regex.h>
#include <errno.h>
-
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/smack.h>
#include "sysdeps.h"
#define TRACE_TAG TRACE_SYNC
#include "sdb.h"
#include "file_sync_service.h"
+#include "sdktools.h"
+#include "utils.h"
+
+#define SYNC_TIMEOUT 15
+
+struct sync_permit_rule
+{
+ const char *name;
+ const char *regx;
+ int mode; // 0:push, 1: pull, 2: push&push
+};
+
+struct sync_permit_rule sdk_sync_permit_rule[] = {
+// /* 0 */ {"rds", "^((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/info/\\.sdk_delta\\.info$", 1},
+ /* 1 */ {"unitest", "^((/tmp)|(/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,50}\\.xml$", 1},
+ /* 2 */ {"codecoverage", "^((/tmp)|(/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/+(.)*\\.gcda$", 1},
+ /* 3 */ {"da", "^(/tmp/da/)*+[a-zA-Z0-9_\\-\\.]{1,50}\\.png$", 1},
+ /* end */ {NULL, NULL, 0}
+};
/* The typical default value for the umask is S_IWGRP | S_IWOTH (octal 022).
* Before use the DIR_PERMISSION, the process umask value should be set 0 using umask().
*/
#define DIR_PERMISSION 0777
-static int mkdirs(char *name)
+int is_install_pkg_file = 0;
+
+static void set_syncfile_smack_label(char *src) {
+ char *label_transmuted = NULL;
+ char *label = NULL;
+ char *src_chr = strrchr(src, '/');
+ int pos = src_chr - src + 1;
+ char dirname[512];
+
+ if (getuid() != 0) {
+ D("need root permission to set smack label: %d\n", getuid());
+ return;
+ }
+
+ snprintf(dirname, pos, "%s", src);
+
+ //D("src:[%s], dirname:[%s]\n", src, dirname);
+ int rc = smack_getlabel(dirname, &label_transmuted, SMACK_LABEL_TRANSMUTE);
+
+ if (rc == 0 && label_transmuted != NULL) {
+ if (!strcmp("TRUE", label_transmuted)) {
+ rc = smack_getlabel(dirname, &label, SMACK_LABEL_ACCESS);
+ if (rc == 0 && label != NULL) {
+ if (smack_setlabel(src, label, SMACK_LABEL_ACCESS) == -1) {
+ D("unable to set sync file smack label %s due to %s\n", label, strerror(errno));
+ }
+ free(label);
+ }
+ } else{
+ D("fail to set label, is it transmuted?:%s\n", label_transmuted);
+ }
+ free(label_transmuted);
+ } else {
+ if (smack_setlabel(src, SMACK_SYNC_FILE_LABEL, SMACK_LABEL_ACCESS) == -1) {
+ D("unable to set sync file smack label %s due to (errno:%d)\n", SMACK_SYNC_FILE_LABEL, errno);
+ }
+ }
+}
+
+static int sync_send_label_notify(int s, const char *path, int success)
+{
+ char buffer[512] = {0,};
+ snprintf(buffer, sizeof(buffer), "%d:%s", success, path);
+
+ int len = sdb_write(s, buffer, sizeof(buffer));
+
+ return len;
+}
+
+static void sync_read_label_notify(int s)
+{
+ char buffer[512] = {0,};
+
+ while (1) {
+ int len = sdb_read(s, buffer, sizeof(buffer));
+ if (len < 0) {
+ D("sync notify read error : (errno:%d)\n", errno);
+ exit(-1);
+ }
+
+ if (buffer[0] == '0') {
+ D("sync notify child process exit\n");
+ exit(-1);
+ }
+ buffer[511] = '\0';
+ char *path = buffer;
+ path++;
+ path++;
+ set_syncfile_smack_label(path);
+ }
+}
+
+static int mkdirs(int noti_fd, char *name)
{
int ret;
char *x = name + 1;
- if(name[0] != '/') return -1;
+ if(name[0] != '/') {
+ return -1;
+ }
for(;;) {
x = sdb_dirstart(x);
- if(x == 0) return 0;
+ if(x == 0) {
+ return 0;
+ }
*x = 0;
+
ret = sdb_mkdir(name, DIR_PERMISSION);
+ if (ret == 0) {
+ sync_send_label_notify(noti_fd, name, 1);
+ }
if((ret < 0) && (errno != EEXIST)) {
- D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
+ D("mkdir(\"%s\") -> (errno:%d)\n", name, errno);
*x = '/';
return ret;
}
msg.stat.id = ID_STAT;
- if(lstat(path, &st)) {
+ /* follow link */
+ if(stat(path, &st)) {
msg.stat.mode = 0;
msg.stat.size = 0;
msg.stat.time = 0;
+ D("failed to stat %s due to: (errno:%d)\n", path, errno);
} else {
msg.stat.mode = htoll(st.st_mode);
msg.stat.size = htoll(st.st_size);
msg.dent.id = ID_DENT;
d = opendir(path);
- if(d == 0) goto done;
+ if(d == NULL) {
+ D("failed to open dir due to: (errno:%d)\n", errno);
+ goto done;
+ }
while((de = readdir(d))) {
int len = strlen(de->d_name);
/* not supposed to be possible, but
if it does happen, let's not buffer overrun */
- if(len > 256) continue;
+ if(len > 256) {
+ continue;
+ }
- strcpy(fname, de->d_name);
+ s_strncpy(fname, de->d_name, sizeof tmp);
if(lstat(tmp, &st) == 0) {
msg.dent.mode = htoll(st.st_mode);
msg.dent.size = htoll(st.st_size);
if(writex(s, &msg.dent, sizeof(msg.dent)) ||
writex(s, de->d_name, len)) {
+ closedir(d);
return -1;
}
}
static int fail_errno(int s)
{
- return fail_message(s, strerror(errno));
+ char err_msg[20] = {0, };
+ snprintf(err_msg, sizeof(err_msg), "(errno:%d)", errno);
+ return fail_message(s, err_msg);
}
-static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
+// FIXME: should get the following paths with api later but, do it for simple and not having dependency on other packages
+#define CMD_MEDIADB_UPDATE "/usr/bin/mediadb-update"
+#define MEDIA_CONTENTS_PATH1 "/opt/media"
+#define MEDIA_CONTENTS_PATH2 "/opt/usr/media"
+#define MEDIA_CONTENTS_PATH3 "/opt/storage/sdcard"
+
+static void sync_mediadb(char *path) {
+ if (access(CMD_MEDIADB_UPDATE, F_OK) != 0) {
+ D("%s: command not found\n", CMD_MEDIADB_UPDATE);
+ return;
+ }
+
+ if (strstr(path, MEDIA_CONTENTS_PATH1) != NULL) {
+ char *arg_list[] = {CMD_MEDIADB_UPDATE, "r", MEDIA_CONTENTS_PATH1, NULL};
+
+ spawn(CMD_MEDIADB_UPDATE, arg_list);
+ D("media db update done to %s\n", MEDIA_CONTENTS_PATH1);
+ } else if (strstr(path, MEDIA_CONTENTS_PATH2) != NULL) {
+ char *arg_list[] = {CMD_MEDIADB_UPDATE, "r", MEDIA_CONTENTS_PATH2, NULL};
+
+ spawn(CMD_MEDIADB_UPDATE, arg_list);
+ D("media db update done to %s\n", MEDIA_CONTENTS_PATH2);
+ } else if (strstr(path, MEDIA_CONTENTS_PATH3) != NULL) {
+ char *arg_list[] = {CMD_MEDIADB_UPDATE, "r", MEDIA_CONTENTS_PATH3, NULL};
+
+ spawn(CMD_MEDIADB_UPDATE, arg_list);
+ D("media db update done to %s\n", MEDIA_CONTENTS_PATH3);
+ }
+ return;
+}
+
+static int handle_send_file(int s, int noti_fd, char *path, mode_t mode, char *buffer)
{
syncmsg msg;
unsigned int timestamp = 0;
fd = sdb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
if(fd < 0 && errno == ENOENT) {
- mkdirs(path);
+ mkdirs(noti_fd, path);
fd = sdb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
}
if(fd < 0 && errno == EEXIST) {
return -1;
fd = -1;
}
-
for(;;) {
unsigned int len;
- if(readx(s, &msg.data, sizeof(msg.data)))
+ if(readx(s, &msg.data, sizeof(msg.data))) {
goto fail;
-
+ }
if(msg.data.id != ID_DATA) {
if(msg.data.id == ID_DONE) {
timestamp = ltohl(msg.data.size);
fail_message(s, "oversize data message");
goto fail;
}
- if(readx(s, buffer, len))
+ if(readx(s, buffer, len)) {
+ D("read failed due to unknown reason\n");
goto fail;
+ }
- if(fd < 0)
+ if(fd < 0) {
continue;
+ }
if(writex(fd, buffer, len)) {
+ int saved_errno = errno;
sdb_close(fd);
sdb_unlink(path);
fd = -1;
+ errno = saved_errno;
if(fail_errno(s)) return -1;
}
}
msg.status.msglen = 0;
if(writex(s, &msg.status, sizeof(msg.status)))
return -1;
+ // flush file system buffers due to N_SE-22305
+ sync();
+ } else {
+ D("sync error: %d!!!\n", fd);
+ return -1;
}
+ sync_send_label_notify(noti_fd, path, 1);
+ sync_mediadb(path);
return 0;
fail:
}
#ifdef HAVE_SYMLINKS
-static int handle_send_link(int s, char *path, char *buffer)
+static int handle_send_link(int s, int noti_fd, char *path, char *buffer)
{
syncmsg msg;
unsigned int len;
ret = symlink(buffer, path);
if(ret && errno == ENOENT) {
- mkdirs(path);
+ mkdirs(noti_fd, path);
ret = symlink(buffer, path);
}
if(ret) {
}
#endif /* HAVE_SYMLINKS */
-static int do_send(int s, char *path, char *buffer)
+static int do_send(int s, int noti_fd, char *path, char *buffer)
{
char *tmp;
mode_t mode;
#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.
is_link = 0;
}
+ if(is_install_pkg_file) {
+ mode = 0444;
+ is_link = 0;
+ }
// 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, path, buffer);
+ ret = handle_send_link(s, noti_fd, path, buffer);
else {
#else
{
//mode |= ((mode >> 3) & 0070);
//mode |= ((mode >> 3) & 0007);
-
- ret = handle_send_file(s, path, mode, buffer);
+ ret = handle_send_file(s, noti_fd, path, mode, buffer);
}
return ret;
if(writex(s, &msg.data, sizeof(msg.data))) {
return -1;
}
+ return 0;
+}
+
+static int verify_sync_rule(const char* path) {
+ regex_t regex;
+ int ret;
+ char buf[PATH_MAX];
+ int i=0;
+
+ // to prevent hijacking the pkg file.
+ if (is_pkg_file_path(path)) {
+ is_install_pkg_file = 1;
+ D("matched pkg file path: to prevent hijacking the pkg file\n");
+ return 1;
+ }
+ for (i=0; sdk_sync_permit_rule[i].regx != NULL; i++) {
+ ret = regcomp(®ex, sdk_sync_permit_rule[i].regx, REG_EXTENDED);
+ if(ret){
+ return 0;
+ }
+ // execute regular expression
+ ret = regexec(®ex, path, 0, NULL, 0);
+ if(!ret){
+ regfree(®ex);
+ D("found matched rule(%s) from %s path\n", sdk_sync_permit_rule[i].name, path);
+ return 1;
+ } else if( ret == REG_NOMATCH ){
+ // do nothin
+ } else{
+ regerror(ret, ®ex, buf, sizeof(buf));
+ D("regex match failed(%s): %s\n",sdk_sync_permit_rule[i].name, buf);
+ }
+ }
+ regfree(®ex);
return 0;
}
syncmsg msg;
char name[1025];
unsigned namelen;
-
+ fd_set set;
+ struct timeval timeout;
+ int rv;
+ int s[2];
+ is_install_pkg_file = 0;
+
+ if(sdb_socketpair(s)) {
+ D("cannot create service socket pair\n");
+ exit(-1);
+ }
char *buffer = malloc(SYNC_DATA_MAX);
- if(buffer == 0) goto fail;
+ if(buffer == 0) {
+ goto fail;
+ }
- for(;;) {
- D("sync: waiting for command\n");
+ FD_ZERO(&set); /* clear the set */
+ FD_SET(fd, &set); /* add our file descriptor to the set */
+
+ pid_t pid = fork();
+
+ if (pid == 0) {
+ sdb_close(s[0]); //close the parent fd
+ sync_read_label_notify(s[1]);
+ } else if (pid > 0) {
+ sdb_close(s[1]);
+ for(;;) {
+ D("sync: waiting for command for %d sec\n", SYNC_TIMEOUT);
+
+ // in Linux, timeout would be altered after each select() call.
+ // Therefore, re-initialization is needed.
+ timeout.tv_sec = SYNC_TIMEOUT;
+ timeout.tv_usec = 0;
+ rv = select(fd + 1, &set, NULL, NULL, &timeout);
+ if (rv == -1) {
+ D("sync file descriptor select failed\n");
+ } else if (rv == 0) {
+ D("sync file descriptor timeout: (took %d sec over)\n", SYNC_TIMEOUT);
+ fail_message(fd, "sync timeout");
+ goto fail;
+ }
- if(readx(fd, &msg.req, sizeof(msg.req))) {
- fail_message(fd, "command read failure");
- break;
- }
- namelen = ltohl(msg.req.namelen);
- if(namelen > 1024) {
- fail_message(fd, "invalid namelen");
- break;
- }
- if(readx(fd, name, namelen)) {
- fail_message(fd, "filename read failure");
- break;
- }
- name[namelen] = 0;
-
- msg.req.namelen = 0;
- D("sync: '%s' '%s'\n", (char*) &msg.req, name);
-
- switch(msg.req.id) {
- case ID_STAT:
- if(do_stat(fd, name)) goto fail;
- break;
- case ID_LIST:
- if(do_list(fd, name)) goto fail;
- break;
- case ID_SEND:
- if(do_send(fd, name, buffer)) goto fail;
- break;
- case ID_RECV:
- if(do_recv(fd, name, buffer)) goto fail;
- break;
- case ID_QUIT:
- goto fail;
- default:
- fail_message(fd, "unknown command");
- goto fail;
+ if(readx(fd, &msg.req, sizeof(msg.req))) {
+ fail_message(fd, "command read failure");
+ break;
+ }
+ namelen = ltohl(msg.req.namelen);
+ if(namelen > 1024) {
+ fail_message(fd, "invalid namelen");
+ break;
+ }
+ if(readx(fd, name, namelen)) {
+ fail_message(fd, "filename read failure");
+ break;
+ }
+ name[namelen] = 0;
+
+ msg.req.namelen = 0;
+ D("sync: '%s' '%s'\n", (char*) &msg.req, name);
+
+ if (should_drop_privileges() && !verify_sync_rule(name)) {
+ set_developer_privileges();
+ }
+
+ switch(msg.req.id) {
+ case ID_STAT:
+ if(do_stat(fd, name)) goto fail;
+ break;
+ case ID_LIST:
+ if(do_list(fd, name)) goto fail;
+ break;
+ case ID_SEND:
+ if(do_send(fd, s[0], name, buffer)) goto fail;
+ break;
+ case ID_RECV:
+ if(do_recv(fd, name, buffer)) goto fail;
+ break;
+ case ID_QUIT:
+ goto fail;
+ default:
+ fail_message(fd, "unknown command");
+ goto fail;
+ }
}
}
+
fail:
- if(buffer != 0) free(buffer);
+ if(buffer != 0) {
+ free(buffer);
+ }
D("sync: done\n");
+ sync_send_label_notify(s[0], name, 0);
+ sdb_close(s[0]);
+ sdb_close(s[1]);
sdb_close(fd);
}
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 _FILE_SYNC_SERVICE_H_
#define _FILE_SYNC_SERVICE_H_
-#ifdef __ppc__
+#ifdef HAVE_BIG_ENDIAN
static inline unsigned __swap_uint32(unsigned x)
{
return (((x) & 0xFF000000) >> 24)
void file_sync_service(int fd, void *cookie);
+void file_sync_subproc(int fd, void *cookie);
int do_sync_ls(const char *path);
-int do_sync_push(const char *lpath, const char *rpath, int verifyApk);
+int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int isUtf8);
int do_sync_sync(const char *lpath, const char *rpath, int listonly);
int do_sync_pull(const char *rpath, const char *lpath);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <limits.h>
+
+static int recurse(const char *path, mode_t mode, int (*fn)(const char *,mode_t, int)) {
+ struct stat st;
+ char dir[PATH_MAX];
+
+ if (path == NULL) {
+ return -1;
+ }
+ if (lstat (path, &st) == -1) {
+ return -1;
+ }
+ if (strrchr(path, '/') != NULL) {
+ int n = strlen(path)-strlen(strrchr(path, '/'));
+ if (n >= PATH_MAX) {
+ return -1;
+ }
+ strncpy(dir, path, n);
+ dir[n] = '\0';
+ fn(dir, mode,1);
+ return 1;
+ }
+ return -1;
+}
+
+int sdb_chmod(const char *path, mode_t mode, int recursive) {
+#ifdef HAVE_WIN32_PROC
+ fprintf(stderr, "error: sdb_chmod not implemented on Win32 (%s)\n", path);
+ return -1;
+#else
+ struct stat st;
+
+ if (stat (path, &st) == -1)
+ return -1;
+
+ if (chmod (path, mode) == -1) {
+ return -1;
+ }
+ if (recursive) {
+ return recurse(path, mode, sdb_chmod);
+ }
+ return 1;
+#endif
+}
--- /dev/null
+#ifndef _FILEUTILS_H_
+#define _FILEUTILS_H_
+
+int sdb_chmod(const char *path, mode_t mode, int recursive);
+#endif
+
+++ /dev/null
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-
-#include "fdevent.h"
-#include "sdb.h"
-
-#include <linux/fb.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-/* TODO:
-** - sync with vsync to avoid tearing
-*/
-/* This version number defines the format of the fbinfo struct.
- It must match versioning in ddms where this data is consumed. */
-#define DDMS_RAWIMAGE_VERSION 1
-struct fbinfo {
- unsigned int version;
- unsigned int bpp;
- unsigned int size;
- unsigned int width;
- unsigned int height;
- unsigned int red_offset;
- unsigned int red_length;
- unsigned int blue_offset;
- unsigned int blue_length;
- unsigned int green_offset;
- unsigned int green_length;
- unsigned int alpha_offset;
- unsigned int alpha_length;
-} __attribute__((packed));
-
-void framebuffer_service(int fd, void *cookie)
-{
- struct fb_var_screeninfo vinfo;
- int fb, offset;
- char x[256];
-
- struct fbinfo fbinfo;
- unsigned i, bytespp;
-
- fb = open("/dev/graphics/fb0", O_RDONLY);
- if(fb < 0) goto done;
-
- if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done;
- fcntl(fb, F_SETFD, FD_CLOEXEC);
-
- bytespp = vinfo.bits_per_pixel / 8;
-
- fbinfo.version = DDMS_RAWIMAGE_VERSION;
- fbinfo.bpp = vinfo.bits_per_pixel;
- fbinfo.size = vinfo.xres * vinfo.yres * bytespp;
- fbinfo.width = vinfo.xres;
- fbinfo.height = vinfo.yres;
- fbinfo.red_offset = vinfo.red.offset;
- fbinfo.red_length = vinfo.red.length;
- fbinfo.green_offset = vinfo.green.offset;
- fbinfo.green_length = vinfo.green.length;
- fbinfo.blue_offset = vinfo.blue.offset;
- fbinfo.blue_length = vinfo.blue.length;
- fbinfo.alpha_offset = vinfo.transp.offset;
- fbinfo.alpha_length = vinfo.transp.length;
-
- /* HACK: for several of our 3d cores a specific alignment
- * is required so the start of the fb may not be an integer number of lines
- * from the base. As a result we are storing the additional offset in
- * xoffset. This is not the correct usage for xoffset, it should be added
- * to each line, not just once at the beginning */
- offset = vinfo.xoffset * bytespp;
-
- offset += vinfo.xres * vinfo.yoffset * bytespp;
-
- if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
-
- lseek(fb, offset, SEEK_SET);
- for(i = 0; i < fbinfo.size; i += 256) {
- if(readx(fb, &x, 256)) goto done;
- if(writex(fd, &x, 256)) goto done;
- }
-
- if(readx(fb, &x, fbinfo.size % 256)) goto done;
- if(writex(fd, &x, fbinfo.size % 256)) goto done;
-
-done:
- if(fb >= 0) close(fb);
- close(fd);
-}
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2009 bsdroid project
- * Alexey Tarasov <tarasov@dodologics.com>
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
+/*
+ * 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 <errno.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
/* here's how these things work.
struct iovec iov;
char dummy = '!';
char buffer[sizeof(struct cmsghdr) + sizeof(int)];
+ int flags;
iov.iov_base = &dummy;
iov.iov_len = 1;
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)
+ if (ret >= 0) {
+ sdb_close(fd);
break;
+ }
if (errno == EINTR)
continue;
D("sending new file descriptor to JDWP %d failed: %s\n",
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 );
}
/* 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;
}
#endif /* !SDB_HOST */
-
-/* the list of mutexes used by addb */
+/*
+ * 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.
+ */
+/* the list of mutexes used by sdb */
+/* #ifndef __MUTEX_LIST_H
+ * Do not use an include-guard. This file is included once to declare the locks
+ * and once in win32 to actually do the runtime initialization.
+ */
#ifndef SDB_MUTEX
#error SDB_MUTEX not defined when including this file
#endif
-
SDB_MUTEX(dns_lock)
SDB_MUTEX(socket_list_lock)
SDB_MUTEX(transport_lock)
#endif
SDB_MUTEX(usb_lock)
+// Sadly logging to /data/sdb/sdb-... is not thread safe.
+// After modifying sdb.h::D() to count invocations:
+// DEBUG(jpa):0:Handling main()
+// DEBUG(jpa):1:[ usb_init - starting thread ]
+// (Oopsies, no :2:, and matching message is also gone.)
+// DEBUG(jpa):3:[ usb_thread - opening device ]
+// DEBUG(jpa):4:jdwp control socket started (10)
+SDB_MUTEX(D_lock)
+
#undef SDB_MUTEX
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "sockets.h"
+#include <errno.h>
+#include <assert.h>
+
+#include "properties.h"
+//#include "loghack.h"
+#include "sysdeps.h"
+#define TRACE_TAG TRACE_PROPERTIES
+#include "sdb.h"
+
+#define HAVE_TIZEN_PROPERTY
+
+#ifdef HAVE_TIZEN_PROPERTY
+
+#define HAVE_PTHREADS
+#include <stdio.h>
+#include "strutils.h"
+#include "threads.h"
+
+static mutex_t env_lock = MUTEX_INITIALIZER;
+
+#define TIZEN_PROPERTY_FILE "/tmp/.sdb.conf" /* tizen specific*/
+#define PROPERTY_SEPARATOR "="
+
+struct config_node {
+ char *key;
+ char value[PROPERTY_VALUE_MAX];
+} sdbd_config[] = {
+ { "service.sdb.tcp.port", "0" },
+ { NULL, "" }
+};
+
+void property_save();
+
+static void property_init(void)
+{
+ int fd;
+ int i = 0;
+ char buffer[PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX+1];
+ char *tok = NULL;
+
+ fd = unix_open(TIZEN_PROPERTY_FILE, O_RDONLY);
+ if (fd < 0)
+ return;
+ for(;;) {
+ if(read_line(fd, buffer, PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX+1) < 0)
+ break;
+ tok = strtok(buffer, PROPERTY_SEPARATOR);
+ for (i = 0; sdbd_config[i].key; i++) {
+ if (!strcmp(tok, sdbd_config[i].key)) {
+ tok = strtok(NULL, PROPERTY_SEPARATOR);
+ strncpy(sdbd_config[i].value, tok, PROPERTY_VALUE_MAX);
+ D("property init key=%s, value=%s\n", sdbd_config[i].key, tok);
+ }
+ }
+
+ }
+ sdb_close(fd);
+ D("called property_init\n");
+}
+
+void property_save()
+{
+ int fd;
+ int i = 0;
+ char buffer[PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX+1];
+
+ mutex_lock(&env_lock);
+ if (access(TIZEN_PROPERTY_FILE, F_OK) == 0) // if exist
+ sdb_unlink(TIZEN_PROPERTY_FILE);
+
+ fd = unix_open(TIZEN_PROPERTY_FILE, O_WRONLY | O_CREAT | O_APPEND, 0640);
+ if (fd <0 ) {
+ mutex_unlock(&env_lock);
+ return;
+ }
+
+ for (i = 0; sdbd_config[i].key; i++) {
+ sprintf(buffer,"%s%s%s\n", sdbd_config[i].key, PROPERTY_SEPARATOR, sdbd_config[i].value);
+ sdb_write(fd, buffer, strlen(buffer));
+ }
+ sdb_close(fd);
+ mutex_unlock(&env_lock);
+}
+
+int property_set(const char *key, const char *value)
+{
+ int i = 0;
+
+ mutex_lock(&env_lock);
+ for (i = 0; sdbd_config[i].key; i++) {
+ if (!strcmp(key,sdbd_config[i].key)) {
+ strncpy(sdbd_config[i].value, value, PROPERTY_VALUE_MAX);
+ D("property set key=%s, value=%s\n", key, value);
+ break;
+ }
+ }
+ mutex_unlock(&env_lock);
+ property_save();
+ return -1;
+}
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+ int len = 0;
+ int i = 0;
+
+ property_init();
+ mutex_lock(&env_lock);
+ for (i = 0; sdbd_config[i].key; i++) {
+ if (!strcmp(key,sdbd_config[i].key)) {
+ len = strlen(sdbd_config[i].value);
+ memcpy(value, sdbd_config[i].value, len + 1);
+ D("property get key=%s, value=%s\n", key, value);
+ mutex_unlock(&env_lock);
+ return len;
+ }
+ }
+
+ if(default_value) {
+ len = strlen(default_value);
+ memcpy(value, default_value, len + 1);
+ D("by default, property get key=%s, value=%s\n", key, value);
+ }
+ mutex_unlock(&env_lock);
+ return len;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
+ void *cookie)
+{
+ return 0;
+}
+
+#elif defined(HAVE_LIBC_SYSTEM_PROPERTIES)
+
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+//#include <sys/_system_properties.h>
+
+int property_set(const char *key, const char *value)
+{
+ return __system_property_set(key, value);
+}
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+ int len;
+
+ len = __system_property_get(key, value);
+ if(len > 0) {
+ return len;
+ }
+
+ if(default_value) {
+ len = strlen(default_value);
+ memcpy(value, default_value, len + 1);
+ }
+ return len;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
+ void *cookie)
+{
+ char name[PROP_NAME_MAX];
+ char value[PROP_VALUE_MAX];
+ const prop_info *pi;
+ unsigned n;
+
+ for(n = 0; (pi = __system_property_find_nth(n)); n++) {
+ __system_property_read(pi, name, value);
+ propfn(name, value, cookie);
+ }
+ return 0;
+}
+
+#elif defined(HAVE_SYSTEM_PROPERTY_SERVER)
+
+/*
+ * The Linux simulator provides a "system property server" that uses IPC
+ * to set/get/list properties. The file descriptor is shared by all
+ * threads in the process, so we use a mutex to ensure that requests
+ * from multiple threads don't get interleaved.
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <pthread.h>
+
+static pthread_once_t gInitOnce = PTHREAD_ONCE_INIT;
+static pthread_mutex_t gPropertyFdLock = PTHREAD_MUTEX_INITIALIZER;
+static int gPropFd = -1;
+
+/*
+ * Connect to the properties server.
+ *
+ * Returns the socket descriptor on success.
+ */
+static int connectToServer(const char* fileName)
+{
+ int sock = -1;
+ int cc;
+
+ struct sockaddr_un addr;
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ D("UNIX domain socket create failed (errno=%d)\n", errno);
+ return -1;
+ }
+
+ /* connect to socket; fails if file doesn't exist */
+ strcpy(addr.sun_path, fileName); // max 108 bytes
+ addr.sun_family = AF_UNIX;
+ cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));
+ if (cc < 0) {
+ // ENOENT means socket file doesn't exist
+ // ECONNREFUSED means socket exists but nobody is listening
+ D("AF_UNIX connect failed for '%s': %s\n",
+ fileName, strerror(errno));
+ sdb_close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+/*
+ * Perform one-time initialization.
+ */
+static void init(void)
+{
+ assert(gPropFd == -1);
+
+ gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);
+ if (gPropFd < 0) {
+ D("not connected to system property server\n");
+ } else {
+ D("Connected to system property server\n");
+ }
+}
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+ char sendBuf[1+PROPERTY_KEY_MAX];
+ char recvBuf[1+PROPERTY_VALUE_MAX];
+ int len = -1;
+
+ D("PROPERTY GET [%s]\n", key);
+
+ pthread_once(&gInitOnce, init);
+ if (gPropFd < 0) {
+ /* this mimics the behavior of the device implementation */
+ if (default_value != NULL) {
+ strcpy(value, default_value);
+ len = strlen(value);
+ }
+ return len;
+ }
+
+ if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
+
+ memset(sendBuf, 0xdd, sizeof(sendBuf)); // placate valgrind
+
+ sendBuf[0] = (char) kSystemPropertyGet;
+ strcpy(sendBuf+1, key);
+
+ pthread_mutex_lock(&gPropertyFdLock);
+ if (sdb_write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
+ pthread_mutex_unlock(&gPropertyFdLock);
+ return -1;
+ }
+ if (sdb_read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
+ pthread_mutex_unlock(&gPropertyFdLock);
+ return -1;
+ }
+ pthread_mutex_unlock(&gPropertyFdLock);
+
+ /* first byte is 0 if value not defined, 1 if found */
+ if (recvBuf[0] == 0) {
+ if (default_value != NULL) {
+ strcpy(value, default_value);
+ len = strlen(value);
+ } else {
+ /*
+ * If the value isn't defined, hand back an empty string and
+ * a zero length, rather than a failure. This seems wrong,
+ * since you can't tell the difference between "undefined" and
+ * "defined but empty", but it's what the device does.
+ */
+ value[0] = '\0';
+ len = 0;
+ }
+ } else if (recvBuf[0] == 1) {
+ strcpy(value, recvBuf+1);
+ len = strlen(value);
+ } else {
+ D("Got strange response to property_get request (%d)\n",
+ recvBuf[0]);
+ assert(0);
+ return -1;
+ }
+ D("PROP [found=%d def='%s'] (%d) [%s]: [%s]\n",
+ recvBuf[0], default_value, len, key, value);
+
+ return len;
+}
+
+
+int property_set(const char *key, const char *value)
+{
+ char sendBuf[1+PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX];
+ char recvBuf[1];
+ int result = -1;
+
+ D("PROPERTY SET [%s]: [%s]\n", key, value);
+
+ pthread_once(&gInitOnce, init);
+ if (gPropFd < 0)
+ return -1;
+
+ if (strlen(key) >= PROPERTY_KEY_MAX) return -1;
+ if (strlen(value) >= PROPERTY_VALUE_MAX) return -1;
+
+ memset(sendBuf, 0xdd, sizeof(sendBuf)); // placate valgrind
+
+ sendBuf[0] = (char) kSystemPropertySet;
+ strcpy(sendBuf+1, key);
+ strcpy(sendBuf+1+PROPERTY_KEY_MAX, value);
+
+ pthread_mutex_lock(&gPropertyFdLock);
+ if (sdb_write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {
+ pthread_mutex_unlock(&gPropertyFdLock);
+ return -1;
+ }
+ if (sdb_read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {
+ pthread_mutex_unlock(&gPropertyFdLock);
+ return -1;
+ }
+ pthread_mutex_unlock(&gPropertyFdLock);
+
+ if (recvBuf[0] != 1)
+ return -1;
+ return 0;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
+ void *cookie)
+{
+ D("PROPERTY LIST\n");
+ pthread_once(&gInitOnce, init);
+ if (gPropFd < 0)
+ return -1;
+
+ return 0;
+}
+
+#else
+
+/* SUPER-cheesy place-holder implementation for Win32 */
+#define HAVE_PTHREADS /*tizen specific */
+#include <stdio.h>
+#include "threads.h"
+
+static mutex_t env_lock = MUTEX_INITIALIZER;
+
+int property_get(const char *key, char *value, const char *default_value)
+{
+ char ename[PROPERTY_KEY_MAX + 6];
+ char *p;
+ int len;
+
+ len = strlen(key);
+ if(len >= PROPERTY_KEY_MAX) return -1;
+ memcpy(ename, "PROP_", 5);
+ memcpy(ename + 5, key, len + 1);
+
+ mutex_lock(&env_lock);
+
+ p = getenv(ename);
+ if(p == 0) p = "";
+ len = strlen(p);
+ if(len >= PROPERTY_VALUE_MAX) {
+ len = PROPERTY_VALUE_MAX - 1;
+ }
+
+ if((len == 0) && default_value) {
+ len = strlen(default_value);
+ memcpy(value, default_value, len + 1);
+ } else {
+ memcpy(value, p, len);
+ value[len] = 0;
+ }
+
+ mutex_unlock(&env_lock);
+ D("get [key=%s value='%s:%s']\n", key, ename, value);
+ return len;
+}
+
+
+int property_set(const char *key, const char *value)
+{
+ char ename[PROPERTY_KEY_MAX + 6];
+ char *p;
+ int len;
+ int r;
+
+ if(strlen(value) >= PROPERTY_VALUE_MAX) return -1;
+
+ len = strlen(key);
+ if(len >= PROPERTY_KEY_MAX) return -1;
+ memcpy(ename, "PROP_", 5);
+ memcpy(ename + 5, key, len + 1);
+
+ mutex_lock(&env_lock);
+#ifdef HAVE_MS_C_RUNTIME
+ {
+ char temp[256];
+ snprintf( temp, sizeof(temp), "%s=%s", ename, value);
+ putenv(temp);
+ r = 0;
+ }
+#else
+ r = setenv(ename, value, 1);
+#endif
+ mutex_unlock(&env_lock);
+ D("set [key=%s value='%s%s']\n", key, ename, value);
+ return r;
+}
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
+ void *cookie)
+{
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * 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 __CUTILS_PROPERTIES_H
+#define __CUTILS_PROPERTIES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* System properties are *small* name value pairs managed by the
+** property service. If your data doesn't fit in the provided
+** space it is not appropriate for a system property.
+**
+** WARNING: system/bionic/include/sys/system_properties.h also defines
+** these, but with different names. (TODO: fix that)
+*/
+#define PROPERTY_KEY_MAX 32
+#define PROPERTY_VALUE_MAX 92
+
+/* property_get: returns the length of the value which will never be
+** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
+** (the length does not include the terminating zero).
+**
+** If the property read fails or returns an empty value, the default
+** value is used (if nonnull).
+*/
+int property_get(const char *key, char *value, const char *default_value);
+
+/* property_set: returns 0 on success, < 0 on failure
+*/
+int property_set(const char *key, const char *value);
+
+int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);
+
+#ifdef HAVE_SYSTEM_PROPERTY_SERVER
+/*
+ * We have an external property server instead of built-in libc support.
+ * Used by the simulator.
+ */
+#define SYSTEM_PROPERTY_PIPE_NAME "/tmp/sdb-sysporp"
+
+enum {
+ kSystemPropertyUnknown = 0,
+ kSystemPropertyGet,
+ kSystemPropertySet,
+ kSystemPropertyList
+};
+#endif /*HAVE_SYSTEM_PROPERTY_SERVER*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * 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 ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
+#define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H
+
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <pthread.h> /* for pthread_once() */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef D
+# define D(...) do{}while(0)
+#endif
+
+/* Try to open a new Qemu fast-pipe. This function returns a file descriptor
+ * that can be used to communicate with a named service managed by the
+ * emulator.
+ *
+ * This file descriptor can be used as a standard pipe/socket descriptor.
+ *
+ * 'pipeName' is the name of the emulator service you want to connect to.
+ * E.g. 'opengles' or 'camera'.
+ *
+ * On success, return a valid file descriptor
+ * Returns -1 on error, and errno gives the error code, e.g.:
+ *
+ * EINVAL -> unknown/unsupported pipeName
+ * ENOSYS -> fast pipes not available in this system.
+ *
+ * ENOSYS should never happen, except if you're trying to run within a
+ * misconfigured emulator.
+ *
+ * You should be able to open several pipes to the same pipe service,
+ * except for a few special cases (e.g. GSM modem), where EBUSY will be
+ * returned if more than one client tries to connect to it.
+ */
+static __inline__ int
+qemu_pipe_open(const char* pipeName)
+{
+ char buff[256];
+ int buffLen;
+ int fd, ret;
+
+ if (pipeName == NULL || pipeName[0] == '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ snprintf(buff, sizeof buff, "pipe:%s", pipeName);
+
+ fd = open("/dev/qemu_pipe", O_RDWR);
+ if (fd < 0) {
+ D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno));
+ //errno = ENOSYS;
+ return -1;
+ }
+
+ buffLen = strlen(buff);
+
+ ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1));
+ if (ret != buffLen+1) {
+ D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno));
+ if (ret == 0) {
+ errno = ECONNRESET;
+ } else if (ret > 0) {
+ errno = EINVAL;
+ }
+ return -1;
+ }
+
+ return fd;
+}
+
+#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/mount.h>
-#include <errno.h>
-
-#include "sysdeps.h"
-
-#define TRACE_TAG TRACE_SDB
-#include "sdb.h"
-
-
-static int system_ro = 1;
-
-/* Returns the device used to mount a directory in /proc/mounts */
-static char *find_mount(const char *dir)
-{
- int fd;
- int res;
- int size;
- char *token = NULL;
- const char delims[] = "\n";
- char buf[4096];
-
- fd = unix_open("/proc/mounts", O_RDONLY);
- if (fd < 0)
- return NULL;
-
- buf[sizeof(buf) - 1] = '\0';
- size = sdb_read(fd, buf, sizeof(buf) - 1);
- sdb_close(fd);
-
- token = strtok(buf, delims);
-
- while (token) {
- char mount_dev[256];
- char mount_dir[256];
- int mount_freq;
- int mount_passno;
-
- res = sscanf(token, "%255s %255s %*s %*s %d %d\n",
- mount_dev, mount_dir, &mount_freq, &mount_passno);
- mount_dev[255] = 0;
- mount_dir[255] = 0;
- if (res == 4 && (strcmp(dir, mount_dir) == 0))
- return strdup(mount_dev);
-
- token = strtok(NULL, delims);
- }
- return NULL;
-}
-
-/* Init mounts /system as read only, remount to enable writes. */
-static int remount_system()
-{
- char *dev;
-
- if (system_ro == 0) {
- return 0;
- }
-
- dev = find_mount("/system");
-
- if (!dev)
- return -1;
-
- system_ro = mount(dev, "/system", "none", MS_REMOUNT, NULL);
-
- free(dev);
-
- return system_ro;
-}
-
-static void write_string(int fd, const char* str)
-{
- writex(fd, str, strlen(str));
-}
-
-void remount_service(int fd, void *cookie)
-{
- int ret = remount_system();
-
- if (!ret)
- write_string(fd, "remount succeeded\n");
- else {
- char buffer[200];
- snprintf(buffer, sizeof(buffer), "remount failed: %s\n", strerror(errno));
- write_string(fd, buffer);
- }
-
- sdb_close(fd);
-}
-
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <time.h>
#include <sys/time.h>
#include <signal.h>
+#include <grp.h>
+#include <pthread.h>
#include "sysdeps.h"
#include "sdb.h"
+#include "strutils.h"
+#include "utils.h"
#if !SDB_HOST
-//#include <private/android_filesystem_config.h> eric
-#include <linux/capability.h>
#include <linux/prctl.h>
-#define SDB_PIDPATH "/var/run/sdbd.pid"
+#define SDB_PIDPATH "/tmp/.sdbd.pid"
#else
#include "usb_vendors.h"
#endif
+#include <system_info_internal.h>
+#include <vconf.h>
+#include "utils.h"
+#define PROC_CMDLINE_PATH "/proc/cmdline"
+#define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial"
+
+#if SDB_TRACE
+SDB_MUTEX_DEFINE( D_lock );
+#endif
int HOST = 0;
+int is_emulator(void) {
+ if (access(USB_NODE_FILE, F_OK) == 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
void handle_sig_term(int sig) {
#ifdef SDB_PIDPATH
if (access(SDB_PIDPATH, F_OK) == 0)
- sdb_unlink(SDB_PIDPATH);
+ sdb_unlink(SDB_PIDPATH);
#endif
- if (access("/dev/samsung_sdb", F_OK) == 0) {
- exit(0);
+ char *cmd1_args[] = {"/usr/bin/killall", "/usr/bin/debug_launchpad_preloading_preinitializing_daemon", NULL};
+
+ if (!is_emulator()) {
+ int val = 0;
+ if (vconf_get_int(DEBUG_MODE_KEY, &val)) {
+ D("Failed to get debug mode\n");
+ } else {
+ if (usb_mode != 6 && val == 6) { // set mtp mode by default!.
+ vconf_set_int(DEBUG_MODE_KEY, 2);
+ }
+ }
} else {
- // do nothing on a emulator
+ // do nothing on a emulator
}
+ spawn("/usr/bin/killall", cmd1_args);
+ sdb_sleep_ms(1000);
}
static const char *sdb_device_banner = "device";
{
va_list ap;
va_start(ap, fmt);
- fprintf(stderr, "error: %s: ", strerror(errno));
+ fprintf(stderr, "error: (errno:%d): ", errno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
{ "sysdeps", TRACE_SYSDEPS },
{ "transport", TRACE_TRANSPORT },
{ "jdwp", TRACE_JDWP },
+ { "services", TRACE_SERVICES },
+ { "properties", TRACE_PROPERTIES },
+ { "sdktools", TRACE_SDKTOOLS },
{ NULL, 0 }
};
}
}
+#if !SDB_HOST
+/*
+ * Implements SDB tracing inside the emulator.
+ */
+
+#include <stdarg.h>
+
+/*
+ * Redefine open and write for qemu_pipe.h that contains inlined references
+ * to those routines. We will redifine them back after qemu_pipe.h inclusion.
+ */
+
+#undef open
+#undef write
+#define open sdb_open
+#define write sdb_write
+#include "qemu_pipe.h"
+#undef open
+#undef write
+#define open ___xxx_open
+#define write ___xxx_write
+
+/* A handle to sdb-debug qemud service in the emulator. */
+int sdb_debug_qemu = -1;
+
+/* Initializes connection with the sdb-debug qemud service in the emulator. */
+#if 0 /* doen't support in Tizen */
+static int sdb_qemu_trace_init(void)
+{
+ char con_name[32];
+
+ if (sdb_debug_qemu >= 0) {
+ return 0;
+ }
+
+ /* sdb debugging QEMUD service connection request. */
+ snprintf(con_name, sizeof(con_name), "qemud:sdb-debug");
+ sdb_debug_qemu = qemu_pipe_open(con_name);
+ return (sdb_debug_qemu >= 0) ? 0 : -1;
+}
+
+void sdb_qemu_trace(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ char msg[1024];
+
+ if (sdb_debug_qemu >= 0) {
+ vsnprintf(msg, sizeof(msg), fmt, args);
+ sdb_write(sdb_debug_qemu, msg, strlen(msg));
+ }
+}
+#endif
+#endif /* !SDB_HOST */
apacket *get_apacket(void)
{
void put_apacket(apacket *p)
{
- free(p);
+ if (p != NULL) {
+ free(p);
+ p = NULL;
+ }
}
void handle_online(void)
cp->msg.command = A_CNXN;
cp->msg.arg0 = A_VERSION;
cp->msg.arg1 = MAX_PAYLOAD;
- snprintf((char*) cp->data, sizeof cp->data, "%s::",
- HOST ? "host" : sdb_device_banner);
+
+ char device_name[256]={0,};
+ int r = 0;
+ int status = 0;
+ if (is_pwlocked()) {
+ status = 1;
+ t->connection_state = CS_PWLOCK;
+ }
+
+ if (is_emulator()) {
+ r = get_emulator_name(device_name, sizeof device_name);
+ } else {
+ r = get_device_name(device_name, sizeof device_name);
+ }
+ if (r < 0) {
+ snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, status);
+ } else {
+ snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, status);
+ }
+
+ D("CNXN data:%s\n", (char*)cp->data);
cp->msg.data_length = strlen((char*) cp->data) + 1;
+
send_packet(cp, t);
#if SDB_HOST
/* XXX why sleep here? */
#endif
}
+static void send_device_status()
+{
+ D("broadcast device status\n");
+ apacket* cp = get_apacket();
+ cp->msg.command = A_STAT;
+ cp->msg.arg0 = is_pwlocked();
+ cp->msg.arg1 = 0;
+
+ broadcast_transport(cp);
+
+ //all broadcasted packets are memory copied
+ //so, we should call put_apacket
+ put_apacket(cp);
+}
+
static char *connection_state_name(atransport *t)
{
if (t == NULL) {
}
}
+static int get_str_cmdline(char *src, char *dest, char str[], int str_size) {
+ char *s = strstr(src, dest);
+ if (s == NULL) {
+ return -1;
+ }
+ char *e = strstr(s, " ");
+ if (e == NULL) {
+ return -1;
+ }
+
+ int len = e-s-strlen(dest);
+
+ if (len >= str_size) {
+ D("buffer size(%d) should be bigger than %d\n", str_size, len+1);
+ return -1;
+ }
+
+ strncpy(str, s + strlen(dest), len);
+ str[len]='\0';
+ return len;
+}
+
+int get_emulator_forward_port() {
+ char cmdline[512];
+ int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY);
+ char *port_str = "sdb_port=";
+ char port_buf[128]={0,};
+ int port = -1;
+
+ if (fd < 0) {
+ return -1;
+ }
+ if(read_line(fd, cmdline, sizeof(cmdline))) {
+ D("qemu cmd: %s\n", cmdline);
+ if (get_str_cmdline(cmdline, port_str, port_buf, sizeof(port_buf)) < 1) {
+ D("could not get port from cmdline\n");
+ sdb_close(fd);
+ return -1;
+ }
+ // FIXME: remove comma!
+ port_buf[strlen(port_buf)-1]='\0';
+ port = strtol(port_buf, NULL, 10);
+ }
+ sdb_close(fd);
+ return port;
+}
+
+int get_emulator_name(char str[], int str_size) {
+ char cmdline[512];
+ int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY);
+ char *name_str = "vm_name=";
+
+ if (fd < 0) {
+ D("fail to read /proc/cmdline\n");
+ return -1;
+ }
+ if(read_line(fd, cmdline, sizeof(cmdline))) {
+ D("qemu cmd: %s\n", cmdline);
+ if (get_str_cmdline(cmdline, name_str, str, str_size) < 1) {
+ D("could not get emulator name from cmdline\n");
+ sdb_close(fd);
+ return -1;
+ }
+ }
+ sdb_close(fd);
+ return 0;
+}
+
+int get_device_name(char str[], int str_size) {
+ char *value = NULL;
+ int r = system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &value);
+ if (r != SYSTEM_INFO_ERROR_NONE) {
+ D("fail to get system model:%d\n", errno);
+ return -1;
+ } else {
+ s_strncpy(str, value, str_size);
+ D("returns model_name:%s\n", value);
+ if (value != NULL) {
+ free(value);
+ }
+ return 0;
+ }
+ /*
+ int fd = unix_open(USB_SERIAL_PATH, O_RDONLY);
+ if (fd < 0) {
+ D("fail to read:%s (%d)\n", USB_SERIAL_PATH, errno);
+ return -1;
+ }
+
+ if(read_line(fd, str, str_size)) {
+ D("device serial name: %s\n", str);
+ sdb_close(fd);
+ return 0;
+ }
+ sdb_close(fd);
+ */
+ return -1;
+}
+
void parse_banner(char *banner, atransport *t)
{
char *type, *product, *end;
return;
}
+ if(!strcmp(type, "sideload")) {
+ D("setting connection_state to CS_SIDELOAD\n");
+ t->connection_state = CS_SIDELOAD;
+ update_transports();
+ return;
+ }
+
t->connection_state = CS_HOST;
}
{
asocket *s;
- D("handle_packet() %d\n", p->msg.command);
+ D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
+ ((char*) (&(p->msg.command)))[1],
+ ((char*) (&(p->msg.command)))[2],
+ ((char*) (&(p->msg.command)))[3]);
print_packet("recv", p);
break;
case A_OPEN: /* OPEN(local-id, 0, "destination") */
- if(t->connection_state != CS_OFFLINE) {
- char *name = (char*) p->data;
- name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
- s = create_local_service_socket(name);
- if(s == 0) {
- send_close(0, p->msg.arg0, t);
- } else {
- s->peer = create_remote_socket(p->msg.arg0, t);
- s->peer->peer = s;
- send_ready(s->id, s->peer->id, t);
- s->ready(s);
+ if (is_pwlocked() && t->connection_state == CS_PWLOCK) { // in case of already locked before get A_CNXN
+ D("open failed due to password locked before get A_CNXN:%d\n", t->connection_state);
+ send_close(0, p->msg.arg0, t);
+ } else {
+ if(t->connection_state != CS_OFFLINE) {
+ char *name = (char*) p->data;
+ name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
+ s = create_local_service_socket(name);
+ if(s == 0) {
+ send_close(0, p->msg.arg0, t);
+ } else {
+ s->peer = create_remote_socket(p->msg.arg0, t);
+ s->peer->peer = s;
+ send_ready(s->id, s->peer->id, t);
+ s->ready(s);
+ }
}
}
break;
fd = sdb_socket_accept(_fd, &addr, &alen);
if(fd < 0) return;
- sdb_socket_setbufsize(fd, CHUNK_SIZE);
+ if (sdb_socket_setbufsize(fd, CHUNK_SIZE) == -1) {
+ D("failed to set buffer size of sdb socket: (errno:%d)\n", errno);
+ }
s = create_local_socket(fd);
if(s) {
return -2;
}
- close_on_exec(l->fd);
+ if (close_on_exec(l->fd) < 0) {
+ D("fail to close fd exec:%d\n",l->fd);
+ }
if(!strcmp(l->connect_to, "*smartsocket*")) {
fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
} else {
return 0;
}
-#ifdef HAVE_FORKEXEC
-static void sigchld_handler(int n)
-{
- int status;
- while(waitpid(-1, &status, WNOHANG) > 0) ;
-}
-#endif
-
#ifdef HAVE_WIN32_PROC
static BOOL WINAPI ctrlc_handler(DWORD type)
{
int fd;
fd = unix_open("/dev/null", O_RDONLY);
+ if (fd < 0) {
+ // hopefully not gonna happen
+ return;
+ }
dup2(fd, 0);
+ sdb_close(fd);
fd = unix_open("/tmp/sdb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
if(fd < 0) {
fd = unix_open("/dev/null", O_WRONLY);
+ if (fd < 0) {
+ // hopefully not gonna happen
+ return;
+ }
}
dup2(fd, 1);
dup2(fd, 2);
+ sdb_close(fd);
fprintf(stderr,"--- sdb starting (pid %d) ---\n", getpid());
#endif
}
char path[PATH_MAX];
struct tm now;
time_t t;
- const char* p = getenv("SDB_TRACE");
-
- if (p == NULL)
- return;
+// char value[PROPERTY_VALUE_MAX];
+ const char* p = getenv("SDB_TRACE");
+ // 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 */
+ property_get("persist.sdb.trace_mask", value, "");
+ if (sscanf(value, "%x", &sdb_trace_mask) != 1)
+ return;
+#endif
+ if (p == NULL) {
+ return;
+ }
tzset();
time(&t);
localtime_r(&t, &now);
strftime(path, sizeof(path),
- "/tmp/sdb-%Y-%m-%d-%H-%M-%S.txt",
+ "/tmp/sdbd-%Y-%m-%d-%H-%M-%S.txt",
&now);
fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
- if (fd < 0)
+ if (fd < 0) {
return;
+ }
// redirect stdout and stderr to the log file
dup2(fd, 1);
dup2(fd, 2);
- fprintf(stderr,"--- sdb starting (pid %d) ---\n", getpid());
+ fprintf(stderr,"--- sdbd starting (pid %d) ---\n", getpid());
+ sdb_close(fd);
fd = unix_open("/dev/null", O_RDONLY);
+ if (fd < 0) {
+ // hopefully not gonna happen
+ return;
+ }
dup2(fd, 0);
+ sdb_close(fd);
}
int daemonize(void) {
default:
_exit(0);
}
-
- if (setsid() == -1)
- return -1;
-
- if (chdir("/") < 0)
- D("sdbd: unable to change working directory to /\n");
-
#ifdef SDB_PIDPATH
FILE *f = fopen(SDB_PIDPATH, "w");
if (f != NULL) {
- fprintf(f, "%ld\n", (long) getpid());
+ fprintf(f, "%d\n", getpid());
fclose(f);
}
#endif
+ if (setsid() == -1)
+ return -1;
+
+ if (chdir("/") < 0)
+ D("sdbd: unable to change working directory to /\n");
+
return 0;
}
#endif
// wait for the "OK\n" message
sdb_close(fd[1]);
int ret = sdb_read(fd[0], temp, 3);
+ int saved_errno = errno;
sdb_close(fd[0]);
if (ret < 0) {
- fprintf(stderr, "could not read ok from SDB Server, errno = %d\n", errno);
+ fprintf(stderr, "could not read ok from SDB Server, errno = %d\n", saved_errno);
return -1;
}
if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
snprintf(target_str, target_size, "tcp:%d", server_port);
}
+#if !SDB_HOST
+static void init_drop_privileges() {
+#ifdef _DROP_PRIVILEGE
+ rootshell_mode = 0;
+#else
+ rootshell_mode = 1;
+#endif
+}
+
+int is_pwlocked(void) {
+ int pwlock_status = 0;
+ int pwlock_type = 0;
+
+ if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &pwlock_status)) {
+ pwlock_status = 0;
+ D("failed to get pw lock status\n");
+ }
+ if (vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, &pwlock_type)) {
+ pwlock_type = 0;
+ D("failed to get pw lock type\n");
+ }
+ if (pwlock_status == VCONFKEY_IDLE_LOCK && (pwlock_type == SETTING_SCREEN_LOCK_TYPE_SIMPLE_PASSWORD || pwlock_type == SETTING_SCREEN_LOCK_TYPE_PASSWORD)) {
+ D("device has been locked\n");
+ return 1; // locked!
+ }
+
+ return 0; // unlocked!
+}
+
+int should_drop_privileges() {
+ if (rootshell_mode == 1) { // if root, then don't drop
+ return 0;
+ }
+ return 1;
+}
+
+static void *pwlock_tmp_cb(void *x)
+{
+ int status = is_pwlocked();
+ /**
+ * FIXME: make it callback using vconf_notify_key_changed
+ */
+
+ while(1) {
+ if (status != is_pwlocked()) {
+ send_device_status();
+ status = is_pwlocked();
+ }
+ sdb_sleep_ms(3000);
+ }
+ return 0;
+}
+
+void register_pwlock_cb() {
+ D("registerd vconf callback\n");
+
+ sdb_thread_t t;
+ if(sdb_thread_create( &t, pwlock_tmp_cb, NULL)){
+ D("cannot create service thread\n");
+ return;
+ }
+}
+
+int set_developer_privileges() {
+ gid_t groups[] = { SID_DEVELOPER, SID_APP_LOGGING, SID_SYS_LOGGING, SID_INPUT };
+ if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) {
+ D("set groups failed (errno: %d, %s)\n", errno, strerror(errno));
+ }
+
+ // then switch user and group to developer
+ if (setgid(SID_DEVELOPER) != 0) {
+ D("set group id failed (errno: %d, %s)\n", errno, strerror(errno));
+ return -1;
+ }
+
+ if (setuid(SID_DEVELOPER) != 0) {
+ D("set user id failed (errno: %d)\n", errno);
+ return -1;
+ }
+
+ if (chdir("/home/developer") < 0) {
+ D("sdbd: unable to change working directory to /home/developer\n");
+ } else {
+ if (chdir("/") < 0) {
+ D("sdbd: unable to change working directory to /\n");
+ }
+ }
+ // TODO: use pam later
+ putenv("HOME=/home/developer");
+
+ return 1;
+}
+#define ONDEMAND_ROOT_PATH "/home/developer"
+
+static void execute_required_process() {
+ char *cmd_args[] = {"/usr/bin/debug_launchpad_preloading_preinitializing_daemon",NULL};
+
+ spawn("/usr/bin/debug_launchpad_preloading_preinitializing_daemon", cmd_args);
+}
+
+static void init_sdk_requirements() {
+ struct stat st;
+
+ // initialize usb mode
+ usb_mode = 0;
+
+ if (stat(ONDEMAND_ROOT_PATH, &st) == -1) {
+ return;
+ }
+ if (st.st_uid != SID_DEVELOPER || st.st_gid != SID_DEVELOPER) {
+ char *arg_list[] = {"/bin/chown", ONDEMAND_ROOT_PATH, "-R", NULL};
+
+ spawn("/bin/chown", arg_list);
+ }
+
+ execute_required_process();
+
+ register_pwlock_cb();
+}
+#endif /* !SDB_HOST */
+
int sdb_main(int is_daemon, int server_port)
{
-#if 0 //!SDB_HOST eric
- int secure = 0;
- int port;
- char value[PROPERTY_VALUE_MAX];
+#if !SDB_HOST
+ init_drop_privileges();
+ init_sdk_requirements();
+ umask(000);
#endif
atexit(sdb_cleanup);
#ifdef HAVE_WIN32_PROC
SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#elif defined(HAVE_FORKEXEC)
- signal(SIGCHLD, sigchld_handler);
+ // No SIGCHLD. Let the service subproc handle its children.
signal(SIGPIPE, SIG_IGN);
#endif
exit(1);
}
#else
- /* run sdbd in secure mode if ro.secure is set and
- ** we are not in the emulator
- */
-#if 0 //eric
- property_get("ro.kernel.qemu", value, "");
- if (strcmp(value, "1") != 0) {
- property_get("ro.secure", value, "");
- if (strcmp(value, "1") == 0) {
- // don't run as root if ro.secure is set...
- secure = 1;
-
- // ... except we allow running as root in userdebug builds if the
- // service.sdb.root property has been set by the "sdb root" command
- property_get("ro.debuggable", value, "");
- if (strcmp(value, "1") == 0) {
- property_get("service.sdb.root", value, "");
- if (strcmp(value, "1") == 0) {
- secure = 0;
- }
- }
- }
- }
-
/* don't listen on a port (default 5037) if running in secure mode */
/* don't run as root if we are running in secure mode */
- if (secure) {
+
+ if (should_drop_privileges()) {
+# if 0
struct __user_cap_header_struct header;
struct __user_cap_data_struct cap;
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
exit(1);
}
-
/* add extra groups:
- ** AID_SDB to access the USB driver
- ** AID_LOG to read system logs (sdb logcat)
- ** AID_INPUT to diagnose input issues (getevent)
- ** AID_INET to diagnose network issues (netcfg, ping)
- ** AID_GRAPHICS to access the frame buffer
- ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
- ** AID_SDCARD_RW to allow writing to the SD card
- ** AID_MOUNT to allow unmounting the SD card before rebooting
+ ** SID_TTY to access /dev/ptmx
*/
- gid_t groups[] = { AID_SDB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
- AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, AID_MOUNT };
+ gid_t groups[] = { SID_TTY, SID_APP_LOGGING, SID_SYS_LOGGING };
if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
exit(1);
}
-
- /* then switch user and group to "shell" */
- if (setgid(AID_SHELL) != 0) {
+ /* then switch user and group to "developer" */
+ if (setgid(SID_DEVELOPER) != 0) {
+ fprintf(stderr, "set group id failed errno: %d\n", errno);
exit(1);
}
- if (setuid(AID_SHELL) != 0) {
+ if (setuid(SID_DEVELOPER) != 0) {
+ fprintf(stderr, "set user id failed errno: %d\n", errno);
exit(1);
}
cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
cap.inheritable = 0;
capset(&header, &cap);
-
+#endif
D("Local port disabled\n");
} else {
-#endif
char local_name[30];
build_local_name(local_name, sizeof(local_name), server_port);
if(install_listener(local_name, "*smartsocket*", NULL)) {
- exit(1);
+ D("Cannot install listener (smartsocket)\n");
+ return 1;
+ //exit(1);
}
-#if 0 //eric
}
-#endif
- /* for the device, start the usb transport if the
- ** android usb device exists and the "service.sdb.tcp.port" and
- ** "persist.sdb.tcp.port" properties are not set.
- ** Otherwise start the network transport.
- */
-#if 0 //eric
- property_get("service.sdb.tcp.port", value, "");
- if (!value[0])
- property_get("persist.sdb.tcp.port", value, "");
- if (sscanf(value, "%d", &port) == 1 && port > 0) {
- // listen on TCP port specified by service.sdb.tcp.port property
- local_init(port);
- } else
-#endif
- if (access("/dev/samsung_sdb", F_OK) == 0) {
+
+ if (!is_emulator()) {
// listen on USB
usb_init();
+ // listen on tcp
+ //local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
} else {
// listen on default port
local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
}
+
+#if 0 /* tizen specific */
+ D("sdb_main(): pre init_jdwp()\n");
init_jdwp();
+ D("sdb_main(): post init_jdwp()\n");
+#endif
#endif
if (is_daemon)
start_logging();
}
+ D("Event loop starting\n");
+
fdevent_loop();
usb_cleanup();
char hostbuf[100];
char serial[100];
- strncpy(hostbuf, host, sizeof(hostbuf) - 1);
+ s_strncpy(hostbuf, host, sizeof(hostbuf) - 1);
if (portstr) {
if (portstr - host >= sizeof(hostbuf)) {
snprintf(buffer, buffer_size, "bad host name %s", host);
fd = socket_network_client(hostbuf, port, SOCK_STREAM);
if (fd < 0) {
- snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
+ snprintf(buffer, buffer_size, "unable to connect to %s", host);
return;
}
D("client: connected on remote on fd %d\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
- register_socket_transport(fd, serial, port, 0);
+ register_socket_transport(fd, serial, port, 0, NULL);
snprintf(buffer, buffer_size, "connected to %s", serial);
}
}
/* Preconditions met, try to connect to the emulator. */
- if (!local_connect_arbitrary_ports(console_port, sdb_port)) {
+ if (!local_connect_arbitrary_ports(console_port, sdb_port, NULL)) {
snprintf(buffer, buffer_size,
"Connected to emulator on ports %d,%d", console_port, sdb_port);
} else {
}
#endif
+int copy_packet(apacket* dest, apacket* src) {
+
+ if(dest == NULL) {
+ D("dest packet is NULL\n");
+ return -1;
+ }
+
+ if(src == NULL) {
+ D("src packet is NULL\n");
+ return -1;
+ }
+
+ dest->next = src->next;
+ dest->ptr = src->ptr;
+ dest->len = src->len;
+
+ memcpy(&(dest->msg), &(src->msg), sizeof(amessage));
+ // TODO: should verify what if data length is over MAX_PAYLOAD
+ int data_length = src->msg.data_length;
+ if(data_length > MAX_PAYLOAD) {
+ data_length = MAX_PAYLOAD;
+ dest->msg.data_length = data_length;
+ D("copy packet error: %d > MAX_PAYLOAD\n", src->msg.data_length);
+ }
+
+ memcpy(&(dest->data), &(src->data), data_length);
+ return 0;
+}
+
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
{
atransport *transport = NULL;
type = kTransportAny;
} else if (!strncmp(service, "transport:", strlen("transport:"))) {
service += strlen("transport:");
- serial = strdup(service);
+ serial = service;
}
transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
unregister_all_tcp_transports();
} else {
char hostbuf[100];
- // assume port 5555 if no port is specified
+ // assume port 26101 if no port is specified
if (!strchr(serial, ':')) {
- snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
+ snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:26101", serial);
serial = hostbuf;
}
atransport *t = find_transport(serial);
return 0;
}
// indicates a new emulator instance has started
- if (!strncmp(service,"emulator:",9)) {
- int port = atoi(service+9);
- local_connect(port);
- /* we don't even need to send a reply */
+ if (!strncmp(service,"emulator:",9)) { /* tizen specific */
+ char *tmp = strtok(service+9, DEVICEMAP_SEPARATOR);
+ int port = 0;
+
+ if (tmp == NULL) {
+ port = atoi(service+9);
+ } else {
+ port = atoi(tmp);
+ tmp = strtok(NULL, DEVICEMAP_SEPARATOR);
+ if (tmp != NULL) {
+ local_connect(port, tmp);
+ }
+ }
+ local_connect(port, NULL);
return 0;
}
#endif // SDB_HOST
int main(int argc, char **argv)
{
- sdb_trace_init();
+ sdb_trace_init(); /* tizen specific */
#if SDB_HOST
sdb_sysdeps_init();
+ sdb_trace_init();
return sdb_commandline(argc - 1, argv + 1);
#else
+ /* If sdbd runs inside the emulator this will enable sdb tracing via
+ * sdb-debug qemud service in the emulator. */
+#if 0 /* tizen specific */
+ sdb_qemu_trace_init();
if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
sdb_device_banner = "recovery";
recovery_mode = 1;
}
-
- //sdbd will never die on emulator!
- signal(SIGTERM, handle_sig_term);
+#endif
#if !SDB_HOST
if (daemonize() < 0)
- fatal("daemonize() failed: %.200s", strerror(errno));
- start_device_log();
+ fatal("daemonize() failed: (errno:%d)", errno);
#endif
+
+ start_device_log();
+ D("Handling main()\n");
+
+ //sdbd will never die on emulator!
+ signal(SIGTERM, handle_sig_term); /* tizen specific */
return sdb_main(0, DEFAULT_SDB_PORT);
#endif
}
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <limits.h>
+#include "transport.h" /* readx(), writex() */
+
#define MAX_PAYLOAD 4096
#define A_SYNC 0x434e5953
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
+#define A_STAT 0x54415453
-#define A_VERSION 0x01000000 // SDB protocol version
+#define A_VERSION 0x02000000 // SDB protocol version
-#define SDB_VERSION_MAJOR 1 // Used for help/version information
-#define SDB_VERSION_MINOR 0 // Used for help/version information
+#define SDB_VERSION_MAJOR 2 // Used for help/version information
+#define SDB_VERSION_MINOR 1 // Used for help/version information
-#define SDB_SERVER_VERSION 0 // Increment this when we want to force users to start a new sdb server
+#define SDB_SERVER_VERSION 0 // Increment this when we want to force users to start a new sdb server
typedef struct amessage amessage;
typedef struct apacket apacket;
*/
int closing;
+ /* flag: quit adbd when both ends close the
+ ** local service socket
+ */
+ int exit_on_close;
+
/* the asocket we are connected to
*/
char *serial;
char *product;
int sdb_port; // Use for emulators (local transport)
+ char *device_name; // for connection explorer
/* a list of adisconnect callbacks called when the transport is kicked */
int kicked;
void init_transport_registration(void);
int list_transports(char *buf, size_t bufsize);
void update_transports(void);
+void broadcast_transport(apacket *p);
asocket* create_device_tracker(void);
void close_usb_devices();
/* cause new transports to be init'd and added to the list */
-void register_socket_transport(int s, const char *serial, int port, int local);
+void register_socket_transport(int s, const char *serial, int port, int local, const char *device_name);
/* these should only be used for the "sdb disconnect" command */
void unregister_transport(atransport *t);
#endif
#if !SDB_HOST
+typedef enum {
+ BACKUP,
+ RESTORE
+} BackupOperation;
+int backup_service(BackupOperation operation, char* args);
void framebuffer_service(int fd, void *cookie);
-#if 0 //eric
void log_service(int fd, void *cookie);
void remount_service(int fd, void *cookie);
char * get_log_file_path(const char * log_name);
+
+int rootshell_mode;// 0: developer, 1: root
+int usb_mode; // 2:mtp 6:rndis
+
+// This is the users and groups config for the platform
+
+#define SID_ROOT 0 /* traditional unix root user */
+#define SID_TTY 5 /* group for /dev/ptmx */
+#define SID_APP 5000 /* application */
+#define SID_DEVELOPER 5100 /* developer with SDK */
+#define SID_APP_LOGGING 6509
+#define SID_SYS_LOGGING 6527
+#define SID_INPUT 1004
+
#endif
-#endif
+int is_pwlocked(void);
+int should_drop_privileges(void);
+int set_developer_privileges();
+void set_root_privileges();
+
+int get_emulator_forward_port(void);
+int get_emulator_name(char str[], int str_size);
+int get_device_name(char str[], int str_size);
/* packet allocator */
apacket *get_apacket(void);
void put_apacket(apacket *p);
int check_header(apacket *p);
int check_data(apacket *p);
-/* convenience wrappers around read/write that will retry on
-** EINTR and/or short read/write. Returns 0 on success, -1
-** on error or EOF.
-*/
-int readx(int fd, void *ptr, size_t len);
-int writex(int fd, const void *ptr, size_t len);
-
/* define SDB_TRACE to 1 to enable tracing support, or 0 to disable it */
#define SDB_TRACE 1
TRACE_SYNC,
TRACE_SYSDEPS,
TRACE_JDWP,
-} AdbTrace;
+ TRACE_SERVICES,
+ TRACE_PROPERTIES,
+ TRACE_SDKTOOLS
+} SdbTrace;
#if SDB_TRACE
- int sdb_trace_mask;
+#if !SDB_HOST
+/*
+ * When running inside the emulator, guest's sdbd can connect to 'sdb-debug'
+ * qemud service that can display sdb trace messages (on condition that emulator
+ * has been started with '-debug sdb' option).
+ */
+/* Delivers a trace message to the emulator via QEMU pipe. */
+void sdb_qemu_trace(const char* fmt, ...);
+/* Macro to use to send SDB trace messages to the emulator. */
+#define DQ(...) sdb_qemu_trace(__VA_ARGS__)
+#else
+#define DQ(...) ((void)0)
+#endif /* !SDB_HOST */
+
+ extern int sdb_trace_mask;
+ extern unsigned char sdb_trace_output_count;
void sdb_trace_init(void);
# define SDB_TRACING ((sdb_trace_mask & (1 << TRACE_TAG)) != 0)
/* you must define TRACE_TAG before using this macro */
- #define D(...) \
+# define D(...) \
do { \
- if (SDB_TRACING) \
+ if (SDB_TRACING) { \
+ int save_errno = errno; \
+ sdb_mutex_lock(&D_lock); \
+ fprintf(stderr, "%s::%s():", \
+ __FILE__, __FUNCTION__); \
+ errno = save_errno; \
fprintf(stderr, __VA_ARGS__ ); \
+ fflush(stderr); \
+ sdb_mutex_unlock(&D_lock); \
+ errno = save_errno; \
+ } \
} while (0)
-#else
-//# define D(...) ((void)0)
- #define D(...) \
+# define DR(...) \
do { \
- fprintf(stderr, __VA_ARGS__ ); \
+ if (SDB_TRACING) { \
+ int save_errno = errno; \
+ sdb_mutex_lock(&D_lock); \
+ errno = save_errno; \
+ fprintf(stderr, __VA_ARGS__ ); \
+ fflush(stderr); \
+ sdb_mutex_unlock(&D_lock); \
+ errno = save_errno; \
+ } \
} while (0)
+#else
+# define D(...) ((void)0)
+# define DR(...) ((void)0)
# define SDB_TRACING 0
#endif
#define print_packet(tag,p) do {} while (0)
#endif
-#define DEFAULT_SDB_PORT 26099
-#define DEFAULT_SDB_LOCAL_TRANSPORT_PORT 26101
+#if SDB_HOST_ON_TARGET
+/* sdb and sdbd are coexisting on the target, so use 26099 for sdb
+ * to avoid conflicting with sdbd's usage of 26098
+ */
+# define DEFAULT_SDB_PORT 26099 /* tizen specific */
+#else
+# define DEFAULT_SDB_PORT 26099 /* tizen specific */
+#endif
+
+# define QEMU_FORWARD_IP "10.0.2.2"
-#define SDB_CLASS 0xFF
-#define SDB_SUBCLASS 0x20
-#define SDB_PROTOCOL 0x02
+#define DEFAULT_SDB_LOCAL_TRANSPORT_PORT 26101 /* tizen specific */
+
+#define SDB_CLASS 0xff
+#define SDB_SUBCLASS 0x20 //0x42 /* tizen specific */
+#define SDB_PROTOCOL 0x02 //0x01 /* tizen specific */
void local_init(int port);
-int local_connect(int port);
-int local_connect_arbitrary_ports(int console_port, int sdb_port);
+int local_connect(int port, const char *device_name);
+int local_connect_arbitrary_ports(int console_port, int sdb_port, const char *device_name);
/* usb host/client interface */
void usb_init();
#define CS_HOST 3
#define CS_RECOVERY 4
#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */
+#define CS_SIDELOAD 6
+#define CS_PWLOCK 10
extern int HOST;
+extern int SHELL_EXIT_NOTIFY_FD;
#define CHUNK_SIZE (64*1024)
int sendfailmsg(int fd, const char *reason);
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
+int copy_packet(apacket* dest, apacket* src);
+
+int is_emulator(void);
+#define DEFAULT_DEVICENAME "unknown"
+#if SDB_HOST /* tizen-specific */
+#define DEVICEMAP_SEPARATOR ":"
+#define DEVICENAME_MAX 256
+#define VMS_PATH OS_PATH_SEPARATOR_STR "vms" OS_PATH_SEPARATOR_STR // should include sysdeps.h above
+
+void register_device_name(const char *device_type, const char *device_name, int port);
+int get_devicename_from_shdmem(int port, char *device_name);
+int read_line(const int fd, char* ptr, const size_t maxlen);
+#endif
#endif
+
+#define USB_NODE_FILE "/dev/samsung_sdb"
+#define DEBUG_MODE_KEY "db/usb/sel_mode"
+/*
+ * 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
-#if 0 //eric
-#include <zipfile/zipfile.h>
-#endif
+// tizen specific #include <zipfile/zipfile.h>
#include <sys/types.h>
#include <sys/stat.h>
return -1;
}
+ D("_sdb_connect: return fd %d\n", fd);
return fd;
}
// 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);
if(fd == -2) {
fprintf(stderr,"** daemon still not running");
}
+ D("sdb_connect: return fd %d\n", fd);
return fd;
error:
+/*
+ * 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_
** 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.
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <grp.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/smack.h>
+
+#include "sysdeps.h"
+#include "sdktools.h"
+
+#define TRACE_TAG TRACE_SERVICES
+#include "sdb.h"
+#include "sdktools.h"
+#include "strutils.h"
+#include "fileutils.h"
+#include "utils.h"
+
+struct sudo_command root_commands[] = {
+ /* 0 */ {"da_command", "/usr/bin/da_command"},
+ /* 1 */ {"profile", "/usr/bin/profile_command"},
+ /* 2 */ {"rm1", "rm"},
+ /* 3 */ {"rm2", "/bin/rm"},
+ /* end */ {NULL, NULL}
+};
+
+static struct command_suffix
+{
+ const char *name; // comments for human
+ const char *suffix; //pattern
+};
+
+static struct command_suffix CMD_SUFFIX_DENY_KEYWORD[] = {
+ /* 0 */ {"pipe", "|"},
+ /* 1 */ {"redirect", ">"},
+ /* 2 */ {"semicolon", ";"}, // separated list is executed
+ /* 3 */ {"and", "&"},
+ /* end */ {NULL, NULL}
+};
+
+struct arg_permit_rule sdk_arg_permit_rule[] = {
+ /* 0 */ {"gcove_env1", "^GCOV_PREFIX=((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data$", 1},
+ /* 1 */ {"gcove_env2", "GCOV_PREFIX_STRIP=0", 0},
+ /* 2 */ {"gcove_env3", "LD_LIBRARY_PATH=/home/developer/sdk_tools/gtest/usr/lib:$LD_LIBRARY_PATH", 0},
+ /* 3 */ {"gcove_env4", "TIZEN_LAUNCH_MODE=debug", 0},
+ /* 4 */ {"da_env1", "LD_PRELOAD=/usr/lib/da_probe_osp.so", 0},
+ /* 5 */ {"gcove_arg1", "^\\-\\-gtest_output=xml:((/opt/apps)|(/opt/usr/apps))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,30}\\.xml$", 1},
+ /* end */ {NULL, NULL, 0}
+};
+
+/**
+ * return 1 if the arg is arrowed, otherwise 0 is denied
+ */
+static int is_cmd_suffix_denied(const char* arg) {
+ int i;
+
+ for (i=0; CMD_SUFFIX_DENY_KEYWORD[i].name != NULL; i++) {
+ if (strstr(arg, CMD_SUFFIX_DENY_KEYWORD[i].suffix) != NULL) {
+ D("cmd suffix denied:%s\n", arg);
+ return 1;
+ }
+ }
+ D("cmd suffix arrowed:%s\n", arg);
+ return 0;
+}
+
+static int get_application_install_path(char* pkg_path) {
+ FILE *fp = NULL;
+ char ret_str[PATH_MAX+64] = {0,};
+ int len = 0;
+
+ fp = popen("/usr/bin/pkgcmd -a", "r");
+ if (fp == NULL) {
+ D("failed : popen pkgcmd -a\n");
+ return 0;
+ }
+ if (!fgets(ret_str, PATH_MAX+64, fp)) {
+ D("failed : fgets pkgcmd -a\n");
+ pclose(fp);
+ return 0;
+ }
+ pclose(fp);
+
+ len = strlen(ret_str);
+ while(ret_str[--len]=='\n');
+ ret_str[len + 1] = '\0';
+
+ if (sscanf(ret_str, "Tizen Application Installation Path: %s", pkg_path) != 1) {
+ D("failed : parsing fail (str:%s)\n", ret_str);
+ return 0;
+ }
+
+ D("Tizen install path: %s\n", pkg_path);
+ return 1;
+}
+
+int is_pkg_file_path(const char* path) {
+ regex_t regex;
+ int ret;
+ char pkg_path[PATH_MAX] = {0,};
+ char pkg_path_regx[PATH_MAX+64] = {0,};
+
+ if (!get_application_install_path(pkg_path)) {
+ D("failed to get application install path\n");
+ return 0;
+ }
+
+ snprintf(pkg_path_regx, sizeof(pkg_path_regx),
+ "^.*(%s/tmp/)+[a-zA-Z0-9_\\-\\.]*\\.(wgt|tpk),*[0-9]*$", pkg_path);
+
+ ret = regcomp(®ex, pkg_path_regx, REG_EXTENDED);
+ if (ret){
+ D("failed : recomp (error:%d)\n", ret);
+ return 0;
+ }
+
+ ret = regexec(®ex, path, 0, NULL, 0);
+ regfree(®ex);
+
+ if (ret){
+ D("This path is NOT package file: %s\n", path);
+ return 0;
+ }
+
+ D("This path is temporary package file: %s\n", path);
+ return 1;
+}
+
+/**
+ * Returns 1 if the command is root, otherwise 0.
+ */
+int verify_root_commands(const char *arg1) {
+ char *tokens[MAX_TOKENS];
+ size_t cnt;
+ int ret = 0;
+ int index = -1;
+ int i = 0;
+
+ D("cmd processing......: %s\n", arg1);
+
+ cnt = tokenize(arg1, " ", tokens, MAX_TOKENS);
+ for (i=0; i<cnt; i++) {
+ D("tokenize: %dth: %s\n", i, tokens[i]);
+ }
+ if (cnt == 0 ) {
+ return 0; // just keep going to execute normal commands
+ }
+ index = is_root_commands(tokens[0]);
+ if (index == -1) {
+ if (exec_app_standalone(arg1)) {
+ ret = 1;
+ } else {
+ return 0; // just keep going to execute normal commands
+ }
+ }
+
+ switch (index) {
+ case 0: { // in case of da_command
+ ret = 0;
+ if (!is_cmd_suffix_denied(arg1)) {
+ ret = 1;
+ }
+ // this is exception to allow suffix
+ if (cnt == 5 && !strcmp(tokens[1], "process")
+ && !strcmp(tokens[2], "|")
+ && !strcmp(tokens[3], "grep")
+ && !is_cmd_suffix_denied(tokens[4])) {
+ ret = 1;
+ }
+ break;
+ }
+ case 1: { // in case of oprofile_command
+ ret = 0;
+ if (!is_cmd_suffix_denied(arg1)) {
+ ret = 1;
+ }
+ if (!strcmp(tokens[1], "valgrind") && cnt >= 3) {
+ char *appid = NULL;
+ // the tokens[2] should be apppath
+ int rc = smack_lgetlabel(tokens[2], &appid, SMACK_LABEL_ACCESS);
+ if (rc == 0 && appid != NULL) {
+ if (apply_sdb_rules(SDBD_LABEL_NAME, appid, "rwax") < 0) {
+ D("unable to set %s %s rules\n", SDBD_LABEL_NAME, appid);
+ } else {
+ D("apply rule to '%s %s rwax' rules\n", SDBD_LABEL_NAME, appid);
+ }
+ if (apply_sdb_rules(appid, SDBD_LABEL_NAME, "rwax") < 0) {
+ D("unable to set %s %s rules\n", appid, SDBD_LABEL_NAME);
+ } else {
+ D("apply rule to '%s %s rwax' rules\n", appid, SDBD_LABEL_NAME);
+ }
+ //apply_app_process();
+
+ free(appid);
+ }
+ D("standalone launch for valgrind\n");
+ }
+
+ break;
+ }
+ case 2:
+ case 3:
+ { // in case of rm to remove the temporary package file
+ if (is_cmd_suffix_denied(arg1)) {
+ ret = 0;
+ break;
+ }
+ if (is_pkg_file_path(tokens[1])) {
+ ret = 1;
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ D("doing the cmd as a %s\n", ret == 1 ? "root" : "developer");
+
+ if (cnt) {
+ free_strings(tokens, cnt);
+ }
+
+ return ret;
+}
+
+int verify_app_path(const char* path) {
+ char buf[PATH_MAX];
+
+ snprintf(buf, sizeof buf, "^((%s)|(%s))/[a-zA-Z0-9]{%d}/bin/[a-zA-Z0-9_\\-]{1,}(\\.exe)?$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2, 10);
+ int reg_cmp = regcmp(buf, path);
+
+ return reg_cmp;
+}
+
+int regcmp(const char* pattern, const char* str) {
+ regex_t regex;
+ int ret;
+
+ ret = regcomp(®ex, pattern, REG_EXTENDED);
+ if(ret){ // not match
+ return 0;
+ }
+
+ // execute regular expression
+ ret = regexec(®ex, str, 0, NULL, 0);
+ if(!ret){
+ regfree(®ex);
+ return 1;
+ } else if( ret == REG_NOMATCH ){
+ //D("not valid application path\n");
+ } else{
+ //regerror(ret, ®ex, buf, sizeof(buf));
+ //D("regex match failed: %s\n", buf);
+ }
+ regfree(®ex);
+ return 0;
+}
+
+int env_verify(const char* arg) {
+ int i;
+ for (i=0; sdk_arg_permit_rule[i].name != NULL; i++) {
+ if (sdk_arg_permit_rule[i].expression == 0) {
+ if (!strcmp(sdk_arg_permit_rule[i].pattern, arg)) {
+ D("success to set %s\n", arg);
+ return 1;
+ }
+ } else if (sdk_arg_permit_rule[i].expression == 1) {
+ if (regcmp(sdk_arg_permit_rule[i].pattern, arg)) {
+ D("success to set %s\n", arg);
+ return 1;
+ }
+ }
+ }
+ D("failed to set %s\n", arg);
+ return 0;
+}
+
+int exec_app_standalone(const char* path) {
+ char *tokens[MAX_TOKENS];
+ int ret = 0;
+ int cnt = 0;
+ int flag = 1;
+ int i=0;
+
+ cnt = tokenize(path, " ", tokens, MAX_TOKENS);
+ for (i=0; i<cnt; i++) {
+ D("tokenize: %dth: %s\n", i, tokens[i]);
+
+ if (!strcmp("export", tokens[i])) {
+ flag = 0;
+ i++;
+ if (i>=cnt) break;
+ if (env_verify(tokens[i])) {
+ flag = 1;
+ }
+ i++;
+ if (i>=cnt) break;
+ if (!strcmp("&&", tokens[i])) {
+ continue;
+ }
+ }
+ if (flag == 0) {
+ // TODO: check evn setting
+ }
+
+ if(!strcmp(tokens[i], SDK_LAUNCH_PATH)) {
+ int pid = 0;
+ char* pkg_id = NULL;
+ char* executable = NULL;
+ ++i;
+ while( i < cnt ) {
+ if(!strcmp(tokens[i], "-attach")) {
+ if(++i < cnt) {
+ char* pid_pattern = "[1-9][0-9]{2,5}";
+ if (regcmp(pid_pattern, tokens[i])) {
+ pid = atoi(tokens[i]);
+ }
+ }
+ }
+ else if(!strcmp(tokens[i], "-p")) {
+ if(++i < cnt) {
+ pkg_id = tokens[i];
+ }
+ }
+ else if(!strcmp(tokens[i], "-e")) {
+ if(++i < cnt) {
+ executable = tokens[i];
+ }
+ }
+ i++;
+ }
+ if(pid > 0) {
+ char cmdline[128];
+ if (pid) {
+ snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
+ int fd = unix_open(cmdline, O_RDONLY);
+ if (fd >= 0) {
+ if(read_line(fd, cmdline, sizeof(cmdline))) {
+ if (set_smack_rules_for_gdbserver(cmdline, 1)) {
+ ret = 1;
+ }
+ }
+ sdb_close(fd);
+ }
+ }
+ }
+ break;
+ }
+ // TODO: i length check
+ else if (!strcmp(tokens[i], GDBSERVER_PATH) || !strcmp(tokens[i], GDBSERVER_PLATFORM_PATH)) { //gdbserver :11 --attach 2332 (cnt=4,)
+ char *gdb_attach_arg_pattern = "^:[1-9][0-9]{2,5} \\-\\-attach [1-9][0-9]{2,5}$";
+ int argcnt = cnt-i-1;
+ if (argcnt == 3 && !strcmp("--attach", tokens[i+2])) {
+ char cmdline[128];
+ int pid = 0;
+ D("parsing.... debug attach mode\n");
+ snprintf(cmdline, sizeof(cmdline), "%s %s %s",tokens[i+1], tokens[i+2], tokens[i+3]);
+ if (regcmp(gdb_attach_arg_pattern, cmdline)) {
+ char cmdline[128];
+ pid = atoi(tokens[i+3]);
+ if (pid) {
+ snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
+ int fd = unix_open(cmdline, O_RDONLY);
+ if (fd >= 0) {
+ if(read_line(fd, cmdline, sizeof(cmdline))) {
+ if (set_smack_rules_for_gdbserver(cmdline, 1)) {
+ ret = 1;
+ }
+ }
+ sdb_close(fd);
+ }
+ }
+ }
+ }
+ else if (argcnt >= 2) {
+ if(should_drop_privileges() == 0 || verify_app_path(tokens[i+2])) {
+ D("parsing.... debug run as mode\n");
+ if (set_smack_rules_for_gdbserver(tokens[i+2], 0)) {
+ ret = 1;
+ }
+ }
+ }
+ D("finished debug launch mode\n");
+ } else {
+ if (verify_app_path(tokens[i])) {
+ char *path = tokens[i];
+ char *appid = NULL;
+ int rc = smack_lgetlabel(path, &appid, SMACK_LABEL_ACCESS);
+ if (rc == 0 && appid != NULL) {
+ if (apply_sdb_rules(SDBD_LABEL_NAME, appid, "rwax") < 0) {
+ D("unable to set sdbd rules to %s %s rwax\n", SDBD_LABEL_NAME, appid);
+ } else {
+ D("set sdbd rules to %s %s rwax\n", SDBD_LABEL_NAME, appid);
+ }
+ if (apply_sdb_rules(appid, SDBD_LABEL_NAME, "rwax") < 0) {
+ D("unable to set sdbd rules to %s %s rwax\n", appid, SDBD_LABEL_NAME);
+ } else {
+ D("set sdbd rules to %s %s rwax\n", appid, SDBD_LABEL_NAME);
+ }
+ if (smack_set_label_for_self(appid) != -1) {
+ D("set smack lebel [%s] appid to %s\n", appid, SMACK_LEBEL_SUBJECT_PATH);
+ apply_app_process();
+ ret = 1;
+ } else {
+ D("unable to open %s due to (errno:%d)\n", SMACK_LEBEL_SUBJECT_PATH, errno);
+ }
+ free(appid);
+ }
+ D("standalone launch\n");
+ }
+ }
+ // TODO: verify arguments
+ break;
+ }
+
+ if (cnt) {
+ free_strings(tokens, cnt);
+ }
+ return ret;
+}
+
+/**
+ * free after use it
+ */
+char* clone_gdbserver_label_from_app(const char* app_path) {
+ char *new_appid = NULL;
+ char appid[APPID_MAX_LENGTH+1];
+ char *buffer = NULL;
+
+#if 0
+ if (!verify_app_path(app_path)) {
+ D("not be able to access %s\n", app_path);
+ return NULL;
+ }
+#endif
+
+ int rc = smack_lgetlabel(app_path, &buffer, SMACK_LABEL_ACCESS);
+
+ if (rc == 0 && buffer != NULL) {
+ s_strncpy(appid, buffer, sizeof appid);
+ free(buffer);
+ } else {
+ appid[0] = '_';
+ appid[1] = '\0';
+ }
+ new_appid = (char *)malloc(sizeof(appid)+1);
+ if (new_appid == NULL) {
+ D("could not allocate buffer for new appid'\n");
+ return NULL;
+ }
+ strncpy(new_appid, appid, APPID_MAX_LENGTH);
+ // Do not label to gdbserver executable
+/*
+ if (new_appid != NULL) {
+ rc = smack_lsetlabel(GDBSERVER_PATH, new_appid, SMACK_LABEL_ACCESS);
+ if (rc < 0) {
+ D("unable to set access smack label: %s to %s\n", GDBSERVER_PATH, new_appid);
+ }
+ D("set access smack label: %s to %s\n", GDBSERVER_PATH, new_appid);
+
+ rc = smack_lsetlabel(GDBSERVER_PATH, new_appid, SMACK_LABEL_EXEC);
+ if (rc < 0) {
+ D("unable to set execute smack label: %s to %s\n", GDBSERVER_PATH, new_appid);
+ }
+ D("set execute smack label: %s to %s\n", GDBSERVER_PATH, new_appid);
+ }
+*/
+ return new_appid;
+}
+
+int set_smack_rules_for_gdbserver(const char* apppath, int mode) {
+ // FIXME: set gdbfolder to 755 also
+ if(sdb_chmod(GDBSERVER_PATH, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 1) < 0)
+ {
+ D("unable to set 755 to %s", GDBSERVER_PATH);
+ }
+
+ // in case of debug as mode
+ char *new_appid = clone_gdbserver_label_from_app(apppath);
+ if (new_appid != NULL) {
+ if (apply_sdb_rules(SDBD_LABEL_NAME, new_appid, "w") < 0) {
+ D("unable to set sdbd rules\n");
+ }
+ if (apply_sdb_rules(new_appid, SDK_HOME_LABEL_NAME, "rx") < 0) {
+ D("unable to set sdbd home rules\n");
+ }
+ if (smack_set_label_for_self(new_appid) != -1) {
+ D("set smack lebel [%s] appid to %s\n", new_appid, SMACK_LEBEL_SUBJECT_PATH);
+ // apply app precess only if not attach mode
+ if (mode == 0) {
+ apply_app_process();
+ }
+ } else {
+ D("unable to open %s due to (errno:%d)\n", SMACK_LEBEL_SUBJECT_PATH, errno);
+ }
+ free(new_appid);
+ return 1;
+ }
+ // TODO: in case of attach mode
+ return 0;
+}
+
+int apply_sdb_rules(const char* subject, const char* object, const char* access_type) {
+ struct smack_accesses *rules = NULL;
+ int ret = 0;
+
+ if (smack_accesses_new(&rules))
+ return -1;
+
+ if (smack_accesses_add(rules, subject, object, access_type)) {
+ smack_accesses_free(rules);
+ return -1;
+ }
+
+ ret = smack_accesses_apply(rules);
+ smack_accesses_free(rules);
+
+ return ret;
+}
+
+void apply_app_process() {
+ set_appuser_groups();
+
+ if (setgid(SID_APP) != 0) {
+ //fprintf(stderr, "set group id failed errno: %d\n", errno);
+ exit(1);
+ }
+
+ if (setuid(SID_APP) != 0) {
+ //fprintf(stderr, "set user id failed errno: %d\n", errno);
+ exit(1);
+ }
+}
+
+void set_appuser_groups(void) {
+
+ int fd = 0;
+ char buffer[5];
+ gid_t t_gid = -1;
+ gid_t groups[APP_GROUPS_MAX]={0,};
+ int cnt = 0;
+
+ //groups[cnt++] = SID_DEVELOPER;
+ fd = sdb_open(APP_GROUP_LIST, O_RDONLY);
+ if (fd < 0) {
+ D("cannot get app's group lists from %s", APP_GROUP_LIST);
+ return;
+ }
+ for (;;) {
+ if (read_line(fd, buffer, sizeof buffer) < 0) {
+ break;
+ }
+ t_gid = strtoul(buffer, 0, 10);
+ errno = 0;
+ if(errno != 0)
+ {
+ D("cannot change string to integer: [%s]\n", buffer);
+ continue;
+ }
+ if (t_gid) {
+ if (cnt < APP_GROUPS_MAX) {
+ groups[cnt++] = t_gid;
+ } else {
+ D("cannot add groups more than %d", APP_GROUPS_MAX);
+ break;
+ }
+ }
+ }
+ if (cnt > 0) {
+ if (setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0) {
+ sdb_close(fd);
+ fprintf(stderr, "set groups failed errno: %d\n", errno);
+ exit(1);
+ }
+ }
+ sdb_close(fd);
+}
+
+int is_root_commands(const char *command) {
+ int i = -1;
+ for(i = 0; root_commands[i].path != NULL; i++) {
+ if(!strncmp(root_commands[i].path, command, PATH_MAX)) {
+ return i;
+ }
+ }
+ // not found
+ return -1;
+}
--- /dev/null
+#ifndef _SDKTOOLS_H
+#define _SDKTOOLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sudo_command
+{
+ const char *command;
+ const char *path;
+ //const char *arguments;
+ //const char *regx;
+ //int permission; /* 0: root, 1: developer, 2: app*/
+};
+
+
+struct arg_permit_rule
+{
+ const char *name;
+ const char *pattern;
+ int expression; // 0:compare, 1: regx
+};
+
+#define SDK_LAUNCH_PATH "/usr/sbin/sdk_launch"
+#define APP_INSTALL_PATH_PREFIX1 "/opt/apps"
+#define APP_INSTALL_PATH_PREFIX2 "/opt/usr/apps"
+#define GDBSERVER_PATH "/home/developer/sdk_tools/gdbserver/gdbserver"
+#define GDBSERVER_PLATFORM_PATH "/home/developer/sdk_tools/gdbserver-platform/gdbserver"
+#define SMACK_LEBEL_SUBJECT_PATH "/proc/self/attr/current"
+#define SMACK_SYNC_FILE_LABEL "*"
+#define APP_GROUPS_MAX 100
+#define APP_GROUP_LIST "/usr/share/privilege-control/app_group_list"
+#define APPID_MAX_LENGTH 50
+#define SDBD_LABEL_NAME "sdbd"
+#define SDK_HOME_LABEL_NAME "sdbd::home"
+
+int verify_root_commands(const char *arg1);
+int verify_app_path(const char* path);
+int regcmp(const char* pattern, const char* str);
+int exec_app_standalone(const char* path);
+char* clone_gdbserver_label_from_app(const char* app_path);
+int set_smack_rules_for_gdbserver(const char* apppath, int mode);
+void apply_app_process();
+void set_appuser_groups(void);
+int is_root_commands(const char *command);
+int apply_sdb_rules(const char* subject, const char* object, const char* access_type);
+int is_pkg_file_path(const char* path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <grp.h>
#include "sysdeps.h"
-#define TRACE_TAG TRACE_SDB
+#define TRACE_TAG TRACE_SERVICES
#include "sdb.h"
#include "file_sync_service.h"
# ifndef HAVE_WINSOCK
# include <netinet/in.h>
# include <netdb.h>
+# include <sys/ioctl.h>
# endif
#else
-//# include <sys/reboot.h> eric
+# include <sys/inotify.h>
+# include "sdktools.h"
#endif
-#define PROCESS_WORKING_DIRECTORY "/"
+#include "strutils.h"
+#include <system_info_internal.h>
+#include <vconf.h>
+#include <limits.h>
typedef struct stinfo stinfo;
sdb_close(fd);
}
#else
+
+#if 0
extern int recovery_mode;
static void recover_service(int s, void *cookie)
fd = sdb_creat("/tmp/update.begin", 0644);
sdb_close(fd);
}
-#if 0 //eric
+
void restart_root_service(int fd, void *cookie)
{
char buf[100];
snprintf(buf, sizeof(buf), "restarting sdbd as root\n");
writex(fd, buf, strlen(buf));
sdb_close(fd);
-
- // quit, and init will restart us as root
- sleep(1);
- exit(1);
}
}
+#endif
-void restart_tcp_service(int fd, void *cookie)
+void rootshell_service(int fd, void *cookie)
{
char buf[100];
- char value[PROPERTY_VALUE_MAX];
- int port = (int)cookie;
+ char *mode = (char*) cookie;
- if (port <= 0) {
- snprintf(buf, sizeof(buf), "invalid port\n");
+ if (!strcmp(mode, "on")) {
+ if (rootshell_mode == 1) {
+ //snprintf(buf, sizeof(buf), "Already changed to developer mode\n");
+ // do not show message
+ } else {
+ if (access("/bin/su", F_OK) == 0) {
+ rootshell_mode = 1;
+ //allows a permitted user to execute a command as the superuser
+ snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n");
+ } else {
+ snprintf(buf, sizeof(buf), "Permission denied\n");
+ }
+ writex(fd, buf, strlen(buf));
+ }
+ } else if (!strcmp(mode, "off")) {
+ if (rootshell_mode == 1) {
+ rootshell_mode = 0;
+ snprintf(buf, sizeof(buf), "Switched to 'developer' account mode\n");
+ writex(fd, buf, strlen(buf));
+ }
+ } else {
+ snprintf(buf, sizeof(buf), "Unknown command option\n");
writex(fd, buf, strlen(buf));
- sdb_close(fd);
- return;
}
-
- snprintf(value, sizeof(value), "%d", port);
- property_set("service.sdb.tcp.port", value);
- snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
- writex(fd, buf, strlen(buf));
- sdb_close(fd);
-
- // quit, and init will restart us in TCP mode
- sleep(1);
- exit(1);
-}
-
-void restart_usb_service(int fd, void *cookie)
-{
- char buf[100];
-
- property_set("service.sdb.tcp.port", "0");
- snprintf(buf, sizeof(buf), "restarting in USB mode\n");
- writex(fd, buf, strlen(buf));
+ D("set rootshell to %s\n", rootshell_mode == 1 ? "root" : "developer");
+ free(mode);
sdb_close(fd);
-
- // quit, and init will restart us in USB mode
- sleep(1);
- exit(1);
}
-#endif
void reboot_service(int fd, void *arg)
{
+#if 0
char buf[100];
int pid, ret;
pid = fork();
if (pid == 0) {
/* ask vdc to unmount it */
+ // prevent: Use of untrusted string value (TAINTED_STRING)
execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
getenv("EXTERNAL_STORAGE"), "force", NULL);
} else if (pid > 0) {
waitpid(pid, &ret, 0);
}
-// ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
-// LINUX_REBOOT_CMD_RESTART2, (char *)arg);
+ ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
if (ret < 0) {
snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
writex(fd, buf, strlen(buf));
}
free(arg);
sdb_close(fd);
+#endif
}
+#if !SDB_HOST
+#define EVENT_SIZE ( sizeof (struct inotify_event) )
+#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
+#define CS_PATH "/opt/usr/share/crash/report"
+
+void inoti_service(int fd, void *arg)
+{
+ int wd;
+ int ifd;
+ char buffer[BUF_LEN];
+
+ D( "inoti_service start\n");
+ ifd = inotify_init();
+
+ if ( ifd < 0 ) {
+ D( "inotify_init failed\n");
+ return;
+ }
+
+ wd = inotify_add_watch( ifd, CS_PATH, IN_CREATE);
+
+ for ( ; ; ) {
+ int length, i = 0;
+ length = sdb_read( ifd, buffer, BUF_LEN );
+
+ if ( length < 0 ) {
+ D( "inoti read failed\n");
+ goto done;
+ }
+ while (i >= 0 && i <= (length - EVENT_SIZE)) {
+ struct inotify_event *event = (struct inotify_event *) &buffer[i];
+ if (event->len) {
+ if (event->mask & IN_CREATE) {
+ if (!(event->mask & IN_ISDIR)) {
+ char *cspath = NULL;
+ int len = asprintf(&cspath, "%s/%s", CS_PATH,
+ event->name);
+ D( "The file %s was created.\n", cspath);
+ writex(fd, cspath, len);
+ if (cspath != NULL) {
+ free(cspath);
+ }
+ }
+ }
+ }
+ if (i + EVENT_SIZE + event->len < event->len) { // in case of integer overflow
+ break;
+ }
+ i += EVENT_SIZE + event->len;
+ }
+ }
+
+done:
+ inotify_rm_watch( ifd, wd );
+ sdb_close(ifd);
+ sdb_close(fd);
+ D( "inoti_service end\n");
+}
+#endif
#endif
+void rndis_config_service(int fd, void *cookie)
+{
+ char buf[100];
+ int val = 0;
+ char* mode = (char*) cookie;
+
+ usb_mode = 0;
+ if (vconf_get_int(DEBUG_MODE_KEY, &val)) {
+ D("Failed to get debug mode\n");
+ sdb_close(fd);
+ free(mode);
+ return;
+ }
+ if (!strcmp(mode, "on")) {
+ if (val != 6) {
+ usb_mode = 6;
+ sdb_sleep_ms(500);
+ if (vconf_set_int(DEBUG_MODE_KEY, 6)) {
+ D("Failed to set rndis %s\n", mode);
+ snprintf(buf, sizeof(buf), "Failed to set rndis %s\n", mode);
+ writex(fd, buf, strlen(buf));
+ }
+ }
+ } else if (!strcmp(mode, "off")) {
+ if (val != 2) {
+ usb_mode = 2;
+ sdb_sleep_ms(500);
+ if (vconf_set_int(DEBUG_MODE_KEY, 2)) {
+ D("Failed to set rndis %s\n", mode);
+ snprintf(buf, sizeof(buf), "Failed to set rndis %s\n", mode);
+ writex(fd, buf, strlen(buf));
+ }
+ }
+ } else {
+ D("Unknown command option:(rndis %s)\n", mode);
+ snprintf(buf, sizeof(buf), "Unknown command option:(rndis %s)\n", mode);
+ writex(fd, buf, strlen(buf));
+ }
+ free(mode);
+ sdb_close(fd);
+}
+
#if 0
static void echo_service(int fd, void *cookie)
{
int s[2];
if(sdb_socketpair(s)) {
- printf("cannot create service socket pair\n");
+ D("cannot create service socket pair\n");
return -1;
}
free(sti);
sdb_close(s[0]);
sdb_close(s[1]);
- printf("cannot create service thread\n");
+ D("cannot create service thread\n");
return -1;
}
return s[0];
}
-static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
+#if !SDB_HOST
+
+static void redirect_and_exec(int pts, const char *cmd, const char *argv[], const char *envp[])
+{
+ dup2(pts, 0);
+ dup2(pts, 1);
+ dup2(pts, 2);
+
+ sdb_close(pts);
+
+ execve(cmd, argv, envp);
+}
+
+static int create_subprocess(const char *cmd, pid_t *pid, const char *argv[], const char *envp[])
{
-#ifdef HAVE_WIN32_PROC
- fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
- return -1;
-#else /* !HAVE_WIN32_PROC */
char *devname;
int ptm;
- pid_t pid;
ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
if(ptm < 0){
- printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
+ D("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
return -1;
}
- fcntl(ptm, F_SETFD, FD_CLOEXEC);
+ if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) {
+ D("[ cannot set cloexec to /dev/ptmx - %s ]\n",strerror(errno));
+ }
if(grantpt(ptm) || unlockpt(ptm) ||
((devname = (char*) ptsname(ptm)) == 0)){
- printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
+ D("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
+ sdb_close(ptm);
return -1;
}
- pid = fork();
- if(pid < 0) {
- printf("- fork failed: %s -\n", strerror(errno));
+ *pid = fork();
+ if(*pid < 0) {
+ D("- fork failed: %s -\n", strerror(errno));
+ sdb_close(ptm);
return -1;
}
- if(pid == 0){
+ if(*pid == 0){
int pts;
setsid();
- if (chdir(PROCESS_WORKING_DIRECTORY) < 0)
- D("sdb: unable to change working directory to %s\n", PROCESS_WORKING_DIRECTORY);
pts = unix_open(devname, O_RDWR);
- if(pts < 0) exit(-1);
-
- dup2(pts, 0);
- dup2(pts, 1);
- dup2(pts, 2);
+ if(pts < 0) {
+ fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
+ exit(-1);
+ }
sdb_close(ptm);
- execl(cmd, cmd, arg0, arg1, NULL);
- fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
- cmd, strerror(errno), errno);
+ // set OOM adjustment to zero
+ {
+ char text[64];
+ snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
+ int fd = sdb_open(text, O_WRONLY);
+ if (fd >= 0) {
+ sdb_write(fd, "0", 1);
+ sdb_close(fd);
+ } else {
+ // FIXME: not supposed to be here
+ D("sdb: unable to open %s due to %s\n", text, strerror(errno));
+ }
+ }
+
+ if (should_drop_privileges()) {
+ if (argv[2] != NULL && verify_root_commands(argv[2])) {
+ // do nothing
+ D("sdb: executes root commands!!:%s\n", argv[2]);
+ } else {
+ set_developer_privileges();
+ }
+ }
+
+ redirect_and_exec(pts, cmd, argv, envp);
+ fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n",
+ cmd, errno);
exit(-1);
} else {
+ // Don't set child's OOM adjustment to zero.
+ // Let the child do it itself, as sometimes the parent starts
+ // running before the child has a /proc/pid/oom_adj.
+ // """sdb: unable to open /proc/644/oom_adj""" seen in some logs.
+ return ptm;
+ }
+}
+#endif /* !SDB_HOST */
+
+#define SHELL_COMMAND "/bin/sh"
+#define LOGIN_COMMAND "/bin/login"
+#define SDK_USER "developer"
+#define SUPER_USER "root"
+#define LOGIN_CONFIG "/etc/login.defs"
+
#if !SDB_HOST
- // set child's OOM adjustment to zero
- char text[64];
- snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
- int fd = sdb_open(text, O_WRONLY);
- if (fd >= 0) {
- sdb_write(fd, "0", 1);
- sdb_close(fd);
+static void subproc_waiter_service(int fd, void *cookie)
+{
+ pid_t pid = (pid_t)cookie;
+
+ D("entered. fd=%d of pid=%d\n", fd, pid);
+ for (;;) {
+ int status;
+ pid_t p = waitpid(pid, &status, 0);
+ if (p == pid) {
+ D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
+
+ if (WIFEXITED(status)) {
+ D("*** Exit code %d\n", WEXITSTATUS(status));
+ break;
+ } else if (WIFSIGNALED(status)) {
+ D("*** Killed by signal %d\n", WTERMSIG(status));
+ break;
+ } else {
+ D("*** Killed by unknown code %d\n", status);
+ break;
+ }
+ }
+ }
+ D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
+ if (SHELL_EXIT_NOTIFY_FD >=0) {
+ int res;
+ res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
+ D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
+ SHELL_EXIT_NOTIFY_FD, pid, res, errno);
+ }
+}
+
+static void get_env(char *key, char **env)
+{
+ FILE *fp;
+ char buf[1024];
+ int i;
+ char *s, *e, *value;
+
+ fp = fopen (LOGIN_CONFIG, "r");
+ if (NULL == fp) {
+ return;
+ }
+
+ while (fgets(buf, (int) sizeof (buf), fp) != NULL) {
+ s = buf;
+ e = buf + (strlen(buf) - 1);
+
+ while(*e == ' ' || *e == '\n' || *e == '\t') {
+ e--;
+ }
+ *(e+1) ='\0';
+
+ while(*s != '\0' && (*s == ' ' || *s == '\t' || *s == '\n')) {
+ s++;
+ }
+
+ if (*s == '#' || *s == '\0') {
+ continue;
+ }
+ value = s + strcspn(s, " \t");
+ *value++ = '\0';
+
+ if(!strcmp(buf, key)) {
+ *env = value;
+ break;
+ }
+ }
+
+ fclose(fp);
+}
+
+static int create_subproc_thread(const char *name, int lines, int columns)
+{
+ stinfo *sti;
+ sdb_thread_t t;
+ int ret_fd;
+ pid_t pid;
+ char *value = NULL;
+ char lines_str[20] = {'\0',};
+ char columns_str[20] = {'\0',};
+
+ 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
+ };
+ if (should_drop_privileges()) {
+ envp[2] = "HOME=/home/developer";
+ get_env("ENV_PATH", &value);
+ } else {
+ get_env("ENV_SUPATH", &value);
+ envp[2] = "HOME=/root";
+ }
+ if (value != NULL) {
+ envp[3] = value;
+ }
+
+ D("path env:%s,%s,%s,%s\n", envp[0], envp[1], envp[2], envp[3]);
+
+ if (lines > 0 && columns > 0) {
+ snprintf(lines_str, sizeof(lines_str), "LINES=%d", lines);
+ snprintf(columns_str, sizeof(columns_str), "COLUMNS=%d", columns);
+ envp[4] = lines_str;
+ envp[5] = columns_str;
+ D("shell size env:%s,%s\n", envp[4], envp[5]);
+ }
+
+ if(name) { // in case of shell execution directly
+ char *args[] = {
+ SHELL_COMMAND,
+ "-c",
+ NULL,
+ "-l",
+ SUPER_USER,
+ NULL,
+ };
+ args[2] = name;
+
+ ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
+ } else { // in case of shell interactively
+ char *args[] = {
+ SHELL_COMMAND,
+ "-",
+ NULL,
+ };
+ ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
+#if 0 // FIXME: should call login command instead of /bin/sh
+ if (should_drop_privileges()) {
+ char *args[] = {
+ SHELL_COMMAND,
+ "-",
+ NULL,
+ };
+ ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp);
} else {
- D("sdb: unable to open %s\n", text);
+ char *args[] = {
+ LOGIN_COMMAND,
+ "-f",
+ SUPER_USER,
+ NULL,
+ };
+ ret_fd = create_subprocess(LOGIN_COMMAND, &pid, args, envp);
}
#endif
- return ptm;
}
-#endif /* !HAVE_WIN32_PROC */
+ D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
+
+ if (ret_fd < 0) {
+ D("cannot create service thread\n");
+ return -1;
+ }
+ sti = malloc(sizeof(stinfo));
+ if(sti == 0) fatal("cannot allocate stinfo");
+ sti->func = subproc_waiter_service;
+ sti->cookie = (void*)pid;
+ sti->fd = ret_fd;
+
+ if(sdb_thread_create( &t, service_bootstrap_func, sti)){
+ free(sti);
+ sdb_close(ret_fd);
+ D("cannot create service thread\n");
+ return -1;
+ }
+
+ D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
+ return ret_fd;
}
-//#if SDB_HOST
-#define SHELL_COMMAND "/bin/sh"
-//#else
-//#define SHELL_COMMAND "/system/bin/sh"
-//#endif
+static int create_sync_subprocess(void (*func)(int, void *), void* cookie) {
+ stinfo *sti;
+ sdb_thread_t t;
+ int s[2];
+
+ if(sdb_socketpair(s)) {
+ D("cannot create service socket pair\n");
+ return -1;
+ }
+
+ pid_t pid = fork();
+
+ if (pid == 0) {
+ sdb_close(s[0]);
+ func(s[1], cookie);
+ exit(-1);
+ } else if (pid > 0) {
+ sdb_close(s[1]);
+ // FIXME: do not wait child process hear
+ //waitpid(pid, &ret, 0);
+ }
+ if (pid < 0) {
+ D("- fork failed: (errno:%d) -\n", errno);
+ sdb_close(s[0]);
+ sdb_close(s[1]);
+ D("cannot create sync service sub process\n");
+ return -1;
+ }
+
+ sti = malloc(sizeof(stinfo));
+ if(sti == 0) fatal("cannot allocate stinfo");
+ sti->func = subproc_waiter_service;
+ sti->cookie = (void*)pid;
+ sti->fd = s[0];
+
+ 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;
+ }
+
+ D("service process started, fd=%d pid=%d\n",s[0], pid);
+ return s[0];
+}
+
+static int create_syncproc_thread()
+{
+ int ret_fd;
+
+ ret_fd = create_sync_subprocess(file_sync_service, NULL);
+ // FIXME: file missing bug when root on mode
+ /*
+ if (should_drop_privileges()) {
+ ret_fd = create_sync_subprocess(file_sync_service, NULL);
+ } else {
+ ret_fd = create_service_thread(file_sync_service, NULL);
+ }
+ */
+
+ return ret_fd;
+}
+
+#endif
+
+#define UNKNOWN "unknown"
+#define INFOBUF_MAXLEN 64
+#define INFO_VERSION "2.2.0"
+typedef struct platform_info {
+
+ char platform_info_version[INFOBUF_MAXLEN];
+ char model_name[INFOBUF_MAXLEN]; // Emulator
+ char platform_name[INFOBUF_MAXLEN]; // Tizen
+ char platform_version[INFOBUF_MAXLEN]; // 2.2.1
+ char profile_name[INFOBUF_MAXLEN]; // 2.2.1
+} pinfo;
+
+static void get_platforminfo(int fd, void *cookie) {
+ pinfo sysinfo;
+
+ char *value = NULL;
+ s_strncpy(sysinfo.platform_info_version, INFO_VERSION, strlen(INFO_VERSION));
+
+ int r = system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &value);
+ if (r != SYSTEM_INFO_ERROR_NONE) {
+ s_strncpy(sysinfo.model_name, UNKNOWN, strlen(UNKNOWN));
+ D("fail to get system model:%d\n", errno);
+ } else {
+ s_strncpy(sysinfo.model_name, value, sizeof(sysinfo.model_name));
+ D("returns model_name:%s\n", value);
+ if (value != NULL) {
+ free(value);
+ }
+ }
+
+ r = system_info_get_value_string(SYSTEM_INFO_KEY_PLATFORM_NAME, &value);
+ if (r != SYSTEM_INFO_ERROR_NONE) {
+ s_strncpy(sysinfo.platform_name, UNKNOWN, strlen(UNKNOWN));
+ D("fail to get platform name:%d\n", errno);
+ } else {
+ s_strncpy(sysinfo.platform_name, value, sizeof(sysinfo.platform_name));
+ D("returns platform_name:%s\n", value);
+ if (value != NULL) {
+ free(value);
+ }
+
+ }
+
+ // FIXME: the result is different when using SYSTEM_INFO_KEY_TIZEN_VERSION_NAME
+ r = system_info_get_platform_string("tizen.org/feature/platform.version", &value);
+ if (r != SYSTEM_INFO_ERROR_NONE) {
+ s_strncpy(sysinfo.platform_version, UNKNOWN, strlen(UNKNOWN));
+ D("fail to get platform version:%d\n", errno);
+ } else {
+ s_strncpy(sysinfo.platform_version, value, sizeof(sysinfo.platform_version));
+ D("returns platform_version:%s\n", value);
+ if (value != NULL) {
+ free(value);
+ }
+ }
+
+ r = system_info_get_platform_string("tizen.org/feature/profile", &value);
+ if (r != SYSTEM_INFO_ERROR_NONE) {
+ s_strncpy(sysinfo.profile_name, UNKNOWN, strlen(UNKNOWN));
+ D("fail to get profile name:%d\n", errno);
+ } else {
+ s_strncpy(sysinfo.profile_name, value, sizeof(sysinfo.profile_name));
+ D("returns profile name:%s\n", value);
+ if (value != NULL) {
+ free(value);
+ }
+ }
+
+ writex(fd, &sysinfo, sizeof(pinfo));
+
+ sdb_close(fd);
+}
int service_to_fd(const char *name)
{
int port = atoi(name + 4);
name = strchr(name + 4, ':');
if(name == 0) {
- ret = socket_loopback_client(port, SOCK_STREAM);
- if (ret >= 0)
- disable_tcp_nagle(ret);
+ if (is_emulator()){
+ ret = socket_ifr_client(port , SOCK_STREAM, "eth0");
+ } else {
+ ret = socket_ifr_client(port , SOCK_STREAM, "usb0");
+ if (ret < 0) {
+ if (ifconfig(SDB_FORWARD_IFNAME, SDB_FORWARD_INTERNAL_IP, SDB_FORWARD_INTERNAL_MASK, 1) == 0) {
+ ret = socket_ifr_client(port , SOCK_STREAM, SDB_FORWARD_IFNAME);
+ }
+ }
+ }
+ if (ret < 0) {
+ ret = socket_loopback_client(port, SOCK_STREAM);
+ }
+ if (ret >= 0) {
+ if (disable_tcp_nagle(ret) < 0) {
+ D("failed to disable_tcp_nagle\n");
+ }
+ }
} else {
#if SDB_HOST
sdb_mutex_lock(&dns_lock);
if(n == 0) return -1;
ret = create_service_thread(dns_service, n);
#else /* !SDB_HOST */
- } else if(!strncmp("dev:", name, 4)) {
+ }/* else if(!strncmp("dev:", name, 4)) {// tizen specific
ret = unix_open(name + 4, O_RDWR);
} else if(!strncmp(name, "framebuffer:", 12)) {
ret = create_service_thread(framebuffer_service, 0);
ret = create_service_thread(recover_service, (void*) atoi(name + 8));
} else if (!strncmp(name, "jdwp:", 5)) {
ret = create_jdwp_connection_fd(atoi(name+5));
-#if 0 // eric
} else if (!strncmp(name, "log:", 4)) {
ret = create_service_thread(log_service, get_log_file_path(name + 4));
-#endif
-#endif
- } else if(!HOST && !strncmp(name, "shell:", 6)) {
+ }*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
if(name[6]) {
- ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
+ ret = create_subproc_thread(name + 6, 0, 0);
} else {
- ret = create_subprocess(SHELL_COMMAND, "-", 0);
+ ret = create_subproc_thread(NULL, 0, 0);
+ }
+ } else if(!strncmp(name, "eshell:", 7)) {
+ int lines, columns;
+ if (sscanf(name+7, "%d:%d", &lines, &columns) == 2) {
+ ret = create_subproc_thread(NULL, lines, columns);
}
-#if !SDB_HOST
} else if(!strncmp(name, "sync:", 5)) {
- ret = create_service_thread(file_sync_service, NULL);
-#if 0 //eric
- } else if(!strncmp(name, "remount:", 8)) {
+ //ret = create_service_thread(file_sync_service, NULL);
+ ret = create_syncproc_thread();
+ }/* else if(!strncmp(name, "remount:", 8)) {
ret = create_service_thread(remount_service, NULL);
-#endif
} else if(!strncmp(name, "reboot:", 7)) {
void* arg = strdup(name + 7);
if(arg == 0) return -1;
ret = create_service_thread(reboot_service, arg);
-#if 0 //eric
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread(restart_root_service, NULL);
- } else if(!strncmp(name, "tcpip:", 6)) {
- int port;
- if (sscanf(name + 6, "%d", &port) == 0) {
- port = 0;
- }
- ret = create_service_thread(restart_tcp_service, (void *)port);
- } else if(!strncmp(name, "usb:", 4)) {
- ret = create_service_thread(restart_usb_service, NULL);
-#endif
-#endif
-#if 0
- } else if(!strncmp(name, "echo:", 5)){
- ret = create_service_thread(echo_service, 0);
+ } else if(!strncmp(name, "backup:", 7)) {
+ char* arg = strdup(name+7);
+ if (arg == NULL) return -1;
+ ret = backup_service(BACKUP, arg);
+ } else if(!strncmp(name, "restore:", 8)) {
+ ret = backup_service(RESTORE, NULL);
+ }*/ else if(!strncmp(name, "root:", 5)) {
+ char* service_name = NULL;
+
+ service_name = strdup(name+5);
+ ret = create_service_thread(rootshell_service, (void *)(service_name));
+ } else if(!strncmp(name, "cs:", 5)) {
+ ret = create_service_thread(inoti_service, NULL);
#endif
+ } else if(!strncmp(name, "sysinfo:", 8)){
+ ret = create_service_thread(get_platforminfo, 0);
+ } else if(!strncmp(name, "rndis:", 6)){
+ char *service_name = NULL;
+
+ service_name = strdup(name+6);
+ ret = create_service_thread(rndis_config_service, (void *)(service_name));
}
if (ret >= 0) {
- close_on_exec(ret);
+ if (close_on_exec(ret) < 0) {
+ D("failed to close fd exec\n");
+ }
}
return ret;
}
-/* libs/cutils/socket_inaddr_any_server.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
+// libs/cutils/socket_inaddr_any_server.c
#include "sockets.h"
if(s < 0) return -1;
n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) {
+ close(s);
+ return -1;
+ }
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <sys/types.h>
#include "socket_local.h"
-
+#include "strutils.h"
#define LISTEN_BACKLOG 4
/* Documented in header file. */
goto error;
}
- strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
- strcat(p_addr->sun_path, name);
+ s_strncpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX, strlen(FILESYSTEM_SOCKET_PREFIX));
+ strncat(p_addr->sun_path, name, strlen(name));
#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
break;
goto error;
}
- strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
- strcat(p_addr->sun_path, name);
+ s_strncpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX, strlen(ANDROID_RESERVED_SOCKET_PREFIX));
+ strncat(p_addr->sun_path, name, strlen(name));
break;
case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
goto error;
}
- strcpy(p_addr->sun_path, name);
+ s_strncpy(p_addr->sun_path, name, strlen(name));
break;
default:
// invalid namespace id
-/* libs/cutils/socket_local_server.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
+// libs/cutils/socket_local_server.c
#include "sockets.h"
}
n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0 ) {
+ return -1;
+ }
if(bind(s, (struct sockaddr *) &addr, alen) < 0) {
return -1;
-/* libs/cutils/socket_loopback_client.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
+// libs/cutils/socket_loopback_client.c
#include "sockets.h"
-
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/types.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
#endif
+#include "strutils.h"
/* Connect to port on the loopback IP interface. type is
* SOCK_STREAM or SOCK_DGRAM.
* return is a file descriptor or -1 on error
}
return s;
+}
+
+int socket_ifr_client(int port, int type, char *ifr_dev)
+{
+ int s;
+ struct ifreq ifr;
+ struct sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if(s < 0) {
+ return -1;
+ }
+ ifr.ifr_addr.sa_family = AF_INET;
+ s_strncpy(ifr.ifr_name, ifr_dev, IFNAMSIZ-1);
+
+ if (ioctl(s, SIOCGIFADDR, &ifr) < 0 ) {
+ close(s);
+ return -1;
+ }
+
+ addr.sin_addr.s_addr = inet_addr(inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
+
+ close(s);
+
+ s = socket(AF_INET, type, 0);
+ if(s < 0) {
+ return -1;
+ }
+ if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(s);
+ return -1;
+ }
+
+ return s;
}
+/* Simple implementation of ifconfig.
+ * activate: '0' causes the ifname driver to be shut down.
+ */
+int ifconfig(char *ifname, char *address, char *netmask, int activated) {
+ struct ifreq ifr;
+ struct sockaddr_in *sin;
+ int sockfd;
+
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ fprintf(stderr, "cannot open socket\n");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+ s_strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
+
+ sin = (struct sockaddr_in *) &ifr.ifr_addr;
+ sin->sin_family = AF_INET;
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = inet_addr(address);
+
+ if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
+ fprintf(stderr,"cannot set SIOCSIFADDR flags: %s(errno:%d)\n", address, errno);
+ close(sockfd);
+ return -1;
+ }
+
+ sin->sin_addr.s_addr = inet_addr(netmask);
+ if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
+ fprintf(stderr,"cannot set SIOCSIFNETMASK flags: %s(errno:%d)\n", netmask, errno);
+ close(sockfd);
+ return -1;
+ }
+
+ if (activated) {
+ ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+ } else {
+ ifr.ifr_flags |= ~IFF_UP;
+ }
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
+ fprintf(stderr,"cannot set SIOCGIFFLAGS flags: (errno:%d)\n", errno);
+ close(sockfd);
+ return -1;
+ }
+
+ close(sockfd);
+ return 0;
+}
-/* libs/cutils/socket_loopback_server.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
+// libs/cutils/socket_loopback_server.c
#include "sockets.h"
int get_loopback_status(void) {
- int s;
- struct ifconf ifc;
- struct ifreq *ifr;
- int ifcnt;
- char buf[1024];
- int i;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if(s < 0)
- {
- perror("socket");
- return LOOPBACK_DOWN;
- }
-
- // query available interfaces
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
- if(ioctl(s, SIOCGIFCONF, &ifc) < 0)
- {
- perror("ioctl(SIOCGIFCONF)");
- return LOOPBACK_DOWN;
- }
-
- // iterate the list of interfaces
- ifr = ifc.ifc_req;
- ifcnt = ifc.ifc_len / sizeof(struct ifreq);
- for(i = 0; i < ifcnt; i++)
- {
- struct sockaddr_in *addr;
- addr = (struct sockaddr_in *)&ifr->ifr_addr;
-
- if (ntohl(addr->sin_addr.s_addr) == INADDR_LOOPBACK)
- {
- return LOOPBACK_UP;
- }
- }
- return LOOPBACK_DOWN;
+ int s;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int ifcnt;
+ char buf[1024];
+ int i;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if(s < 0)
+ {
+ perror("socket");
+ return LOOPBACK_DOWN;
+ }
+
+ // query available interfaces
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if(ioctl(s, SIOCGIFCONF, &ifc) < 0)
+ {
+ perror("ioctl(SIOCGIFCONF)");
+ sdb_close(s);
+ return LOOPBACK_DOWN;
+ }
+
+ // iterate the list of interfaces
+ ifr = ifc.ifc_req;
+ ifcnt = ifc.ifc_len / sizeof(struct ifreq);
+ for(i = 0; i < ifcnt; i++)
+ {
+ struct sockaddr_in *addr;
+ addr = (struct sockaddr_in *)&ifr->ifr_addr;
+
+ if (ntohl(addr->sin_addr.s_addr) == INADDR_LOOPBACK)
+ {
+ sdb_close(s);
+ return LOOPBACK_UP;
+ }
+ }
+ sdb_close(s);
+ return LOOPBACK_DOWN;
}
/* open listen() port on loopback interface */
int s, n;
int cnt_max = 30;
+ /* tizen specific */
+#if !SDB_HOST
// check the loopback interface has been up in 30 sec
while(cnt_max > 0) {
if(get_loopback_status() == LOOPBACK_DOWN) {
break;
}
}
-
+#endif
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
- if(cnt_max ==0)
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
+ if(cnt_max ==0) {
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
s = socket(AF_INET, type, 0);
- if(s < 0) return -1;
+ if(s < 0) {
+ return -1;
+ }
n = 1;
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
-
-
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) {
+ sdb_close(s);
+ return -1;
+ }
if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
sdb_close(s);
-/* libs/cutils/socket_network_client.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
+/*
+ * 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.
+ */
+// libs/cutils/socket_network_client.c
#include "sockets.h"
-
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
*/
int socket_network_client(const char *host, int port, int type)
{
- struct hostent *hp;
+ struct hostent hostbuf, *hp;
struct sockaddr_in addr;
int s;
+ size_t hstbuflen = 1024;
+ int res, herr;
+ char *tmphstbuf;
+
+ tmphstbuf = malloc(hstbuflen);
+ if (tmphstbuf == NULL) {
+ fprintf(stderr, "out of memory\n");
+ exit(-1);
+ }
- hp = gethostbyname(host);
- if(hp == 0) return -1;
-
+ while ((res = gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) {
+ // enlarge the buffer
+ hstbuflen *= 2;
+ tmphstbuf = realloc(tmphstbuf, hstbuflen);
+ if (tmphstbuf == NULL) {
+ fprintf(stderr, "out of memory\n");
+ exit(-1);
+ }
+ }
+ if (res || hp == NULL) {
+ if (tmphstbuf != NULL) {
+ free(tmphstbuf);
+ }
+ 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 < 0) return -1;
+ if(s < 0) {
+ if (tmphstbuf != NULL) {
+ free(tmphstbuf);
+ }
+ return -1;
+ }
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(s);
+
+ if (tmphstbuf != NULL) {
+ free(tmphstbuf);
+ }
return -1;
}
-
+ if (tmphstbuf != NULL) {
+ free(tmphstbuf);
+ }
return s;
}
-
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
#define TRACE_TAG TRACE_SOCKETS
#include "sdb.h"
+#include "strutils.h"
SDB_MUTEX_DEFINE( socket_list_lock );
asocket *result = NULL;
sdb_mutex_lock(&socket_list_lock);
- for(s = local_socket_list.next; s != &local_socket_list && !result; s = s->next) {
- if(s->id == id) result = s;
+ for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+ if (s->id == id) {
+ result = s;
+ break;
+ }
}
sdb_mutex_unlock(&socket_list_lock);
continue;
}
if((r == 0) || (errno != EAGAIN)) {
- D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
+ D( "LS(%d): not ready, errno=%d\n", s->id, errno);
s->close(s);
return 1; /* not ready (error) */
} else {
static void local_socket_destroy(asocket *s)
{
apacket *p, *n;
+ int exit_on_close = s->exit_on_close;
+
+ D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
/* IMPORTANT: the remove closes the fd
** that belongs to this socket
}
remove_socket(s);
free(s);
+
+ if (exit_on_close) {
+ D("local_socket_destroy: exiting\n");
+ exit(1);
+ }
}
static void local_socket_close_locked(asocket *s)
{
+ D("entered. LS(%d) fd=%d\n", s->id, s->fd);
if(s->peer) {
+ D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
+ s->id, s->peer->id, s->peer->fd);
s->peer->peer = 0;
// tweak to avoid deadlock
- if (s->peer->close == local_socket_close)
+ if (s->peer->close == local_socket_close) {
local_socket_close_locked(s->peer);
- else
+ } else {
s->peer->close(s->peer);
+ }
+ s->peer = 0;
}
/* If we are already closing, or if there are no
s->closing = 1;
fdevent_del(&s->fde, FDE_READ);
remove_socket(s);
+ D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
insert_local_socket(s, &local_socket_closing_list);
}
{
asocket *s = _s;
+ D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
+
/* put the FDE_WRITE processing before the FDE_READ
** in order to simplify the code.
*/
if(errno == EAGAIN) return;
if(errno == EINTR) continue;
}
+ D(" closing after write because r=%d and errno is %d\n", r, errno);
s->close(s);
return;
}
** we can now destroy it.
*/
if (s->closing) {
+ D(" closing because 'closing' is set after write\n");
s->close(s);
return;
}
while(avail > 0) {
r = sdb_read(fd, x, avail);
+ D("LS(%d): post sdb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail);
if(r > 0) {
avail -= r;
x += r;
is_eof = 1;
break;
}
-
+ D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
+ s->id, s->fd, r, is_eof, s->fde.force_eof);
if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
put_apacket(p);
} else {
p->len = MAX_PAYLOAD - avail;
r = s->peer->enqueue(s->peer, p);
+ D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
if(r < 0) {
/* error return means they closed us as a side-effect
fdevent_del(&s->fde, FDE_READ);
}
}
-
- if(is_eof) {
+ /* Don't allow a forced eof if data is still there */
+ if((s->fde.force_eof && !r) || is_eof) {
+ D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
s->close(s);
}
}
** bytes of readable data.
*/
// s->close(s);
+ D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
+
return;
}
}
asocket *create_local_socket(int fd)
{
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
- install_local_socket(s);
+ if (s == NULL) fatal("cannot allocate socket");
s->fd = fd;
s->enqueue = local_socket_enqueue;
s->ready = local_socket_ready;
s->close = local_socket_close;
+ install_local_socket(s);
fdevent_install(&s->fde, fd, local_socket_event_func, s);
/* fdevent_add(&s->fde, FDE_ERROR); */
asocket *s;
int fd;
+#if 0 /* not support in tizen */
#if !SDB_HOST
if (!strcmp(name,"jdwp")) {
return create_jdwp_service_socket();
return create_jdwp_tracker_service_socket();
}
#endif
+#endif
fd = service_to_fd(name);
if(fd < 0) return 0;
s = create_local_socket(fd);
- D("LS(%d): bound to '%s'\n", s->id, name);
+ D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
+
+#if !SDB_HOST
+ if ((!strncmp(name, "root:", 5) && getuid() != 0)
+ || !strncmp(name, "usb:", 4)
+ || !strncmp(name, "tcpip:", 6)) {
+ D("LS(%d): enabling exit_on_close\n", s->id);
+ s->exit_on_close = 1;
+ }
+#endif
+
return s;
}
static int remote_socket_enqueue(asocket *s, apacket *p)
{
- D("Calling remote_socket_enqueue\n");
+ D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
+ s->id, s->fd, s->peer->fd);
p->msg.command = A_WRTE;
p->msg.arg0 = s->peer->id;
p->msg.arg1 = s->id;
static void remote_socket_ready(asocket *s)
{
- D("Calling remote_socket_ready\n");
+ D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
+ s->id, s->fd, s->peer->fd);
apacket *p = get_apacket();
p->msg.command = A_OKAY;
p->msg.arg0 = s->peer->id;
static void remote_socket_close(asocket *s)
{
- D("Calling remote_socket_close\n");
+ D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
+ s->id, s->fd, s->peer?s->peer->fd:-1);
apacket *p = get_apacket();
p->msg.command = A_CLSE;
if(s->peer) {
p->msg.arg0 = s->peer->id;
s->peer->peer = 0;
+ D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
+ s->id, s->peer->id, s->peer->fd);
s->peer->close(s->peer);
}
p->msg.arg1 = s->id;
asocket *s = calloc(1, sizeof(aremotesocket));
adisconnect* dis = &((aremotesocket*)s)->disconnect;
- if(s == 0) fatal("cannot allocate socket");
+ if (s == NULL) fatal("cannot allocate socket");
s->id = id;
s->enqueue = remote_socket_enqueue;
s->ready = remote_socket_ready;
void connect_to_remote(asocket *s, const char *destination)
{
- D("Connect_to_remote call \n");
+ D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
apacket *p = get_apacket();
int len = strlen(destination) + 1;
p->msg.command = A_OPEN;
p->msg.arg0 = s->id;
p->msg.data_length = len;
- strcpy((char*) p->data, destination);
+ s_strncpy((char*) p->data, destination, len);
send_packet(p, s->transport);
}
return n;
}
+/* skip_host_serial return the position in a string
+ skipping over the 'serial' parameter in the SDB protocol,
+ where parameter string may be a host:port string containing
+ the protocol delimiter (colon). */
+char *skip_host_serial(char *service) {
+ char *first_colon, *serial_end;
+
+ first_colon = strchr(service, ':');
+ if (!first_colon) {
+ /* No colon in service string. */
+ return NULL;
+ }
+ serial_end = first_colon;
+ if (isdigit(serial_end[1])) {
+ serial_end++;
+ while ((*serial_end) && isdigit(*serial_end)) {
+ serial_end++;
+ }
+ if ((*serial_end) != ':') {
+ // Something other than numbers was found, reset the end.
+ serial_end = first_colon;
+ }
+ }
+ return serial_end;
+}
+
static int smart_socket_enqueue(asocket *s, apacket *p)
{
unsigned len;
char* serial_end;
service += strlen("host-serial:");
- // serial number should follow "host:"
- serial_end = strchr(service, ':');
+ // serial number should follow "host:" and could be a host:port string.
+ serial_end = skip_host_serial(service);
if (serial_end) {
*serial_end = 0; // terminate string
serial = service;
if(s->peer) {
s->peer->peer = 0;
s->peer->close(s->peer);
+ s->peer = 0;
}
free(s);
}
{
D("Creating smart socket \n");
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
- s->id = 0;
+ if (s == NULL) fatal("cannot allocate socket");
s->enqueue = smart_socket_enqueue;
s->ready = smart_socket_ready;
s->close = smart_socket_close;
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
// Normal filesystem namespace
#define ANDROID_SOCKET_NAMESPACE_FILESYSTEM 2
+#define SDB_FORWARD_IFNAME "lo:sdb"
+#define SDB_FORWARD_INTERNAL_IP "192.168.129.3"
+#define SDB_FORWARD_INTERNAL_MASK "255.255.255.0"
+
extern int socket_loopback_client(int port, int type);
extern int socket_network_client(const char *host, int port, int type);
extern int socket_loopback_server(int port, int type);
const char *name, int namespaceId, int type);
extern int socket_local_client(const char *name, int namespaceId, int type);
extern int socket_inaddr_any_server(int port, int type);
-
+int socket_ifr_client(int port, int type, char *ifr_dev);
+int socket_ifr_client(int port, int type, char *ifr_dev);
+int ifconfig(char *ifname, char *address, char *netmask, int activated);
#ifdef __cplusplus
}
#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "sysdeps.h"
+#include "strutils.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+
+size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_tokens ) {
+ int cnt = 0;
+
+ char tmp[PATH_MAX+1];
+ char *ptr;
+
+ strncpy(tmp, str, PATH_MAX);
+ tmp[PATH_MAX] = '\0';
+
+ char *p = strtok_r(tmp, delim, &ptr);
+ if (max_tokens < 1 || max_tokens > MAX_TOKENS) {
+ max_tokens = 1;
+ }
+
+ if (p != NULL) {
+ tokens[cnt++] = strdup(p);
+ while(cnt < max_tokens && p != NULL) {
+ p = strtok_r(NULL, delim, &ptr);
+ if (p != NULL) {
+ tokens[cnt++] = strdup(p);
+ }
+ }
+ }
+ return cnt;
+}
+
+void free_strings(char **array, int n)
+{
+ int i;
+
+ for(i = 0; i < n; i++) {
+ if (array[i] != NULL) {
+ free(array[i]);
+ }
+ }
+}
+
+
+int read_line(const int fd, char* ptr, const unsigned int maxlen)
+{
+ unsigned int n = 0;
+ char c[2];
+ int rc;
+
+ while(n != maxlen) {
+ if((rc = sdb_read(fd, c, 1)) != 1)
+ return -1; // eof or read err
+
+ if(*c == '\n') {
+ ptr[n] = 0;
+ return n;
+ }
+ ptr[n++] = *c;
+ }
+ return -1; // no space
+}
+
+/**
+ * The standard strncpy() function does not guarantee that the resulting string is null terminated.
+ * char ntbs[NTBS_SIZE];
+ * strncpy(ntbs, source, sizeof(ntbs)-1);
+ * ntbs[sizeof(ntbs)-1] = '\0'
+ */
+
+char *s_strncpy(char *dest, const char *source, size_t n) {
+
+ char *start = dest;
+
+ while(n && (*dest++ = *source++)) {
+ n--;
+ }
+
+ if (n) {
+ while (--n) {
+ *dest++ = '\0';
+ }
+ }
+ return start;
+}
--- /dev/null
+#ifndef _STRUTILS_H_
+#define _STRUTILS_H_
+
+#define MAX_TOKENS 30
+
+size_t tokenize(const char *str, const char *delim, char *tokens[], size_t max_tokens);
+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);
+#endif
+
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
#define SDB_MUTEX_DEFINE(x) sdb_mutex_t x
/* declare all mutexes */
+/* For win32, sdb_sysdeps_init() will do the mutex runtime initialization. */
#define SDB_MUTEX(x) extern sdb_mutex_t x;
#include "mutex_list.h"
extern void sdb_sysdeps_init(void);
+static __inline__ char* ansi_to_utf8(const char *str)
+{
+ int len;
+ char *utf8;
+ wchar_t *unicode;
+
+ //ANSI( MutiByte ) -> UCS-2( WideByte ) -> UTF-8( MultiByte )
+ len = MultiByteToWideChar (CP_ACP, 0, str, -1, NULL, 0);
+ unicode = (wchar_t *)calloc (len+1, sizeof(wchar_t));
+ MultiByteToWideChar (CP_ACP, 0, str, -1, unicode, len);
+
+ len = WideCharToMultiByte (CP_UTF8, 0, unicode, -1, NULL, 0, NULL, NULL);
+ utf8 = (char *)calloc (len+1, sizeof(char));
+
+ WideCharToMultiByte (CP_UTF8, 0, unicode, -1, utf8, len, NULL, NULL);
+ free (unicode);
+
+ return utf8;
+}
+
static __inline__ void sdb_mutex_lock( sdb_mutex_t* lock )
{
EnterCriticalSection( lock );
return 0;
}
-static __inline__ void close_on_exec(int fd)
+static __inline__ int close_on_exec(int fd)
{
/* nothing really */
}
static __inline__ int sdb_mkdir(const char* path, int mode)
{
- return _mkdir(path);
+ return _mkdir(path);
}
#undef mkdir
#define mkdir ___xxx_mkdir
fdevent *prev;
int fd;
+ int force_eof;
+
unsigned short state;
unsigned short events;
#include "fdevent.h"
#include "sockets.h"
+// tizen specific #include <cutils/misc.h>
+#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/stat.h>
#define OS_PATH_SEPARATOR_STR "/"
typedef pthread_mutex_t sdb_mutex_t;
+
#define SDB_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define sdb_mutex_init pthread_mutex_init
#define sdb_mutex_lock pthread_mutex_lock
#define sdb_mutex_unlock pthread_mutex_unlock
#define sdb_mutex_destroy pthread_mutex_destroy
-#define SDB_MUTEX_DEFINE(m) static sdb_mutex_t m = PTHREAD_MUTEX_INITIALIZER
+#define SDB_MUTEX_DEFINE(m) sdb_mutex_t m = PTHREAD_MUTEX_INITIALIZER
#define sdb_cond_t pthread_cond_t
#define sdb_cond_init pthread_cond_init
#define sdb_cond_signal pthread_cond_signal
#define sdb_cond_destroy pthread_cond_destroy
-static __inline__ void close_on_exec(int fd)
+/* declare all mutexes */
+#define SDB_MUTEX(x) extern sdb_mutex_t x;
+#include "mutex_list.h"
+
+static __inline__ int close_on_exec(int fd)
{
- fcntl( fd, F_SETFD, FD_CLOEXEC );
+ return fcntl( fd, F_SETFD, FD_CLOEXEC );
}
static __inline__ int unix_open(const char* path, int options,...)
static __inline__ int sdb_open( const char* pathname, int options )
{
int fd = open( pathname, options );
- if (fd < 0)
+ if (fd < 0) {
+ return -1;
+ }
+ if (close_on_exec( fd ) < 0 ) {
+ close(fd);
return -1;
- close_on_exec( fd );
+ }
return fd;
}
#undef open
{
int fd = creat(path, mode);
- if ( fd < 0 )
+ if ( fd < 0 ) {
return -1;
+ }
- close_on_exec(fd);
+ if (close_on_exec(fd) < 0) {
+ return -1;
+ }
return fd;
}
#undef creat
static __inline__ int sdb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
{
- return accept( serverfd, addr, addrlen );
+ int fd;
+
+ fd = accept(serverfd, addr, addrlen);
+ if (fd >= 0) {
+ if (close_on_exec(fd) < 0) {
+ sdb_close(fd);
+ return -1;
+ }
+ }
+
+ return fd;
}
#undef accept
return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
}
-static __inline__ void disable_tcp_nagle(int fd)
+static __inline__ int disable_tcp_nagle(int fd)
{
- int on = 1;
- setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on) );
+ int on = 1;
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*) &on, sizeof(on)) < 0) {
+ return -1;
+ }
+ return 0;
}
int rc;
rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
- if (rc < 0)
+ if (rc < 0) {
return -1;
+ }
- close_on_exec( sv[0] );
- close_on_exec( sv[1] );
+ if (close_on_exec( sv[0] ) < 0 ) {
+ return -1;
+ }
+ if (close_on_exec( sv[1] ) < 0 ) {
+ return -1;
+ }
return 0;
}
return path[0] == '/';
}
+#include "strutils.h"
+
+static __inline__ char* ansi_to_utf8(const char *str)
+{
+ // Not implement!
+ // If need, use iconv later event though unix system is using utf8 encoding.
+ int len;
+ char *utf8;
+
+ len = strlen(str);
+ utf8 = (char *)calloc(len+1, sizeof(char));
+ s_strncpy(utf8, str, strlen(str));
+ return utf8;
+}
+
#endif /* !_WIN32 */
#endif /* _SDB_SYSDEPS_H */
+/*
+ * 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 <windows.h>
#include <winsock2.h>
#include "mutex_list.h"
InitializeCriticalSection( &_win32_lock );
}
-
--- /dev/null
+/*
+ * 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 _LIBS_CUTILS_THREADS_H
+#define _LIBS_CUTILS_THREADS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** local thread storage *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+#include <pthread.h>
+
+typedef struct {
+ pthread_mutex_t lock;
+ int has_tls;
+ pthread_key_t tls;
+
+} thread_store_t;
+
+#define THREAD_STORE_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
+
+#elif defined HAVE_WIN32_THREADS
+
+#include <windows.h>
+
+typedef struct {
+ int lock_init;
+ int has_tls;
+ DWORD tls;
+ CRITICAL_SECTION lock;
+
+} thread_store_t;
+
+#define THREAD_STORE_INITIALIZER { 0, 0, 0, {0, 0, 0, 0, 0, 0} }
+
+#else
+# error "no thread_store_t implementation for your platform !!"
+#endif
+
+typedef void (*thread_store_destruct_t)(void* value);
+
+extern void* thread_store_get(thread_store_t* store);
+
+extern void thread_store_set(thread_store_t* store,
+ void* value,
+ thread_store_destruct_t destroy);
+
+/***********************************************************************/
+/***********************************************************************/
+/***** *****/
+/***** mutexes *****/
+/***** *****/
+/***********************************************************************/
+/***********************************************************************/
+
+#ifdef HAVE_PTHREADS
+
+typedef pthread_mutex_t mutex_t;
+
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+static __inline__ void mutex_lock(mutex_t* lock)
+{
+ pthread_mutex_lock(lock);
+}
+static __inline__ void mutex_unlock(mutex_t* lock)
+{
+ pthread_mutex_unlock(lock);
+}
+static __inline__ int mutex_init(mutex_t* lock)
+{
+ return pthread_mutex_init(lock, NULL);
+}
+static __inline__ void mutex_destroy(mutex_t* lock)
+{
+ pthread_mutex_destroy(lock);
+}
+#endif
+
+#ifdef HAVE_WIN32_THREADS
+typedef struct {
+ int init;
+ CRITICAL_SECTION lock[1];
+} mutex_t;
+
+#define MUTEX_INITIALIZER { 0, {{ NULL, 0, 0, NULL, NULL, 0 }} }
+
+static __inline__ void mutex_lock(mutex_t* lock)
+{
+ if (!lock->init) {
+ lock->init = 1;
+ InitializeCriticalSection( lock->lock );
+ lock->init = 2;
+ } else while (lock->init != 2)
+ Sleep(10);
+
+ EnterCriticalSection(lock->lock);
+}
+
+static __inline__ void mutex_unlock(mutex_t* lock)
+{
+ LeaveCriticalSection(lock->lock);
+}
+static __inline__ int mutex_init(mutex_t* lock)
+{
+ InitializeCriticalSection(lock->lock);
+ lock->init = 2;
+ return 0;
+}
+static __inline__ void mutex_destroy(mutex_t* lock)
+{
+ if (lock->init) {
+ lock->init = 0;
+ DeleteCriticalSection(lock->lock);
+ }
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_CUTILS_THREADS_H */
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
SDB_MUTEX_DEFINE( transport_lock );
#if SDB_TRACE
+#define MAX_DUMP_HEX_LEN 16
static void dump_hex( const unsigned char* ptr, size_t len )
{
int nn, len2 = len;
+ // Build a string instead of logging each character.
+ // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
+ char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
- if (len2 > 16) len2 = 16;
+ if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
- for (nn = 0; nn < len2; nn++)
- D("%02x", ptr[nn]);
- D(" ");
+ int pbSize = sizeof(buffer);
+ for (nn = 0; nn < len2; nn++) {
+ snprintf(pb, pbSize, "%02x", ptr[nn]);
+ pb += 2;
+ pbSize -= 2;
+ }
+ *pb++ = ' ';
for (nn = 0; nn < len2; nn++) {
int c = ptr[nn];
if (c < 32 || c > 127)
c = '.';
- D("%c", c);
+ *pb++ = c;
}
- D("\n");
- fflush(stdout);
+ *pb++ = '\0';
+ DR("%s\n", buffer);
}
#endif
{
adisconnect* dis = t->disconnects.next;
- D("run_transport_disconnects: %p (%s)\n", t, t->serial ? t->serial : "unknown" );
+ D("%s: run_transport_disconnects\n", t->serial);
while (dis != &t->disconnects) {
adisconnect* next = dis->next;
dis->func( dis->opaque, t );
}
}
+#if SDB_TRACE
+static void
+dump_packet(const char* name, const char* func, apacket* p)
+{
+ unsigned command = p->msg.command;
+ int len = p->msg.data_length;
+ char cmd[9];
+ char arg0[12], arg1[12];
+ int n;
+
+ for (n = 0; n < 4; n++) {
+ int b = (command >> (n*8)) & 255;
+ if (b < 32 || b >= 127)
+ break;
+ cmd[n] = (char)b;
+ }
+ if (n == 4) {
+ cmd[4] = 0;
+ } else {
+ /* There is some non-ASCII name in the command, so dump
+ * the hexadecimal value instead */
+ snprintf(cmd, sizeof cmd, "%08x", command);
+ }
+
+ if (p->msg.arg0 < 256U)
+ snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
+ else
+ snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
+
+ if (p->msg.arg1 < 256U)
+ snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
+ else
+ snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
+
+ D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
+ name, func, cmd, arg0, arg1, len);
+ dump_hex(p->data, len);
+}
+#endif /* SDB_TRACE */
+
static int
-read_packet(int fd, apacket** ppacket)
+read_packet(int fd, const char* name, apacket** ppacket)
{
char *p = (char*)ppacket; /* really read a packet address */
int r;
int len = sizeof(*ppacket);
+ char buff[8];
+ if (!name) {
+ snprintf(buff, sizeof buff, "fd=%d", fd);
+ name = buff;
+ }
while(len > 0) {
r = sdb_read(fd, p, len);
if(r > 0) {
len -= r;
p += r;
} else {
- D("read_packet: %d error %d %d\n", fd, r, errno);
+ D("%s: read_packet (fd=%d), error ret=%d errno=%d\n", name, fd, r, errno);
if((r < 0) && (errno == EINTR)) continue;
return -1;
}
}
#if SDB_TRACE
- if (SDB_TRACING)
- {
- unsigned command = (*ppacket)->msg.command;
- int len = (*ppacket)->msg.data_length;
- char cmd[5];
- int n;
-
- for (n = 0; n < 4; n++) {
- int b = (command >> (n*8)) & 255;
- if (b >= 32 && b < 127)
- cmd[n] = (char)b;
- else
- cmd[n] = '.';
- }
- cmd[4] = 0;
-
- D("read_packet: %d ok: [%08x %s] %08x %08x (%d) ",
- fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len);
- dump_hex((*ppacket)->data, len);
+ if (SDB_TRACING) {
+ dump_packet(name, "from remote", *ppacket);
}
#endif
return 0;
}
static int
-write_packet(int fd, apacket** ppacket)
+write_packet(int fd, const char* name, apacket** ppacket)
{
char *p = (char*) ppacket; /* we really write the packet address */
int r, len = sizeof(ppacket);
+ char buff[8];
+ if (!name) {
+ snprintf(buff, sizeof buff, "fd=%d", fd);
+ name = buff;
+ }
#if SDB_TRACE
- if (SDB_TRACING)
- {
- unsigned command = (*ppacket)->msg.command;
- int len = (*ppacket)->msg.data_length;
- char cmd[5];
- int n;
-
- for (n = 0; n < 4; n++) {
- int b = (command >> (n*8)) & 255;
- if (b >= 32 && b < 127)
- cmd[n] = (char)b;
- else
- cmd[n] = '.';
- }
- cmd[4] = 0;
-
- D("write_packet: %d [%08x %s] %08x %08x (%d) ",
- fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len);
- dump_hex((*ppacket)->data, len);
+ if (SDB_TRACING) {
+ dump_packet(name, "to remote", *ppacket);
}
#endif
len = sizeof(ppacket);
len -= r;
p += r;
} else {
- D("write_packet: %d error %d %d\n", fd, r, errno);
+ D("%s: write_packet (fd=%d) error ret=%d errno=%d\n", name, fd, r, errno);
if((r < 0) && (errno == EINTR)) continue;
return -1;
}
static void transport_socket_events(int fd, unsigned events, void *_t)
{
+ atransport *t = _t;
+ D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
if(events & FDE_READ){
apacket *p = 0;
- if(read_packet(fd, &p)){
- D("failed to read packet from transport socket on fd %d\n", fd);
+ if(read_packet(fd, t->serial, &p)){
+ D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
} else {
handle_packet(p, (atransport *) _t);
}
print_packet("send", p);
if (t == NULL) {
- fatal_errno("Transport is null");
D("Transport is null \n");
+ // Zap errno because print_packet() and other stuff have errno effect.
+ errno = 0;
+ fatal_errno("Transport is null");
}
- if(write_packet(t->transport_socket, &p)){
+ if(write_packet(t->transport_socket, t->serial, &p)){
fatal_errno("cannot enqueue packet on transport socket");
}
}
atransport *t = _t;
apacket *p;
- D("from_remote: starting thread for transport %p, on fd %d\n", t, t->fd );
-
- D("from_remote: transport %p SYNC online (%d)\n", t, t->sync_token + 1);
+ D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
+ t->serial, t->fd, t->sync_token + 1);
p = get_apacket();
p->msg.command = A_SYNC;
p->msg.arg0 = 1;
p->msg.arg1 = ++(t->sync_token);
p->msg.magic = A_SYNC ^ 0xffffffff;
- if(write_packet(t->fd, &p)) {
+ if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
- D("from_remote: failed to write SYNC apacket to transport %p", t);
+ D("%s: failed to write SYNC packet\n", t->serial);
goto oops;
}
- D("from_remote: data pump for transport %p\n", t);
+ D("%s: data pump started\n", t->serial);
for(;;) {
p = get_apacket();
if(t->read_from_remote(p, t) == 0){
- D("from_remote: received remote packet, sending to transport %p\n",
- t);
- if(write_packet(t->fd, &p)){
+ D("%s: received remote packet, sending to transport\n",
+ t->serial);
+ if(write_packet(t->fd, t->serial, &p)){
put_apacket(p);
- D("from_remote: failed to write apacket to transport %p", t);
+ D("%s: failed to write apacket to transport\n", t->serial);
goto oops;
}
} else {
- D("from_remote: remote read failed for transport %p\n", p);
+ D("%s: remote read failed for transport\n", t->serial);
put_apacket(p);
break;
}
}
- D("from_remote: SYNC offline for transport %p\n", t);
+ D("%s: SYNC offline for transport\n", t->serial);
p = get_apacket();
p->msg.command = A_SYNC;
p->msg.arg0 = 0;
p->msg.arg1 = 0;
p->msg.magic = A_SYNC ^ 0xffffffff;
- if(write_packet(t->fd, &p)) {
+ if(write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
- D("from_remote: failed to write SYNC apacket to transport %p", t);
+ D("%s: failed to write SYNC apacket to transport", t->serial);
}
oops:
- D("from_remote: thread is exiting for transport %p\n", t);
+ D("%s: transport output thread is exiting\n", t->serial);
kick_transport(t);
transport_unref(t);
return 0;
apacket *p;
int active = 0;
- D("to_remote: starting input_thread for %p, reading from fd %d\n",
- t, t->fd);
+ D("%s: starting transport input thread, reading from fd %d\n",
+ t->serial, t->fd);
for(;;){
- if(read_packet(t->fd, &p)) {
- D("to_remote: failed to read apacket from transport %p on fd %d\n",
- t, t->fd );
+ if(read_packet(t->fd, t->serial, &p)) {
+ D("%s: failed to read apacket from transport on fd %d\n",
+ t->serial, t->fd );
break;
}
if(p->msg.command == A_SYNC){
if(p->msg.arg0 == 0) {
- D("to_remote: transport %p SYNC offline\n", t);
+ D("%s: transport SYNC offline\n", t->serial);
put_apacket(p);
break;
} else {
if(p->msg.arg1 == t->sync_token) {
- D("to_remote: transport %p SYNC online\n", t);
+ D("%s: transport SYNC online\n", t->serial);
active = 1;
} else {
- D("to_remote: trandport %p ignoring SYNC %d != %d\n",
- t, p->msg.arg1, t->sync_token);
+ D("%s: transport ignoring SYNC %d != %d\n",
+ t->serial, p->msg.arg1, t->sync_token);
}
}
} else {
if(active) {
- D("to_remote: transport %p got packet, sending to remote\n", t);
+ D("%s: transport got packet, sending to remote\n", t->serial);
t->write_to_remote(p, t);
} else {
- D("to_remote: transport %p ignoring packet while offline\n", t);
+ D("%s: transport ignoring packet while offline\n", t->serial);
}
}
// while a client socket is still active.
close_all_sockets(t);
- D("to_remote: thread is exiting for transport %p, fd %d\n", t, t->fd);
+ D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
kick_transport(t);
transport_unref(t);
return 0;
p += r;
} else {
if((r < 0) && (errno == EINTR)) continue;
- D("transport_read_action: on fd %d, error %d: %s\n",
- fd, errno, strerror(errno));
+ D("transport_read_action: on fd %d, error %d\n",
+ fd, errno);
return -1;
}
}
p += r;
} else {
if((r < 0) && (errno == EINTR)) continue;
- D("transport_write_action: on fd %d, error %d: %s\n",
- fd, errno, strerror(errno));
+ D("transport_write_action: on fd %d, error %d\n",
+ fd, errno);
return -1;
}
}
t = m.transport;
if(m.action == 0){
- D("transport: %p removing and free'ing %d\n", t, t->transport_socket);
+ D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
/* IMPORTANT: the remove closes one half of the
** socket pair. The close closes the other half.
free(t->product);
if (t->serial)
free(t->serial);
+ if (t->device_name)
+ free(t->device_name);
memset(t,0xee,sizeof(atransport));
free(t);
fatal_errno("cannot open transport socketpair");
}
- D("transport: %p (%d,%d) starting\n", t, s[0], s[1]);
+ D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
t->transport_socket = s[0];
t->fd = s[1];
- D("transport: %p install %d\n", t, t->transport_socket );
fdevent_install(&(t->transport_fde),
t->transport_socket,
transport_socket_events,
tmsg m;
m.transport = transport;
m.action = 1;
- D("transport: %p registered\n", transport);
+ D("transport: %s registered\n", transport->serial);
if(transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
tmsg m;
m.transport = transport;
m.action = 0;
- D("transport: %p removed\n", transport);
+ D("transport: %s removed\n", transport->serial);
if(transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
static void transport_unref_locked(atransport *t)
{
t->ref_count--;
- D("transport: %p R- (ref=%d)\n", t, t->ref_count);
if (t->ref_count == 0) {
- D("transport: %p kicking and closing\n", t);
+ D("transport: %s unref (kicking and closing)\n", t->serial);
if (!t->kicked) {
t->kicked = 1;
t->kick(t);
}
t->close(t);
remove_transport(t);
+ } else {
+ D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
}
}
case CS_DEVICE: return "device";
case CS_HOST: return "host";
case CS_RECOVERY: return "recovery";
+ case CS_SIDELOAD: return "sideload";
case CS_NOPERM: return "no permissions";
default: return "unknown";
}
sdb_mutex_lock(&transport_lock);
for(t = transport_list.next; t != &transport_list; t = t->next) {
const char* serial = t->serial;
+ const char* devicename = (t->device_name == NULL) ? DEFAULT_DEVICENAME : t->device_name; /* tizen specific */
if (!serial || !serial[0])
serial = "????????????";
- len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
+ len = snprintf(p, end - p, "%s\t%s\t%s\n", serial, statename(t), devicename);
if (p + len >= end) {
/* discard last line if buffer is too short */
}
#endif // SDB_HOST
-void register_socket_transport(int s, const char *serial, int port, int local)
+void register_socket_transport(int s, const char *serial, int port, int local, const char *device_name)
{
atransport *t = calloc(1, sizeof(atransport));
- D("transport: %p init'ing for socket %d, on port %d\n", t, s, port);
+ if (t == NULL) {
+ D("could not allocate atransport'\n");
+ return;
+ }
+ char buff[32];
+
+ if (!serial) {
+ snprintf(buff, sizeof buff, "T-%p", t);
+ serial = buff;
+ }
+ D("transport: %s init'ing for socket %d, on port %d (%s)\n", serial, s, port, device_name);
if ( init_socket_transport(t, s, port, local) < 0 ) {
sdb_close(s);
free(t);
+#if SDB_HOST /* tizen specific */
+ atransport *old_t = find_transport(serial);
+ if (old_t) {
+ unregister_transport(old_t);
+ } else {
+ D("No such device %s", serial);
+ }
+#endif
return;
}
if(serial) {
t->serial = strdup(serial);
}
+#if SDB_HOST /* tizen specific */
+ if (device_name) {/* tizen specific */
+ t->device_name = strdup(device_name);
+ } else { // device_name could be null when sdb server was forked before qemu has sent the connect message.
+ char device_name[DEVICENAME_MAX];
+ if (get_devicename_from_shdmem(port, device_name) == 0) {
+ t->device_name = strdup(device_name);
+ }
+ }
+#endif
register_transport(t);
}
#endif
+int get_connected_count(transport_type type) /* tizen specific */
+{
+ int cnt = 0;
+ atransport *t;
+ sdb_mutex_lock(&transport_lock);
+ for(t = transport_list.next; t != &transport_list; t = t->next) {
+ if (type == kTransportAny || type == t->type)
+ cnt++;
+ }
+ sdb_mutex_unlock(&transport_lock);
+ if (type == kTransportUsb) {
+ D("connected device count:%d\n",cnt);
+ }
+ return cnt;
+}
+
+void broadcast_transport(apacket *p)
+{
+ atransport *t;
+ sdb_mutex_lock(&transport_lock);
+ for(t = transport_list.next; t != &transport_list; t = t->next) {
+ D("broadcast device transport:%d\n", t->connection_state);
+ apacket* ap = get_apacket();
+ copy_packet(ap, p);
+
+ send_packet(ap, t);
+ if (is_pwlocked()) {
+ t->connection_state = CS_PWLOCK;
+ } else {
+ t->connection_state = CS_DEVICE;
+ }
+ }
+ sdb_mutex_unlock(&transport_lock);
+}
+
void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
{
atransport *t = calloc(1, sizeof(atransport));
+ if (t == NULL) {
+ D("cannot allocate atransport");
+ return;
+ }
+ char device_name[256];
+
D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
serial ? serial : "");
init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
if(serial) {
t->serial = strdup(serial);
}
+
+ /* tizen specific */
+ snprintf(device_name, sizeof(device_name), "device-%d",get_connected_count(kTransportUsb)+1);
+ t->device_name = strdup(device_name);
register_transport(t);
}
#if SDB_TRACE
int len0 = len;
#endif
- D("readx: %d %p %d\n", fd, ptr, (int)len);
+ D("readx: fd=%d wanted=%d\n", fd, (int)len);
while(len > 0) {
r = sdb_read(fd, p, len);
if(r > 0) {
len -= r;
p += r;
} else {
- D("readx: %d %d %s\n", fd, r, strerror(errno));
- if((r < 0) && (errno == EINTR)) continue;
+ if (r < 0) {
+ D("readx: fd=%d (errno:%d)\n", fd, errno);
+ if (errno == EINTR)
+ continue;
+ } else {
+ D("readx: fd=%d disconnected\n", fd);
+ }
return -1;
}
}
#if SDB_TRACE
- D("readx: %d ok: ", fd);
+ D("readx: fd=%d wanted=%d got=%d\n", fd, len0, len0 - len);
dump_hex( ptr, len0 );
#endif
return 0;
int r;
#if SDB_TRACE
- D("writex: %d %p %d: ", fd, ptr, (int)len);
+ D("writex: fd=%d len=%d: ", fd, (int)len);
dump_hex( ptr, len );
#endif
while(len > 0) {
len -= r;
p += r;
} else {
- D("writex: %d %d %s\n", fd, r, strerror(errno));
- if((r < 0) && (errno == EINTR)) continue;
+ if (r < 0) {
+ D("writex: fd=%d error %d\n", fd, errno);
+ if (errno == EINTR)
+ continue;
+ } else {
+ D("writex: fd=%d disconnected\n", fd);
+ }
return -1;
}
}
-
- D("writex: %d ok\n", fd);
return 0;
}
return 0;
}
}
-
--- /dev/null
+/*
+ * 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 __TRANSPORT_H
+#define __TRANSPORT_H
+
+/* convenience wrappers around read/write that will retry on
+** EINTR and/or short read/write. Returns 0 on success, -1
+** on error or EOF.
+*/
+int readx(int fd, void *ptr, size_t len);
+int writex(int fd, const void *ptr, size_t len);
+#endif /* __TRANSPORT_H */
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <arpa/inet.h>
#include "sysdeps.h"
#include <sys/types.h>
+#ifndef HAVE_WIN32_IPC
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#endif
+
#define TRACE_TAG TRACE_TRANSPORT
#include "sdb.h"
+#include "strutils.h"
-#ifdef __ppc__
+#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)
{
static atransport* local_transports[ SDB_LOCAL_TRANSPORT_MAX ];
#endif /* SDB_HOST */
+SDB_MUTEX_DEFINE( register_noti_lock );
+#ifndef _WIN32
+static pthread_cond_t noti_cond = PTHREAD_COND_INITIALIZER;
+#endif
+
static int remote_read(apacket *p, atransport *t)
{
if(readx(t->sfd, &p->msg, sizeof(amessage))){
fix_endians(p);
-#if 0 && defined __ppc__
+#if 0 && defined HAVE_BIG_ENDIAN
D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
#endif
fix_endians(p);
-#if 0 && defined __ppc__
+#if 0 && defined HAVE_BIG_ENDIAN
D("write remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
#endif
}
-int local_connect(int port) {
- return local_connect_arbitrary_ports(port-1, port);
+int local_connect(int port, const char *device_name) {
+ return local_connect_arbitrary_ports(port-1, port, device_name);
}
-int local_connect_arbitrary_ports(int console_port, int sdb_port)
+int local_connect_arbitrary_ports(int console_port, int sdb_port, const char *device_name)
{
char buf[64];
int fd = -1;
if (fd >= 0) {
D("client: connected on remote on fd %d\n", fd);
- close_on_exec(fd);
- disable_tcp_nagle(fd);
+ if (close_on_exec(fd) < 0) {
+ D("failed to close fd exec\n");
+ }
+ if (disable_tcp_nagle(fd) < 0) {
+ D("failed to disable_tcp_nagle\n");
+ }
snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
- register_socket_transport(fd, buf, sdb_port, 1);
+ register_socket_transport(fd, buf, sdb_port, 1, device_name);
return 0;
}
return -1;
}
+#if SDB_HOST /* tizen specific */
+int get_devicename_from_shdmem(int port, char *device_name)
+{
+ char *vms = NULL;
+#ifndef HAVE_WIN32_IPC
+ int shm_id;
+ void *shared_memory = (void *)0;
+
+ shm_id = shmget( (key_t)port-1, 0, 0);
+ if (shm_id == -1)
+ return -1;
+
+ shared_memory = shmat(shm_id, (void *)0, SHM_RDONLY);
+
+ if (shared_memory == (void *)-1)
+ {
+ D("faild to get shdmem key (%d) : %s\n", port, strerror(errno));
+ return -1;
+ }
+
+ vms = strstr((char*)shared_memory, VMS_PATH);
+ if (vms != NULL)
+ s_strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX);
+ else
+ s_strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX);
+
+#else /* _WIN32*/
+ HANDLE hMapFile;
+ char s_port[5];
+ char* pBuf;
+
+ sprintf(s_port, "%d", port-1);
+ hMapFile = OpenFileMapping(FILE_MAP_READ, TRUE, s_port);
+
+ if(hMapFile == NULL) {
+ D("faild to get shdmem key (%ld) : %s\n", port, GetLastError() );
+ return -1;
+ }
+ pBuf = (char*)MapViewOfFile(hMapFile,
+ FILE_MAP_READ,
+ 0,
+ 0,
+ 50);
+ if (pBuf == NULL) {
+ D("Could not map view of file (%ld)\n", GetLastError());
+ CloseHandle(hMapFile);
+ return -1;
+ }
+
+ vms = strstr((char*)pBuf, VMS_PATH);
+ if (vms != NULL)
+ s_strncpy(device_name, vms+strlen(VMS_PATH), DEVICENAME_MAX);
+ else
+ s_strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX);
+ CloseHandle(hMapFile);
+#endif
+ D("init device name %s on port %d\n", device_name, port);
+
+ return 0;
+}
+
+int read_line(const int fd, char* ptr, size_t maxlen)
+{
+ unsigned int n = 0;
+ char c[2];
+ int rc;
+
+ while(n != maxlen) {
+ if((rc = sdb_read(fd, c, 1)) != 1)
+ return -1; // eof or read err
+
+ if(*c == '\n') {
+ ptr[n] = 0;
+ return n;
+ }
+ ptr[n++] = *c;
+ }
+ return -1; // no space
+}
+#endif
static void *client_socket_thread(void *x)
{
#if SDB_HOST
-// for (;;){
- int port = DEFAULT_SDB_LOCAL_TRANSPORT_PORT;
- int count = SDB_LOCAL_TRANSPORT_MAX;
-
- D("transport: client_socket_thread() starting\n");
-
- /* try to connect to any number of running emulator instances */
- /* this is only done when SDB starts up. later, each new emulator */
- /* will send a message to SDB to indicate that is is starting up */
- for ( ; count > 0; count--, port += 10 ) {
- (void) local_connect(port);
- }
-
-// sdb_sleep_ms(1000);
-// }
+ int port = DEFAULT_SDB_LOCAL_TRANSPORT_PORT;
+ int count = SDB_LOCAL_TRANSPORT_MAX;
+
+ D("transport: client_socket_thread() starting\n");
+
+ /* try to connect to any number of running emulator instances */
+ /* this is only done when SDB starts up. later, each new emulator */
+ /* will send a message to SDB to indicate that is is starting up */
+ for ( ; count > 0; count--, port += 10 ) { /* tizen specific */
+ (void) local_connect(port, NULL);
+ }
#endif
return 0;
}
serverfd = -1;
for(;;) {
if(serverfd == -1) {
+ // socket_inaddr_any_server returns -1 if there is any error
serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
if(serverfd < 0) {
D("server: cannot bind socket yet\n");
sdb_sleep_ms(1000);
continue;
}
- close_on_exec(serverfd);
+ if (close_on_exec(serverfd) < 0) {
+ D("failed to close serverfd exec\n");
+ }
}
alen = sizeof(addr);
D("server: trying to get new connection from %d\n", port);
+
+ if (is_emulator()) {
+ // im ready to accept new client!
+ pthread_cond_broadcast(¬i_cond);
+ }
+
fd = sdb_socket_accept(serverfd, &addr, &alen);
if(fd >= 0) {
D("server: new connection on fd %d\n", fd);
- close_on_exec(fd);
- disable_tcp_nagle(fd);
- register_socket_transport(fd, "host", port, 1);
+ if (close_on_exec(fd) < 0) {
+ D("failed to close fd exec\n");
+ }
+ if (disable_tcp_nagle(fd) < 0) {
+ D("failed to disable_tcp_nagle\n");
+ }
+ register_socket_transport(fd, "host", port, 1, NULL);
}
}
D("transport: server_socket_thread() exiting\n");
return 0;
}
+/* This is relevant only for SDB daemon running inside the emulator. */
+#if !SDB_HOST
+/*
+ * Redefine open and write for qemu_pipe.h that contains inlined references
+ * to those routines. We will redifine them back after qemu_pipe.h inclusion.
+ */
+#undef open
+#undef write
+#define open sdb_open
+#define write sdb_write
+#include "qemu_pipe.h"
+#undef open
+#undef write
+#define open ___xxx_open
+#define write ___xxx_write
+
+/* A worker thread that monitors host connections, and registers a transport for
+ * every new host connection. This thread replaces server_socket_thread on
+ * condition that sdbd daemon runs inside the emulator, and emulator uses QEMUD
+ * pipe to communicate with sdbd daemon inside the guest. This is done in order
+ * to provide more robust communication channel between SDB host and guest. The
+ * main issue with server_socket_thread approach is that it runs on top of TCP,
+ * and thus is sensitive to network disruptions. For instance, the
+ * ConnectionManager may decide to reset all network connections, in which case
+ * the connection between SDB host and guest will be lost. To make SDB traffic
+ * independent from the network, we use here 'sdb' QEMUD service to transfer data
+ * between the host, and the guest. See external/qemu/android/sdb-*.* that
+ * implements the emulator's side of the protocol. Another advantage of using
+ * QEMUD approach is that SDB will be up much sooner, since it doesn't depend
+ * anymore on network being set up.
+ * The guest side of the protocol contains the following phases:
+ * - Connect with sdb QEMUD service. In this phase a handle to 'sdb' QEMUD service
+ * is opened, and it becomes clear whether or not emulator supports that
+ * protocol.
+ * - Wait for the SDB host to create connection with the guest. This is done by
+ * sending an 'accept' request to the sdb QEMUD service, and waiting on
+ * response.
+ * - When new SDB host connection is accepted, the connection with sdb QEMUD
+ * service is registered as the transport, and a 'start' request is sent to the
+ * sdb QEMUD service, indicating that the guest is ready to receive messages.
+ * Note that the guest will ignore messages sent down from the emulator before
+ * the transport registration is completed. That's why we need to send the
+ * 'start' request after the transport is registered.
+ */
+#if 0
+static void *qemu_socket_thread(void * arg)
+{
+/* 'accept' request to the sdb QEMUD service. */
+static const char _accept_req[] = "accept";
+/* 'start' request to the sdb QEMUD service. */
+static const char _start_req[] = "start";
+/* 'ok' reply from the sdb QEMUD service. */
+static const char _ok_resp[] = "ok";
+
+ const int port = (int)arg;
+ int res, fd;
+ char tmp[256];
+ char con_name[32];
+
+ D("transport: qemu_socket_thread() starting\n");
+
+ /* sdb QEMUD service connection request. */
+ snprintf(con_name, sizeof(con_name), "qemud:sdb:%d", port);
+
+ /* Connect to the sdb QEMUD service. */
+ fd = qemu_pipe_open(con_name);
+ if (fd < 0) {
+ /* This could be an older version of the emulator, that doesn't
+ * implement sdb QEMUD service. Fall back to the old TCP way. */
+ sdb_thread_t thr;
+ D("sdb service is not available. Falling back to TCP socket.\n");
+ sdb_thread_create(&thr, server_socket_thread, arg);
+ return 0;
+ }
+
+ for(;;) {
+ /*
+ * Wait till the host creates a new connection.
+ */
+
+ /* Send the 'accept' request. */
+ res = sdb_write(fd, _accept_req, strlen(_accept_req));
+ if (res == strlen(_accept_req)) {
+ /* Wait for the response. In the response we expect 'ok' on success,
+ * or 'ko' on failure. */
+ res = sdb_read(fd, tmp, sizeof(tmp));
+ if (res != 2 || memcmp(tmp, _ok_resp, 2)) {
+ D("Accepting SDB host connection has failed.\n");
+ sdb_close(fd);
+ } else {
+ /* Host is connected. Register the transport, and start the
+ * exchange. */
+ register_socket_transport(fd, "host", port, 1, NULL);
+ sdb_write(fd, _start_req, strlen(_start_req));
+ }
+
+ /* Prepare for accepting of the next SDB host connection. */
+ fd = qemu_pipe_open(con_name);
+ if (fd < 0) {
+ D("sdb service become unavailable.\n");
+ return 0;
+ }
+ } else {
+ D("Unable to send the '%s' request to SDB service.\n", _accept_req);
+ return 0;
+ }
+ }
+ D("transport: qemu_socket_thread() exiting\n");
+ return 0;
+}
+#endif // !SDB_HOST
+#endif
+
+int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen,
+ int nsec) {
+ int flags, n, error;
+ socklen_t len;
+ fd_set rset, wset;
+ struct timeval tval;
+
+ flags = fcntl(sockfd, F_GETFL, 0);
+ if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ D("failed to set file O_NONBLOCK status flag for socket %d: %s\n",
+ sockfd, strerror(errno));
+ }
+
+ error = 0;
+ if ((n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
+ if (errno != EINPROGRESS)
+ return (-1);
+
+ /* Do whatever we want while the connect is taking place. */
+
+ if (n == 0)
+ goto done;
+ /* connect completed immediately */
+
+ FD_ZERO(&rset);
+ FD_SET(sockfd, &rset);
+ wset = rset;
+ tval.tv_sec = nsec;
+ tval.tv_usec = 0;
+ if ((n = select(sockfd + 1, &rset, &wset, NULL, nsec ? &tval : NULL))
+ == 0) {
+ sdb_close(sockfd); /* timeout */
+ errno = ETIMEDOUT;
+ return (-1);
+ }
+ if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+ len = sizeof(error);
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+ return (-1); /* Solaris pending error */
+ } else
+ D("select error: sockfd not set\n");
+
+ done:
+ if(fcntl(sockfd, F_SETFL, flags) == -1) { /* restore file status flags */
+ D("failed to restore file status flag for socket %d: (errno:%d)\n",
+ sockfd, errno);
+ }
+
+ if (error) {
+ sdb_close(sockfd); /* just in case */
+ errno = error;
+ return (-1);
+ }
+ return (0);
+}
+
+static int send_msg_to_localhost_from_guest(int local_port, char *request, int sock_type) {
+ int ret, s;
+ struct sockaddr_in server;
+ int connect_timeout = 1;
+ memset( &server, 0, sizeof(server) );
+ server.sin_family = AF_INET;
+ server.sin_port = htons(local_port);
+ server.sin_addr.s_addr = inet_addr(QEMU_FORWARD_IP);
+
+ D("try to send notification to host(%s:%d) using %s:[%s]\n", QEMU_FORWARD_IP, local_port, (sock_type == 0) ? "tcp" : "udp", request);
+
+ if (sock_type == 0) {
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ } else {
+ s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ }
+ if (s < 0) {
+ D("could not create socket\n");
+ return -1;
+ }
+ ret = connect_nonb(s, (struct sockaddr*) &server, sizeof(server), connect_timeout);
+ if (ret < 0) {
+ D("could not connect to server\n");
+ sdb_close(s);
+ return -1;
+ }
+ // writex handles EINTR and returns 0 if success
+ if (writex(s, request, strlen(request)) != 0) {
+ D("could not send notification request to host\n");
+ sdb_close(s);
+ return -1;
+ }
+ sdb_close(s);
+ D("sent notification request to host\n");
+
+ return 0;
+}
+
+static void notify_sdbd_startup() {
+ char buffer[512];
+ char request[512];
+
+ // send the request to sdbserver
+ char vm_name[256]={0,};
+ int base_port = get_emulator_forward_port();
+ int r = get_emulator_name(vm_name, sizeof vm_name);
+ int time = 0;
+ int try_limit_time = 60; // It would take 20 or more trials in slow VMs
+ if (base_port < 0 || r < 0) {
+ return;
+ }
+
+ // tell qemu sdbd is just started with udp
+ char sensord_buf[16];
+ while (time < try_limit_time) {
+ snprintf(sensord_buf, sizeof sensord_buf, "2\n");
+ if (send_msg_to_localhost_from_guest(base_port + 3, sensord_buf, 1) < 0) {
+ D("could not send sensord noti request, try again %dth\n", time+1);
+ } else {
+ // tell sdb server emulator's vms name
+ snprintf(request, sizeof request, "host:emulator:%d:%s",base_port + 1, vm_name);
+ snprintf(buffer, sizeof buffer, "%04x%s", strlen(request), request );
+
+ if (send_msg_to_localhost_from_guest(DEFAULT_SDB_PORT, buffer, 0) <0) {
+ D("could not send sdbd noti request. it might sdb server has not been started yet.\n");
+ } else {
+ break;
+ }
+
+ }
+ time ++;
+ sleep(1);
+ }
+}
+
+// send the "emulator" request to sdbserver
+static void notify_sdbd_startup_thread() {
+ char buffer[512];
+ char request[512];
+
+ char vm_name[256]={0,};
+ int base_port = get_emulator_forward_port();
+ int r = get_emulator_name(vm_name, sizeof vm_name);
+ int time = 0;
+ int try_limit_time = -1; // try_limit_time < 0 if unlimited
+ if (base_port < 0 || r < 0) {
+ return;
+ }
+
+ // XXX: Known issue - log collision
+ while (1) {
+ /* XXX: Known issue - timing issue
+ A request failure can happen at the starting up of a SDB server
+ (with very little probability)
+ If a SDB server establish a new connection and send a request
+ between D1 and D2, the request will fail.
+ Becuase when a SDB server gets a duplicated "emulator:" command,
+ it closes the existing transport connection.
+ */
+
+ // If there is any connected (via TCP/IP) SDB server, sleep 10 secs (D1)
+ if (get_connected_count(kTransportLocal) > 0) {
+ if (time >= 0) {
+ time = 0;
+ D("notify_sdbd_startup() success after %d trial(s)", time);
+ }
+ sleep(10);
+ continue;
+ }
+
+ // tell qemu sdbd is just started with udp
+ if (send_msg_to_localhost_from_guest(base_port + 3, "2\n", 1) < 0) {
+ D("could not send sensord noti request, try again %dth\n", time+1);
+ goto sleep_and_continue;
+ }
+
+ // tell sdb server emulator's vms name (D2)
+ snprintf(request, sizeof request, "host:emulator:%d:%s",base_port + 1, vm_name);
+ snprintf(buffer, sizeof buffer, "%04x%s", strlen(request), request );
+
+ if (get_connected_count(kTransportLocal) > 0) continue; // See comment above
+
+ if (send_msg_to_localhost_from_guest(DEFAULT_SDB_PORT, buffer, 0) <0) {
+ D("could not send sdbd noti request. it might sdb server has not been started yet.\n");
+ goto sleep_and_continue;
+ }
+
+ //LOGI("sdbd noti request sent.\n");
+
+sleep_and_continue:
+ time++;
+ sleep(1);
+ }
+}
+
void local_init(int port)
{
sdb_thread_t thr;
if(HOST) {
func = client_socket_thread;
} else {
+#if SDB_HOST
func = server_socket_thread;
+#else
+ /* For the sdbd daemon in the system image we need to distinguish
+ * between the device, and the emulator. */
+#if 0 /* tizen specific */
+ char is_qemu[PROPERTY_VALUE_MAX];
+ property_get("ro.kernel.qemu", is_qemu, "");
+ if (!strcmp(is_qemu, "1")) {
+ /* Running inside the emulator: use QEMUD pipe as the transport. */
+ func = qemu_socket_thread;
+ } else
+#endif
+ {
+ /* Running inside the device: use TCP socket as the transport. */
+ func = server_socket_thread;
+ }
+#endif // !SDB_HOST
}
D("transport: local %s init\n", HOST ? "client" : "server");
fatal_errno("cannot create local socket %s thread",
HOST ? "client" : "server");
}
+
+ /*
+ * wait until server socket thread made!
+ * get noti from server_socket_thread
+ */
+ if (is_emulator()) {
+ sdb_mutex_lock(®ister_noti_lock);
+ pthread_cond_wait(¬i_cond, ®ister_noti_lock);
+
+ // thread start
+ if(sdb_thread_create(&thr, notify_sdbd_startup_thread, NULL)) {
+ fatal("cannot create notify_sdbd_startup_thread");
+ notify_sdbd_startup(); // defensive code
+ }
+ sdb_mutex_unlock(®ister_noti_lock);
+ }
}
static void remote_kick(atransport *t)
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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"
#endif
-/* XXX better define? */
-#ifdef __ppc__
+#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)
{
-/*
- * Copyright (C) 2009 bsdroid project
- * Alexey Tarasov <tarasov@dodologics.com>
- *
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+/*
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/* usb scan debugging is waaaay too verbose */
#define DBGX(x...)
-static sdb_mutex_t usb_lock = SDB_MUTEX_INITIALIZER;
+SDB_MUTEX_DEFINE( usb_lock );
struct usb_handle
{
// DBGX("[ scanning %s ]\n", busname);
while((de = readdir(devdir))) {
- unsigned char devdesc[256];
+ unsigned char devdesc[4096];
unsigned char* bufptr = devdesc;
unsigned char* bufend;
struct usb_device_descriptor* device;
struct usb_endpoint_descriptor *ep1, *ep2;
unsigned zero_mask = 0;
unsigned vid, pid;
- size_t desclength;
+ unsigned int desclength;
if(badname(de->d_name)) continue;
snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
continue;
}
- vid = __le16_to_cpu(device->idVendor);
- pid = __le16_to_cpu(device->idProduct);
- pid = devdesc[10] | (devdesc[11] << 8);
+ vid = device->idVendor;
+ pid = device->idProduct;
DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
// should have config descriptor next
config = (struct usb_config_descriptor *)bufptr;
- // sdb needs 2nd configuration
+
+ /* tizen specific */
if (device->bNumConfigurations > 1) {
bufptr += config->wTotalLength;
config = (struct usb_config_descriptor *)bufptr;
}
bufptr += USB_DT_CONFIG_SIZE;
-
if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
D("usb_config_descriptor not found\n");
sdb_close(fd);
is_sdb_interface(vid, pid, interface->bInterfaceClass,
interface->bInterfaceSubClass, interface->bInterfaceProtocol)) {
- DBGX("looking for bulk endpoints\n");
+ D("looking for bulk endpoints\n");
// looks like SDB...
ep1 = (struct usb_endpoint_descriptor *)bufptr;
bufptr += USB_DT_ENDPOINT_SIZE;
continue;
}
/* aproto 01 needs 0 termination */
- if(interface->bInterfaceProtocol == 0x02) {
+ if(interface->bInterfaceProtocol == 0x01) {
zero_mask = ep1->wMaxPacketSize - 1;
}
h->reaper_thread = pthread_self();
sdb_mutex_unlock(&h->lock);
res = ioctl(h->desc, USBDEVFS_REAPURB, &out);
+ int saved_errno = errno;
sdb_mutex_lock(&h->lock);
h->reaper_thread = 0;
if(h->dead) {
break;
}
if(res < 0) {
- if(errno == EINTR) {
+ if(saved_errno == EINTR) {
continue;
}
D("[ reap urb - error ]\n");
usb_handle* usb = 0;
int n = 0;
char serial[256];
- int bConfigurationValue = 2; /* sdb needs 2nd configruation */
+ int bConfigurationValue = 2; /* tizen specific : sdb needs 2nd configruation */
/* Since Linux will not reassign the device ID (and dev_name)
** as long as the device is open, we can add to the list here
D("[ usb open read-only %s fd = %d]\n", usb->fname, usb->desc);
} else {
D("[ usb open %s fd = %d]\n", usb->fname, usb->desc);
+ /* tizen specific */
n = ioctl(usb->desc, USBDEVFS_RESET);
- if(n != 0) goto fail;
- ioctl(usb->desc, USBDEVFS_SETCONFIGURATION, &bConfigurationValue);
+ if(n != 0) {
+ D("[ usb reset failed %s fd = %d]\n", usb->fname, usb->desc);
+ goto fail;
+ }
+ n = ioctl(usb->desc, USBDEVFS_SETCONFIGURATION, &bConfigurationValue);
+ if (n != 0) {
+ D("[ usb set %d configuration failed %s fd = %d]\n", bConfigurationValue, usb->fname, usb->desc);
+ D("check kernel is supporting %dth configuration\n", bConfigurationValue);
+ }
+
n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
- if(n != 0) goto fail;
+ if(n != 0) {
+ D("[ usb claim failed %s fd = %d]\n", usb->fname, usb->desc);
+ goto fail;
+ }
}
/* read the device's serial number */
ctrl.wIndex = 0;
ctrl.wLength = sizeof(languages);
ctrl.data = languages;
+ ctrl.timeout = 1000;
result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
if (result > 0)
ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
ctrl.wValue = (USB_DT_STRING << 8) | serial_index;
- ctrl.wIndex = languages[i];
+ ctrl.wIndex = __le16_to_cpu(languages[i]);
ctrl.wLength = sizeof(buffer);
ctrl.data = buffer;
+ ctrl.timeout = 1000;
result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
if (result > 0) {
// skip first word, and copy the rest to the serial string, changing shorts to bytes.
result /= 2;
for (i = 1; i < result; i++)
- serial[i - 1] = buffer[i];
+ serial[i - 1] = __le16_to_cpu(buffer[i]);
serial[i - 1] = 0;
break;
}
fatal_errno("cannot create input thread");
}
}
-
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
D("[ usb_thread - opening device ]\n");
do {
/* XXX use inotify? */
- fd = unix_open("/dev/samsung_sdb", O_RDWR);
-#if 0
+ fd = unix_open(USB_NODE_FILE, O_RDWR); /* tizen-specific */
if (fd < 0) {
// to support older kernels
- fd = unix_open("/dev/android", O_RDWR);
+ //fd = unix_open("/dev/android", O_RDWR);
+ D("[ opening %s device failed ]\n", USB_NODE_FILE);
}
-#endif
if (fd < 0) {
sdb_sleep_ms(1000);
}
} while (fd < 0);
D("[ opening device succeeded ]\n");
- close_on_exec(fd);
+ if (close_on_exec(fd) < 0) {
+ D("[closing fd exec failed ]\n");
+ }
usb->fd = fd;
D("[ usb_thread - registering device ]\n");
{
int n;
- D("[ write %d ]\n", len);
+ D("about to write (fd=%d, len=%d)\n", h->fd, len);
n = sdb_write(h->fd, data, len);
if(n != len) {
- D("ERROR: n = %d, errno = %d (%s)\n",
- n, errno, strerror(errno));
+ D("ERROR: fd = %d, n = %d, errno = %d\n",
+ h->fd, n, errno);
return -1;
}
- D("[ done ]\n");
+ D("[ done fd=%d ]\n", h->fd);
return 0;
}
{
int n;
- D("[ read %d ]\n", len);
+ D("about to read (fd=%d, len=%d)\n", h->fd, len);
n = sdb_read(h->fd, data, len);
if(n != len) {
- D("ERROR: n = %d, errno = %d (%s)\n",
- n, errno, strerror(errno));
+ D("ERROR: fd = %d, n = %d, errno = %d\n",
+ h->fd, n, errno);
return -1;
}
+ D("[ done fd=%d ]\n", h->fd);
return 0;
}
{
usb_handle *h;
sdb_thread_t tid;
-#if 0 //eric
- int fd;
-#endif
+// int fd;
+
h = calloc(1, sizeof(usb_handle));
+ if (h == NULL) {
+ D("cannot allocate usb handle");
+ return;
+ }
h->fd = -1;
sdb_cond_init(&h->notify, 0);
sdb_mutex_init(&h->lock, 0);
// We never touch this file again - just leave it open
// indefinitely so the kernel will know when we are running
// and when we are not.
-#if 0 //eric
+#if 0 /* tizen specific */
fd = unix_open("/dev/android_sdb_enable", O_RDWR);
if (fd < 0) {
D("failed to open /dev/android_sdb_enable\n");
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
// 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_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_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_KYOCERA,
VENDOR_ID_PANTECH,
VENDOR_ID_QUALCOMM,
+ VENDOR_ID_OTGV,
VENDOR_ID_NEC,
VENDOR_ID_PMC,
VENDOR_ID_TOSHIBA,
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]))
/* 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) >= len) {
+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_SDB_INI) >= (signed)len) {
return 1;
}
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
void usb_vendors_init(void);
-#endif
\ No newline at end of file
+#endif
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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.
ret->prev = ret;
// Create interface.
- ret->sdb_interface = AdbCreateInterfaceByName(interface_name);
+ ret->sdb_interface = SdbCreateInterfaceByName(interface_name);
if (NULL == ret->sdb_interface) {
free(ret);
// Open read pipe (endpoint)
ret->sdb_read_pipe =
- AdbOpenDefaultBulkReadEndpoint(ret->sdb_interface,
- AdbOpenAccessTypeReadWrite,
- AdbOpenSharingModeReadWrite);
+ SdbOpenDefaultBulkReadEndpoint(ret->sdb_interface,
+ SdbOpenAccessTypeReadWrite,
+ SdbOpenSharingModeReadWrite);
if (NULL != ret->sdb_read_pipe) {
// Open write pipe (endpoint)
ret->sdb_write_pipe =
- AdbOpenDefaultBulkWriteEndpoint(ret->sdb_interface,
- AdbOpenAccessTypeReadWrite,
- AdbOpenSharingModeReadWrite);
+ 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
- AdbGetInterfaceName(ret->sdb_interface,
+ SdbGetInterfaceName(ret->sdb_interface,
NULL,
&name_len,
true);
if (NULL != ret->interface_name) {
// Now save the name
- if (AdbGetInterfaceName(ret->sdb_interface,
+ if (SdbGetInterfaceName(ret->sdb_interface,
ret->interface_name,
&name_len,
true)) {
}
// Something went wrong.
- errno = GetLastError();
+ int saved_errno = GetLastError();
usb_cleanup_handle(ret);
free(ret);
- SetLastError(errno);
+ SetLastError(saved_errno);
return NULL;
}
int usb_write(usb_handle* handle, const void* data, int len) {
- unsigned long time_out = 500 + len * 8;
+ unsigned long time_out = 5000;
unsigned long written = 0;
int ret;
D("usb_write %d\n", len);
if (NULL != handle) {
// Perform write
- ret = AdbWriteEndpointSync(handle->sdb_write_pipe,
+ ret = SdbWriteEndpointSync(handle->sdb_write_pipe,
(void*)data,
(unsigned long)len,
&written,
time_out);
- errno = GetLastError();
+ int saved_errno = GetLastError();
if (ret) {
// Make sure that we've written what we were asked to write
if (written == (unsigned long)len) {
if(handle->zero_mask && (len & handle->zero_mask) == 0) {
// Send a zero length packet
- AdbWriteEndpointSync(handle->sdb_write_pipe,
+ SdbWriteEndpointSync(handle->sdb_write_pipe,
(void*)data,
0,
&written,
}
} else {
// assume ERROR_INVALID_HANDLE indicates we are disconnected
- if (errno == ERROR_INVALID_HANDLE)
+ if (saved_errno == ERROR_INVALID_HANDLE)
usb_kick(handle);
}
+ errno = saved_errno;
} else {
D("usb_write NULL handle\n");
SetLastError(ERROR_INVALID_HANDLE);
}
int usb_read(usb_handle *handle, void* data, int len) {
- unsigned long time_out = 500 + len * 8;
+ unsigned long time_out = 0;
unsigned long read = 0;
int ret;
while (len > 0) {
int xfer = (len > 4096) ? 4096 : len;
- ret = AdbReadEndpointSync(handle->sdb_read_pipe,
+ ret = SdbReadEndpointSync(handle->sdb_read_pipe,
(void*)data,
(unsigned long)xfer,
&read,
time_out);
- errno = GetLastError();
- D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
+ 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 if (errno != ERROR_SEM_TIMEOUT) {
+ } else {
// assume ERROR_INVALID_HANDLE indicates we are disconnected
- if (errno == ERROR_INVALID_HANDLE)
+ if (saved_errno == ERROR_INVALID_HANDLE)
usb_kick(handle);
break;
}
+ errno = saved_errno;
}
} else {
D("usb_read NULL handle\n");
if (NULL != handle->interface_name)
free(handle->interface_name);
if (NULL != handle->sdb_write_pipe)
- AdbCloseHandle(handle->sdb_write_pipe);
+ SdbCloseHandle(handle->sdb_write_pipe);
if (NULL != handle->sdb_read_pipe)
- AdbCloseHandle(handle->sdb_read_pipe);
+ SdbCloseHandle(handle->sdb_read_pipe);
if (NULL != handle->sdb_interface)
- AdbCloseHandle(handle->sdb_interface);
+ SdbCloseHandle(handle->sdb_interface);
handle->interface_name = NULL;
handle->sdb_write_pipe = NULL;
// Check vendor and product id first
USB_DEVICE_DESCRIPTOR device_desc;
- if (!AdbGetUsbDeviceDescriptor(handle->sdb_interface,
+ if (!SdbGetUsbDeviceDescriptor(handle->sdb_interface,
&device_desc)) {
return 0;
}
// Then check interface properties
USB_INTERFACE_DESCRIPTOR interf_desc;
- if (!AdbGetUsbInterfaceDescriptor(handle->sdb_interface,
+ if (!SdbGetUsbInterfaceDescriptor(handle->sdb_interface,
&interf_desc)) {
return 0;
}
interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
if(interf_desc.bInterfaceProtocol == 0x01) {
- AdbEndpointInformation endpoint_info;
+ SdbEndpointInformation endpoint_info;
// assuming zero is a valid bulk endpoint ID
- if (AdbGetEndpointInformation(handle->sdb_interface, 0, &endpoint_info)) {
+ if (SdbGetEndpointInformation(handle->sdb_interface, 0, &endpoint_info)) {
handle->zero_mask = endpoint_info.max_packet_size - 1;
}
}
usb_handle* handle = NULL;
char entry_buffer[2048];
char interf_name[2048];
- AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
+ 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 =
- AdbEnumInterfaces(usb_class_id, true, true, true);
+ SdbEnumInterfaces(usb_class_id, true, true, true);
if (NULL == enum_handle)
return;
- while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
+ 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.
D("adding a new device %s\n", interf_name);
char serial_number[512];
unsigned long serial_number_len = sizeof(serial_number);
- if (AdbGetSerialNumber(handle->sdb_interface,
+ if (SdbGetSerialNumber(handle->sdb_interface,
serial_number,
&serial_number_len,
true)) {
entry_buffer_size = sizeof(entry_buffer);
}
- AdbCloseHandle(enum_handle);
+ SdbCloseHandle(enum_handle);
}
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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 "utils.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <errno.h>
+#define STRING_MAXLEN 1024
char*
buff_addc (char* buff, char* buffEnd, int c)
{
}
return buff;
}
+
+char *str_trim(const char* string)
+{
+ const char* s = string;
+ const char* e = string + (strlen(string) - 1);
+ char* ret;
+
+ while(*s == ' ' || *s == '\t') // ltrim
+ s++;
+ while(*e == ' ' || *e == '\t') // rtrim
+ e--;
+
+ ret = strdup(s);
+ if (ret == NULL) {
+ fprintf(stderr, "failed to strdup");
+ return NULL;
+ }
+ ret[e - s + 1] = 0;
+
+ return ret;
+}
+
+int spawn(char* program, char** arg_list)
+{
+ pid_t pid;
+ int ret;
+
+ if ((pid = fork()) < 0) {
+ fprintf(stderr, "couldn't fork: %d\n", errno);
+ exit(1);
+ } else if (pid == 0) {
+ if ((pid = fork()) < 0) {
+ fprintf(stderr, "couldn't fork: %d\n", errno);
+ exit(1);
+ } else if (pid > 0) {
+ // init takes the process, and the process is not able to be zombie
+ exit(0);
+ }
+ execvp (program, arg_list);
+ fprintf(stderr, "failed to spawn: never reach here!:%s\n", program);
+ exit(0);
+ }
+ if (waitpid(pid, &ret, 0) != pid) {
+ fprintf(stderr, "failed to wait pid\n");
+ }
+
+ return pid;
+}
+
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * 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
+ * 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,
+ * 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_UTILS_H
#define _SDB_UTILS_H
#define BUFF_DECL(_buff,_cursor,_end,_size) \
char _buff[_size], *_cursor=_buff, *_end = _cursor + (_size)
+char *str_trim(const char* string);
+
+/*
+ * spawn a process and returns the process id of the new spawned process.
+ * it is working as async.
+ */
+int spawn(char* program, char** arg_list);
+
#endif /* _SDB_UTILS_H */
--- /dev/null
+TMP_FILE=99-samsung-device.rules
+echo "# Add a udev rules when you want to develop a Tizen application with your device." >> $TMP_FILE
+echo "# Use this format to add each vendor to the file:" >> $TMP_FILE
+echo "# SUBSYSTEM==\"usb\", ATTR{idVendor}==\"04e8\", ATTRS{idProduct}==\"6864\", MODE=\"0666\", GROUP=\"plugdev\"" >> $TMP_FILE
+echo "# In the example, the vendor ID is for Samsung manufacture. The mode specifies read/write permissions, and group defines which Unix group owns the device node." >> $TMP_FILE
+echo "#" >> $TMP_FILE
+echo "# Contact : Kangho Kim <kh5325.kim@samsung.com>, Yoonki Park<yoonki.park@samsung.com>, Ho Namkoong <ho.namkoong@samsung.com>" >> $TMP_FILE
+echo "# See also udev(7) for an overview of rule syntax." >> $TMP_FILE
+echo "" >> $TMP_FILE
+echo "# Samsung" >> $TMP_FILE
+echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"04e8\", ATTRS{idProduct}==\"6864\", MODE=\"0666\", GROUP=\"plugdev\"" >> $TMP_FILE
+echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"04e8\", ATTRS{idProduct}==\"6863\", MODE=\"0666\", GROUP=\"plugdev\"" >> $TMP_FILE
+chmod +x $TMP_FILE
+#gksudo mv ${TMP_FILE} /etc/udev/rules.d/
--- /dev/null
+/*\r
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the License);\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an AS IS BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* a simple test program, connects to SDB server, and opens a track-devices session */\r
+#include <netdb.h>\r
+#include <sys/socket.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <errno.h>\r
+#include <memory.h>\r
+\r
+static void\r
+panic( const char* msg )\r
+{\r
+ fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));\r
+ exit(1);\r
+}\r
+\r
+static int\r
+unix_write( int fd, const char* buf, int len )\r
+{\r
+ int result = 0;\r
+ while (len > 0) {\r
+ int len2 = write(fd, buf, len);\r
+ if (len2 < 0) {\r
+ if (errno == EINTR || errno == EAGAIN)\r
+ continue;\r
+ return -1;\r
+ }\r
+ result += len2;\r
+ len -= len2;\r
+ buf += len2;\r
+ }\r
+ return result;\r
+}\r
+\r
+static int unix_read( int fd, char* buf, int len )\r
+{\r
+ int result = 0;\r
+ while (len > 0) {\r
+ int len2 = read(fd, buf, len);\r
+ if (len2 < 0) {\r
+ if (errno == EINTR || errno == EAGAIN)\r
+ continue;\r
+ return -1;\r
+ }\r
+ result += len2;\r
+ len -= len2;\r
+ buf += len2;\r
+ }\r
+ return result;\r
+}\r
+\r
+int main( void )\r
+{\r
+ int ret, s;\r
+ struct sockaddr_in server;\r
+ char buffer[1024];\r
+ const char* transport = "host:transport-a";\r
+ const char* request = "cs:";\r
+ int len;\r
+\r
+ memset( &server, 0, sizeof(server) );\r
+ server.sin_family = AF_INET;\r
+ server.sin_port = htons(26099);\r
+ server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\r
+\r
+ s = socket( PF_INET, SOCK_STREAM, 0 );\r
+ ret = connect( s, (struct sockaddr*) &server, sizeof(server) );\r
+ if (ret < 0) panic( "could not connect to server" );\r
+\r
+ /* send the transport */\r
+ len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(transport), transport );\r
+ if (unix_write(s, buffer, len) < 0)\r
+ panic( "could not send request" );\r
+\r
+ /* read the OKAY answer */\r
+ if (unix_read(s, buffer, 4) != 4)\r
+ panic( "could not read request" );\r
+\r
+ /* send the request */\r
+ len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );\r
+ if (unix_write(s, buffer, len) < 0)\r
+ panic( "could not send request" );\r
+\r
+ /* read the OKAY answer */\r
+ if (unix_read(s, buffer, 4) != 4)\r
+ panic( "could not read request" );\r
+\r
+ printf( "server answer: %.*s\n", 4, buffer );\r
+\r
+ /* now loop */\r
+ for (;;) {\r
+ memset(buffer, 0, sizeof(buffer));\r
+ if (unix_read(s, buffer, 30) < 0)\r
+ panic("could not read length");\r
+\r
+ printf( "server answer: %s\n",buffer );\r
+ break;\r
+ }\r
+ close(s);\r
+}\r
+/*
+ * 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 <netdb.h>
#include <sys/socket.h>
-/* a simple test program, connects to ADB server, and opens a track-devices session */
+/*
+ * 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 <netdb.h>
#include <sys/socket.h>
#include <stdio.h>