tizen 2.3.1 release tizen_2.3.1 submit/tizen_2.3.1/20150915.082106 tizen_2.3.1_release
authorjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:38:15 +0000 (22:38 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Tue, 8 Sep 2015 13:38:15 +0000 (22:38 +0900)
75 files changed:
AUTHORS [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile
NOTICE [new file with mode: 0644]
packaging/sdbd.changes [new file with mode: 0644]
packaging/sdbd.service [new file with mode: 0644]
packaging/sdbd.spec
packaging/sdbd_device.service [new file with mode: 0644]
packaging/sdbd_emulator.service [new file with mode: 0644]
script/S06sdbd [deleted file]
script/profile_command [new file with mode: 0755]
script/sdbd [deleted file]
script/sdk_launch [new file with mode: 0755]
sdbd.manifest [new file with mode: 0644]
src/MODULE_LICENSE_APACHE2 [deleted file]
src/TizenConfig.h [new file with mode: 0644]
src/clear_vars.mk [new file with mode: 0644]
src/commandline.c
src/console.c
src/fdevent.c
src/fdevent.h
src/file_sync_client.c
src/file_sync_service.c
src/file_sync_service.h
src/fileutils.c [new file with mode: 0644]
src/fileutils.h [new file with mode: 0644]
src/framebuffer_service.c [deleted file]
src/get_my_path_darwin.c
src/get_my_path_freebsd.c
src/get_my_path_linux.c
src/get_my_path_windows.c
src/jdwp_service.c
src/mutex_list.h
src/properties.c [new file with mode: 0644]
src/properties.h [new file with mode: 0644]
src/qemu_pipe.h [new file with mode: 0644]
src/remount_service.c [deleted file]
src/sdb.c
src/sdb.h
src/sdb_client.c
src/sdb_client.h
src/sdktools.c [new file with mode: 0644]
src/sdktools.h [new file with mode: 0644]
src/services.c
src/socket_inaddr_any_server.c
src/socket_local.h
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
src/sockets.c
src/sockets.h
src/strutils.c [new file with mode: 0644]
src/strutils.h [new file with mode: 0644]
src/sysdeps.h
src/sysdeps_win32.c
src/threads.h [new file with mode: 0644]
src/transport.c
src/transport.h [new file with mode: 0644]
src/transport_local.c
src/transport_usb.c
src/usb_libusb.c
src/usb_linux.c
src/usb_linux_client.c
src/usb_osx.c
src/usb_vendors.c
src/usb_vendors.h
src/usb_windows.c
src/utils.c
src/utils.h
test/install_udev.sh [new file with mode: 0755]
test/test_inoti_service.c [new file with mode: 0644]
test/test_track_devices.c [moved from src/test_track_devices.c with 79% similarity]
test/test_track_jdwp.c [moved from src/test_track_jdwp.c with 77% similarity]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..9e88574
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Kangho Kim <kh5325.kim@samsung.com>
+Ho Namkoong <ho.namkoong@samsung.com>
+Yoonki Park <yoonki.park@samsung.com>
+HyunGoo Kang <hyungoo1.kang@samsung.com>
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..a06208b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+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.
+
index efc0c6a..3e48fd7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,30 +1,13 @@
-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 \
@@ -35,9 +18,6 @@ SDBD_SRC_FILES := \
        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 \
@@ -45,17 +25,18 @@ SDBD_SRC_FILES := \
        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)))
@@ -80,25 +61,13 @@ endif
 
 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)/*
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..4297ee3
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
diff --git a/packaging/sdbd.changes b/packaging/sdbd.changes
new file mode 100644 (file)
index 0000000..abe5d97
--- /dev/null
@@ -0,0 +1,15 @@
+* 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
diff --git a/packaging/sdbd.service b/packaging/sdbd.service
new file mode 100644 (file)
index 0000000..76a066e
--- /dev/null
@@ -0,0 +1,8 @@
+[Unit]
+Description=sdbd
+
+[Service]
+Type=forking
+PIDFile=/tmp/.sdbd.pid
+RemainAfterExit=yes
+ExecStart=/usr/sbin/sdbd
index d604e5a..ef4e34a 100644 (file)
@@ -1,14 +1,23 @@
 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
@@ -16,22 +25,45 @@ Description: SDB daemon
 %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
+
diff --git a/packaging/sdbd_device.service b/packaging/sdbd_device.service
new file mode 100644 (file)
index 0000000..1570a3d
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=sdbd
+
+[Service]
+Type=forking
+Environment=DISPLAY=:0
+PIDFile=/tmp/.sdbd.pid
+RemainAfterExit=yes
+ExecStart=/usr/sbin/sdbd
diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service
new file mode 100644 (file)
index 0000000..fde66ac
--- /dev/null
@@ -0,0 +1,14 @@
+[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
+
diff --git a/script/S06sdbd b/script/S06sdbd
deleted file mode 100755 (executable)
index 6a05d55..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-/etc/init.d/sdbd start
diff --git a/script/profile_command b/script/profile_command
new file mode 100755 (executable)
index 0000000..ce52681
--- /dev/null
@@ -0,0 +1,112 @@
+#!/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
diff --git a/script/sdbd b/script/sdbd
deleted file mode 100755 (executable)
index 9f477bb..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#! /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
diff --git a/script/sdk_launch b/script/sdk_launch
new file mode 100755 (executable)
index 0000000..5537feb
--- /dev/null
@@ -0,0 +1,177 @@
+#!/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
diff --git a/sdbd.manifest b/sdbd.manifest
new file mode 100644 (file)
index 0000000..02b5aed
--- /dev/null
@@ -0,0 +1,36 @@
+<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>
diff --git a/src/MODULE_LICENSE_APACHE2 b/src/MODULE_LICENSE_APACHE2
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/TizenConfig.h b/src/TizenConfig.h
new file mode 100644 (file)
index 0000000..81d36f3
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * 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*/
diff --git a/src/clear_vars.mk b/src/clear_vars.mk
new file mode 100644 (file)
index 0000000..ee28f21
--- /dev/null
@@ -0,0 +1,107 @@
+###########################################################
+## 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))
index 9ab5daf..7b6f7a9 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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;
 
