2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://floralicense.org/license/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FIo_MmcStorageManagerService.cpp
20 * @brief This is the implementation for the _MmcStorageManagerService class.
24 #include <sys/mount.h>
25 #include <sys/types.h>
29 #include <unique_ptr.h>
30 #include <sysman_managed.h>
34 #include <FIoDirectory.h>
35 #include <FIoMmcStorageManager.h>
36 #include <FBaseSysLog.h>
37 #include <FBaseInternalTypes.h>
38 #include <FBase_StringConverter.h>
39 #include <FAppTypes.h>
40 #include "FIo_MmcStorageManagerService.h"
41 #include "FIo_MmcStorageManagerStub.h"
43 #define VCONFKEY_APPSERVICE_MMC_STATUS "memory/appservice/mmc"
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Io;
48 using namespace Tizen::App;
50 struct mmc_contents mmcContents;
52 namespace Tizen { namespace Io {
54 _MmcStorageManagerService* _MmcStorageManagerService::__pMmcStorageManagerService = null;
55 static const char _EXTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/external";
56 static const int _MAX_PATH_LENGTH = 256;
59 _MmcStorageManagerService::ConvertNativeErrorToResult(int errNo)
61 SysLog(NID_IO, "ConvertNativeErrorToResult received : %d\n", errNo);
63 //Covert the SLP response to Osp response
86 //Callbacks from SLP. Its a C function.
88 MmcMountCb(int response, void* data)
90 SysLog(NID_IO, "MmcMountCb Called: %d\n", response);
91 result ospResult = E_SUCCESS;
93 ospResult = _MmcStorageManagerService::ConvertNativeErrorToResult(response);
94 SysTryLog(NID_IO, !IsFailed(ospResult), "[%s] Failed to mount MMC, errno: %d (%s)", GetErrorMessage(ospResult), response, strerror(response));
95 result r = ((_IMmcStorageServiceEventListener*)data)->OnMmcMountResponseReceived(ospResult);
96 SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] OnMmcMountResponseReceived failed.", GetErrorMessage(r));
100 MmcUnmountCb(int response, void* data)
102 SysLog(NID_IO, "MmcUnmountCb Called: %d\n", response);
103 result ospResult = E_SUCCESS;
105 ospResult = _MmcStorageManagerService::ConvertNativeErrorToResult(response);
106 SysTryLog(NID_IO, !IsFailed(ospResult), "[%s] Failed to unmount MMC, errno: %d (%s)", GetErrorMessage(ospResult), response, strerror(response));
107 result r = ((_IMmcStorageServiceEventListener*)data)->OnMmcUnmountResponseReceived(ospResult);
108 SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] OnMmcUnmountResponseReceived failed.", GetErrorMessage(r));
112 MmcFormatCb(int response, void* data)
114 SysLog(NID_IO, "MmcFormatCb Called: %d\n", response);
115 result ospResult = E_SUCCESS;
117 ospResult = _MmcStorageManagerService::ConvertNativeErrorToResult(response);
118 SysTryLog(NID_IO, !IsFailed(ospResult), "[%s] Failed to format MMC, errno: %d (%s)", GetErrorMessage(ospResult), response, strerror(response));
119 result r = ((_IMmcStorageServiceEventListener*)data)->OnMmcFormatResponseReceived(ospResult);
120 SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] OnMmcFormatResponseReceived failed.", GetErrorMessage(r));
123 _MmcStorageManagerService::_MmcStorageManagerService(void)
128 _MmcStorageManagerService::~_MmcStorageManagerService(void)
130 int ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, MmcEventVconfCallback);
133 _MmcStorageManagerService*
134 _MmcStorageManagerService::GetInstance(void)
136 if (__pMmcStorageManagerService == null)
138 __pMmcStorageManagerService = new (std::nothrow) _MmcStorageManagerService();
140 return __pMmcStorageManagerService;
144 _MmcStorageManagerService::Construct(_IMmcStorageServiceEventListener* pStub)
148 int ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, MmcEventVconfCallback, this);
149 SysTryReturnResult(NID_IO, ret == 0, E_SYSTEM, "Failed to register MMC event vconf callback.");
155 _MmcStorageManagerService::Mount(void)
159 mmcContents.mmc_cb = MmcMountCb;
160 mmcContents.user_data = __pStub;
162 slpResult = sysman_request_mount_mmc(&mmcContents);
163 SysTryReturnResult(NID_IO, slpResult == 0, E_SYSTEM, "Mount Failed. Slp sync return value: %d", slpResult);
169 _MmcStorageManagerService::Unmount(void)
173 mmcContents.mmc_cb = MmcUnmountCb;
174 mmcContents.user_data = __pStub;
176 slpResult = sysman_request_unmount_mmc(&mmcContents, 1);
177 SysTryReturnResult(NID_IO, slpResult == 0, E_SYSTEM, "Unmount Failed. Slp sync return value: %d", slpResult);
183 _MmcStorageManagerService::Format(void)
187 mmcContents.mmc_cb = MmcFormatCb;
188 mmcContents.user_data = __pStub;
190 slpResult = sysman_request_format_mmc(&mmcContents);
191 SysTryReturnResult(NID_IO, slpResult == 0, E_SYSTEM, "Format Failed. Slp sync return value: %d", slpResult);
197 _MmcStorageManagerService::MmcEventVconfCallback(keynode_t* node, void* userData)
199 static char mountList[][_MAX_PATH_LENGTH] =
201 "/opt/storage/sdcard",
204 char mountPoint[_MAX_PATH_LENGTH] = { 0, };
206 if (strcmp(VCONFKEY_SYSMAN_MMC_STATUS, vconf_keynode_get_name(node)) == 0)
209 int res = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &value);
210 result r = E_SUCCESS;
212 _MmcStorageManagerService* pMmcMgr = static_cast< _MmcStorageManagerService* >(userData);
213 _AppList::const_iterator iter;
214 for (iter = pMmcMgr->__appList.begin(); iter != pMmcMgr->__appList.end(); ++iter)
216 const String* pAppRoot = iter->second;
217 if (pAppRoot != null)
219 std::unique_ptr< char[] > pAppRootPath(_StringConverter::CopyToCharArrayN(*pAppRoot));
220 SysTryReturnVoidResult(NID_IO, pAppRootPath != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
222 char* pPkgId = strrchr(pAppRootPath.get(), '/');
223 char mountFlag[_MAX_PATH_LENGTH] = { 0, };
224 sprintf(mountFlag, "%s/%s", _EXTERNAL_MOUNT_FLAG, ++pPkgId);
228 SysLog(NID_IO, "MMC mount event for OSP compatible application.");
230 res = access(mountFlag, F_OK);
231 if (res == -1 && errno == ENOENT)
233 r = _MmcStorageManagerService::CreateFlag(mountFlag);
234 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_SYSTEM, "[%s] Failed to create mount flag (%s)",
235 GetErrorMessage(r), mountFlag);
237 if (access(pAppRootPath.get(), F_OK) == 0)
239 for (int i = 0; i < sizeof(mountList)/_MAX_PATH_LENGTH; ++i)
241 memset(mountPoint, 0, _MAX_PATH_LENGTH);
242 sprintf(mountPoint, "%ls%s", pAppRoot->GetPointer(), mountList[i]);
244 res = mount("/dev/emul_mmcblk0", mountPoint, "ext3", 0, "");
246 res = mount("/dev/mmcblk1p1", mountPoint, "vfat", 0,
247 "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed,smackfsroot=*,smackfsdef=*");
251 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to mount (%s), errno: %d (%s)",
252 mountPoint, errno, strerror(errno));
254 res = unlink(mountFlag);
255 SysTryReturnVoidResult(NID_IO, res == 0, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
256 mountFlag, errno, strerror(errno));
260 r = _MmcStorageManagerService::CreateExternalDirectories(*pAppRoot, String(pPkgId));
261 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_SYSTEM, "[%s] Failed to create external directories.",
264 char mountSrc[_MAX_PATH_LENGTH] = { 0, };
265 char mountDest[_MAX_PATH_LENGTH] = { 0, };
266 sprintf(mountSrc, "/opt/storage/sdcard/osp/apps/%s", pPkgId);
267 sprintf(mountDest, "%ls/HomeExt", pAppRoot->GetPointer());
268 res = mount(mountSrc, mountDest, null, MS_BIND, null);
271 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to mount (%s), errno: %d (%s)",
272 mountDest, errno, strerror(errno));
274 res = unlink(mountFlag);
275 SysTryReturnVoidResult(NID_IO, res == 0, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
276 mountFlag, errno, strerror(errno));
279 SysLog(NID_IO, "mount() succeeded, mount flag: %s", mountFlag);
284 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to access mount flag (%s), errno: %d (%s)",
285 mountFlag, errno, strerror(errno));
290 SysLog(NID_IO, "mount() was already done.");
295 SysLog(NID_IO, "MMC unmount event for OSP compatible application.");
297 for (int i = 0; i < sizeof(mountList)/_MAX_PATH_LENGTH; ++i)
299 memset(mountPoint, 0, _MAX_PATH_LENGTH);
300 sprintf(mountPoint, "%ls%s", pAppRoot->GetPointer(), mountList[i]);
302 res = umount2(mountPoint, MNT_DETACH);
303 SysTryLog(NID_IO, res == 0 || errno == ENOENT, "[E_SYSTEM] Failed to unmount (%s), errno: %d (%s)",
304 mountPoint, errno, strerror(errno));
307 char mountDest[_MAX_PATH_LENGTH] = { 0, };
308 sprintf(mountDest, "%ls/HomeExt", pAppRoot->GetPointer());
309 res = umount2(mountDest, MNT_DETACH);
310 SysTryLog(NID_IO, res == 0 || errno == ENOENT, "[E_SYSTEM] Failed to unmount (%s), errno: %d (%s)",
311 mountDest, errno, strerror(errno));
313 if (access(mountFlag, F_OK) == 0)
315 res = unlink(mountFlag);
316 SysTryReturnVoidResult(NID_IO, res == 0, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
317 mountFlag, errno, strerror(errno));
320 if (access(pAppRootPath.get(), F_OK) != 0 && errno == ENOENT)
322 std::string key(pPkgId);
323 String* pAppRoot = pMmcMgr->__appList[key];
324 if (pAppRoot != null)
326 pMmcMgr->__appList.erase(key);
327 SysLog(NID_IO, "OSP compatible application is unregistered.");
330 SysLog(NID_IO, "unmount() succeeded, mount flag: %s", mountFlag);
334 res = vconf_set_int(VCONFKEY_APPSERVICE_MMC_STATUS, value);
339 _MmcStorageManagerService::CreateFlag(const String& path)
342 result r = path.LastIndexOf(L'/', path.GetLength() - 1, index);
343 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
346 r = path.SubString(0, index, dirPath);
347 SysTryReturnResult(NID_IO, !IsFailed(r), E_SYSTEM, "The method cannot proceed due to a severe system error.");
349 if (!File::IsFileExist(dirPath) && GetLastResult() == E_SUCCESS)
351 r = Directory::Create(dirPath, true);
352 SysTryReturnResult(NID_IO, !IsFailed(r), r, "Failed to create parent directory.");
356 r = file.Construct(path, "w");
357 SysTryReturnResult(NID_IO, !IsFailed(r), r, "Failed to create mount flag.");
363 _MmcStorageManagerService::CreateExternalDirectories(const String& appRoot, const PackageId& pkgId)
365 String appHomeExt(appRoot);
366 appHomeExt.Append("/HomeExt");
367 if (!File::IsFileExist(appHomeExt) && GetLastResult() == E_SUCCESS)
369 result r = Directory::Create(appHomeExt, false);
370 SysTryReturnResult(NID_IO, !IsFailed(r), r, "Failed to create application HomeExt directory.");
373 String mmcHomeExt(L"/opt/storage/sdcard/osp/apps/");
374 mmcHomeExt.Append(pkgId);
375 if (!File::IsFileExist(mmcHomeExt) && GetLastResult() == E_SUCCESS)
377 result r = Directory::Create(mmcHomeExt, true);
378 SysTryReturnResult(NID_IO, !IsFailed(r), r, "Failed to create MMC HomeExt directory.");