--- /dev/null
+Garima Shrivastava<garima.s@samsung.com>
--- /dev/null
+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)
+
--- /dev/null
+<manifest>
+ <define>
+ <domain name="app2sd"/>
+ </define>
+ <request>
+ <domain name="app2sd"/>
+ </request>
+ <assign>
+ <filesystem path="/usr/lib/libapp2ext.so.0" label="_"/>
+ <filesystem path="/usr/lib/libapp2ext.so.0.4.2" label="_"/>
+ <filesystem path="/usr/lib/libapp2sd.so" label="_"/>
+ <filesystem path="/usr/lib/libapp2sd.so.0" label="_"/>
+ <filesystem path="/usr/lib/libapp2sd.so.0.4.2" label="_"/>
+ </assign>
+</manifest>
--- /dev/null
+# 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
--- /dev/null
+@PREFIX@/include/app2sd_interface.h
+@PREFIX@/lib/pkgconfig/*.pc
--- /dev/null
+@PREFIX@/lib/*.so*
--- /dev/null
+app2sd (0.2.1) unstable; urgency=low
+
+ * Initial release
+ * Git: slp/pkgs/a/app2sd
+ * Tag: app2sd_0.2.1
+
+ -- Jaeho Lee <jaeho81.lee@samsung.com> Thu, 24 May 2012 12:04:51 +0530
+
--- /dev/null
+Source: app2sd
+Section: devel
+Priority: extra
+Maintainer: Garima Shrivastava <garima.s@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
+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: <App2sd is a utility for enabling installation of applications to sd card and also to move to and from sd card.>
+
+Package: app2sd-dev
+Architecture: any
+Depends: app2sd (= ${Source-Version})
+Description: App2sd dev package
+
+Package: app2sd-doc
+Architecture: all
+Description: <App2sd is a utility for enabling installation of applications to sd card and also to move to and from sd card.>
+
+Package: app2sd-dbg
+Section: debug
+Architecture: any
+Depends: app2sd (= ${Source-Version})
+Description: App2sd dbg package
+
--- /dev/null
+/*
+ * 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.
+ *
+ */
--- /dev/null
+usr/bin
+usr/sbin
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jyotsna Dhumale <jyotsna.a@samsung.com>
+ *
+ * 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
+ * @{
+
+<h1 class="pg">Introduction</h1>
+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.
+
+<h1 class="pg">App2Ext process view</h1>
+\image html app2ext_diag.png "Picture 1. App2Ext Process View Diagram"
+\image rtf app2ext_diag.png "Picture 1. App2Ext Process View Diagram"
+
+<h1 class="pg">Installation to SD Card</h1>
+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.
+
+<h1 class="pg">Installation Setup Flow for App2SD plug-in</h1>
+\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"
+
+<h1 class="pg">Un-installation from SD Card</h1>
+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.
+
+<h1 class="pg">Un-installation Setup Flow for App2SD plug-in</h1>
+\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"
+
+
+<h1 class="pg">API list and description</h1>
+<ul>
+ <li>app2ext_init() : Initialize plug-in based on storage type </li>
+ <li>app2ext_deinit() : De-initialize plug-in</li>
+ <li>app2ext_get_app_location() : Returns application current location</li>
+</ul>
+
+ * @}
+ */
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jyotsna Dhumale <jyotsna.a@samsung.com>
+ *
+ * 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 <app2ext_interface.h>
+ * @endcode
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef API
+#define API __attribute__ ((visibility("default")))
+#endif
+
+#include <dlog/dlog.h>
+#include <glib.h>
+#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_interface.h>
+ 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_interface.h>
+ 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 <app2ext_interface.h>
+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
--- /dev/null
+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
+
+
+
--- /dev/null
+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)
+
+
--- /dev/null
+/*
+ * app2sd
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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
+ * @{
+
+<h1 class="pg">Introduction</h1>
+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.
+
+<h1 class="pg">App2sd process view</h1>
+\image html app2sd_diag.png "Picture 1. Process View Diagram"
+\image rtf app2sd_diag.png "Picture 1. Process View Diagram"
+
+<h1 class="pg">Installation to SD Card</h1>
+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.
+
+<h1 class="pg">App2sd Installation Setup Flow</h1>
+\image html app2sd_install_diag.png "Picture 2. Installation Flow Diagram"
+\image rtf app2sd_install_diag.png "Picture 2. Installation Flow Diagram"
+
+<h1 class="pg">Uninstallation to SD Card</h1>
+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.
+<h1 class="pg">App2sd Uninstallation Setup Flow</h1>
+\image html app2sd_uninstall_diag.png "Picture 3. Uninstallation Flow Diagram"
+\image rtf app2sd_uninstall_diag.png "Picture 3. Uninstallation Flow Diagram"
+
+<h1 class="pg">API list and description</h1>
+<ul>
+ <li>app2sd_pre_app_install() : Pre app installation setup.</li>
+ <li>app2sd_post_app_install() : Post app installation setup.</li>
+ <li>app2sd_pre_app_upgrade() : Pre app upgrade setup.</li>
+ <li>app2sd_post_app_upgrade() : Post app upgarde setup.</li>
+ <li>app2sd_pre_app_uninstall() : Pre app uninstall setup.</li>
+ <li>app2sd_post_app_uninstall() : Post app uninstall setup.</li>
+ <li>app2sd_move_installed_app() : Move installed application to/from sdcard</li>
+ <li>app2sd_get_app_install_location() : Get application installation location[external\internal memory].</li>
+ <li>app2sd_on_demand_setup_init() : Enables the application installed in sdcard.</li>
+ <li>app2sd_on_demand_setup_exit() : Disables the application installed in sdcard.</li>
+ <li></li>
+</ul>
+
+ * @}
+ */
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <app2sd_interface.h>
+ * @endcode
+ *
+ * @addtogroup app2sd
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <app2ext_interface.h>
+
+
+ /**
+ * @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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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 <app2sd_interface.h>
+ 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
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/mount.h>
+#include <app2sd_interface.h>
+
+#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
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <app2sd_internals.h>
+#include <app2sd_interface.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+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<size) {
+ ret = _app2sd_update_loopback_device_size(pkgid, size, dir_list);
+ if(APP2EXT_SUCCESS !=ret) {
+ app2ext_print
+ ("App2SD Error: _app2sd_update_loopback_device_size() failed\n");
+ return ret;
+ }
+ }
+
+ /*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_UPGRADE);
+ if (ret) {
+ app2ext_print("App2Sd Error : Re-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_UPGRADE);
+ 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_post_app_upgrade(const char *pkgid,
+ app2ext_status install_status)
+{
+ char *device_name = NULL;
+ 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;
+ }
+
+ /*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;
+}
+
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <app2sd_internals.h>
+#include <app2sd_interface.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/sha.h>
+#include <fcntl.h>
+#include <time.h>
+#include <dlog.h>
+
+/*
+########### 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;
+}
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <app2sd_internals.h>
+#include <app2sd_interface.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <dlog.h>
+#include <time.h>
+#include <db-util.h>
+#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;
+}
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Garima Shrivastava<garima.s@samsung.com>
+ * Jyotsna Dhumale <jyotsna.a@samsung.com>
+ * Venkatesha Sarpangala <sarpangala.v@samsung.com>
+ *
+ * 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 <app2sd_internals.h>
+#include <app2sd_interface.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <dlog.h>
+#include <sys/statvfs.h>
+#include <errno.h>
+
+#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<PASSWD_LEN-3)
+ passwd[i+2] = set[char_2];
+ i++;
+ }
+
+ app2ext_print("Password is %s\n", passwd);
+ memcpy(ret_result, passwd, PASSWD_LEN+1);
+ return ret_result;
+}
--- /dev/null
+/*
+ * app2ext
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jyotsna Dhumale <jyotsna.a@samsung.com>
+ *
+ * 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 <app2ext_interface.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#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;
+ }
+ }
+}