@@ -85,36 +84,51 @@ void help()
     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"
         );
 }
 
@@ -157,7 +171,9 @@ static void read_and_dump(int fd)
     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;
         }
@@ -171,6 +187,34 @@ static void read_and_dump(int fd)
     }
 }
 
+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;
@@ -185,7 +229,9 @@ static void *stdin_read_thread(void *x)
 
     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;
@@ -265,7 +311,83 @@ static void format_host_command(char* buffer, size_t  buflen, const char* comman
         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];
@@ -448,18 +570,14 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv)
 {
     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;
@@ -477,6 +595,109 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv)
     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)
 {
@@ -623,6 +844,7 @@ int sdb_commandline(int argc, char **argv)
     char buf[4096];
     int no_daemon = 0;
     int is_daemon = 0;
+    int is_server = 0;
     int persist = 0;
     int r;
     int quote;
@@ -659,7 +881,9 @@ int sdb_commandline(int argc, char **argv)
 
     /* 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 */
@@ -703,10 +927,11 @@ int sdb_commandline(int argc, char **argv)
         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 {
@@ -718,11 +943,28 @@ int sdb_commandline(int argc, char **argv)
         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")) {
@@ -731,6 +973,22 @@ int sdb_commandline(int argc, char **argv)
         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 {
@@ -738,63 +996,49 @@ int sdb_commandline(int argc, char **argv)
         }
     }
 
-    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]);
@@ -813,9 +1057,12 @@ int sdb_commandline(int argc, char **argv)
         }
 
         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 {
@@ -828,6 +1075,11 @@ int sdb_commandline(int argc, char **argv)
                 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;
             }
         }
@@ -842,66 +1094,75 @@ int sdb_commandline(int argc, char **argv)
         }
         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();
@@ -929,8 +1190,34 @@ int sdb_commandline(int argc, char **argv)
     }
 
     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")) {
@@ -943,49 +1230,54 @@ int sdb_commandline(int argc, char **argv)
         }
     }
 
-//    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 */
 
@@ -1015,25 +1307,33 @@ int sdb_commandline(int argc, char **argv)
         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], "/?")) {
@@ -1042,7 +1342,11 @@ int sdb_commandline(int argc, char **argv)
     }
 
     if(!strcmp(argv[0], "version")) {
-        version(stdout);
+        if (ttype == kTransportUsb || ttype == kTransportLocal) {
+            version_sdbd(ttype, serial);
+        } else {
+            version(stdout);
+        }
         return 0;
     }
 
@@ -1069,7 +1373,9 @@ static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
     }
 
     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
@@ -1142,6 +1448,81 @@ static int pm_command(transport_type transport, char* serial,
     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
@@ -1160,7 +1541,6 @@ int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
     return pm_command(transport, serial, argc, argv);
 }
 
-#if 0 //eric
 static int delete_file(transport_type transport, char* serial, char* filename)
 {
     char buf[4096];
@@ -1175,51 +1555,164 @@ static int delete_file(transport_type transport, char* serial, char* filename)
     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);
