From: HyungKyu Song Date: Fri, 15 Feb 2013 15:54:06 +0000 (+0900) Subject: Tizen 2.0 Release X-Git-Tag: accepted/tizen_2.0/20130215.202215^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a5896b154f6032739feb669fd897b415748729fc;p=platform%2Fcore%2Fappfw%2Fapp2sd.git Tizen 2.0 Release --- diff --git a/AUTHORS b/AUTHORS new file mode 100755 index 0000000..ead8dbd --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Garima Shrivastava diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..ed20cfa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,53 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +#SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) +PROJECT(app2ext C) + +SET(VERSION_MAJOR 0) +SET(VERSION "${VERSION_MAJOR}.4.2") + +#Add your submodule directory name +ADD_SUBDIRECTORY(plugin/app2sd) +### Required packages +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED dlog) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +pkg_check_modules(libpkgs REQUIRED dlog) + +FOREACH(flag ${libpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +### Local include directories +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/inc ${CMAKE_SOURCE_DIR}/src) + +## build app2ext library +SET(app2ext_dir "${CMAKE_SOURCE_DIR}") +SET(app2ext_inc_dir "${app2ext_dir}/inc") +SET(app2ext_src_dir "${app2ext_dir}/src") +SET(APP2EXT "app2ext") +SET(libapp2ext_SOURCES ${app2ext_src_dir}/app2ext_interface.c) +SET(libapp2ext_LDFLAGS " -L/usr/lib -module -avoid-version -ldl ") +SET(libapp2ext_CFLAGS " ${CFLAGS} -fPIC -I${app2ext_inc_dir} ") + +ADD_LIBRARY(${APP2EXT} SHARED ${libapp2ext_SOURCES}) +SET_TARGET_PROPERTIES(${APP2EXT} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${APP2EXT} PROPERTIES VERSION ${VERSION}) +SET_TARGET_PROPERTIES(${APP2EXT} PROPERTIES COMPILE_FLAGS "${libapp2ext_CFLAGS}") +TARGET_LINK_LIBRARIES(${APP2EXT} ${libpkgs_LDFLAGS}) + +SET(CMAKE_INSTALL_PREFIX "/usr") +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + + +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/app2sd.pc.in ${CMAKE_BINARY_DIR}/app2sd.pc @ONLY) + +INSTALL(TARGETS ${APP2EXT} DESTINATION lib COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/app2sd.pc DESTINATION lib/pkgconfig) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/inc/app2ext_interface.h DESTINATION include) + diff --git a/app2sd.manifest b/app2sd.manifest new file mode 100755 index 0000000..ec5cd53 --- /dev/null +++ b/app2sd.manifest @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app2sd.pc.in b/app2sd.pc.in new file mode 100755 index 0000000..bc90238 --- /dev/null +++ b/app2sd.pc.in @@ -0,0 +1,12 @@ +# Package information for app2sd +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: app2sd +Description: The app2sd Library +Version: 1.1.0 +Requires: vconf dlog +Cflags: -I${includedir} +Libs: -L${libdir} -lapp2sd -lapp2ext diff --git a/debian/app2sd-dev.install.in b/debian/app2sd-dev.install.in new file mode 100644 index 0000000..258b9f0 --- /dev/null +++ b/debian/app2sd-dev.install.in @@ -0,0 +1,2 @@ +@PREFIX@/include/app2sd_interface.h +@PREFIX@/lib/pkgconfig/*.pc diff --git a/debian/app2sd.install.in b/debian/app2sd.install.in new file mode 100644 index 0000000..bf766f0 --- /dev/null +++ b/debian/app2sd.install.in @@ -0,0 +1 @@ +@PREFIX@/lib/*.so* diff --git a/debian/changelog b/debian/changelog new file mode 100755 index 0000000..0d77b89 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,8 @@ +app2sd (0.2.1) unstable; urgency=low + + * Initial release + * Git: slp/pkgs/a/app2sd + * Tag: app2sd_0.2.1 + + -- Jaeho Lee Thu, 24 May 2012 12:04:51 +0530 + diff --git a/debian/compat b/debian/compat new file mode 100755 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100755 index 0000000..7bf93c6 --- /dev/null +++ b/debian/control @@ -0,0 +1,27 @@ +Source: app2sd +Section: devel +Priority: extra +Maintainer: Garima Shrivastava , Jaeho Lee +Build-Depends: debhelper (>= 5),libssl-dev, libslp-setting-dev, libslp-db-util-dev +Standards-Version: 3.7.2 + +Package: app2sd +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: + +Package: app2sd-dev +Architecture: any +Depends: app2sd (= ${Source-Version}) +Description: App2sd dev package + +Package: app2sd-doc +Architecture: all +Description: + +Package: app2sd-dbg +Section: debug +Architecture: any +Depends: app2sd (= ${Source-Version}) +Description: App2sd dbg package + diff --git a/debian/copyright b/debian/copyright new file mode 100755 index 0000000..37b94ac --- /dev/null +++ b/debian/copyright @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ diff --git a/debian/dirs b/debian/dirs new file mode 100755 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..f902937 --- /dev/null +++ b/debian/rules @@ -0,0 +1,126 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_GNU_OS) + +CFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +# architecture is not arm +ifneq (, $(findstring arm, $(DEB_HOST_ARCH))) + # do something here +else + # do something here for arm +endif + +CFLAGS += -fvisibility=hidden -fPIC +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed + +CMAKE_TMP_DIR = $(CURDIR)/cmake_tmp + +config.status: + +configure: configure-stamp + +configure-stamp: + dh_testdir + mkdir -p $(CMAKE_TMP_DIR); + export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CMAKE_TMP_DIR) && cd $(CMAKE_TMP_DIR); CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX=$(PREFIX) + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + # Add here commands to compile the package. + cd $(CMAKE_TMP_DIR) && $(MAKE) all + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f *-stamp + + rm -rf $(CMAKE_TMP_DIR) + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/ncurses. + cd $(CMAKE_TMP_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs +# dh_installdocs + dh_installexamples + dh_install --list-missing --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=app2sd-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/doc/images/SLP_app2ext_PG_image01.png b/doc/images/SLP_app2ext_PG_image01.png new file mode 100755 index 0000000..e69de29 diff --git a/doc/images/app2ext_diag.png b/doc/images/app2ext_diag.png new file mode 100755 index 0000000..137eaf3 Binary files /dev/null and b/doc/images/app2ext_diag.png differ diff --git a/doc/images/app2ext_install_diag.png b/doc/images/app2ext_install_diag.png new file mode 100755 index 0000000..6fd73ee Binary files /dev/null and b/doc/images/app2ext_install_diag.png differ diff --git a/doc/images/app2ext_uninstall_diag.png b/doc/images/app2ext_uninstall_diag.png new file mode 100755 index 0000000..2e61c71 Binary files /dev/null and b/doc/images/app2ext_uninstall_diag.png differ diff --git a/inc/SLP_app2ext_PG.h b/inc/SLP_app2ext_PG.h new file mode 100755 index 0000000..48c0b8a --- /dev/null +++ b/inc/SLP_app2ext_PG.h @@ -0,0 +1,65 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jyotsna Dhumale + * + * 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. + * + */ + +/** + * + * @ingroup SLP_PG + * @defgroup app2ext_PG App2Ext + * @{ + +

Introduction

+App2Ext is a feature that enables package installers to install applications on external storage like SD card, Micro USB flash drive or Cloud. +It also provides option to move installed applications from external memory to internal memory and vice versa. + +

App2Ext process view

+\image html app2ext_diag.png "Picture 1. App2Ext Process View Diagram" +\image rtf app2ext_diag.png "Picture 1. App2Ext Process View Diagram" + +

Installation to SD Card

+Package installer should call the App2Ext's Init API to initialize SD plug-in. Once the plug-in initialization is done App2Ext returns a storage handle to the Package installer. Package installer should then call the pre-install setup API with respect to the storage handle which will be mapped to app2sd's pre-install API. The App2Ext Pre-install API performs the setup required for the installation based on the external storage type. +After pre-install setup is done Package installer can proceed with the installation of the application. When package installation is completed by the package installer, post-install setup API should be called. This API removes the setup created for installation during pre-install API. + +Refer to Picture 2. for flow diagram. + +

Installation Setup Flow for App2SD plug-in

+\image html app2ext_install_diag.png "Picture 2. Installation on SD card Flow Diagram" +\image rtf app2ext_install_diag.png "Picture 2. Installation on SD card Flow Diagram" + +

Un-installation from SD Card

+Package installer should call the App2Ext's Init API to initialize SD plug-in. Once the plug-in initialization is done App2Ext returns a storage handle to the Package installer. Package installer should then call the pre-uninstall setup API with respect to the storage handle which will be mapped to app2sd's pre-uninstall API. Pre-uninstall API performs the setup required for the package un-installation based on the external storage type. +After pre-uninstall setup is done Package installer can proceed with un-installation of the package. When package un-installation is completed by the package installer, post-uninstall setup API should be called. This API removes the setup created for un-installation during pre-uninstall API. + +Refer to Picture 3. for flow diagram. + +

Un-installation Setup Flow for App2SD plug-in

+\image html app2ext_uninstall_diag.png "Picture 3. Un-installation from SD card Flow Diagram" +\image rtf app2ext_uninstall_diag.png "Picture 3. Un-installation from SD card Flow Diagram" + + +

API list and description

+
    +
  • app2ext_init() : Initialize plug-in based on storage type
  • +
  • app2ext_deinit() : De-initialize plug-in
  • +
  • app2ext_get_app_location() : Returns application current location
  • +
