1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <string.h> 18#include <stdio.h> 19#include <fcntl.h> 20#include <errno.h> 21#include <unistd.h> 22#include <stdlib.h> 23#include <dirent.h> 24#include <unistd.h> 25#include <sys/stat.h> 26#include <sys/vfs.h> 27#include <sys/mman.h> 28#include "xpl_Memory.h" 29#include "xpl_File.h" 30#include "xpl_Logger.h" 31#include "dmvector.h" 32 33class DMDirHandler 34{ 35public : 36 DMDirHandler() 37 { 38 m_nIndex = 0; 39 m_nDirLen = 0; 40 m_pDir = XPL_NULL; 41 42 } 43 ~DMDirHandler() 44 { 45 if (m_pDir) 46 closedir(m_pDir); 47 } 48 49 void* operator new(size_t dwSize) 50 { 51 return (xplAllocMem(dwSize)); 52 } 53 54 void operator delete(void *pvBuf) 55 { 56 xplFreeMem(pvBuf); 57 } 58 59 DMString m_szDirectory; 60 DMString m_szExtension; 61 INT32 m_nIndex; 62 INT32 m_nDirLen; 63 DIR *m_pDir; 64}; 65 66 67#ifdef __cplusplus 68extern "C" { 69#endif 70 71 72XPL_FS_HANDLE_T XPL_FS_Open(CPCHAR file_uri, 73 const XPL_FS_OPEN_MODE_T open_mode, 74 XPL_FS_RET_STATUS_T * result) 75{ 76 int flags = 0; 77 XPL_FS_HANDLE_T nFileHandle; 78 79 if ( result ) 80 *result = XPL_FS_RET_SUCCESS; 81 82 switch ( open_mode) { 83 case XPL_FS_FILE_READ: 84 flags = O_RDONLY; /* read-only at current position */ 85 break; 86 87 case XPL_FS_FILE_WRITE: 88 flags = O_WRONLY | O_TRUNC | O_CREAT; /* write-only truncate file */ 89 break; 90 91 case XPL_FS_FILE_RDWR: 92 flags = O_RDWR| O_CREAT; /* read and write at current position */ 93 break; 94 95 case XPL_FS_FILE_APPEND: 96 flags = O_WRONLY | O_APPEND | O_CREAT; /* read and write at current position */ 97 break; 98 } 99 100 nFileHandle = (XPL_FS_HANDLE_T)open(file_uri, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 101 // XPL_LOG_DM_XPL_Debug(("DMFileHandler::open: opening file %s with mode flag %d, errno is %d, handle = %d\n",file_uri,(int)open_mode, errno, nFileHandle)); 102 if ( result && nFileHandle == -1 ) 103 { 104 if (errno == EPERM) { // permission failure 105 *result = XPL_FS_RET_PERM_FAIL; 106 } 107 else { 108 *result = XPL_FS_RET_FAIL; 109 } 110 XPL_LOG_DM_XPL_Error(("DMFileHandler::open: can't open file %s with mode flag %d errno is %d\n",file_uri,(int)open_mode,errno)); 111 } 112 113 if ( nFileHandle > 0 && open_mode != XPL_FS_FILE_READ ) 114 { 115 chmod(file_uri,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 116 } 117 return nFileHandle; 118 119} 120 121 122XPL_FS_RET_STATUS_T XPL_FS_Close(XPL_FS_HANDLE_T file_handle) 123{ 124 int result = close((int)file_handle); 125 if ( result < 0 ) 126 return XPL_FS_RET_FAIL; 127 else 128 return XPL_FS_RET_SUCCESS; 129} 130 131 132XPL_FS_COUNT_T XPL_FS_Read(XPL_FS_HANDLE_T file_handle, 133 void* buffer, 134 const XPL_FS_COUNT_T count, 135 XPL_FS_RET_STATUS_T * result) 136{ 137 if ( result ) 138 *result = XPL_FS_RET_SUCCESS; 139 XPL_FS_COUNT_T nRead = (XPL_FS_COUNT_T)read((int)file_handle,buffer,(int)count); 140 if ( result && nRead == -1 ) 141 *result = XPL_FS_RET_FAIL; 142 return nRead; 143} 144 145 146XPL_FS_COUNT_T XPL_FS_Write(XPL_FS_HANDLE_T file_handle, 147 void* buffer, 148 const XPL_FS_COUNT_T count, 149 XPL_FS_RET_STATUS_T * result) 150{ 151 if ( result ) 152 *result = XPL_FS_RET_SUCCESS; 153 154 XPL_FS_COUNT_T nWrite = (XPL_FS_COUNT_T)write((int)file_handle,buffer,(int)count); 155 if ( result && nWrite == -1 ) { 156 XPL_LOG_DM_XPL_Error(("XPL_FS_Write: file_handle %d, nWrite = %d errno is %d\n",file_handle, nWrite, errno)); 157 *result = XPL_FS_RET_FAIL; 158 } 159 return nWrite; 160} 161 162 163XPL_FS_SEEK_OFFSET_T XPL_FS_Seek(XPL_FS_HANDLE_T file_handle, 164 XPL_FS_SEEK_OFFSET_T offset, 165 XPL_FS_SEEK_MODE_T whence, 166 XPL_FS_RET_STATUS_T * result) 167{ 168 int whence_posix; 169 XPL_FS_SEEK_OFFSET_T result_offset; 170 171 if ( result ) 172 *result = XPL_FS_RET_SUCCESS; 173 switch(whence) 174 { 175 case XPL_FS_SEEK_SET: 176 whence_posix = SEEK_SET; 177 break; 178 case XPL_FS_SEEK_CUR: 179 whence_posix = SEEK_CUR; 180 break; 181 case XPL_FS_SEEK_END: 182 whence_posix = SEEK_END; 183 break; 184 } 185 result_offset = lseek(file_handle,offset,whence_posix); 186 if ( result && result_offset == -1) 187 *result = XPL_FS_RET_FAIL; 188 return result_offset; 189 190} 191 192 193XPL_FS_RET_STATUS_T XPL_FS_Remove(CPCHAR path) 194{ 195 int result = remove(path); 196 if ( result < 0 ) 197 return XPL_FS_RET_FAIL; 198 else 199 return XPL_FS_RET_SUCCESS; 200} 201 202XPL_FS_RET_STATUS_T XPL_FS_Rename(CPCHAR old_name, CPCHAR new_name) 203{ 204 int result = rename(old_name, new_name); 205 206 // XPL_LOG_DM_XPL_Debug(("XPL_FS_Rename: old name %s new name %s result = %d, errno is %d%d\n",old_name,new_name, errno, result)); 207 208 if ( result < 0 ) { 209 XPL_LOG_DM_XPL_Error(("XPL_FS_Rename error: old name %s new name %s result = %d, errno is %d\n",old_name,new_name, errno, result)); 210 return XPL_FS_RET_FAIL; 211 } 212 else 213 return XPL_FS_RET_SUCCESS; 214} 215 216BOOLEAN XPL_FS_Exist(CPCHAR match_uri) 217{ 218 struct stat st; 219 bool result; 220 221 222 errno = 0; // reset to 0 223 224 if(stat(match_uri, &st) < 0) 225 result = FALSE; 226 else 227 result = TRUE; 228 229 // XPL_LOG_DM_XPL_Debug(("XPL_FS_Exists: match uri %s, errno is %d result = %d\n",match_uri, errno, result)); 230 231 return result; 232} 233 234BOOLEAN XPL_FS_CheckPermission(CPCHAR match_uri, XPL_FS_OPEN_MODE_T permission) 235{ 236 bool result = FALSE; 237 int mode = 0; 238 239 switch (permission) { 240 case XPL_FS_RDONLY_MODE: 241 mode = R_OK; 242 break; 243 case XPL_FS_WRONLY_MODE: 244 case XPL_FS_RDWR_MODE: 245 case XPL_FS_CREAT_MODE: 246 case XPL_FS_TRUNC_MODE: 247 case XPL_FS_APPEND_MODE: 248 mode = R_OK | W_OK; 249 break; 250 default: 251 break; 252 } 253 254 errno = 0; // reset to 0 255 if (access(match_uri, mode) == 0) { 256 result = TRUE; 257 } 258 // XPL_LOG_DM_XPL_Debug(("XPL_FS_CheckPermission: match uri %s, errno is %d result = %d\n",match_uri, errno, result)); 259 260 return result; 261} 262 263 264XPL_CLK_CLOCK_T XPL_FS_GetModTime(CPCHAR file_uri) 265{ 266 struct stat st; 267 268 if(stat( file_uri, &st) < 0) 269 return 0; // like it was never modified 270 else 271 return (XPL_CLK_CLOCK_T)st.st_mtime; 272 } 273 274XPL_FS_SIZE_T XPL_FS_GetSize(XPL_FS_HANDLE_T file_handle) 275{ 276 struct stat st; 277 278 if(fstat(file_handle, &st) < 0) 279 return XPL_FS_SIZE_INVALID; 280 return st.st_size; 281} 282 283 284XPL_FS_RET_STATUS_T XPL_FS_MkDir(CPCHAR dir_uri) 285{ 286 mkdir(dir_uri, S_IRWXU|S_IRWXG|S_IRWXO); 287 return XPL_FS_RET_SUCCESS; 288} 289 290XPL_FS_RET_STATUS_T XPL_FS_Lock(XPL_FS_HANDLE_T file_handle, BOOLEAN bLockExclusive ) 291{ 292 struct flock fl; 293 294 fl.l_type = bLockExclusive ? F_WRLCK : F_RDLCK; 295 fl.l_whence = SEEK_SET; 296 fl.l_start = 0; 297 fl.l_len = 0; 298 fl.l_pid = getpid(); 299 300 if (fcntl(file_handle, F_SETLK, &fl) != -1) 301 return XPL_FS_RET_SUCCESS; 302 else 303 return (errno == EAGAIN ? XPL_FS_RET_TRYAGAIN : XPL_FS_RET_FAIL); 304} 305 306XPL_FS_RET_STATUS_T XPL_FS_Unlock(XPL_FS_HANDLE_T file_handle) 307{ 308 struct flock fl; 309 310 fl.l_type = F_UNLCK; 311 fl.l_whence = SEEK_SET; 312 fl.l_start = 0; 313 fl.l_len = 0; 314 fl.l_pid = getpid(); 315 316 if (fcntl(file_handle, F_SETLK, &fl) != -1) 317 return XPL_FS_RET_SUCCESS; 318 else 319 return XPL_FS_RET_FAIL; 320} 321 322 323XPL_FS_RET_STATUS_T XPL_FS_Unlink(CPCHAR file_name) 324{ 325 if ( unlink(file_name) == 0 ) 326 return XPL_FS_RET_SUCCESS; 327 else 328 return XPL_FS_RET_FAIL; 329} 330 331 332 333XPL_FS_SHANDLE_T XPL_FS_StartSearch(CPCHAR dir_uri, CPCHAR extension, BOOLEAN bFullName, XPL_FS_RET_STATUS_T * result) 334{ 335 DIR *dir = XPL_NULL; 336 337 if ( result ) 338 *result = XPL_FS_RET_SUCCESS; 339 340 dir = opendir(dir_uri); 341 if ( dir == NULL ) 342 { 343 if ( result ) 344 *result = XPL_FS_RET_FAIL; 345 346 return XPL_FS_SHANDLE_INVALID; 347 } 348 349 DMDirHandler * pDirHandler = NULL; 350 pDirHandler = new DMDirHandler; 351 352 if ( pDirHandler == NULL ) 353 { 354 if ( result ) 355 *result = XPL_FS_RET_FAIL; 356 357 closedir( dir ); 358 return XPL_FS_SHANDLE_INVALID; 359 } 360 361 if ( bFullName ) 362 { 363 int nDirLen = strlen(dir_uri); 364 if ( nDirLen >= XPL_FS_MAX_FILE_NAME_LENGTH ) 365 { 366 return XPL_FS_SHANDLE_INVALID; 367 } 368 if (nDirLen>0) 369 { 370 pDirHandler->m_szDirectory = dir_uri; 371 if ( dir_uri[nDirLen-1] != '/' ) 372 { 373 pDirHandler->m_szDirectory += "/"; 374 ++nDirLen; 375 } 376 pDirHandler->m_nDirLen = nDirLen; 377 } 378 } 379 380 pDirHandler->m_szExtension = extension; 381 pDirHandler->m_pDir = dir; 382 383 return (XPL_FS_SHANDLE_T)(pDirHandler); 384} 385 386 387XPL_FS_RET_STATUS_T XPL_FS_GetSearchResult(XPL_FS_SHANDLE_T search_handle, XPL_FS_SEARCH_FILE file_name) 388{ 389 DMDirHandler * pDirHandler = (DMDirHandler*)search_handle; 390 struct dirent *de = NULL; 391 392 if ( !pDirHandler || search_handle == XPL_FS_SHANDLE_INVALID ) 393 return XPL_FS_RET_FAIL; 394 395 int nNameLen = 0; 396 int nExtensionLen = strlen(pDirHandler->m_szExtension); 397 de = readdir(pDirHandler->m_pDir); 398 while ( de ) 399 { 400 nNameLen = strlen(de->d_name); 401 if (nNameLen > nExtensionLen && !strncmp((de->d_name + nNameLen - nExtensionLen), pDirHandler->m_szExtension, nExtensionLen)) 402 { 403 if ( pDirHandler->m_nDirLen+nNameLen >= XPL_FS_MAX_FILE_NAME_LENGTH ) 404 { 405 return XPL_FS_RET_FAIL; 406 } 407 if ( pDirHandler->m_nDirLen>0 ) 408 { 409 strcpy(file_name,pDirHandler->m_szDirectory); 410 } 411 strcpy(file_name+pDirHandler->m_nDirLen,(CPCHAR)de->d_name); 412 return XPL_FS_RET_SUCCESS; 413 } 414 else 415 { 416 de = readdir(pDirHandler->m_pDir); 417 } 418 } 419 420 return XPL_FS_RET_NOT_FOUND; 421} 422 423 424XPL_FS_RET_STATUS_T XPL_FS_EndSearch(XPL_FS_SHANDLE_T search_handle) 425{ 426 DMDirHandler * pDirHandler = (DMDirHandler*)search_handle; 427 // DO not call closedir(...); since it's called from DirHandle destructor... 428 delete pDirHandler; 429 return XPL_FS_RET_SUCCESS; 430} 431 432 433UINT8 * XPL_FS_MemMap(XPL_FS_HANDLE_T file_handle, UINT32 size, UINT32 offset, XPL_FS_RET_STATUS_T * result) 434{ 435 UINT8 * pBuffer = NULL; 436 437 if ( result ) 438 *result = XPL_FS_RET_SUCCESS; 439 440 pBuffer = (UINT8*)mmap(0,size,PROT_READ,MAP_PRIVATE,file_handle,offset); 441 if ( pBuffer == MAP_FAILED ) 442 { 443 if ( result) 444 *result = XPL_FS_RET_FAIL; 445 return NULL; 446 } 447 448 return pBuffer; 449 450} 451 452 453XPL_FS_RET_STATUS_T XPL_FS_MemUnMap(UINT8 * pBuffer, UINT32 size) 454{ 455 int res = munmap(pBuffer,size); 456 if ( res == 0 ) 457 return XPL_FS_RET_SUCCESS; 458 else 459 return XPL_FS_RET_FAIL; 460} 461#ifdef LOB_SUPPORT 462static const char TEMP_ESN_DIR_NAME[]= "/data/data/com.android.omadm.service/tmp/"; 463CPCHAR XPL_FS_TempEsnDir() 464{ 465 return TEMP_ESN_DIR_NAME; 466} 467XPL_FS_SIZE_T XPL_FS_FreeDiskSpace(CPCHAR pEsnDir) 468{ 469 struct statfs sf; 470 XPL_FS_SIZE_T retSize = 0; 471 472 if(statfs(pEsnDir, &sf) == 0) 473 { 474 retSize = sf.f_bfree * sf.f_bsize; 475 } 476 return retSize; 477} 478#endif 479 480#ifdef __cplusplus 481} 482#endif 483