+}
index fb7ad7b..2926b5c 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * 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"
index c179b20..ca1bf3c 100644 (file)
@@ -1,19 +1,20 @@
-/* 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, ...)
 {
@@ -45,15 +56,28 @@ 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
 
@@ -67,6 +91,7 @@ static void dump_fde(fdevent *fde, const char *info)
 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,
@@ -270,10 +295,73 @@ static void fdevent_update(fdevent *fde, unsigned events)
         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;
@@ -284,33 +372,56 @@ static void fdevent_process()
     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
@@ -350,14 +461,14 @@ static void fdevent_unregister(fdevent *fde)
     }
 
     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);
     }
 }
 
@@ -394,6 +505,74 @@ static fdevent *fdevent_plist_dequeue(void)
     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));
@@ -412,16 +591,19 @@ void fdevent_destroy(fdevent *fde)
     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");
@@ -437,7 +619,7 @@ void fdevent_remove(fdevent *fde)
 
     if(fde->state & FDE_ACTIVE) {
         fdevent_disconnect(fde);
-        dump_fde(fde, "disconnect");    
+        dump_fde(fde, "disconnect");
         fdevent_unregister(fde);
     }
 
@@ -484,23 +666,35 @@ void fdevent_del(fdevent *fde, unsigned events)
         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);
         }
     }
 }
-
index 6b7e7ec..a6db9ea 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -70,6 +70,8 @@ struct fdevent
     fdevent *prev;
 
     int fd;
+    int force_eof;
+
     unsigned short state;
     unsigned short events;
 
index 135b0eb..0e80efd 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -24,9 +24,8 @@
 #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"
@@ -35,6 +34,7 @@
 
 static unsigned total_bytes;
 static long long start_time;
+extern const char* get_basename(const char* filename);
 
 static long long NOW()
 {
@@ -50,7 +50,7 @@ static void BEGIN()
     start_time = NOW();
 }
 
-static void END()
+static void END(const char* filename)
 {
     long long t = NOW() - start_time;
     if(total_bytes == 0) return;
@@ -58,11 +58,13 @@ static void END()
     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;
@@ -310,9 +312,8 @@ static int sync_send(int fd, const char *lpath, const char *rpath,
 
     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;
@@ -367,9 +368,8 @@ static int sync_send(int fd, const char *lpath, const char *rpath,
             free(file_buffer);
             return 1;
         }
-#endif
     }
-
+#endif
     msg.req.id = ID_SEND;
     msg.req.namelen = htoll(len + r);
 
@@ -644,12 +644,13 @@ static int local_build_list(copyinfo **filelist,
         } 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;
@@ -741,11 +742,14 @@ static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, i
 }
 
 
-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) {
@@ -764,13 +768,14 @@ int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
         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
@@ -782,22 +787,36 @@ int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
                 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;
 }
 
 
@@ -959,7 +978,8 @@ int do_sync_pull(const char *rpath, const char *lpath)
         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;
     }
 
@@ -986,7 +1006,7 @@ int do_sync_pull(const char *rpath, const char *lpath)
         if(sync_recv(fd, rpath, lpath)) {
             return 1;
         } else {
-            END();
+            END(get_basename(rpath));
             sync_quit(fd);
             return 0;
         }
@@ -995,12 +1015,12 @@ int do_sync_pull(const char *rpath, const char *lpath)
         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;
     }
 }
@@ -1019,7 +1039,7 @@ int do_sync_sync(const char *lpath, const char *rpath, int listonly)
     if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
         return 1;
     } else {
-        END();
+        END(get_basename(lpath));
         sync_quit(fd);
         return 0;
     }
index d01f314..bd953d8 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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;
         }
@@ -65,10 +166,12 @@ static int do_stat(int s, const char *path)
 
     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);
@@ -97,16 +200,21 @@ static int do_list(int s, const char *path)
     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);
@@ -115,6 +223,7 @@ static int do_list(int s, const char *path)
 
             if(writex(s, &msg.dent, sizeof(msg.dent)) ||
                writex(s, de->d_name, len)) {
+                closedir(d);
                 return -1;
             }
         }
@@ -150,10 +259,43 @@ static int fail_message(int s, const char *reason)
 
 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;
@@ -161,7 +303,7 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
 
     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) {
@@ -172,13 +314,12 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
             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);
@@ -192,15 +333,20 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
             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;
         }
     }
@@ -216,7 +362,14 @@ static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
         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:
@@ -227,7 +380,7 @@ 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;
@@ -251,7 +404,7 @@ static int handle_send_link(int s, char *path, char *buffer)
 
     ret = symlink(buffer, path);
     if(ret && errno == ENOENT) {
-        mkdirs(path);
+        mkdirs(noti_fd, path);
         ret = symlink(buffer, path);
     }
     if(ret) {
@@ -276,7 +429,7 @@ static int handle_send_link(int s, char *path, char *buffer)
 }
 #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;
@@ -294,11 +447,16 @@ static int do_send(int s, char *path, char *buffer)
 #endif
         // extracts file permission from stat.mode. (ex 100644 & 0777 = 644);
         mode &= 0777; // combination of (S_IRWXU | S_IRWXG | S_IRWXO)
+        mode |= S_IWOTH; // SDK requirement from N_SE-43337
     }
     if(!tmp || errno) {
         mode = 0644; // set default permission value in most of unix system.
         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);
@@ -306,7 +464,7 @@ static int do_send(int s, char *path, char *buffer)
 
 #ifdef HAVE_SYMLINKS
     if(is_link)
-        ret = handle_send_link(s, path, buffer);
+        ret = handle_send_link(s, noti_fd, path, buffer);
     else {
 #else
     {
@@ -318,8 +476,7 @@ static int do_send(int s, char *path, char *buffer)
 
         //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;
@@ -361,7 +518,41 @@ static int do_recv(int s, const char *path, char *buffer)
     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(&regex, sdk_sync_permit_rule[i].regx, REG_EXTENDED);
+        if(ret){
+            return 0;
+        }
+        // execute regular expression
+        ret = regexec(&regex, path, 0, NULL, 0);
+        if(!ret){
+            regfree(&regex);
+            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, &regex, buf, sizeof(buf));
+            D("regex match failed(%s): %s\n",sdk_sync_permit_rule[i].name, buf);
+        }
+    }
+    regfree(&regex);
     return 0;
 }
 
@@ -370,54 +561,99 @@ void file_sync_service(int fd, void *cookie)
     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);
 }
index 11ea06b..68059da 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -17,7 +17,7 @@
 #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)
@@ -77,8 +77,9 @@ typedef union {
 
 
 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);
 
diff --git a/src/fileutils.c b/src/fileutils.c
new file mode 100644 (file)
index 0000000..bb5071b
--- /dev/null
@@ -0,0 +1,49 @@
+#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
+}
diff --git a/src/fileutils.h b/src/fileutils.h
new file mode 100644 (file)
index 0000000..4debc92
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _FILEUTILS_H_
+#define _FILEUTILS_H_
+
+int sdb_chmod(const char *path, mode_t mode, int recursive);
+#endif
+
diff --git a/src/framebuffer_service.c b/src/framebuffer_service.c
deleted file mode 100644 (file)
index acf8173..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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);
-}
index 5b95d15..880ccfd 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
index b06ec66..628a2b0 100644 (file)
@@ -1,17 +1,14 @@
 /*
- * 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.
index 179c3dd..08ba668 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
index ddf2816..630e4d1 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
index 6f22cdb..6a85391 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * 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
@@ -5,6 +20,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 /* here's how these things work.
 
@@ -320,6 +336,7 @@ jdwp_process_event( int  socket, unsigned  events, void*  _proc )
             struct iovec     iov;
             char             dummy = '!';
             char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
+            int flags;
 
             iov.iov_base       = &dummy;
             iov.iov_len        = 1;
@@ -337,10 +354,27 @@ jdwp_process_event( int  socket, unsigned  events, void*  _proc )
             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",
@@ -354,6 +388,12 @@ jdwp_process_event( int  socket, unsigned  events, void*  _proc )
             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 );
         }
@@ -474,6 +514,7 @@ jdwp_control_init( JdwpControl*  control,
 
     /* 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;
@@ -706,4 +747,3 @@ init_jdwp(void)
 }
 
 #endif /* !SDB_HOST */