+ + * @} + */ diff --git a/inc/app2ext_interface.h b/inc/app2ext_interface.h new file mode 100755 index 0000000..fc11918 --- /dev/null +++ b/inc/app2ext_interface.h @@ -0,0 +1,402 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jyotsna Dhumale + * + * 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 __APP2EXT_INTERFACE_H__ +#define __APP2EXT_INTERFACE_H__ + +/** + * @file app2ext_interface.h + * @version 0.5 + * @brief This file declares API of app2ext library + */ +/** + * @addtogroup APPLICATION_FRAMEWORK + * @{ + * + * @defgroup app2ext + * @version 0.5 + * + * @section Header to use them: + * @code + * #include + * @endcode + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef API +#define API __attribute__ ((visibility("default"))) +#endif + +#include +#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "APP2EXT" + +#ifdef _DEBUG_MODE_ +#define app2ext_print(fmt, arg...) LOGD(fmt,##arg) +#else +#define app2ext_print(FMT, ARG...) SLOGD(FMT,##ARG); +#endif + +#define APP2EXT_SUCCESS 0 +#define MMC_PATH "/opt/storage/sdcard" +#define APP2SD_PATH MMC_PATH"/app2sd/" +#define APP_INSTALLATION_PATH "/opt/usr/apps/" + +/** + * Enum for application installation location + */ +typedef enum app2ext_install_location_t { + APP2EXT_INTERNAL_MEM = 0, + APP2EXT_SD_CARD, + APP2EXT_MICRO_USB, + APP2EXT_CLOUD, + APP2EXT_NOT_INSTALLED +} app2ext_install_location; + +/** + * Enum for installation/upgrade status[success/failure] + */ +typedef enum app2ext_status_t { + APP2EXT_STATUS_FAILED = 1, + APP2EXT_STATUS_SUCCESS +} app2ext_status; + +/** + * Enum for directory type + */ +typedef enum app2ext_dir_type_t { + APP2EXT_DIR_RO, + APP2EXT_DIR_RW, +} app2ext_dir_type; + +/** + * Enum for move command + * @see app2sd_move_installed_app() + */ +typedef enum app2ext_move_type_t { + APP2EXT_MOVE_TO_EXT = 1, + APP2EXT_MOVE_TO_PHONE +} app2ext_move_type; + +/** + * Enum for error codes + */ +typedef enum app2ext_error_t { + APP2EXT_ERROR_INVALID_ARGUMENTS = 2, + APP2EXT_ERROR_MOVE, + APP2EXT_ERROR_PRE_UNINSTALL, + APP2EXT_ERROR_MMC_STATUS, + APP2EXT_ERROR_DB_INITIALIZE, + APP2EXT_ERROR_SQLITE_REGISTRY, + APP2EXT_ERROR_PASSWD_GENERATION, + APP2EXT_ERROR_MMC_INFORMATION, + APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY, + APP2EXT_ERROR_DELETE_DIRECTORY, + APP2EXT_ERROR_CREATE_SYMLINK, + APP2EXT_ERROR_CREATE_DIRECTORY, + APP2EXT_ERROR_DELETE_LINK_FILE, + APP2EXT_ERROR_PKG_EXISTS, + APP2EXT_ERROR_ACCESS_FILE, + APP2EXT_ERROR_OPEN_DIR, + APP2EXT_ERROR_ALREADY_FILE_PRESENT, + APP2EXT_ERROR_FILE_ABSENT, + APP2EXT_ERROR_STRCMP_FAILED, + APP2EXT_ERROR_INVALID_PACKAGE, + APP2EXT_ERROR_CREATE_DIR_ENTRY, + APP2EXT_ERROR_PASSWORD_GENERATION, + APP2EXT_ERROR_COPY_DIRECTORY, + APP2EXT_ERROR_INVALID_CASE, + APP2EXT_ERROR_SYMLINK_ALREADY_EXISTS, + APP2EXT_ERROR_APPEND_HASH_TO_FILE, + APP2EXT_ERROR_CREATE_DEVICE, + APP2EXT_ERROR_DO_LOSETUP, + APP2EXT_ERROR_CREATE_FS, + APP2EXT_ERROR_MOUNT_PATH, + APP2EXT_ERROR_CLEANUP, + APP2EXT_ERROR_MOUNT, + APP2EXT_ERROR_REMOUNT, + APP2EXT_ERROR_PIPE_CREATION, + APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE, + APP2EXT_ERROR_VCONF_REGISTRY, + APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE, + APP2EXT_ERROR_UNMOUNT, + APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE, + APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE, + APP2EXT_ERROR_ALREADY_MOUNTED, + APP2EXT_ERROR_PLUGIN_INIT_FAILED, + APP2EXT_ERROR_PLUGIN_DEINIT_FAILED +} app2ext_error; + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called before application is to be installed. + * + * @param[in] appname application package name which is to be installed + * @param[in] dir_list directory structure of the application + * This should be polulated by the package manager + * before calling pre_install and should be freed after + * pre_install returns. + * Each node of dir_list is of type app2ext_dir_details + * which has members Name(dirname) and Type (RO/RW) + * For eg for rpm the dir_list should be populated with + * nodes like : (lib, APP2EXT_DIR_RO), (res, APP2EXT_DIR_RO), + (bin, APP2EXT_DIR_RO), (data, APP2EXT_DIR_RW) + * @param[in] size Size of the application + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_pre_install)(const char *appname, GList* dir_list, int size); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called after application installation. + * + * @param[in] appname application package name which is to be installed + * @param[in] install_status Installation status (Success/Failure) + * [ Enum :APP2EXT_STATUS_SUCCESS, + * APP2EXT_STATUS_FAILED] + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_post_install)(const char *appname, app2ext_status install_status); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called before application upgrade. + * + * @param[in] appname application package name which is to be upgraded + * @param[in] dir_list directory structure of the application + * This should be polulated by the package manager + * before calling pre_upgrade and should be freed after + * pre_upgrade returns. + * Each node of dir_list is of type app2ext_dir_details + * which has members Name(dirname) and Type (RO/RW) + * For eg for rpm the dir_list should be populated with + * nodes like : (lib, APP2EXT_DIR_RO), (res, APP2EXT_DIR_RO), + (bin, APP2EXT_DIR_RO), (data, APP2EXT_DIR_RW) + * @param[in] size Size of the application + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_pre_upgrade)(const char *appname, GList* dir_list, int size); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called before application upgradation. + * + * @param[in] appname application package name which is to be upgraded + * @param[in] upgrade_status Upgrade status (Success/Failure) + * [ Enum :APP2EXT_STATUS_SUCCESS, + * APP2EXT_STATUS_FAILED] + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_post_upgrade)(const char *appname, app2ext_status upgrade_status); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called before application uninstallation. + * + * @param[in] appname application package name which is to be uninstalled + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_pre_uninstall)(const char *appname); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called after application uninstallation. + * + * @param[in] appname application package name which is to be uninstalled + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_post_uninstall)(const char *appname); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called when application is to be moved from extrenal memory + *to internal memory or vice versa. + * + * @param[in] appname application package name which is to be moved + * @param[in] dir_list directory structure of the application + * This should be polulated by the package manager + * before calling move and should be freed after + * move returns. + * Each node of dir_list is of type app2ext_dir_details + * which has members Name(dirname) and Type (RO/RW) + * For eg for rpm the dir_list should be populated with + * nodes like : (lib, APP2EXT_DIR_RO), (res, APP2EXT_DIR_RO), + (bin, APP2EXT_DIR_RO), (data, APP2EXT_DIR_RW) + * @param[in] move_type move type + * [Enum: APP2EXT_MOVE_TO_EXT, APP2EXT_MOVE_TO_PHONE] + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_move)(const char *appname, GList* dir_list, app2ext_move_type move_type); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called to enable application before application launch. + * + * @param[in] appname application package name which is to be enabled + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_enable)(const char *appname); + +/** + * @brief :This function type is for a function that is implemented by plugin + * and called to disable application before application exit. + * + * @param[in] appname application package name which is to be disabled + * @return 0 if success, error code(>0) if fail + */ +typedef int (*app2ext_disable)(const char *appname); + +/** + * This structure defines the app2ext interfaces. Plugins have to implement these functions + */ +typedef struct app2ext_interface_t{ + app2ext_pre_install pre_install; + app2ext_post_install post_install; + app2ext_pre_upgrade pre_upgrade; + app2ext_post_upgrade post_upgrade; + app2ext_pre_uninstall pre_uninstall; + app2ext_post_uninstall post_uninstall; + app2ext_move move; + app2ext_enable enable; + app2ext_disable disable; +} app2ext_interface; + +/** + * This structure defines app2ext handle .Each storage type maps to a different plugin + * type : storage type + * plugin_handle : plugin handle + */ +typedef struct { + app2ext_install_location type; + void *plugin_handle; + app2ext_interface interface; +} app2ext_handle; + +/** + * This structure defines directory details + * name : directory name + * type : permission (rw/ro) + */ +typedef struct { + char * name; + app2ext_dir_type type; +} app2ext_dir_details; + +/** + * @brief : This API initializes the appropriate plugin based on storage type. + * It should be called before installation/uninstallation/upgrade + * @param[in] storage_type Location where package should be installed + * [Ex: SD card, MicroUSB, Cloud] + * @return app2ext_handle pointer if success, NULL if fail + * + @code + #include + app2ext_handle *handle = NULL; + GLIst *dir_list = NULL; + handle = app2ext_init(APP2EXT_SD_CARD); //Initializes SD card plug-in + if(handle) + { + printf("\n SUCCESS"); + // Perform package install/uninstall/upgrade/move here + // Packge install example + // Package manager should polulate dir_list with directory structure information of the package + ret = handle->interface.pre_install("com.samsung.calculator", dir_list, 20); + if (ret) { + printf("\n TC : pre app install API fail. Reason %s", error_list[ret]); + return -1; + } + + // Package manager installs the package + + ret = handle->interface.post_install("com.samsung.calculator", APP2EXT_STATUS_SUCCESS); + if (ret) { + printf("\n TC : post app install API fail Reason %s", error_list[ret]); + + return -1; + } + // Package manager should free dir_list + return; + } else + printf("\n FAILURE"); + @endcode + */ +API app2ext_handle *app2ext_init(int storage_type); + +/** + * @brief : This API deinitializes the plugin + * This should be called when use of the plugin is completed + * @param[in] handle pointer to app2ext_handle which is to be deinitialized + * @pre Initialization is done for the storage handle + * @return 0 if success, error code(>0) if fail + * + @code + #include + app2ext_handle *handle = NULL; + handle = app2ext_init(APP2EXT_SD_CARD); //Initializes SD card plug-in + int ret = -1; + ret = app2ext_deinit(handle); // De-initializes the SD plugin + if(!ret) + { + printf("\n SUCCESS"); + } + else + printf("\n FAILURE"); + @endcode + */ +API int app2ext_deinit(app2ext_handle *handle); + +/** + * @brief : This API returns the application location + * by refering to package manager DB + * This should be called to know location of an application + * @param[in] appname name of the application + * @return APP2EXT_SD_CARD if app is in SD card, + * APP2EXT_INTERNAL_MEM if app is in internal memory + * error code(>0) if fail + *@remarks see app2ext_install_location for more details + @code + #include +int ret = -1; + +ret = app2ext_get_app_location("com.samsung.calculator"); +if (ret == APP2EXT_SD_CARD) { + printf("\n app is in sd card "); +} else if (ret == APP2EXT_INTERNAL_MEM) { + printf("\n app is in internal memory "); +} else { + printf("\napp is not installed"); +} + @endcode + */ +API int app2ext_get_app_location(const char *appname); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/packaging/app2sd.spec b/packaging/app2sd.spec new file mode 100755 index 0000000..012342c --- /dev/null +++ b/packaging/app2sd.spec @@ -0,0 +1,60 @@ +Name: app2sd +Summary: Application installation on external memory +Version: 0.5 +Release: 8 +Group: TO_BE/FILLED_IN +License: Apache2.0 +Source0: %{name}-%{version}.tar.gz + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(libssl) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(db-util) +BuildRequires: cmake + +%description +Tizen application installation on external memory + +%package devel +Summary: Application install on external memory (devel) +Group: Development/Libraries +Requires: app2sd = %{version}-%{release} + +%description devel +Tizen application installation on external memory (devel) + +%prep +%setup -q + +%build +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest app2sd.manifest +%defattr(-,root,root,-) +%{_libdir}/libapp2ext.so.* +%{_libdir}/libapp2sd.so* + + +%files devel +%defattr(-,root,root,-) +%{_includedir}/app2ext_interface.h +%{_libdir}/pkgconfig/app2sd.pc +%{_libdir}/libapp2sd.so +%{_libdir}/libapp2ext.so + + + diff --git a/plugin/app2sd/CMakeLists.txt b/plugin/app2sd/CMakeLists.txt new file mode 100755 index 0000000..ceff836 --- /dev/null +++ b/plugin/app2sd/CMakeLists.txt @@ -0,0 +1,44 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(app2sd C) + +### Required packages +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED libssl dlog openssl db-util) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +pkg_check_modules(libpkgs REQUIRED libssl dlog openssl db-util) + +FOREACH(flag ${libpkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +### Local include directories +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/inc ${CMAKE_SOURCE_DIR}/src) + +## build app2sd library +SET(app2sd_dir "${CMAKE_SOURCE_DIR}/plugin/app2sd") +SET(app2sd_inc_dir "${app2sd_dir}/inc") +SET(app2sd_src_dir "${app2sd_dir}/src") +SET(APP2SD "app2sd") +SET(libapp2sd_SOURCES ${app2sd_src_dir}/app2sd_internals.c ${app2sd_src_dir}/app2sd_interface.c ${app2sd_src_dir}/app2sd_internals_registry.c ${app2sd_src_dir}/app2sd_internals_utils.c) +SET(libapp2sd_LDFLAGS " -L/usr/lib -lcrypto -module -avoid-version ") +SET(libapp2sd_CFLAGS " ${CFLAGS} -fPIC -I${app2sd_inc_dir} ") + +ADD_LIBRARY(${APP2SD} SHARED ${libapp2sd_SOURCES}) +SET_TARGET_PROPERTIES(${APP2SD} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${APP2SD} PROPERTIES VERSION ${VERSION}) +SET_TARGET_PROPERTIES(${APP2SD} PROPERTIES COMPILE_FLAGS "${libapp2sd_CFLAGS}") +TARGET_LINK_LIBRARIES(${APP2SD} ${libpkgs_LDFLAGS}) + +SET(CMAKE_INSTALL_PREFIX "/usr") +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + + +INSTALL(TARGETS ${APP2SD} DESTINATION lib COMPONENT RuntimeLibraries) + + diff --git a/plugin/app2sd/inc/SLP_app2sd_PG.h b/plugin/app2sd/inc/SLP_app2sd_PG.h new file mode 100755 index 0000000..4933bc1 --- /dev/null +++ b/plugin/app2sd/inc/SLP_app2sd_PG.h @@ -0,0 +1,74 @@ +/* + * app2sd + * + * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * 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. + * + */ + +/** + * + * @ingroup SLP_PG + * @defgroup app2sd_PG App2sd + * @{ + +

Introduction

+App2sd is a feature that enables package installers to install applications on sdcard. +It also provides API to move installed applications from sd card to internal memory and vice versa. +App2sd provides an API for validating the integrity of the package before launching by the launchpad. + +

App2sd process view

+\image html app2sd_diag.png "Picture 1. Process View Diagram" +\image rtf app2sd_diag.png "Picture 1. Process View Diagram" + +

Installation to SD Card

+Package installer should call the App2sd pre-install setup API before installation. +This API creates directory structure in SD card. +Refer to Picture 2. for flow diagram. + +

App2sd Installation Setup Flow

+\image html app2sd_install_diag.png "Picture 2. Installation Flow Diagram" +\image rtf app2sd_install_diag.png "Picture 2. Installation Flow Diagram" + +

Uninstallation to SD Card

+Package installer should call the App2sd pre-uninstall setup API before uninstallation. +Once the uninstallation is done by the package installer +then App2sd post-uninstall setup API should be called. +This API will clean up the directory structure and remove password from sqlite db. +Refer to Picture 3. for flow diagram. +

App2sd Uninstallation Setup Flow

+\image html app2sd_uninstall_diag.png "Picture 3. Uninstallation Flow Diagram" +\image rtf app2sd_uninstall_diag.png "Picture 3. Uninstallation Flow Diagram" + +

API list and description

+
    +
  • app2sd_pre_app_install() : Pre app installation setup.
  • +
  • app2sd_post_app_install() : Post app installation setup.
  • +
  • app2sd_pre_app_upgrade() : Pre app upgrade setup.
  • +
  • app2sd_post_app_upgrade() : Post app upgarde setup.
  • +
  • app2sd_pre_app_uninstall() : Pre app uninstall setup.
  • +
  • app2sd_post_app_uninstall() : Post app uninstall setup.
  • +
  • app2sd_move_installed_app() : Move installed application to/from sdcard
  • +
  • app2sd_get_app_install_location() : Get application installation location[external\internal memory].
  • +
  • app2sd_on_demand_setup_init() : Enables the application installed in sdcard.
  • +
  • app2sd_on_demand_setup_exit() : Disables the application installed in sdcard.
  • +
  • +
