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