-
index 8b62206..3e55e9f 100644 (file)
@@ -1,8 +1,26 @@
-/* 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)
@@ -11,4 +29,13 @@ SDB_MUTEX(local_transports_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
diff --git a/src/properties.c b/src/properties.c
new file mode 100644 (file)
index 0000000..c187d30
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * 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
diff --git a/src/properties.h b/src/properties.h
new file mode 100644 (file)
index 0000000..08f9d18
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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
diff --git a/src/qemu_pipe.h b/src/qemu_pipe.h
new file mode 100644 (file)
index 0000000..5d6e87e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 */
diff --git a/src/remount_service.c b/src/remount_service.c
deleted file mode 100644 (file)
index c6332cd..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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);
-}
-
index d0b324d..072f05b 100644 (file)
--- a/src/sdb.c
+++ b/src/sdb.c
@@ -1,14 +1,14 @@
 /*
- * 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";
@@ -70,7 +100,7 @@ void fatal_errno(const char *fmt, ...)
 {
     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);
@@ -104,6 +134,9 @@ void  sdb_trace_init(void)
         { "sysdeps", TRACE_SYSDEPS },
         { "transport", TRACE_TRANSPORT },
         { "jdwp", TRACE_JDWP },
+        { "services", TRACE_SERVICES },
+        { "properties", TRACE_PROPERTIES },
+        { "sdktools", TRACE_SDKTOOLS },
         { NULL, 0 }
     };
 
@@ -141,6 +174,60 @@ void  sdb_trace_init(void)
     }
 }
 
+#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)
 {
@@ -152,7 +239,10 @@ apacket *get_apacket(void)
 
 void put_apacket(apacket *p)
 {
-    free(p);
+    if (p != NULL) {
+        free(p);
+        p = NULL;
+    }
 }
 
 void handle_online(void)
@@ -234,9 +324,29 @@ static void send_connect(atransport *t)
     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? */
@@ -245,6 +355,21 @@ static void send_connect(atransport *t)
 #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) {
@@ -263,6 +388,105 @@ static char *connection_state_name(atransport *t)
     }
 }
 
+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;
@@ -309,6 +533,13 @@ void parse_banner(char *banner, atransport *t)
         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;
 }
 
@@ -316,7 +547,10 @@ void handle_packet(apacket *p, atransport *t)
 {
     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);
 
@@ -344,17 +578,22 @@ void handle_packet(apacket *p, atransport *t)
         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;
@@ -419,7 +658,9 @@ static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
         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) {
@@ -577,7 +818,9 @@ static int install_listener(const char *local_name, const char *connect_to, atra
         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 {
@@ -603,14 +846,6 @@ nomem:
     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)
 {
@@ -652,14 +887,24 @@ void start_logging(void)
     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
 }
@@ -671,28 +916,43 @@ void start_device_log(void)
     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) {
@@ -708,21 +968,20 @@ 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
@@ -844,9 +1103,10 @@ int launch_server(int server_port)
         // 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') {
@@ -873,19 +1133,140 @@ void build_local_name(char* target_str, size_t target_size, int server_port)
   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
 
@@ -904,60 +1285,31 @@ int sdb_main(int is_daemon, int server_port)
         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);
         }
 
@@ -967,40 +1319,33 @@ int sdb_main(int is_daemon, int server_port)
         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)
@@ -1015,6 +1360,8 @@ int sdb_main(int is_daemon, int server_port)
         start_logging();
     }
 
+    D("Event loop starting\n");
+
     fdevent_loop();
 
     usb_cleanup();
@@ -1030,7 +1377,7 @@ void connect_device(char* host, char* buffer, int buffer_size)
     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);
@@ -1054,14 +1401,14 @@ void connect_device(char* host, char* buffer, int buffer_size)
 
     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);
 }
 
@@ -1110,7 +1457,7 @@ void connect_emulator(char* port_spec, char* buffer, int buffer_size)
     }
 
     /* 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 {
@@ -1121,6 +1468,35 @@ void connect_emulator(char* port_spec, char* buffer, int buffer_size)
 }
 #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;
@@ -1151,7 +1527,7 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
             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);
@@ -1203,9 +1579,9 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
             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);
@@ -1242,10 +1618,20 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
         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
@@ -1311,23 +1697,31 @@ int recovery_mode = 0;
 
 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
 }
index e66f9e2..6e228fe 100644 (file)
--- a/src/sdb.h
+++ b/src/sdb.h
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -19,6 +19,8 @@
 
 #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;
@@ -84,6 +87,11 @@ struct asocket {
         */
     int    closing;
 
+        /* flag: quit adbd when both ends close the
+        ** local service socket
+        */
+    int    exit_on_close;
+
         /* the asocket we are connected to
         */
 
@@ -184,6 +192,7 @@ struct atransport
     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;
@@ -248,6 +257,7 @@ int sdb_main(int is_daemon, int server_port);
 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);
 
@@ -273,7 +283,7 @@ void init_usb_transport(atransport *t, usb_handle *usb, int state);
 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);
@@ -302,14 +312,39 @@ int       create_jdwp_connection_fd(int  jdwp_pid);
 #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);