+ + * @} + */ diff --git a/plugin/app2sd/inc/app2sd_interface.h b/plugin/app2sd/inc/app2sd_interface.h new file mode 100755 index 0000000..a59cb9a --- /dev/null +++ b/plugin/app2sd/inc/app2sd_interface.h @@ -0,0 +1,404 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * 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 __APPTOSD_INTERFACE_H__ +#define __APPTOSD_INTERFACE_H__ + +/** + * @file app2sd_interface.h + * @version 0.2 + * @brief This file declares API of app2sd library + */ +/** + * @addtogroup APPLICATION_FRAMEWORK + * @{ + * + * @defgroup app2sd + * @version 0.2 + * + * @section Header to use them: + * @code + * #include + * @endcode + * + * @addtogroup app2sd + * @{ + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + + /** + * @brief : This API prepares the setup for installation in SD card. + * It should be called before actual installation is done. + * @pre vfat type sd card must be present. + * @post Installation is done by package installer. + Encryption password is saved in db /opt/dbspace/.app2sd.db + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + *This entry is parsed from application package control/manifest file. + * @param[in] dir_list directory structure of the application + * @param[in] size size of memory required by application(in MB). + *This entry is parsed from application package control/manifest file. + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + GList* dir_list = NULL; + // Package manager populates dir_list with directory structure information + ret= app2sd_pre_app_install + ("com.samsung.calculotor", dir_list, 10); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs installation + // app2sd_post_app_install() API should be called + return; + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_pre_app_install(const char *appname, + GList* dir_list, int size); + + /** + * @brief : This API does post installation operations after + * the installation in SD card + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + * @param[in] install_status Status of installation of package + *[ enum app2ext_status].If package installation failed then + * install_status= APP2EXT_STATUS_FAILURE else if installation + * was successful then install_status = APP2EXT_ISTATUS_SUCCESS. + * @pre Installation should be done by package installer. + * @return 0 if success, error code(>0) if fail + * @remark @see enum app2sd_install_status + * + * + @code + #include + int ret = -1; + ret= app2sd_pre_app_install + ("com.samsung.calculotor", APP2EXT_NATIVE_APP, 10); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs installation + //Package was installed successfully. + if(package_installation _success) + { + ret = app2sd_post_app_install + ("com.samsung.calculator",APP2EXT_STATUS_SUCCESS); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + return; + } + else + { + //Package installation failed + ret = app2sd_post_app_install + ("com.samsung.calculator",APP2EXT_STATUS_FAILURE); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + return; + } + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_post_app_install(const char *appname, + app2ext_status install_status); + + /** + * @brief : This API prepares the setup for upgradation of + * application package + * @pre vfat type sd card must be present. + * @post Upgradation is done by package installer. + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + * @param[in] dir_list directory structure of the application + * @param[in] size size of memory required by application(in MB). + *This entry is parsed from application package control/manifest file. + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + GList* dir_list = NULL; + // Package manager populates dir_list with directory structure information + ret= app2sd_pre_app_upgrade + ("com.samsung.calculator", dir_list, 10); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs upgradation + // app2sd_post_app_upgrade() API should be called + return; + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_pre_app_upgrade(const char *appname, + GList* dir_list, int size); + + /** + * @brief : This API does post upgradation operations after + * the installation in SD card + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + * @param[in] install_status Status of installation of package + *[ enum app2extl_status].If package upgradation failed then + * upgrade_status= APP2EXT_STATUS_FAILURE else if upgradation + * was successful then upgrade_status = APP2EXT_STATUS_SUCCESS. + * @pre Upgradation should be done by package installer. + * @return 0 if success, error code(>0) if fail + * @remark @see enum app2ext_status + * + * + @code + #include + int ret = -1; + ret= app2sd_pre_app_upgrade + ("com.samsung.calculator", APP2EXT_NATIVE_APP, 10); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs upgradation + //Package was upgraded successfully. + if(package_upgradation _success) + { + ret = app2sd_post_app_upgrade + ("com.samsung.calculator",APP2EXT_STATUS_SUCCESS); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + return; + } + else + { + //Package upgradation failed + ret = app2sd_post_app_upgrade + ("com.samsung.calculator",APP2EXT_STATUS_FAILURE); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + return; + } + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_post_app_upgrade(const char *appname, + app2ext_status upgrade_status); + + /** + * @brief: This API prepares the setup for uninstallation + * @pre Package must be installed in sdcard. + * @post Package is uninstalled by the package installer. + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + ret= app2sd_pre_app_uninstall + ("com.samsung.calculator"); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs uninstallation + // app2sd_post_app_uninstall() API should be called + return; + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_pre_app_uninstall(const char *appname); + + /** + * @brief This API removes the resources created during + app2sd setup.It is called after uninstallation. + * @pre Package must be uninstalled . + * @post Encryption password is removed from sqlite db. + * @param[in] appname application package name + * [Ex: com.samsung.calculator] + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + ret= app2sd_pre_app_uninstall + ("com.samsung.calculator"); + if(!ret) + { + printf("\n SUCCESS"); + // Package installer performs uninstallation + ret = app2sd_post_app_uninstall("com.samsung.calculator"); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + return; + } + else + printf("\n FAILURE"); + @endcode + */ + API int app2sd_post_app_uninstall(const char *appname); + + /** + * @brief : This API moves the package from sd card + to internal memory and vice versa. + * @param[in] pkgid application package id + * [Ex: com.samsung.calculator] + * @param[in] move_type Move type[enum app2ext_move_type] + * [sd card to internal/internal to sd card] + * @param[in] dir_list directory structure of the application + * @pre Package must be installed and its installation + * location should be known.Use app2sd_get_app_install_location() + * to get installation location. + * @see app2sd_get_app_install_location(). + * @post Package is moved to new location. + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + GList* dir_list = NULL; + // Package manager populates dir_list with directory structure information + ret = app2sd_get_app_install_location("com.samsung.calculator"); + if(ret == APP2SD_INTERNAL_MEM) + { + ret= app2sd_move_installed_app("com.samsung.calculator", + dir_list, APP2EXT_MOVE_TO_EXT); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + } + else if(ret == APP2SD_EXTERNAL_MEM) + { + ret= app2sd_move_installed_app("com.samsung.calculator", + dir_list, APP2SD_MOVE_TO PHONE); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + } + @endcode + */ + API int app2sd_move_installed_app(const char *pkgid, + GList* dir_list, app2ext_move_type move_type); + + /** + * @brief : This API Enables the application in sd card + for use. This API should be called by AUL. + * @param[in] pkgid application package id + * [Ex: com.samsung.calculator] + * @pre Package must be installed + * @post application is enabled in SD card. + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + ret= app2sd_on_demand_setup_init("com.samsung.calculator"); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + } + @endcode + */ + API int app2sd_on_demand_setup_init(const char *pkgid); + + + /** + * @brief : This API Disables the application in sd card + . This API should be called by Launchpad callback which will be registered + during app launch for exit action of the application + * @param[in] pkgid application package id + * [Ex: com.samsung.calculator] + * @pre Package must be installed and enabled + * and application must be running in SD card + * @post application is disabked in SD card. + * @return 0 if success, error code(>0) if fail + * @remark None. + * + * + @code + #include + int ret = -1; + ret= app2sd_on_demand_setup_exit("com.samsung.calculator"); + if(!ret) + printf("\n SUCCESS"); + else + printf("\n FAILURE"); + } + @endcode + */ + API int app2sd_on_demand_setup_exit(const char *pkgid); + + /** + * @brief : This is the plug-in load function. + The plugin has to bind its functions to function pointers of storage handle + * @param[in/out] st_interface Specifies the storage interface. + * @return None + */ + API void app2ext_on_load(app2ext_interface *st_interface); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/plugin/app2sd/inc/app2sd_internals.h b/plugin/app2sd/inc/app2sd_internals.h new file mode 100755 index 0000000..c81ca7c --- /dev/null +++ b/plugin/app2sd/inc/app2sd_internals.h @@ -0,0 +1,183 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * 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 _APP2SD_INTERNAL_H +#define _APP2SD_INTERNAL_H + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif + +/*Include Headers*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DIR_PERMS (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) + +#define BUF_SIZE 256 +#define MEM_BUF_SIZE 5 /*Memory buffer size in MB*/ +#define PKG_BUF_SIZE 2 /*Memory buffer size in MB*/ + +/*Device entry defines*/ +#define DEV_MAJOR 7 + +#define FS_TYPE "ext4" + +typedef enum mount_type_t { + MOUNT_TYPE_RD = 0, + MOUNT_TYPE_RW, + MOUNT_TYPE_RW_NOEXEC, + MOUNT_TYPE_RD_REMOUNT, + MOUNT_TYPE_RW_REMOUNT +} mount_type; + +typedef enum app2sd_cmd_t { + APP2SD_PRE_INSTALL = 1, + APP2SD_POST_INSTALL, + APP2SD_PRE_UNINSTALL, + APP2SD_POST_UNINSTALL, + APP2SD_PRE_UPGRADE, + APP2SD_POST_UPGRADE, + APP2SD_APP_LAUNCH, + APP2SD_APP_TERMINATE, + APP2SD_MOVE_APP_TO_MMC, + APP2SD_MOVE_APP_TO_PHONE +} app2sd_cmd; + +/*This will store password in DB*/ +int _app2sd_set_passwod_in_db(const char *pkgid, const char *password); + +/*This will remove password from db*/ +int _app2sd_remove_password_from_db(const char *pkgid); + +/*This will fetch password from db*/ +char *_app2sd_get_passowrd_from_db(const char *pkgid); + +/*Checks whether mmc is present or not*/ +int _app2sd_check_mmc_status(void); + +/*this function is similar to system()*/ +int _xsystem(const char *argv[]); + +/*this function will return the free available memory on the SD Card*/ +int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem); + +/*Function to move the application from/to SD Card*/ +int _app2sd_move_app(const char *pkgid, app2ext_move_type move_cmd, GList* dir_list); + +/*utility to delete the directory*/ +int _app2sd_delete_directory(char *dirname); + +/*utility to calculate the size of a directory in MB*/ +unsigned long long _app2sd_calculate_dir_size(char *dirname); + +/*utility to calculate the size of a file in MB*/ +unsigned long long _app2sd_calculate_file_size(const char *filename); + +/*Utility to copy a directory*/ +int _app2sd_copy_dir(const char *src, const char *dest); + +/*Utility to rename a directory*/ +int _app2sd_rename_dir(const char *old_name, const char *new_name); + +/*Utility to create application directory structure entry as per package type*/ +int _app2sd_create_directory_entry(const char *pkgid, GList* dir_list); + +/* Utility to create symlinks */ +int _app2sd_create_symlink(char *pkgid); + +/*This function finds the associated device node for the app*/ +char *_app2sd_find_associated_device_node(const char *pkgid); + +/*This function does the loopback encryption for app*/ +char *_app2sd_do_loopback_encryption_setup(const char *pkgid); + +/*This function detaches the loopback device*/ +char *_app2sd_detach_loop_device(const char *device); + +/*This function finds loopback device associated with the app*/ +char *_app2sd_find_associated_device(const char *mmc_app_path); + +/*This function creates loopback device*/ +int _app2sd_create_loopback_device(const char *pkgid, int size); + +/*This function deletes loopback device associated with the app*/ +int _app2sd_delete_loopback_device(const char *pkgid); + +/*This function creates ext4 FS on the device path*/ +int _app2sd_create_file_system(const char *device_path); + +/*This function mounts the app content on the device node*/ +int _app2sd_mount_app_content(const char *pkgid, const char *dev, + int mount_type, GList* dir_list, app2sd_cmd cmd); + +/*This function unmounts the app content */ +int _app2sd_unmount_app_content(const char *pkgid); + +/*This function removes the loopbck encryption setup for the app*/ +int _app2sd_remove_loopback_encryption_setup(const char *pkgid); + +/*This function updates loopback device size*/ +int _app2sd_update_loopback_device_size(const char *pkgid, + int size, GList* dir_list); + +/* This generates password */ +char *_app2sd_generate_password(const char *pkgid); + +/*This function encrypts device*/ +char *_app2sd_encrypt_device(const char *device, const char *pkgid, + char *passwd); + +/*This function finds free device*/ +char *_app2sd_find_free_device(void); + +/*This function initializes app2sd DB*/ +int _app2sd_initialize_db(); + +/*This function is used to get password from db*/ +char *_app2sd_get_password_from_db(const char *pkgid); + +/*This function removes password from db */ +int _app2sd_remove_password_from_db(const char *pkgid); + +/* This functions saved password in db */ +int _app2sd_set_password_in_db(const char *pkgid, + const char *passwd); + +#endif diff --git a/plugin/app2sd/src/app2sd_interface.c b/plugin/app2sd/src/app2sd_interface.c new file mode 100755 index 0000000..3e9fe76 --- /dev/null +++ b/plugin/app2sd/src/app2sd_interface.c @@ -0,0 +1,722 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * 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 + +int app2sd_pre_app_install(const char *pkgid, GList* dir_list, + int size) +{ + int ret = 0; + int free_mmc_mem = 0; + char *device_node = NULL; + char *devi = NULL; + char *result = NULL; + + /*Validate the function parameter recieved */ + if (pkgid == NULL || dir_list == NULL || size <= 0) { + app2ext_print("App2Sd Error : Invalid function arguments\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*Find available free memory in the MMC card */ + ret = _app2sd_get_available_free_memory(MMC_PATH, + &free_mmc_mem); + if (ret) { + app2ext_print("App2Sd Error : Unable to get available free memory in MMC %d\n", ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*If avaialalbe free memory in MMC is less than required size + 5MB , return error */ + if ((size + PKG_BUF_SIZE + MEM_BUF_SIZE) > free_mmc_mem) { + app2ext_print("Insufficient memory in MMC for application installation %d\n", ret); + return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY; + } + /*Create a loopback device */ + ret = _app2sd_create_loopback_device(pkgid, (size+PKG_BUF_SIZE)); + if (ret) { + app2ext_print("App2Sd Error : Package already present\n"); + return ret; + } + /*Perform Loopback encryption setup */ + device_node = _app2sd_do_loopback_encryption_setup(pkgid); + if (!device_node) { + app2ext_print("App2Sd Error : Loopback encryption setup failed\n"); + _app2sd_delete_loopback_device(pkgid); + return APP2EXT_ERROR_DO_LOSETUP; + } + /*Check whether loopback device is associated with device node or not */ + devi = _app2sd_find_associated_device_node(pkgid); + if (devi == NULL) { + app2ext_print("App2Sd Error : finding associated device node failed\n"); + ret = APP2EXT_ERROR_DO_LOSETUP; + goto FINISH_OFF; + } + + /*Format the loopback file system */ + ret = _app2sd_create_file_system(device_node); + if (ret) { + app2ext_print("App2Sd Error : creating FS failed failed\n"); + ret = APP2EXT_ERROR_CREATE_FS; + goto FINISH_OFF; + } + + /*Mount the loopback encrypted pseudo device on application installation path as with Read Write permission */ + ret =_app2sd_mount_app_content(pkgid, device_node, MOUNT_TYPE_RW, + dir_list, APP2SD_PRE_INSTALL); + if (ret) { + app2ext_print("App2Sd Error : mounting dev path to app install path failed\n"); + ret = APP2EXT_ERROR_MOUNT_PATH; + goto FINISH_OFF; + } + + /*Success */ + ret = APP2EXT_SUCCESS; + goto END; + +FINISH_OFF: + + if (device_node) { + result = _app2sd_detach_loop_device(device_node); + if (result) { + free(result); + result = NULL; + } + _app2sd_delete_loopback_device(pkgid); + } +END: + if (device_node) { + free(device_node); + device_node = NULL; + } + if (devi) { + free(devi); + devi = NULL; + } + return ret; +} + +int app2sd_post_app_install(const char *pkgid, + app2ext_status install_status) +{ + char *device_name = NULL; + char buf_dir[FILENAME_MAX] = { 0, }; + int ret = APP2EXT_SUCCESS; + /*Validate the function parameter recieved */ + if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED + || install_status > APP2EXT_STATUS_SUCCESS) { + app2ext_print("Invalid func parameters\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + sync(); //2 + /*Get the associated device node for SD card applicationer */ + device_name = _app2sd_find_associated_device_node(pkgid); + if (NULL == device_name) { + return APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE; + } + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + if (device_name) { + free(device_name); + device_name = NULL; + } + app2ext_print("Unable to unmount the app content %d\n", ret); + return APP2EXT_ERROR_UNMOUNT; + } + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + if (device_name) { + free(device_name); + device_name = NULL; + } + app2ext_print + ("Unable to Detach the loopback encryption setup for the application"); + return APP2EXT_ERROR_UNMOUNT; + } + if (device_name) { + free(device_name); + device_name = NULL; + } + + /*Take appropriate action based on installation + status of application package */ + if (install_status == APP2EXT_STATUS_FAILED) { + /*Delete the loopback device from the SD card */ + ret = _app2sd_delete_loopback_device(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : Unable to delete the loopback device from the SD Card\n"); + return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + ret = _app2sd_remove_password_from_db(pkgid); + + if (ret) { + app2ext_print + ("App2Sd Error : Unable to delete the password\n"); + } + + snprintf(buf_dir, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, pkgid); + + ret = _app2sd_delete_directory(buf_dir); + + if (ret) { + app2ext_print + ("App2Sd Error : Unable to delete the directory %s\n", + buf_dir); + } + + } + return ret; +} + +int app2sd_on_demand_setup_init(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char app_path[FILENAME_MAX] = { 0, }; + char *device_node = NULL; + char *result = NULL; + FILE *fp = NULL; + + /*Validate the function parameter recieved */ + if (pkgid == NULL) { + app2ext_print + ("App2Sd Error : Invalid function arguments to app launch setup\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + /*check app entry is there in sd card or not. */ + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + fp = fopen(app_path, "r+"); + if (fp == NULL) { + app2ext_print + ("App2SD Error: App Entry is not present in SD Card\n"); + return APP2EXT_ERROR_INVALID_PACKAGE; + } + fclose(fp); + result = (char *)_app2sd_find_associated_device(app_path); + /*process the string */ + if ((result!=NULL) && strstr(result, "/dev") != NULL) { + app2ext_print("App2SD Error! Already associated\n"); + free(result); + result = NULL; + return APP2EXT_ERROR_ALREADY_MOUNTED; + } + + /*Do loopback setup */ + device_node = _app2sd_do_loopback_encryption_setup(pkgid); + if (device_node == NULL) { + app2ext_print + ("App2Sd Error : loopback encryption setup failed\n"); + return APP2EXT_ERROR_DO_LOSETUP; + } + + /*Do mounting */ + ret = + _app2sd_mount_app_content(pkgid, device_node, MOUNT_TYPE_RD, + NULL, APP2SD_APP_LAUNCH); + if (ret) { + app2ext_print("App2Sd Error : Re-mount failed\n"); + if (device_node) { + free(device_node); + device_node = NULL; + } + return APP2EXT_ERROR_MOUNT_PATH; + } + if (device_node) { + free(device_node); + device_node = NULL; + } + return ret; +} + +int app2sd_on_demand_setup_exit(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char app_path[FILENAME_MAX] = { 0, }; + FILE *fp = NULL; + + /*Validate the function parameter recieved */ + if (pkgid == NULL) { + app2ext_print + ("App2Sd Error : Invalid function arguments to app launch setup\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*check app entry is there in sd card or not. */ + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + fp = fopen(app_path, "r+"); + if (fp == NULL) { + app2ext_print + ("App2SD Error: App Entry is not present in SD Card\n"); + return APP2EXT_ERROR_INVALID_PACKAGE; + } + fclose(fp); + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + app2ext_print + ("App2SD Error: Unable to unmount the SD application\n"); + return APP2EXT_ERROR_UNMOUNT; + } + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print("App2SD Error: Unable to remove loopback setup\n"); + return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + return ret; +} + +int app2sd_pre_app_uninstall(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char app_path[FILENAME_MAX] = { 0, }; + char *device_node = NULL; + FILE*fp = NULL; + + /*Validate the function parameter recieved */ + if (pkgid == NULL) { + app2ext_print + ("App2Sd Error : Invalid function arguments to app launch setup\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*check app entry is there in sd card or not. */ + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, pkgid); + fp = fopen(app_path, "r+"); + if (fp == NULL) { + app2ext_print + ("App2SD Error: App Entry is not present in SD Card\n"); + return APP2EXT_ERROR_INVALID_PACKAGE; + } + fclose(fp); + + /*Get the associated device node for SD card applicationer */ + device_node = _app2sd_find_associated_device_node(pkgid); + if (NULL == device_node) { + /*Do loopback setup */ + device_node = _app2sd_do_loopback_encryption_setup(pkgid); + + if (device_node == NULL) { + app2ext_print + ("App2Sd Error : loopback encryption setup failed\n"); + return APP2EXT_ERROR_DO_LOSETUP; + } + /*Do mounting */ + ret = + _app2sd_mount_app_content(pkgid, device_node, + MOUNT_TYPE_RW, NULL, + APP2SD_PRE_UNINSTALL); + + if (ret) { + app2ext_print("App2Sd Error : RW-mount failed\n"); + if (device_node) { + free(device_node); + device_node = NULL; + } + return APP2EXT_ERROR_MOUNT_PATH; + } + } else { + /*Do re-mounting */ + ret = + _app2sd_mount_app_content(pkgid, device_node, + MOUNT_TYPE_RW_REMOUNT, NULL, + APP2SD_PRE_UNINSTALL); + + if (ret) { + app2ext_print("App2Sd Error : Re-mount failed\n"); + if (device_node) { + free(device_node); + device_node = NULL; + } + return APP2EXT_ERROR_MOUNT_PATH; + } + } + if (device_node) { + free(device_node); + device_node = NULL; + } + return ret; +} + +/* +* app2sd_post_app_uninstall_setup +* Uninstall Application and free all the allocated resources +* Called after dpkg remove, It deallocates dev node and loopback +*/ +int app2sd_post_app_uninstall(const char *pkgid) +{ + char buf_dir[FILENAME_MAX] = { 0, }; + int ret = APP2EXT_SUCCESS; + int ret1 = APP2EXT_SUCCESS; + /*Validate the function parameter recieved */ + if (pkgid == NULL) { + app2ext_print + ("App2Sd Error : Invalid function arguments to Post Uninstall\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*Unmount the loopback encrypted pseudo device from the application installation path */ + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + app2ext_print("Unable to unmount the app content %d\n", ret); + return APP2EXT_ERROR_UNMOUNT; + } + /*Detach the loopback encryption setup for the application */ + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print + ("Unable to Detach the loopback encryption setup for the application"); + return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE; + } + /*Delete the loopback device from the SD card */ + ret = _app2sd_delete_loopback_device(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : Unable to delete the loopback device from the SD Card\n"); + return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + memset((void *)&buf_dir, '\0', FILENAME_MAX); + snprintf(buf_dir, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, pkgid); + ret1 = _app2sd_delete_directory(buf_dir); + if (ret1) { + app2ext_print + ("App2Sd Error : Unable to delete the directory %s\n", + buf_dir); + } + /*remove encryption password from DB */ + ret = _app2sd_initialize_db(); + if (ret) { + app2ext_print("\n app2sd db initialize failed"); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + ret = _app2sd_remove_password_from_db(pkgid); + if (ret) { + app2ext_print("cannot remove password from db \n"); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + return ret; +} + +int app2sd_move_installed_app(const char *pkgid, GList* dir_list, + app2ext_move_type move_type) +{ + int ret = 0; + + /*Validate function arguments*/ + if (pkgid == NULL || dir_list == NULL + || move_type < APP2EXT_MOVE_TO_EXT + || move_type > APP2EXT_MOVE_TO_PHONE) { + app2ext_print("App2Sd Error : Invalid function arguments\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + ret = _app2sd_move_app(pkgid, move_type, dir_list); + if (ret) { + app2ext_print("App2Sd Error : Unable to move application\n"); + return ret; + } + return ret; +} + +int app2sd_pre_app_upgrade(const char *pkgid, GList* dir_list, + int size) +{ + int ret = APP2EXT_SUCCESS; + char app_path[FILENAME_MAX] = { 0, }; + char *device_node = NULL; + unsigned long long curr_size = 0; + FILE *fp = NULL; + + /*Validate function arguments*/ + if (pkgid == NULL || dir_list == NULL || size<=0) { + app2ext_print + ("App2Sd Error : Invalid function arguments \n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*check app entry is there in sd card or not. */ + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + app2ext_print("App2Sd Log : Checking path %s\n", app_path); + fp = fopen(app_path, "r+"); + if (fp == NULL) { + app2ext_print + ("App2SD Error: App Entry is not present in SD Card\n"); + return APP2EXT_ERROR_INVALID_PACKAGE; + } + fclose(fp); + /*Get installed app size*/ + curr_size = _app2sd_calculate_file_size(app_path); + curr_size = (curr_size/1024)/1024; + + if (curr_size<=0) { + app2ext_print + ("App2SD Error: App Entry is not present in SD Card\n"); + return APP2EXT_ERROR_LOOPBACK_DEVICE_UNAVAILABLE; + } + if (curr_size APP2EXT_STATUS_SUCCESS) { + app2ext_print("Invalid func parameters\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + /*Get the associated device node for SD card applicationer */ + device_name = _app2sd_find_associated_device_node(pkgid); + if (NULL == device_name) { + return APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE; + } + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + if (device_name) { + free(device_name); + device_name = NULL; + } + app2ext_print("Unable to unmount the app content %d\n", ret); + return APP2EXT_ERROR_UNMOUNT; + } + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + if (device_name) { + free(device_name); + device_name = NULL; + } + app2ext_print + ("Unable to Detach the loopback encryption setup for the application"); + return APP2EXT_ERROR_UNMOUNT; + } + if (device_name) { + free(device_name); + device_name = NULL; + } + return ret; +} + +/** + * Reserved API for forced cleanup + * + */ +int app2sd_force_cleanup(const char *pkgid){ + char *device_name = NULL; + char buf_dir[FILENAME_MAX] = { 0, }; + int ret = APP2EXT_SUCCESS; + FILE *fp = NULL; + + /*Validate the function parameter recieved */ + if (pkgid == NULL) { + app2ext_print("invalid func parameters\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + memset((void *)&buf_dir, '\0', FILENAME_MAX); + snprintf(buf_dir, FILENAME_MAX, "%s%s", APP2SD_PATH, pkgid); + fp = fopen(buf_dir, "r+"); + if (fp == NULL) { + app2ext_print("\"%s\" not installed on SD Card\n", pkgid); + return APP2EXT_ERROR_INVALID_PACKAGE; + } + fclose(fp); + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + /*Get the associated device node for SD card applicationer */ + device_name = _app2sd_find_associated_device_node(pkgid); + if (NULL != device_name) { + free(device_name); + device_name = NULL; + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + app2ext_print("Unable to unmount the app content %d\n", ret); + return APP2EXT_ERROR_UNMOUNT; + } + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print + ("Unable to Detach the loopback encryption setup for the application"); + return APP2EXT_ERROR_UNMOUNT; + } + } + + memset((void *)&buf_dir, '\0', FILENAME_MAX); + snprintf(buf_dir, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, pkgid); + ret = _app2sd_delete_directory(buf_dir); + if (ret) { + app2ext_print + ("App2Sd Error : Unable to delete the directory %s\n", + buf_dir); + } + + /*remove passwrd from DB*/ + ret = _app2sd_initialize_db(); + if (ret) { + app2ext_print("\n app2sd db initialize failed"); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + ret = _app2sd_remove_password_from_db(pkgid); + if (ret) { + app2ext_print("cannot remove password from db \n"); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + return ret; +} + +/* This is the plug-in load function. The plugin has to bind its functions to function pointers of handle + @param[in/out] st_interface Specifies the storage interface. +*/ +void +app2ext_on_load(app2ext_interface *st_interface) +{ + /*Plug-in Binding.*/ + st_interface->pre_install= app2sd_pre_app_install; + st_interface->post_install= app2sd_post_app_install; + st_interface->pre_uninstall= app2sd_pre_app_uninstall; + st_interface->post_uninstall= app2sd_post_app_uninstall; + st_interface->pre_upgrade= app2sd_pre_app_upgrade; + st_interface->post_upgrade= app2sd_post_app_upgrade; + st_interface->move= app2sd_move_installed_app; + st_interface->enable= app2sd_on_demand_setup_init; + st_interface->disable= app2sd_on_demand_setup_exit; +} + diff --git a/plugin/app2sd/src/app2sd_internals.c b/plugin/app2sd/src/app2sd_internals.c new file mode 100755 index 0000000..e3942ea --- /dev/null +++ b/plugin/app2sd/src/app2sd_internals.c @@ -0,0 +1,1371 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +########### Internal APIs ################## + */ + +char *_app2sd_find_associated_device_node(const char *pkgid) +{ + char *ret_result = NULL; + char delims[] = ":"; + char *result = NULL; + char app_path[FILENAME_MAX] = { '\0' }; + + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + result = (char *)_app2sd_find_associated_device(app_path); + if (result == NULL) { + app2ext_print + ("App2SD Error! Unable to find the associated File\n"); + return NULL; + } + /*process the string*/ + if (strstr(result, "/dev") == NULL) { + app2ext_print + ("App2SD Error! Unable to find the associated File\n"); + return NULL; + } else { + ret_result = strtok(result, delims); + } + + return ret_result; + +} + +char *_app2sd_create_loopdevice_node(void) +{ + char *ret_result = NULL; + mode_t mode = DIR_PERMS; + int count = 0; + int ret = APP2EXT_SUCCESS; + char *result = NULL; + FILE *fp = NULL; + + result = (char *)_app2sd_find_free_device(); + /*validate the result */ + if (result == NULL || strstr(result, "/dev") == NULL) { + app2ext_print("No device found, creating device node...\n"); + + if (result) { + free(result); + result = NULL; + } + count = 0; + char dev_path[BUF_SIZE] = { 0, }; + snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count); + while ((fp = fopen(dev_path, "r+")) != NULL) { + count = count + 1; + snprintf(dev_path, BUF_SIZE, "/dev/loop%d", count); + app2ext_print("next dev path for checking is %s\n", + dev_path); + fclose(fp); + } + app2ext_print("Device node candidate is %s \n", dev_path); + dev_t dev_node; + dev_node = makedev(DEV_MAJOR, count); + if ((ret = mknod(dev_path, S_IFBLK | mode, dev_node)) < 0) { + app2ext_print + ("Error while creating the device node: errno is %d\n", + errno); + return NULL; + } + ret_result = (char *)malloc(strlen(dev_path) + 1); + if (ret_result == NULL) { + app2ext_print("Unable to allocate memory\n"); + return NULL; + } + memset(ret_result, '\0', strlen(dev_path) + 1); + memcpy(ret_result, dev_path, strlen(dev_path)); + } else { + ret_result = (char *)malloc(strlen(result) + 1); + if (ret_result == NULL) { + app2ext_print("Malloc failed!\n"); + free(result); + result = NULL; + return NULL; + } + memset(ret_result, '\0', strlen(result) + 1); + if (strlen(result) > 0) { + memcpy(ret_result, result, strlen(result) - 1); + } + free(result); + result = NULL; + + } + return ret_result; +} + +char *_app2sd_do_loopback_encryption_setup(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char *passwd = NULL; + char app_path[FILENAME_MAX] = { '\0' }; + char *result = NULL; + char *device_node = NULL; + if (pkgid == NULL) { + app2ext_print("App2Sd Error: Invalid argument\n"); + return NULL; + } + + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + /* Get password for loopback encryption */ + ret = _app2sd_initialize_db(); + if (ret) { + app2ext_print("\n app2sd db initialize failed"); + return NULL; + } + if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) { + passwd = (char *)_app2sd_generate_password(pkgid); + if (NULL == passwd) { + app2ext_print + ("App2Sd Error: Unable to generate password\n"); + return NULL; + } else { + app2ext_print("Password is %s\n", passwd); + if ((ret = _app2sd_set_password_in_db(pkgid, + passwd)) < 0) { + app2ext_print + ("App2Sd Error: Unable to save password\n"); + free(passwd); + passwd = NULL; + return NULL; + } + } + } + + /*Get Free device node*/ + device_node = _app2sd_create_loopdevice_node(); + if (NULL == device_node) { + free(passwd); + passwd = NULL; + app2ext_print + ("App2Sd Error: Unable to find free loopback node\n"); + return NULL; + } + result = (char *)_app2sd_encrypt_device(device_node, app_path, passwd); + if (result == NULL) { + app2ext_print("App2Sd Error: Encryption failed!\n\n"); + free(passwd); + passwd = NULL; + return NULL; + } else { + free(result); + result = NULL; + free(passwd); + passwd = NULL; + return device_node; + } +} + +char *_app2sd_do_loopback_duplicate_encryption_setup(const char *pkgid, const char * dup_appname) +{ + int ret = APP2EXT_SUCCESS; + char *passwd = NULL; + char app_path[FILENAME_MAX] = { '\0' }; + char *result = NULL; + char *device_node = NULL; + if (pkgid == NULL || dup_appname == NULL) { + app2ext_print("App2Sd Error: Invalid argument\n"); + return NULL; + } + + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + dup_appname); + /* Get password for loopback encryption */ + ret = _app2sd_initialize_db(); + if (ret) { + app2ext_print("\n app2sd db initialize failed"); + return NULL; + } + if ((passwd = _app2sd_get_password_from_db(pkgid)) == NULL) { + passwd = (char *)_app2sd_generate_password(pkgid); + if (NULL == passwd) { + app2ext_print + ("App2Sd Error: Unable to generate password\n"); + return NULL; + } else { + app2ext_print("Password is %s\n", passwd); + if ((ret = _app2sd_set_password_in_db(pkgid, + passwd)) < 0) { + app2ext_print + ("App2Sd Error: Unable to save password\n"); + free(passwd); + passwd = NULL; + return NULL; + } + } + + } + /*Get Free device node*/ + device_node = _app2sd_create_loopdevice_node(); + if (NULL == device_node) { + free(passwd); + passwd = NULL; + app2ext_print + ("App2Sd Error: Unable to find free loopback node\n"); + return NULL; + } + result = (char *)_app2sd_encrypt_device(device_node, app_path, passwd); + if (result == NULL) { + app2ext_print("App2Sd Error: Encryption failed!\n\n"); + free(passwd); + passwd = NULL; + return NULL; + } else { + if (strlen(result) == 0) { + free(result); + result = NULL; + free(passwd); + passwd = NULL; + return device_node; + } else { + app2ext_print("App2Sd Error: Error is %s\n", result); + free(result); + result = NULL; + free(passwd); + passwd = NULL; + return NULL; + } + } + return device_node; +} + +int _app2sd_remove_loopback_encryption_setup(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char *result = NULL; + char *dev_node = NULL; + if ((dev_node = _app2sd_find_associated_device_node(pkgid)) == NULL) { + app2ext_print("Unable to find the association\n"); + ret = APP2EXT_ERROR_FIND_ASSOCIATED_DEVICE_NODE; + } + result = (char *)_app2sd_detach_loop_device(dev_node); + if (result == NULL) { + app2ext_print("App2sd Error: Error in detaching\n"); + ret = APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE; + } else { + free(result); + result = NULL; + } + if (dev_node) { + free(dev_node); + dev_node = NULL; + } + return ret; +} + +int _app2sd_create_loopback_device(const char *pkgid, int size) +{ + int ret = APP2EXT_SUCCESS; + char command[FILENAME_MAX] = { 0, }; + mode_t mode = DIR_PERMS; + char external_storage_path[FILENAME_MAX] = { 0, }; + char buff[BUF_SIZE] = { 0, }; + char app_path[FILENAME_MAX] = { 0, }; + FILE *fp = NULL; + + if (NULL == pkgid || size <= 0) { + app2ext_print("App2Sd Error: Invalid argument\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + snprintf(command, FILENAME_MAX, "of=%s%s", APP2SD_PATH, + pkgid); + snprintf(buff, BUF_SIZE, "count=%d", size); + const char *argv1[] = + { "dd", "if=/dev/zero", command, "bs=1M", buff, NULL }; + snprintf(external_storage_path, FILENAME_MAX, "%s", + APP2SD_PATH); + ret = mkdir(external_storage_path, mode); + if (ret) { + if (errno != EEXIST) { + app2ext_print + ("App2sd Error : Create directory failed, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + } + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + if ((fp = fopen(app_path, "r+")) != NULL) { + app2ext_print("Application already exists %s\n", app_path); + fclose(fp); + return APP2EXT_ERROR_PKG_EXISTS; + } + + ret = _xsystem(argv1); + if (ret) { + app2ext_print("App2Sd Error : command \"%s\" failed \n", + command); + return ret; + } + return ret; +} + +int _app2sd_delete_loopback_device(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char loopback_device[FILENAME_MAX] = { 0, }; + + snprintf(loopback_device, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + + ret = unlink(loopback_device); + if (ret) { + if (errno == ENOENT) { + app2ext_print("Unable to access file %s\n", loopback_device); + } else { + app2ext_print("Unable to delete %s\n", loopback_device); + return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + } + return ret; +} + +int _app2sd_create_file_system(const char *device_path) +{ + int ret = APP2EXT_SUCCESS; + FILE *fp = NULL; + if (NULL == device_path) { + app2ext_print("App2Sd Error: invalid param [NULL]\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + /*Format the filesystem [create a filesystem]*/ + const char *argv[] = { "mkfs.ext4", device_path, NULL }; + fp = fopen(device_path, "r+"); + if (fp == NULL) { + app2ext_print + ("App2sd Error: Unable to access %s [System errono is %d.....%s]\n", + device_path, errno, strerror(errno)); + return APP2EXT_ERROR_ACCESS_FILE; + } else { + fclose(fp); + } + ret = _xsystem(argv); + if (ret) { + app2ext_print + ("App2Sd Error : creating file system failed [System error is %s\n", + strerror(errno)); + return APP2EXT_ERROR_CREATE_FS; + } + return ret; +} + +static int _app2sd_create_dir_with_link(const char *pkgid, + const char *dir_name) +{ + mode_t mode = DIR_PERMS; + int ret = APP2EXT_SUCCESS; + char app_dir_mmc_path[FILENAME_MAX] = { 0, }; + char app_dir_path[FILENAME_MAX] = { 0, }; + snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc/%s",APP_INSTALLATION_PATH, + pkgid, dir_name); + snprintf(app_dir_path, FILENAME_MAX, "%s%s/%s", APP_INSTALLATION_PATH, pkgid, + dir_name); + + ret = mkdir(app_dir_mmc_path, mode); + if (ret) { + if (errno != EEXIST) { + app2ext_print + ("App2sd Error : Create directory failed, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + } + + if ((ret = symlink(app_dir_mmc_path, app_dir_path)) < 0) { + if (errno == EEXIST) { + app2ext_print + ("App2sd : File with Symlink name present %s\n", + app_dir_path); + } else { + app2ext_print + ("A2Sd Error : Symbolic link creation failed, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_SYMLINK; + } + } + + return ret; +} + +int _app2sd_create_directory_entry(const char *pkgid, GList* dir_list) +{ + int ret = APP2EXT_SUCCESS; + char app_dir_path[FILENAME_MAX] = { 0, }; + GList *list = NULL; + app2ext_dir_details* dir_detail = NULL; + + snprintf(app_dir_path, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, + pkgid); + + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + ret = _app2sd_create_dir_with_link(pkgid, dir_detail->name); + if (ret) { + return ret; + } + } + list = g_list_next(list); + } + return APP2EXT_SUCCESS; +} + + +/* + * + * _app2sd_mount_app_content + This function is to create the path for mmc and mount the content +Example usage: _app2sd_mount_app_content("deb.com.samsung.helloworld","/dev/loop0",MOUNT_TYPE_RD) +*/ +int _app2sd_mount_app_content(const char *pkgid, const char *dev, + int mount_type, GList* dir_list, app2sd_cmd cmd) +{ + int ret = APP2EXT_SUCCESS; + mode_t mode = DIR_PERMS; + char app_dir_path[FILENAME_MAX] = { 0, }; + char app_dir_mmc_path[FILENAME_MAX] = { 0, }; + if (NULL == pkgid || NULL == dev) { + app2ext_print("App2Sd Error : Input param is NULL %s %s \n", + pkgid, dev); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + snprintf(app_dir_path, FILENAME_MAX, "%s%s", APP_INSTALLATION_PATH, pkgid); + ret = mkdir(app_dir_path, mode); + if (ret) { + if (errno != EEXIST) { + app2ext_print + ("App2Sd Error : Create directory failed, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + } + snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid); + ret = mkdir(app_dir_mmc_path, mode); + if (ret) { + if (errno != EEXIST) { + app2ext_print + ("App2Sd Error : Create directory failed, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + } + + switch (mount_type) { + case MOUNT_TYPE_RD: + { + if ((ret = + mount(dev, app_dir_mmc_path, FS_TYPE, + MS_MGC_VAL | MS_RDONLY, NULL)) < 0) { + app2ext_print + ("App2Sd Error : Read Only Mount failed [System Erro no is %d], dev is %s path is %s\n", + errno, dev, app_dir_mmc_path); + ret = APP2EXT_ERROR_MOUNT; + } + break; + } + case MOUNT_TYPE_RW: + { + if ((ret = + mount(dev, app_dir_mmc_path, FS_TYPE, MS_MGC_VAL, + NULL)) < 0) { + app2ext_print + ("App2Sd Error : Read Write Mount failed [System Erro no is %d]\n", + errno); + ret = APP2EXT_ERROR_MOUNT; + } + break; + } + case MOUNT_TYPE_RW_NOEXEC: + { + if ((ret = + mount(dev, app_dir_mmc_path, FS_TYPE, + MS_MGC_VAL | MS_NOEXEC, NULL)) < 0) { + app2ext_print + ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n", + errno); + ret = APP2EXT_ERROR_MOUNT; + } + break; + } + case MOUNT_TYPE_RD_REMOUNT: + { + if ((ret = + mount(dev, app_dir_mmc_path, FS_TYPE, + MS_MGC_VAL | MS_RDONLY | MS_REMOUNT, + NULL)) < 0) { + app2ext_print + ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n", + errno); + ret = APP2EXT_ERROR_MOUNT; + } + break; + } + case MOUNT_TYPE_RW_REMOUNT: + { + if ((ret = + mount(dev, app_dir_mmc_path, FS_TYPE, + MS_MGC_VAL | MS_REMOUNT, NULL)) < 0) { + app2ext_print + ("App2Sd Error : RWX Mount failed [System Erro no is %d]\n", + errno); + ret = APP2EXT_ERROR_MOUNT; + } + break; + } + + default: + { + app2ext_print("App2Sd Error: Invalid mount type\n"); + break; + } + } + if (cmd == APP2SD_PRE_INSTALL || cmd == APP2SD_MOVE_APP_TO_MMC) { + ret = _app2sd_create_directory_entry(pkgid, dir_list); + } + return ret; +} + +int _app2sd_unmount_app_content(const char *pkgid) +{ + int ret = APP2EXT_SUCCESS; + char app_dir_mmc_path[FILENAME_MAX] = { 0, }; + snprintf(app_dir_mmc_path, FILENAME_MAX, "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid); + if ((ret = umount(app_dir_mmc_path)) < 0) { + app2ext_print("Unable to umount the dir %s\n", strerror(errno)); + } + return ret; +} + +static int _app2sd_move_to_archive(const char *src_path, const char *arch_path) +{ + int ret = APP2EXT_SUCCESS; + + ret = _app2sd_copy_dir(src_path, arch_path); + if (ret) { + if (ret != APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s .....err is %s\n", + src_path, arch_path, strerror(errno)); + return APP2EXT_ERROR_MOVE; + } + } + ret = _app2sd_delete_directory((char *)src_path); + if (ret) { + if (ret != APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print("App2Sd Error : unable to delete %s \n", src_path); + return APP2EXT_ERROR_DELETE_DIRECTORY; + } + } + return ret; +} + +int _app2sd_move_app_to_external(const char *pkgid, GList* dir_list) +{ + int ret = APP2EXT_SUCCESS; + char app_path[FILENAME_MAX] = { 0, }; + char path[FILENAME_MAX] = { 0, }; + char app_mmc_path[FILENAME_MAX] = { 0, }; + char app_archive_path[FILENAME_MAX] = { 0, }; + char mmc_path[FILENAME_MAX] = { 0, }; + unsigned long long total_size = 0; + int reqd_size = 0; + char *device_node = NULL; + char *devi = NULL; + mode_t mode = DIR_PERMS; + int free_mmc_mem = 0; + FILE *fp = NULL; + GList *list = NULL; + app2ext_dir_details* dir_detail = NULL; + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print + ("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + snprintf(mmc_path, FILENAME_MAX, + "%s%s", APP2SD_PATH, pkgid); + + /*check whether application is in external memory or not */ + fp = fopen(mmc_path, "r+"); + if (fp != NULL) { + app2ext_print + ("Already %s entry is present in the SD Card\n", + pkgid); + fclose(fp); + return APP2EXT_ERROR_ALREADY_FILE_PRESENT; + } + + snprintf(app_mmc_path, FILENAME_MAX, + "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid); + snprintf(app_archive_path, FILENAME_MAX, + "%s%s/.archive", APP_INSTALLATION_PATH, pkgid); + + ret = mkdir(app_archive_path, mode); + if (ret) { + if (errno != EEXIST) { + app2ext_print + ("App2sd Error: Unable to create directory for archiving, error no is %d\n", + errno); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + } + + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + memset((void *)&app_path, '\0', + FILENAME_MAX); + snprintf(app_path, FILENAME_MAX, + "%s%s/%s",APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + total_size += + _app2sd_calculate_dir_size + (app_path); + } + list = g_list_next(list); + } + + reqd_size = ((total_size / 1024) / 1024) + 2; + + /*Find avialable free memory in the MMC card */ + ret = + _app2sd_get_available_free_memory + (MMC_PATH, &free_mmc_mem); + if (ret) { + app2ext_print + ("App2Sd Error : Unable to get available free memory in MMC %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + /*If avaialalbe free memory in MMC is less than required size + 5MB , return error */ + if (reqd_size > free_mmc_mem) { + app2ext_print + ("App2Sd Error : Insufficient memory in MMC for application installation %d\n", + ret); + return APP2EXT_ERROR_MMC_INSUFFICIENT_MEMORY; + } + /*Create a loopback device */ + ret = + _app2sd_create_loopback_device(pkgid, (reqd_size+PKG_BUF_SIZE)); + if (ret) { + app2ext_print + ("App2Sd Error : loopback node creation failed\n"); + return APP2EXT_ERROR_CREATE_DEVICE; + } + /*Perform Loopback encryption setup */ + device_node = + _app2sd_do_loopback_encryption_setup(pkgid); + if (!device_node) { + app2ext_print + ("App2Sd Error : losetup failed, device node is %s\n", + device_node); + return APP2EXT_ERROR_DO_LOSETUP; + } + /*Check whether loopback device is associated with device node or not */ + devi = _app2sd_find_associated_device_node(pkgid); + if (devi == NULL) { + app2ext_print + ("App2Sd Error : _app2sd_find_associated_device_node losetup failed\n"); + return APP2EXT_ERROR_DO_LOSETUP; + } else { + free(devi); + devi = NULL; + } + /*Format the loopback file system */ + ret = _app2sd_create_file_system(device_node); + if (ret) { + app2ext_print + ("App2Sd Error : create ext4 filesystem failed\n"); + return APP2EXT_ERROR_CREATE_FS; + } + /********Archiving code begin***********/ + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + snprintf(path, FILENAME_MAX, + "%s%s/%s",APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + ret = + _app2sd_move_to_archive + (path, + app_archive_path); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s \n", + path, + app_archive_path); + return + APP2EXT_ERROR_MOVE; + } + } + } + list = g_list_next(list); + } + /********Archiving code ends***********/ + + /*mount the loopback encrypted pseudo device on application installation path as with Read Write permission */ + ret = + _app2sd_mount_app_content(pkgid, device_node, + MOUNT_TYPE_RW, dir_list, + APP2SD_MOVE_APP_TO_MMC); + if (ret) { + return ret; + } + /********restore Archive begin***********/ + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + memset((void *)&path, '\0', + FILENAME_MAX); + snprintf(path, FILENAME_MAX, + "%s%s/.archive/%s",APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + ret = + _app2sd_copy_dir + (path, + app_mmc_path); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s .....err is %s\n", + path, + app_mmc_path, + strerror + (errno)); + return + APP2EXT_ERROR_MOVE; + } + } + ret = + _app2sd_delete_directory + (path); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + path); + return + APP2EXT_ERROR_DELETE_DIRECTORY; + } + } + } + list = g_list_next(list); + } + + ret = _app2sd_delete_directory(app_archive_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + app_archive_path); + return APP2EXT_ERROR_DELETE_DIRECTORY; + } + /*Restore archive ends */ + /*Re-mount the loopback encrypted pseudo device on application installation path as with Read Only permission */ + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + return APP2EXT_ERROR_REMOUNT; + } + ret = + _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : unable to detach loopback setup for %s\n", + pkgid); + return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE; + } + return APP2EXT_SUCCESS; +} + +int _app2sd_move_app_to_internal(const char *pkgid, GList* dir_list) +{ + int ret = APP2EXT_SUCCESS; + mode_t mode = DIR_PERMS; + char path[FILENAME_MAX] = { 0, }; + char app_mmc_path[FILENAME_MAX] = { 0, }; + char app_path[FILENAME_MAX] = { 0, }; + char mmc_path[FILENAME_MAX] = { 0, }; + char app_archive_path[FILENAME_MAX] = { 0, }; + char *device_node = NULL; + FILE *fp = NULL; + GList *list = NULL; + app2ext_dir_details* dir_detail = NULL; + + snprintf(app_mmc_path, FILENAME_MAX, + "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid); + snprintf(app_path, FILENAME_MAX, "%s%s/", APP_INSTALLATION_PATH, + pkgid); + snprintf(app_archive_path, FILENAME_MAX, + "%s%s/.archive", APP_INSTALLATION_PATH, pkgid); + snprintf(mmc_path, FILENAME_MAX, + "%s%s", APP2SD_PATH, pkgid); + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print + ("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + /*check whether application is in external memory or not */ + fp = fopen(mmc_path, "r+"); + if (fp == NULL) { + app2ext_print + ("Application %s is not installed on SD Card\n", + pkgid); + return APP2EXT_ERROR_FILE_ABSENT; + } else { + fclose(fp); + fp = NULL; + } + + /*Get the associated device node for SD card applicationer */ + device_node = + _app2sd_find_associated_device_node(pkgid); + if (NULL == device_node) { + /*Do loopback setup */ + device_node = + _app2sd_do_loopback_encryption_setup + (pkgid); + if (device_node == NULL) { + app2ext_print + ("App2Sd Error : loopback encryption setup failed\n"); + return APP2EXT_ERROR_DO_LOSETUP; + } + /*Do mounting */ + ret = + _app2sd_mount_app_content(pkgid, + device_node, + MOUNT_TYPE_RW, + dir_list, + APP2SD_MOVE_APP_TO_PHONE); + if (ret) { + app2ext_print + ("App2Sd Error : Re-mount failed\n"); + return APP2EXT_ERROR_MOUNT_PATH; + } + } else { + /*Do re-mounting */ + ret = + _app2sd_mount_app_content(pkgid, + device_node, + MOUNT_TYPE_RW_REMOUNT, + dir_list, + APP2SD_MOVE_APP_TO_PHONE); + if (ret) { + app2ext_print + ("App2Sd Error : Re-mount failed\n"); + return APP2EXT_ERROR_MOUNT_PATH; + } + } + ret = mkdir(app_archive_path, mode); + if (ret) { + app2ext_print + ("App2Sd Error : unable to create directory%s\n", + app_archive_path); + return APP2EXT_ERROR_CREATE_DIRECTORY; + } + + + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + /*Archiving code */ + memset((void *)&path, '\0', + FILENAME_MAX); + snprintf(path, FILENAME_MAX, + "%s%s/.mmc/%s", APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + ret = + _app2sd_copy_dir + (path, + app_archive_path); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s .....err is %s\n", + path, + app_archive_path, + strerror + (errno)); + return + APP2EXT_ERROR_MOVE; + } + } + + /*Delete the symbolic link files [bin, lib, res]*/ + memset((void *)&path, '\0', + FILENAME_MAX); + snprintf(path, FILENAME_MAX, + "%s%s/%s", APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + ret = unlink(path); + if (ret) { + if (errno == ENOENT) { + app2ext_print + ("App2Sd Error : Directory %s does not exist\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to remove the symbolic link file %s\n", + path); + return + APP2EXT_ERROR_DELETE_LINK_FILE; + } + } + + /*Copy content to destination */ + memset((void *)&path, '\0', + FILENAME_MAX); + snprintf(path, FILENAME_MAX, + "%s%s/.archive/%s", APP_INSTALLATION_PATH, + pkgid, + dir_detail->name); + ret = + _app2sd_copy_dir + (path, app_path); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s .....err is %s\n", + path, + app_path, + strerror + (errno)); + return + APP2EXT_ERROR_MOVE; + } + } + } + list = g_list_next(list); + } + + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : unable to unmount SD directory for app %s\n", + pkgid); + return APP2EXT_ERROR_UNMOUNT; + } + ret = + _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : unable to detach loopback setup for %s\n", + pkgid); + return APP2EXT_ERROR_DETACH_LOOPBACK_DEVICE; + } + ret = _app2sd_delete_loopback_device(pkgid); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete the loopback device for %s\n", + pkgid); + return APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + ret = _app2sd_delete_directory(app_mmc_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + app_mmc_path); + return APP2EXT_ERROR_DELETE_DIRECTORY; + } + ret = _app2sd_delete_directory(app_archive_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + app_archive_path); + return APP2EXT_ERROR_DELETE_DIRECTORY; + } + return APP2EXT_SUCCESS; +} + +int _app2sd_move_app(const char *pkgid, app2ext_move_type move_cmd, GList* dir_list) +{ + int ret = APP2EXT_SUCCESS; + + /*Check whether MMC is present or not */ + ret = _app2sd_check_mmc_status(); + if (ret) { + app2ext_print + ("App2Sd Error : MMC not preset OR Not ready %d\n", + ret); + return APP2EXT_ERROR_MMC_STATUS; + } + + switch (move_cmd) { + case APP2EXT_MOVE_TO_EXT: + { + ret = _app2sd_move_app_to_external(pkgid, dir_list); + if (ret) { + app2ext_print + ("App2Sd Error : move app to external memory failed %d\n", + ret); + return ret; + } + break; + } + case APP2EXT_MOVE_TO_PHONE: + { + ret = _app2sd_move_app_to_internal(pkgid, dir_list); + if (ret) { + app2ext_print + ("App2Sd Error : move app to internal memory failed %d\n", + ret); + return ret; + } + break; + } + default: + { + app2ext_print("App2Sd Error : invalid argument\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + } + + return ret; + +} + +int _app2sd_copy_ro_content(const char *src, const char *dest, GList* dir_list) +{ + char path[FILENAME_MAX] = { 0, }; + int ret = APP2EXT_SUCCESS; + GList *list = NULL; + app2ext_dir_details* dir_detail = NULL; + + list = g_list_first(dir_list); + while (list) { + dir_detail = (app2ext_dir_details *)list->data; + if (dir_detail && dir_detail->name + && dir_detail->type == APP2EXT_DIR_RO) { + memset((void *)&path, '\0', + FILENAME_MAX); + snprintf(path, FILENAME_MAX, + "%s/%s", src, + dir_detail->name); + ret = + _app2sd_copy_dir + (path, + dest); + if (ret) { + if (ret == APP2EXT_ERROR_ACCESS_FILE) { + app2ext_print + ("App2Sd Error : unable to access %s\n", + path); + } else { + app2ext_print + ("App2Sd Error : unable to copy from %s to %s .....errno is %d\n", + path, + dest, + errno); + return + APP2EXT_ERROR_MOVE; + } + } + } + list = g_list_next(list); + } + + return APP2EXT_SUCCESS; +} + +int _app2sd_duplicate_device(const char *pkgid, GList* dir_list, char *dev_node, int size) +{ + int ret = 0; + char temp_pkgid[FILENAME_MAX] = { 0, }; + char *devi = NULL; + int err_res = 0; + char *result = NULL; + + /*Create a new loopback device */ + snprintf(temp_pkgid, FILENAME_MAX, + "%s.new", pkgid); + ret = _app2sd_create_loopback_device(temp_pkgid, (size+PKG_BUF_SIZE)); + if (ret) { + app2ext_print("App2Sd Error : Package already present\n"); + return ret; + } + app2ext_print("App2Sd : _app2sd_create_loopback_device SUCCESS\n"); + /*Perform Loopback encryption setup */ + dev_node = _app2sd_do_loopback_duplicate_encryption_setup(pkgid, temp_pkgid); + if (!dev_node) { + app2ext_print("App2Sd Error : losetup failed, device node is %s\n", dev_node); + _app2sd_delete_loopback_device(pkgid); + app2ext_print("App2Sd Error : create ext filesystem failed\n"); + return APP2EXT_ERROR_DO_LOSETUP; + } + app2ext_print("App2Sd : _app2sd_do_loopback_duplicate_encryption_setup SUCCESS\n"); + /*Check whether loopback device is associated with device node or not */ + devi = _app2sd_find_associated_device_node(temp_pkgid); + if (devi == NULL) { + app2ext_print("App2Sd Error : finding associated device node failed\n"); + err_res = APP2EXT_ERROR_DO_LOSETUP; + goto FINISH_OFF; + } + app2ext_print("App2Sd : _app2sd_find_associated_device_node SUCCESS\n"); + /*Format the loopback file system */ + ret = _app2sd_create_file_system(dev_node); + if (ret) { + app2ext_print("App2Sd Error : creating FS failed failed\n"); + err_res = APP2EXT_ERROR_CREATE_FS; + goto FINISH_OFF; + } + app2ext_print("App2Sd : _app2sd_create_file_system SUCCESS\n"); + /*Do mounting for new dev*/ + ret = + _app2sd_mount_app_content(temp_pkgid, dev_node, MOUNT_TYPE_RW, + dir_list, APP2SD_PRE_UPGRADE); + if (ret) { + app2ext_print("App2Sd Error : Re-mount failed\n"); + err_res = APP2EXT_ERROR_MOUNT_PATH; + goto FINISH_OFF; + } + if (devi) { + free(devi); + devi = NULL; + } + return APP2EXT_SUCCESS; + +FINISH_OFF: + if (dev_node) { + result = _app2sd_detach_loop_device(dev_node); + if (result) { + free(result); + result = NULL; + } + _app2sd_delete_loopback_device(pkgid); + free(dev_node); + dev_node = NULL; + } + + if (devi) { + free(devi); + devi = NULL; + } + return err_res; +} + +int _app2sd_update_loopback_device_size(const char *pkgid, + int size, GList* dir_list) +{ + int ret = 0; + char *device_node = NULL; + char *old_device_node = NULL; + char *result = NULL; + int err_res = 0; + char app_mmc_path[FILENAME_MAX] = { 0, }; + char app_archive_path[FILENAME_MAX] = { 0, }; + char temp_pkgid[FILENAME_MAX] = { 0, }; + char app_path[FILENAME_MAX] = { 0, }; + + snprintf(temp_pkgid, FILENAME_MAX, + "%s.new", pkgid); + + ret = _app2sd_duplicate_device(pkgid, dir_list, device_node, size); + if (ret) { + app2ext_print("App2Sd Error : Creating duplicate device failed\n"); + return ret; + } + + app2ext_print("App2Sd : _app2sd_mount_app_content SUCCESS\n"); + /*check app entry is there in sd card or not. */ + snprintf(app_path, FILENAME_MAX, "%s%s", APP2SD_PATH, + pkgid); + + /*Get the associated device node for SD card applicatione */ + old_device_node = _app2sd_find_associated_device_node(pkgid); + if (NULL == old_device_node) { + /*Do loopback setup */ + old_device_node = _app2sd_do_loopback_encryption_setup(pkgid); + if (old_device_node == NULL) { + app2ext_print + ("App2Sd Error : loopback encryption setup failed\n"); + err_res = APP2EXT_ERROR_DO_LOSETUP; + goto FINISH_OFF; + } + /*Do mounting */ + ret = + _app2sd_mount_app_content(pkgid, old_device_node, + MOUNT_TYPE_RW, dir_list, + APP2SD_PRE_UPGRADE); + if (ret) { + app2ext_print("App2Sd Error : Re-mount failed\n"); + err_res = APP2EXT_ERROR_MOUNT_PATH; + goto FINISH_OFF; + } + } else { + /*Do re-mounting */ + ret = + _app2sd_mount_app_content(pkgid, old_device_node, + MOUNT_TYPE_RW_REMOUNT, dir_list, + APP2SD_PRE_UPGRADE); + if (ret) { + app2ext_print("App2Sd Error : Re-mount failed\n"); + err_res = APP2EXT_ERROR_MOUNT_PATH; + goto FINISH_OFF; + } + } + + snprintf(app_mmc_path, FILENAME_MAX, + "%s%s/.mmc", APP_INSTALLATION_PATH, pkgid); + snprintf(app_archive_path, FILENAME_MAX, + "%s%s/.mmc", APP_INSTALLATION_PATH, temp_pkgid); + + ret = _app2sd_copy_ro_content(app_mmc_path, app_archive_path, dir_list); + if (ret) { + app2ext_print("App2Sd Error : copy ro content failed\n"); + err_res = ret; + goto FINISH_OFF; + } + + ret = _app2sd_unmount_app_content(pkgid); + if (ret) { + app2ext_print + ("App2SD Error: Unable to unmount the SD application\n"); + err_res = APP2EXT_ERROR_UNMOUNT; + goto FINISH_OFF; + } + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print("App2SD Error: Unable to remove loopback setup\n"); + err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + goto FINISH_OFF; + } + ret = _app2sd_unmount_app_content(temp_pkgid); + if (ret) { + app2ext_print + ("App2SD Error: Unable to unmount the SD application\n"); + err_res = APP2EXT_ERROR_UNMOUNT; + goto FINISH_OFF; + } + ret = _app2sd_remove_loopback_encryption_setup(temp_pkgid); + if (ret) { + app2ext_print("App2SD Error: Unable to remove loopback setup\n"); + err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + goto FINISH_OFF; + } + snprintf(app_archive_path, FILENAME_MAX, + "%s%s", APP2SD_PATH, temp_pkgid); + ret = _app2sd_delete_directory(app_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + app_path); + err_res = APP2EXT_ERROR_DELETE_DIRECTORY; + goto FINISH_OFF; + } + ret = _app2sd_rename_dir(app_archive_path, app_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to rename %s \n", + app_archive_path); + err_res = APP2EXT_ERROR_MOVE; + goto FINISH_OFF; + } + snprintf(app_path, FILENAME_MAX, + "%s%s", APP_INSTALLATION_PATH, temp_pkgid); + ret = _app2sd_delete_directory(app_path); + if (ret) { + app2ext_print + ("App2Sd Error : unable to delete %s \n", + app_path); + err_res = APP2EXT_ERROR_DELETE_DIRECTORY; + goto FINISH_OFF; + } + return APP2EXT_SUCCESS; + +FINISH_OFF: + if (old_device_node) { + free(old_device_node); + old_device_node = NULL; + } + + ret = _app2sd_remove_loopback_encryption_setup(pkgid); + if (ret) { + app2ext_print("App2SD Error: Unable to remove loopback setup\n"); + err_res = APP2EXT_ERROR_DELETE_LOOPBACK_DEVICE; + } + return err_res; +} diff --git a/plugin/app2sd/src/app2sd_internals_registry.c b/plugin/app2sd/src/app2sd_internals_registry.c new file mode 100755 index 0000000..6f29fc9 --- /dev/null +++ b/plugin/app2sd/src/app2sd_internals_registry.c @@ -0,0 +1,252 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define MAX_QUERY_LEN 4096 +#define PASSWORD_LENGTH 64 +/* +########### Internal APIs ################## + */ + +/*sqlite db code*/ +#define APP2SD_DB_FILE "/opt/dbspace/.app2sd.db" +sqlite3 *app2sd_db; +#define QUERY_CREATE_TABLE_APP2SD "create table app2sd \ + (pkgid text primary key,\ + password text\ + )" + +/* + *@_app2sd_initialize_db + *This function is to initialize sqlite db. + * return: On success, it will return zero else if fail then return val<0. + */ +int _app2sd_initialize_db() +{ + char *error_message = NULL; + int ret; + FILE * fp = NULL; + fp = fopen(APP2SD_DB_FILE, "r"); + if (fp != NULL) { + fclose(fp); + ret = + db_util_open(APP2SD_DB_FILE, &app2sd_db, + DB_UTIL_REGISTER_HOOK_METHOD); + + if (ret != SQLITE_OK) { + app2ext_print("====>>>> connect menu_db [%s] failed!\n", + APP2SD_DB_FILE); + return -1; + } + return 0; + } + + ret = + db_util_open(APP2SD_DB_FILE, &app2sd_db, + DB_UTIL_REGISTER_HOOK_METHOD); + + if (ret != SQLITE_OK) { + app2ext_print("====>>>> connect menu_db [%s] failed!\n", + APP2SD_DB_FILE); + return -1; + } + + if (SQLITE_OK != + sqlite3_exec(app2sd_db, QUERY_CREATE_TABLE_APP2SD, + NULL, NULL, &error_message)) { + app2ext_print("Don't execute query = %s, " + "error message = %s\n", + QUERY_CREATE_TABLE_APP2SD, error_message); + return -1; + } + + app2ext_print("\n db_initialize_done "); + return 0; +} + +/* + *@_app2sd_set_password_in_db + *This function is to store password into db. + * param[in]: pkgid: package id + * param[in]: password: password string + * return: On success, it will return 0. + * Else appropriate error will be returned. + */ +int _app2sd_set_password_in_db(const char *pkgid, + const char *passwd) +{ + char query[MAX_QUERY_LEN] = { 0, }; + char *error_message = NULL; + + snprintf(query, MAX_QUERY_LEN, "insert into app2sd(pkgid,password)\ + values ('%s','%s')", pkgid, passwd); + + if (SQLITE_OK != sqlite3_exec(app2sd_db, query, NULL, NULL, + &error_message)) { + app2ext_print("Don't execute query = %s, error message = %s\n", + query, error_message); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + app2ext_print("\n sqlite insertion done "); + return APP2EXT_SUCCESS; +} + +/* + *@_app2sd_remove_password_from_db + *This function is to remove passwod from db. + * param[in]: pkgid: package id + * return: On success, it will return 0. + * Else appropriate error will be returned. + */ +int _app2sd_remove_password_from_db(const char *pkgid) +{ + char query[MAX_QUERY_LEN] = { 0 }; + char *error_message = NULL; + + snprintf(query, MAX_QUERY_LEN, + "delete from app2sd where pkgid LIKE '%s'", pkgid); + app2ext_print("\n deletion querys is %s ", query); + + if (SQLITE_OK != sqlite3_exec(app2sd_db, query, NULL, + NULL, &error_message)) { + app2ext_print("Don't execute query = %s, error message = %s\n", + query, error_message); + return APP2EXT_ERROR_SQLITE_REGISTRY; + } + + app2ext_print("\n app2sd password deletion done "); + return APP2EXT_SUCCESS; + +} + +/* + *@_app2sd_access_password_from_db + *This function is to find out whther password exists for an application. + * param[in]: pkgid: package id + * return: On success, it will return zero , else value<0 if fail. + */ +int _app2sd_access_password_from_db(const char *pkgid) +{ + char query[MAX_QUERY_LEN] = { 0 }; + int access_flag = 0; + int i; + sqlite3_stmt *stmt = NULL; + const char *tail = NULL; + + snprintf(query, MAX_QUERY_LEN, + "select * from app2sd where pkgid LIKE '%s'", pkgid); + app2ext_print("\n access querys is %s ", query); + + if (SQLITE_OK != sqlite3_prepare(app2sd_db, query, + strlen(query), &stmt, &tail)) { + app2ext_print("sqlite3_prepare error\n"); + return -1; + } + for (i = 0; SQLITE_ROW == sqlite3_step(stmt); i++) { + app2ext_print("\n entry available in sqlite"); + access_flag = 1; + + } + if (SQLITE_OK != sqlite3_finalize(stmt)) { + app2ext_print("error : sqlite3_finalize\n"); + return -1; + } + if (access_flag == 1) { + app2ext_print("\n app2sd value is accessible "); + return APP2EXT_SUCCESS; + } else { + app2ext_print("\n app2sd value is not accessible "); + return -1; + } +} + +/* + *@_app2sd_get_password_from_db + *This function is to retrive password from DB + * param[in]: pkgid: package id + * return: On success, it will return the password, else NULL. + */ +char *_app2sd_get_password_from_db(const char *pkgid) +{ + char query[MAX_QUERY_LEN] = { 0 }; + sqlite3_stmt *stmt = NULL; + const char *tail = NULL; + int rc = 0; + char *passwd = NULL; + + snprintf(query, MAX_QUERY_LEN, + "select * from app2sd where pkgid LIKE '%s'", pkgid); + app2ext_print("\n access querys is %s ", query); + + if (SQLITE_OK != sqlite3_prepare(app2sd_db, query, + strlen(query), &stmt, &tail)) { + app2ext_print("sqlite3_prepare error\n"); + return NULL; + } + + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW || rc == SQLITE_DONE) { + app2ext_print("No records found"); + goto FINISH_OFF; + } + passwd = malloc(PASSWORD_LENGTH + 1); + if (passwd == NULL) { + app2ext_print("memory allocation failed\n"); + goto FINISH_OFF; + } + + app2ext_print("\n entry available in sqlite"); + strncpy(passwd, (const char*)sqlite3_column_text(stmt, 1), + PASSWORD_LENGTH); + if (passwd == NULL) { + app2ext_print("\n password is NULL "); + goto FINISH_OFF; + } + app2ext_print("\n passwd is %s ", passwd); + if (SQLITE_OK != sqlite3_finalize(stmt)) { + app2ext_print("error : sqlite3_finalize\n"); + goto FINISH_OFF; + } + return passwd; + +FINISH_OFF: + rc = sqlite3_finalize(stmt); + if (rc != SQLITE_OK) { + app2ext_print(" sqlite3_finalize failed - %d", rc); + } + if (passwd) + free(passwd); + return NULL; +} diff --git a/plugin/app2sd/src/app2sd_internals_utils.c b/plugin/app2sd/src/app2sd_internals_utils.c new file mode 100755 index 0000000..23a8c30 --- /dev/null +++ b/plugin/app2sd/src/app2sd_internals_utils.c @@ -0,0 +1,470 @@ +/* + * app2ext + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Garima Shrivastava + * Jyotsna Dhumale + * Venkatesha Sarpangala + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PASSWD_LEN 8 +#define ASCII_PASSWD_CHAR 94 + +/* +########### Internal APIs ################## + */ + +/*Note: Don't use any printf statement inside this function*/ +/*This function is similar to Linux's "system()" for executing a process.*/ +int _xsystem(const char *argv[]) +{ + int status = 0; + pid_t pid; + pid = fork(); + switch (pid) { + case -1: + perror("fork failed"); + return -1; + case 0: + /* child */ + execvp(argv[0], (char *const *)argv); + _exit(-1); + default: + /* parent */ + break; + } + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid failed"); + return -1; + } + if (WIFSIGNALED(status)) { + perror("signal"); + return -1; + } + if (!WIFEXITED(status)) { + /* shouldn't happen */ + perror("should not happen"); + return -1; + } + return WEXITSTATUS(status); +} + + +/* +* @_app2sd_check_mmc_status +* This function checks and returns MMC status +*/ +int _app2sd_check_mmc_status(void) +{ + FILE *fp1 = NULL; + char line[512]; + fp1 = fopen("/etc/mtab", "r"); + if (fp1 == NULL) { + fprintf(stderr, "failed to open file\n"); + app2ext_print("failed to open file /etc/mtab\n"); + return APP2EXT_ERROR_MMC_STATUS; + } + while (fgets(line, 512, fp1) != NULL) { + if (strstr(line, MMC_PATH) != NULL) { + fclose(fp1); + return APP2EXT_SUCCESS; + } + } + fclose(fp1); + return APP2EXT_ERROR_MMC_STATUS; +} + +/* + * @_app2sd_get_available_free_memory + * This function returns the available free memory in the SD Card. + * param [in]: sd_path: This is sd card access path. + * param [out]: free_mem: Result will be available in this. + * User has to pass valid memory address. + * return: On success, it will return 0. + * Else, appropriate error no will be returned. + */ +int _app2sd_get_available_free_memory(const char *sd_path, int *free_mem) +{ + struct statvfs buf; + int ret = 0; + if (sd_path == NULL || free_mem == NULL) { + app2ext_print("App2Sd Error : Invalid input parameter\n"); + return -1; + } + memset((void *)&buf, '\0', sizeof(struct statvfs)); + ret = statvfs(sd_path, &buf); + if (ret) { + app2ext_print + ("App2SD Error: Unable to get SD Card memory information\n"); + return APP2EXT_ERROR_MMC_INFORMATION; + } + *free_mem = ((buf.f_bfree * buf.f_bsize) / 1024) / 1024; + return 0; +} + +int _app2sd_delete_directory(char *dirname) +{ + DIR *dp = NULL; + struct dirent *ep = NULL; + char abs_filename[FILENAME_MAX] = { 0, }; + int ret = 0; + dp = opendir(dirname); + if (dp != NULL) { + while ((ep = readdir(dp)) != NULL) { + struct stat stFileInfo; + + snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, + ep->d_name); + + if (lstat(abs_filename, &stFileInfo) < 0) { + perror(abs_filename); + return -1; + } + + if (S_ISDIR(stFileInfo.st_mode)) { + if (strcmp(ep->d_name, ".") + && strcmp(ep->d_name, "..")) { + ret = _app2sd_delete_directory(abs_filename); + if (ret <0) + return -1; + } + } else { + ret = remove(abs_filename); + if (ret <0) + return -1; + } + } + (void)closedir(dp); + ret = remove(dirname); + if (ret <0) + return -1; + } else { + app2ext_print("Couldn't open the directory\n"); + } + return 0; +} + +int _app2sd_copy_dir(const char *src, const char *dest) +{ + int ret = APP2EXT_SUCCESS; + const char *argv_bin[] = { "/bin/cp", "-raf", src, dest, NULL }; + ret = _xsystem(argv_bin); + if (ret) { + app2ext_print("copy fail\n"); + return APP2EXT_ERROR_MOVE; + } + return ret; +} + +int _app2sd_rename_dir(const char *old_name, const char *new_name) +{ + int ret = APP2EXT_SUCCESS; + const char *argv_bin[] = { "/bin/mv", old_name, new_name, NULL }; + ret = _xsystem(argv_bin); + if (ret) { + app2ext_print("mv/rename fail\n"); + return APP2EXT_ERROR_MOVE; + } + return ret; +} + +unsigned long long _app2sd_calculate_dir_size(char *dirname) +{ + static unsigned long long total = 0; + DIR *dp = NULL; + struct dirent *ep = NULL; + char abs_filename[FILENAME_MAX] = { 0, };; + dp = opendir(dirname); + if (dp != NULL) { + while ((ep = readdir(dp)) != NULL) { + struct stat stFileInfo; + + snprintf(abs_filename, FILENAME_MAX, "%s/%s", dirname, + ep->d_name); + + if (stat(abs_filename, &stFileInfo) < 0) + perror(abs_filename); + else { + total += stFileInfo.st_size; + + if (S_ISDIR(stFileInfo.st_mode)) { + if (strcmp(ep->d_name, ".") + && strcmp(ep->d_name, "..")) { + _app2sd_calculate_dir_size + (abs_filename); + } + } else { + /*Do Nothing */ + } + } + } + (void)closedir(dp); + } else { + app2ext_print("\n error in opening directory "); + } + return total; +} + +unsigned long long _app2sd_calculate_file_size(const char *filename) +{ + struct stat stFileInfo; + app2ext_print("\n Calculating file size for %s\n", filename); + + if (stat(filename, &stFileInfo) < 0) { + perror(filename); + return 0; + } else + return stFileInfo.st_size; +} + +/*Note: Don't use any printf statement inside this function*/ +char *_app2sd_encrypt_device(const char *device, const char *pkgid, + char *passwd) +{ + const char *argv[] = + { "/sbin/losetup", "-e", "aes", device, pkgid, "-k", passwd, NULL }; + pid_t pid = 0; + int my_pipe[2] = { 0, }; + char buf[FILENAME_MAX] = { 0, }; + char *ret_result = NULL; + int result = 0; + if (pipe(my_pipe) < 0) { + fprintf(stderr, "Unable to create pipe\n"); + return NULL; + } + pid = fork(); + switch (pid) { + case -1: + perror("fork failed"); + return NULL; + case 0: + /* child */ + close(1); + close(2); + result = dup(my_pipe[1]); + result = dup(my_pipe[1]); + if (execvp(argv[0], (char *const *)argv) < 0) { + fprintf(stderr, "execvp failed %d....%s\n", errno, strerror(errno)); /*Don't use d_msg_app2sd */ + } + _exit(-1); + default: + /* parent */ + close(my_pipe[1]); + result = read(my_pipe[0], buf, FILENAME_MAX); + break; + } + + ret_result = (char *)malloc(strlen(buf) + 1); + if (ret_result == NULL) { + app2ext_print("Malloc failed!\n"); + return NULL; + } + memset(ret_result, '\0', strlen(buf) + 1); + memcpy(ret_result, buf, strlen(buf)); + return ret_result; +} + +/*Note: Don't use any printf statement inside this function*/ +char *_app2sd_detach_loop_device(const char *device) +{ + const char *argv[] = { "/sbin/losetup", "-d", device, NULL }; + pid_t pid; + int my_pipe[2] = { 0, }; + char buf[FILENAME_MAX] = { 0, }; + char *ret_result = NULL; + int result = 0; + if (pipe(my_pipe) < 0) { + fprintf(stderr, "Unable to create pipe\n"); + return NULL; + } + pid = fork(); + switch (pid) { + case -1: + perror("fork failed"); + return NULL; + case 0: + /* child */ + close(1); + close(2); + result = dup(my_pipe[1]); + result = dup(my_pipe[1]); + if (execvp(argv[0], (char *const *)argv) < 0) { + fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */ + } + _exit(-1); + default: + /* parent */ + close(my_pipe[1]); + result = read(my_pipe[0], buf, FILENAME_MAX); + break; + } + + ret_result = (char *)malloc(strlen(buf) + 1); + if (ret_result == NULL) { + app2ext_print("Malloc failed!\n"); + return NULL; + } + memset(ret_result, '\0', strlen(buf) + 1); + memcpy(ret_result, buf, strlen(buf)); + + return ret_result; +} + +/*Note: Don't use any printf statement inside this function*/ +char *_app2sd_find_associated_device(const char *mmc_app_path) +{ + const char *argv[] = { "/sbin/losetup", "-j", mmc_app_path, NULL }; + pid_t pid; + int my_pipe[2] = { 0, }; + char buf[FILENAME_MAX] = { 0, }; + char *ret_result = NULL; + int result = 0; + if (pipe(my_pipe) < 0) { + fprintf(stderr, "Unable to create pipe\n"); + return NULL; + } + pid = fork(); + switch (pid) { + case -1: + perror("fork failed"); + return NULL; + case 0: + /* child */ + close(1); + close(2); + result = dup(my_pipe[1]); + result = dup(my_pipe[1]); + if (execvp(argv[0], (char *const *)argv) < 0) { + fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */ + } + _exit(-1); + default: + /* parent */ + close(my_pipe[1]); + result = read(my_pipe[0], buf, FILENAME_MAX); + break; + } + + ret_result = (char *)malloc(strlen(buf) + 1); + if (ret_result == NULL) { + app2ext_print("Malloc failed!\n"); + return NULL; + } + memset(ret_result, '\0', strlen(buf) + 1); + memcpy(ret_result, buf, strlen(buf)); + + return ret_result; +} + +/*Note: Don't use any printf statement inside this function*/ +char *_app2sd_find_free_device(void) +{ + const char *argv[] = { "/sbin/losetup", "-f", NULL }; + pid_t pid; + int my_pipe[2] = { 0, }; + char buf[FILENAME_MAX+1] = { 0, }; + char *ret_result = NULL; + int result = 0; + if (pipe(my_pipe) < 0) { + fprintf(stderr, "Unable to create pipe\n"); + return NULL; + } + pid = fork(); + switch (pid) { + case -1: + perror("fork failed"); + return NULL; + case 0: + /* child */ + close(1); + close(2); + result = dup(my_pipe[1]); + result = dup(my_pipe[1]); + if (execvp(argv[0], (char *const *)argv) < 0) { + fprintf(stderr, "execvp failed\n"); /*Don't use d_msg_app2sd */ + } + _exit(-1); + default: + /* parent */ + close(my_pipe[1]); + result = read(my_pipe[0], buf, FILENAME_MAX); + break; + } + + ret_result = (char *)malloc(strlen(buf) + 1); + if (ret_result == NULL) { + app2ext_print("Malloc failed!\n"); + return NULL; + } + memset(ret_result, '\0', strlen(buf) + 1); + memcpy(ret_result, buf, strlen(buf)); + + return ret_result; +} + +/*@_app2sd_generate_password +* This is a simple password generator +* return: On success, it will return the password, else NULL. +*/ +char *_app2sd_generate_password(const char *pkgid) +{ + char passwd[PASSWD_LEN+1] = { 0, }; + char *ret_result = NULL; + char set[ASCII_PASSWD_CHAR+1] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + unsigned char char_1; + unsigned char char_2; + int i = 0; + int appname_len = strlen(pkgid); + int j = appname_len; + + /* Length of the password */ + ret_result = (char*)malloc(PASSWD_LEN+1); + if (NULL == ret_result) { + app2ext_print("Unable to Allocate memory\n"); + return NULL; + } + memset((void *)ret_result, '\0', PASSWD_LEN+1); + + while(i < PASSWD_LEN) { + char_1 = (rand()+pkgid[j--])%ASCII_PASSWD_CHAR; + char_2 = rand()%ASCII_PASSWD_CHAR; + passwd[i] = set[char_1]; + passwd[i+1] = set[(pkgid[j--])*2]; + if (i + * + * 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 + +#define APP2EXT_SD_PLUGIN_PATH "/usr/lib/libapp2sd.so" + +app2ext_handle *app2ext_init(int storage_type) +{ + /*Validate the function parameter recieved */ + if (storage_type < APP2EXT_INTERNAL_MEM || + storage_type > APP2EXT_CLOUD) { + app2ext_print("App2Ext Error : Invalid function arguments\n"); + return NULL; + } + if (storage_type != APP2EXT_SD_CARD ) { + app2ext_print("App2Ext Error : Storage type currently not supported\n"); + return NULL; + } + + /* allocate memory for app2ext handle*/ + app2ext_handle *handle = (app2ext_handle *)calloc(1, sizeof(app2ext_handle)); + if (handle == NULL) { + app2ext_print("App2Ext Error : Memory allocation failure\n"); + return NULL; + } + void *dl_handle = NULL; + int (*dl_on_load)(app2ext_interface *)=NULL; + + /* Load SD plugin*/ + handle->type = APP2EXT_SD_CARD; + dl_handle = dlopen(APP2EXT_SD_PLUGIN_PATH, RTLD_LAZY|RTLD_GLOBAL); + if (NULL == dl_handle) + { + app2ext_print("App2Ext Error : dlopen(%s) failed.\n", APP2EXT_SD_PLUGIN_PATH); + free(handle); + return NULL; + } + handle->plugin_handle = dl_handle; + dl_on_load = dlsym(dl_handle, "app2ext_on_load"); + if (NULL == dl_on_load) + { + app2ext_print("App2Ext Error : Cannot find app2ext_on_load symbol in %s.", APP2EXT_SD_PLUGIN_PATH); + dlclose(dl_handle); + free(handle); + return NULL; + } + + /*Initialize the SD plugin*/ + if(!dl_on_load(&(handle->interface))) + { + app2ext_print("App2Ext Error : [%s] app2ext_on_load() failed.", APP2EXT_SD_PLUGIN_PATH); + dlclose(dl_handle); + free(handle); + return NULL; + } + + app2ext_print("App2Ext: %s plugin loaded\n", APP2EXT_SD_PLUGIN_PATH); + + return handle; +} + +int app2ext_deinit(app2ext_handle *handle) +{ + /*Validate the function parameter recieved */ + if (handle == NULL || handle->plugin_handle == NULL){ + app2ext_print("App2Ext Error : Invalid function arguments\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + + /* Close the plugin handle*/ + dlclose(handle->plugin_handle); + + /* Free allocated memory during installtion*/ + free(handle); + return APP2EXT_SUCCESS; +} + +int app2ext_get_app_location(const char *appname) +{ + /*Validate the function parameter received */ + if (appname == NULL) { + app2ext_print("invalid func parameters\n"); + return APP2EXT_ERROR_INVALID_ARGUMENTS; + } + FILE *fp = NULL; + char app_mmc_path[FILENAME_MAX] = { 0, }; + char app_dir_path[FILENAME_MAX] = { 0, }; + char app_mmc_internal_path[FILENAME_MAX] = { 0, }; + snprintf(app_dir_path, FILENAME_MAX, + "%s%s", APP_INSTALLATION_PATH, appname); + snprintf(app_mmc_path, FILENAME_MAX, + "%s%s", APP2SD_PATH, appname); + snprintf(app_mmc_internal_path, FILENAME_MAX, + "%s%s/.mmc", APP_INSTALLATION_PATH, appname); + + + /*check whether application is in external memory or not */ + fp = fopen(app_mmc_path, "r"); + if (fp == NULL) { + app2ext_print + (" app path in external memory not accesible\n"); + } else { + fclose(fp); + fp = NULL; + return APP2EXT_SD_CARD; + } + + /*check whether application is in internal or not */ + fp = fopen(app_dir_path, "r"); + if (fp == NULL) { + app2ext_print + (" app path in internal memory not accesible\n"); + return APP2EXT_NOT_INSTALLED; + } else { + fclose(fp); + /*check whether the application is installed in SD card + but SD card is not present*/ + fp = fopen(app_mmc_internal_path, "r"); + if (fp == NULL) { + return APP2EXT_INTERNAL_MEM; + } else { + fclose(fp); + return APP2EXT_ERROR_MMC_STATUS; + } + } +}