From 7ca00d5b36269273d3ac7ec57422c2f7925bda94 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Wed, 13 Mar 2013 01:50:13 +0900 Subject: [PATCH] Tizen 2.1 base --- AUTHORS | 3 + LICENSE.APLv2.0 | 205 ++++ Makefile.am | 148 +++ NOTICE | 3 + autogen.sh | 12 + build-aux/depcomp | 630 ++++++++++++ build-aux/install-sh | 520 ++++++++++ build-aux/missing | 376 +++++++ common/include/media-server-db-svc.h | 160 +++ common/include/media-server-db.h | 31 + common/include/media-server-dbg.h | 56 + common/include/media-server-dbus-type.h | 33 + common/include/media-server-dbus.h | 30 + common/include/media-server-drm.h | 54 + common/include/media-server-external-storage.h | 44 + common/include/media-server-inotify-internal.h | 63 ++ common/include/media-server-inotify.h | 70 ++ common/include/media-server-scanner.h | 28 + common/include/media-server-socket.h | 47 + common/include/media-server-thumb.h | 62 ++ common/include/media-server-types.h | 125 +++ common/include/media-server-utils.h | 96 ++ common/media-server-db-svc.c | 1297 ++++++++++++++++++++++++ common/media-server-db.c | 139 +++ common/media-server-dbus.c | 81 ++ common/media-server-drm.c | 137 +++ common/media-server-external-storage.c | 338 ++++++ common/media-server-inotify-internal.c | 125 +++ common/media-server-inotify.c | 889 ++++++++++++++++ common/media-server-main.c | 420 ++++++++ common/media-server-scanner.c | 261 +++++ common/media-server-socket.c | 592 +++++++++++ common/media-server-thumb.c | 1115 ++++++++++++++++++++ common/media-server-utils.c | 336 ++++++ common/mediadb-update.c | 157 +++ common/scanner/include/media-scanner-db-svc.h | 102 ++ common/scanner/include/media-scanner-dbg.h | 49 + common/scanner/include/media-scanner-drm.h | 54 + common/scanner/include/media-scanner-scan.h | 43 + common/scanner/include/media-scanner-socket.h | 44 + common/scanner/include/media-scanner-utils.h | 86 ++ common/scanner/media-scanner-db-svc.c | 610 +++++++++++ common/scanner/media-scanner-drm.c | 123 +++ common/scanner/media-scanner-scan.c | 1091 ++++++++++++++++++++ common/scanner/media-scanner-socket.c | 185 ++++ common/scanner/media-scanner-utils.c | 513 ++++++++++ common/scanner/media-scanner.c | 270 +++++ config.in | 161 +++ configure.ac | 128 +++ data/mediasvr | 3 + lib/include/media-server-ipc.h | 107 ++ lib/include/media-util-db.h | 61 ++ lib/include/media-util-dbg.h | 83 ++ lib/include/media-util-err.h | 83 ++ lib/include/media-util-internal.h | 65 ++ lib/include/media-util-ipc.h | 61 ++ lib/include/media-util-noti.h | 83 ++ lib/include/media-util-register.h | 111 ++ lib/include/media-util.h | 38 + lib/media-util-db.c | 515 ++++++++++ lib/media-util-ipc.c | 227 +++++ lib/media-util-noti.c | 92 ++ lib/media-util-register.c | 382 +++++++ libmedia-utils.manifest | 6 + libmedia-utils.pc.in | 11 + media-server.manifest | 17 + packaging/media-server.service | 9 + packaging/media-server.spec | 124 +++ reset_mediadb.sh | 28 + 69 files changed, 14248 insertions(+) create mode 100644 AUTHORS create mode 100644 LICENSE.APLv2.0 create mode 100755 Makefile.am create mode 100644 NOTICE create mode 100755 autogen.sh create mode 100755 build-aux/depcomp create mode 100755 build-aux/install-sh create mode 100755 build-aux/missing create mode 100755 common/include/media-server-db-svc.h create mode 100755 common/include/media-server-db.h create mode 100755 common/include/media-server-dbg.h create mode 100755 common/include/media-server-dbus-type.h create mode 100755 common/include/media-server-dbus.h create mode 100755 common/include/media-server-drm.h create mode 100755 common/include/media-server-external-storage.h create mode 100755 common/include/media-server-inotify-internal.h create mode 100755 common/include/media-server-inotify.h create mode 100755 common/include/media-server-scanner.h create mode 100755 common/include/media-server-socket.h create mode 100755 common/include/media-server-thumb.h create mode 100755 common/include/media-server-types.h create mode 100755 common/include/media-server-utils.h create mode 100755 common/media-server-db-svc.c create mode 100755 common/media-server-db.c create mode 100755 common/media-server-dbus.c create mode 100755 common/media-server-drm.c create mode 100755 common/media-server-external-storage.c create mode 100755 common/media-server-inotify-internal.c create mode 100755 common/media-server-inotify.c create mode 100755 common/media-server-main.c create mode 100755 common/media-server-scanner.c create mode 100755 common/media-server-socket.c create mode 100755 common/media-server-thumb.c create mode 100755 common/media-server-utils.c create mode 100644 common/mediadb-update.c create mode 100755 common/scanner/include/media-scanner-db-svc.h create mode 100755 common/scanner/include/media-scanner-dbg.h create mode 100755 common/scanner/include/media-scanner-drm.h create mode 100755 common/scanner/include/media-scanner-scan.h create mode 100755 common/scanner/include/media-scanner-socket.h create mode 100755 common/scanner/include/media-scanner-utils.h create mode 100755 common/scanner/media-scanner-db-svc.c create mode 100755 common/scanner/media-scanner-drm.c create mode 100755 common/scanner/media-scanner-scan.c create mode 100755 common/scanner/media-scanner-socket.c create mode 100755 common/scanner/media-scanner-utils.c create mode 100755 common/scanner/media-scanner.c create mode 100644 config.in create mode 100755 configure.ac create mode 100755 data/mediasvr create mode 100755 lib/include/media-server-ipc.h create mode 100755 lib/include/media-util-db.h create mode 100755 lib/include/media-util-dbg.h create mode 100755 lib/include/media-util-err.h create mode 100755 lib/include/media-util-internal.h create mode 100755 lib/include/media-util-ipc.h create mode 100755 lib/include/media-util-noti.h create mode 100755 lib/include/media-util-register.h create mode 100755 lib/include/media-util.h create mode 100755 lib/media-util-db.c create mode 100755 lib/media-util-ipc.c create mode 100755 lib/media-util-noti.c create mode 100755 lib/media-util-register.c create mode 100644 libmedia-utils.manifest create mode 100755 libmedia-utils.pc.in create mode 100644 media-server.manifest create mode 100644 packaging/media-server.service create mode 100755 packaging/media-server.spec create mode 100755 reset_mediadb.sh diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..699f897 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Yong Yeon Kim +Hyunjun Ko +Haejeong Kim diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0 new file mode 100644 index 0000000..8aa906c --- /dev/null +++ b/LICENSE.APLv2.0 @@ -0,0 +1,205 @@ + + 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. + + + diff --git a/Makefile.am b/Makefile.am new file mode 100755 index 0000000..a5b44b3 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,148 @@ +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = . + +AM_CPPFLAGS = $(FMS_DEBUG_FLAGS) + +AM_LDFLAGS=-Wl,--as-needed -Wl,--hash-style=both + +### pkgconfig ### +pkgconfigdir = $(libdir)/pkgconfig +dist_pkgconfig_DATA = libmedia-utils.pc + +nor_directory = /etc/rc.d/rc3.d +hib_directory = /etc/rc.d/rc5.d + +install-data-hook: + mkdir $(DESTDIR)/usr/local/bin/ -p + cp -a $(CURDIR)/reset_mediadb.sh $(DESTDIR)/usr/local/bin/ + mkdir $(DESTDIR)$(nor_directory) -p + ln -s ../init.d/mediasvr S99mediasvr + mv ./S99mediasvr $(DESTDIR)$(nor_directory) + mkdir $(DESTDIR)$(hib_directory) -p + ln -s ../init.d/mediasvr S99mediasvr + mv ./S99mediasvr $(DESTDIR)$(hib_directory) + +# init.d script +fmsvcdir = /etc/rc.d/init.d +dist_fmsvc_DATA = ./data/mediasvr + +### libmedia-utils.la ### +lib_LTLIBRARIES = libmedia-utils.la +libmedia_utils_la_SOURCES = lib/media-util-noti.c \ + lib/media-util-ipc.c \ + lib/media-util-db.c \ + lib/media-util-register.c + +libmedia_utils_la_CFLAGS = -I${srcdir}/lib/include \ + $(GLIB_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(SQLITE3_CFLAGS) \ + $(DB_UTIL_CFLAGS) \ + $(PHONESTATUS_CFLAGS) + +libmedia_utils_la_LIBADD = $(GLIB_LIBS) \ + $(DLOG_LIBS) \ + $(DBUS_LIBS) \ + $(SQLITE3_LIBS) \ + $(DB_UTIL_LIBS) \ + $(PHONESTATUS_LIBS) + + +### file-manager-server ### +bin_PROGRAMS = media-server \ + media-scanner \ + mediadb-update + +media_server_SOURCES = common/media-server-dbus.c \ + common/media-server-drm.c \ + common/media-server-utils.c \ + common/media-server-external-storage.c \ + common/media-server-db-svc.c \ + common/media-server-inotify-internal.c \ + common/media-server-inotify.c \ + common/media-server-db.c \ + common/media-server-socket.c \ + common/media-server-thumb.c \ + common/media-server-scanner.c \ + common/media-server-main.c + +media_server_CFLAGS = -I${srcdir}/common/include \ + -I${srcdir}/lib/include \ + $(GTHREAD_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(PHONESTATUS_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(DRM_SERVICE_CFLAGS) \ + $(AUL_CFLAG)\ + $(LIBPMCONTROL_CFLAGS) \ + $(HEYNOTI_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(STATUS_CFLAGS) + +media_server_LDADD = libmedia-utils.la \ + $(GLIB_LIBS) \ + $(GTHREAD_LIBS) \ + $(PHONESTATUS_LIBS) \ + $(DLOG_LIBS) \ + $(DRM_SERVICE_LIBS) \ + $(AUL_LIBS) \ + $(LIBPMCONTROL_LIBS) \ + $(HEYNOTI_LIBS) \ + $(DBUS_LIBS) \ + -ldl \ + $(STATUS_LIBS) + +media_scanner_SOURCES = common/scanner/media-scanner-drm.c \ + common/scanner/media-scanner-utils.c \ + common/scanner/media-scanner-db-svc.c \ + common/scanner/media-scanner-scan.c \ + common/scanner/media-scanner-socket.c \ + common/scanner/media-scanner.c + +media_scanner_CFLAGS = -I${srcdir}/common/scanner/include \ + -I${srcdir}/lib/include \ + -I${srcdir}/common/include \ + $(GTHREAD_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(PHONESTATUS_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(DRM_SERVICE_CFLAGS) \ + $(AUL_CFLAG)\ + $(LIBPMCONTROL_CFLAGS) \ + $(HEYNOTI_CFLAGS) \ + $(DBUS_CFLAGS) + +media_scanner_LDADD = libmedia-utils.la \ + $(GLIB_LIBS) \ + $(GTHREAD_LIBS) \ + $(PHONESTATUS_LIBS) \ + $(DLOG_LIBS) \ + $(DRM_SERVICE_LIBS) \ + $(AUL_LIBS) \ + $(LIBPMCONTROL_LIBS) \ + $(THUMB_GEN_LIBS) \ + $(HEYNOTI_LIBS) \ + $(DBUS_LIBS) \ + -ldl #this is for using dlsym + +mediadb_update_SOURCES = common/mediadb-update.c + +mediadb_update_CFLAGS = -I${srcdir}/lib/include \ + $(GTHREAD_CFLAGS) \ + $(GLIB_CFLAGS) + +mediadb_update_LDADD = libmedia-utils.la \ + $(GLIB_LIBS) \ + $(GTHREAD_LIBS) + +### includeheaders ### +includeheadersdir = $(includedir)/media-utils +includeheaders_HEADERS = lib/include/media-util-noti.h \ + lib/include/media-util-register.h \ + lib/include/media-util-err.h \ + lib/include/media-util-db.h \ + lib/include/media-util-ipc.h \ + lib/include/media-util.h \ + lib/include/media-server-ipc.h diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..ccdad52 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE file for Apache License terms and conditions. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..a9d7ee4 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +rm -rf autom4te.cache +rm -f aclocal.m4 ltmain.sh +mkdir -p m4 + +echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1 +echo "Running autoheader..." ; autoheader || exit 1 +echo "Running autoconf..." ; autoconf || exit 1 +echo "Running libtoolize..." ; (libtoolize --copy --automake --force || glibtoolize --automake) || exit 1 +echo "Running automake..." ; automake --add-missing --copy --foreign --force-missing || exit 1 +echo "You can now compile and build package." diff --git a/build-aux/depcomp b/build-aux/depcomp new file mode 100755 index 0000000..df8eea7 --- /dev/null +++ b/build-aux/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/install-sh b/build-aux/install-sh new file mode 100755 index 0000000..6781b98 --- /dev/null +++ b/build-aux/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/build-aux/missing b/build-aux/missing new file mode 100755 index 0000000..28055d2 --- /dev/null +++ b/build-aux/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/common/include/media-server-db-svc.h b/common/include/media-server-db-svc.h new file mode 100755 index 0000000..903837a --- /dev/null +++ b/common/include/media-server-db-svc.h @@ -0,0 +1,160 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-db-svc.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SERVER_DB_SVC_H_ +#define _MEDIA_SERVER_DB_SVC_H_ + +#include "media-server-types.h" +#if MS_INOTI_ENABLE +typedef int (*CHECK_ITEM)(const char*, const char*, char **); +typedef int (*CONNECT)(void**, char **); +typedef int (*DISCONNECT)(void*, char **); +typedef int (*CHECK_ITEM_EXIST)(void*, const char*, int, char **); +typedef int (*INSERT_ITEM_BEGIN)(void*, int, char **); +typedef int (*INSERT_ITEM_END)(void*, char **); +typedef int (*INSERT_ITEM)(void*, const char*, int, const char*, char **); +typedef int (*INSERT_ITEM_IMMEDIATELY)(void*, const char*, int, const char*, char **); +typedef int (*MOVE_ITEM_BEGIN)(void*, int, char **); +typedef int (*MOVE_ITEM_END)(void*, char **); +typedef int (*MOVE_ITEM)(void*, const char*, int, const char*, int, const char*, char **); +typedef int (*SET_ALL_STORAGE_ITEMS_VALIDITY)(void*, int, int, char **); +typedef int (*SET_ITEM_VALIDITY_BEGIN)(void*, int, char **); +typedef int (*SET_ITEM_VALIDITY_END)(void*, char **); +typedef int (*SET_ITEM_VALIDITY)(void*, const char*, int, const char*, int, char **); +typedef int (*DELETE_ITEM)(void*, const char*, int, char **); +typedef int (*DELETE_ALL_ITEMS_IN_STORAGE)(void*, int, char **); +typedef int (*DELETE_ALL_INVALID_ITMES_IN_STORAGE)(void*, int, char **); +typedef int (*UPDATE_BEGIN)(char **); +typedef int (*UPDATE_END)(char **); +typedef int (*REFRESH_ITEM)(void*, const char *, int, const char*, char**); + +int +ms_load_functions(void); + +void +ms_unload_functions(void); + +int +ms_connect_db(void ***handle); + +int +ms_disconnect_db(void ***handle); + +int +ms_validate_item(void **handle, char *path); + +int +ms_register_file(void **handle, const char *path, GAsyncQueue* queue); + +int +ms_insert_item_batch(void **handle, const char *path); + +int +ms_insert_item(void **handle, const char *path); + +int +ms_delete_item(void **handle, const char *full_file_path); + +int +ms_move_item(void **handle, + ms_storage_type_t src_store_type, + ms_storage_type_t dest_store_type, + const char *src_file_full_path, + const char *dest_file_full_path); + +bool +ms_delete_all_items(void **handle, ms_storage_type_t store_type); + +int +ms_invalidate_all_items(void **handle, ms_storage_type_t store_type); + +bool +ms_delete_invalid_items(void **handle, ms_storage_type_t store_type); + +int +ms_refresh_item(void **handle, const char *path); + +int +ms_check_exist(void **handle, const char *path); + +/**************************************************************************************************** +FOR BULK COMMIT +*****************************************************************************************************/ + +void +ms_register_start(void **handle); + +void +ms_register_end(void **handle); + +void +ms_move_start(void **handle); + +void +ms_move_end(void **handle); + +void +ms_validate_start(void **handle); + +void +ms_validate_end(void **handle); +#else +typedef int (*CHECK_ITEM)(const char*, const char*, char **); +typedef int (*CONNECT)(void**, char **); +typedef int (*DISCONNECT)(void*, char **); +typedef int (*CHECK_ITEM_EXIST)(void*, const char*, int, char **); +typedef int (*INSERT_ITEM_IMMEDIATELY)(void*, const char*, int, const char*, char **); +typedef int (*SET_ALL_STORAGE_ITEMS_VALIDITY)(void*, int, int, char **); + +int +ms_load_functions(void); + +void +ms_unload_functions(void); + +int +ms_connect_db(void ***handle); + +int +ms_disconnect_db(void ***handle); + +int +ms_insert_item(void **handle, const char *path); + +int +ms_register_file(void **handle, const char *path); + +int +ms_check_exist(void **handle, const char *path); + +int +ms_invalidate_all_items(void **handle, ms_storage_type_t store_type); +#endif + +#endif /*_MEDIA_SERVER_DB_SVC_H_*/ diff --git a/common/include/media-server-db.h b/common/include/media-server-db.h new file mode 100755 index 0000000..87f0b00 --- /dev/null +++ b/common/include/media-server-db.h @@ -0,0 +1,31 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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 _MEDIA_SERVER_DB_H_ +#define _MEDIA_SERVER_DB_H_ + +#include + +GMainLoop *ms_db_get_mainloop(void); +gboolean ms_db_get_thread_status(void); +gboolean ms_db_thread(void *data); + +#endif/* _MEDIA_SERVER_DB_H_ */ diff --git a/common/include/media-server-dbg.h b/common/include/media-server-dbg.h new file mode 100755 index 0000000..64122bc --- /dev/null +++ b/common/include/media-server-dbg.h @@ -0,0 +1,56 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-dbg.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SERVER_DBG_H_ +#define _MEDIA_SERVER_DBG_H_ + +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "MEDIA_SERVER" + +#define MS_DBG(fmt, args...) LOGD(fmt "\n", ##args); + +#define MS_DBG_INFO(fmt, args...) do{ if (true) { \ + LOGE(fmt "\n" , ##args); \ + }} while(false) + +#define MS_DBG_WARN(fmt, args...) do{ if (true) { \ + LOGW(fmt "\n", ##args); \ + }} while(false) + +#define MS_DBG_ERR(fmt, args...) do{ if (true) { \ + LOGE(fmt "\n", ##args); \ + }} while(false) + +#endif /*_MEDIA_SERVER_DBG_H_*/ diff --git a/common/include/media-server-dbus-type.h b/common/include/media-server-dbus-type.h new file mode 100755 index 0000000..54c227a --- /dev/null +++ b/common/include/media-server-dbus-type.h @@ -0,0 +1,33 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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 _MEDIA_SERVER_DBUS_TYPES_H_ +#define _MEDIA_SERVER_DBUS_TYPES_H_ + +#define MS_DBUS_PATH "/com/mediaserver/dbus/notify" +#define MS_DBUS_INTERFACE "com.mediaserver.dbus.Signal" +#define MS_DBUS_NAME "ms_db_updated" +#define MS_DBUS_MATCH_RULE "type='signal',interface='com.mediaserver.dbus.Signal'" + +typedef enum { + MS_DBUS_DB_UPDATED +} ms_dbus_noti_type_t; + +#endif /*_MEDIA_SERVER_DBUS_TYPES_H_*/ \ No newline at end of file diff --git a/common/include/media-server-dbus.h b/common/include/media-server-dbus.h new file mode 100755 index 0000000..241d543 --- /dev/null +++ b/common/include/media-server-dbus.h @@ -0,0 +1,30 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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 _MEDIA_SERVER_DBUS_H__ +#define _MEDIA_SERVER_DBUS_H__ + +#include "media-server-dbus-type.h" + +void ms_dbus_init(void); + +gboolean ms_dbus_send_noti(ms_dbus_noti_type_t data); + +#endif/*_MEDIA_SERVER_DBUS_H__*/ \ No newline at end of file diff --git a/common/include/media-server-drm.h b/common/include/media-server-drm.h new file mode 100755 index 0000000..27f3dc6 --- /dev/null +++ b/common/include/media-server-drm.h @@ -0,0 +1,54 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-drm.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ +#ifndef _MEDIA_SERVER_DRM_H_ +#define _MEDIA_SERVER_DRM_H_ + +bool +ms_is_drm_file(const char *path); + +int +ms_get_mime_in_drm_info(const char *path, char *mime); + +int +ms_drm_register(const char* path); + +void +ms_drm_unregister(const char* path); + +void +ms_drm_unregister_all(void); + +bool +ms_drm_insert_ext_memory(void); + +bool +ms_drm_extract_ext_memory(void); + +#endif /*_MEDIA_SERVER_DRM_H_*/ \ No newline at end of file diff --git a/common/include/media-server-external-storage.h b/common/include/media-server-external-storage.h new file mode 100755 index 0000000..d7deb2c --- /dev/null +++ b/common/include/media-server-external-storage.h @@ -0,0 +1,44 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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 _MEDIA_SERVER_EXTERNAL_STORAGE_H_ +#define _MEDIA_SERVER_EXTERNAL_STORAGE_H_ + +#include "media-server-types.h" + +void +ms_make_default_path_mmc(void); + +int +ms_update_mmc_info(void); + +void +ms_mmc_removed_handler(void); + +int +ms_present_mmc_insert(void); + +void +ms_mmc_vconf_cb(void *data); + +ms_dir_scan_type_t +ms_get_mmc_state(void); + +#endif /*_MEDIA_SERVER_EXTERNAL_STORAGE_H_*/ diff --git a/common/include/media-server-inotify-internal.h b/common/include/media-server-inotify-internal.h new file mode 100755 index 0000000..bbd260c --- /dev/null +++ b/common/include/media-server-inotify-internal.h @@ -0,0 +1,63 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-inotify-internal.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SERVER_INOTIFY_INTERNAL_H_ +#define _MEDIA_SERVER_INOTIFY_INTERNAL_H_ + +#include +#include "media-server-types.h" +#if MS_INOTI_ENABLE +#define INOTI_EVENT_SIZE (sizeof(struct inotify_event)) +#define INOTI_BUF_LEN (1024*(INOTI_EVENT_SIZE+16)) +#define INOTI_FOLDER_COUNT_MAX 1024 + +typedef struct ms_inoti_dir_data { + char *name; + int wd; + struct ms_inoti_dir_data *next; +} ms_inoti_dir_data; + +typedef struct ms_create_file_info { + char *name; + int wd; + struct ms_create_file_info *previous; + struct ms_create_file_info *next; +} ms_create_file_info; + +int _ms_inoti_add_create_file_list(int wd, char *name); + +int _ms_inoti_delete_create_file_list(ms_create_file_info *node); + +ms_create_file_info *_ms_inoti_find_create_file_list(int wd, char *name); + +bool _ms_inoti_full_path(int wd, char *name, char *path, int sizeofpath); + +bool _ms_inoti_get_full_path(int wd, char *name, char *path, int sizeofpath); +#endif +#endif /*_MEDIA_SERVER_INOTIFY_INTERNAL_H_*/ diff --git a/common/include/media-server-inotify.h b/common/include/media-server-inotify.h new file mode 100755 index 0000000..c35d071 --- /dev/null +++ b/common/include/media-server-inotify.h @@ -0,0 +1,70 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-inotify.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SERVER_INOTI_H_ +#define _MEDIA_SERVER_INOTI_H_ + +#include +#include "media-server-types.h" + +#if MS_INOTI_ENABLE + +typedef struct ms_ignore_file_info { + char *path; + struct ms_ignore_file_info *previous; + struct ms_ignore_file_info *next; +} ms_ignore_file_info; + +int ms_inoti_init(void); + +gboolean ms_inoti_thread(gpointer data); + +void ms_inoti_add_watch(char *path); + +int ms_inoti_add_watch_with_node(ms_dir_scan_info * const current_node, int depth); + +void ms_inoti_remove_watch_recursive(char *path); + +void ms_inoti_remove_watch(char *path); + +void ms_inoti_modify_watch(char *path_from, char *path_to); + +int ms_inoti_add_ignore_file(const char *path); + +int ms_inoti_delete_ignore_file(ms_ignore_file_info * delete_node); + +ms_ignore_file_info *ms_inoti_find_ignore_file(const char *path); + +void ms_inoti_delete_mmc_ignore_file(void); + +void ms_inoti_add_watch_all_directory(ms_storage_type_t storage_type); + +#endif +#endif/* _MEDIA_SERVER_INOTI_H_ */ diff --git a/common/include/media-server-scanner.h b/common/include/media-server-scanner.h new file mode 100755 index 0000000..735a5df --- /dev/null +++ b/common/include/media-server-scanner.h @@ -0,0 +1,28 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +int ms_scanner_start(void); + +bool ms_get_scanner_status(void); + +void ms_reset_scanner_status(void); + +int ms_get_scanner_pid(void); \ No newline at end of file diff --git a/common/include/media-server-socket.h b/common/include/media-server-socket.h new file mode 100755 index 0000000..f75c981 --- /dev/null +++ b/common/include/media-server-socket.h @@ -0,0 +1,47 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-thumb.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SERVER_SOCKET_H_ +#define _MEDIA_SERVER_SOCKET_H_ + +#include "media-server-types.h" +#include "media-server-ipc.h" + +gboolean ms_read_socket(GIOChannel *src, GIOCondition condition, gpointer data); + +gboolean ms_receive_message_from_scanner(GIOChannel *src, GIOCondition condition, gpointer data); + +int ms_send_scan_request(ms_comm_msg_s *send_msg); + +int ms_send_storage_scan_request(ms_storage_type_t storage_type, ms_dir_scan_type_t scan_type); + +gboolean ms_read_db_socket(GIOChannel *src, GIOCondition condition, gpointer data); +gboolean ms_read_db_tcp_socket(GIOChannel *src, GIOCondition condition, gpointer data); + +#endif /*_MEDIA_SERVER_SOCKET_H_*/ diff --git a/common/include/media-server-thumb.h b/common/include/media-server-thumb.h new file mode 100755 index 0000000..f8dc096 --- /dev/null +++ b/common/include/media-server-thumb.h @@ -0,0 +1,62 @@ +/* + * media-thumbnail-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hyunjun Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include "media-server-types.h" +#include "media-server-ipc.h" + +#ifndef _MEDIA_SERVER_THUMB_H_ +#define _MEDIA_SERVER_THUMB_H_ + +GMainLoop * +ms_get_thumb_thread_mainloop(void); + +int +ms_thumb_get_server_pid(); + +void +ms_thumb_reset_server_status(); + +gpointer +ms_thumb_agent_start_thread(gpointer data); + +int +_ms_thumb_create_socket(int sock_type, int *sock); + +int +_ms_thumb_create_udp_socket(int *sock); + +gboolean +_ms_thumb_agent_prepare_udp_socket(); + +int +_ms_thumb_recv_msg(int sock, int header_size, thumbMsg *msg); + +int +_ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_in *from_addr, unsigned int *from_size); + +int +_ms_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size); + +#endif /*_MEDIA_SERVER_THUMB_H_*/ + diff --git a/common/include/media-server-types.h b/common/include/media-server-types.h new file mode 100755 index 0000000..994493c --- /dev/null +++ b/common/include/media-server-types.h @@ -0,0 +1,125 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-types.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SERVER_TYPES_H_ +#define _MEDIA_SERVER_TYPES_H_ + +#include +#include +#include +#include +#include + +#define FMS_PERF +#define MS_INOTI_ENABLE 0 + +#define MS_VALIND 1 +#define MS_INVALID 0 +#define MS_RECURSIVE 1 +#define MS_NON_RECURSIVE 0 + +/*This macro is used to save and check information of inserted memory card*/ +#define MS_MMC_INFO_KEY "db/private/mediaserver/mmc_info" + +/* store scanning status of each storage */ +#define MS_SCAN_STATUS_INTERNAL "file/private/mediaserver/scan_internal" +#define MS_SCAN_STATUS_DIRECTORY "file/private/mediaserver/scan_directory" +enum{ + P_VCONF_SCAN_DOING = 0, + P_VCONF_SCAN_DONE, +}; + +/*Use for Poweroff sequence*/ +#define POWEROFF_NOTI_NAME "power_off_start" /*poeroff noti from system-server*/ +#define POWEROFF_DIR_PATH "/opt/usr/media/_POWER_OFF" /*This path uses for stopping Inotify thread and Socket thread*/ +#define POWEROFF_DIR_NAME "_POWER_OFF" /*This path uses for stopping Inotify thread and Socket thread*/ +#define POWEROFF -1 /*This number uses for stopping Scannig thread*/ + +#define MS_SAFE_FREE(src) { if(src) {free(src); src = NULL;} } +#define MS_MALLOC(src, size) { if (size > SIZE_MAX || size <= 0) {src = NULL;} \ + else { src = malloc(size); memset(src, 0x0, size);} } + +/*System default folder definition*/ +#define FAT_FILENAME_LEN_MAX 255 /* not inc null */ +#define FAT_FILEPATH_LEN_MAX 4096 /* inc null */ + +/* The following MACROs(TAF_XXX) are defined in "fs-limit.h"*/ +#define MS_FILE_NAME_LEN_MAX FAT_FILENAME_LEN_MAX /**< File name max length on file system */ +#define MS_FILE_PATH_LEN_MAX FAT_FILEPATH_LEN_MAX /**< File path max length (include file name) on file system */ + +#define MS_SOCK_NOT_ALLOCATE -1 + +typedef enum { + MS_STORAGE_INTERNAL, /**< Stored only in phone */ + MS_STORAGE_EXTERNAL, /**< Stored only in MMC */ +} ms_storage_type_t; + +typedef enum { + MS_SCANNING_INTERNAL, + MS_SCANNING_EXTERNAL, + MS_SCANNING_DIRECTORY, +} ms_scanning_location_t; + +typedef enum { + MS_SCAN_INVALID, + MS_SCAN_PART, + MS_SCAN_ALL, +} ms_dir_scan_type_t; + +typedef enum { + MS_DB_UPDATING = 0, + MS_DB_UPDATED = 1 +} ms_db_status_type_t; + +typedef struct ms_dir_scan_info { + char *name; + struct ms_dir_scan_info *parent; + struct ms_dir_scan_info *Rbrother; + struct ms_dir_scan_info *next; +} ms_dir_scan_info; + +typedef struct { + char *path; + ms_storage_type_t storage_type; + ms_dir_scan_type_t scan_type; + int pid; + bool recursive_on; +} ms_scan_data_t; + +typedef struct { + char *path; + int pid; +} ms_register_data_t; + +/** + * @} + */ + +#endif /*_MEDIA_SERVER_TYPES_H_*/ diff --git a/common/include/media-server-utils.h b/common/include/media-server-utils.h new file mode 100755 index 0000000..d8b6d96 --- /dev/null +++ b/common/include/media-server-utils.h @@ -0,0 +1,96 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-utils.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SERVER_UTILS_H__ +#define _MEDIA_SERVER_UTILS_H__ + +#include "media-server-types.h" + +int +ms_set_db_status(ms_db_status_type_t status); + +int +ms_db_init(bool need_db_create); + +bool +ms_is_mmc_inserted(void); + +void +ms_usb_vconf_cb(void *data); + +int +ms_start(bool need_db_create); + +void +ms_end(void); + +int +ms_get_full_path_from_node(ms_dir_scan_info * const node, char *ret_path, int depth); + +ms_storage_type_t +ms_get_storage_type_by_full(const char *path); + +int +ms_strappend(char *res, const int size, const char *pattern, + const char *str1, const char *str2); + +int +ms_strcopy(char *res, const int size, const char *pattern, + const char *str1); + +bool +ms_config_get_int(const char *key, int *value); + +bool +ms_config_set_int(const char *key, int value); + +bool +ms_config_get_str(const char *key, char *value); + +bool +ms_config_set_str(const char *key, const char *value); + +#ifdef FMS_PERF +void +ms_check_start_time(struct timeval *start_time); + +void +ms_check_end_time(struct timeval *end_time); + +void +ms_check_time_diff(struct timeval *start_time, struct timeval *end_time); +#endif/*FMS_PERF */ + + +/** + * @} + */ +#endif/*_MEDIA_SERVER_UTILS_H__*/ + diff --git a/common/media-server-db-svc.c b/common/media-server-db-svc.c new file mode 100755 index 0000000..77a320f --- /dev/null +++ b/common/media-server-db-svc.c @@ -0,0 +1,1297 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-db-svc.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ + +#include +#include + +#include "media-util.h" + +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-inotify.h" +#include "media-server-drm.h" +#include "media-server-db-svc.h" +#if MS_INOTI_ENABLE +GAsyncQueue* soc_queue; +GArray *reg_list; +GMutex *list_mutex; +GMutex *queue_mutex; +GMutex * db_mutex; + +#define MS_REGISTER_COUNT 100 /*For bundle commit*/ +#define MS_VALID_COUNT 100 /*For bundle commit*/ +#define MS_MOVE_COUNT 100 /*For bundle commit*/ + +void **func_handle = NULL; /*dlopen handel*/ + +enum func_list { + eCHECK, + eCONNECT, + eDISCONNECT, + eEXIST, + eINSERT_BEGIN, + eINSERT_END, + eINSERT_BATCH, + eINSERT, + eMOVE_BEGIN, + eMOVE_END, + eMOVE, + eSET_ALL_VALIDITY, + eSET_VALIDITY_BEGIN, + eSET_VALIDITY_END, + eSET_VALIDITY, + eDELETE, + eDELETE_ALL, + eDELETE_INVALID_ITEMS, + eUPDATE_BEGIN, + eUPDATE_END, + eREFRESH_ITEM, + eFUNC_MAX +}; + +static void +_ms_insert_reg_list(const char *path) +{ + char *reg_path = strdup(path); + + g_mutex_lock(list_mutex); + + g_array_append_val(reg_list, reg_path); + + g_mutex_unlock(list_mutex); +} + +static bool +_ms_find_reg_list(const char *path) +{ + int list_index; + int len = reg_list->len; + char *data; + bool res = false; + + g_mutex_lock(list_mutex); + MS_DBG("array length : %d", len); + + for(list_index = 0; list_index < len; list_index++) { + data = g_array_index (reg_list, char*, list_index); + if(!strcmp(data, path)) + res = true; + } + + g_mutex_unlock(list_mutex); + + return res; +} + +static void +_ms_delete_reg_list(const char *path) +{ + int list_index; + int len = reg_list->len; + char *data; + + MS_DBG("Delete : %s", path); + g_mutex_lock(list_mutex); + + for(list_index = 0; list_index < len; list_index++) { + data = g_array_index (reg_list, char*, list_index); + if(!strcmp(data, path)) { + MS_DBG("Delete complete : %s", data); + MS_SAFE_FREE(data); + g_array_remove_index(reg_list, list_index); + break; + } + } + + g_mutex_unlock(list_mutex); +} + +static int +_ms_get_mime(const char *path, char *mimetype) +{ + int ret = 0; + + if (path == NULL) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + /*get content type and mime type from file. */ + /*in case of drm file. */ + if (ms_is_drm_file(path)) { +#if MS_INOTI_ENABLE + ms_inoti_add_ignore_file(path); +#endif + ret = ms_get_mime_in_drm_info(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("Fail to get mime"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } else { + /*in case of normal files */ + if (aul_get_mime_from_file(path, mimetype, 255) < 0) { + MS_DBG_ERR("aul_get_mime_from_file fail"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +#define CONFIG_PATH "/opt/usr/data/file-manager-service/plugin-config" +#define EXT ".so" +#define EXT_LEN 3 + +GArray *so_array; +void ***func_array; +int lib_num; + +static int +_ms_check_category(const char *path, const char *mimetype, int index) +{ + int ret; + char *err_msg = NULL; + + ret = ((CHECK_ITEM)func_array[index][eCHECK])(path, mimetype, &err_msg); + if (ret != 0) { + MS_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, index), err_msg, path); + MS_SAFE_FREE(err_msg); + } + + return ret; +} + +static int +_ms_token_data(char *buf, char **name) +{ + int len; + char* pos = NULL; + + pos = strstr(buf, EXT); + if (pos == NULL) { + MS_DBG_ERR("This is not shared object library."); + name = NULL; + return -1; + } else { + len = pos - buf + EXT_LEN; + *name = strndup(buf, len); + MS_DBG("%s", *name); + } + + return 0; +} + + +static bool +_ms_load_config() +{ + int ret; + FILE *fp; + char *so_name = NULL; + char buf[256] = {0}; + + fp = fopen(CONFIG_PATH, "rt"); + if (fp == NULL) { + MS_DBG_ERR("fp is NULL"); + return MS_MEDIA_ERR_FILE_OPEN_FAIL; + } + while(1) { + if (fgets(buf, 256, fp) == NULL) { + MS_DBG_ERR("fgets failed"); + break; + } + + ret = _ms_token_data(buf, &so_name); + if (ret == 0) { + /*add to array*/ + g_array_append_val(so_array, so_name); + so_name = NULL; + } + } + + fclose(fp); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_load_functions(void) +{ + int lib_index = 0, func_index; + char func_list[eFUNC_MAX][40] = { + "check_item", + "connect", + "disconnect", + "check_item_exist", + "insert_item_begin", + "insert_item_end", + "insert_item", + "insert_item_immediately", + "move_item_begin", + "move_item_end", + "move_item", + "set_all_storage_items_validity", + "set_item_validity_begin", + "set_item_validity_end", + "set_item_validity", + "delete_item", + "delete_all_items_in_storage", + "delete_all_invalid_items_in_storage", + "update_begin", + "update_end", + "refresh_item" + }; + /*init array for adding name of so*/ + so_array = g_array_new(FALSE, FALSE, sizeof(char*)); + + /*load information of so*/ + _ms_load_config(); + + if(so_array->len == 0) { + MS_DBG("There is no information for functions"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + + /*the number of functions*/ + lib_num = so_array->len; + + MS_DBG("The number of information of so : %d", lib_num); + MS_MALLOC(func_handle, sizeof(void*) * lib_num); + if (func_handle == NULL) { + MS_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + while(lib_index < lib_num) { + /*get handle*/ + MS_DBG("[name of so : %s]", g_array_index(so_array, char*, lib_index)); + func_handle[lib_index] = dlopen(g_array_index(so_array, char*, lib_index), RTLD_LAZY); + if (!func_handle[lib_index]) { + MS_DBG_ERR("%s", dlerror()); + MS_SAFE_FREE(func_handle); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + lib_index++; + } + + dlerror(); /* Clear any existing error */ + + /*allocate for array of functions*/ + MS_MALLOC(func_array, sizeof(void*) * lib_num); + if (func_array == NULL) { + MS_DBG_ERR("malloc failed"); + MS_SAFE_FREE(func_handle); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + for(lib_index = 0 ; lib_index < lib_num; lib_index ++) { + MS_MALLOC(func_array[lib_index], sizeof(void*) * eFUNC_MAX); + if (func_array[lib_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(func_handle); + + MS_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + } + + /*add functions to array */ + for (lib_index = 0; lib_index < lib_num; lib_index++) { + for (func_index = 0; func_index < eFUNC_MAX ; func_index++) { + func_array[lib_index][func_index] = dlsym(func_handle[lib_index], func_list[func_index]); + if (func_array[lib_index][func_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(func_handle); + + MS_DBG_ERR("dlsym failed"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + } + } + + return MS_MEDIA_ERR_NONE; +} + +void +ms_unload_functions(void) +{ + int lib_index; + + for (lib_index = 0; lib_index < lib_num; lib_index ++) + dlclose(func_handle[lib_index]); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (func_array[lib_index]) { + MS_SAFE_FREE(func_array[lib_index]); + } + } + + MS_SAFE_FREE (func_array); + MS_SAFE_FREE (func_handle); + if (so_array) g_array_free(so_array, TRUE); +} + +int +ms_connect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + /*Lock mutex for openning db*/ + g_mutex_lock(db_mutex); + + MS_MALLOC(*handle, sizeof (void*) * lib_num); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CONNECT)func_array[lib_index][eCONNECT])(&((*handle)[lib_index]), &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + } + + MS_DBG("connect Media DB"); + + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_disconnect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DISCONNECT)func_array[lib_index][eDISCONNECT])((*handle)[lib_index], &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return MS_MEDIA_ERR_DB_DISCONNECT_FAIL; + } + } + + MS_SAFE_FREE(*handle); + + MS_DBG("Disconnect Media DB"); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_validate_item(void **handle, char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + char mimetype[255] = {0}; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + storage_type = ms_get_storage_type_by_full(path); + + MS_DBG("[%s] %s", mimetype, path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(path, mimetype, lib_index)) { + /*check exist in Media DB, If file is not exist, insert data in DB. */ + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG("not exist in %d. insert data", lib_index); + MS_SAFE_FREE(err_msg); + + ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } else { + /*if meta data of file exist, change valid field to "1" */ + ret = ((SET_ITEM_VALIDITY)func_array[lib_index][eSET_VALIDITY])(handle[lib_index], path, true, mimetype, true, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + } + } + + if (ms_is_drm_file(path)) { + ret = ms_drm_register(path); + } + + return res; +} + +int +ms_invalidate_all_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + MS_DBG(""); + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ALL_STORAGE_ITEMS_VALIDITY)func_array[lib_index][eSET_ALL_VALIDITY])(handle[lib_index], store_type, false, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + MS_DBG(""); + return res; +} + +int +ms_register_file(void **handle, const char *path, GAsyncQueue* queue) +{ + MS_DBG("[%d]register file : %s", syscall(__NR_gettid), path); + + int res = MS_MEDIA_ERR_NONE; + int ret; + + if (path == NULL) { + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + /*check item in DB. If it exist in DB, return directly.*/ + ret = ms_check_exist(handle, path); + if (ret == MS_MEDIA_ERR_NONE) { + MS_DBG("Already exist"); + return MS_MEDIA_ERR_NONE; + } + + g_mutex_lock(queue_mutex); + /*first request for this file*/ + if(!_ms_find_reg_list(path)) { + /*insert registering file list*/ + _ms_insert_reg_list(path); + } else { + MS_DBG("______________________ALREADY INSERTING"); + if(queue != NULL) { + MS_DBG("Need reply"); + soc_queue = queue; + } + g_mutex_unlock(queue_mutex); + return MS_MEDIA_ERR_NOW_REGISTER_FILE; + } + g_mutex_unlock(queue_mutex); + + ret = ms_insert_item(handle, path); + if (ret != MS_MEDIA_ERR_NONE) { + int lib_index; + char mimetype[255]; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + res = MS_MEDIA_ERR_MIME_GET_FAIL; + goto END; + } + storage_type = ms_get_storage_type_by_full(path); + + MS_DBG("[%s] %s", mimetype, path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + /*check item is already inserted*/ + if (!_ms_check_category(path, mimetype, lib_index)) { + char *err_msg = NULL; + + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret == 0) { + res = MS_MEDIA_ERR_NONE; + } else { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } + } + } +END: + if (ms_is_drm_file(path)) { + ret = ms_drm_register(path); + } + + g_mutex_lock(queue_mutex); + + _ms_delete_reg_list(path); + + if (soc_queue != NULL) { + MS_DBG("%d", res); + g_async_queue_push(soc_queue, GINT_TO_POINTER(res+MS_MEDIA_ERR_MAX)); + MS_DBG("Return OK"); + } + soc_queue = NULL; + g_mutex_unlock(queue_mutex); + + return res; +} + +int +ms_insert_item_batch(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255] = {0}; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + storage_type = ms_get_storage_type_by_full(path); + + MS_DBG("[%s] %s", mimetype, path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(path, mimetype, lib_index)) { + ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } + } + + if (ms_is_drm_file(path)) { + ret = ms_drm_register(path); + res = ret; + } + + return res; +} + +int +ms_insert_item(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255] = {0}; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + storage_type = ms_get_storage_type_by_full(path); + + MS_DBG("[%s] %s", mimetype, path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(path, mimetype, lib_index)) { + ret = ((INSERT_ITEM_IMMEDIATELY)func_array[lib_index][eINSERT])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } + } + + return res; +} + +int +ms_delete_item(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + storage_type = ms_get_storage_type_by_full(path); + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret == 0) { + ret = ((DELETE_ITEM)func_array[lib_index][eDELETE])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret !=0 ) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_DELETE_FAIL; + } + } else { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_DELETE_FAIL; + } + } + + if (ms_is_drm_file(path)) { + ms_drm_unregister(path); + } + + return res; +} + +int +ms_move_item(void **handle, + ms_storage_type_t src_store, ms_storage_type_t dst_store, + const char *src_path, const char *dst_path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255]; + char *err_msg = NULL; + + ret = _ms_get_mime(dst_path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + MS_DBG("[%s] %s", mimetype, dst_path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(dst_path, mimetype, lib_index)) { + ret = ((MOVE_ITEM)func_array[lib_index][eMOVE])(handle[lib_index], src_path, src_store, + dst_path, dst_store, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + } + + return res; +} + +bool +ms_delete_all_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + /* To reset media db when differnet mmc is inserted. */ + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DELETE_ALL_ITEMS_IN_STORAGE)func_array[lib_index][eDELETE_ALL])(handle[lib_index], store_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return false; + } + } + + return true; +} + +bool +ms_delete_invalid_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int ret; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DELETE_ALL_INVALID_ITMES_IN_STORAGE)func_array[lib_index][eDELETE_INVALID_ITEMS])(handle[lib_index], store_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return false; + } + } + + return true; +} + +int +ms_refresh_item(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255]; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + MS_DBG("[%s] %s", mimetype, path); + + storage_type = ms_get_storage_type_by_full(path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(path, mimetype, lib_index)) { + ret = ((REFRESH_ITEM)func_array[lib_index][eREFRESH_ITEM])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + } + + return res; +} + +int +ms_check_exist(void **handle, const char *path) +{ + int lib_index; + int ret; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + storage_type = ms_get_storage_type_by_full(path); + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret != 0) { + return MS_MEDIA_ERR_DB_EXIST_ITEM_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +/**************************************************************************************************** +FOR BULK COMMIT +*****************************************************************************************************/ + +void +ms_register_start(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((INSERT_ITEM_BEGIN)func_array[lib_index][eINSERT_BEGIN])(handle[lib_index], MS_REGISTER_COUNT, &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +ms_register_end(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((INSERT_ITEM_END)func_array[lib_index][eINSERT_END])(handle[lib_index], &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +ms_validate_start(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ITEM_VALIDITY_BEGIN)func_array[lib_index][eSET_VALIDITY_BEGIN])(handle[lib_index], MS_VALID_COUNT, &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +ms_validate_end(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ITEM_VALIDITY_END)func_array[lib_index][eSET_VALIDITY_END])(handle[lib_index], &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +ms_move_start(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((MOVE_ITEM_BEGIN)func_array[lib_index][eMOVE_BEGIN])(handle[lib_index], MS_MOVE_COUNT, &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +ms_move_end(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((MOVE_ITEM_END)func_array[lib_index][eMOVE_END])(handle[lib_index], &err_msg);/*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} +#else + +GMutex * db_mutex; +#define CONFIG_PATH "/opt/usr/data/file-manager-service/plugin-config" +#define EXT ".so" +#define EXT_LEN 3 + +GArray *so_array; +void ***func_array; +int lib_num; + +void **func_handle = NULL; /*dlopen handle*/ + +enum func_list { + eCHECK, + eCONNECT, + eDISCONNECT, + eEXIST, + eINSERT, + eSET_ALL_VALIDITY, + eFUNC_MAX +}; + +static int +_ms_get_mime(const char *path, char *mimetype) +{ + int ret = 0; + + if (path == NULL) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + /*get content type and mime type from file. */ + /*in case of drm file. */ + if (ms_is_drm_file(path)) { +#if MS_INOTI_ENABLE + ms_inoti_add_ignore_file(path); +#endif + ret = ms_get_mime_in_drm_info(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("Fail to get mime"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } else { + /*in case of normal files */ + if (aul_get_mime_from_file(path, mimetype, 255) < 0) { + MS_DBG_ERR("aul_get_mime_from_file fail"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +static int +_ms_check_category(const char *path, const char *mimetype, int index) +{ + int ret; + char *err_msg = NULL; + + ret = ((CHECK_ITEM)func_array[index][eCHECK])(path, mimetype, &err_msg); + if (ret != 0) { + MS_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, index), err_msg, path); + MS_SAFE_FREE(err_msg); + } + + return ret; +} + +static int +_ms_token_data(char *buf, char **name) +{ + int len; + char* pos = NULL; + + pos = strstr(buf, EXT); + if (pos == NULL) { + MS_DBG_ERR("This is not shared object library."); + name = NULL; + return -1; + } else { + len = pos - buf + EXT_LEN; + *name = strndup(buf, len); + MS_DBG("%s", *name); + } + + return 0; +} + +static bool +_ms_load_config() +{ + int ret; + FILE *fp; + char *so_name = NULL; + char buf[256] = {0}; + + fp = fopen(CONFIG_PATH, "rt"); + if (fp == NULL) { + MS_DBG_ERR("fp is NULL"); + return MS_MEDIA_ERR_FILE_OPEN_FAIL; + } + while(1) { + if (fgets(buf, 256, fp) == NULL) { + MS_DBG_ERR("fgets failed"); + break; + } + + ret = _ms_token_data(buf, &so_name); + if (ret == 0) { + /*add to array*/ + g_array_append_val(so_array, so_name); + so_name = NULL; + } + } + + fclose(fp); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_load_functions(void) +{ + int lib_index = 0, func_index; + char func_list[eFUNC_MAX][40] = { + "check_item", + "connect", + "disconnect", + "check_item_exist", + "insert_item_immediately", + "set_all_storage_items_validity", + }; + /*init array for adding name of so*/ + so_array = g_array_new(FALSE, FALSE, sizeof(char*)); + + /*load information of so*/ + _ms_load_config(); + + if(so_array->len == 0) { + MS_DBG("There is no information for functions"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + + /*the number of functions*/ + lib_num = so_array->len; + + MS_DBG("The number of information of so : %d", lib_num); + MS_MALLOC(func_handle, sizeof(void*) * lib_num); + if (func_handle == NULL) { + MS_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + while(lib_index < lib_num) { + /*get handle*/ + MS_DBG("[name of so : %s]", g_array_index(so_array, char*, lib_index)); + func_handle[lib_index] = dlopen(g_array_index(so_array, char*, lib_index), RTLD_LAZY); + if (!func_handle[lib_index]) { + MS_DBG_ERR("%s", dlerror()); + MS_SAFE_FREE(func_handle); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + lib_index++; + } + + dlerror(); /* Clear any existing error */ + + /*allocate for array of functions*/ + MS_MALLOC(func_array, sizeof(void*) * lib_num); + if (func_array == NULL) { + MS_DBG_ERR("malloc failed"); + MS_SAFE_FREE(func_handle); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + for(lib_index = 0 ; lib_index < lib_num; lib_index ++) { + MS_MALLOC(func_array[lib_index], sizeof(void*) * eFUNC_MAX); + if (func_array[lib_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(func_handle); + + MS_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + } + + /*add functions to array */ + for (lib_index = 0; lib_index < lib_num; lib_index++) { + for (func_index = 0; func_index < eFUNC_MAX ; func_index++) { + func_array[lib_index][func_index] = dlsym(func_handle[lib_index], func_list[func_index]); + if (func_array[lib_index][func_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(func_handle); + + MS_DBG_ERR("dlsym failed"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + } + } + + return MS_MEDIA_ERR_NONE; +} + +void +ms_unload_functions(void) +{ + int lib_index; + + for (lib_index = 0; lib_index < lib_num; lib_index ++) + dlclose(func_handle[lib_index]); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (func_array[lib_index]) { + MS_SAFE_FREE(func_array[lib_index]); + } + } + + MS_SAFE_FREE (func_array); + MS_SAFE_FREE (func_handle); + if (so_array) g_array_free(so_array, TRUE); +} + +int +ms_connect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + /*Lock mutex for openning db*/ + g_mutex_lock(db_mutex); + + MS_MALLOC(*handle, sizeof (void*) * lib_num); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CONNECT)func_array[lib_index][eCONNECT])(&((*handle)[lib_index]), &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + } + + MS_DBG("connect Media DB"); + + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_disconnect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DISCONNECT)func_array[lib_index][eDISCONNECT])((*handle)[lib_index], &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return MS_MEDIA_ERR_DB_DISCONNECT_FAIL; + } + } + + MS_SAFE_FREE(*handle); + + MS_DBG("Disconnect Media DB"); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_check_exist(void **handle, const char *path) +{ + int lib_index; + int ret; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + storage_type = ms_get_storage_type_by_full(path); + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret != 0) { + return MS_MEDIA_ERR_DB_EXIST_ITEM_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +int +ms_insert_item(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255] = {0}; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + ret = _ms_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("err : _ms_get_mime [%d]", ret); + return ret; + } + storage_type = ms_get_storage_type_by_full(path); + + MS_DBG("[%s] %s", mimetype, path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_ms_check_category(path, mimetype, lib_index)) { + ret = ((INSERT_ITEM_IMMEDIATELY)func_array[lib_index][eINSERT])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } + } + + return res; +} + +int +ms_register_file(void **handle, const char *path) +{ + MS_DBG("[%d]register file : %s", syscall(__NR_gettid), path); + + int res = MS_MEDIA_ERR_NONE; + int ret; + + if (path == NULL) { + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + /*check item in DB. If it exist in DB, return directly.*/ + ret = ms_check_exist(handle, path); + if (ret == MS_MEDIA_ERR_NONE) { + MS_DBG("Already exist"); + return MS_MEDIA_ERR_NONE; + } + + ret = ms_insert_item(handle, path); + if (ret != MS_MEDIA_ERR_NONE) { + res = ret; + MS_DBG_ERR("ms_insert_item failed [%d]", ret); + } + + if (ms_is_drm_file(path)) { + ret = ms_drm_register(path); + } + + return res; +} + +int +ms_invalidate_all_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + MS_DBG(""); + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ALL_STORAGE_ITEMS_VALIDITY)func_array[lib_index][eSET_ALL_VALIDITY])(handle[lib_index], store_type, false, &err_msg); /*dlopen*/ + if (ret != 0) { + MS_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + MS_DBG(""); + return res; +} + +#endif diff --git a/common/media-server-db.c b/common/media-server-db.c new file mode 100755 index 0000000..ebd6425 --- /dev/null +++ b/common/media-server-db.c @@ -0,0 +1,139 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of media db write. + * + * @file media-server-db.c + * @author Haejeong Kim(backto.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include + +#include "media-util.h" + +#include "media-server-dbg.h" +#include "media-server-db.h" +#include "media-server-types.h" +#include "media-server-socket.h" +#include "media-server-db.h" +#include "media-server-ipc.h" + +static GMainLoop *g_db_mainloop = NULL; +static bool db_thread_ready = FALSE; + +GMainLoop *ms_db_get_mainloop(void) +{ + return g_db_mainloop; +} +gboolean ms_db_get_thread_status(void) +{ + return db_thread_ready; +} + +gboolean ms_db_thread(void *data) +{ + int sockfd = -1; + int tcp_sockfd = -1; + int ret = MS_MEDIA_ERR_NONE; + GSource *source = NULL; + GIOChannel *channel = NULL; + GSource *tcp_source = NULL; + GIOChannel *tcp_channel = NULL; + GMainContext *context = NULL; + MediaDBHandle *db_handle = NULL; + + /* Connect Media DB*/ + if(media_db_connect(&db_handle) != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("Failed to connect DB\n"); + return FALSE; + } + + /* Create Socket*/ + ret = ms_ipc_create_server_socket(MS_PROTOCOL_UDP, MS_DB_UPDATE_PORT, &sockfd); + if(ret != MS_MEDIA_ERR_NONE) { + /* Disconnect DB*/ + media_db_disconnect(db_handle); + + MS_DBG_ERR("Failed to create socket\n"); + return FALSE; + } + + /* Create TCP Socket for batch query*/ + ret = ms_ipc_create_server_socket(MS_PROTOCOL_TCP, MS_DB_BATCH_UPDATE_PORT, &tcp_sockfd); + if(ret != MS_MEDIA_ERR_NONE) { + /* Disconnect DB*/ + media_db_disconnect(db_handle); + + MS_DBG_ERR("Failed to create socket\n"); + return FALSE; + } + + context = g_main_context_new(); + /*Init main loop*/ + g_db_mainloop = g_main_loop_new(context, FALSE); + //context = g_main_loop_get_context(g_db_mainloop); + + /* Create new channel to watch udp socket */ + channel = g_io_channel_unix_new(sockfd); + source = g_io_create_watch(channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)ms_read_db_socket, db_handle, NULL); + g_source_attach(source, context); + + /* Create new channel to watch TCP socket */ + tcp_channel = g_io_channel_unix_new(tcp_sockfd); + tcp_source = g_io_create_watch(tcp_channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(tcp_source, (GSourceFunc)ms_read_db_tcp_socket, db_handle, NULL); + g_source_attach(tcp_source, context); + + g_main_context_push_thread_default(context); + + MS_DBG("*******************************************"); + MS_DBG("*** Media Server DB thread is running ***"); + MS_DBG("*******************************************"); + + db_thread_ready = TRUE; + + g_main_loop_run(g_db_mainloop); + + MS_DBG("*** Media Server DB thread will be closed ***"); + + db_thread_ready = FALSE; + + g_io_channel_shutdown(channel, FALSE, NULL); + g_io_channel_unref(channel); + + /* Disconnect DB*/ + media_db_disconnect(db_handle); + + /*close socket*/ + close(sockfd); + + g_main_loop_unref(g_db_mainloop); + + return FALSE; +} diff --git a/common/media-server-dbus.c b/common/media-server-dbus.c new file mode 100755 index 0000000..718f939 --- /dev/null +++ b/common/media-server-dbus.c @@ -0,0 +1,81 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include "media-server-dbg.h" +#include "media-server-types.h" +#include "media-server-dbus.h" + +void ms_dbus_init(void) +{ + DBusConnection *bus; + DBusError error; + + /* Get a connection to the session bus */ + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) { + MS_DBG ("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free (&error); + return; + } + + /* Set up this connection to work in a GLib event loop */ + dbus_connection_setup_with_g_main (bus, NULL); +} + +gboolean ms_dbus_send_noti(ms_dbus_noti_type_t data) +{ + MS_DBG(""); + DBusMessage *message; + DBusConnection *bus; + DBusError error; + dbus_uint16_t noti_type = data; + + /* Get a connection to the session bus */ + dbus_error_init (&error); + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) { + MS_DBG ("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free (&error); + return false; + } + + /* Create a new signal on the "MS_DBUS_INTERFACE" interface, + * from the object "MS_DBUS_PATH". */ + message = dbus_message_new_signal (MS_DBUS_PATH, MS_DBUS_INTERFACE, MS_DBUS_NAME); + + /* Append the notification type to the signal */ + dbus_message_append_args (message, DBUS_TYPE_UINT16, ¬i_type, DBUS_TYPE_INVALID); + + /* Send the signal */ + dbus_connection_send (bus, message, NULL); + + /* Free the signal now we have finished with it */ + dbus_message_unref (message); + + /* Return TRUE to tell the event loop we want to be called again */ + return true; +} \ No newline at end of file diff --git a/common/media-server-drm.c b/common/media-server-drm.c new file mode 100755 index 0000000..65687f2 --- /dev/null +++ b/common/media-server-drm.c @@ -0,0 +1,137 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-drm.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ +#include +#include + +#include "media-util.h" + +#include "media-server-dbg.h" +#include "media-server-types.h" +#include "media-server-inotify.h" +#include "media-server-drm.h" + +bool +ms_is_drm_file(const char *path) +{ + int ret; + drm_bool_type_e is_drm_file = DRM_UNKNOWN; + + ret = drm_is_drm_file(path,&is_drm_file); + if(DRM_RETURN_SUCCESS == ret && DRM_TRUE == is_drm_file) + return true; + + return false; +} + +int +ms_get_mime_in_drm_info(const char *path, char *mime) +{ + int ret; + drm_content_info_s contentInfo; + + if (path == NULL || mime == NULL) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + memset(&contentInfo,0x0,sizeof(drm_content_info_s)); + ret = drm_get_content_info(path, &contentInfo); + if (ret != DRM_RETURN_SUCCESS) { + MS_DBG_ERR("drm_svc_get_content_info() fails. "); + return MS_MEDIA_ERR_DRM_GET_INFO_FAIL; + } + + strncpy(mime, contentInfo.mime_type, 100); + MS_DBG("DRM contentType : %s", contentInfo.mime_type); + MS_DBG("DRM mime : %s", mime); + + return MS_MEDIA_ERR_NONE; +} + +int +ms_drm_register(const char* path) +{ + MS_DBG("THIS IS DRM FILE"); + int res = MS_MEDIA_ERR_NONE; + int ret; +#if MS_INOTI_ENABLE +// ms_inoti_add_ignore_file(path); +#endif + ret = drm_process_request(DRM_REQUEST_TYPE_REGISTER_FILE, (void *)path, NULL); + if (ret != DRM_RETURN_SUCCESS) { + MS_DBG_ERR("drm_svc_register_file error : %d", ret); + res = MS_MEDIA_ERR_DRM_REGISTER_FAIL; + } + + return res; +} + +void +ms_drm_unregister(const char* path) +{ + int ret; +#if MS_INOTI_ENABLE + ms_ignore_file_info *ignore_file; +#endif + ret = drm_process_request(DRM_REQUEST_TYPE_UNREGISTER_FILE, (void *)path, NULL); + if (ret != DRM_RETURN_SUCCESS) + MS_DBG_ERR("drm_process_request error : %d", ret); +#if MS_INOTI_ENABLE + ignore_file = ms_inoti_find_ignore_file(path); + if (ignore_file != NULL) + ms_inoti_delete_ignore_file(ignore_file); +#endif +} + +void +ms_drm_unregister_all(void) +{ + if (drm_process_request(DRM_REQUEST_TYPE_UNREGISTER_ALL_FILES , NULL, NULL) == DRM_RETURN_SUCCESS) + MS_DBG("drm_svc_unregister_all_contents OK"); +} + +bool +ms_drm_insert_ext_memory(void) +{ + MS_DBG(""); + if (drm_process_request(DRM_REQUEST_TYPE_INSERT_EXT_MEMORY, NULL, NULL) != DRM_RETURN_SUCCESS) + return false; + + return true; +} + +bool +ms_drm_extract_ext_memory(void) +{ + MS_DBG(""); + if (drm_process_request(DRM_REQUEST_TYPE_EXTRACT_EXT_MEMORY , NULL, NULL) != DRM_RETURN_SUCCESS) + return false; + + return true; +} + diff --git a/common/media-server-external-storage.c b/common/media-server-external-storage.c new file mode 100755 index 0000000..e5abd5b --- /dev/null +++ b/common/media-server-external-storage.c @@ -0,0 +1,338 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "media-util.h" +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-ipc.h" +#include "media-server-socket.h" +#include "media-server-inotify.h" +#include "media-server-db-svc.h" +#include "media-server-scanner.h" +#include "media-server-external-storage.h" +#include "media-server-drm.h" + +#define MMC_INFO_SIZE 256 + +int mmc_state = 0; + +char default_path[][MS_FILE_NAME_LEN_MAX + 1] = { + {"/opt/storage/sdcard/Images"}, + {"/opt/storage/sdcard/Videos"}, + {"/opt/storage/sdcard/Sounds"}, + {"/opt/storage/sdcard/Downloads"}, + {"/opt/storage/sdcard/Camera"} +}; + +#define DIR_NUM ((int)(sizeof(default_path)/sizeof(default_path[0]))) + +void +ms_make_default_path_mmc(void) +{ + int i = 0; + int ret = 0; + DIR *dp = NULL; + + for (i = 0; i < DIR_NUM; ++i) { + dp = opendir(default_path[i]); + if (dp == NULL) { + ret = mkdir(default_path[i], 0777); + if (ret < 0) { + MS_DBG("make fail"); + } else { +#if MS_INOTI_ENABLE + ms_inoti_add_watch(default_path[i]); +#endif + /*this fuction for emulator*/ + /*at the first time, the directroies are made permission 755*/ + chmod(default_path[i], 0777); + chown(default_path[i], 5000, 5000); + } + } else { + closedir(dp); + } + } +} + +int +_ms_update_mmc_info(const char *cid) +{ + bool res; + + if (cid == NULL) { + MS_DBG_ERR("Parameters are invalid"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res = ms_config_set_str(MS_MMC_INFO_KEY, cid); + if (!res) { + MS_DBG_ERR("fail to get MS_MMC_INFO_KEY"); + return MS_MEDIA_ERR_VCONF_SET_FAIL; + } + + return MS_MEDIA_ERR_NONE; +} + +bool +_ms_check_mmc_info(const char *cid) +{ + char pre_mmc_info[MMC_INFO_SIZE] = { 0 }; + bool res = false; + + if (cid == NULL) { + MS_DBG_ERR("Parameters are invalid"); + return false; + } + + res = ms_config_get_str(MS_MMC_INFO_KEY, pre_mmc_info); + if (!res) { + MS_DBG_ERR("fail to get MS_MMC_INFO_KEY"); + return false; + } + + MS_DBG("Last MMC info = %s", pre_mmc_info); + MS_DBG("Current MMC info = %s", cid); + + if (strcmp(pre_mmc_info, cid) == 0) { + return true; + } + + return false; +} + +static int +_get_contents(const char *filename, char *buf) +{ + FILE *fp; + + fp = fopen(filename, "rt"); + if (fp == NULL) { + MS_DBG_ERR("fp is NULL. file name : %s", filename); + return MS_MEDIA_ERR_FILE_OPEN_FAIL; + } + if (fgets(buf, 255, fp) == NULL) + MS_DBG_ERR("fgets failed"); + + fclose(fp); + + return MS_MEDIA_ERR_NONE; +} + +/*need optimize*/ +int +_ms_get_mmc_info(char *cid) +{ + int i; + int j; + int len; + int err = -1; + bool getdata = false; + bool bHasColon = false; + char path[MS_FILE_PATH_LEN_MAX] = { 0 }; + char mmcpath[MS_FILE_PATH_LEN_MAX] = { 0 }; + + DIR *dp; + struct dirent ent; + struct dirent *res = NULL; + + /* mmcblk0 and mmcblk1 is reserved for movinand */ + for (j = 1; j < 3; j++) { + len = snprintf(mmcpath, MS_FILE_PATH_LEN_MAX, "/sys/class/mmc_host/mmc%d/", j); + if (len < 0) { + MS_DBG_ERR("FAIL : snprintf"); + return MS_MEDIA_ERR_INTERNAL; + } + else { + mmcpath[len] = '\0'; + } + + dp = opendir(mmcpath); + if (dp == NULL) { + MS_DBG_ERR("dp is NULL"); + return MS_MEDIA_ERR_DIR_OPEN_FAIL; + } + + while (!readdir_r(dp, &ent, &res)) { + /*end of read dir*/ + if (res == NULL) + break; + + bHasColon = false; + if (ent.d_name[0] == '.') + continue; + + if (ent.d_type == DT_DIR) { + /*ent->d_name is including ':' */ + for (i = 0; i < strlen(ent.d_name); i++) { + if (ent.d_name[i] == ':') { + bHasColon = true; + break; + } + } + + if (bHasColon) { + /*check serial */ + err = ms_strappend(path, sizeof(path), "%s%s/cid", mmcpath, ent.d_name); + if (err < 0) { + MS_DBG_ERR("ms_strappend error : %d", err); + continue; + } + + if (_get_contents(path, cid) != MS_MEDIA_ERR_NONE) + break; + else + getdata = true; + } + } + } + closedir(dp); + + if (getdata == true) { + break; + } + } + + return MS_MEDIA_ERR_NONE; +} + +ms_dir_scan_type_t +ms_get_mmc_state(void) +{ + char cid[MMC_INFO_SIZE] = { 0 }; + ms_dir_scan_type_t ret = MS_SCAN_ALL; + + /*get new info */ + _ms_get_mmc_info(cid); + + /*check it's same mmc */ + if (_ms_check_mmc_info(cid)) { + ret = MS_SCAN_PART; + } + + return ret; +} + +int +ms_update_mmc_info(void) +{ + int err; + char cid[MMC_INFO_SIZE] = { 0 }; + + err = _ms_get_mmc_info(cid); + + err = _ms_update_mmc_info(cid); + + /*Active flush */ + if (!malloc_trim(0)) + MS_DBG_ERR("malloc_trim is failed"); + + return err; +} + +#define _GETSYSTEMSTR(ID) dgettext("sys_string", (ID)) + +void update_lang(void) +{ + char *lang; + char *r; + + lang = vconf_get_str(VCONFKEY_LANGSET); + if (lang) { + setenv("LANG", lang, 1); + setenv("LC_MESSAGES", lang, 1); + r = setlocale(LC_ALL, ""); + if (r == NULL) { + r = setlocale(LC_ALL, vconf_get_str(VCONFKEY_LANGSET)); + MS_DBG_ERR("*****appcore setlocale=%s\n", r); + } + free(lang); + } +} + +int +ms_present_mmc_insert(void) +{ + int ret; + + update_lang(); + + ret = notification_status_message_post(_GETSYSTEMSTR("IDS_COM_BODY_PREPARING_SD_CARD")); + if(ret != NOTIFICATION_ERROR_NONE) + return MS_MEDIA_ERR_INTERNAL; + + return MS_MEDIA_ERR_NONE; +} + +void +ms_mmc_vconf_cb(void *data) +{ + int status = 0; + + if (!ms_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status)) { + MS_DBG_ERR("Get VCONFKEY_SYSMAN_MMC_STATUS failed."); + } + + MS_DBG("VCONFKEY_SYSMAN_MMC_STATUS :%d", status); + + mmc_state = status; + + /* If scanner is not working, media server executes media scanner and sends request. */ + /* If scanner is working, it detects changing status of SD card. */ + if (mmc_state == VCONFKEY_SYSMAN_MMC_REMOVED || + mmc_state == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED) { + + /*remove added watch descriptors */ +#if MS_INOTI_ENABLE + ms_inoti_remove_watch_recursive(MEDIA_ROOT_PATH_SDCARD); + ms_inoti_delete_mmc_ignore_file(); +#endif + if (!ms_get_scanner_status()) { + if (!ms_drm_extract_ext_memory()) + MS_DBG_ERR("ms_drm_extract_ext_memory failed"); + + ms_send_storage_scan_request(MS_STORAGE_EXTERNAL, MS_SCAN_INVALID); + } + } else if (mmc_state == VCONFKEY_SYSMAN_MMC_MOUNTED) { + + ms_make_default_path_mmc(); +#if MS_INOTI_ENABLE + ms_inoti_add_watch_all_directory(MS_STORAGE_EXTERNAL); +#endif + ms_present_mmc_insert(); + + if (!ms_get_scanner_status()) { + if (!ms_drm_insert_ext_memory()) + MS_DBG_ERR("ms_drm_insert_ext_memory failed"); + + ms_send_storage_scan_request(MS_STORAGE_EXTERNAL, ms_get_mmc_state()); + } + } + + return; +} + diff --git a/common/media-server-inotify-internal.c b/common/media-server-inotify-internal.c new file mode 100755 index 0000000..136e380 --- /dev/null +++ b/common/media-server-inotify-internal.c @@ -0,0 +1,125 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-inotify-internal.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief23 + */ +#include "media-util.h" + +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-inotify-internal.h" +#if MS_INOTI_ENABLE +int inoti_fd; +ms_create_file_info *latest_create_file; +extern ms_inoti_dir_data *first_inoti_node; + +int _ms_inoti_add_create_file_list(int wd, char *name) +{ + ms_create_file_info *new_node; + + new_node = malloc(sizeof(ms_create_file_info)); + new_node->name = strdup(name); + new_node->wd = wd; + + /*first created file */ + if (latest_create_file == NULL) { + latest_create_file = malloc(sizeof(ms_create_file_info)); + new_node->previous = NULL; + } else { + latest_create_file->next = new_node; + new_node->previous = latest_create_file; + } + new_node->next = NULL; + + latest_create_file = new_node; + + return MS_MEDIA_ERR_NONE; +} + +int _ms_inoti_delete_create_file_list(ms_create_file_info *node) +{ + if (node->previous != NULL) + node->previous->next = node->next; + if (node->next != NULL) + node->next->previous = node->previous; + + if (node == latest_create_file) { + latest_create_file = node->previous; + } + + MS_SAFE_FREE(node->name); + MS_SAFE_FREE(node); + + return MS_MEDIA_ERR_NONE; +} + +ms_create_file_info *_ms_inoti_find_create_file_list(int wd, char *name) +{ + ms_create_file_info *node = NULL; + node = latest_create_file; + + while (node != NULL) { + if ((node->wd == wd) && (strcmp(node->name, name) == 0)) { + return node; + } + + node = node->previous; + } + + return NULL; +} + +bool _ms_inoti_get_full_path(int wd, char *name, char *path, int sizeofpath) +{ + int err; + ms_inoti_dir_data *node = NULL; + + if (name == NULL || path == NULL) + return false; + + if (first_inoti_node != NULL) { + node = first_inoti_node; + while (node->next != NULL) { + if (wd == node->wd) { + break; + } + node = node->next; + } + } else { + return false; + } + + err = ms_strappend(path, sizeofpath, "%s/%s", node->name, name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strappend error : %d", err); + return false; + } + MS_DBG("full path : %s", path); + return true; +} + +#endif diff --git a/common/media-server-inotify.c b/common/media-server-inotify.c new file mode 100755 index 0000000..3f922ff --- /dev/null +++ b/common/media-server-inotify.c @@ -0,0 +1,889 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-inotify.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#include +#include +#include +#include + +#include "media-util.h" +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-db-svc.h" +#include "media-server-inotify-internal.h" +#include "media-server-inotify.h" + +#if MS_INOTI_ENABLE + +bool power_off; +extern int inoti_fd; +extern int mmc_state; +ms_inoti_dir_data *first_inoti_node; +ms_ignore_file_info *latest_ignore_file; + +int _ms_inoti_directory_scan_and_register_file(void **handle, char *dir_path) +{ + struct dirent ent; + struct dirent *res = NULL; + DIR *dp = NULL; + char path[MS_FILE_PATH_LEN_MAX] = { 0 }; + int err; + + if (dir_path == NULL) + return MS_MEDIA_ERR_INVALID_PATH; + + dp = opendir(dir_path); + if (dp == NULL) { + MS_DBG_ERR("Fail to open dir %s", dir_path); + return MS_MEDIA_ERR_DIR_OPEN_FAIL; + } + + ms_inoti_add_watch(dir_path); + + while (!readdir_r(dp, &ent, &res)) { + if (res == NULL) + break; + + if (ent.d_name[0] == '.') + continue; + + err = ms_strappend(path, sizeof(path), "%s/%s", dir_path, ent.d_name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strappend error : %d", err); + continue; + } + + /*in case of directory */ + if (ent.d_type == DT_DIR) { + _ms_inoti_directory_scan_and_register_file(handle, path); + } else { + err = ms_register_file(handle, path, NULL); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_register_file error : %d", err); + continue; + } + } + } + + closedir(dp); + + return 0; +} + +int _ms_inoti_scan_renamed_folder(void **handle, char *org_path, char *chg_path) +{ + int err = -1; + struct dirent ent; + struct dirent *res = NULL; + + DIR *dp = NULL; + char path_from[MS_FILE_PATH_LEN_MAX] = { 0 }; + char path_to[MS_FILE_PATH_LEN_MAX] = { 0 }; + ms_storage_type_t src_storage = 0; + ms_storage_type_t des_storage = 0; + + if (org_path == NULL || chg_path == NULL) { + MS_DBG_ERR("Parameter is wrong"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + dp = opendir(chg_path); + if (dp == NULL) { + MS_DBG_ERR("Fail to open dir %s", chg_path); + return MS_MEDIA_ERR_DIR_OPEN_FAIL; + } else { + MS_DBG("Modify added watch"); + ms_inoti_modify_watch(org_path, chg_path); + } + + while (!readdir_r(dp, &ent, &res)) { + if (res == NULL) + break; + + if (ent.d_name[0] == '.') + continue; + + err = ms_strappend(path_from, sizeof(path_from), "%s/%s", org_path, ent.d_name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strappend error : %d", err); + continue; + } + + err = ms_strappend(path_to, sizeof(path_to), "%s/%s", chg_path, ent.d_name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strappend error : %d", err); + continue; + } + + /*in case of directory */ + if (ent.d_type == DT_DIR) { + _ms_inoti_scan_renamed_folder(handle, path_from, path_to); + } + + /*in case of file */ + if (ent.d_type == DT_REG) { + src_storage = ms_get_storage_type_by_full(path_from); + des_storage = ms_get_storage_type_by_full(path_to); + + if ((src_storage != MS_MEDIA_ERR_INVALID_PATH) + && (des_storage != MS_MEDIA_ERR_INVALID_PATH)) + ms_move_item(handle, src_storage, des_storage, path_from, path_to); + else { + MS_DBG_ERR("src_storage : %s", src_storage); + MS_DBG_ERR("des_storage : %s", des_storage); + } + } + } + + closedir(dp); + + return 0; +} + +int ms_inoti_add_ignore_file(const char *path) +{ + ms_ignore_file_info *new_node; + + new_node = ms_inoti_find_ignore_file(path); + if (new_node != NULL) + return MS_MEDIA_ERR_NONE; + + new_node = malloc(sizeof(ms_ignore_file_info)); + new_node->path = strdup(path); + + /*first created file */ + if (latest_ignore_file == NULL) { + latest_ignore_file = malloc(sizeof(ms_ignore_file_info)); + new_node->previous = NULL; + } else { + latest_ignore_file->next = new_node; + new_node->previous = latest_ignore_file; + } + new_node->next = NULL; + + latest_ignore_file = new_node; + + return MS_MEDIA_ERR_NONE; +} + +int ms_inoti_delete_ignore_file(ms_ignore_file_info * delete_node) +{ + if (delete_node->previous != NULL) + delete_node->previous->next = delete_node->next; + if (delete_node->next != NULL) + delete_node->next->previous = delete_node->previous; + + if (delete_node == latest_ignore_file) { + latest_ignore_file = delete_node->previous; + } + + MS_SAFE_FREE(delete_node->path); + MS_SAFE_FREE(delete_node); + + + return MS_MEDIA_ERR_NONE; +} + +ms_ignore_file_info *ms_inoti_find_ignore_file(const char *path) +{ + ms_ignore_file_info *node = NULL; + + node = latest_ignore_file; + while (node != NULL) { + if (strcmp(node->path, path) == 0) { + return node; + } + + node = node->previous; + } + + return NULL; +} + +void ms_inoti_delete_mmc_ignore_file(void) +{ + ms_ignore_file_info *prv_node = NULL; + ms_ignore_file_info *cur_node = NULL; + ms_ignore_file_info *del_node = NULL; + + if (latest_ignore_file != NULL) { + cur_node = latest_ignore_file; + while (cur_node != NULL) { + if (strstr(cur_node->path, MEDIA_ROOT_PATH_SDCARD) != NULL) { + if (prv_node != NULL) { + prv_node->previous = cur_node->previous; + } + + if (cur_node == latest_ignore_file) + latest_ignore_file = latest_ignore_file->previous; + + del_node = cur_node; + } else { + prv_node = cur_node; + } + + cur_node = cur_node->previous; + + if (del_node != NULL) { + MS_SAFE_FREE(del_node->path); + MS_SAFE_FREE(del_node); + } + } + } + + /*active flush */ + malloc_trim(0); +} + +int ms_inoti_init(void) +{ + inoti_fd = inotify_init(); + if (inoti_fd < 0) { + perror("inotify_init"); + MS_DBG_ERR("inotify_init failed"); + return inoti_fd; + } + + return MS_MEDIA_ERR_NONE; +} + +void ms_inoti_add_watch(char *path) +{ + ms_inoti_dir_data *current_dir = NULL; + ms_inoti_dir_data *prv_node = NULL; + ms_inoti_dir_data *last_node = NULL; + + /*find same folder */ + if (first_inoti_node != NULL) { + last_node = first_inoti_node; + while (last_node != NULL) { + if (strcmp(path, last_node->name) == 0) { + MS_DBG("watch is already added: %s", path); + return; + } + prv_node = last_node; + last_node = last_node->next; + } + } + + /*there is no same path. */ + current_dir = malloc(sizeof(ms_inoti_dir_data)); + current_dir->wd = inotify_add_watch(inoti_fd, path, + IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | + IN_MOVED_FROM | IN_MOVED_TO); + + if (current_dir->wd > 0) { + current_dir->name = strdup(path); + current_dir->next = NULL; + + if (first_inoti_node == NULL) { + first_inoti_node = current_dir; + } else { + /*if next node of current node is NULL, it is the lastest node. */ + prv_node->next = current_dir; + } + MS_DBG("add watch : %s", path); + } else { + MS_DBG_ERR("inotify_add_watch failed"); + MS_SAFE_FREE(current_dir); + } +} + +int ms_inoti_add_watch_with_node(ms_dir_scan_info * const node, int depth) +{ + int err; + char full_path[MS_FILE_PATH_LEN_MAX] = { 0 }; + ms_inoti_dir_data *current_dir = NULL; + ms_inoti_dir_data *prv_node = NULL; + ms_inoti_dir_data *last_node = NULL; + + err = ms_get_full_path_from_node(node, full_path, depth); + if (err != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_INVALID_PATH; + + /*find same folder */ + if (first_inoti_node != NULL) { + last_node = first_inoti_node; + while (last_node != NULL) { + if (strcmp(full_path, last_node->name) == 0) { + return MS_MEDIA_ERR_NONE; + } + prv_node = last_node; + last_node = last_node->next; + } + } + + /*there is no same path. */ + current_dir = malloc(sizeof(ms_inoti_dir_data)); + current_dir->wd = inotify_add_watch(inoti_fd, full_path, + IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | + IN_MOVED_FROM | IN_MOVED_TO); + if( current_dir->wd > 0) { + current_dir->name = strdup(full_path); + current_dir->next = NULL; + + if (first_inoti_node == NULL) { + first_inoti_node = current_dir; + } else { + /*if next node of current node is NULL, it is the lastest node. */ + prv_node->next = current_dir; + } + MS_DBG("add watch : %s", full_path); + } else { + MS_DBG_ERR("inotify_add_watch failed : %d", current_dir->wd); + MS_SAFE_FREE(current_dir); + } + + return MS_MEDIA_ERR_NONE; +} + +void ms_inoti_remove_watch_recursive(char *path) +{ + ms_inoti_dir_data *prv_node = NULL; + ms_inoti_dir_data *cur_node = NULL; + ms_inoti_dir_data *del_node = NULL; + + if (first_inoti_node != NULL) { + cur_node = first_inoti_node; + while (cur_node != NULL) { + if (strstr(cur_node->name, path) != NULL) { + if (prv_node != NULL) { + prv_node->next = + cur_node->next; + } + + if (cur_node == first_inoti_node) + first_inoti_node = + first_inoti_node->next; + + del_node = cur_node; + } else { + prv_node = cur_node; + } + + cur_node = cur_node->next; + + if (del_node != NULL) { + MS_SAFE_FREE(del_node->name); + MS_SAFE_FREE(del_node); + } + } + } + + /*active flush */ + malloc_trim(0); +} + +void ms_inoti_remove_watch(char *path) +{ + ms_inoti_dir_data *del_node = NULL; + ms_inoti_dir_data *prv_node = NULL; + + if (strcmp(first_inoti_node->name, path) == 0) { + del_node = first_inoti_node; + first_inoti_node = first_inoti_node->next; + } else { + /*find same folder */ + if (first_inoti_node != NULL) { + del_node = first_inoti_node; + while (del_node != NULL) { + MS_DBG("current node %s", del_node->name); + if (strcmp(path, del_node->name) == 0) { + MS_DBG("find delete node: %s", del_node->name); + if (prv_node != NULL) { + MS_DBG("previous_node : %s", prv_node->name); + prv_node->next = del_node->next; + } + /*free deleted node */ + MS_SAFE_FREE(del_node->name); + MS_SAFE_FREE(del_node); + break; + } + prv_node = del_node; + del_node = del_node->next; + } + } + } + + /*active flush */ + malloc_trim(0); +} + +void ms_inoti_modify_watch(char *path_from, char *path_to) +{ + bool find = false; + ms_inoti_dir_data *mod_node; + + if (strcmp(first_inoti_node->name, path_from) == 0) { + mod_node = first_inoti_node; + } else { + /*find same folder */ + if (first_inoti_node != NULL) { + mod_node = first_inoti_node; + while (mod_node != NULL) { + /*find previous directory*/ + if (strcmp(path_from, mod_node->name) == 0) { + /*change path of directory*/ + /*free previous name of node */ + MS_SAFE_FREE(mod_node->name); + + /*add new name */ + mod_node->name = strdup(path_to); + + /*active flush */ + malloc_trim(0); + + find = true; + break; + } + mod_node = mod_node->next; + } + } + } + + /*this is new directory*/ + if (find == false) { + ms_inoti_add_watch(path_to); + } +} + +#define STOP_INOTI "stop_inoti" + +gboolean ms_inoti_thread(void *data) +{ + uint32_t i; + int length; + int err; + int prev_mask = 0; + int prev_wd = -1; + bool res; + char name[MS_FILE_NAME_LEN_MAX + 1] = { 0 }; + char prev_name[MS_FILE_NAME_LEN_MAX + 1] = { 0 }; + char buffer[INOTI_BUF_LEN] = { 0 }; + char path[MS_FILE_PATH_LEN_MAX] = { 0 }; + struct inotify_event *event; + void **handle = NULL; + + MS_DBG("START INOTIFY"); + + err = ms_connect_db(&handle); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR(" INOTIFY : sqlite3_open: ret = %d", err); + return false; + } + + while (1) { + i = 0; + length = read(inoti_fd, buffer, sizeof(buffer) - 1); + + if (length < 0 || length > sizeof(buffer)) { /*this is error */ + continue; + } + + while (i < length && i < INOTI_BUF_LEN) { + /*check poweroff status*/ + if(power_off) { + MS_DBG("power off"); + goto _POWEROFF; + } + + /*it's possible that ums lets reset phone data... */ + event = (struct inotify_event *)&buffer[i]; + + if (strcmp(event->name, POWEROFF_DIR_NAME) == 0) { + MS_DBG("power off"); + goto _POWEROFF; + } else if (strcmp(event->name, STOP_INOTI) == 0) { + MS_DBG("stop inotify thread"); + goto _POWEROFF; + } else if (event->name[0] == '.') { + /*event of hidden folder is ignored */ + goto NEXT_INOTI_EVENT; + } else if (event->wd < 1) { + /*this is error */ + MS_DBG_ERR("invalid wd : %d", event->wd); + goto NEXT_INOTI_EVENT; + } + + /*start of one event */ + if (event->len && (event->len <= MS_FILE_NAME_LEN_MAX + 1)) { + /*Add for fixing prevent defect 2011-02-15 */ + err = ms_strcopy(name, sizeof(name), "%s", event->name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strcopy error : %d", err); + goto NEXT_INOTI_EVENT; + } + + /*get full path of file or directory */ + res = _ms_inoti_get_full_path(event->wd, name, path, sizeof(path)); + if (res == false) { + MS_DBG_ERR("_ms_inoti_get_full_path error"); + goto NEXT_INOTI_EVENT; + } + + MS_DBG("INOTIFY[%d : %s]", event->wd, name); + if (event->mask & IN_ISDIR) { + MS_DBG("DIRECTORY INOTIFY"); + + if (event->mask & IN_MOVED_FROM) { + MS_DBG("MOVED_FROM"); + + prev_mask = event->mask; + prev_wd = event->wd; + + err = ms_strcopy(prev_name, sizeof(prev_name), "%s", event->name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strcopy fail"); + goto NEXT_INOTI_EVENT; + } + } + else if (event->mask & IN_MOVED_TO) { + MS_DBG("MOVED_TO"); + + char full_path_from[MS_FILE_PATH_LEN_MAX] = { 0 }; + + res = _ms_inoti_get_full_path(prev_wd, prev_name, full_path_from, sizeof(full_path_from)); + if (res == false) { + MS_DBG_ERR("_ms_inoti_get_full_path error"); + goto NEXT_INOTI_EVENT; + } + /*enable bundle commit*/ + ms_move_start(handle); + + /*need update file information under renamed directory */ + _ms_inoti_scan_renamed_folder(handle, full_path_from, path); + + /*disable bundle commit*/ + ms_move_end(handle); + + prev_mask = prev_wd = 0; /*reset */ + } + else if (event->mask & IN_CREATE) { + MS_DBG("CREATE"); + + _ms_inoti_directory_scan_and_register_file(handle, path); + prev_mask = event->mask; + } + else if (event->mask & IN_DELETE) { + MS_DBG("DELETE"); + + ms_inoti_remove_watch(path); + } + } + else { + MS_DBG("FILE INOTIFY"); + + if (event->mask & IN_MOVED_FROM) { + MS_DBG("MOVED_FROM"); + + err = ms_delete_item(handle, path); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_media_db_delete fail error : %d", err); + } + } + else if (event->mask & IN_MOVED_TO) { + MS_DBG("MOVED_TO"); + + err = ms_register_file(handle, path, NULL); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_register_file error : %d", err); + } + } + else if (event->mask & IN_CREATE) { + MS_DBG("CREATE"); + + _ms_inoti_add_create_file_list(event->wd, name); + } + else if (event->mask & IN_DELETE) { + MS_DBG("DELETE"); + + err = ms_delete_item(handle, path); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_media_db_delete error : %d", err); + } + } + else if (event->mask & IN_CLOSE_WRITE) { + MS_DBG("CLOSE_WRITE"); + ms_create_file_info *node; + + node = _ms_inoti_find_create_file_list (event->wd, name); + if (node != NULL || ((prev_mask & IN_ISDIR) & IN_CREATE)) { + err = ms_register_file(handle, path, NULL); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_register_file error : %d", err); + } + if (node != NULL) + _ms_inoti_delete_create_file_list(node); + } + else { + ms_ignore_file_info *ignore_file; + + ignore_file = ms_inoti_find_ignore_file(path); + if (ignore_file == NULL) { + /*in case of replace */ + MS_DBG("This case is replacement or changing meta data."); + err = ms_refresh_item(handle, path); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_refresh_item error : %d", err); + goto NEXT_INOTI_EVENT; + } + } else { + /*This is ignore case*/ + } + } + prev_mask = prev_wd = 0; /*reset */ + } + } + } /*end of one event */ + else { + /*This is ignore case*/ + if (event->mask & IN_IGNORED) { + MS_DBG("This case is ignored"); + } + } + NEXT_INOTI_EVENT: ; + i += INOTI_EVENT_SIZE + event->len; + } + + /*Active flush */ + malloc_trim(0); + } +_POWEROFF: + ms_inoti_remove_watch_recursive(MEDIA_ROOT_PATH_INTERNAL); + ms_inoti_remove_watch_recursive(MEDIA_ROOT_PATH_SDCARD); + + close(inoti_fd); + + if (handle) ms_disconnect_db(&handle); + + return false; +} + +int _ms_get_path_from_current_node(int find_folder, + ms_dir_scan_info **current_root, + ms_dir_scan_info **real_root, char **path, int *depth) +{ + int err = MS_MEDIA_ERR_NONE; + char get_path[FAT_FILEPATH_LEN_MAX] = { 0 }; + + if (find_folder == 0) { + if ((*current_root)->Rbrother != NULL) { + *current_root = (*current_root)->Rbrother; + } else { + while (1) { + if ((*current_root)->parent == *real_root + || (*current_root)->parent == NULL) { + *current_root = NULL; + *depth = 0; + return MS_MEDIA_ERR_NONE; + } else if ((*current_root)->parent->Rbrother == NULL) { + *current_root = (*current_root)->parent; + (*depth) --; + } else { + *current_root = (*current_root)->parent->Rbrother; + (*depth) --; + break; + } + } + } + (*depth) --; + } + + err = ms_get_full_path_from_node(*current_root, get_path, *depth); + if (err != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_INVALID_PATH; + + *path = strdup(get_path); + + return err; +} + +void ms_inoti_add_watch_all_directory(ms_storage_type_t storage_type) +{ + int err = 0; + int depth = 0; + int find_folder = 0; + char get_path[MS_FILE_PATH_LEN_MAX] = { 0 }; + char *path = NULL; + DIR *dp = NULL; + struct dirent entry; + struct dirent *result; + + ms_dir_scan_info *root; + ms_dir_scan_info *tmp_root = NULL; + ms_dir_scan_info *cur_node = NULL; /*current node*/ + ms_dir_scan_info *prv_node = NULL; /*previous node*/ + ms_dir_scan_info *next_node = NULL; + + root = malloc(sizeof(ms_dir_scan_info)); + if (root == NULL) { + MS_DBG_ERR("malloc fail"); + return; + } + + if (storage_type == MS_STORAGE_INTERNAL) + root->name = strdup(MEDIA_ROOT_PATH_INTERNAL); + else + root->name = strdup(MEDIA_ROOT_PATH_SDCARD); + if (root->name == NULL) { + MS_DBG_ERR("strdup fail"); + MS_SAFE_FREE(root); + return; + } + + root->parent = NULL; + root->Rbrother = NULL; + root->next = NULL; + tmp_root = root; + prv_node = root; + + path = malloc(sizeof(char) * MS_FILE_PATH_LEN_MAX); + + err = ms_get_full_path_from_node(tmp_root, path, depth); + if (err != MS_MEDIA_ERR_NONE) { + MS_SAFE_FREE(path); + MS_SAFE_FREE(root); + return; + } + + ms_inoti_add_watch_with_node(root, depth); + + while (1) { + /*check poweroff status*/ + if (power_off) { + MS_DBG("Power off"); + goto FREE_RESOURCES; + } + + /*check SD card in out*/ + if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL)) + goto FREE_RESOURCES; + + depth ++; + dp = opendir(path); + if (dp == NULL) { + MS_DBG_ERR("%s folder opendir fails", path); + goto NEXT_DIR; + } + + while (!readdir_r(dp, &entry, &result)) { + /*check poweroff status*/ + if (power_off) { + MS_DBG("Power off"); + goto FREE_RESOURCES; + } + + if (result == NULL) + break; + + if (entry.d_name[0] == '.') + continue; + + /*check SD card in out*/ + if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL)) { + goto FREE_RESOURCES; + } + + if (entry.d_type & DT_DIR) { + DIR *tmp_dp = NULL; + err = ms_strappend(get_path, sizeof(get_path), "%s/%s",path, entry.d_name); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strappend error"); + continue; + } + + tmp_dp = opendir(get_path); + if (tmp_dp == NULL) { + MS_DBG_ERR("%s folder opendir fails", get_path); + MS_DBG("error : %d, %s", errno ,strerror(errno)); + continue; + } + else + closedir(tmp_dp); + + cur_node = malloc(sizeof(ms_dir_scan_info)); + if (cur_node == NULL) { + MS_DBG_ERR("malloc fail"); + + goto FREE_RESOURCES; + } + + cur_node->name = strdup(entry.d_name); + cur_node->Rbrother = NULL; + cur_node->next = NULL; + + /*1. 1st folder */ + if (find_folder == 0) { + cur_node->parent = tmp_root; + tmp_root = cur_node; + } else { + cur_node->parent = tmp_root->parent; + prv_node->Rbrother = cur_node; + } + prv_node->next = cur_node; + + /*add watch */ + ms_inoti_add_watch_with_node(cur_node, depth); + + /*change previous */ + prv_node = cur_node; + find_folder++; + } + } +NEXT_DIR: + if (dp) closedir(dp); + MS_SAFE_FREE(path); + dp = NULL; + path = NULL; + + err = _ms_get_path_from_current_node(find_folder, &tmp_root, &root, &path, &depth); + if (err != MS_MEDIA_ERR_NONE) + break; + + if (tmp_root == NULL) + break; + + find_folder = 0; + } + +FREE_RESOURCES: + /*free allocated memory */ + if (dp) closedir(dp); + MS_SAFE_FREE(path); + + cur_node = root; + while (cur_node != NULL) { + next_node = cur_node->next; + MS_SAFE_FREE(cur_node->name); + MS_SAFE_FREE(cur_node); + cur_node = next_node; + } +} + +#endif \ No newline at end of file diff --git a/common/media-server-main.c b/common/media-server-main.c new file mode 100755 index 0000000..ae232d7 --- /dev/null +++ b/common/media-server-main.c @@ -0,0 +1,420 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-main.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "media-util.h" +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-external-storage.h" +#include "media-server-db-svc.h" +#include "media-server-inotify.h" +#include "media-server-socket.h" +#include "media-server-db.h" +#include "media-server-drm.h" +#include "media-server-dbus.h" +#include "media-server-thumb.h" +#include "media-server-scanner.h" + +#define APP_NAME "media-server" + +extern GMutex *scanner_mutex; +extern GMutex *db_mutex; +extern int mmc_state; + +#if MS_INOTI_ENABLE +extern GAsyncQueue* ret_queue; +extern GMutex *list_mutex; +extern GMutex *queue_mutex; +extern GArray *reg_list; +extern bool power_off; /*If this is TRUE, poweroff notification received*/ +#endif +GMainLoop *mainloop = NULL; + +bool check_process() +{ + DIR *pdir; + struct dirent pinfo; + struct dirent *result = NULL; + bool ret = false; + int find_pid = 0; + pid_t current_pid = 0; + + current_pid = getpid(); + + pdir = opendir("/proc"); + if (pdir == NULL) { + MS_DBG_ERR("err: NO_DIR\n"); + return 0; + } + + while (!readdir_r(pdir, &pinfo, &result)) { + if (result == NULL) + break; + + if (pinfo.d_type != 4 || pinfo.d_name[0] == '.' + || pinfo.d_name[0] > 57) + continue; + + FILE *fp; + char buff[128]; + char path[128]; + + ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name); + fp = fopen(path, "rt"); + if (fp) { + if (fgets(buff, 128, fp) == NULL) + MS_DBG_ERR("fgets failed"); + fclose(fp); + + if (strstr(buff, APP_NAME)) { + find_pid = atoi(pinfo.d_name); + if (find_pid == current_pid) + ret = true; + else { + ret = false; + break; + } + } + } else { + MS_DBG_ERR("Can't read file [%s]", path); + } + } + + closedir(pdir); + + return ret; +} + +void init_process() +{ + +} + +static void _power_off_cb(void* data) +{ + MS_DBG("++++++++++++++++++++++++++++++++++++++"); + MS_DBG("POWER OFF"); + MS_DBG("++++++++++++++++++++++++++++++++++++++"); +#if MS_INOTI_ENABLE + power_off = true; +#endif + /*Quit Thumbnail Thread*/ + GMainLoop *thumb_mainloop = ms_get_thumb_thread_mainloop(); + if (thumb_mainloop && g_main_is_running(thumb_mainloop)) { + g_main_loop_quit(thumb_mainloop); + } + + /*Quit DB Thread*/ + GMainLoop *db_mainloop = ms_db_get_mainloop(); + if(db_mainloop && g_main_loop_is_running(db_mainloop)) { + g_main_loop_quit(db_mainloop); + } + + /*Quit Main Thread*/ + if (mainloop && g_main_loop_is_running(mainloop)) { + g_main_loop_quit(mainloop); + } + + return; +} + +static bool _db_clear(void** handle) +{ + int err; + int db_status; + bool need_db_create = false; + + /*update just valid type*/ + err = ms_invalidate_all_items(handle, MS_STORAGE_EXTERNAL); + if (err != MS_MEDIA_ERR_NONE) + MS_DBG_ERR("ms_change_valid_type fail"); + + ms_config_get_int(MS_SCAN_STATUS_INTERNAL, &db_status); + MS_DBG("finish_phone_init_data db = %d", db_status); + + if (db_status == P_VCONF_SCAN_DOING) { + need_db_create = true; + + err = ms_invalidate_all_items(handle, MS_STORAGE_INTERNAL); + if (err != MS_MEDIA_ERR_NONE) + MS_DBG_ERR("ms_change_valid_type fail"); + } + +// ms_set_db_status(MS_DB_UPDATED); + + return need_db_create; +} + +void _ms_signal_handler(int n) +{ + MS_DBG("Receive SIGNAL"); + int stat, pid, thumb_pid; + int scanner_pid; + + thumb_pid = ms_thumb_get_server_pid(); + MS_DBG("Thumbnail server pid : %d", thumb_pid); + + scanner_pid = ms_get_scanner_pid(); + + pid = waitpid(-1, &stat, WNOHANG); + /* check pid of child process of thumbnail thread */ + MS_DBG("[PID %d] signal ID %d", pid, n); + + if (pid == thumb_pid) { + MS_DBG("Thumbnail server is dead"); + ms_thumb_reset_server_status(); + } else if (pid == scanner_pid) { + MS_DBG("Scanner is dead"); + ms_reset_scanner_status(); + } else if (pid == -1) { + MS_DBG("%s", strerror(errno)); + } + + if (WIFEXITED(stat)) { + MS_DBG("normal termination , exit status : %d", WEXITSTATUS(stat)); + } else if (WIFSIGNALED(stat)) { + MS_DBG("abnormal termination , signal number : %d", WTERMSIG(stat)); + } else if (WIFSTOPPED(stat)) { + MS_DBG("child process is stoped, signal number : %d", WSTOPSIG(stat)); + } + + return; +} + +static void _ms_new_global_variable(void) +{ +#if MS_INOTI_ENABLE + /*Init for register file*/ + if (!list_mutex) list_mutex = g_mutex_new(); + if (!queue_mutex) queue_mutex = g_mutex_new(); + if (!reg_list) reg_list = g_array_new(TRUE, TRUE, sizeof(char*)); + /*These are a communicator for thread*/ + if (!ret_queue) ret_queue = g_async_queue_new(); +#endif + /*Init mutex variable*/ + if (!db_mutex) db_mutex = g_mutex_new(); + + /*media scanner stop/start mutex*/ + if (!scanner_mutex) scanner_mutex = g_mutex_new(); +} + +static void _ms_free_global_variable(void) +{ +#if MS_INOTI_ENABLE + if (list_mutex) g_mutex_free(list_mutex); + if (queue_mutex)g_mutex_free(queue_mutex); + if (reg_list) g_array_free(reg_list, true); + if (ret_queue) g_async_queue_unref(ret_queue); +#endif + /*Clear mutex variable*/ + if (db_mutex) g_mutex_free (db_mutex); + + if (scanner_mutex) g_mutex_free(scanner_mutex); +} + +int main(int argc, char **argv) +{ +#if MS_INOTI_ENABLE + GThread *inoti_thread = NULL; +#endif + GThread *db_thread = NULL; + GThread *thumb_thread = NULL; + GSource *source = NULL; + GIOChannel *channel = NULL; + GMainContext *context = NULL; + int sockfd = MS_SOCK_NOT_ALLOCATE; + int err; + int heynoti_id; + bool check_result = false; + bool need_db_create; + void **handle = NULL; + struct sigaction sigset; + + check_result = check_process(); + if (check_result == false) + exit(0); + + if (!g_thread_supported()) { + g_thread_init(NULL); + } + + /*Init main loop*/ + mainloop = g_main_loop_new(NULL, FALSE); +#if MS_INOTI_ENABLE + /*inotify setup */ + ms_inoti_init(); +#endif + /*heynoti for power off*/ + if ((heynoti_id = heynoti_init()) <0) { + MS_DBG("heynoti_init failed"); + } else { + err = heynoti_subscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb, NULL); + if (err < 0) + MS_DBG("heynoti_subscribe failed"); + + err = heynoti_attach_handler(heynoti_id); + if (err < 0) + MS_DBG("heynoti_attach_handler failed"); + } + + /*load functions from plusin(s)*/ + err = ms_load_functions(); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("function load failed"); + exit(0); + } + + _ms_new_global_variable(); + + /*connect to media db, if conneting is failed, db updating is stopped*/ + ms_connect_db(&handle); + + ms_dbus_init(); +#if MS_INOTI_ENABLE + ms_inoti_add_watch_all_directory(MS_STORAGE_INTERNAL); +#endif + /*prepare socket*/ + /* Create and bind new UDP socket */ + if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, MS_SCANNER_PORT, &sockfd) + != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("Failed to create socket"); + } else { + context = g_main_loop_get_context(mainloop); + + /* Create new channel to watch udp socket */ + channel = g_io_channel_unix_new(sockfd); + source = g_io_create_watch(channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)ms_read_socket, handle, NULL); + g_source_attach(source, context); + g_source_unref(source); + } + + /*create each threads*/ +#if MS_INOTI_ENABLE + inoti_thread = g_thread_new("inotify_thread", (GThreadFunc)ms_inoti_thread, NULL); +#endif + db_thread = g_thread_new("db_thread", (GThreadFunc)ms_db_thread, NULL); + thumb_thread = g_thread_new("thumb_agent_thread", (GThreadFunc)ms_thumb_agent_start_thread, NULL); + + /*set vconf callback function*/ + err = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, (vconf_callback_fn) ms_mmc_vconf_cb, NULL); + if (err == -1) + MS_DBG_ERR("add call back function for event %s fails", VCONFKEY_SYSMAN_MMC_STATUS); + + MS_DBG("*********************************************************"); + MS_DBG("*** Begin to check tables of file manager in database ***"); + MS_DBG("*********************************************************"); + + /* Add signal handler */ + sigset.sa_handler = _ms_signal_handler; + if (sigaction(SIGCHLD, &sigset, NULL) < 0) { + MS_DBG_ERR("sigaction failed [%s]", strerror(errno)); + } else { + MS_DBG("handler ok"); + } + + /*clear previous data of sdcard on media database and check db status for updating*/ + while(!ms_db_get_thread_status()) { + MS_DBG("wait db thread"); + sleep(1); + } + + need_db_create = _db_clear(handle); + if (need_db_create) { + /*insert records*/ + ms_send_storage_scan_request(MS_STORAGE_INTERNAL, MS_SCAN_ALL); + } else { + ms_send_storage_scan_request(MS_STORAGE_INTERNAL, MS_SCAN_PART); + } + + if (ms_is_mmc_inserted()) { + mmc_state = VCONFKEY_SYSMAN_MMC_MOUNTED; + + if (!ms_drm_insert_ext_memory()) + MS_DBG_ERR("ms_drm_insert_ext_memory failed"); + + ms_make_default_path_mmc(); +#if MS_INOTI_ENABLE + ms_inoti_add_watch_all_directory(MS_STORAGE_EXTERNAL); +#endif + ms_present_mmc_insert(); + + ms_send_storage_scan_request(MS_STORAGE_EXTERNAL, ms_get_mmc_state()); + } + + /*Active flush */ + malloc_trim(0); + + MS_DBG("*****************************************"); + MS_DBG("*** Server of File Manager is running ***"); + MS_DBG("*****************************************"); + + g_main_loop_run(mainloop); +#if MS_INOTI_ENABLE + g_thread_join(inoti_thread); +#endif + g_thread_join(db_thread); + g_thread_join(thumb_thread); + + /*close an IO channel*/ + g_io_channel_shutdown(channel, FALSE, NULL); + g_io_channel_unref(channel); + + heynoti_unsubscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb); + heynoti_close(heynoti_id); + + /*********** + **remove call back functions + ************/ + vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, + (vconf_callback_fn) ms_mmc_vconf_cb); + + _ms_free_global_variable(); + + /*disconnect form media db*/ + if (handle) ms_disconnect_db(&handle); + + /*close socket*/ + close(sockfd); + + /*unload functions*/ + ms_unload_functions(); + + exit(0); +} diff --git a/common/media-server-scanner.c b/common/media-server-scanner.c new file mode 100755 index 0000000..ef10f34 --- /dev/null +++ b/common/media-server-scanner.c @@ -0,0 +1,261 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include + +#include "media-util.h" +#include "media-server-types.h" +#include "media-server-dbg.h" +#include "media-server-utils.h" +#include "media-server-socket.h" +#include "media-server-scanner.h" + +#define MS_NO_REMAIN_TASK 0 + +extern GMainLoop *mainloop; +extern GArray *owner_list; +GMutex *scanner_mutex; + +static bool scanner_ready; +static int alarm_id; +static int receive_id; +static int child_pid; + + + +static int _ms_check_remain_task(void) +{ + int remain_task; + + if (owner_list != NULL) + remain_task = owner_list->len; + else + remain_task = MS_NO_REMAIN_TASK; + + return remain_task; +} + +ms_db_status_type_t ms_check_scanning_status(void) +{ + int status; + + if(ms_config_get_int(VCONFKEY_FILEMANAGER_DB_STATUS, &status)) { + if (status == VCONFKEY_FILEMANAGER_DB_UPDATING) { + return MS_DB_UPDATING; + } + } + + return MS_DB_UPDATED; +} + +static gboolean _ms_stop_scanner (gpointer user_data) +{ + int sockfd; + int task_num; + GIOChannel *src = user_data; + + g_mutex_lock(scanner_mutex); + + /* check status of scanner */ + /* If some task remain or scanner is running, scanner must not stop*/ + task_num = _ms_check_remain_task(); + if (task_num != MS_NO_REMAIN_TASK) { + MS_DBG("[%d] task(s) remains", task_num); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + if (ms_check_scanning_status() == MS_DB_UPDATING) { + MS_DBG("DB is updating"); + g_mutex_unlock(scanner_mutex); + return TRUE; + } else { + MS_DBG("DB updating is not working"); + } + + /* stop media scanner */ + if (child_pid >0 ) { + if (kill(child_pid, SIGKILL) < 0) { + MS_DBG_ERR("kill failed : %s", strerror(errno)); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + } + /* close socket */ + sockfd = g_io_channel_unix_get_fd(src); + g_io_channel_shutdown(src, FALSE, NULL); + g_io_channel_unref(src); + close(sockfd); + + g_source_destroy(g_main_context_find_source_by_id(g_main_loop_get_context (mainloop), alarm_id)); + g_source_destroy(g_main_context_find_source_by_id(g_main_loop_get_context (mainloop), receive_id)); + + return FALSE; +} + + +static void _ms_add_timeout(guint interval, GSourceFunc func, gpointer data) +{ + MS_DBG(""); + GSource *src; + + src = g_timeout_source_new_seconds(interval); + g_source_set_callback(src, func, data, NULL); + alarm_id = g_source_attach(src, g_main_loop_get_context (mainloop)); + g_source_unref(src); +} + +int +ms_scanner_start(void) +{ + int pid; + + g_mutex_lock(scanner_mutex); + + if (child_pid > 0) { + MS_DBG_ERR("media scanner is already started"); + g_mutex_unlock(scanner_mutex); + return MS_MEDIA_ERR_NONE; + } + + if((pid = fork()) < 0) { + MS_DBG_ERR("Fork error\n"); + } else if (pid > 0) { + /* parent process */ + /* wait until scanner is ready*/ + int ret = MS_MEDIA_ERR_NONE; + int sockfd = -1; + int err = -1; + int n_reuse = 1; + struct sockaddr_in serv_addr; + unsigned int serv_addr_len = -1; + int port = MS_SCAN_COMM_PORT; + ms_comm_msg_s recv_msg; + + GSource *res_source = NULL; + GIOChannel *res_channel = NULL; + GMainContext *res_context = NULL; + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_create_client_socket failed [%d]",ret); + g_mutex_unlock(scanner_mutex); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + /* set socket re-use */ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) { + MS_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sockfd); + g_mutex_unlock(scanner_mutex); + return MS_MEDIA_ERR_SOCKET_INTERNAL; + } + + /*Set server Address*/ + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP); + serv_addr.sin_port = htons(port); + + /* Bind to the local address */ + if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + MS_DBG_ERR("bind failed [%s]", strerror(errno)); + close(sockfd); + g_mutex_unlock(scanner_mutex); + return MS_MEDIA_ERR_SOCKET_BIND; + } + + /*Receive Response*/ + serv_addr_len = sizeof(serv_addr); + err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL); + if (err != MS_MEDIA_ERR_NONE) { + ret = err; + close(sockfd); + } else { + int scanner_status = recv_msg.msg_type; + if (scanner_status == MS_MSG_SCANNER_READY) { + MS_DBG("RECEIVE OK [%d] %d", recv_msg.msg_type, pid); + scanner_ready = true; + child_pid = pid; + + /* attach result receiving socket to mainloop */ + res_context = g_main_loop_get_context(mainloop); + + /* Create new channel to watch udp socket */ + res_channel = g_io_channel_unix_new(sockfd); + res_source = g_io_create_watch(res_channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(res_source, (GSourceFunc)ms_receive_message_from_scanner, NULL, NULL); + receive_id = g_source_attach(res_source, res_context); + g_source_unref(res_source); + + _ms_add_timeout(30, (GSourceFunc)_ms_stop_scanner, res_channel); + + ret = MS_MEDIA_ERR_NONE; + } else { + MS_DBG_ERR("Receive wrong message from scanner[%d]", scanner_status); + close(sockfd); + ret = MS_MEDIA_ERR_SOCKET_RECEIVE; + } + } + + g_mutex_unlock(scanner_mutex); + + return ret; + /* attach socket receive message callback */ + } else if(pid == 0) { + /* child process */ + MS_DBG_ERR("CHILD PROCESS"); + MS_DBG("EXECUTE MEDIA SCANNER"); + execl("/usr/bin/media-scanner", "media-scanner", NULL); + g_mutex_unlock(scanner_mutex); + } + + return MS_MEDIA_ERR_NONE; +} + +bool ms_get_scanner_status(void) +{ + return scanner_ready; +} + +void ms_reset_scanner_status(void) +{ + child_pid = 0; + scanner_ready = false; + + /* scanning is done */ + if (!ms_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DONE)) { + MS_DBG_ERR("ms_config_set_int failed"); + } + + g_mutex_unlock(scanner_mutex); +} + +int ms_get_scanner_pid(void) +{ + return child_pid; +} \ No newline at end of file diff --git a/common/media-server-socket.c b/common/media-server-socket.c new file mode 100755 index 0000000..ae9f30b --- /dev/null +++ b/common/media-server-socket.c @@ -0,0 +1,592 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-thumb.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#include +#include +#include +#include +#include +#include + +#include "media-util.h" +#include "media-util-internal.h" +#include "media-server-dbg.h" +#include "media-server-ipc.h" +#include "media-server-db-svc.h" +#include "media-server-utils.h" +#include "media-server-scanner.h" +#include "media-server-socket.h" +#include "media-server-db.h" + +extern GAsyncQueue *scan_queue; +GAsyncQueue* ret_queue; +GArray *owner_list; +extern GMutex *scanner_mutex; + +typedef struct ms_req_owner_data +{ + int pid; + struct sockaddr_in *client_addr; +}ms_req_owner_data; + +int _ms_add_owner(ms_req_owner_data *owner_data) +{ +// MS_DBG("the length of array : %d", owner_list->len); +// MS_DBG("pid : %d", owner_data->pid); +// MS_DBG("client_addr : %p", owner_data->client_addr); + + g_array_append_val(owner_list, owner_data); + + return MS_MEDIA_ERR_NONE; +} + +int _ms_find_owner(int pid, ms_req_owner_data **owner_data) +{ + int i; + int len = owner_list->len; + bool find_flag = false; + ms_req_owner_data *data = NULL; + + MS_DBG("length list : %d", len); + + for (i=0; i < len; i++) { + data = g_array_index(owner_list, ms_req_owner_data*, i); + MS_DBG("%d %d", data->pid, pid); + if (data->pid == pid) { + find_flag = true; + break; + } + } + + if (find_flag == true) { + *owner_data = data; + MS_DBG("FIND OWNER"); + } else { + *owner_data = NULL; + MS_DBG("DO NOT FIND OWNER"); + } + + return MS_MEDIA_ERR_NONE; +} + +int _ms_delete_owner(ms_req_owner_data *owner_data) +{ + int i; + int len = owner_list->len; + ms_req_owner_data *data = NULL; + + for (i=0; i < len; i++) { + data = g_array_index(owner_list, ms_req_owner_data*, i); + if (data->pid == owner_data->pid) { + if (data->client_addr == owner_data->client_addr) { + g_array_remove_index(owner_list, i); + MS_SAFE_FREE(owner_data->client_addr); + MS_SAFE_FREE(owner_data); + } + break; + } + } + + return MS_MEDIA_ERR_NONE; +} + +gboolean ms_read_socket(GIOChannel *src, GIOCondition condition, gpointer data) +{ + struct sockaddr_in *client_addr = NULL; + socklen_t client_addr_len; + ms_comm_msg_s recv_msg; + ms_comm_msg_s result_msg; + ms_comm_msg_s scan_msg; + int msg_size; + int sockfd = MS_SOCK_NOT_ALLOCATE; + int ret; + int pid; + int req_num; + int path_size; + void **handle = data; + char *path = NULL; + + g_mutex_lock(scanner_mutex); + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MS_DBG_ERR("sock fd is invalid!"); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + /* Socket is readable */ + MS_MALLOC(client_addr, sizeof(struct sockaddr_in)); + if (client_addr == NULL) { + MS_DBG_ERR("malloc failed"); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + client_addr_len = sizeof(struct sockaddr_in); + ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), client_addr, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_receive_message failed"); + MS_SAFE_FREE(client_addr); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + MS_DBG("receive msg from [%d] %d, %s", recv_msg.pid, recv_msg.msg_type, recv_msg.msg); + + if (recv_msg.msg_size > 0 && recv_msg.msg_size < MS_FILE_PATH_LEN_MAX) { + msg_size = recv_msg.msg_size; + path_size = msg_size + 1; + } else { + /*NEED IMPLEMETATION*/ + MS_SAFE_FREE(client_addr); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + /* copy received data */ + req_num = recv_msg.msg_type; + pid = recv_msg.pid; + + /* register file request + * media server inserts the meta data of one file into media db */ + if (req_num == MS_MSG_DB_UPDATE) { + MS_MALLOC(path, path_size); + if (path != NULL) { + ret = ms_strcopy(path, path_size, "%s", recv_msg.msg); + if (ret != MS_MEDIA_ERR_NONE) { + MS_SAFE_FREE(path); + MS_SAFE_FREE(client_addr); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + + MS_DBG("REQUEST FILE REGISTER"); +#if MS_INOTI_ENABLE + ret = ms_register_file(handle, path, ret_queue); + if (ret == MS_MEDIA_ERR_NOW_REGISTER_FILE) { + ret= GPOINTER_TO_INT(g_async_queue_pop(ret_queue)) - MS_MEDIA_ERR_MAX; + } +#else + ret = ms_register_file(handle, path); +#endif + MS_DBG_INFO("register result : %d", ret); + /* the result of inserting to db */ + result_msg.result = ret; + } else { + MS_DBG_ERR("malloc failed"); + result_msg.result = MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + ms_ipc_send_msg_to_client(sockfd, &result_msg, client_addr); + + MS_SAFE_FREE(path); + MS_SAFE_FREE(client_addr); + + g_mutex_unlock(scanner_mutex); + } else if (req_num == MS_MSG_DIRECTORY_SCANNING + ||req_num == MS_MSG_BULK_INSERT + ||req_num == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) { + /* this request process in media scanner */ + + ms_req_owner_data *owner_data = NULL; + + /* If owner list is NULL, create it */ + /* pid and client address are stored in ower list */ + /* These are used for sending result of scanning */ + if (owner_list == NULL) { + /*create array for processing overlay data*/ + owner_list = g_array_new (FALSE, FALSE, sizeof (ms_req_owner_data *)); + if (owner_list == NULL) { + MS_DBG_ERR("g_array_new error"); + MS_SAFE_FREE(client_addr); + g_mutex_unlock(scanner_mutex); + return TRUE; + } + } + + /* store pid and client address */ + MS_MALLOC(owner_data, sizeof(ms_req_owner_data)); + owner_data->pid = recv_msg.pid; + owner_data->client_addr = client_addr; + + _ms_add_owner(owner_data); + + /* create send message for media scanner */ + scan_msg.msg_type = req_num; + scan_msg.pid = pid; + scan_msg.msg_size = msg_size; + ms_strcopy(scan_msg.msg, path_size, "%s", recv_msg.msg); + + /* change the status of media scanner for directory scanning */ + if (req_num == MS_MSG_DIRECTORY_SCANNING + || req_num == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) { + MS_DBG("DIRECTORY SCANNING IS START"); + if (!ms_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DOING)) { + MS_DBG_ERR("ms_config_set_int failed"); + } + } + + g_mutex_unlock(scanner_mutex); + + if (ms_get_scanner_status()) { + MS_DBG("Scanner is ready"); + ms_send_scan_request(&scan_msg); + } else { + MS_DBG("Scanner starts"); + ret = ms_scanner_start(); + if(ret == MS_MEDIA_ERR_NONE) { + ms_send_scan_request(&scan_msg); + } else { + MS_DBG("Scanner starting failed. %d", ret); + } + } + } else { + /* NEED IMPLEMENTATION */ + MS_SAFE_FREE(client_addr); + g_mutex_unlock(scanner_mutex); + } + + /*Active flush */ + malloc_trim(0); + + return TRUE; +} +gboolean ms_receive_message_from_scanner(GIOChannel *src, GIOCondition condition, gpointer data) +{ + ms_comm_msg_s recv_msg; + int sockfd = MS_SOCK_NOT_ALLOCATE; + int msg_type; + int ret; + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + + /* Socket is readable */ + ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), NULL, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_receive_message failed [%s]", strerror(errno)); + return TRUE; + } + + MS_DBG("receive msg from [%d] %d, %s", recv_msg.pid, recv_msg.msg_type, recv_msg.msg); + + msg_type = recv_msg.msg_type; + if ((msg_type == MS_MSG_SCANNER_RESULT) || + (msg_type == MS_MSG_SCANNER_BULK_RESULT)) { + if (owner_list != NULL) { + /* If the owner of result message is not media-server, media-server notify to the owner */ + /* The owner of message is distingushied by pid in received message*/ + /* find owner data */ + ms_req_owner_data *owner_data = NULL; + + _ms_find_owner(recv_msg.pid, &owner_data); + if (owner_data != NULL) { + MS_DBG("PID : %d", owner_data->pid); + ms_comm_msg_s *result_msg; + + if (msg_type == MS_MSG_SCANNER_RESULT) { + MS_DBG("DIRECTORY SCANNING IS DONE"); + if (!ms_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DONE)) { + MS_DBG_ERR("ms_config_set_int failed"); + } + } + + MS_MALLOC(result_msg, sizeof(ms_comm_msg_s)); + /* owner data exists */ + /* send result to the owner of request */ + ms_ipc_send_msg_to_client(sockfd, &recv_msg, owner_data->client_addr); + + /* free owner data*/ + _ms_delete_owner(owner_data); + + MS_SAFE_FREE(result_msg); + } + } else { + /* owner data does not exist*/ + /* this is result of request of media server*/ + } + } else { + MS_DBG_ERR("This result message is wrong : %d", recv_msg.msg_type ); + } + + return TRUE; +} + +int ms_send_scan_request(ms_comm_msg_s *send_msg) +{ + int ret; + int res = MS_MEDIA_ERR_NONE; + int sockfd = -1; + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd); + if (ret != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_SOCKET_CONN; + + ret = ms_ipc_send_msg_to_server(sockfd, MS_SCAN_DAEMON_PORT, send_msg, NULL); + if (ret != MS_MEDIA_ERR_NONE) + res = ret; + + close(sockfd); + + return res; +} + +int ms_send_storage_scan_request(ms_storage_type_t storage_type, ms_dir_scan_type_t scan_type) +{ + int ret = MS_MEDIA_ERR_NONE; + ms_comm_msg_s scan_msg = { + .msg_type = MS_MSG_STORAGE_INVALID, + .pid = 0, /* pid 0 means media-server */ + .result = -1, + .msg_size = 0, + .msg = {0}, + }; + + /* msg_type */ + switch (scan_type) { + case MS_SCAN_PART: + scan_msg.msg_type = MS_MSG_STORAGE_PARTIAL; + break; + case MS_SCAN_ALL: + scan_msg.msg_type = MS_MSG_STORAGE_ALL; + break; + case MS_SCAN_INVALID: + scan_msg.msg_type = MS_MSG_STORAGE_INVALID; + break; + default : + ret = MS_MEDIA_ERR_INVALID_PARAMETER; + MS_DBG_ERR("ms_send_storage_scan_request invalid parameter"); + goto ERROR; + break; + } + + /* msg_size & msg */ + switch (storage_type) { + case MS_STORAGE_INTERNAL: + scan_msg.msg_size = strlen(MEDIA_ROOT_PATH_INTERNAL); + strncpy(scan_msg.msg, MEDIA_ROOT_PATH_INTERNAL, scan_msg.msg_size ); + break; + case MS_STORAGE_EXTERNAL: + scan_msg.msg_size = strlen(MEDIA_ROOT_PATH_SDCARD); + strncpy(scan_msg.msg, MEDIA_ROOT_PATH_SDCARD, scan_msg.msg_size ); + break; + default : + ret = MS_MEDIA_ERR_INVALID_PARAMETER; + MS_DBG_ERR("ms_send_storage_scan_request invalid parameter"); + goto ERROR; + break; + } + + g_mutex_lock(scanner_mutex); + + if (ms_get_scanner_status()) { + ms_send_scan_request(&scan_msg); + g_mutex_unlock(scanner_mutex); + } else { + g_mutex_unlock(scanner_mutex); + + ret = ms_scanner_start(); + if(ret == MS_MEDIA_ERR_NONE) { + ms_send_scan_request(&scan_msg); + } else { + MS_DBG("Scanner starting failed. "); + } + } + +ERROR: + + return ret; +} + +gboolean ms_read_db_socket(GIOChannel *src, GIOCondition condition, gpointer data) +{ + struct sockaddr_in client_addr; + + ms_comm_msg_s recv_msg; + int send_msg = MS_MEDIA_ERR_NONE; + int sockfd = MS_SOCK_NOT_ALLOCATE; + int ret = MS_MEDIA_ERR_NONE; + MediaDBHandle *db_handle = (MediaDBHandle *)data; + ms_comm_msg_s msg; + char * sql_query = NULL; + size_t sql_query_size = 0; + + memset(&recv_msg, 0, sizeof(recv_msg)); + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + + ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), &client_addr, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_receive_message failed"); + return TRUE; + } + +// MS_DBG("msg_type[%d], msg_size[%d] msg[%s]", recv_msg.msg_type, recv_msg.msg_size, recv_msg.msg); + + if((recv_msg.msg_size <= 0) ||(recv_msg.msg_size > MS_FILE_PATH_LEN_MAX) || (!MS_STRING_VALID(recv_msg.msg))) { + MS_DBG_ERR("invalid query. size[%d]", recv_msg.msg_size); + return TRUE; + } + + sql_query_size = recv_msg.msg_size + 1; + MS_MALLOC(sql_query, sql_query_size); + if (sql_query != NULL) { + ret = ms_strcopy(sql_query, sql_query_size, "%s", recv_msg.msg); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strcopy failed"); + MS_SAFE_FREE(sql_query); + return TRUE; + } + + ret = media_db_update_db(db_handle, sql_query); + if (ret != MS_MEDIA_ERR_NONE) + MS_DBG_ERR("media_db_update_db error : %d", ret); + + send_msg = ret; + MS_SAFE_FREE(sql_query); + } else { + send_msg = MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + memset(&msg, 0x0, sizeof(ms_comm_msg_s)); + msg.result = send_msg; + + ms_ipc_send_msg_to_client(sockfd, &msg, &client_addr); + + /*Active flush */ + malloc_trim(0); + + return TRUE; +} + +gboolean ms_read_db_tcp_socket(GIOChannel *src, GIOCondition condition, gpointer data) +{ + struct sockaddr_in client_addr; + unsigned int client_addr_len; + + ms_comm_msg_s recv_msg; + int sock = -1; + int client_sock = -1; + int send_msg = MS_MEDIA_ERR_NONE; + int recv_msg_size = -1; + int ret = MS_MEDIA_ERR_NONE; + char * sql_query = NULL; + size_t sql_query_size = 0; + MediaDBHandle *db_handle = (MediaDBHandle *)data; + + sock = g_io_channel_unix_get_fd(src); + if (sock < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + memset((void *)&recv_msg, 0, sizeof(ms_comm_msg_s)); + + if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { + MS_DBG_ERR("accept failed : %s", strerror(errno)); + return TRUE; + } + + MS_DBG("Client[%d] is accepted", client_sock); + + while(1) { + if ((recv_msg_size = recv(client_sock, &recv_msg, sizeof(ms_comm_msg_s), 0)) < 0) { + MS_DBG_ERR("recv failed : %s", strerror(errno)); + + close(client_sock); + if (errno == EWOULDBLOCK) { + MS_DBG_ERR("Timeout. Can't try any more"); + return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT; + } else { + MS_DBG_ERR("recv failed : %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_RECEIVE; + } + } + + MS_DBG("Received [%d](%d) [%s]", recv_msg.msg_type, recv_msg.msg_size, recv_msg.msg); + + if((recv_msg.msg_size <= 0) ||(recv_msg.msg_size > MS_FILE_PATH_LEN_MAX) || (!MS_STRING_VALID(recv_msg.msg))) { + MS_DBG_ERR("invalid query. size[%d]", recv_msg.msg_size); + close(client_sock); + return TRUE; + } + + sql_query_size = recv_msg.msg_size + 1; + MS_MALLOC(sql_query, sql_query_size); + if (sql_query != NULL) { + ret = ms_strcopy(sql_query, sql_query_size, "%s", recv_msg.msg); + if (ret != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_strcopy failed"); + MS_SAFE_FREE(sql_query); + close(client_sock); + return TRUE; + } + + if (recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_START) { + ret = media_db_update_db_batch_start(sql_query); + } else if(recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_END) { + ret = media_db_update_db_batch_end(db_handle, sql_query); + } else if(recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH) { + ret = media_db_update_db_batch(sql_query); + } else { + + } + + MS_SAFE_FREE(sql_query); + send_msg = ret; + + if (send(client_sock, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) { + MS_DBG_ERR("send failed : %s", strerror(errno)); + } else { + MS_DBG("Sent successfully"); + } + + if (recv_msg.msg_type == MS_MSG_DB_UPDATE_BATCH_END) + break; + + memset((void *)&recv_msg, 0, sizeof(ms_comm_msg_s)); + } else { + MS_DBG_ERR("MS_MALLOC failed"); + close(client_sock); + return TRUE; + } + + } + + close(client_sock); + return TRUE; +} diff --git a/common/media-server-thumb.c b/common/media-server-thumb.c new file mode 100755 index 0000000..edbc7cc --- /dev/null +++ b/common/media-server-thumb.c @@ -0,0 +1,1115 @@ +/* + * media-thumbnail-server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Hyunjun Ko + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "media-util.h" +#include "media-server-dbg.h" +#include "media-server-thumb.h" +#include "media-server-utils.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "MEDIA_SERVER_THUMB" + +#define THUMB_SERVER_NAME "media-thumbnail" + +gboolean _ms_thumb_agent_timer(); + +static GMainLoop *g_thumb_agent_loop = NULL; +static GIOChannel *g_udp_channel = NULL; +static gboolean g_folk_thumb_server = FALSE; +static gboolean g_thumb_server_extracting = FALSE; +static int g_communicate_sock = 0; +static int g_timer_id = 0; +static int g_server_pid = 0; + +static GQueue *g_request_queue = NULL; +static int g_queue_work = 0; + +typedef struct { + int client_sock; + thumbMsg *recv_msg; +} thumbRequest; + +gboolean _ms_thumb_agent_start_jobs(gpointer data) +{ + MS_DBG(""); + + return FALSE; +} + +void _ms_thumb_agent_finish_jobs() +{ + MS_DBG(""); + + return; +} + +GMainLoop * +ms_get_thumb_thread_mainloop(void) +{ + return g_thumb_agent_loop; +} + +int ms_thumb_get_server_pid() +{ + return g_server_pid; +} + +void ms_thumb_reset_server_status() +{ + g_folk_thumb_server = FALSE; + + if (g_timer_id > 0) { + g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id)); + g_timer_id = 0; + } + + if (g_thumb_server_extracting) { + /* Need to inplement when crash happens */ +#if 0 + /* Restart thumbnail server */ + if (_ms_thumb_agent_execute_server() < 0) { + MS_DBG_ERR("starting thumbnail-server failed"); + } else { + MS_DBG("Thumbnail-server is started"); + } + + thumbMsg msg; + thumbMsg recv_msg; + memset((void *)&msg, 0, sizeof(msg)); + memset((void *)&recv_msg, 0, sizeof(recv_msg)); + + msg.msg_type = 2; // THUMB_REQUEST_ALL_MEDIA + msg.org_path[0] = '\0'; + msg.origin_path_size = 1; + msg.dst_path[0] = '\0'; + msg.dest_path_size = 1; + + /* Command all thumbnail extraction to thumbnail server */ + if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) { + MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed"); + } + + _ms_thumb_create_timer(g_timer_id); +#else + MS_DBG_ERR("Thumbnail server is dead when processing all-thumbs extraction"); + g_thumb_server_extracting = FALSE; + g_server_pid = 0; +#endif + } else { + g_thumb_server_extracting = FALSE; + g_server_pid = 0; + } + + return; +} + +void _ms_thumb_create_timer(int id) +{ + if (id > 0) + g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), id)); + + GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20); + g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL); + g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default()); + +} + +/* This checks if thumbnail server is running */ +bool _ms_thumb_check_process() +{ + DIR *pdir; + struct dirent pinfo; + struct dirent *result = NULL; + bool ret = FALSE; + + pdir = opendir("/proc"); + if (pdir == NULL) { + MS_DBG_ERR("err: NO_DIR\n"); + return 0; + } + + while (!readdir_r(pdir, &pinfo, &result)) { + if (result == NULL) + break; + + if (pinfo.d_type != 4 || pinfo.d_name[0] == '.' + || pinfo.d_name[0] > 57) + continue; + + FILE *fp; + char buff[128]; + char path[128]; + + ms_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name); + fp = fopen(path, "rt"); + if (fp) { + if (fgets(buff, 128, fp) == NULL) + MS_DBG_ERR("fgets failed"); + fclose(fp); + + if (strstr(buff, THUMB_SERVER_NAME)) { + ret = TRUE; + break; + } + } else { + MS_DBG_ERR("Can't read file [%s]", path); + } + } + + closedir(pdir); + + return ret; +} +int +_ms_thumb_create_socket(int sock_type, int *sock) +{ + int sock_fd = 0; + + if ((sock_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + MS_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + if (sock_type == CLIENT_SOCKET) { + + struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 }; + + if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) { + MS_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sock_fd); + return MS_MEDIA_ERR_SOCKET_INTERNAL; + } + } else if (sock_type == SERVER_SOCKET) { + + int n_reuse = 1; + + if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) { + MS_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sock_fd); + return MS_MEDIA_ERR_SOCKET_INTERNAL; + } + } + + *sock = sock_fd; + + return MS_MEDIA_ERR_NONE; +} + + +int +_ms_thumb_create_udp_socket(int *sock) +{ + int sock_fd = 0; + + if ((sock_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + MS_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + struct timeval tv_timeout = { MS_TIMEOUT_SEC_10, 0 }; + + if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) { + MS_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sock_fd); + return MS_MEDIA_ERR_SOCKET_INTERNAL; + } + + *sock = sock_fd; + + return MS_MEDIA_ERR_NONE; +} + +int _media_thumb_get_error() +{ + if (errno == EWOULDBLOCK) { + MS_DBG_ERR("Timeout. Can't try any more"); + return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT; + } else { + MS_DBG_ERR("recvfrom failed : %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_RECEIVE; + } +} + +int +_ms_thumb_recv_msg(int sock, int header_size, thumbMsg *msg) +{ + int recv_msg_len = 0; + unsigned char *buf = NULL; + + buf = (unsigned char*)malloc(header_size); + + if ((recv_msg_len = recv(sock, buf, header_size, 0)) < 0) { + MS_DBG_ERR("recv failed : %s", strerror(errno)); + MS_SAFE_FREE(buf); + return _media_thumb_get_error(); + } + + memcpy(msg, buf, header_size); + //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size); + + MS_SAFE_FREE(buf); + + if (msg->origin_path_size <= 0 || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) { + MS_SAFE_FREE(buf); + MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size ); + return MS_MEDIA_ERR_DATA_TAINTED; + } + + buf = (unsigned char*)malloc(msg->origin_path_size); + + if ((recv_msg_len = recv(sock, buf, msg->origin_path_size, 0)) < 0) { + MS_DBG_ERR("recv failed : %s", strerror(errno)); + MS_SAFE_FREE(buf); + return _media_thumb_get_error(); + } + + strncpy(msg->org_path, (char*)buf, msg->origin_path_size); + //MS_DBG("original path : %s", msg->org_path); + + MS_SAFE_FREE(buf); + + if (msg->dest_path_size <= 0 || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) { + MS_SAFE_FREE(buf); + MS_DBG_ERR("msg->dest_path_size is invalid %d", msg->dest_path_size ); + return MS_MEDIA_ERR_DATA_TAINTED; + } + + buf = (unsigned char*)malloc(msg->dest_path_size); + + if ((recv_msg_len = recv(sock, buf, msg->dest_path_size, 0)) < 0) { + MS_DBG_ERR("recv failed : %s", strerror(errno)); + MS_SAFE_FREE(buf); + return _media_thumb_get_error(); + } + + strncpy(msg->dst_path, (char*)buf, msg->dest_path_size); + //MS_DBG("destination path : %s", msg->dst_path); + + MS_SAFE_FREE(buf); + return MS_MEDIA_ERR_NONE; +} + + +int +_ms_thumb_recv_udp_msg(int sock, int header_size, thumbMsg *msg, struct sockaddr_in *from_addr, unsigned int *from_size) +{ + int recv_msg_len = 0; + unsigned int from_addr_size = sizeof(struct sockaddr_in); + unsigned char *buf = NULL; + + buf = (unsigned char*)malloc(sizeof(thumbMsg)); + + recv_msg_len = ms_ipc_wait_message(sock, buf, sizeof(thumbMsg), from_addr, &from_addr_size); + if (recv_msg_len != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_wait_message failed : %s", strerror(errno)); + MS_SAFE_FREE(buf); + return _media_thumb_get_error(); + } + + memcpy(msg, buf, header_size); + //MS_DBG("origin_path_size : %d, dest_path_size : %d", msg->origin_path_size, msg->dest_path_size); + + if (msg->origin_path_size <= 0 || msg->origin_path_size > MS_FILE_PATH_LEN_MAX) { + MS_SAFE_FREE(buf); + MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->origin_path_size ); + return MS_MEDIA_ERR_DATA_TAINTED; + } + + strncpy(msg->org_path, (char*)buf + header_size, msg->origin_path_size); + //MS_DBG("original path : %s", msg->org_path); + + if (msg->dest_path_size <= 0 || msg->dest_path_size > MS_FILE_PATH_LEN_MAX) { + MS_SAFE_FREE(buf); + MS_DBG_ERR("msg->origin_path_size is invalid %d", msg->dest_path_size ); + return MS_MEDIA_ERR_DATA_TAINTED; + } + + strncpy(msg->dst_path, (char*)buf + header_size + msg->origin_path_size, msg->dest_path_size); + //MS_DBG("destination path : %s", msg->dst_path); + + MS_SAFE_FREE(buf); + *from_size = from_addr_size; + + return MS_MEDIA_ERR_NONE; +} + +int +_ms_thumb_set_buffer(thumbMsg *req_msg, unsigned char **buf, int *buf_size) +{ + if (req_msg == NULL || buf == NULL) { + return -1; + } + + int org_path_len = 0; + int dst_path_len = 0; + int size = 0; + int header_size = 0; + + header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2; + org_path_len = strlen(req_msg->org_path) + 1; + dst_path_len = strlen(req_msg->dst_path) + 1; + + //MS_DBG("Basic Size : %d, org_path : %s[%d], dst_path : %s[%d]", header_size, req_msg->org_path, org_path_len, req_msg->dst_path, dst_path_len); + + size = header_size + org_path_len + dst_path_len; + *buf = malloc(size); + memcpy(*buf, req_msg, header_size); + memcpy((*buf)+header_size, req_msg->org_path, org_path_len); + memcpy((*buf)+header_size + org_path_len, req_msg->dst_path, dst_path_len); + + *buf_size = size; + + return 0; +} + +/* +void _ms_thumb_agent_child_handler(GPid pid, gint status, gpointer user_data) +{ + MS_DBG_WARN("media-thumbnail-server[%d] is shutdown : %d", pid, status); + g_folk_thumb_server = FALSE; +} +*/ +gboolean _ms_thumb_agent_child_handler(gpointer data) +{ + int pid = GPOINTER_TO_INT(data); + MS_DBG("media-thumbnail-server[%d] is killed", pid); + return FALSE; +} + +gboolean _ms_thumb_agent_recv_msg_from_server() +{ + if (g_communicate_sock <= 0) { + _ms_thumb_agent_prepare_udp_socket(); + } + + ms_thumb_server_msg recv_msg; + int recv_msg_size = 0; + + recv_msg_size = ms_ipc_receive_message(g_communicate_sock, & recv_msg, sizeof(ms_thumb_server_msg), NULL, NULL); + if (recv_msg_size != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_receive_message failed : %s\n", strerror(errno)); + return FALSE; + } + + //MS_DBG("Receive : %d(%d)", recv_msg.msg_type, recv_msg_size); + if (recv_msg.msg_type == MS_MSG_THUMB_SERVER_READY) { + MS_DBG("Thumbnail server is ready"); + } + + return TRUE; +} + +gboolean _ms_thumb_agent_recv_thumb_done_from_server(GIOChannel *src, GIOCondition condition, gpointer data) +{ + int sockfd = -1; + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return FALSE; + } + + ms_thumb_server_msg recv_msg; + int recv_msg_size = 0; + + recv_msg_size = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(ms_thumb_server_msg), NULL, NULL); + if (recv_msg_size != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("ms_ipc_receive_message failed : %s\n", strerror(errno)); + return FALSE; + } + + MS_DBG("Receive : %d(%d)", recv_msg.msg_type, recv_msg_size); + if (recv_msg.msg_type == MS_MSG_THUMB_EXTRACT_ALL_DONE) { + MS_DBG("Thumbnail extracting done"); + g_thumb_server_extracting = FALSE; + + return FALSE; + } + + return FALSE; +} + +gboolean _ms_thumb_agent_execute_server() +{ + int pid; + pid = fork(); + + if (pid < 0) { + return FALSE; + } else if (pid == 0) { + execl("/usr/bin/media-thumbnail-server", "media-thumbnail-server", NULL); + } else { + MS_DBG("Child process is %d", pid); + g_folk_thumb_server = TRUE; + } +#if 0 + GSource *child_watch_src = g_child_watch_source_new(pid); + g_source_set_callback(child_watch_src, _ms_thumb_agent_child_handler, GINT_TO_POINTER(pid), NULL); + g_source_attach(child_watch_src, g_main_context_get_thread_default()); +#endif + //g_child_watch_add(pid, _ms_thumb_agent_child_handler, NULL); + g_server_pid = pid; + + if (!_ms_thumb_agent_recv_msg_from_server()) { + MS_DBG_ERR("_ms_thumb_agent_recv_msg_from_server is failed"); + return FALSE; + } + + return TRUE; +} + +gboolean _ms_thumb_agent_send_msg_to_thumb_server(thumbMsg *recv_msg, thumbMsg *res_msg) +{ + int sock; + const char *serv_ip = "127.0.0.1"; + struct sockaddr_in serv_addr; + + int send_str_len = strlen(recv_msg->org_path); + + if (send_str_len > MAX_MSG_SIZE) { + MS_DBG_ERR("original path's length exceeds %d(max packet size)", MAX_MSG_SIZE); + return FALSE; + } + +#if 0 + /* Creaete a datagram/UDP socket */ + if (_ms_thumb_create_udp_socket(&sock) < 0) { + MS_DBG_ERR("_ms_thumb_create_udp_socket failed"); + return FALSE; + } +#endif + if (ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sock) < 0) { + MS_DBG_ERR("ms_ipc_create_client_socket failed"); + return FALSE; + } + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(serv_ip); + serv_addr.sin_port = htons(MS_THUMB_DAEMON_PORT); + + int buf_size = 0; + int header_size = 0; + unsigned char *buf = NULL; + _ms_thumb_set_buffer(recv_msg, &buf, &buf_size); + + //MS_DBG("buffer size : %d", buf_size); + if (sendto(sock, buf, buf_size, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != buf_size) { + MS_DBG_ERR("sendto failed: %s\n", strerror(errno)); + MS_SAFE_FREE(buf); + close(sock); + return FALSE; + } + + MS_SAFE_FREE(buf); + MS_DBG("Sending msg to thumbnail server is successful"); + + struct sockaddr_in client_addr; + unsigned int client_addr_len; + header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2; + + if (_ms_thumb_recv_udp_msg(sock, header_size, res_msg, &client_addr, &client_addr_len) < 0) { + MS_DBG_ERR("_ms_thumb_recv_udp_msg failed"); + close(sock); + return FALSE; + } + + MS_DBG("recv %s from thumb daemon is successful", res_msg->dst_path); + close(sock); + + if (res_msg->msg_type == 2 && g_communicate_sock > 0) { // THUMB_REQUEST_ALL_MEDIA + /* Create new channel to watch udp socket */ + GSource *source = NULL; + if (g_udp_channel == NULL) + g_udp_channel = g_io_channel_unix_new(g_communicate_sock); + source = g_io_create_watch(g_udp_channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_recv_thumb_done_from_server, NULL, NULL); + g_source_attach(source, g_main_context_get_thread_default()); + + g_thumb_server_extracting = TRUE; + } + + return TRUE; +} + +gboolean _ms_thumb_agent_timer() +{ + if (g_thumb_server_extracting) { + MS_DBG("Timer is called.. But media-thumbnail-server[%d] is busy.. so timer is recreated", g_server_pid); + + _ms_thumb_create_timer(g_timer_id); + return FALSE; + } + + g_timer_id = 0; + MS_DBG("Timer is called.. Now killing media-thumbnail-server[%d]", g_server_pid); + + if (g_server_pid > 0) { +#if 0 + if (kill(g_server_pid, SIGKILL) < 0) { + MS_DBG_ERR("kill failed : %s", strerror(errno)); + } +#else + /* Kill thumbnail server */ + thumbMsg msg; + thumbMsg recv_msg; + memset((void *)&msg, 0, sizeof(msg)); + memset((void *)&recv_msg, 0, sizeof(recv_msg)); + + msg.msg_type = 5; // THUMB_REQUEST_KILL_SERVER + msg.org_path[0] = '\0'; + msg.origin_path_size = 1; + msg.dst_path[0] = '\0'; + msg.dest_path_size = 1; + + /* Command Kill to thumbnail server */ + if (!_ms_thumb_agent_send_msg_to_thumb_server(&msg, &recv_msg)) { + MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed"); + } +#endif + usleep(200000); + } else { + MS_DBG_ERR("g_server_pid is %d. Maybe there's problem in thumbnail-server", g_server_pid); + } + + return FALSE; +} + +#if 0 +gboolean _ms_thumb_agent_read_socket(GIOChannel *src, + GIOCondition condition, + gpointer data) +{ + struct sockaddr_in client_addr; + unsigned int client_addr_len; + + thumbMsg recv_msg; + thumbMsg res_msg; + int header_size = 0; + int sock = -1; + int client_sock = -1; + + sock = g_io_channel_unix_get_fd(src); + if (sock < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + + memset((void *)&recv_msg, 0, sizeof(thumbMsg)); + memset((void *)&res_msg, 0, sizeof(res_msg)); + header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2; + + if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { + MS_DBG_ERR("accept failed : %s", strerror(errno)); + return TRUE; + } + + MS_DBG("Client[%d] is accepted", client_sock); + + if (_ms_thumb_recv_msg(client_sock, header_size, &recv_msg) < 0) { + MS_DBG_ERR("_ms_thumb_recv_msg failed "); + close(client_sock); + return TRUE; + } + + MS_DBG("Received [%d] %s(%d) from PID(%d) \n", recv_msg.msg_type, recv_msg.org_path, strlen(recv_msg.org_path), recv_msg.pid); + + if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) { + if(_ms_thumb_check_process() == FALSE) { // This logic is temporary + MS_DBG_WARN("Thumb server is not running.. so start it"); + if (!_ms_thumb_agent_execute_server()) { + MS_DBG_ERR("_ms_thumb_agent_execute_server is failed"); + return TRUE; + } else { + + GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20); + g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL); + g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default()); + } + } + } else { + if (g_timer_id > 0) { + g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), g_timer_id)); + //MS_DBG("Timer is recreated"); + GSource *timer_src = g_timeout_source_new_seconds(MS_TIMEOUT_SEC_20); + g_source_set_callback (timer_src, _ms_thumb_agent_timer, NULL, NULL); + g_timer_id = g_source_attach (timer_src, g_main_context_get_thread_default()); + } + } + + if (!_ms_thumb_agent_send_msg_to_thumb_server(&recv_msg, &res_msg)) { + MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed"); + + return TRUE; + } + + strncpy(res_msg.org_path, recv_msg.org_path, recv_msg.origin_path_size); + res_msg.origin_path_size = recv_msg.origin_path_size; + res_msg.dest_path_size = strlen(res_msg.dst_path) + 1; + + int buf_size = 0; + unsigned char *buf = NULL; + _ms_thumb_set_buffer(&res_msg, &buf, &buf_size); + + //MS_DBG("buffer size : %d", buf_size); + + if (send(client_sock, buf, buf_size, 0) != buf_size) { + MS_DBG_ERR("sendto failed : %s", strerror(errno)); + } else { + MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path)); + } + + close(client_sock); + MS_SAFE_FREE(buf); + return TRUE; +} +#else +int _ms_thumb_cancel_media(const char *path, int pid) +{ + int ret = -1; + int i = 0; + int req_len = 0; + + req_len = g_queue_get_length(g_request_queue); + + MS_DBG("Queue length : %d", req_len); + + for (i = 0; i < req_len; i++) { + thumbRequest *req = NULL; + req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i); + if (req == NULL) continue; + + if ((req->recv_msg->pid) == pid && (strncmp(path, req->recv_msg->org_path, strlen(path))) == 0) { + MS_DBG("Remove %s from queue", req->recv_msg->org_path); + g_queue_pop_nth(g_request_queue, i); + + close(req->client_sock); + MS_SAFE_FREE(req->recv_msg); + MS_SAFE_FREE(req); + ret = 0; + + break; + } + } + + return ret; +} + +int _ms_thumb_cancel_all(int pid) +{ + int ret = -1; + int i = 0; + int req_len = 0; + + req_len = g_queue_get_length(g_request_queue); + + MS_DBG("Queue length : %d", req_len); + + for (i = 0; i < req_len; i++) { + thumbRequest *req = NULL; + req = (thumbRequest *)g_queue_peek_nth(g_request_queue, i); + if (req == NULL) continue; + + if (req->recv_msg->pid == pid) { + MS_DBG("Remove [%d] %s from queue", req->recv_msg->pid, req->recv_msg->org_path); + g_queue_pop_nth(g_request_queue, i); + i--; + req_len--; + + close(req->client_sock); + MS_SAFE_FREE(req->recv_msg); + MS_SAFE_FREE(req); + ret = 0; + } + } + + return ret; +} + +void _ms_thumb_cancle_request(thumbRequest *thumb_req) +{ + MS_DBG(""); + int ret = -1; + + if (thumb_req == NULL) return; + + thumbMsg *recv_msg = thumb_req->recv_msg; + if (recv_msg == NULL) { + MS_SAFE_FREE(thumb_req); + return; + } + + if (recv_msg->msg_type == 3) + ret = _ms_thumb_cancel_media(recv_msg->org_path, recv_msg->pid); + else if (recv_msg->msg_type == 4) + ret = _ms_thumb_cancel_all(recv_msg->pid); + + if (ret == 0) { + recv_msg->status = 0; // THUMB_SUCCESS + } else { + recv_msg->status = 0; // THUMB_SUCCESS + } + + if (recv_msg->origin_path_size <= 0 || recv_msg->origin_path_size > MS_FILE_PATH_LEN_MAX) { + MS_DBG_ERR("recv_msg->origin_path_size is invalid %d", recv_msg->origin_path_size ); + return; + } + + recv_msg->dest_path_size = recv_msg->origin_path_size; + strncpy(recv_msg->dst_path, recv_msg->org_path, recv_msg->dest_path_size); +/* + int buf_size = 0; + unsigned char *buf = NULL; + _ms_thumb_set_buffer(recv_msg, &buf, &buf_size); + + if (send(thumb_req->client_sock, buf, buf_size, 0) != buf_size) { + MS_DBG_ERR("sendto failed : %s", strerror(errno)); + } else { + MS_DBG("Sent response"); + } +*/ + close(thumb_req->client_sock); + //MS_SAFE_FREE(buf); + MS_SAFE_FREE(thumb_req->recv_msg); + MS_SAFE_FREE(thumb_req); + + return; +} + +gboolean _ms_thumb_request_to_server(gpointer data) +{ + int req_len = 0; + + req_len = g_queue_get_length(g_request_queue); + + MS_DBG("Queue length : %d", req_len); + + if (req_len <= 0) { + MS_DBG("There is no request job in the queue"); + g_queue_work = 0; + return FALSE; + } + + if (g_folk_thumb_server == FALSE && g_thumb_server_extracting == FALSE) { + if(_ms_thumb_check_process() == FALSE) { // This logic is temporary + MS_DBG_WARN("Thumb server is not running.. so start it"); + if (!_ms_thumb_agent_execute_server()) { + MS_DBG_ERR("_ms_thumb_agent_execute_server is failed"); + g_queue_work = 0; + return FALSE; + } else { + _ms_thumb_create_timer(g_timer_id); + } + } + } else { + /* Timer is re-created*/ + _ms_thumb_create_timer(g_timer_id); + } + + thumbRequest *req = NULL; + req = (thumbRequest *)g_queue_pop_head(g_request_queue); + + if (req == NULL) { + MS_DBG_ERR("Failed to get a request job from queue"); + return TRUE; + } + + int client_sock = -1; + thumbMsg *recv_msg = NULL; + thumbMsg res_msg; + memset((void *)&res_msg, 0, sizeof(res_msg)); + + client_sock = req->client_sock; + recv_msg = req->recv_msg; + + if (req->client_sock <=0 || req->recv_msg == NULL) { + MS_DBG_ERR("client sock is below 0 or recv msg is NULL"); + MS_SAFE_FREE(req->recv_msg); + MS_SAFE_FREE(req); + return TRUE; + } + + if (recv_msg) { + if (!_ms_thumb_agent_send_msg_to_thumb_server(recv_msg, &res_msg)) { + MS_DBG_ERR("_ms_thumb_agent_send_msg_to_thumb_server is failed"); + + close(client_sock); + MS_SAFE_FREE(req->recv_msg); + MS_SAFE_FREE(req); + return TRUE; + } + } else { + MS_DBG_ERR("recv_msg is NULL from queue request"); + } + + strncpy(res_msg.org_path, recv_msg->org_path, recv_msg->origin_path_size); + res_msg.origin_path_size = recv_msg->origin_path_size; + res_msg.dest_path_size = strlen(res_msg.dst_path) + 1; + + int buf_size = 0; + unsigned char *buf = NULL; + _ms_thumb_set_buffer(&res_msg, &buf, &buf_size); + + if (send(client_sock, buf, buf_size, 0) != buf_size) { + MS_DBG_ERR("sendto failed : %s", strerror(errno)); + } else { + MS_DBG("Sent %s(%d) \n", res_msg.dst_path, strlen(res_msg.dst_path)); + } + + close(client_sock); + MS_SAFE_FREE(buf); + MS_SAFE_FREE(req->recv_msg); + MS_SAFE_FREE(req); + + return TRUE; +} + +gboolean _ms_thumb_agent_read_socket(GIOChannel *src, + GIOCondition condition, + gpointer data) +{ + struct sockaddr_in client_addr; + unsigned int client_addr_len; + + thumbMsg *recv_msg = NULL; + int header_size = 0; + int sock = -1; + int client_sock = -1; + + sock = g_io_channel_unix_get_fd(src); + if (sock < 0) { + MS_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + + header_size = sizeof(thumbMsg) - MAX_MSG_SIZE*2; + client_addr_len = sizeof(client_addr); + + if ((client_sock = accept(sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { + MS_DBG_ERR("accept failed : %s", strerror(errno)); + return TRUE; + } + + MS_DBG("Client[%d] is accepted", client_sock); + + recv_msg = calloc(1, sizeof(thumbMsg)); + if (recv_msg == NULL) { + MS_DBG_ERR("Failed to allocate memory"); + close(client_sock); + return TRUE; + } + + if (_ms_thumb_recv_msg(client_sock, header_size, recv_msg) < 0) { + MS_DBG_ERR("_ms_thumb_recv_msg failed "); + close(client_sock); + MS_SAFE_FREE(recv_msg); + return TRUE; + } + + MS_DBG("Received [%d] %s(%d) from PID(%d) \n", recv_msg->msg_type, recv_msg->org_path, strlen(recv_msg->org_path), recv_msg->pid); + + thumbRequest *thumb_req = NULL; + thumb_req = calloc(1, sizeof(thumbRequest)); + if (thumb_req == NULL) { + MS_DBG_ERR("Failed to create request element"); + close(client_sock); + MS_SAFE_FREE(recv_msg); + return TRUE; + } + + thumb_req->client_sock = client_sock; + thumb_req->recv_msg = recv_msg; + + if (recv_msg->msg_type == 3 || recv_msg->msg_type == 4) { // THUMB_REQUEST_CANCEL_MEDIA || THUMB_REQUEST_CANCEL_ALL + _ms_thumb_cancle_request(thumb_req); + return TRUE; + } + + if (g_request_queue == NULL) { + MS_DBG_WARN("queue is init"); + g_request_queue = g_queue_new(); + } + + MS_DBG("%s is queued", recv_msg->org_path); + g_queue_push_tail(g_request_queue, (gpointer)thumb_req); + + if (!g_queue_work) { + GSource *src_request = NULL; + src_request = g_idle_source_new (); + g_source_set_callback (src_request, _ms_thumb_request_to_server, NULL, NULL); + //g_source_set_priority(src_request, G_PRIORITY_LOW); + g_source_attach (src_request, g_main_context_get_thread_default()); + g_queue_work = 1; + } + + return TRUE; +} +#endif + + +gboolean _ms_thumb_agent_prepare_tcp_socket(int *sock_fd) +{ + int sock; + unsigned short serv_port; + + serv_port = MS_THUMB_CREATOR_PORT; + +#if 0 + struct sockaddr_in serv_addr; + + /* Create a TCP socket */ + if (_ms_thumb_create_socket(SERVER_SOCKET, &sock) < 0) { + MS_DBG_ERR("_ms_thumb_create_socket failed"); + return FALSE; + } + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(serv_port); + + /* Bind to the local address */ + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + MS_DBG_ERR("bind failed"); + return FALSE; + } + + MS_DBG("bind success"); + + /* Listening */ + if (listen(sock, SOMAXCONN) < 0) { + MS_DBG_ERR("listen failed : %s", strerror(errno)); + return FALSE; + } + + MS_DBG("Listening..."); +#endif + if (ms_ipc_create_server_socket(MS_PROTOCOL_TCP, serv_port, &sock) < 0) { + MS_DBG_ERR("_ms_thumb_create_socket failed"); + return FALSE; + } + + *sock_fd = sock; + + return TRUE; +} + +gboolean _ms_thumb_agent_prepare_udp_socket() +{ + int sock; + unsigned short serv_port; + + serv_port = MS_THUMB_COMM_PORT; + + if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, serv_port, &sock) < 0) { + MS_DBG_ERR("ms_ipc_create_client_socket failed"); + return FALSE; + } +#if 0 + struct sockaddr_in serv_addr; + + /* Creaete a UDP socket */ + if (_ms_thumb_create_udp_socket(&sock) < 0) { + MS_DBG_ERR("_ms_thumb_create_udp_socket failed"); + return FALSE; + } + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(serv_port); + + /* Bind to the local address */ + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + MS_DBG_ERR("bind failed"); + return FALSE; + } + + MS_DBG("bind success"); +#endif + g_communicate_sock = sock; + + return TRUE; +} + +gpointer ms_thumb_agent_start_thread(gpointer data) +{ + MS_DBG(""); + int sockfd = -1; + + GSource *source = NULL; + GIOChannel *channel = NULL; + GMainContext *context = NULL; + + /* Create and bind new TCP socket */ + if (!_ms_thumb_agent_prepare_tcp_socket(&sockfd)) { + MS_DBG_ERR("Failed to create socket\n"); + return NULL; + } + + context = g_main_context_new(); + + if (context == NULL) { + MS_DBG_ERR("g_main_context_new failed"); + } else { + MS_DBG("g_main_context_new success"); + } + + g_thumb_agent_loop = g_main_loop_new(context, FALSE); + g_main_context_push_thread_default(context); + + /* Create new channel to watch udp socket */ + channel = g_io_channel_unix_new(sockfd); + source = g_io_create_watch(channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)_ms_thumb_agent_read_socket, NULL, NULL); + g_source_attach(source, context); + + + MS_DBG("************************************"); + MS_DBG("*** Thumbnail Agent thread is running ***"); + MS_DBG("************************************"); + + g_main_loop_run(g_thumb_agent_loop); + + MS_DBG("Thumbnail Agent thread is shutting down..."); + _ms_thumb_agent_finish_jobs(); + + /*close an IO channel*/ + g_io_channel_shutdown(channel, FALSE, NULL); + g_io_channel_shutdown(g_udp_channel, FALSE, NULL); + g_io_channel_unref(channel); + close(g_communicate_sock); + + g_main_loop_unref(g_thumb_agent_loop); + + return NULL; +} + diff --git a/common/media-server-utils.c b/common/media-server-utils.c new file mode 100755 index 0000000..360f52c --- /dev/null +++ b/common/media-server-utils.c @@ -0,0 +1,336 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-utils.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ + +#include +#include +#include + +#include "media-util.h" +#include "media-server-dbg.h" +#include "media-server-ipc.h" +#include "media-server-inotify.h" +#include "media-server-utils.h" +#include "media-server-drm.h" +#include "media-server-dbus.h" +#include "media-server-socket.h" + +#ifdef FMS_PERF +#include +#define MILLION 1000000L +struct timeval g_mmc_start_time; +struct timeval g_mmc_end_time; +#endif + +#define MS_DRM_CONTENT_TYPE_LENGTH 100 + +extern int mmc_state; + +static int +_ms_set_power_mode(ms_db_status_type_t status) +{ + int res = MS_MEDIA_ERR_NONE; + int err; + + switch (status) { + case MS_DB_UPDATING: + err = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0); + if (err != 0) + res = MS_MEDIA_ERR_INTERNAL; + break; + case MS_DB_UPDATED: + err = pm_unlock_state(LCD_OFF, STAY_CUR_STATE); + if (err != 0) + res = MS_MEDIA_ERR_INTERNAL; + break; + default: + MS_DBG_ERR("Unacceptable type : %d", status); + break; + } + + return res; +} + +int +ms_set_db_status(ms_db_status_type_t status) +{ + int res = MS_MEDIA_ERR_NONE; + int err = 0; + + if (status == MS_DB_UPDATING) { + if (ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING)) + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + } else if (status == MS_DB_UPDATED) { + if(ms_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATED)) + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + /*notify to other application about db updated by DBUS*/ + ms_dbus_send_noti(MS_DBUS_DB_UPDATED); + } + + err = _ms_set_power_mode(status); + if (err != MS_MEDIA_ERR_NONE) { + MS_DBG_ERR("_ms_set_power_mode fail"); + res = err; + } + + return res; +} + +#ifdef FMS_PERF +void +ms_check_start_time(struct timeval *start_time) +{ + gettimeofday(start_time, NULL); +} + +void +ms_check_end_time(struct timeval *end_time) +{ + gettimeofday(end_time, NULL); +} + +void +ms_check_time_diff(struct timeval *start_time, struct timeval *end_time) +{ + struct timeval time; + long difftime; + + time.tv_sec = end_time->tv_sec - start_time->tv_sec; + time.tv_usec = end_time->tv_usec - start_time->tv_usec; + difftime = MILLION * time.tv_sec + time.tv_usec; + MS_DBG("The function_to_time took %ld microseconds or %f seconds.", + difftime, difftime / (double)MILLION); +} +#endif + +bool +ms_is_mmc_inserted(void) +{ + int data = -1; + ms_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &data); + if (data != VCONFKEY_SYSMAN_MMC_MOUNTED) { + return false; + } else { + return true; + } +} + +/*CAUTION : Before using this function, Have to allocate static memory of ret_path*/ +/*And the array length does not over MS_FILE_PATH_LEN_MAX*/ +/*for example : char path[MS_FILE_PATH_LEN_MAX] = {0};*/ +int +ms_get_full_path_from_node(ms_dir_scan_info * const node, char *ret_path, int depth) +{ + int i = 0; + int path_length = 0; + int length = 0; + ms_dir_scan_info *cur_node; + char **path_array; + + if (depth < 0) { + MS_DBG_ERR("depth < 0"); + return MS_MEDIA_ERR_INVALID_PATH; + } + + MS_MALLOC(path_array, sizeof(char*) * (depth + 1)); + + cur_node = node; + + while (1) { + path_array[i] = cur_node->name; + if (cur_node->parent == NULL) + break; + + cur_node = cur_node->parent; + i++; + } + + for(i = depth ; i >= 0 ; i --) { + length = strlen(path_array[i]); + + if (path_length + length > MS_FILE_PATH_LEN_MAX) { + MS_DBG_ERR("This is invalid path, %s, %d", node->name, depth); + MS_SAFE_FREE(path_array); + return MS_MEDIA_ERR_INVALID_PATH; + } + + strncpy(ret_path+path_length, path_array[i], length); + path_length += length; + + ret_path[path_length] = '/'; + path_length ++; + } + + ret_path[-- path_length] = '\0'; + + MS_SAFE_FREE(path_array); + + return MS_MEDIA_ERR_NONE; +} + +ms_storage_type_t +ms_get_storage_type_by_full(const char *path) +{ + if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) { + return MS_STORAGE_INTERNAL; + } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) { + return MS_STORAGE_EXTERNAL; + } else + return MS_MEDIA_ERR_INVALID_PATH; +} + +int +ms_strappend(char *res, const int size, const char *pattern, + const char *str1, const char *str2) +{ + int len = 0; + int real_size = size - 1; + + if (!res ||!pattern || !str1 ||!str2 ) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + if (real_size < (strlen(str1) + strlen(str2))) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + len = snprintf(res, real_size, pattern, str1, str2); + if (len < 0) { + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res[len] = '\0'; + + return MS_MEDIA_ERR_NONE; +} + +int +ms_strcopy(char *res, const int size, const char *pattern, const char *str1) +{ + int len = 0; + int real_size = size; + + if (!res || !pattern || !str1) { + MS_DBG_ERR("parameta is invalid"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + if (real_size < strlen(str1)) { + MS_DBG_ERR("size is wrong"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + len = snprintf(res, real_size, pattern, str1); + if (len < 0) { + MS_DBG_ERR("snprintf failed"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res[len] = '\0'; + + return MS_MEDIA_ERR_NONE; +} + +bool +ms_config_get_int(const char *key, int *value) +{ + int err; + + if (!key || !value) { + MS_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + err = vconf_get_int(key, value); + if (err == 0) + return true; + else if (err == -1) + return false; + else + MS_DBG_ERR("Unexpected error code: %d", err); + + return false; +} + +bool +ms_config_set_int(const char *key, int value) +{ + int err; + + if (!key) { + MS_DBG_ERR("Arguments key is NULL"); + return false; + } + + err = vconf_set_int(key, value); + if (err == 0) + return true; + else if (err == -1) + return false; + else + MS_DBG_ERR("Unexpected error code: %d", err); + + return false; +} + +bool +ms_config_get_str(const char *key, char *value) +{ + char *res; + if (!key || !value) { + MS_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + res = vconf_get_str(key); + if (res) { + strncpy(value, res, strlen(res) + 1); + return true; + } + + return false; +} + +bool +ms_config_set_str(const char *key, const char *value) +{ + int err; + + if (!key || !value) { + MS_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + err = vconf_set_str(key, value); + if (err == 0) + return true; + else + MS_DBG_ERR("fail to vconf_set_str %d", err); + + return false; +} + diff --git a/common/mediadb-update.c b/common/mediadb-update.c new file mode 100644 index 0000000..034b4d6 --- /dev/null +++ b/common/mediadb-update.c @@ -0,0 +1,157 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "media-util.h" + +GMainLoop * mainloop = NULL; + +void callback(media_request_result_s * result, void *user_data) +{ + printf("db updating done\n"); + + g_main_loop_quit(mainloop); +} + +void print_help() +{ + printf("=======================================================================================\n"); + printf("\n"); + printf("mediadb-update [option] \n"); + printf("\n"); + printf("[option]\n"); + printf(" -r : [only directory] update all directory recursivly under \n"); + printf("\n"); + printf("mediadb-update --help for check this messages.\n"); + printf("\n"); + printf("A file or directory must exists under /opt/usr/media or /opt/storage/sdcard.\n"); + printf("Using /opt/storage/sdcard is allowed SD card is mounted.\n"); + printf("\n"); + printf("=======================================================================================\n"); + exit(1); +} + +int dir_scan_non_recursive(char *path) +{ + return media_directory_scanning_async(path, FALSE, callback, NULL); +} + +int dir_scan_recursive(char *path) +{ + return media_directory_scanning_async(path, TRUE, callback, NULL); +} + +typedef enum { + DIRECTORY_OK, + FILE_OK, + NOT_OK, +}check_result; + +check_result check_path(char *path) +{ + struct stat buf; + DIR *dp = NULL; + + /*check the path directory or file*/ + if (stat(path, &buf) == 0) { + if (S_ISDIR(buf.st_mode)) { + printf("This is directory\n"); + return DIRECTORY_OK; + } else { + dp = opendir(path); + if (dp == NULL) { + /*if openning directory is failed, check it exists. */ + if (errno == ENOENT) { + /* this directory is deleted */ + return DIRECTORY_OK; + } + } else { + closedir(dp); + } + printf("[%d]invalid path\n", __LINE__); + print_help(); + } + } else { + printf("stat error : %s\n", strerror(errno)); + } + + return NOT_OK; +} + +int main(int argc, char **argv) +{ + int ret; + char *argv1 = NULL; + char *argv2 = NULL; + + if (argc > 3 || argc < 2) { + print_help(); + } + + argv1 = strdup(argv[1]); + + mainloop = g_main_loop_new(NULL, FALSE); + + if (argc == 2) { + if (strcmp(argv1 , "--help") == 0) { + print_help(); + } + + if (check_path(argv1) == DIRECTORY_OK) { + ret = dir_scan_non_recursive(argv1); + if (ret != 0) { + printf("error : %d\n", ret); + exit(1); + } + } else { + print_help(); + } + } else if (argc == 3) { + argv2 = strdup(argv[2]); + if (strcmp(argv1, "-r") == 0) { + if (check_path(argv2) == DIRECTORY_OK) { + ret = dir_scan_recursive(argv2); + if (ret != 0) { + printf("error : %d\n", ret); + exit(1); + } + } else { + print_help(); + } + } else { + printf("[%d] invalide option\n", __LINE__); + print_help(); + } + } + + g_main_loop_run(mainloop); + + exit(0); +} diff --git a/common/scanner/include/media-scanner-db-svc.h b/common/scanner/include/media-scanner-db-svc.h new file mode 100755 index 0000000..06bc60c --- /dev/null +++ b/common/scanner/include/media-scanner-db-svc.h @@ -0,0 +1,102 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-db-svc.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SCANNER_DB_SVC_H_ +#define _MEDIA_SCANNER_DB_SVC_H_ + +#include "media-server-types.h" + +typedef int (*CHECK_ITEM)(const char*, const char*, char **); +typedef int (*CONNECT)(void**, char **); +typedef int (*DISCONNECT)(void*, char **); +typedef int (*CHECK_ITEM_EXIST)(void*, const char*, int, char **); +typedef int (*INSERT_ITEM_BEGIN)(void*, int, char **); +typedef int (*INSERT_ITEM_END)(void*, char **); +typedef int (*INSERT_ITEM)(void*, const char*, int, const char*, char **); +typedef int (*SET_ALL_STORAGE_ITEMS_VALIDITY)(void*, int, int, char **); +typedef int (*SET_ITEM_VALIDITY_BEGIN)(void*, int, char **); +typedef int (*SET_ITEM_VALIDITY_END)(void*, char **); +typedef int (*SET_ITEM_VALIDITY)(void*, const char*, int, const char*, int, char **); +typedef int (*DELETE_ALL_ITEMS_IN_STORAGE)(void*, int, char **); +typedef int (*DELETE_ALL_INVALID_ITMES_IN_STORAGE)(void*, int, char **); +typedef int (*UPDATE_BEGIN)(void); +typedef int (*UPDATE_END)(void); +typedef int (*SET_FOLDER_ITEM_VALIDITY)(void*, const char*, int, int, char**); +typedef int (*DELETE_ALL_INVALID_ITEMS_IN_FOLDER)(void*, const char*, char**); + +int +msc_load_functions(void); + +void +msc_unload_functions(void); + +int +msc_connect_db(void ***handle); + +int +msc_disconnect_db(void ***handle); + +int +msc_validate_item(void **handle, char *path); + +int +msc_insert_item_batch(void **handle, const char *path); + +bool +msc_delete_all_items(void **handle, ms_storage_type_t store_type); + +int +msc_invalidate_all_items(void **handle, ms_storage_type_t store_type); + +bool +msc_delete_invalid_items(void **handle, ms_storage_type_t store_type); + +int +msc_set_folder_validity(void **handle, const char *path, int validity, int recursive); + +int +msc_delete_invalid_items_in_folder(void **handle, const char*path); + +/**************************************************************************************************** +FOR BULK COMMIT +*****************************************************************************************************/ + +void +msc_register_start(void **handle); + +void +msc_register_end(void **handle); + +void +msc_validate_start(void **handle); + +void +msc_validate_end(void **handle); + +#endif /*_MEDIA_SCANNER_DB_SVC_H_*/ diff --git a/common/scanner/include/media-scanner-dbg.h b/common/scanner/include/media-scanner-dbg.h new file mode 100755 index 0000000..6c892f3 --- /dev/null +++ b/common/scanner/include/media-scanner-dbg.h @@ -0,0 +1,49 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-scanner-dbg.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SCANNER_DBG_H_ +#define _MEDIA_SCANNER_DBG_H_ +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "MEDIA_SCANNER" +#define MSC_DBG_INFO(fmt, args...) LOGD(fmt "\n" , ##args); +#define MSC_DBG_ERR(fmt, args...) do{ if (true) { \ + LOGE(fmt "\n", ##args); \ + }} while(false) + +/** + * @} + */ +#endif /*_MEDIA_SCANNER_DBG_H_*/ + diff --git a/common/scanner/include/media-scanner-drm.h b/common/scanner/include/media-scanner-drm.h new file mode 100755 index 0000000..33ef8f2 --- /dev/null +++ b/common/scanner/include/media-scanner-drm.h @@ -0,0 +1,54 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-drm.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ +#ifndef _MEDIA_SCANNER_DRM_H_ +#define _MEDIA_SCANNER_DRM_H_ + +bool +msc_is_drm_file(const char *path); + +int +msc_get_mime_in_drm_info(const char *path, char *mime); + +int +msc_drm_register(const char* path); + +void +msc_drm_unregister(const char* path); + +void +msc_drm_unregister_all(void); + +bool +msc_drm_insert_ext_memory(void); + +bool +msc_drm_extract_ext_memory(void); + +#endif /*_MEDIA_SCANNER_DRM_H_*/ \ No newline at end of file diff --git a/common/scanner/include/media-scanner-scan.h b/common/scanner/include/media-scanner-scan.h new file mode 100755 index 0000000..49e32c9 --- /dev/null +++ b/common/scanner/include/media-scanner-scan.h @@ -0,0 +1,43 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-scan.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SCANNER_SCAN_H_ +#define _MEDIA_SCANNER_SCAN_H_ + +gboolean msc_directory_scan_thread(void *data); + +gboolean msc_register_thread(void *data); + +gboolean msc_storage_scan_thread(void *data); + +int msc_check_remain_task(void); + +ms_db_status_type_t msc_check_scanning_status(void); + +#endif /*_MEDIA_SCANNER_SCAN_H_*/ \ No newline at end of file diff --git a/common/scanner/include/media-scanner-socket.h b/common/scanner/include/media-scanner-socket.h new file mode 100755 index 0000000..68f7dff --- /dev/null +++ b/common/scanner/include/media-scanner-socket.h @@ -0,0 +1,44 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-thumb.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SCANNER_SOCKET_H_ +#define _MEDIA_SCANNER_SOCKET_H_ + +#include "media-server-types.h" +#include "media-server-ipc.h" + +gboolean msc_receive_request(GIOChannel *src, GIOCondition condition, gpointer data); + +int msc_send_ready(void); + +int msc_send_scan_result(int result, ms_comm_msg_s *scan_data); + +int msc_send_register_result(int result, ms_comm_msg_s *reg_data); + +#endif /*_MEDIA_SCANNER_SOCKET_H_*/ diff --git a/common/scanner/include/media-scanner-utils.h b/common/scanner/include/media-scanner-utils.h new file mode 100755 index 0000000..a19043d --- /dev/null +++ b/common/scanner/include/media-scanner-utils.h @@ -0,0 +1,86 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-utils.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_SCANNER_UTILS_H__ +#define _MEDIA_SCANNER_UTILS_H__ + +#include "media-server-types.h" + +bool +msc_is_mmc_inserted(void); + +int +msc_update_mmc_info(void); + +void +msc_mmc_vconf_cb(void *data); + +int +msc_get_full_path_from_node(ms_dir_scan_info * const node, char *ret_path, int depth); + +ms_storage_type_t +msc_get_storage_type_by_full(const char *path); + +int +msc_strappend(char *res, const int size, const char *pattern, + const char *str1, const char *str2); + +int +msc_strcopy(char *res, const int size, const char *pattern, + const char *str1); + +bool +msc_config_get_int(const char *key, int *value); + +bool +msc_config_set_int(const char *key, int value); + +bool +msc_config_get_str(const char *key, char *value); + +bool +msc_config_set_str(const char *key, const char *value); + +#ifdef FMS_PERF +void +msc_check_start_time(struct timeval *start_time); + +void +msc_check_end_time(struct timeval *end_time); + +void +msc_check_time_diff(struct timeval *start_time, struct timeval *end_time); +#endif/*FMS_PERF */ + +/** + * @} + */ +#endif/*_MEDIA_SCANNER_UTILS_H__*/ + diff --git a/common/scanner/media-scanner-db-svc.c b/common/scanner/media-scanner-db-svc.c new file mode 100755 index 0000000..df0543e --- /dev/null +++ b/common/scanner/media-scanner-db-svc.c @@ -0,0 +1,610 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-db-svc.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ + +#include +#include + +#include "media-util.h" + +#include "media-scanner-dbg.h" +#include "media-scanner-utils.h" +#include "media-scanner-drm.h" +#include "media-scanner-db-svc.h" + +#define CONFIG_PATH "/opt/usr/data/file-manager-service/plugin-config" +#define EXT ".so" +#define EXT_LEN 3 +#define MSC_REGISTER_COUNT 100 /*For bundle commit*/ +#define MSC_VALID_COUNT 100 /*For bundle commit*/ + +GMutex * db_mutex; +GArray *so_array; +void ***func_array; +int lib_num; +void **scan_func_handle = NULL; /*dlopen handel*/ + +enum func_list { + eCHECK, + eCONNECT, + eDISCONNECT, + eEXIST, + eINSERT_BEGIN, + eINSERT_END, + eINSERT_BATCH, + eSET_ALL_VALIDITY, + eSET_VALIDITY_BEGIN, + eSET_VALIDITY_END, + eSET_VALIDITY, + eDELETE_ALL, + eDELETE_INVALID_ITEMS, + eUPDATE_BEGIN, + eUPDATE_END, + eSET_FOLDER_VALIDITY, + eDELETE_FOLDER, + eFUNC_MAX +}; + + +static int +_msc_get_mime(const char *path, char *mimetype) +{ + int ret = 0; + + if (path == NULL) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + /*get content type and mime type from file. */ + /*in case of drm file. */ + if (msc_is_drm_file(path)) { + ret = msc_get_mime_in_drm_info(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("Fail to get mime"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } else { + /*in case of normal files */ + if (aul_get_mime_from_file(path, mimetype, 255) < 0) { + MSC_DBG_ERR("aul_get_mime_from_file fail"); + return MS_MEDIA_ERR_MIME_GET_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +static int +_msc_check_category(const char *path, const char *mimetype, int index) +{ + int ret; + char *err_msg = NULL; + + ret = ((CHECK_ITEM)func_array[index][eCHECK])(path, mimetype, &err_msg); + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, index), err_msg, path); + MS_SAFE_FREE(err_msg); + } + + return ret; +} + +static int +_msc_token_data(char *buf, char **name) +{ + int len; + char* pos = NULL; + + pos = strstr(buf, EXT); + if (pos == NULL) { + MSC_DBG_ERR("This is not shared object library."); + name = NULL; + return -1; + } else { + len = pos - buf + EXT_LEN; + *name = strndup(buf, len); + MSC_DBG_INFO("%s", *name); + } + + return 0; +} + +static bool +_msc_load_config() +{ + int ret; + FILE *fp; + char *so_name = NULL; + char buf[256] = {0}; + + fp = fopen(CONFIG_PATH, "rt"); + if (fp == NULL) { + MSC_DBG_ERR("fp is NULL"); + return MS_MEDIA_ERR_FILE_OPEN_FAIL; + } + while(1) { + if (fgets(buf, 256, fp) == NULL) + break; + + ret = _msc_token_data(buf, &so_name); + if (ret == 0) { + /*add to array*/ + g_array_append_val(so_array, so_name); + so_name = NULL; + } + } + + fclose(fp); + + return MS_MEDIA_ERR_NONE; +} + +int +msc_load_functions(void) +{ + int lib_index = 0, func_index; + char func_list[eFUNC_MAX][40] = { + "check_item", + "connect", + "disconnect", + "check_item_exist", + "insert_item_begin", + "insert_item_end", + "insert_item", + "set_all_storage_items_validity", + "set_item_validity_begin", + "set_item_validity_end", + "set_item_validity", + "delete_all_items_in_storage", + "delete_all_invalid_items_in_storage", + "update_begin", + "update_end", + "set_folder_item_validity", + "delete_all_invalid_items_in_folder", + }; + /*init array for adding name of so*/ + so_array = g_array_new(FALSE, FALSE, sizeof(char*)); + + /*load information of so*/ + _msc_load_config(); + + if(so_array->len == 0) { + MSC_DBG_INFO("There is no information for functions"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + + /*the number of functions*/ + lib_num = so_array->len; + + MSC_DBG_INFO("The number of information of so : %d", lib_num); + MS_MALLOC(scan_func_handle, sizeof(void*) * lib_num); + if (scan_func_handle == NULL) { + MSC_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + while(lib_index < lib_num) { + /*get handle*/ + MSC_DBG_INFO("[name of so : %s]", g_array_index(so_array, char*, lib_index)); + scan_func_handle[lib_index] = dlopen(g_array_index(so_array, char*, lib_index), RTLD_LAZY); + if (!scan_func_handle[lib_index]) { + MSC_DBG_ERR("%s", dlerror()); + MS_SAFE_FREE(scan_func_handle); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + lib_index++; + } + + dlerror(); /* Clear any existing error */ + + /*allocate for array of functions*/ + MS_MALLOC(func_array, sizeof(void*) * lib_num); + if (func_array == NULL) { + MSC_DBG_ERR("malloc failed"); + MS_SAFE_FREE(scan_func_handle); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + for(lib_index = 0 ; lib_index < lib_num; lib_index ++) { + MS_MALLOC(func_array[lib_index], sizeof(void*) * eFUNC_MAX); + if (func_array[lib_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(scan_func_handle); + + MSC_DBG_ERR("malloc failed"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + } + + /*add functions to array */ + for (lib_index = 0; lib_index < lib_num; lib_index++) { + for (func_index = 0; func_index < eFUNC_MAX ; func_index++) { + func_array[lib_index][func_index] = dlsym(scan_func_handle[lib_index], func_list[func_index]); + if (func_array[lib_index][func_index] == NULL) { + int index; + + for (index = 0; index < lib_index; index ++) { + MS_SAFE_FREE(func_array[index]); + } + MS_SAFE_FREE(func_array); + MS_SAFE_FREE(scan_func_handle); + + MSC_DBG_ERR("dlsym failed"); + return MS_MEDIA_ERR_DYNAMIC_LINK; + } + } + } + + return MS_MEDIA_ERR_NONE; +} + +void +msc_unload_functions(void) +{ + int lib_index; + + for (lib_index = 0; lib_index < lib_num; lib_index ++) + dlclose(scan_func_handle[lib_index]); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (func_array[lib_index]) { + MS_SAFE_FREE(func_array[lib_index]); + } + } + + MS_SAFE_FREE (func_array); + MS_SAFE_FREE (scan_func_handle); + if (so_array) g_array_free(so_array, TRUE); +} + +int +msc_connect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + /*Lock mutex for openning db*/ + g_mutex_lock(db_mutex); + + MS_MALLOC(*handle, sizeof (void*) * lib_num); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((CONNECT)func_array[lib_index][eCONNECT])(&((*handle)[lib_index]), &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + } + + MSC_DBG_INFO("connect Media DB"); + + g_mutex_unlock(db_mutex); + + return MS_MEDIA_ERR_NONE; +} + +int +msc_disconnect_db(void ***handle) +{ + int lib_index; + int ret; + char * err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DISCONNECT)func_array[lib_index][eDISCONNECT])((*handle)[lib_index], &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return MS_MEDIA_ERR_DB_DISCONNECT_FAIL; + } + } + + MS_SAFE_FREE(*handle); + + MSC_DBG_INFO("Disconnect Media DB"); + + return MS_MEDIA_ERR_NONE; +} + +int +msc_validate_item(void **handle, char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + char mimetype[255] = {0}; + ms_storage_type_t storage_type; + + ret = _msc_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("err : _msc_get_mime [%d]", ret); + return ret; + } + storage_type = msc_get_storage_type_by_full(path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_msc_check_category(path, mimetype, lib_index)) { + /*check exist in Media DB, If file is not exist, insert data in DB. */ + ret = ((CHECK_ITEM_EXIST)func_array[lib_index][eEXIST])(handle[lib_index], path, storage_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("not exist in %d. insert data", lib_index); + MS_SAFE_FREE(err_msg); + + ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path); + MSC_DBG_ERR("[%s] %s", mimetype, path); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } else { + /*if meta data of file exist, change valid field to "1" */ + ret = ((SET_ITEM_VALIDITY)func_array[lib_index][eSET_VALIDITY])(handle[lib_index], path, true, mimetype, true, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s] %s", g_array_index(so_array, char*, lib_index), err_msg, path); + MSC_DBG_ERR("[%s] %s", mimetype, path); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + } else { + MSC_DBG_ERR("check category failed"); + MSC_DBG_ERR("[%s] %s", mimetype, path); + } + } + + if (msc_is_drm_file(path)) { + ret = msc_drm_register(path); + } + + return res; +} + +int +msc_invalidate_all_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ALL_STORAGE_ITEMS_VALIDITY)func_array[lib_index][eSET_ALL_VALIDITY])(handle[lib_index], store_type, false, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + + return res; +} + +int +msc_insert_item_batch(void **handle, const char *path) +{ + int lib_index; + int res = MS_MEDIA_ERR_NONE; + int ret; + char mimetype[255] = {0}; + char *err_msg = NULL; + ms_storage_type_t storage_type; + + ret = _msc_get_mime(path, mimetype); + if (ret != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("err : _msc_get_mime [%d]", ret); + return ret; + } + storage_type = msc_get_storage_type_by_full(path); + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + if (!_msc_check_category(path, mimetype, lib_index)) { + ret = ((INSERT_ITEM)func_array[lib_index][eINSERT_BATCH])(handle[lib_index], path, storage_type, mimetype, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MSC_DBG_ERR("[%s] %s", mimetype, path); + MS_SAFE_FREE(err_msg); + res = MS_MEDIA_ERR_DB_INSERT_FAIL; + } + } else { + MSC_DBG_ERR("check category failed"); + MSC_DBG_ERR("[%s] %s", mimetype, path); + } + } + + if (msc_is_drm_file(path)) { + ret = msc_drm_register(path); + res = ret; + } + + return res; +} + +bool +msc_delete_all_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + /* To reset media db when differnet mmc is inserted. */ + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DELETE_ALL_ITEMS_IN_STORAGE)func_array[lib_index][eDELETE_ALL])(handle[lib_index], store_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return false; + } + } + + return true; +} + +bool +msc_delete_invalid_items(void **handle, ms_storage_type_t store_type) +{ + int lib_index; + int ret; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DELETE_ALL_INVALID_ITMES_IN_STORAGE)func_array[lib_index][eDELETE_INVALID_ITEMS])(handle[lib_index], store_type, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return false; + } + } + + return true; +} + +int +msc_set_folder_validity(void **handle, const char *path, int validity, int recursive) +{ + int lib_index; + int ret; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_FOLDER_ITEM_VALIDITY)func_array[lib_index][eSET_FOLDER_VALIDITY])(handle[lib_index], path, validity, recursive,&err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +int +msc_delete_invalid_items_in_folder(void **handle, const char*path) +{ + int lib_index; + int ret; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((DELETE_ALL_INVALID_ITEMS_IN_FOLDER)func_array[lib_index][eDELETE_FOLDER])(handle[lib_index], path, &err_msg); /*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + return MS_MEDIA_ERR_DB_UPDATE_FAIL; + } + } + + return MS_MEDIA_ERR_NONE; +} + +/**************************************************************************************************** +FOR BULK COMMIT +*****************************************************************************************************/ + +void +msc_register_start(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((INSERT_ITEM_BEGIN)func_array[lib_index][eINSERT_BEGIN])(handle[lib_index], MSC_REGISTER_COUNT, &err_msg);/*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +msc_register_end(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((INSERT_ITEM_END)func_array[lib_index][eINSERT_END])(handle[lib_index], &err_msg);/*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((UPDATE_END)func_array[lib_index][eUPDATE_END])();/*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +msc_validate_start(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ITEM_VALIDITY_BEGIN)func_array[lib_index][eSET_VALIDITY_BEGIN])(handle[lib_index], MSC_VALID_COUNT, &err_msg);/*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + +void +msc_validate_end(void **handle) +{ + int lib_index; + int ret = 0; + char *err_msg = NULL; + + for (lib_index = 0; lib_index < lib_num; lib_index++) { + ret = ((SET_ITEM_VALIDITY_END)func_array[lib_index][eSET_VALIDITY_END])(handle[lib_index], &err_msg);/*dlopen*/ + if (ret != 0) { + MSC_DBG_ERR("error : %s [%s]", g_array_index(so_array, char*, lib_index), err_msg); + MS_SAFE_FREE(err_msg); + } + } +} + diff --git a/common/scanner/media-scanner-drm.c b/common/scanner/media-scanner-drm.c new file mode 100755 index 0000000..8860f90 --- /dev/null +++ b/common/scanner/media-scanner-drm.c @@ -0,0 +1,123 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-drm.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ +#include +#include + +#include "media-util.h" + +#include "media-scanner-dbg.h" +#include "media-server-types.h" +#include "media-scanner-drm.h" + +bool +msc_is_drm_file(const char *path) +{ + int ret; + drm_bool_type_e is_drm_file = DRM_UNKNOWN; + + ret = drm_is_drm_file(path,&is_drm_file); + if(DRM_RETURN_SUCCESS == ret && DRM_TRUE == is_drm_file) + return true; + + return false; +} + +int +msc_get_mime_in_drm_info(const char *path, char *mime) +{ + int ret; + drm_content_info_s contentInfo; + + if (path == NULL || mime == NULL) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + memset(&contentInfo,0x0,sizeof(drm_content_info_s)); + ret = drm_get_content_info(path, &contentInfo); + if (ret != DRM_RETURN_SUCCESS) { + MSC_DBG_ERR("drm_svc_get_content_info() failed"); + MSC_DBG_ERR("%s [%d]", path, ret); + return MS_MEDIA_ERR_DRM_GET_INFO_FAIL; + } + + strncpy(mime, contentInfo.mime_type, 100); + + return MS_MEDIA_ERR_NONE; +} + +int +msc_drm_register(const char* path) +{ + int res = MS_MEDIA_ERR_NONE; + int ret; + + ret = drm_process_request(DRM_REQUEST_TYPE_REGISTER_FILE, (void *)path, NULL); + if (ret != DRM_RETURN_SUCCESS) { + MSC_DBG_ERR("drm_svc_register_file error : %d %s", ret, path); + res = MS_MEDIA_ERR_DRM_REGISTER_FAIL; + } + + return res; +} + +void +msc_drm_unregister(const char* path) +{ + int ret; + + ret = drm_process_request(DRM_REQUEST_TYPE_UNREGISTER_FILE, (void *)path, NULL); + if (ret != DRM_RETURN_SUCCESS) + MSC_DBG_ERR("drm_process_request error : %d", ret); +} + +void +msc_drm_unregister_all(void) +{ + if (drm_process_request(DRM_REQUEST_TYPE_UNREGISTER_ALL_FILES , NULL, NULL) == DRM_RETURN_SUCCESS) + MSC_DBG_INFO("drm_svc_unregister_all_contents OK"); +} + +bool +msc_drm_insert_ext_memory(void) +{ + if (drm_process_request(DRM_REQUEST_TYPE_INSERT_EXT_MEMORY, NULL, NULL) != DRM_RETURN_SUCCESS) + return false; + + return true; +} + +bool +msc_drm_extract_ext_memory(void) +{ + if (drm_process_request(DRM_REQUEST_TYPE_EXTRACT_EXT_MEMORY , NULL, NULL) != DRM_RETURN_SUCCESS) + return false; + + return true; +} + diff --git a/common/scanner/media-scanner-scan.c b/common/scanner/media-scanner-scan.c new file mode 100755 index 0000000..eee8567 --- /dev/null +++ b/common/scanner/media-scanner-scan.c @@ -0,0 +1,1091 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-scan.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#include +#include +#include +#include +#include +#include +#include + +#include "media-util.h" +#include "media-server-ipc.h" +#include "media-scanner-dbg.h" +#include "media-scanner-utils.h" +#include "media-scanner-db-svc.h" +#include "media-scanner-socket.h" +#include "media-scanner-scan.h" + +typedef struct msc_scan_data { + char *name; + struct msc_scan_data *next; +} msc_scan_data; + +int mmc_state; +bool power_off; +GAsyncQueue * storage_queue; +GAsyncQueue *scan_queue; +GAsyncQueue *reg_queue; + +#ifdef FMS_PERF +extern struct timeval g_mmc_start_time; +extern struct timeval g_mmc_end_time; +#endif + +static int +_msc_set_power_mode(ms_db_status_type_t status) +{ + int res = MS_MEDIA_ERR_NONE; + int err; + + switch (status) { + case MS_DB_UPDATING: + err = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0); + if (err != 0) + res = MS_MEDIA_ERR_INTERNAL; + break; + case MS_DB_UPDATED: + err = pm_unlock_state(LCD_OFF, STAY_CUR_STATE); + if (err != 0) + res = MS_MEDIA_ERR_INTERNAL; + break; + default: + MSC_DBG_ERR("Unacceptable type : %d", status); + break; + } + + return res; +} + +static int +_msc_set_db_status(ms_scanning_location_t location, ms_db_status_type_t status) +{ + int res = MS_MEDIA_ERR_NONE; + int err = 0; + + if (status == MS_DB_UPDATING) { + if (location != MS_SCANNING_DIRECTORY) { + if (!msc_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATING)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + /* this is temporay code for tizen 2.0*/ + if(location == MS_SCANNING_EXTERNAL) { + if (!msc_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADING)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + + /* Update private vconf key for media server*/ + if (location == MS_SCANNING_INTERNAL) { + if (!msc_config_set_int(MS_SCAN_STATUS_INTERNAL, P_VCONF_SCAN_DOING)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } else if (location == MS_SCANNING_DIRECTORY) { + if (!msc_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DOING)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + } else if (status == MS_DB_UPDATED) { + if (location != MS_SCANNING_DIRECTORY) { + if(!msc_config_set_int(VCONFKEY_FILEMANAGER_DB_STATUS, VCONFKEY_FILEMANAGER_DB_UPDATED)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + + /* this is temporay code for tizen 2.0*/ + if(location == MS_SCANNING_EXTERNAL) { + if (!msc_config_set_int(VCONFKEY_FILEMANAGER_MMC_STATUS, VCONFKEY_FILEMANAGER_MMC_LOADED)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + + /* Update private vconf key for media server*/ + if (location == MS_SCANNING_INTERNAL) { + if (!msc_config_set_int(MS_SCAN_STATUS_INTERNAL, P_VCONF_SCAN_DONE)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } else if (location == MS_SCANNING_DIRECTORY) { + if (!msc_config_set_int(MS_SCAN_STATUS_DIRECTORY, P_VCONF_SCAN_DONE)) { + res = MS_MEDIA_ERR_VCONF_SET_FAIL; + MSC_DBG_ERR("msc_config_set_int failed"); + } + } + } + + err = _msc_set_power_mode(status); + if (err != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("_msc_set_power_mode fail"); + res = err; + } + + return res; +} + +static int _msc_scan_get_next_path_from_current_node(int find_folder, + ms_dir_scan_info **current_root, + ms_dir_scan_info **real_root, char **path, int *depth) +{ + int err = MS_MEDIA_ERR_NONE; + char get_path[FAT_FILEPATH_LEN_MAX] = { 0 }; + + if (find_folder == 0) { + if ((*current_root)->Rbrother != NULL) { + *current_root = (*current_root)->Rbrother; + } else { + while (1) { + if ((*current_root)->parent == *real_root + || (*current_root)->parent == NULL) { + *current_root = NULL; + *depth = 0; + return MS_MEDIA_ERR_NONE; + } else if ((*current_root)->parent->Rbrother == NULL) { + *current_root = (*current_root)->parent; + (*depth) --; + } else { + *current_root = (*current_root)->parent->Rbrother; + (*depth) --; + break; + } + } + } + (*depth) --; + } + + err = msc_get_full_path_from_node(*current_root, get_path, *depth); + if (err != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_INVALID_PATH; + + *path = strdup(get_path); + + return err; +} + +static int _msc_scan_add_node(msc_scan_data **first_node, ms_dir_scan_info *const node, int depth) +{ + int err; + char full_path[MS_FILE_PATH_LEN_MAX] = { 0 }; + msc_scan_data *current_dir = NULL; + msc_scan_data *prv_node = NULL; + msc_scan_data *last_node = NULL; + + err = msc_get_full_path_from_node(node, full_path, depth); + if (err != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_INVALID_PATH; + + last_node = *first_node; + while (last_node != NULL) { + last_node = last_node->next; + } + + /*find same folder */ + if (*first_node != NULL) { + last_node = *first_node; + while (last_node != NULL) { + if (strcmp(full_path, last_node->name) == 0) { + return MS_MEDIA_ERR_NONE; + } + prv_node = last_node; + last_node = last_node->next; + } + } + + MS_MALLOC(current_dir, sizeof(msc_scan_data)); + current_dir->name = strdup(full_path); + current_dir->next = NULL; + + if (*first_node == NULL) { + *first_node = current_dir; + } else { + /*if next node of current node is NULL, it is the lastest node. */ + prv_node->next = current_dir; + } + +// MSC_DBG_INFO("scan path : %s %x %p", full_path, first_node, first_node); + + return MS_MEDIA_ERR_NONE; +} + +static bool _msc_check_scan_ignore(char * path) +{ + DIR *dp = NULL; + struct dirent entry; + struct dirent *result; + char *ignore_path = ".scan_ignore"; + + dp = opendir(path); + if (dp == NULL) { + MSC_DBG_ERR("%s folder opendir fails", path); + return true; + } + + while (!readdir_r(dp, &entry, &result)) { + if (result == NULL) + break; + + if (strcmp(entry.d_name, ignore_path) == 0) { + closedir(dp); + return true; + } + } + + closedir(dp); + return false; +} + +static int _ms_check_stop_status(ms_storage_type_t storage_type) +{ + int ret = MS_MEDIA_ERR_NONE; + + /*check poweroff status*/ + if (power_off) { + MSC_DBG_INFO("Power off"); + ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP; + } + + /*check SD card in out */ + if ((mmc_state != VCONFKEY_SYSMAN_MMC_MOUNTED) && (storage_type == MS_STORAGE_EXTERNAL)) { + MSC_DBG_INFO("Directory scanning is stopped"); + ret = MS_MEDIA_ERR_SCANNER_FORCE_STOP; + } + + return ret; +} + +static void _msc_dir_check(msc_scan_data **first_node, const ms_comm_msg_s *scan_data) +{ + int err = 0; + int depth = 0; + int find_folder = 0; + char get_path[MS_FILE_PATH_LEN_MAX] = { 0 }; + char *path = NULL; + DIR *dp = NULL; + struct dirent entry; + struct dirent *result; + ms_storage_type_t storage_type; + + ms_dir_scan_info *root = NULL; + ms_dir_scan_info *tmp_root = NULL; + ms_dir_scan_info *cur_node = NULL; /*current node*/ + ms_dir_scan_info *prv_node = NULL; /*previous node*/ + ms_dir_scan_info *next_node = NULL; + + MS_MALLOC(root, sizeof(ms_dir_scan_info)); + if (root == NULL) { + MSC_DBG_ERR("malloc fail"); + return; + } + + storage_type = msc_get_storage_type_by_full(scan_data->msg); + + root->name = strndup(scan_data->msg, scan_data->msg_size); + if (root->name == NULL) { + MSC_DBG_ERR("strdup fail"); + MS_SAFE_FREE(root); + return; + } + + root->parent = NULL; + root->Rbrother = NULL; + root->next = NULL; + tmp_root = root; + prv_node = root; + + MS_MALLOC(path, sizeof(char) * MS_FILE_PATH_LEN_MAX); + + err = msc_get_full_path_from_node(tmp_root, path, depth); + if (err != MS_MEDIA_ERR_NONE) { + MS_SAFE_FREE(path); + MS_SAFE_FREE(root); + return; + } + + _msc_scan_add_node(first_node, root, depth); + + while (1) { + /*check poweroff status*/ + err = _ms_check_stop_status(storage_type); + if (err != MS_MEDIA_ERR_NONE) { + goto FREE_RESOURCES; + } + + depth ++; + dp = opendir(path); + if (dp == NULL) { + MSC_DBG_ERR("%s folder opendir fails", path); + goto NEXT_DIR; + } + + while (!readdir_r(dp, &entry, &result)) { + /*check poweroff status*/ + err = _ms_check_stop_status(storage_type); + if (err != MS_MEDIA_ERR_NONE) { + goto FREE_RESOURCES; + } + + if (result == NULL) + break; + + if (entry.d_name[0] == '.') + continue; + + if (entry.d_type & DT_DIR) { + err = msc_strappend(get_path, sizeof(get_path), "%s/%s",path, entry.d_name); + if (err != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("msc_strappend error"); + continue; + } + + if (_msc_check_scan_ignore(get_path)) { + MSC_DBG_ERR("%s is ignore", get_path); + continue; + } + + MS_MALLOC(cur_node, sizeof(ms_dir_scan_info)); + if (cur_node == NULL) { + MSC_DBG_ERR("malloc fail"); + + goto FREE_RESOURCES; + } + + cur_node->name = strdup(entry.d_name); + cur_node->Rbrother = NULL; + cur_node->next = NULL; + + /*1. 1st folder */ + if (find_folder == 0) { + cur_node->parent = tmp_root; + tmp_root = cur_node; + } else { + cur_node->parent = tmp_root->parent; + prv_node->Rbrother = cur_node; + } + prv_node->next = cur_node; + + /*add watch */ + _msc_scan_add_node(first_node, cur_node, depth); + + /*change previous */ + prv_node = cur_node; + find_folder++; + } + } +NEXT_DIR: + MS_SAFE_FREE(path); + if (dp) closedir(dp); + dp = NULL; + + err = _msc_scan_get_next_path_from_current_node(find_folder, &tmp_root, &root, &path, &depth); + if (err != MS_MEDIA_ERR_NONE) + break; + + if (tmp_root == NULL) + break; + + find_folder = 0; + } + +FREE_RESOURCES: + /*free allocated memory */ + MS_SAFE_FREE(path); + if (dp) closedir(dp); + dp = NULL; + + cur_node = root; + while (cur_node != NULL) { + next_node = cur_node->next; + MS_SAFE_FREE(cur_node->name); + MS_SAFE_FREE(cur_node); + cur_node = next_node; + } +} + +static int _msc_dir_scan(void **handle, msc_scan_data **first_node, const ms_comm_msg_s * scan_data) +{ + DIR *dp = NULL; + int scan_type; + int ret = MS_MEDIA_ERR_NONE; + int err = 0; + char path[MS_FILE_PATH_LEN_MAX] = { 0 }; + msc_scan_data *node; + ms_storage_type_t storage_type; + + err = msc_strcopy(path, sizeof(path), "%s", scan_data->msg); + if (err != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("error : %d", err ); + return err; + } + + storage_type = msc_get_storage_type_by_full(scan_data->msg); + scan_type = scan_data->msg_type; + + /*if scan type is not MS_SCAN_NONE, check data in db. */ + if (scan_type != MS_MSG_STORAGE_INVALID) { + struct dirent entry; + struct dirent *result = NULL; + + if (scan_data->msg_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) { + _msc_dir_check(first_node, scan_data); + } else { + msc_scan_data *scan_node; + + MS_MALLOC(scan_node, sizeof(msc_scan_data)); + + scan_node->name = strdup(scan_data->msg); + scan_node->next = NULL; + + *first_node = scan_node; + } + + node = *first_node; + + /*start db update. If node is null, db update is done.*/ + while (node != NULL) { + /*check poweroff status*/ + ret = _ms_check_stop_status(storage_type); + if (ret != MS_MEDIA_ERR_NONE) { + goto STOP_SCAN; + } + + dp = opendir(node->name); + if (dp != NULL) { + while (!readdir_r(dp, &entry, &result)) { + /*check poweroff status*/ + ret = _ms_check_stop_status(storage_type); + if (ret != MS_MEDIA_ERR_NONE) { + goto STOP_SCAN; + } + + if (result == NULL) + break; + + if (entry.d_name[0] == '.') + continue; + + if (entry.d_type & DT_REG) { + err = msc_strappend(path, sizeof(path), "%s/%s", node->name, entry.d_name); + if (err < 0) { + MSC_DBG_ERR("error : %d", err); + continue; + } + + if (scan_type == MS_MSG_STORAGE_ALL) + err = msc_insert_item_batch(handle, path); + else + err = msc_validate_item(handle,path); + if (err < 0) { + MSC_DBG_ERR("failed to update db : %d , %d\n", err, scan_type); + continue; + } + } + } + } else { + MSC_DBG_ERR("%s folder opendir fails", node->name); + } + if (dp) closedir(dp); + dp = NULL; + + node = node->next; + } /*db update while */ + } else if ( scan_type == MS_MSG_STORAGE_INVALID) { + /*In this case, update just validation record*/ + /*update just valid type*/ + err = msc_invalidate_all_items(handle, storage_type); + if (err != MS_MEDIA_ERR_NONE) + MSC_DBG_ERR("error : %d", err); + } +STOP_SCAN: + if (dp) closedir(dp); + + /*delete all node*/ + node = *first_node; + + while (node != NULL) { + MS_SAFE_FREE(node->name); + MS_SAFE_FREE(node); + } + + *first_node = NULL; + + sync(); + + MSC_DBG_INFO("ret : %d", ret); + + return ret; +} + + +static void _msc_insert_array(GArray *garray, ms_comm_msg_s *insert_data) +{ + ms_scan_data_t *data; + bool insert_ok = false; + int len = garray->len; + int i; + + MSC_DBG_INFO("the length of array : %d", len); + MSC_DBG_INFO("path : %s", insert_data->msg); + MSC_DBG_INFO("scan_type : %d", insert_data->msg_type); + + if (insert_data->pid == POWEROFF) { + g_array_prepend_val(garray, insert_data); + } else { + for (i=0; i < len; i++) { + data = g_array_index(garray, ms_scan_data_t*, i); +/* + if (data->pid != POWEROFF) { + if (data->storage_type == insert_data->storage_type) { + if(data->scan_type > insert_data->scan_type) { + g_array_remove_index (garray, i); + g_array_insert_val(garray, i, insert_data); + insert_ok = true; + } + } + } +*/ + } + + if (insert_ok == false) + g_array_append_val(garray, insert_data); + } +} + +void _msc_check_dir_path(char *dir_path) +{ + int len = strlen(dir_path); + + if (dir_path[len -1] == '/') + dir_path[len -1] = '\0'; +} + +gboolean msc_directory_scan_thread(void *data) +{ + ms_comm_msg_s *scan_data = NULL; + ms_comm_msg_s *insert_data = NULL; + GArray *garray = NULL; + int length; + int err; + int ret; + void **handle = NULL; + ms_storage_type_t storage_type; + int scan_type; + msc_scan_data *first_node = NULL; + + /*create array for processing overlay data*/ + garray = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *)); + if (garray == NULL) { + MSC_DBG_ERR("g_array_new error"); + return false; + } + + while (1) { + length = g_async_queue_length(scan_queue); + + /*updating requests remain*/ + if (garray->len != 0 && length == 0) { + scan_data = g_array_index(garray, ms_comm_msg_s*, 0); + g_array_remove_index (garray, 0); + if (scan_data->pid == POWEROFF) { + MSC_DBG_INFO("power off"); + goto _POWEROFF; + } + } else if (length != 0) { + insert_data = g_async_queue_pop(scan_queue); + _msc_insert_array(garray, insert_data); + continue; + } else if (garray->len == 0 && length == 0) { + /*Threre is no request, Wait until pushung new request*/ + insert_data = g_async_queue_pop(scan_queue); + _msc_insert_array(garray, insert_data); + continue; + } + + MSC_DBG_INFO("DIRECTORY SCAN START"); + + /*connect to media db, if conneting is failed, db updating is stopped*/ + err = msc_connect_db(&handle); + if (err != MS_MEDIA_ERR_NONE) + continue; + + storage_type = msc_get_storage_type_by_full(scan_data->msg); + scan_type = scan_data->msg_type; + + if (scan_type != MS_MSG_DIRECTORY_SCANNING + && scan_type != MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) { + MSC_DBG_ERR("Invalid request"); + ret = MS_MEDIA_ERR_INVALID_PARAMETER; + goto NEXT; + } + + /*start db updating */ +// _msc_set_db_status(MS_SCANNING_DIRECTORY, MS_DB_UPDATING); + + _msc_check_dir_path(scan_data->msg); + + /*change validity before scanning*/ + if (scan_type == MS_MSG_DIRECTORY_SCANNING) + err = msc_set_folder_validity(handle, scan_data->msg, MS_INVALID, MS_RECURSIVE); + else + err = msc_set_folder_validity(handle, scan_data->msg, MS_INVALID, MS_NON_RECURSIVE); + if (err != MS_MEDIA_ERR_NONE) + MSC_DBG_ERR("error : %d", err); + + /*call for bundle commit*/ + msc_register_start(handle); + msc_validate_start(handle); + + /*insert data into media db */ + ret = _msc_dir_scan(handle, &first_node, scan_data); + + /*call for bundle commit*/ + msc_register_end(handle); + msc_validate_end(handle); + + if (ret == MS_MEDIA_ERR_NONE) { + MSC_DBG_INFO("working normally"); + msc_delete_invalid_items_in_folder(handle, scan_data->msg); + } + + /*set vconf key mmc loading for indicator */ +// _msc_set_db_status(MS_SCANNING_DIRECTORY, MS_DB_UPDATED); + + if (power_off) { + MSC_DBG_INFO("power off"); + goto _POWEROFF; + } + + /*disconnect form media db*/ + if (handle) msc_disconnect_db(&handle); +NEXT: + /*Active flush */ + malloc_trim(0); + + msc_send_scan_result(ret, scan_data); + +// MS_SAFE_FREE(scan_data->msg); + MS_SAFE_FREE(scan_data); + + MSC_DBG_INFO("DIRECTORY SCAN END"); + } /*thread while*/ + +_POWEROFF: +// MS_SAFE_FREE(scan_data->msg); + MS_SAFE_FREE(scan_data); + if (garray) g_array_free (garray, TRUE); + if (handle) msc_disconnect_db(&handle); + + return false; +} + +/* this thread process only the request of media-server */ +gboolean msc_storage_scan_thread(void *data) +{ + ms_comm_msg_s *scan_data = NULL; + ms_comm_msg_s *insert_data = NULL; + GArray *garray = NULL; + bool res; + int ret; + int length; + int err; + void **handle = NULL; + ms_storage_type_t storage_type; + int scan_type; + msc_scan_data *first_node = NULL; + + /*create array for processing overlay data*/ + garray = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *)); + if (garray == NULL) { + MSC_DBG_ERR("g_array_new error"); + return false; + } + + while (1) { + length = g_async_queue_length(storage_queue); + + /*updating requests remain*/ + if (garray->len != 0 && length == 0) { + scan_data = g_array_index(garray, ms_comm_msg_s*, 0); + g_array_remove_index (garray, 0); + if (scan_data->pid == POWEROFF) { + MSC_DBG_INFO("power off"); + goto _POWEROFF; + } + } else if (length != 0) { + insert_data = g_async_queue_pop(storage_queue); + _msc_insert_array(garray, insert_data); + continue; + } else if (garray->len == 0 && length == 0) { + /*Threre is no request, Wait until pushing new request*/ + insert_data = g_async_queue_pop(storage_queue); + _msc_insert_array(garray, insert_data); + continue; + } + + MSC_DBG_INFO("STORAGE SCAN START"); + + scan_type = scan_data->msg_type; + if (scan_type != MS_MSG_STORAGE_ALL + && scan_type != MS_MSG_STORAGE_PARTIAL + && scan_type != MS_MSG_STORAGE_INVALID) { + MSC_DBG_ERR("Invalid request"); + ret = MS_MEDIA_ERR_INVALID_PARAMETER; + goto NEXT; + } + + storage_type = msc_get_storage_type_by_full(scan_data->msg); + MSC_DBG_INFO("%d", storage_type); + + /*connect to media db, if conneting is failed, db updating is stopped*/ + err = msc_connect_db(&handle); + if (err != MS_MEDIA_ERR_NONE) + continue; + + /*start db updating */ + if (storage_type == MS_STORAGE_INTERNAL) + _msc_set_db_status(MS_SCANNING_INTERNAL, MS_DB_UPDATING); + else if (storage_type == MS_STORAGE_EXTERNAL) + _msc_set_db_status(MS_SCANNING_EXTERNAL, MS_DB_UPDATING); + + /*Delete all data before full scanning*/ + if (scan_type == MS_MSG_STORAGE_ALL) { + res = msc_delete_all_items(handle, storage_type); + if (res != true) { + MSC_DBG_ERR("msc_delete_all_record fails"); + } + } else if (scan_type == MS_MSG_STORAGE_PARTIAL) { + err = msc_invalidate_all_items(handle, storage_type); + if (err != MS_MEDIA_ERR_NONE) + MSC_DBG_ERR("error : %d", err); + } + + if (storage_type == MS_STORAGE_EXTERNAL && scan_type == MS_MSG_STORAGE_ALL) { + msc_update_mmc_info(); + } + +#ifdef FMS_PERF + if (storage_type == MS_STORAGE_EXTERNAL) { + msc_check_start_time(&g_mmc_start_time); + } +#endif + /*call for bundle commit*/ + msc_register_start(handle); + if (scan_type == MS_MSG_STORAGE_PARTIAL) { + /*enable bundle commit*/ + msc_validate_start(handle); + } + + /*add inotify watch and insert data into media db */ + ret = _msc_dir_scan(handle, &first_node, scan_data); + + /*call for bundle commit*/ + msc_register_end(handle); + if (scan_type == MS_MSG_STORAGE_PARTIAL) { + /*disable bundle commit*/ + msc_validate_end(handle); + if (ret == MS_MEDIA_ERR_NONE) { + MSC_DBG_INFO("working normally"); + msc_delete_invalid_items(handle, storage_type); + } + } + +#ifdef FMS_PERF + if (storage_type == MS_STORAGE_EXTERNAL) { + msc_check_end_time(&g_mmc_end_time); + msc_check_time_diff(&g_mmc_start_time, &g_mmc_end_time); + } +#endif + + /*set vconf key mmc loading for indicator */ + if (storage_type == MS_STORAGE_INTERNAL) + _msc_set_db_status(MS_SCANNING_INTERNAL, MS_DB_UPDATED); + else if (storage_type == MS_STORAGE_EXTERNAL) + _msc_set_db_status(MS_SCANNING_EXTERNAL, MS_DB_UPDATED); + + if (power_off) { + MSC_DBG_INFO("power off"); + goto _POWEROFF; + } + + /*disconnect form media db*/ + if (handle) msc_disconnect_db(&handle); + +NEXT: + /*Active flush */ + malloc_trim(0); + + msc_send_scan_result(ret, scan_data); + +// MS_SAFE_FREE(scan_data->msg); + MS_SAFE_FREE(scan_data); + + MSC_DBG_INFO("STORAGE SCAN END"); + } /*thread while*/ + +_POWEROFF: +// MS_SAFE_FREE(scan_data->msg); + MS_SAFE_FREE(scan_data); + if (garray) g_array_free (garray, TRUE); + if (handle) msc_disconnect_db(&handle); + + return false; +} + +static void _msc_insert_register_request(GArray *register_array, ms_comm_msg_s *insert_data) +{ + MSC_DBG_INFO("path : %s", insert_data->msg); + + if (insert_data->pid == POWEROFF) { + g_array_prepend_val(register_array, insert_data); + } else { + g_array_append_val(register_array, insert_data); + } +} + +static bool _is_valid_path(const char *path) +{ + if (path == NULL) + return false; + + if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) { + return true; + } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) { + return true; + } else + return false; + + return true; +} + +static int _check_file_path(const char *file_path) +{ + int exist; + struct stat file_st; + + /* check location of file */ + /* file must exists under "/opt/usr/media" or "/opt/storage/sdcard" */ + if(!_is_valid_path(file_path)) { + MSC_DBG_ERR("Invalid path : %s", file_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + + /* check the file exits actually */ + exist = open(file_path, O_RDONLY); + if(exist < 0) { + MSC_DBG_ERR("Not exist path : %s", file_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + close(exist); + + /* check type of the path */ + /* It must be a regular file */ + memset(&file_st, 0, sizeof(struct stat)); + if(stat(file_path, &file_st) == 0) { + if(!S_ISREG(file_st.st_mode)) { + /* In this case, it is not a regula file */ + MSC_DBG_ERR("this path is not a file"); + return MS_MEDIA_ERR_INVALID_PATH; + } + } else { + MSC_DBG_ERR("stat failed [%s]", strerror(errno)); + return MS_MEDIA_ERR_INVALID_PATH; + } + + return MS_MEDIA_ERR_NONE; +} + +gboolean msc_register_thread(void *data) +{ + ms_comm_msg_s *register_data = NULL; + ms_comm_msg_s *insert_data = NULL; + GArray *register_array = NULL; + GArray *path_array = NULL; + FILE *fp = NULL; + char buf[MS_FILE_PATH_LEN_MAX]; + char *insert_path = NULL; + char *path = NULL; + char *file_path = NULL; + int path_size; + int length; + int err; + int i; + int ret; + void **handle = NULL; + + /*create array for processing overlay data*/ + register_array = g_array_new (FALSE, FALSE, sizeof (ms_comm_msg_s *)); + if (register_array == NULL) { + MSC_DBG_ERR("g_array_new error"); + return false; + } + + while (1) { + length = g_async_queue_length(reg_queue); + + /*updating requests remain*/ + if (register_array->len != 0 && length == 0) { + register_data = g_array_index(register_array, ms_comm_msg_s*, 0); + g_array_remove_index (register_array, 0); + if (register_data->pid == POWEROFF) { + MSC_DBG_INFO("power off"); + goto _POWEROFF; + } + } else if (length != 0) { + insert_data = g_async_queue_pop(reg_queue); + _msc_insert_register_request(register_array, insert_data); + continue; + } else if (register_array->len == 0 && length == 0) { + /*Threre is no request, Wait until pushung new request*/ + insert_data = g_async_queue_pop(reg_queue); + _msc_insert_register_request(register_array, insert_data); + continue; + } + + if((register_data->msg_size <= 0) ||(register_data->msg_size > MS_FILE_PATH_LEN_MAX)) { + MSC_DBG_ERR("message size[%d] is wrong", register_data->msg_size); + goto FREE_RESOURCE; + } else { + path_size = register_data->msg_size + 1; + } + + /* copy from received data */ + MS_MALLOC(file_path, path_size); + if (file_path == NULL) { + MSC_DBG_ERR("MS_MALLOC failed"); + goto FREE_RESOURCE; + } + + ret = msc_strcopy(file_path, path_size, "%s", register_data->msg); + if (ret != MS_MEDIA_ERR_NONE){ + MSC_DBG_ERR("msc_strcopy failed : %d", ret); + goto FREE_RESOURCE; + } + + /* load the file list from file */ + fp = fopen(register_data->msg, "rt"); + if (fp == NULL) { + MSC_DBG_ERR("fopen failed [%s]", strerror(errno)); + goto FREE_RESOURCE; + } + + memset(buf, 0x0, MS_FILE_PATH_LEN_MAX); + /* This is an array for storing the path of insert datas*/ + path_array = g_array_new (FALSE, FALSE, sizeof (char *)); + if (path_array == NULL) { + MSC_DBG_ERR("g_array_new failed"); + goto FREE_RESOURCE; + } + + /* read registering file path from stored file */ + while(fgets(buf, MS_FILE_PATH_LEN_MAX, fp) != NULL) { + length = strlen(buf); + buf[length - 1] = '\0'; + path = strdup(buf); + MSC_DBG_INFO("insert path : %s [%d]", path, strlen(path)); + /* insert getted path to the list */ + if (g_array_append_val(path_array, path) == NULL) { + MSC_DBG_ERR("g_array_append_val failed"); + goto FREE_RESOURCE; + } + } + + /* connect to media db, if conneting is failed, db updating is stopped */ + err = msc_connect_db(&handle); + if (err != MS_MEDIA_ERR_NONE) + goto FREE_RESOURCE; + + /*start db updating */ + /*call for bundle commit*/ + msc_register_start(handle); + + /* get the inserting file path from array and insert to db */ + for (i = 0; i < path_array->len; i++) { + + insert_path = g_array_index(path_array, char*, i); + /* check the file */ + /* it is really existing */ + /* it is in /opt/usr/media or /opt/storage/sdcard */ + /* it is really regular file */ + ret = _check_file_path(insert_path); + if (ret != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("Can't insert the meta of the path"); + continue; + } + + /* insert to db */ + err = msc_insert_item_batch(handle, insert_path); + + if (power_off) { + MSC_DBG_INFO("power off"); + /*call for bundle commit*/ + msc_register_end(handle); + goto _POWEROFF; + } + } + + /*call for bundle commit*/ + msc_register_end(handle); + + /*disconnect form media db*/ + if (handle) msc_disconnect_db(&handle); + + /*Active flush */ + malloc_trim(0); + + msc_send_register_result(MS_MEDIA_ERR_NONE, register_data); +FREE_RESOURCE: + if (path_array) { + g_array_free(path_array, TRUE); + path_array = NULL; + } + + MS_SAFE_FREE(file_path); + MS_SAFE_FREE(register_data); + + if(fp) fclose(fp); + fp = NULL; + } /*thread while*/ + +_POWEROFF: + MS_SAFE_FREE(file_path); + MS_SAFE_FREE(register_data); + if (register_array) g_array_free (register_array, TRUE); + if (path_array) g_array_free (path_array, TRUE); + if (handle) msc_disconnect_db(&handle); + + if(fp) fclose(fp); + + return false; +} diff --git a/common/scanner/media-scanner-socket.c b/common/scanner/media-scanner-socket.c new file mode 100755 index 0000000..0608cdb --- /dev/null +++ b/common/scanner/media-scanner-socket.c @@ -0,0 +1,185 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-thumb.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#include +#include +#include +#include +#include + +#include "media-util.h" + +#include "media-server-ipc.h" +#include "media-server-types.h" +#include "media-scanner-dbg.h" +#include "media-scanner-db-svc.h" +#include "media-scanner-utils.h" +#include "media-scanner-socket.h" + +extern GAsyncQueue *storage_queue; +extern GAsyncQueue *scan_queue; +extern GAsyncQueue *reg_queue; +GMutex *receive_mutex; + +gboolean msc_receive_request(GIOChannel *src, GIOCondition condition, gpointer data) +{ + ms_comm_msg_s *recv_msg = NULL; + int sockfd = MS_SOCK_NOT_ALLOCATE; + int req_num = MS_MSG_MAX; + int pid = -1; + int ret = MS_MEDIA_ERR_NONE; + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MSC_DBG_ERR("sock fd is invalid!"); + return TRUE; + } + + MS_MALLOC(recv_msg, sizeof(ms_comm_msg_s)); + if (recv_msg == NULL) { + MSC_DBG_ERR("MS_MALLOC failed"); + return TRUE; + } + + /* Socket is readable */ + ret = ms_ipc_receive_message(sockfd, recv_msg, sizeof(*recv_msg), NULL, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MS_SAFE_FREE(recv_msg); + return TRUE; + } + + MSC_DBG_INFO("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg); + + /* copy from recived data */ + req_num = recv_msg->msg_type; + pid = recv_msg->pid; + + /* request bulk insert*/ + if (req_num == MS_MSG_BULK_INSERT) { + MSC_DBG_INFO("BULK INSERT"); + g_async_queue_push(reg_queue, GINT_TO_POINTER(recv_msg)); + } else if (req_num == MS_MSG_DIRECTORY_SCANNING ||req_num == MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE) { + /* this request from another apps */ + /* set the scan data for scanning thread */ + g_async_queue_push(scan_queue, GINT_TO_POINTER(recv_msg)); + } else if (req_num == MS_MSG_STORAGE_ALL ||req_num == MS_MSG_STORAGE_PARTIAL || req_num == MS_MSG_STORAGE_INVALID) { + /* this request from media-server */ + g_async_queue_push(storage_queue, GINT_TO_POINTER(recv_msg)); + } else { + MSC_DBG_ERR("THIS REQUEST IS INVALID %d", req_num); + MS_SAFE_FREE(recv_msg); + return TRUE; + } + + /*Active flush */ + malloc_trim(0); + + return TRUE; +} + +int msc_send_scan_result(int result, ms_comm_msg_s *scan_data) +{ + int ret; + int res = MS_MEDIA_ERR_NONE; + int sockfd = -1; + ms_comm_msg_s send_msg; + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd); + if (ret != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_SOCKET_CONN; + + /* send ready message */ + memset(&send_msg, 0x0, sizeof(ms_comm_msg_s)); + send_msg.msg_type = MS_MSG_SCANNER_RESULT; + send_msg.pid = scan_data->pid; + send_msg.result = result; + send_msg.msg_size = strlen(scan_data->msg); + strncpy(send_msg.msg, scan_data->msg, send_msg.msg_size); + + ret = ms_ipc_send_msg_to_server(sockfd, MS_SCAN_COMM_PORT, &send_msg, NULL); + if (ret != MS_MEDIA_ERR_NONE) + res = ret; + + close(sockfd); + + return res; +} + +int msc_send_register_result(int result, ms_comm_msg_s *reg_data) +{ + int ret = MS_MEDIA_ERR_NONE; + int sockfd = -1; + ms_comm_msg_s send_msg; + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd); + if (ret != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_SOCKET_CONN; + + /* send ready message */ + memset(&send_msg, 0x0, sizeof(ms_comm_msg_s)); + send_msg.msg_type = MS_MSG_SCANNER_BULK_RESULT; + send_msg.pid = reg_data->pid; + send_msg.result = result; + send_msg.msg_size = reg_data->msg_size; + strncpy(send_msg.msg, reg_data->msg, send_msg.msg_size); + + ret = ms_ipc_send_msg_to_server(sockfd, MS_SCAN_COMM_PORT, &send_msg, NULL); + + close(sockfd); + + return ret; +} + +int msc_send_ready(void) +{ + int ret; + int res = MS_MEDIA_ERR_NONE; + int sockfd = -1; + ms_comm_msg_s send_msg; + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd); + if (ret != MS_MEDIA_ERR_NONE) + return MS_MEDIA_ERR_SOCKET_CONN; + + /* send ready message */ + memset(&send_msg, 0, sizeof(send_msg)); + send_msg.msg_type = MS_MSG_SCANNER_READY; + + ret = ms_ipc_send_msg_to_server(sockfd, MS_SCAN_COMM_PORT, &send_msg, NULL); + if (ret != MS_MEDIA_ERR_NONE) + res = ret; + + close(sockfd); + + return res; +} + diff --git a/common/scanner/media-scanner-utils.c b/common/scanner/media-scanner-utils.c new file mode 100755 index 0000000..ae20bcf --- /dev/null +++ b/common/scanner/media-scanner-utils.c @@ -0,0 +1,513 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-utils.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief This file implements main database operation. + */ + +#include +#include +#include + +#include "media-util.h" +#include "media-scanner-dbg.h" +#include "media-scanner-utils.h" +#include "media-scanner-drm.h" + +#ifdef FMS_PERF +#include +#define MILLION 1000000L +struct timeval g_mmc_start_time; +struct timeval g_mmc_end_time; +#endif + +#define MMC_INFO_SIZE 256 + +extern int mmc_state; +extern GAsyncQueue *storage_queue; +extern GAsyncQueue *scan_queue; + + + +#ifdef FMS_PERF +void +msc_check_start_time(struct timeval *start_time) +{ + gettimeofday(start_time, NULL); +} + +void +msc_check_end_time(struct timeval *end_time) +{ + gettimeofday(end_time, NULL); +} + +void +msc_check_time_diff(struct timeval *start_time, struct timeval *end_time) +{ + struct timeval time; + long difftime; + + time.tv_sec = end_time->tv_sec - start_time->tv_sec; + time.tv_usec = end_time->tv_usec - start_time->tv_usec; + difftime = MILLION * time.tv_sec + time.tv_usec; + MSC_DBG_INFO("The function_to_time took %ld microseconds or %f seconds.", + difftime, difftime / (double)MILLION); +} +#endif + +bool +msc_is_mmc_inserted(void) +{ + int data = -1; + msc_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &data); + if (data != VCONFKEY_SYSMAN_MMC_MOUNTED) { + return false; + } else { + return true; + } +} + +int +_msc_update_mmc_info(const char *cid) +{ + bool res; + + if (cid == NULL) { + MSC_DBG_ERR("Parameters are invalid"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res = msc_config_set_str(MS_MMC_INFO_KEY, cid); + if (!res) { + MSC_DBG_ERR("fail to get MS_MMC_INFO_KEY"); + return MS_MEDIA_ERR_VCONF_SET_FAIL; + } + + return MS_MEDIA_ERR_NONE; +} + +static int +_msc_get_contents(const char *filename, char *buf) +{ + FILE *fp; + + fp = fopen(filename, "rt"); + if (fp == NULL) { + MSC_DBG_ERR("fp is NULL. file name : %s", filename); + return MS_MEDIA_ERR_FILE_OPEN_FAIL; + } + + if (fgets(buf, 255, fp) == NULL) + MSC_DBG_ERR("fgets failed"); + + fclose(fp); + + return MS_MEDIA_ERR_NONE; +} + +/*need optimize*/ +int +_msc_get_mmc_info(char *cid) +{ + int i; + int j; + int len; + int err = -1; + bool getdata = false; + bool bHasColon = false; + char path[MS_FILE_PATH_LEN_MAX] = { 0 }; + char mmcpath[MS_FILE_PATH_LEN_MAX] = { 0 }; + + DIR *dp; + struct dirent ent; + struct dirent *res = NULL; + + /* mmcblk0 and mmcblk1 is reserved for movinand */ + for (j = 1; j < 3; j++) { + len = snprintf(mmcpath, MS_FILE_PATH_LEN_MAX, "/sys/class/mmc_host/mmc%d/", j); + if (len < 0) { + MSC_DBG_ERR("FAIL : snprintf"); + return MS_MEDIA_ERR_INTERNAL; + } + else { + mmcpath[len] = '\0'; + } + + dp = opendir(mmcpath); + if (dp == NULL) { + MSC_DBG_ERR("dp is NULL"); + return MS_MEDIA_ERR_DIR_OPEN_FAIL; + } + + while (!readdir_r(dp, &ent, &res)) { + /*end of read dir*/ + if (res == NULL) + break; + + bHasColon = false; + if (ent.d_name[0] == '.') + continue; + + if (ent.d_type == DT_DIR) { + /*ent->d_name is including ':' */ + for (i = 0; i < strlen(ent.d_name); i++) { + if (ent.d_name[i] == ':') { + bHasColon = true; + break; + } + } + + if (bHasColon) { + /*check serial */ + err = msc_strappend(path, sizeof(path), "%s%s/cid", mmcpath, ent.d_name); + if (err < 0) { + MSC_DBG_ERR("ms_strappend error : %d", err); + continue; + } + + if (_msc_get_contents(path, cid) != MS_MEDIA_ERR_NONE) + break; + else + getdata = true; + } + } + } + closedir(dp); + + if (getdata == true) { + break; + } + } + + return MS_MEDIA_ERR_NONE; +} + +int +msc_update_mmc_info(void) +{ + int err; + char cid[MMC_INFO_SIZE] = { 0 }; + + err = _msc_get_mmc_info(cid); + + err = _msc_update_mmc_info(cid); + + /*Active flush */ + if (!malloc_trim(0)) + MSC_DBG_ERR("malloc_trim is failed"); + + return err; +} + +bool +_msc_check_mmc_info(const char *cid) +{ + char pre_mmc_info[MMC_INFO_SIZE] = { 0 }; + bool res = false; + + if (cid == NULL) { + MSC_DBG_ERR("Parameters are invalid"); + return false; + } + + res = msc_config_get_str(MS_MMC_INFO_KEY, pre_mmc_info); + if (!res) { + MSC_DBG_ERR("fail to get MS_MMC_INFO_KEY"); + return false; + } + + MSC_DBG_INFO("Last MMC info = %s", pre_mmc_info); + MSC_DBG_INFO("Current MMC info = %s", cid); + + if (strcmp(pre_mmc_info, cid) == 0) { + return true; + } + + return false; +} + + +ms_dir_scan_type_t +msc_get_mmc_state(void) +{ + char cid[MMC_INFO_SIZE] = { 0 }; + ms_dir_scan_type_t ret = MS_SCAN_ALL; + + /*get new info */ + _msc_get_mmc_info(cid); + + /*check it's same mmc */ + if (_msc_check_mmc_info(cid)) { + ret = MS_SCAN_PART; + } + + return ret; +} + +void +msc_mmc_vconf_cb(void *data) +{ + int status = 0; + ms_comm_msg_s *scan_msg; + ms_dir_scan_type_t scan_type = MS_SCAN_PART; + + if (!msc_config_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status)) { + MSC_DBG_ERR("Get VCONFKEY_SYSMAN_MMC_STATUS failed."); + } + + MSC_DBG_INFO("VCONFKEY_SYSMAN_MMC_STATUS :%d", status); + + mmc_state = status; + + MS_MALLOC(scan_msg, sizeof(ms_comm_msg_s)); + + if (mmc_state == VCONFKEY_SYSMAN_MMC_REMOVED || + mmc_state == VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED) { + + if (!msc_drm_extract_ext_memory()) + MSC_DBG_ERR("ms_drm_extract_ext_memory failed"); + + scan_type = MS_SCAN_INVALID; + } else if (mmc_state == VCONFKEY_SYSMAN_MMC_MOUNTED) { + + if (!msc_drm_insert_ext_memory()) + MSC_DBG_ERR("ms_drm_insert_ext_memory failed"); + + scan_type = msc_get_mmc_state(); + } + + switch (scan_type) { + case MS_SCAN_ALL: + scan_msg->msg_type = MS_MSG_STORAGE_ALL; + break; + case MS_SCAN_PART: + scan_msg->msg_type = MS_MSG_STORAGE_PARTIAL; + break; + case MS_SCAN_INVALID: + scan_msg->msg_type = MS_MSG_STORAGE_INVALID; + break; + } + + scan_msg->pid = 0; + scan_msg->msg_size = strlen(MEDIA_ROOT_PATH_SDCARD); + msc_strcopy(scan_msg->msg, scan_msg->msg_size+1, "%s", MEDIA_ROOT_PATH_SDCARD); + + MSC_DBG_INFO("ms_get_mmc_state is %d", scan_msg->msg_type); + + g_async_queue_push(storage_queue, GINT_TO_POINTER(scan_msg)); + + return; +} + +/*CAUTION : Before using this function, Have to allocate static memory of ret_path*/ +/*And the array length does not over MS_FILE_PATH_LEN_MAX*/ +/*for example : char path[MS_FILE_PATH_LEN_MAX] = {0};*/ +int +msc_get_full_path_from_node(ms_dir_scan_info * const node, char *ret_path, int depth) +{ + int i = 0; + int path_length = 0; + int length = 0; + ms_dir_scan_info *cur_node; + char **path_array; + + if (depth < 0) { + MSC_DBG_ERR("depth < 0"); + return MS_MEDIA_ERR_INVALID_PATH; + } + + MS_MALLOC(path_array, sizeof(char*) * (depth + 1)); + + cur_node = node; + + while (1) { + path_array[i] = cur_node->name; + if (cur_node->parent == NULL) + break; + + cur_node = cur_node->parent; + i++; + } + + for(i = depth ; i >= 0 ; i --) { + length = strlen(path_array[i]); + + if (path_length + length > MS_FILE_PATH_LEN_MAX) { + MSC_DBG_ERR("This is invalid path, %s, %d", node->name, depth); + MS_SAFE_FREE(path_array); + return MS_MEDIA_ERR_INVALID_PATH; + } + + strncpy(ret_path+path_length, path_array[i], length); + path_length += length; + + ret_path[path_length] = '/'; + path_length ++; + } + + ret_path[-- path_length] = '\0'; + + MS_SAFE_FREE(path_array); + + return MS_MEDIA_ERR_NONE; +} + +ms_storage_type_t +msc_get_storage_type_by_full(const char *path) +{ + if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) { + return MS_STORAGE_INTERNAL; + } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) { + return MS_STORAGE_EXTERNAL; + } else + return MS_MEDIA_ERR_INVALID_PATH; +} + +int +msc_strappend(char *res, const int size, const char *pattern, + const char *str1, const char *str2) +{ + int len = 0; + int real_size = size - 1; + + if (!res ||!pattern || !str1 ||!str2 ) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + if (real_size < (strlen(str1) + strlen(str2))) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + len = snprintf(res, real_size, pattern, str1, str2); + if (len < 0) { + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res[len] = '\0'; + + return MS_MEDIA_ERR_NONE; +} + +int +msc_strcopy(char *res, const int size, const char *pattern, const char *str1) +{ + int len = 0; + int real_size = size; + + if (!res || !pattern || !str1) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + if (real_size < strlen(str1)) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + len = snprintf(res, real_size, pattern, str1); + if (len < 0) { + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + res[len] = '\0'; + + return MS_MEDIA_ERR_NONE; +} + +bool +msc_config_get_int(const char *key, int *value) +{ + int err; + + if (!key || !value) { + MSC_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + err = vconf_get_int(key, value); + if (err == 0) + return true; + else if (err == -1) + return false; + else + MSC_DBG_ERR("Unexpected error code: %d", err); + + return false; +} + +bool +msc_config_set_int(const char *key, int value) +{ + int err; + + if (!key) { + MSC_DBG_ERR("Arguments key is NULL"); + return false; + } + + err = vconf_set_int(key, value); + if (err == 0) + return true; + else if (err == -1) + return false; + else + MSC_DBG_ERR("Unexpected error code: %d", err); + + return false; +} + +bool +msc_config_get_str(const char *key, char *value) +{ + char *res; + if (!key || !value) { + MSC_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + res = vconf_get_str(key); + if (res) { + strncpy(value, res, strlen(res) + 1); + return true; + } + + return false; +} + +bool +msc_config_set_str(const char *key, const char *value) +{ + int err; + + if (!key || !value) { + MSC_DBG_ERR("Arguments key or value is NULL"); + return false; + } + + err = vconf_set_str(key, value); + if (err == 0) + return true; + else + MSC_DBG_ERR("fail to vconf_set_str %d", err); + + return false; +} + diff --git a/common/scanner/media-scanner.c b/common/scanner/media-scanner.c new file mode 100755 index 0000000..604a185 --- /dev/null +++ b/common/scanner/media-scanner.c @@ -0,0 +1,270 @@ +/* + * Media Server + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-server-main.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include + +#include "media-util.h" +#include "media-scanner-dbg.h" +#include "media-scanner-utils.h" +#include "media-scanner-db-svc.h" +#include "media-scanner-scan.h" +#include "media-scanner-socket.h" +#include "media-scanner-drm.h" + +#define APP_NAME "media-scanner" + +static int heynoti_id; +extern int mmc_state; + +extern GAsyncQueue *storage_queue; +extern GAsyncQueue *scan_queue; +extern GAsyncQueue *reg_queue; +extern GMutex *db_mutex; +extern GMutex *receive_mutex; +bool power_off; /*If this is TRUE, poweroff notification received*/ + +static GMainLoop *scanner_mainloop = NULL; + +bool check_process(void) +{ + DIR *pdir; + struct dirent pinfo; + struct dirent *result = NULL; + bool ret = false; + int find_pid = 0; + pid_t current_pid = 0; + + current_pid = getpid(); + + pdir = opendir("/proc"); + if (pdir == NULL) { + MSC_DBG_ERR("err: NO_DIR\n"); + return 0; + } + + while (!readdir_r(pdir, &pinfo, &result)) { + if (result == NULL) + break; + + if (pinfo.d_type != 4 || pinfo.d_name[0] == '.' + || pinfo.d_name[0] > 57) + continue; + + FILE *fp; + char buff[128]; + char path[128]; + + msc_strcopy(path, sizeof(path), "/proc/%s/status", pinfo.d_name); + fp = fopen(path, "rt"); + if (fp) { + if (fgets(buff, 128, fp) == NULL) + MSC_DBG_ERR("fgets failed"); + fclose(fp); + + if (strstr(buff, APP_NAME)) { + find_pid = atoi(pinfo.d_name); + if (find_pid == current_pid) + ret = true; + else { + ret = false; + break; + } + } + } else { + MSC_DBG_ERR("Can't read file [%s]", path); + } + } + + closedir(pdir); + + return ret; +} + +void init_process() +{ + +} + +static void _power_off_cb(void* data) +{ + ms_comm_msg_s *scan_data; + ms_comm_msg_s *reg_data; + + MSC_DBG_INFO("++++++++++++++++++++++++++++++++++++++"); + MSC_DBG_INFO("POWER OFF"); + MSC_DBG_INFO("++++++++++++++++++++++++++++++++++++++"); + + power_off = true; + + if (scan_queue) { + /*notify to scannig thread*/ + MS_MALLOC(scan_data, sizeof(ms_comm_msg_s)); + scan_data->pid = POWEROFF; + g_async_queue_push(scan_queue, GINT_TO_POINTER(scan_data)); + } + + if (reg_queue) { + /*notify to register thread*/ + MS_MALLOC(reg_data, sizeof(ms_comm_msg_s)); + reg_data->pid = POWEROFF; + g_async_queue_push(reg_queue, GINT_TO_POINTER(reg_data)); + } + + if (g_main_loop_is_running(scanner_mainloop)) g_main_loop_quit(scanner_mainloop); +} + +int main(int argc, char **argv) +{ + GThread *storage_scan_thread = NULL; + GThread *scan_thread = NULL; + GThread *register_thread = NULL; + GSource *source = NULL; + GIOChannel *channel = NULL; + GMainContext *context = NULL; + + int sockfd = -1; + int err; + +#if 0 /* temporary */ + check_result = check_process(); + if (check_result == false) + exit(0); +#endif + if (!g_thread_supported()) { + g_thread_init(NULL); + } + + /*Init main loop*/ + scanner_mainloop = g_main_loop_new(NULL, FALSE); + + /*heynoti for power off*/ + if ((heynoti_id = heynoti_init()) <0) { + MSC_DBG_INFO("heynoti_init failed"); + } else { + err = heynoti_subscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb, NULL); + if (err < 0) + MSC_DBG_INFO("heynoti_subscribe failed"); + + err = heynoti_attach_handler(heynoti_id); + if (err < 0) + MSC_DBG_INFO("heynoti_attach_handler failed"); + } + + /*load functions from plusin(s)*/ + err = msc_load_functions(); + if (err != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("function load failed"); + exit(0); + } + + /*Init for register file*/ + /*These are a communicator for thread*/ + if (!scan_queue) scan_queue = g_async_queue_new(); + if (!reg_queue) reg_queue = g_async_queue_new(); + if (!storage_queue) storage_queue = g_async_queue_new(); + + /*Init mutex variable*/ + if (!db_mutex) db_mutex = g_mutex_new(); + + /*prepare socket*/ + /* Create and bind new UDP socket */ + if (ms_ipc_create_server_socket(MS_PROTOCOL_UDP, MS_SCAN_DAEMON_PORT, &sockfd) + != MS_MEDIA_ERR_NONE) { + MSC_DBG_ERR("Failed to create socket\n"); + exit(0); + } else { + context = g_main_loop_get_context(scanner_mainloop); + + /* Create new channel to watch udp socket */ + channel = g_io_channel_unix_new(sockfd); + source = g_io_create_watch(channel, G_IO_IN); + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)msc_receive_request, NULL, NULL); + g_source_attach(source, context); + g_source_unref(source); + } + + /*create each threads*/ + storage_scan_thread = g_thread_new("storage_scan_thread", (GThreadFunc)msc_storage_scan_thread, NULL); + scan_thread = g_thread_new("scanner_thread", (GThreadFunc)msc_directory_scan_thread, NULL); + register_thread = g_thread_new("register_thread", (GThreadFunc)msc_register_thread, NULL); + + /*set vconf callback function*/ + err = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, (vconf_callback_fn) msc_mmc_vconf_cb, NULL); + if (err == -1) + MSC_DBG_ERR("add call back function for event %s fails", VCONFKEY_SYSMAN_MMC_STATUS); + + if (msc_is_mmc_inserted()) { + mmc_state = VCONFKEY_SYSMAN_MMC_MOUNTED; + } + + MSC_DBG_INFO("scanner is ready"); + + msc_send_ready(); + + MSC_DBG_INFO("*****************************************"); + MSC_DBG_INFO("*** Scanner is running ***"); + MSC_DBG_INFO("*****************************************"); + + g_main_loop_run(scanner_mainloop); + + g_thread_join (scan_thread); + g_thread_join (register_thread); + g_thread_join (storage_scan_thread); + + if (power_off) { + g_io_channel_shutdown(channel, FALSE, NULL); + g_io_channel_unref(channel); + } + + heynoti_unsubscribe(heynoti_id, POWEROFF_NOTI_NAME, _power_off_cb); + heynoti_close(heynoti_id); + + if (scan_queue) g_async_queue_unref(scan_queue); + if (reg_queue) g_async_queue_unref(reg_queue); + if (storage_queue) g_async_queue_unref(storage_queue); + + /*Clear db mutex variable*/ + if (db_mutex) g_mutex_free (db_mutex); + + /*close socket*/ + close(sockfd); + + /*unload functions*/ + msc_unload_functions(); + + MSC_DBG_INFO("SCANNER IS END"); + + exit(0); +} + diff --git a/config.in b/config.in new file mode 100644 index 0000000..e4e5149 --- /dev/null +++ b/config.in @@ -0,0 +1,161 @@ +/* config.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if the `closedir' function returns void instead of `int'. */ +#undef CLOSEDIR_VOID + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_LSTAT_EMPTY_STRING_BUG + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strstr' function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VFS_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the header file. */ +#undef HAVE_VFORK_H + +/* Define to 1 if `fork' works. */ +#undef HAVE_WORKING_FORK + +/* Define to 1 if `vfork' works. */ +#undef HAVE_WORKING_VFORK + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define as `fork' if `vfork' does not work. */ +#undef vfork diff --git a/configure.ac b/configure.ac new file mode 100755 index 0000000..ab227c9 --- /dev/null +++ b/configure.ac @@ -0,0 +1,128 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.61) +AC_INIT([media-server], [1.0]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_HEADERS([config.h:config.in]) + +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) + +# for platform setting +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL + +# Check target +if ! (test "x$ARCH" = "xarmel" -o "x$ARCH" = "xi386"); then + echo "$ARCH" +# ARCH=ARM +fi + +#if test "x$MACHINE" = "xfloater"; then + CPPFLAGS="$CPPFLAGS -D _FM_GENERIC_ -D EXPORT_API=\"__attribute__((visibility(\\\"default\\\")))\"" + echo "" + echo $CPPFLAGS + echo "### check point ###" + echo "" +#fi + +CPPFLAGS="${CPPFLAGS} -DRND_LINUX" + +# FMS_DEBUG - File Manager Service debug options +# To open debug options: +# export FMS_DEBUG=1 or configure --enable-debug +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], [Enable debug options])], + [case "x$enableval" in + xyes) debug=true;; + xno) debug=false;; + *) AC_MSG_ERROR([Bad value %enableval for --enable-debug]);; + esac], + [debug=false]) +if test "x$debug" = "xtrue" -o "x$FMS_DEBUG" = "x1"; then + FMS_DEBUG_FLAGS="-D FEXPLORER_DEBUG -g" +else + FMS_DEBUG_FLAGS="" +fi +AC_SUBST(FMS_DEBUG_FLAGS) + +# Checks for libraries. +PKG_CHECK_MODULES(GTHREAD, gthread-2.0) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + +PKG_CHECK_MODULES(GLIB, glib-2.0) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(DLOG, dlog) +AC_SUBST(DLOG_CFLAGS) +AC_SUBST(DLOG_LIBS) + +PKG_CHECK_MODULES(DRM_SERVICE, drm-client) +AC_SUBST(DRM_SERVICE_CFLAGS) +AC_SUBST(DRM_SERVICE_LIBS) + +PKG_CHECK_MODULES(PHONESTATUS, vconf) +AC_SUBST(PHONESTATUS_CFLAGS) +AC_SUBST(PHONESTATUS_LIBS) + +PKG_CHECK_MODULES(AUL, aul) +AC_SUBST(AUL_CFLAGS) +AC_SUBST(AUL_LIBS) + +PKG_CHECK_MODULES(LIBPMCONTROL, pmapi) +AC_SUBST(LIBPMCONTROL_CFLAGS) +AC_SUBST(LIBPMCONTROL_LIBS) + +PKG_CHECK_MODULES(HEYNOTI, heynoti) +AC_SUBST(HEYNOTI_CFLAGS) +AC_SUBST(HEYNOTI_LIBS) + +PKG_CHECK_MODULES(DBUS, dbus-glib-1) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + +PKG_CHECK_MODULES(SQLITE, sqlite3) +AC_SUBST(SQLITE3_CFLAGS) +AC_SUBST(SQLITE3_LIBS) + +PKG_CHECK_MODULES(DB_UTIL, db-util) +AC_SUBST(DB_UTIL_CFLAGS) +AC_SUBST(DB_UTIL_LIBS) + +#ticker noti library +PKG_CHECK_MODULES(STATUS, notification) +AC_SUBST(STATUS_CFLAGS) +AC_SUBST(STATUS_LIBS) + +#Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/file.h sys/vfs.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_CLOSEDIR_VOID +AC_FUNC_FORK +AC_FUNC_LSTAT +AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK +AC_FUNC_MALLOC +AC_CHECK_FUNCS([gettimeofday memset mkdir strcasecmp strstr]) + +AC_CONFIG_FILES([Makefile + libmedia-utils.pc + ]) +AC_OUTPUT diff --git a/data/mediasvr b/data/mediasvr new file mode 100755 index 0000000..d109017 --- /dev/null +++ b/data/mediasvr @@ -0,0 +1,3 @@ +#!/bin/sh +/usr/bin/media-server& + diff --git a/lib/include/media-server-ipc.h b/lib/include/media-server-ipc.h new file mode 100755 index 0000000..bebf961 --- /dev/null +++ b/lib/include/media-server-ipc.h @@ -0,0 +1,107 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines IPC protocol + * + * @file media-server-ipc.h + * @author Haejeong Kim(backto.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_SERVER_IPC_H_ +#define _MEDIA_SERVER_IPC_H_ + +#define MS_TIMEOUT_SEC_3 3 /**< Response from Server time out */ +#define MS_TIMEOUT_SEC_10 10 /**< Response from Server time out */ +#define MS_TIMEOUT_SEC_20 20 /**< Response from Media server time out */ + +#define MS_SCANNER_PORT 1001 /**< Directory Scanner */ +#define MS_DB_UPDATE_PORT 1002 /**< Media DB Update */ +#define MS_THUMB_CREATOR_PORT 1003 /**< Create thumbnail */ +#define MS_THUMB_DAEMON_PORT 1004 /**< Port of Thumbnail server */ +#define MS_THUMB_COMM_PORT 1005 /**< Port of communication between creator and server */ +#define MS_DB_BATCH_UPDATE_PORT 1006 /**< Media DB batch update */ +#define MS_SCAN_DAEMON_PORT 1007 /**< Port of communication between scanner and server */ +#define MS_SCAN_COMM_PORT 1008 /**< Port of communication between scanner and server */ + +#define MAX_MSG_SIZE 4096 + +typedef enum{ + MS_MSG_DB_UPDATE = 0, /**< Media DB Update */ + MS_MSG_DB_UPDATE_BATCH_START, /**< Start of media DB update batch */ + MS_MSG_DB_UPDATE_BATCH, /**< Perform of media DB update batch */ + MS_MSG_DB_UPDATE_BATCH_END, /**< End of media DB update batch */ + MS_MSG_DIRECTORY_SCANNING, /**< Non recursive Directory Scan and Media DB Update*/ + MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE,/**< Recursive Directory Scan and Media DB Update*/ + MS_MSG_BULK_INSERT, /**< Request bulk insert */ + MS_MSG_STORAGE_ALL, + MS_MSG_STORAGE_PARTIAL, + MS_MSG_STORAGE_INVALID, + MS_MSG_THUMB_SERVER_READY, /**< Ready from thumbnail server */ + MS_MSG_THUMB_EXTRACT_ALL_DONE, /**< Done of all-thumbnail extracting */ + MS_MSG_SCANNER_READY, /**< Ready from media scanner */ + MS_MSG_SCANNER_RESULT, /**< Result of directory scanning */ + MS_MSG_SCANNER_BULK_RESULT, /**< Request bulk insert */ + MS_MSG_MAX /**< Invalid msg type */ +}ms_msg_type_e; + +typedef struct +{ + ms_msg_type_e msg_type; + int pid; + int result; + size_t msg_size; /*this is size of message below and this does not include the terminationg null byte ('\0'). */ + char msg[MAX_MSG_SIZE]; +}ms_comm_msg_s; + +typedef enum { + CLIENT_SOCKET, + SERVER_SOCKET +} ms_socket_type_e; + +typedef enum { + MS_MEDIA_THUMB_LARGE, + MS_MEDIA_THUMB_SMALL, +} ms_thumb_type_e; + +typedef struct { + ms_msg_type_e msg_type; +} ms_thumb_server_msg; + +typedef struct _thumbMsg{ + int msg_type; + int thumb_type; + int status; + int pid; + int thumb_size; + int thumb_width; + int thumb_height; + int origin_width; + int origin_height; + int origin_path_size; + int dest_path_size; + char org_path[MAX_MSG_SIZE]; + char dst_path[MAX_MSG_SIZE]; +} thumbMsg; + + +#endif /*_MEDIA_SERVER_IPC_H_*/ diff --git a/lib/include/media-util-db.h b/lib/include/media-util-db.h new file mode 100755 index 0000000..435f74a --- /dev/null +++ b/lib/include/media-util-db.h @@ -0,0 +1,61 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-noti.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + #ifndef _MEDIA_UTIL_DB_H_ +#define _MEDIA_UTIL_DB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void MediaDBHandle; /**< Handle */ + +int media_db_connect(MediaDBHandle **handle); + +int media_db_disconnect(MediaDBHandle *handle); + +int media_db_request_update_db(const char *query_str); + +int media_db_request_update_db_batch_start(const char *query_str); + +int media_db_request_update_db_batch(const char *query_str); + +int media_db_request_update_db_batch_end(const char *query_str); + +int media_db_request_directory_scan(const char *directory_path); + +/** +* @} +*/ + +#ifdef __cplusplus +} +#endif + +#endif /*_MEDIA_UTIL_DB_H_*/ diff --git a/lib/include/media-util-dbg.h b/lib/include/media-util-dbg.h new file mode 100755 index 0000000..eef9866 --- /dev/null +++ b/lib/include/media-util-dbg.h @@ -0,0 +1,83 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-dbg.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_UTIL_DBG_H_ +#define _MEDIA_UTIL_DBG_H_ + +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "MEDIA_UTIL" + +#define FONT_COLOR_RESET "\033[0m" +#define FONT_COLOR_RED "\033[31m" +#define FONT_COLOR_GREEN "\033[32m" +#define FONT_COLOR_YELLOW "\033[33m" +#define FONT_COLOR_BLUE "\033[34m" +#define FONT_COLOR_PURPLE "\033[35m" +#define FONT_COLOR_CYAN "\033[36m" +#define FONT_COLOR_GRAY "\033[37m" + +#define MSAPI_DBG(fmt, arg...) do { \ + LOGD(FONT_COLOR_RESET fmt, ##arg); \ + } while (0) + +#define MSAPI_DBG_INFO(fmt, arg...) do { \ + LOGD(FONT_COLOR_GREEN fmt, ##arg); \ + } while (0) + +#define MSAPI_DBG_ERR(fmt, arg...) do { \ + LOGE(FONT_COLOR_RED fmt, ##arg); \ + } while (0) + +#define MSAPI_DBG_FUNC() do { \ + LOGD(FONT_COLOR_RESET); \ + } while (0) + + +#define MSAPI_RETV_IF(expr, val) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED); \ + return (val); \ + } \ + } while (0) + +#define MSAPI_RETVM_IF(expr, val, fmt, arg...) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED fmt, ##arg); \ + return (val); \ + } \ + } while (0) + +#endif /*_MEDIA_UTIL_DBG_H_*/ diff --git a/lib/include/media-util-err.h b/lib/include/media-util-err.h new file mode 100755 index 0000000..bcbba3f --- /dev/null +++ b/lib/include/media-util-err.h @@ -0,0 +1,83 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-err.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#ifndef _MEDIA_UTIL_ERR_H_ +#define _MEDIA_UTIL_ERR_H_ + +#define MS_MEDIA_ERR_NONE 0 + +/*internal operation error*/ +#define MS_MEDIA_ERR_INTERNAL -1 +#define MS_MEDIA_ERR_INVALID_CONTENT -2 /**< Invalid content */ +#define MS_MEDIA_ERR_INVALID_PARAMETER -3 /**< invalid parameter(s) */ +#define MS_MEDIA_ERR_INVALID_PATH -4 /**< Invalid path */ +#define MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL -5 /**< exception of memory allocation */ +#define MS_MEDIA_ERR_DIR_OPEN_FAIL -6 /**< exception of dir open*/ +#define MS_MEDIA_ERR_FILE_OPEN_FAIL -7 /**< exception of file doesn't exist*/ + +/*DB operation error*/ +#define MS_MEDIA_ERR_DB_CONNECT_FAIL -11 /**< connecting database fails */ +#define MS_MEDIA_ERR_DB_DISCONNECT_FAIL -12 /**< disconnecting database fails */ +#define MS_MEDIA_ERR_DB_INSERT_FAIL -13 /**< inserting record fails */ +#define MS_MEDIA_ERR_DB_DELETE_FAIL -14 /**< deleting record fails */ +#define MS_MEDIA_ERR_DB_UPDATE_FAIL -15 /**< updating record fails */ +#define MS_MEDIA_ERR_DB_EXIST_ITEM_FAIL -16 /**< item does not exist */ +#define MS_MEDIA_ERR_DB_BUSY_FAIL -17 /**< DB Busy */ + +/*DRM operation error*/ +#define MS_MEDIA_ERR_DRM_REGISTER_FAIL -21 /**< interting into drm db fails */ +#define MS_MEDIA_ERR_DRM_GET_INFO_FAIL -22 /**< getting inforamtion fails from DRM content */ + +/*IPC operation error*/ +#define MS_MEDIA_ERR_SOCKET_INTERNAL -31 /**< receive error from socket API */ +#define MS_MEDIA_ERR_SOCKET_CONN -32 /**< socket connect error */ +#define MS_MEDIA_ERR_SOCKET_BIND -33 /**< socket binding fails */ +#define MS_MEDIA_ERR_SOCKET_SEND -34 /**< socket sending fails */ +#define MS_MEDIA_ERR_SOCKET_RECEIVE -35 /**< socket receiving fails */ +#define MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT -36 /**< socket receive timeout error */ +#define MS_MEDIA_ERR_DBUS_ADD_FILTER -37 /**< DBUS add filter fails*/ +#define MS_MEDIA_ERR_DBUS_GET -38 /**< DBUS get fails */ +#define MS_MEDIA_ERR_DATA_TAINTED -39 /**< received data is tainted */ + +/* SERVER error*/ +#define MS_MEDIA_ERR_NOW_REGISTER_FILE -41 /**< already inserting into DB */ +#define MS_MEDIA_ERR_SCANNING_BUSY -42 /**< already directory scanning is running */ +#define MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL -43 /**< DB server busy */ +#define MS_MEDIA_ERR_SCANNER_FORCE_STOP -44 /**< scanning is stopped forcely */ + +/*ETC*/ +#define MS_MEDIA_ERR_VCONF_SET_FAIL -51 /**< vconf set fail*/ +#define MS_MEDIA_ERR_VCONF_GET_FAIL -52 /**< vconf get fail*/ +#define MS_MEDIA_ERR_MIME_GET_FAIL -53 /**< not media file*/ +#define MS_MEDIA_ERR_SCANNER_NOT_READY -54 /**< not media file*/ +#define MS_MEDIA_ERR_DYNAMIC_LINK -55 + +#define MS_MEDIA_ERR_MAX -999 /**< not media file*/ + +#endif /*_MEDIA_UTIL_ERR_H_*/ diff --git a/lib/include/media-util-internal.h b/lib/include/media-util-internal.h new file mode 100755 index 0000000..f964d9f --- /dev/null +++ b/lib/include/media-util-internal.h @@ -0,0 +1,65 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-internal.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#ifndef _MEDIA_UTIL_INTERNAL_H_ +#define _MEDIA_UTIL_INTERNAL_H_ + +#include "media-util-db.h" + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#define MS_SAFE_FREE(src) { if(src) {free(src); src = NULL;} } +#define MS_STRING_VALID(str) \ + ((str != NULL && strlen(str) > 0) ? TRUE : FALSE) + +#define MS_MEDIA_DBUS_PATH "/com/mediaserver/dbus/notify" +#define MS_MEDIA_DBUS_INTERFACE "com.mediaserver.dbus.Signal" +#define MS_MEDIA_DBUS_NAME "ms_db_updated" +#define MS_MEDIA_DBUS_MATCH_RULE "type='signal',interface='com.mediaserver.dbus.Signal'" + + +#define MS_SCAN_STATUS_DIRECTORY "file/private/mediaserver/scan_directory" +enum{ + VCONF_SCAN_DOING = 0, + VCONF_SCAN_DONE, +}; + +int media_db_update_db(MediaDBHandle *handle, const char *query_str); + +int media_db_update_db_batch_start(const char *query_str); +int media_db_update_db_batch(const char *query_str); +int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str); + +#endif /*_MEDIA_UTIL_INTERNAL_H_*/ diff --git a/lib/include/media-util-ipc.h b/lib/include/media-util-ipc.h new file mode 100755 index 0000000..60dd1fa --- /dev/null +++ b/lib/include/media-util-ipc.h @@ -0,0 +1,61 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of IPC. + * + * @file media-util-ipc.h + * @author Haejeong Kim(backto.kim@samsung.com) + * @version 1.0 + * @brief + */ + #ifndef _MEDIA_UTIL_IPC_H_ +#define _MEDIA_UTIL_IPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "media-server-ipc.h" + +#define SERVER_IP "127.0.0.1" + +typedef enum { + MS_PROTOCOL_UDP, + MS_PROTOCOL_TCP +} ms_protocol_e; + +int ms_ipc_create_client_socket(ms_protocol_e protocol, int timeout_sec, int *sock_fd); +int ms_ipc_create_server_socket(ms_protocol_e protocol, int port, int *sock_fd); +int ms_ipc_send_msg_to_server(int sockfd, int port, ms_comm_msg_s *send_msg, struct sockaddr_in *serv_addr); +int ms_ipc_send_msg_to_client(int sockfd, ms_comm_msg_s *send_msg, struct sockaddr_in *client_addr); +int ms_ipc_receive_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *client_addr, unsigned int *size); +int ms_ipc_wait_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *recv_addr, unsigned int *size); + +#ifdef __cplusplus +} +#endif + +#endif /*_MEDIA_UTIL_IPC_H_*/ diff --git a/lib/include/media-util-noti.h b/lib/include/media-util-noti.h new file mode 100755 index 0000000..630f42e --- /dev/null +++ b/lib/include/media-util-noti.h @@ -0,0 +1,83 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-noti.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + #ifndef _MEDIA_UTIL_NOTI_H_ +#define _MEDIA_UTIL_NOTI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @fn int media_db_update_subscribe(void); +* @brief This function announce media database is updated to other applications.
+* @return This function returns 0 on success, and -1 on failure. +* @param[in] none +* @remark This function is recommandation for other application being aware of database updating.
+* @par example +* @code + +#include +#include +#include + +void callback() +{ + printf("listen dbus from media-server\n"); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + + loop = g_main_loop_new (NULL, FALSE); + + media_db_update_subscribe(callback); + + g_main_loop_run (loop); + + return 0; +} + +*/ + +typedef void (*db_update_cb)(void); + +int media_db_update_subscribe(db_update_cb user_cb); + +/** +* @} +*/ + +#ifdef __cplusplus +} +#endif + +#endif /*_MEDIA_UTIL_NOTI_H_*/ diff --git a/lib/include/media-util-register.h b/lib/include/media-util-register.h new file mode 100755 index 0000000..f8dc498 --- /dev/null +++ b/lib/include/media-util-register.h @@ -0,0 +1,111 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-register.h + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + #ifndef _MEDIA_UTIL_REGISTER_H_ +#define _MEDIA_UTIL_REGISTER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @fn int ms_media_file_register(const char *file_full_path); + * @brief This function registers multimedia file to media DB + * When you did some file operations such as Create, Copy, Move, Rename, and Delete in phone or mmc storage, media-server registers the result to database automatically by inotify mechanism. + * However, automatic registration will have a little delay because the method is asynchronous. + * If you want to register some files to database immediately, you should use this API. + * + * @param file_full_path [in] full path of file for register + * @return This function returns zero(MEDIA_INFO_ERROR_NONE) on success, or negative value with error code. + * Please refer 'media-info-error.h' to know the exact meaning of the error. + * @see None. + * @pre None. + * @post None. + * @remark The database name is "/opt/usr/dbspace/.media.db". + * You have to use this API only for registering multimedia files. If you try to register no multimedia file, this API returns error. + * @par example + * @code + +#include + +int main() +{ + int result = -1; + + result = ms_media_file_register("/opt/usr/media/test.mp3"); + if( result < 0 ) + { + printf("FAIL to mediainfo_register_file\n"); + return 0; + } + else + { + printf("SUCCESS to register file\n"); + } + + return 0; +} + + * @endcode + */ +int media_file_register(const char *file_full_path); + +typedef enum +{ + MEDIA_DIRECTORY_SCAN = 0, + MEDIA_FILES_REGISTER, +} media_request_type_e; + +typedef struct +{ + int pid; + int result; + int request_type; + char *complete_path; /* if the request type is MEDIA_FILES_REGISTER, this value will be NULL. */ +}media_request_result_s; + +typedef void (*scan_complete_cb)(media_request_result_s *, void *); +typedef void (*insert_complete_cb)(media_request_result_s *, void *); + +int media_directory_scanning_async(const char *directory_path, bool recusive_on, scan_complete_cb user_callback, void *user_data); + +int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data); + +/** +* @} +*/ + +#ifdef __cplusplus +} +#endif + +#endif /*_MEDIA_UTIL_REGISTER_H_*/ diff --git a/lib/include/media-util.h b/lib/include/media-util.h new file mode 100755 index 0000000..4ae7b54 --- /dev/null +++ b/lib/include/media-util.h @@ -0,0 +1,38 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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 _MEDIA_UTIL_H_ +#define _MEDIA_UTIL_H_ + +#include +#include +#include +#include +#include + +#define MOUNT_PATH "/opt/usr" + +#define MEDIA_ROOT_PATH_INTERNAL MOUNT_PATH"/media" +#define MEDIA_ROOT_PATH_SDCARD "/opt/storage/sdcard" +#define MEDIA_DATA_PATH MOUNT_PATH"/data/file-manager-service" +#define MEDIA_DB_NAME MOUNT_PATH"/dbspace/.media.db" /**< media db name*/ + +#endif /*_MEDIA_UTIL_H_*/ diff --git a/lib/media-util-db.c b/lib/media-util-db.c new file mode 100755 index 0000000..38f6e40 --- /dev/null +++ b/lib/media-util-db.c @@ -0,0 +1,515 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of Media DB. + * + * @file media-util-db.c + * @author Haejeong Kim(backto.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include +#include +#include "media-server-ipc.h" +#include "media-util-dbg.h" +#include "media-util-internal.h" +#include "media-util.h" + +static __thread char **sql_list = NULL; +static __thread int g_list_idx = 0; + +static int __media_db_busy_handler(void *pData, int count); +static int __media_db_connect_db_with_handle(sqlite3 **db_handle); +static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle); +static int __media_db_request_update(ms_msg_type_e msg_type, const char *request_msg); + +void __media_db_destroy_sql_list() +{ + int i = 0; + + for (i = 0; i < g_list_idx; i++) { + MS_SAFE_FREE(sql_list[i]); + } + + MS_SAFE_FREE(sql_list); + g_list_idx = 0; +} + +static int __media_db_busy_handler(void *pData, int count) +{ + usleep(50000); + + MSAPI_DBG("media_db_busy_handler called : %d", count); + + return 100 - count; +} + +static int __media_db_connect_db_with_handle(sqlite3 **db_handle) +{ + int ret = MS_MEDIA_ERR_NONE; + + /*Connect DB*/ + ret = db_util_open(MEDIA_DB_NAME, db_handle, DB_UTIL_REGISTER_HOOK_METHOD); + + if (SQLITE_OK != ret) { + + MSAPI_DBG_ERR("error when db open"); + *db_handle = NULL; + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + + if (*db_handle == NULL) { + MSAPI_DBG_ERR("*db_handle is NULL"); + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + + /*Register busy handler*/ + ret = sqlite3_busy_handler(*db_handle, __media_db_busy_handler, NULL); + + if (SQLITE_OK != ret) { + + if (*db_handle) { + MSAPI_DBG_ERR("[error when register busy handler] %s\n", sqlite3_errmsg(*db_handle)); + } + + db_util_close(*db_handle); + *db_handle = NULL; + + return MS_MEDIA_ERR_DB_CONNECT_FAIL; + } + + return MS_MEDIA_ERR_NONE; +} + +static int __media_db_disconnect_db_with_handle(sqlite3 *db_handle) +{ + int ret = MS_MEDIA_ERR_NONE; + + ret = db_util_close(db_handle); + + if (SQLITE_OK != ret) { + MSAPI_DBG_ERR("error when db close"); + MSAPI_DBG_ERR("Error : %s", sqlite3_errmsg(db_handle)); + db_handle = NULL; + return MS_MEDIA_ERR_DB_DISCONNECT_FAIL; + } + + return MS_MEDIA_ERR_NONE; +} + +static int __media_db_request_update(ms_msg_type_e msg_type, const char *request_msg) +{ + int ret = MS_MEDIA_ERR_NONE; + int request_msg_size = 0; + int sockfd = -1; + int err = -1; + struct sockaddr_in serv_addr; + unsigned int serv_addr_len = -1; + int port = MS_DB_UPDATE_PORT; + + if(msg_type == MS_MSG_DB_UPDATE) + port = MS_DB_UPDATE_PORT; + else + port = MS_SCANNER_PORT; + + if(!MS_STRING_VALID(request_msg)) + { + MSAPI_DBG_ERR("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + request_msg_size = strlen(request_msg); + if(request_msg_size >= MAX_MSG_SIZE) + { + MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + +// MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg); + + ms_comm_msg_s send_msg; + memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s)); + + send_msg.msg_type = msg_type; + send_msg.msg_size = request_msg_size; + strncpy(send_msg.msg, request_msg, request_msg_size); + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_3, &sockfd); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, &serv_addr); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + /*Receive Response*/ + ms_comm_msg_s recv_msg; + serv_addr_len = sizeof(serv_addr); + memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s)); + + err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL); + if (err != MS_MEDIA_ERR_NONE) { + ret = err; + } else { + MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result); + ret = recv_msg.result; + } + + close(sockfd); + + return ret; +} + +static int g_tcp_client_sock = -1; + +static int __media_db_get_client_tcp_sock() +{ + return g_tcp_client_sock; +} + +static int __media_db_prepare_tcp_client_socket() +{ + int ret = MS_MEDIA_ERR_NONE; + int sockfd = -1; + struct sockaddr_in serv_addr; + int port = MS_DB_BATCH_UPDATE_PORT; + + /*Create TCP Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_3, &sockfd); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + /*Set server Address*/ + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP); + serv_addr.sin_port = htons(port); + + /* Connecting to the media db server */ + if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { + MSAPI_DBG_ERR("connect error : %s", strerror(errno)); + close(sockfd); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + g_tcp_client_sock = sockfd; + + MSAPI_DBG("Connected successfully"); + + return 0; +} + +static int __media_db_close_tcp_client_socket() +{ + close(g_tcp_client_sock); + g_tcp_client_sock = -1; + + return 0; +} + +static int __media_db_request_batch_update(ms_msg_type_e msg_type, const char *request_msg) +{ + int ret = MS_MEDIA_ERR_NONE; + int request_msg_size = 0; + int sockfd = -1; + + if(!MS_STRING_VALID(request_msg)) + { + MSAPI_DBG_ERR("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + request_msg_size = strlen(request_msg); + if(request_msg_size >= MAX_MSG_SIZE) + { + MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg); + ms_comm_msg_s send_msg; + memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s)); + + send_msg.msg_type = msg_type; + send_msg.msg_size = request_msg_size; + strncpy(send_msg.msg, request_msg, request_msg_size); + + sockfd = __media_db_get_client_tcp_sock(); + if (sockfd <= 0) { + return MS_MEDIA_ERR_SOCKET_CONN; + } + + /* Send request */ + if (send(sockfd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) { + MSAPI_DBG_ERR("send failed : %s", strerror(errno)); + __media_db_close_tcp_client_socket(sockfd); + return MS_MEDIA_ERR_SOCKET_SEND; + } else { + MSAPI_DBG("Sent successfully"); + } + + /*Receive Response*/ + int recv_msg_size = -1; + int recv_msg = -1; + if ((recv_msg_size = recv(sockfd, &recv_msg, sizeof(recv_msg), 0)) < 0) { + MSAPI_DBG_ERR("recv failed : %s", strerror(errno)); + + __media_db_close_tcp_client_socket(sockfd); + if (errno == EWOULDBLOCK) { + MSAPI_DBG_ERR("Timeout. Can't try any more"); + return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT; + } else { + MSAPI_DBG_ERR("recv failed : %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_RECEIVE; + } + } + + MSAPI_DBG("RECEIVE OK [%d]", recv_msg); + ret = recv_msg; + + return ret; +} + +static int _media_db_update_directly(sqlite3 *db_handle, const char *sql_str) +{ + int ret = MS_MEDIA_ERR_NONE; + char *zErrMsg = NULL; + + MSAPI_DBG_INFO("SQL = [%s]", sql_str); + + ret = sqlite3_exec(db_handle, sql_str, NULL, NULL, &zErrMsg); + + if (SQLITE_OK != ret) { + MSAPI_DBG_ERR("DB Update Fail SQL:%s [%s], err[%d]", sql_str, zErrMsg, ret); + if (ret == SQLITE_BUSY) + ret = MS_MEDIA_ERR_DB_BUSY_FAIL; + else + ret = MS_MEDIA_ERR_DB_UPDATE_FAIL; + } else { + MSAPI_DBG("DB Update Success"); + } + + if (zErrMsg) + sqlite3_free (zErrMsg); + + return ret; +} + +int media_db_connect(MediaDBHandle **handle) +{ + int ret = MS_MEDIA_ERR_NONE; + sqlite3 * db_handle = NULL; + + MSAPI_DBG_FUNC(); + + ret = __media_db_connect_db_with_handle(&db_handle); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + *handle = db_handle; + return MS_MEDIA_ERR_NONE; +} + +int media_db_disconnect(MediaDBHandle *handle) +{ + sqlite3 * db_handle = (sqlite3 *)handle; + + MSAPI_DBG_FUNC(); + + MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL"); + + return __media_db_disconnect_db_with_handle(db_handle); +} + +int media_db_request_update_db(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_DBG_FUNC(); + + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + ret = __media_db_request_update(MS_MSG_DB_UPDATE, query_str); + + return ret; +} + +int media_db_request_update_db_batch_start(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_DBG_FUNC(); + + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + ret = __media_db_prepare_tcp_client_socket(); + + if (ret < MS_MEDIA_ERR_NONE) { + MSAPI_DBG_ERR("__media_db_prepare_tcp_client_socket failed : %d", ret); + __media_db_close_tcp_client_socket(); + return ret; + } + + ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_START, query_str); + + return ret; +} + +int media_db_request_update_db_batch(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_DBG_FUNC(); + + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH, query_str); + + return ret; +} + +int media_db_request_update_db_batch_end(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_DBG_FUNC(); + + if (!MS_STRING_VALID(query_str)) { + MSAPI_DBG_ERR("Invalid Query"); + __media_db_close_tcp_client_socket(); + return ret; + } + + ret = __media_db_request_batch_update(MS_MSG_DB_UPDATE_BATCH_END, query_str); + + __media_db_close_tcp_client_socket(); + + return ret; +} + +int media_db_request_directory_scan(const char *directory_path) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_RETVM_IF(!MS_STRING_VALID(directory_path), MS_MEDIA_ERR_INVALID_PARAMETER, "Directory Path is NULL"); + + ret = __media_db_request_update(MS_MSG_DIRECTORY_SCANNING, directory_path); + + return ret; +} + +int media_db_update_db(MediaDBHandle *handle, const char *query_str) +{ + sqlite3 * db_handle = (sqlite3 *)handle; + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_RETVM_IF(db_handle == NULL, MS_MEDIA_ERR_INVALID_PARAMETER, "Handle is NULL"); + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + ret = _media_db_update_directly(db_handle, query_str); + + return ret; +} + +int media_db_update_db_batch_start(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + if (g_list_idx != 0) { + MSAPI_DBG_ERR("Current idx is not 0"); + ret = MS_MEDIA_ERR_DB_SERVER_BUSY_FAIL; + } else { + sql_list = (char**)malloc(sizeof(char*)); + MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory"); + sql_list[g_list_idx++] = strdup(query_str); + MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory"); + } + + return ret; +} + +int media_db_update_db_batch(const char *query_str) +{ + int ret = MS_MEDIA_ERR_NONE; + + MSAPI_RETVM_IF(!MS_STRING_VALID(query_str), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid Query"); + + sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*)); + MSAPI_RETVM_IF(sql_list == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory"); + + sql_list[g_list_idx++] = strdup(query_str); + MSAPI_RETVM_IF(sql_list[g_list_idx - 1] == NULL, MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL, "Out of memory"); + + return ret; +} + +int media_db_update_db_batch_end(MediaDBHandle *handle, const char *query_str) +{ + sqlite3 * db_handle = (sqlite3 *)handle; + int ret = MS_MEDIA_ERR_NONE; + + if (db_handle == NULL || (!MS_STRING_VALID(query_str))) { + __media_db_destroy_sql_list(); + MSAPI_DBG_ERR("Handle is NULL"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + sql_list = (char**)realloc(sql_list, (g_list_idx + 1) * sizeof(char*)); + if (sql_list == NULL) { + __media_db_destroy_sql_list(); + MSAPI_DBG_ERR("Out of memory"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + sql_list[g_list_idx++] = strdup(query_str); + if (sql_list[g_list_idx - 1] == NULL) { + __media_db_destroy_sql_list(); + MSAPI_DBG_ERR("Out of memory"); + return MS_MEDIA_ERR_ALLOCATE_MEMORY_FAIL; + } + + int i = 0; + char *current_sql = NULL; + for (i = 0; i < g_list_idx; i++) { + current_sql = sql_list[i]; + ret = _media_db_update_directly(db_handle, current_sql); + if (ret < 0) { + if (i == 0) { + /* This is fail of "BEGIN" */ + MSAPI_DBG_ERR("Query failed : %s", current_sql); + break; + } else if (i == g_list_idx - 1) { + /* This is fail of "COMMIT" */ + MSAPI_DBG_ERR("Query failed : %s", current_sql); + break; + } else { + MSAPI_DBG_ERR("Query failed : %s, but keep going to run remaining queries", current_sql); + } + } + } + + __media_db_destroy_sql_list(); + + return ret; +} diff --git a/lib/media-util-ipc.c b/lib/media-util-ipc.c new file mode 100755 index 0000000..1e71ed8 --- /dev/null +++ b/lib/media-util-ipc.c @@ -0,0 +1,227 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of IPC. + * + * @file media-util-ipc.c + * @author Haejeong Kim(backto.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include + +#include "media-util-dbg.h" +#include "media-util.h" + +int ms_ipc_create_client_socket(ms_protocol_e protocol, int timeout_sec, int *sock_fd) +{ + int sock = -1; + + struct timeval tv_timeout = { timeout_sec, 0 }; + + if(protocol == MS_PROTOCOL_UDP) + { + /* Create a datagram/UDP socket */ + if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + MSAPI_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + } + else + { + /*Create TCP Socket*/ + if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + MSAPI_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + } + + if (timeout_sec > 0) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv_timeout, sizeof(tv_timeout)) == -1) { + MSAPI_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sock); + return MS_MEDIA_ERR_SOCKET_CONN; + } + } + + *sock_fd = sock; + + return MS_MEDIA_ERR_NONE; +} + +int ms_ipc_create_server_socket(ms_protocol_e protocol, int port, int *sock_fd) +{ + int sock = -1; + int n_reuse = 1; + struct sockaddr_in serv_addr; + unsigned short serv_port; + + serv_port = port; + + if(protocol == MS_PROTOCOL_UDP) + { + /* Create a datagram/UDP socket */ + if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + MSAPI_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + } + else + { + /* Create a TCP socket */ + if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + MSAPI_DBG_ERR("socket failed: %s", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_CONN; + } + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)) == -1) { + MSAPI_DBG_ERR("setsockopt failed: %s", strerror(errno)); + close(sock); + return MS_MEDIA_ERR_SOCKET_INTERNAL; + } + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; +// serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP); + serv_addr.sin_port = htons(serv_port); + + /* Bind to the local address */ + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + MSAPI_DBG_ERR("bind failed : %s", strerror(errno)); + close(sock); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + MSAPI_DBG("bind success"); + + /* Listening */ + if (protocol == MS_PROTOCOL_TCP) { + if (listen(sock, SOMAXCONN) < 0) { + MSAPI_DBG_ERR("listen failed : %s", strerror(errno)); + close(sock); + return MS_MEDIA_ERR_SOCKET_CONN; + } + + MSAPI_DBG("Listening..."); + } + + *sock_fd = sock; + + return MS_MEDIA_ERR_NONE; +} + +int ms_ipc_send_msg_to_server(int sockfd, int port, ms_comm_msg_s *send_msg, struct sockaddr_in *serv_addr) +{ + int res = MS_MEDIA_ERR_NONE; + struct sockaddr_in addr; + + /* Set server Address */ + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(SERVER_IP); + addr.sin_port = htons(port); + + if (sendto(sockfd, send_msg, sizeof(*(send_msg)), 0, (struct sockaddr *)&addr, sizeof(addr)) != sizeof(*(send_msg))) { + MSAPI_DBG_ERR("sendto failed [%s]", strerror(errno)); + res = MS_MEDIA_ERR_SOCKET_SEND; + } else { + MSAPI_DBG("sent %d", send_msg->result); + MSAPI_DBG("sent %s", send_msg->msg); + if (serv_addr != NULL) + *serv_addr = addr; + } + + return res; +} + +int ms_ipc_send_msg_to_client(int sockfd, ms_comm_msg_s *send_msg, struct sockaddr_in *client_addr) +{ + int res = MS_MEDIA_ERR_NONE; + + if (sendto(sockfd, send_msg, sizeof(*(send_msg)), 0, (struct sockaddr *)client_addr, sizeof(*(client_addr))) != sizeof(*(send_msg))) { + MSAPI_DBG_ERR("sendto failed [%s]", strerror(errno)); + res = MS_MEDIA_ERR_SOCKET_SEND; + } else { + MSAPI_DBG("sent %d", send_msg->result); + MSAPI_DBG("sent %s", send_msg->msg); + } + + return MS_MEDIA_ERR_NONE; +} + +int ms_ipc_receive_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *recv_addr, unsigned int *addr_size) +{ + int recv_msg_size; + struct sockaddr_in addr; + socklen_t addr_len; + + if (!recv_msg) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + addr_len = sizeof(struct sockaddr_in); + + if ((recv_msg_size = recvfrom(sockfd, recv_msg, msg_size, 0, (struct sockaddr *)&addr, &addr_len)) < 0) { + MSAPI_DBG_ERR("recvfrom failed [%s]", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_RECEIVE; + } + + if (recv_addr != NULL) + *recv_addr = addr; + if (addr_size != NULL) + *addr_size = addr_len; + + return MS_MEDIA_ERR_NONE; +} + +int ms_ipc_wait_message(int sockfd, void *recv_msg, unsigned int msg_size, struct sockaddr_in *recv_addr, unsigned int *addr_size) +{ + int recv_msg_size; + socklen_t addr_len; + + if (!recv_msg ||!recv_addr) + return MS_MEDIA_ERR_INVALID_PARAMETER; + + addr_len = sizeof(struct sockaddr_in); + + if ((recv_msg_size = recvfrom(sockfd, recv_msg, msg_size, 0, (struct sockaddr *)recv_addr, &addr_len)) < 0) { + MSAPI_DBG_ERR("recvfrom failed [%s]", strerror(errno)); + if (errno == EWOULDBLOCK) { + MSAPI_DBG_ERR("recvfrom Timeout."); + return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT; + } else { + MSAPI_DBG_ERR("recvfrom error [%s]", strerror(errno)); + return MS_MEDIA_ERR_SOCKET_RECEIVE; + } + } + + if (addr_size != NULL) + *addr_size = addr_len; + + return MS_MEDIA_ERR_NONE; +} + + diff --git a/lib/media-util-noti.c b/lib/media-util-noti.c new file mode 100755 index 0000000..a4af345 --- /dev/null +++ b/lib/media-util-noti.c @@ -0,0 +1,92 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-noti.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "media-util-internal.h" +#include "media-util-dbg.h" +#include "media-util.h" + +static DBusHandlerResult +__message_filter (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + db_update_cb user_cb = user_data; + + /* A Ping signal on the com.burtonini.dbus.Signal interface */ + if (dbus_message_is_signal (message, MS_MEDIA_DBUS_INTERFACE, MS_MEDIA_DBUS_NAME)) { + DBusError error; + dbus_uint16_t noti_type; + + dbus_error_init (&error); + if (dbus_message_get_args (message, &error, DBUS_TYPE_UINT16, ¬i_type, DBUS_TYPE_INVALID)) { + MSAPI_DBG("noti type: %d\n", noti_type); + user_cb(); + } else { + MSAPI_DBG("messgae received, but error getting message: %s\n", error.message); + dbus_error_free (&error); + } + return DBUS_HANDLER_RESULT_HANDLED; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +int media_db_update_subscribe(db_update_cb user_cb) +{ + DBusConnection *bus; + DBusError error; + + dbus_g_thread_init(); + + dbus_error_init (&error); + + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) { + MSAPI_DBG ("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free (&error); + return MS_MEDIA_ERR_DBUS_GET; + } + + dbus_connection_setup_with_g_main (bus, NULL); + + /* listening to messages from all objects as no path is specified */ + dbus_bus_add_match (bus, MS_MEDIA_DBUS_MATCH_RULE, &error); + if( !dbus_connection_add_filter (bus, __message_filter, user_cb, NULL)) + return MS_MEDIA_ERR_DBUS_ADD_FILTER; + + return MS_MEDIA_ERR_NONE; +} + diff --git a/lib/media-util-register.c b/lib/media-util-register.c new file mode 100755 index 0000000..462d79f --- /dev/null +++ b/lib/media-util-register.c @@ -0,0 +1,382 @@ +/* + * Media Utility + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Yong Yeon Kim + * + * 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. + * + */ + +/** + * This file defines api utilities of contents manager engines. + * + * @file media-util-register.c + * @author Yong Yeon Kim(yy9875.kim@samsung.com) + * @version 1.0 + * @brief + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "media-server-ipc.h" +#include "media-util-internal.h" +#include "media-util-dbg.h" +#include "media-util.h" + +typedef struct media_callback_data{ + GSource *source; + scan_complete_cb user_callback; + void *user_data; +} media_callback_data; + +static bool _is_valid_path(const char *path) +{ + if (path == NULL) + return false; + + if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) { + return true; + } else if (strncmp(path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) { + return true; + } else + return false; + + return true; +} + +static int _check_dir_path(const char *dir_path) +{ + struct stat sb; + DIR *dp = NULL; + + if (!_is_valid_path(dir_path)) { + MSAPI_DBG("Invalid path : %s", dir_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + + if (stat(dir_path, &sb) == -1) { + MSAPI_DBG("stat failed"); + dp = opendir(dir_path); + if (dp == NULL) { + /*if openning directory is failed, check it exists. */ + if (errno == ENOENT) { + /* this directory is deleted */ + return MS_MEDIA_ERR_NONE; + } + } else { + closedir(dp); + } + return MS_MEDIA_ERR_INTERNAL; + } else { + if((sb.st_mode & S_IFMT) != S_IFDIR) { + MSAPI_DBG("Invalid path : %s is not directory", dir_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + } + + return MS_MEDIA_ERR_NONE; +} + + +/* receive message from media-server[function : ms_receive_message_from_scanner] */ +gboolean _read_socket(GIOChannel *src, GIOCondition condition, gpointer data) +{ + GSource *source = NULL; + scan_complete_cb user_callback; + void *user_data = NULL; + ms_comm_msg_s recv_msg; + media_request_result_s req_result; + int ret; + int sockfd = -1; + + sockfd = g_io_channel_unix_get_fd(src); + if (sockfd < 0) { + MSAPI_DBG("sock fd is invalid!"); + return TRUE; + } + + memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s)); + + /* Socket is readable */ + ret = ms_ipc_receive_message(sockfd, &recv_msg, sizeof(recv_msg), NULL, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MSAPI_DBG("ms_ipc_receive_message failed"); + return TRUE; + } + + memset(&req_result, 0x0, sizeof(media_request_result_s)); + req_result.pid = recv_msg.pid; + req_result.result = recv_msg.result; + if (recv_msg.msg_type ==MS_MSG_SCANNER_RESULT) { + req_result.complete_path = strdup(recv_msg.msg); + req_result.request_type = MEDIA_DIRECTORY_SCAN; + MSAPI_DBG("complete_path :%d", req_result.complete_path); + } else if (recv_msg.msg_type == MS_MSG_SCANNER_BULK_RESULT) { + req_result.complete_path = strdup(recv_msg.msg); + req_result.request_type = MEDIA_FILES_REGISTER; + } + + MSAPI_DBG("pid :%d", req_result.pid); + MSAPI_DBG("result :%d", req_result.result); + MSAPI_DBG("request_type :%d", req_result.request_type); + + source = ((media_callback_data *)data)->source; + user_callback = ((media_callback_data *)data)->user_callback; + user_data = ((media_callback_data *)data)->user_data; + + /*call user define function*/ + user_callback(&req_result, user_data); + + MS_SAFE_FREE(req_result.complete_path); + + /*close an IO channel*/ + g_io_channel_shutdown(src, FALSE, NULL); + g_io_channel_unref(src); + + g_source_destroy(source); + close(sockfd); + MS_SAFE_FREE(data); + + return TRUE; +} + +static int _attach_callback(int *sockfd, scan_complete_cb user_callback, void *user_data) +{ + GIOChannel *channel = NULL; + GMainContext *context = NULL; + GSource *source = NULL; + media_callback_data *cb_data; + + /*get the global default main context*/ + context = g_main_context_default(); + + /* Create new channel to watch udp socket */ + channel = g_io_channel_unix_new(*sockfd); + source = g_io_create_watch(channel, G_IO_IN); + + cb_data = malloc(sizeof(media_callback_data)); + cb_data->source = source; + cb_data->user_callback = user_callback; + cb_data->user_data = user_data; + + /* Set callback to be called when socket is readable */ + g_source_set_callback(source, (GSourceFunc)_read_socket, cb_data, NULL); + g_source_attach(source, context); + g_source_unref(source); + + return MS_MEDIA_ERR_NONE; +} + +static int __media_db_request_update_sync(ms_msg_type_e msg_type, const char *request_msg) +{ + int ret = MS_MEDIA_ERR_NONE; + int request_msg_size = 0; + int sockfd = -1; + int err = -1; + struct sockaddr_in serv_addr; + unsigned int serv_addr_len = -1; + int port = MS_SCANNER_PORT; + ms_comm_msg_s send_msg; + + if(!MS_STRING_VALID(request_msg)) + { + MSAPI_DBG_ERR("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + request_msg_size = strlen(request_msg); + if(request_msg_size >= MAX_MSG_SIZE) + { + MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg); + + memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s)); + send_msg.msg_type = msg_type; + send_msg.pid = syscall(__NR_getpid); + send_msg.msg_size= request_msg_size; + strncpy(send_msg.msg, request_msg, request_msg_size); + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, MS_TIMEOUT_SEC_10, &sockfd); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, &serv_addr); + if (ret != MS_MEDIA_ERR_NONE) { + MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret); + close(sockfd); + return ret; + } + + /*Receive Response*/ + ms_comm_msg_s recv_msg; + serv_addr_len = sizeof(serv_addr); + + memset(&recv_msg, 0x0, sizeof(ms_comm_msg_s)); + err = ms_ipc_wait_message(sockfd, &recv_msg, sizeof(recv_msg), &serv_addr, NULL); + if (err != MS_MEDIA_ERR_NONE) { + ret = err; + } else { + MSAPI_DBG("RECEIVE OK [%d]", recv_msg.result); + ret = recv_msg.result; + } + + close(sockfd); + + return ret; +} + + +static int __media_db_request_update_async(ms_msg_type_e msg_type, const char *request_msg, scan_complete_cb user_callback, void *user_data) +{ + int ret = MS_MEDIA_ERR_NONE; + int request_msg_size = 0; + int sockfd = -1; + int port = MS_SCANNER_PORT; + ms_comm_msg_s send_msg; + + if(!MS_STRING_VALID(request_msg)) + { + MSAPI_DBG_ERR("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + MSAPI_DBG("REQUEST DIRECTORY SCANNING"); + + request_msg_size = strlen(request_msg); + if(request_msg_size >= MAX_MSG_SIZE) + { + MSAPI_DBG_ERR("Query is Too long. [%d] query size limit is [%d]", request_msg_size, MAX_MSG_SIZE); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + MSAPI_DBG("querysize[%d] query[%s]", request_msg_size, request_msg); + + memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s)); + send_msg.msg_type = msg_type; + send_msg.pid = syscall(__NR_getpid); + send_msg.msg_size = request_msg_size; + strncpy(send_msg.msg, request_msg, request_msg_size); + + /*Create Socket*/ + ret = ms_ipc_create_client_socket(MS_PROTOCOL_UDP, 0, &sockfd); + MSAPI_RETV_IF(ret != MS_MEDIA_ERR_NONE, ret); + + ret = ms_ipc_send_msg_to_server(sockfd, port, &send_msg, NULL); + if (ret != MS_MEDIA_ERR_NONE) { + MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret); + close(sockfd); + return ret; + } + + ret = _attach_callback(&sockfd, user_callback ,user_data); + if(ret != MS_MEDIA_ERR_NONE) + return ret; + + return ret; +} + + +int media_directory_scanning_async(const char *directory_path, bool recusive_on, scan_complete_cb user_callback, void *user_data) +{ + int ret; + + ret = _check_dir_path(directory_path); + if(ret != MS_MEDIA_ERR_NONE) + return ret; + + if (recusive_on == TRUE) + ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, directory_path, user_callback, user_data); + else + ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, directory_path, user_callback, user_data); + + return ret; +} + +static int _check_file_path(const char *file_path) +{ + int exist; + struct stat file_st; + + /* check location of file */ + /* file must exists under "/opt/usr/media" or "/opt/storage/sdcard" */ + if(!_is_valid_path(file_path)) { + MSAPI_DBG("Invalid path : %s", file_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + + /* check the file exits actually */ + exist = open(file_path, O_RDONLY); + if(exist < 0) { + MSAPI_DBG("Not exist path : %s", file_path); + return MS_MEDIA_ERR_INVALID_PATH; + } + close(exist); + + /* check type of the path */ + /* It must be a regular file */ + memset(&file_st, 0, sizeof(struct stat)); + if(stat(file_path, &file_st) == 0) { + if(!S_ISREG(file_st.st_mode)) { + /* In this case, it is not a regula file */ + MSAPI_DBG("this path is not a file"); + return MS_MEDIA_ERR_INVALID_PATH; + } + } else { + MSAPI_DBG("stat failed [%s]", strerror(errno)); + return MS_MEDIA_ERR_INTERNAL; + } + + return MS_MEDIA_ERR_NONE; +} + +int media_file_register(const char *file_full_path) +{ + int ret; + + ret = _check_file_path(file_full_path); + if(ret != MS_MEDIA_ERR_NONE) + return ret; + + ret = __media_db_request_update_sync(MS_MSG_DB_UPDATE, file_full_path); + + MSAPI_DBG("client receive: %d", ret); + + return ret; +} + +int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data) +{ + int ret; + + ret = __media_db_request_update_async(MS_MSG_BULK_INSERT, list_path, user_callback, user_data); + + MSAPI_DBG("client receive: %d", ret); + + return ret; +} + diff --git a/libmedia-utils.manifest b/libmedia-utils.manifest new file mode 100644 index 0000000..ca37499 --- /dev/null +++ b/libmedia-utils.manifest @@ -0,0 +1,6 @@ + + + + + + diff --git a/libmedia-utils.pc.in b/libmedia-utils.pc.in new file mode 100755 index 0000000..886d52d --- /dev/null +++ b/libmedia-utils.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: media contents managing service +Description: media contents managing service API +Requires: +Version: @VERSION@ +Libs: -L${libdir} -lmedia-utils +Cflags: -I${includedir}/media-utils diff --git a/media-server.manifest b/media-server.manifest new file mode 100644 index 0000000..387fd9f --- /dev/null +++ b/media-server.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/packaging/media-server.service b/packaging/media-server.service new file mode 100644 index 0000000..e243d10 --- /dev/null +++ b/packaging/media-server.service @@ -0,0 +1,9 @@ +[Unit] +Description=Media server + +[Service] +Type=simple +ExecStart=/usr/bin/media-server + +[Install] +WantedBy=multi-user.target diff --git a/packaging/media-server.spec b/packaging/media-server.spec new file mode 100755 index 0000000..ef40e86 --- /dev/null +++ b/packaging/media-server.spec @@ -0,0 +1,124 @@ +Name: media-server +Summary: File manager service server. +Version: 0.2.26 +Release: 1 +Group: utils +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz +Source1: media-server.service + +Requires(post): /usr/bin/vconftool +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(drm-client) +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(pmapi) +BuildRequires: pkgconfig(heynoti) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(db-util) +BuildRequires: pkgconfig(notification) + +%description +Description: File manager service server + + +%package -n libmedia-utils +Summary: media server runtime library. +Group: TO_BE/FILLED_IN + +%description -n libmedia-utils +Description : media server runtime library. + + +%package -n libmedia-utils-devel +Summary: media server development library. +Group: Development/Libraries +Requires: libmedia-utils = %{version}-%{release} + +%description -n libmedia-utils-devel +Description: media server development library. + +%prep +%setup -q + +%build + +%autogen +%configure --prefix=%{_prefix} --disable-static + +make %{?jobs:-j%jobs} + +%install +%make_install + +mkdir -p %{buildroot}/usr/lib/systemd/system/multi-user.target.wants +install -m 644 %{SOURCE1} %{buildroot}/usr/lib/systemd/system/media-server.service +ln -s ../media-server.service %{buildroot}/usr/lib/systemd/system/multi-user.target.wants/media-server.service + +#License +mkdir -p %{buildroot}/%{_datadir}/license +cp -rf %{_builddir}/%{name}-%{version}/LICENSE.APLv2.0 %{buildroot}/%{_datadir}/license/%{name} + +%post +vconftool set -t int db/filemanager/dbupdate "1" -f +vconftool set -t int memory/filemanager/Mmc "0" -i -f +vconftool set -t string db/private/mediaserver/mmc_info "" -f +vconftool set -t int file/private/mediaserver/scan_internal "1" -f +vconftool set -t int file/private/mediaserver/scan_directory "1" -f + +%files +%manifest media-server.manifest +%defattr(-,root,root,-) +%{_bindir}/media-server +%{_bindir}/media-scanner +%{_bindir}/mediadb-update +%attr(755,-,-) %{_sysconfdir}/rc.d/init.d/mediasvr +/etc/rc.d/rc3.d/S99mediasvr +/etc/rc.d/rc5.d/S99mediasvr +/usr/local/bin/reset_mediadb.sh +/usr/lib/systemd/system/media-server.service +/usr/lib/systemd/system/multi-user.target.wants/media-server.service +#License +%{_datadir}/license/%{name} + +%files -n libmedia-utils +%manifest libmedia-utils.manifest +%defattr(-,root,root,-) +%{_libdir}/libmedia-utils.so +%{_libdir}/libmedia-utils.so.0 +%{_libdir}/libmedia-utils.so.0.0.0 + +%files -n libmedia-utils-devel +%defattr(-,root,root,-) +%{_libdir}/pkgconfig/libmedia-utils.pc +%{_includedir}/media-utils/*.h + +%changelog +* Mon Oct 15 2012 Hyunjun Ko - 0.1.97 +- Fix a bug in db thread + +* Wed Oct 10 2012 Hyunjun Ko - 0.1.96 +- Some apis are added : media_db_request_update_db_batch / start / end + +* Mon Sep 10 2012 Haejeong Kim - 0.1.86 +- Make new thread for DB write. Only Media server can update db + +* Mon Aug 06 2012 Yong Yeon Kim - 0.1.86 +- add notification subscribe function for application +- fix bug : once validity checking time, call insert_item_batch two times. +- add MS_SAFE_FREE Macro, modify check value after using snprintf by secure coding guide +- change macro name MS_PHONE_ROOT_PATH, MS_MMC_ROOT_PATH +- make reference directory list by each thread + +* Tue Jul 03 2012 Yong Yeon Kim - 0.1.80 +- manage db handle by plug-in + +* Wed Jun 27 2012 Yong Yeon Kim - 0.1.79 +- If item exists in media db, return directly + +* Tue Jun 26 2012 Yong Yeon Kim - 0.1.78 +- change modified file updating routine (delete & insert -> refresh) +- modify return error type of media_file_register + diff --git a/reset_mediadb.sh b/reset_mediadb.sh new file mode 100755 index 0000000..1061599 --- /dev/null +++ b/reset_mediadb.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +if [ $# -ne 1 ] +then + echo 'Usage : reset_mediadb.sh [phone|sd|all]' + exit +fi + +if [ $1 = "phone" ] +then + vconftool set -f -t int db/filemanager/dbupdate "0" + killall media-server +fi + +if [ $1 = "sd" ] +then + vconftool set -f -t string db/private/mediaserver/mmc_info "" + killall media-server +fi + +if [ $1 = "all" ] +then + vconftool set -f -t int db/filemanager/dbupdate "0" + vconftool set -f -t string db/private/mediaserver/mmc_info "" + killall media-server +fi + + -- 2.7.4