@@ -317,13 +352,6 @@ 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
@@ -342,28 +370,64 @@ typedef enum {
     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
 
@@ -372,17 +436,27 @@ typedef enum {
 #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();
@@ -409,12 +483,31 @@ int connection_state(atransport *t);
 #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"
index 78b2f14..08766cd 100644 (file)
@@ -1,12 +1,26 @@
+/*
+ * 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>
 
@@ -204,6 +218,7 @@ int _sdb_connect(const char *service)
         return -1;
     }
 
+    D("_sdb_connect: return fd %d\n", fd);
     return fd;
 }
 
@@ -212,6 +227,7 @@ int sdb_connect(const char *service)
     // first query the sdb server's version
     int fd = _sdb_connect("host:version");
 
+    D("sdb_connect: service %s\n", service);
     if(fd == -2) {
         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                 __sdb_server_port);
@@ -268,6 +284,7 @@ int sdb_connect(const char *service)
     if(fd == -2) {
         fprintf(stderr,"** daemon still not running");
     }
+    D("sdb_connect: return fd %d\n", fd);
 
     return fd;
 error:
index 4cfdfbe..86e9ef1 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * 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_
 
@@ -19,6 +35,7 @@ int sdb_command(const char *service);
 ** 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.
diff --git a/src/sdktools.c b/src/sdktools.c
new file mode 100644 (file)
index 0000000..971e8d8
--- /dev/null
@@ -0,0 +1,592 @@
+#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(&regex, pkg_path_regx, REG_EXTENDED);
+    if (ret){
+        D("failed : recomp (error:%d)\n", ret);
+        return 0;
+    }
+
+    ret = regexec(&regex, path, 0, NULL, 0);
+    regfree(&regex);
+
+    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(&regex, pattern, REG_EXTENDED);
+    if(ret){ // not match
+        return 0;
+    }
+
+    // execute regular expression
+    ret = regexec(&regex, str, 0, NULL, 0);
+    if(!ret){
+        regfree(&regex);
+        return 1;
+    } else if( ret == REG_NOMATCH ){
+        //D("not valid application path\n");
+    } else{
+        //regerror(ret, &regex, buf, sizeof(buf));
+        //D("regex match failed: %s\n", buf);
+    }
+    regfree(&regex);
+    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;
+}
diff --git a/src/sdktools.h b/src/sdktools.h
new file mode 100644 (file)
index 0000000..eed1709
--- /dev/null
@@ -0,0 +1,54 @@
+#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
index 231aee5..93973f2 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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;
 
@@ -75,6 +81,8 @@ static void dns_service(int fd, void *cookie)
     sdb_close(fd);
 }
 #else
+
+#if 0
 extern int recovery_mode;
 
 static void recover_service(int s, void *cookie)
@@ -107,7 +115,7 @@ 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];
@@ -130,54 +138,47 @@ void restart_root_service(int fd, void *cookie)
         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;
 
@@ -189,6 +190,7 @@ void reboot_service(int fd, void *arg)
     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) {
@@ -196,18 +198,119 @@ void reboot_service(int fd, void *arg)
         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)
 {
@@ -249,7 +352,7 @@ static int create_service_thread(void (*func)(int, void *), 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;
     }
 
@@ -263,7 +366,7 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
         free(sti);
         sdb_close(s[0]);
         sdb_close(s[1]);
-        printf("cannot create service thread\n");
+        D("cannot create service thread\n");
         return -1;
     }
 
@@ -271,78 +374,415 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
     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)
 {
@@ -352,9 +792,24 @@ 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);
@@ -384,7 +839,7 @@ int service_to_fd(const char *name)
         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);
@@ -392,48 +847,56 @@ int service_to_fd(const char *name)
         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;
 }
index 1879822..10a84e6 100644 (file)
@@ -1,19 +1,19 @@
-/* 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"
 
@@ -47,7 +47,10 @@ int socket_inaddr_any_server(int port, int type)
     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);
index 45b9856..dc274ac 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
index a104062..559766c 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -38,7 +38,7 @@ int socket_local_client(const char *name, int namespaceId, int type)
 #include <sys/types.h>
 
 #include "socket_local.h"
-
+#include "strutils.h"
 #define LISTEN_BACKLOG 4
 
 /* Documented in header file. */
@@ -75,8 +75,8 @@ int socket_make_sockaddr_un(const char *name, int namespaceId,
                 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;
 
@@ -88,8 +88,8 @@ int socket_make_sockaddr_un(const char *name, int namespaceId,
                 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:
@@ -100,7 +100,7 @@ int socket_make_sockaddr_un(const char *name, int namespaceId,
                 goto error;
             }
 
-            strcpy(p_addr->sun_path, name);
+            s_strncpy(p_addr->sun_path, name, strlen(name));
         break;
         default:
             // invalid namespace id
index 8c4a93f..8f2ed9f 100644 (file)
@@ -1,19 +1,19 @@
-/* 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"
 
@@ -75,7 +75,9 @@ int socket_local_server_bind(int s, const char *name, int namespaceId)
     }
 
     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;
index 563caae..a25307b 100644 (file)
@@ -1,22 +1,22 @@
-/* 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
@@ -53,6 +57,92 @@ int socket_loopback_client(int port, int type)
     }
 
     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;
+}
index 7a31155..b6c186a 100644 (file)
@@ -1,19 +1,19 @@
-/* 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 */
@@ -87,6 +90,8 @@ int socket_loopback_server(int port, int type)
     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) {
@@ -97,23 +102,26 @@ int socket_loopback_server(int port, int type)
             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);
index b0c5a0f..1c0b23b 100644 (file)
@@ -1,22 +1,22 @@
-/* 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;
 
 }
-
index b4a7a19..629d56d 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -25,6 +25,7 @@
 
 #define  TRACE_TAG  TRACE_SOCKETS
 #include "sdb.h"
+#include "strutils.h"
 
 SDB_MUTEX_DEFINE( socket_list_lock );
 
@@ -65,8 +66,11 @@ asocket *find_local_socket(unsigned id)
     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);
 
@@ -149,7 +153,7 @@ static int local_socket_enqueue(asocket *s, apacket *p)
             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 {
@@ -196,6 +200,9 @@ static void local_socket_close(asocket *s)
 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
@@ -210,18 +217,28 @@ static void local_socket_destroy(asocket  *s)
     }
     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
@@ -240,6 +257,7 @@ static void local_socket_close_locked(asocket *s)
     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);
 }
 
@@ -247,6 +265,8 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
 {
     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.
     */
@@ -268,6 +288,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
                     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;
             }
@@ -283,6 +304,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
             ** we can now destroy it.
             */
         if (s->closing) {
+            D(" closing because 'closing' is set after write\n");
             s->close(s);
             return;
         }
@@ -305,6 +327,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
 
         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;
@@ -319,13 +342,15 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
             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
@@ -347,8 +372,9 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
                 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);
         }
     }
@@ -359,6 +385,8 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
             ** bytes of readable data.
             */
 //        s->close(s);
+        D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
+
         return;
     }
 }
@@ -366,12 +394,12 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s)
 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); */
@@ -385,6 +413,7 @@ asocket *create_local_service_socket(const char *name)
     asocket *s;
     int fd;
 
+#if 0 /* not support in tizen */
 #if !SDB_HOST
     if (!strcmp(name,"jdwp")) {
         return create_jdwp_service_socket();
@@ -393,11 +422,22 @@ asocket *create_local_service_socket(const char *name)
         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;
 }
 
@@ -427,7 +467,8 @@ typedef struct aremotesocket {
 
 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;
@@ -438,7 +479,8 @@ static int remote_socket_enqueue(asocket *s, apacket *p)
 
 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;
@@ -448,12 +490,15 @@ static void remote_socket_ready(asocket *s)
 
 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;
@@ -482,7 +527,7 @@ asocket *create_remote_socket(unsigned id, atransport *t)
     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;
@@ -498,7 +543,7 @@ asocket *create_remote_socket(unsigned id, atransport *t)
 
 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;
 
@@ -510,7 +555,7 @@ void connect_to_remote(asocket *s, const char *destination)
     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);
 }
 
@@ -566,6 +611,32 @@ unsigned unhex(unsigned char *s, int len)
     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;
@@ -621,8 +692,8 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
         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;
@@ -753,6 +824,7 @@ static void smart_socket_close(asocket *s)
     if(s->peer) {
         s->peer->peer = 0;
         s->peer->close(s->peer);
+        s->peer = 0;
     }
     free(s);
 }
@@ -761,8 +833,7 @@ asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act))
 {
     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;
index aa8682e..43d401f 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -83,6 +83,10 @@ static inline int android_get_control_socket(const char *name)
 // 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);
@@ -92,7 +96,9 @@ extern int socket_local_client_connect(int fd,
         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
diff --git a/src/strutils.c b/src/strutils.c
new file mode 100644 (file)
index 0000000..4a61cfd
--- /dev/null
@@ -0,0 +1,90 @@
+#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;
+}
diff --git a/src/strutils.h b/src/strutils.h
new file mode 100644 (file)
index 0000000..897579f
--- /dev/null
@@ -0,0 +1,11 @@
+#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
+
index 33cb1b2..edbb2c9 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -44,11 +44,32 @@ typedef CRITICAL_SECTION          sdb_mutex_t;
 #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 );
@@ -74,7 +95,7 @@ static __inline__ int  sdb_thread_create( sdb_thread_t  *thread, sdb_thread_func
     return 0;
 }
 
-static __inline__ void  close_on_exec(int  fd)
+static __inline__ int  close_on_exec(int  fd)
 {
     /* nothing really */
 }
@@ -103,7 +124,7 @@ static __inline__  int    sdb_unlink(const char*  path)
 
 static __inline__ int  sdb_mkdir(const char*  path, int mode)
 {
-       return _mkdir(path);
+    return _mkdir(path);
 }
 #undef   mkdir
 #define  mkdir  ___xxx_mkdir
@@ -195,6 +216,8 @@ struct fdevent {
     fdevent *prev;
 
     int fd;
+    int force_eof;
+
     unsigned short state;
     unsigned short events;
 
@@ -255,6 +278,8 @@ static __inline__  int  sdb_is_absolute_host_path( const char*  path )
 
 #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>
@@ -272,13 +297,14 @@ static __inline__  int  sdb_is_absolute_host_path( const char*  path )
 #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
@@ -287,9 +313,13 @@ typedef  pthread_mutex_t          sdb_mutex_t;
 #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,...)
@@ -318,9 +348,13 @@ static __inline__ int  sdb_open_mode( const char*  pathname, int  options, int
 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
@@ -374,10 +408,13 @@ static __inline__  int  sdb_creat(const char*  path, int  mode)
 {
     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
@@ -385,7 +422,17 @@ static __inline__  int  sdb_creat(const char*  path, int  mode)
 
 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
@@ -415,10 +462,13 @@ static __inline__  int  sdb_socket_setbufsize( int   fd, int  bufsize )
     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;
 }
 
 
@@ -432,11 +482,16 @@ static __inline__ int  sdb_socketpair( int  sv[2] )
     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;
 }
 
@@ -474,6 +529,21 @@ static __inline__  int  sdb_is_absolute_host_path( const char*  path )
     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 */
index 5538600..97399bf 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * 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>
@@ -1964,4 +1980,3 @@ sdb_sysdeps_init( void )
 #include "mutex_list.h"
     InitializeCriticalSection( &_win32_lock );
 }
-
diff --git a/src/threads.h b/src/threads.h
new file mode 100644 (file)
index 0000000..dc587b9
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 */
index 97f9988..6f32b9d 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -35,24 +35,32 @@ static atransport transport_list = {
 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
 
@@ -79,7 +87,7 @@ run_transport_disconnects(atransport*  t)
 {
     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 );
@@ -87,75 +95,91 @@ run_transport_disconnects(atransport*  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);
@@ -165,7 +189,7 @@ write_packet(int  fd, apacket** 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;
         }
@@ -175,10 +199,12 @@ write_packet(int  fd, apacket** ppacket)
 
 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);
         }
@@ -204,11 +230,13 @@ void send_packet(apacket *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");
     }
 }
@@ -231,52 +259,51 @@ static void *output_thread(void *_t)
     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;
@@ -288,35 +315,35 @@ static void *input_thread(void *_t)
     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);
             }
         }
 
@@ -327,7 +354,7 @@ static void *input_thread(void *_t)
     // 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;
@@ -508,8 +535,8 @@ transport_read_action(int  fd, struct tmsg*  m)
             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;
         }
     }
@@ -530,8 +557,8 @@ transport_write_action(int  fd, struct tmsg*  m)
             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;
         }
     }
@@ -557,7 +584,7 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
     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.
@@ -576,6 +603,8 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
             free(t->product);
         if (t->serial)
             free(t->serial);
+        if (t->device_name)
+            free(t->device_name);
 
         memset(t,0xee,sizeof(atransport));
         free(t);
@@ -593,12 +622,11 @@ static void transport_registration_func(int _fd, unsigned ev, void *data)
             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,
@@ -653,7 +681,7 @@ static void register_transport(atransport *transport)
     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");
     }
@@ -664,7 +692,7 @@ static void remove_transport(atransport *transport)
     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");
     }
@@ -674,15 +702,16 @@ static void remove_transport(atransport *transport)
 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);
     }
 }
 
@@ -806,6 +835,7 @@ static const char *statename(atransport *t)
     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";
     }
@@ -822,9 +852,10 @@ int list_transports(char *buf, size_t  bufsize)
     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 */
@@ -854,18 +885,46 @@ void close_usb_devices()
 }
 #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);
 }
 
@@ -924,15 +983,60 @@ void unregister_all_tcp_transports()
 
 #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);
 }
 
@@ -961,21 +1065,26 @@ int readx(int fd, void *ptr, size_t len)
 #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;
@@ -987,7 +1096,7 @@ int writex(int fd, const void *ptr, size_t len)
     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) {
@@ -996,13 +1105,16 @@ int writex(int fd, const void *ptr, size_t len)
             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;
 }
 
@@ -1039,4 +1151,3 @@ int check_data(apacket *p)
         return 0;
     }
 }
-
diff --git a/src/transport.h b/src/transport.h
new file mode 100644 (file)
index 0000000..511b37e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 */
index 609d26f..67a0887 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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)
 {
@@ -52,6 +60,11 @@ SDB_MUTEX_DEFINE( local_transports_lock );
 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))){
@@ -61,7 +74,7 @@ static int remote_read(apacket *p, atransport *t)
 
     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
@@ -89,7 +102,7 @@ static int remote_write(apacket *p, atransport *t)
 
     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
@@ -102,11 +115,11 @@ static int remote_write(apacket *p, atransport *t)
 }
 
 
-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;
@@ -123,34 +136,114 @@ int local_connect_arbitrary_ports(int console_port, int sdb_port)
 
     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;
 }
@@ -166,29 +259,346 @@ static void *server_socket_thread(void * arg)
     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(&noti_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;
@@ -197,7 +607,24 @@ void local_init(int port)
     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");
@@ -206,6 +633,22 @@ void local_init(int port)
         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(&register_noti_lock);
+        pthread_cond_wait(&noti_cond, &register_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(&register_noti_lock);
+    }
 }
 
 static void remote_kick(atransport *t)
index 4233111..e4de29a 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -27,8 +27,7 @@
 #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)
 {
index c9247ae..8d12ea7 100644 (file)
@@ -1,17 +1,14 @@
-/* 
- * 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.
index 2915eaf..cd72c07 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -45,7 +45,7 @@
 /* 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
 {
@@ -149,7 +149,7 @@ static void find_usb_device(const char *base,
 
 //        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;
@@ -158,7 +158,7 @@ static void find_usb_device(const char *base,
             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);
@@ -191,14 +191,14 @@ static void find_usb_device(const char *base,
                 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;
@@ -206,7 +206,6 @@ static void find_usb_device(const char *base,
             }
 
             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);
@@ -236,7 +235,7 @@ static void find_usb_device(const char *base,
                             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;
@@ -259,7 +258,7 @@ static void find_usb_device(const char *base,
                             continue;
                         }
                             /* aproto 01 needs 0 termination */
-                        if(interface->bInterfaceProtocol == 0x02) {
+                        if(interface->bInterfaceProtocol == 0x01) {
                             zero_mask = ep1->wMaxPacketSize - 1;
                         }
 
@@ -378,6 +377,7 @@ static int usb_bulk_read(usb_handle *h, void *data, int len)
         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) {
@@ -385,7 +385,7 @@ static int usb_bulk_read(usb_handle *h, void *data, int len)
             break;
         }
         if(res < 0) {
-            if(errno == EINTR) {
+            if(saved_errno == EINTR) {
                 continue;
             }
             D("[ reap urb - error ]\n");
@@ -547,7 +547,7 @@ static void register_device(const char *dev_name,
     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
@@ -590,11 +590,23 @@ static void register_device(const char *dev_name,
         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 */
@@ -617,6 +629,7 @@ static void register_device(const char *dev_name,
         ctrl.wIndex = 0;
         ctrl.wLength = sizeof(languages);
         ctrl.data = languages;
+        ctrl.timeout = 1000;
 
         result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
         if (result > 0)
@@ -629,9 +642,10 @@ static void register_device(const char *dev_name,
             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) {
@@ -639,7 +653,7 @@ static void register_device(const char *dev_name,
                 // 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;
             }
@@ -698,4 +712,3 @@ void usb_init()
         fatal_errno("cannot create input thread");
     }
 }
-
index 6339497..db7ca9a 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -57,20 +57,21 @@ static void *usb_open_thread(void *x)
         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");
@@ -85,14 +86,14 @@ int usb_write(usb_handle *h, const void *data, int len)
 {
     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;
 }
 
@@ -100,13 +101,14 @@ int usb_read(usb_handle *h, void *data, int len)
 {
     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;
 }
 
@@ -114,10 +116,13 @@ void usb_init()
 {
     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);
@@ -127,7 +132,7 @@ void usb_init()
     // 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");
index 5961619..5fbe1a6 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
index 2c95e78..6364828 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -37,6 +37,8 @@
 
 // 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
@@ -69,6 +71,8 @@
 #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,
@@ -104,6 +148,7 @@ int builtInVendorIds[] = {
     VENDOR_ID_KYOCERA,
     VENDOR_ID_PANTECH,
     VENDOR_ID_QUALCOMM,
+    VENDOR_ID_OTGV,
     VENDOR_ID_NEC,
     VENDOR_ID_PMC,
     VENDOR_ID_TOSHIBA,
@@ -111,6 +156,26 @@ int builtInVendorIds[] = {
     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]))
@@ -172,7 +237,7 @@ void usb_vendors_init(void)
 /* 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;
     }
 
index 43790b9..9e09d9a 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -22,4 +22,4 @@ extern unsigned  vendorIdCount;
 
 void usb_vendors_init(void);
 
-#endif
\ No newline at end of file
+#endif
index 868ed68..37eef1b 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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.
@@ -198,7 +198,7 @@ usb_handle* do_usb_open(const wchar_t* interface_name) {
   ret->prev = ret;
 
   // Create interface.
-  ret->sdb_interface = AdbCreateInterfaceByName(interface_name);
+  ret->sdb_interface = SdbCreateInterfaceByName(interface_name);
 
   if (NULL == ret->sdb_interface) {
     free(ret);
@@ -208,21 +208,21 @@ usb_handle* do_usb_open(const wchar_t* interface_name) {
 
   // 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);
@@ -231,7 +231,7 @@ usb_handle* do_usb_open(const wchar_t* interface_name) {
 
         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)) {
@@ -246,28 +246,28 @@ usb_handle* do_usb_open(const wchar_t* interface_name) {
   }
 
   // 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
@@ -275,7 +275,7 @@ int usb_write(usb_handle* handle, const void* data, int len) {
       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,
@@ -285,9 +285,10 @@ int usb_write(usb_handle* handle, const void* data, int len) {
       }
     } 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);
@@ -299,7 +300,7 @@ int usb_write(usb_handle* handle, const void* data, int len) {
 }
 
 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;
 
@@ -308,25 +309,26 @@ int usb_read(usb_handle *handle, void* data, int len) {
     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");
@@ -343,11 +345,11 @@ void usb_cleanup_handle(usb_handle* handle) {
     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;
@@ -410,7 +412,7 @@ int recognized_device(usb_handle* handle) {
   // 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;
   }
@@ -418,7 +420,7 @@ int recognized_device(usb_handle* handle) {
   // Then check interface properties
   USB_INTERFACE_DESCRIPTOR interf_desc;
 
-  if (!AdbGetUsbInterfaceDescriptor(handle->sdb_interface,
+  if (!SdbGetUsbInterfaceDescriptor(handle->sdb_interface,
                                     &interf_desc)) {
     return 0;
   }
@@ -432,9 +434,9 @@ int recognized_device(usb_handle* handle) {
       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;
       }
     }
@@ -449,18 +451,18 @@ void find_devices() {
         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.
@@ -482,7 +484,7 @@ void find_devices() {
           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)) {
@@ -509,5 +511,5 @@ void find_devices() {
     entry_buffer_size = sizeof(entry_buffer);
   }
 
-  AdbCloseHandle(enum_handle);
+  SdbCloseHandle(enum_handle);
 }
index bd31e20..589f86f 100644 (file)
@@ -1,23 +1,30 @@
 /*
- * 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)
 {
@@ -104,3 +111,52 @@ buff_add  (char*  buff, char*  buffEnd, const char*  format, ... )
     }
     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;
+}
+
index 2f2d2d8..bc228d4 100644 (file)
@@ -1,18 +1,19 @@
 /*
- * 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
 
@@ -65,4 +66,12 @@ char*   buff_add  (char*  buff, char*  buffEnd, const char*  format, ... );
 #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 */
diff --git a/test/install_udev.sh b/test/install_udev.sh
new file mode 100755 (executable)
index 0000000..f405a22
--- /dev/null
@@ -0,0 +1,14 @@
+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/
diff --git a/test/test_inoti_service.c b/test/test_inoti_service.c
new file mode 100644 (file)
index 0000000..b3c63ef
--- /dev/null
@@ -0,0 +1,115 @@
+/*\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
similarity index 79%
rename from src/test_track_devices.c
rename to test/test_track_devices.c
index d157011..64c484f 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * 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>
similarity index 77%
rename from src/test_track_jdwp.c
rename to test/test_track_jdwp.c
index 8ecc6b8..5187d5f 100644 (file)
@@ -1,4 +1,20 @@
-/* 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>