generic.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * File Functions
  4. *
  5. * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. * Copyright 2014 Hewlett-Packard Development Company, L.P.
  7. * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include <winpr/crt.h>
  25. #include <winpr/path.h>
  26. #include <winpr/file.h>
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #ifdef HAVE_FCNTL_H
  31. #include <fcntl.h>
  32. #endif
  33. #include "../log.h"
  34. #define TAG WINPR_TAG("file")
  35. #ifdef _WIN32
  36. #include <io.h>
  37. #include <sys/stat.h>
  38. #else
  39. #include <assert.h>
  40. #include <pthread.h>
  41. #include <dirent.h>
  42. #include <libgen.h>
  43. #include <errno.h>
  44. #include <sys/un.h>
  45. #include <sys/stat.h>
  46. #include <sys/socket.h>
  47. #ifdef HAVE_AIO_H
  48. #undef HAVE_AIO_H /* disable for now, incomplete */
  49. #endif
  50. #ifdef HAVE_AIO_H
  51. #include <aio.h>
  52. #endif
  53. #ifdef ANDROID
  54. #include <sys/vfs.h>
  55. #include <winpr/timezone.h>
  56. #else
  57. #include <sys/statvfs.h>
  58. #endif
  59. #include "../handle/handle.h"
  60. #include "../pipe/pipe.h"
  61. #include "file.h"
  62. #include <winpr/timezone.h>
  63. /**
  64. * api-ms-win-core-file-l1-2-0.dll:
  65. *
  66. * CreateFileA
  67. * CreateFileW
  68. * CreateFile2
  69. * DeleteFileA
  70. * DeleteFileW
  71. * CreateDirectoryA
  72. * CreateDirectoryW
  73. * RemoveDirectoryA
  74. * RemoveDirectoryW
  75. * CompareFileTime
  76. * DefineDosDeviceW
  77. * DeleteVolumeMountPointW
  78. * FileTimeToLocalFileTime
  79. * LocalFileTimeToFileTime
  80. * FindClose
  81. * FindCloseChangeNotification
  82. * FindFirstChangeNotificationA
  83. * FindFirstChangeNotificationW
  84. * FindFirstFileA
  85. * FindFirstFileExA
  86. * FindFirstFileExW
  87. * FindFirstFileW
  88. * FindFirstVolumeW
  89. * FindNextChangeNotification
  90. * FindNextFileA
  91. * FindNextFileW
  92. * FindNextVolumeW
  93. * FindVolumeClose
  94. * GetDiskFreeSpaceA
  95. * GetDiskFreeSpaceExA
  96. * GetDiskFreeSpaceExW
  97. * GetDiskFreeSpaceW
  98. * GetDriveTypeA
  99. * GetDriveTypeW
  100. * GetFileAttributesA
  101. * GetFileAttributesExA
  102. * GetFileAttributesExW
  103. * GetFileAttributesW
  104. * GetFileInformationByHandle
  105. * GetFileSize
  106. * GetFileSizeEx
  107. * GetFileTime
  108. * GetFileType
  109. * GetFinalPathNameByHandleA
  110. * GetFinalPathNameByHandleW
  111. * GetFullPathNameA
  112. * GetFullPathNameW
  113. * GetLogicalDrives
  114. * GetLogicalDriveStringsW
  115. * GetLongPathNameA
  116. * GetLongPathNameW
  117. * GetShortPathNameW
  118. * GetTempFileNameW
  119. * GetTempPathW
  120. * GetVolumeInformationByHandleW
  121. * GetVolumeInformationW
  122. * GetVolumeNameForVolumeMountPointW
  123. * GetVolumePathNamesForVolumeNameW
  124. * GetVolumePathNameW
  125. * QueryDosDeviceW
  126. * SetFileAttributesA
  127. * SetFileAttributesW
  128. * SetFileTime
  129. * SetFileValidData
  130. * SetFileInformationByHandle
  131. * ReadFile
  132. * ReadFileEx
  133. * ReadFileScatter
  134. * WriteFile
  135. * WriteFileEx
  136. * WriteFileGather
  137. * FlushFileBuffers
  138. * SetEndOfFile
  139. * SetFilePointer
  140. * SetFilePointerEx
  141. * LockFile
  142. * LockFileEx
  143. * UnlockFile
  144. * UnlockFileEx
  145. */
  146. /**
  147. * File System Behavior in the Microsoft Windows Environment:
  148. * http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf
  149. */
  150. /**
  151. * Asynchronous I/O - The GNU C Library:
  152. * http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html
  153. */
  154. /**
  155. * aio.h - asynchronous input and output:
  156. * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html
  157. */
  158. /**
  159. * Asynchronous I/O User Guide:
  160. * http://code.google.com/p/kernel/wiki/AIOUserGuide
  161. */
  162. #define EPOCH_DIFF 11644473600LL
  163. #define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
  164. static wArrayList* _HandleCreators;
  165. static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
  166. extern HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void);
  167. #if defined __linux__ && !defined ANDROID
  168. extern HANDLE_CREATOR* GetCommHandleCreator(void);
  169. #endif /* __linux__ && !defined ANDROID */
  170. static void _HandleCreatorsInit()
  171. {
  172. assert(_HandleCreators == NULL);
  173. _HandleCreators = ArrayList_New(TRUE);
  174. if (!_HandleCreators)
  175. return;
  176. /*
  177. * Register all file handle creators.
  178. */
  179. ArrayList_Add(_HandleCreators, GetNamedPipeClientHandleCreator());
  180. #if defined __linux__ && !defined ANDROID
  181. ArrayList_Add(_HandleCreators, GetCommHandleCreator());
  182. #endif /* __linux__ && !defined ANDROID */
  183. ArrayList_Add(_HandleCreators, GetFileHandleCreator());
  184. }
  185. #ifdef HAVE_AIO_H
  186. static BOOL g_AioSignalHandlerInstalled = FALSE;
  187. void AioSignalHandler(int signum, siginfo_t* siginfo, void* arg)
  188. {
  189. WLog_INFO("%d", signum);
  190. }
  191. int InstallAioSignalHandler()
  192. {
  193. if (!g_AioSignalHandlerInstalled)
  194. {
  195. struct sigaction action;
  196. sigemptyset(&action.sa_mask);
  197. sigaddset(&action.sa_mask, SIGIO);
  198. action.sa_flags = SA_SIGINFO;
  199. action.sa_sigaction = (void*)&AioSignalHandler;
  200. sigaction(SIGIO, &action, NULL);
  201. g_AioSignalHandlerInstalled = TRUE;
  202. }
  203. return 0;
  204. }
  205. #endif /* HAVE_AIO_H */
  206. HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
  207. LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
  208. DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  209. {
  210. int i;
  211. if (!lpFileName)
  212. return INVALID_HANDLE_VALUE;
  213. if (pthread_once(&_HandleCreatorsInitialized, _HandleCreatorsInit) != 0)
  214. {
  215. SetLastError(ERROR_DLL_INIT_FAILED);
  216. return INVALID_HANDLE_VALUE;
  217. }
  218. if (_HandleCreators == NULL)
  219. {
  220. SetLastError(ERROR_DLL_INIT_FAILED);
  221. return INVALID_HANDLE_VALUE;
  222. }
  223. ArrayList_Lock(_HandleCreators);
  224. for (i = 0; i <= ArrayList_Count(_HandleCreators); i++)
  225. {
  226. HANDLE_CREATOR* creator = ArrayList_GetItem(_HandleCreators, i);
  227. if (creator && creator->IsHandled(lpFileName))
  228. {
  229. HANDLE newHandle =
  230. creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  231. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  232. ArrayList_Unlock(_HandleCreators);
  233. return newHandle;
  234. }
  235. }
  236. ArrayList_Unlock(_HandleCreators);
  237. return INVALID_HANDLE_VALUE;
  238. }
  239. HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
  240. LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
  241. DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  242. {
  243. LPSTR lpFileNameA = NULL;
  244. HANDLE hdl;
  245. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1)
  246. return NULL;
  247. hdl = CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  248. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  249. free(lpFileNameA);
  250. return hdl;
  251. }
  252. BOOL DeleteFileA(LPCSTR lpFileName)
  253. {
  254. int status;
  255. status = unlink(lpFileName);
  256. return (status != -1) ? TRUE : FALSE;
  257. }
  258. BOOL DeleteFileW(LPCWSTR lpFileName)
  259. {
  260. LPSTR lpFileNameA = NULL;
  261. BOOL rc = FALSE;
  262. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1)
  263. return FALSE;
  264. rc = DeleteFileA(lpFileNameA);
  265. free(lpFileNameA);
  266. return rc;
  267. }
  268. BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
  269. LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
  270. {
  271. ULONG Type;
  272. WINPR_HANDLE* handle;
  273. if (hFile == INVALID_HANDLE_VALUE)
  274. return FALSE;
  275. /*
  276. * from http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx
  277. * lpNumberOfBytesRead can be NULL only when the lpOverlapped parameter is not NULL.
  278. */
  279. if (!lpNumberOfBytesRead && !lpOverlapped)
  280. return FALSE;
  281. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  282. return FALSE;
  283. handle = (WINPR_HANDLE*)hFile;
  284. if (handle->ops->ReadFile)
  285. return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
  286. lpOverlapped);
  287. WLog_ERR(TAG, "ReadFile operation not implemented");
  288. return FALSE;
  289. }
  290. BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
  291. LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
  292. {
  293. ULONG Type;
  294. WINPR_HANDLE* handle;
  295. if (hFile == INVALID_HANDLE_VALUE)
  296. return FALSE;
  297. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  298. return FALSE;
  299. handle = (WINPR_HANDLE*)hFile;
  300. if (handle->ops->ReadFileEx)
  301. return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead, lpOverlapped,
  302. lpCompletionRoutine);
  303. WLog_ERR(TAG, "ReadFileEx operation not implemented");
  304. return FALSE;
  305. return TRUE;
  306. }
  307. BOOL ReadFileScatter(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead,
  308. LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
  309. {
  310. ULONG Type;
  311. WINPR_HANDLE* handle;
  312. if (hFile == INVALID_HANDLE_VALUE)
  313. return FALSE;
  314. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  315. return FALSE;
  316. handle = (WINPR_HANDLE*)hFile;
  317. if (handle->ops->ReadFileScatter)
  318. return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead, lpReserved,
  319. lpOverlapped);
  320. WLog_ERR(TAG, "ReadFileScatter operation not implemented");
  321. return FALSE;
  322. }
  323. BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
  324. LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  325. {
  326. ULONG Type;
  327. WINPR_HANDLE* handle;
  328. if (hFile == INVALID_HANDLE_VALUE)
  329. return FALSE;
  330. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  331. return FALSE;
  332. handle = (WINPR_HANDLE*)hFile;
  333. if (handle->ops->WriteFile)
  334. return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
  335. lpNumberOfBytesWritten, lpOverlapped);
  336. WLog_ERR(TAG, "WriteFile operation not implemented");
  337. return FALSE;
  338. }
  339. BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
  340. LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
  341. {
  342. ULONG Type;
  343. WINPR_HANDLE* handle;
  344. if (hFile == INVALID_HANDLE_VALUE)
  345. return FALSE;
  346. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  347. return FALSE;
  348. handle = (WINPR_HANDLE*)hFile;
  349. if (handle->ops->WriteFileEx)
  350. return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite, lpOverlapped,
  351. lpCompletionRoutine);
  352. WLog_ERR(TAG, "WriteFileEx operation not implemented");
  353. return FALSE;
  354. }
  355. BOOL WriteFileGather(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
  356. DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
  357. {
  358. ULONG Type;
  359. WINPR_HANDLE* handle;
  360. if (hFile == INVALID_HANDLE_VALUE)
  361. return FALSE;
  362. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  363. return FALSE;
  364. handle = (WINPR_HANDLE*)hFile;
  365. if (handle->ops->WriteFileGather)
  366. return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
  367. lpReserved, lpOverlapped);
  368. WLog_ERR(TAG, "WriteFileGather operation not implemented");
  369. return FALSE;
  370. }
  371. BOOL FlushFileBuffers(HANDLE hFile)
  372. {
  373. ULONG Type;
  374. WINPR_HANDLE* handle;
  375. if (hFile == INVALID_HANDLE_VALUE)
  376. return FALSE;
  377. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  378. return FALSE;
  379. handle = (WINPR_HANDLE*)hFile;
  380. if (handle->ops->FlushFileBuffers)
  381. return handle->ops->FlushFileBuffers(handle);
  382. WLog_ERR(TAG, "FlushFileBuffers operation not implemented");
  383. return FALSE;
  384. }
  385. BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
  386. LPVOID lpFileInformation)
  387. {
  388. LPWIN32_FILE_ATTRIBUTE_DATA fd = lpFileInformation;
  389. WIN32_FIND_DATAA findFileData;
  390. HANDLE hFind;
  391. if (!fd)
  392. return FALSE;
  393. if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
  394. return FALSE;
  395. FindClose(hFind);
  396. fd->dwFileAttributes = findFileData.dwFileAttributes;
  397. fd->ftCreationTime = findFileData.ftCreationTime;
  398. fd->ftLastAccessTime = findFileData.ftLastAccessTime;
  399. fd->ftLastWriteTime = findFileData.ftLastWriteTime;
  400. fd->nFileSizeHigh = findFileData.nFileSizeHigh;
  401. fd->nFileSizeLow = findFileData.nFileSizeLow;
  402. return TRUE;
  403. }
  404. BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
  405. LPVOID lpFileInformation)
  406. {
  407. BOOL ret;
  408. LPSTR lpCFileName;
  409. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
  410. {
  411. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  412. return FALSE;
  413. }
  414. ret = GetFileAttributesExA(lpCFileName, fInfoLevelId, lpFileInformation);
  415. free(lpCFileName);
  416. return ret;
  417. }
  418. DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
  419. {
  420. WIN32_FIND_DATAA findFileData;
  421. HANDLE hFind;
  422. if ((hFind = FindFirstFileA(lpFileName, &findFileData)) == INVALID_HANDLE_VALUE)
  423. return INVALID_FILE_ATTRIBUTES;
  424. FindClose(hFind);
  425. return findFileData.dwFileAttributes;
  426. }
  427. DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
  428. {
  429. DWORD ret;
  430. LPSTR lpCFileName;
  431. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
  432. {
  433. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  434. return FALSE;
  435. }
  436. ret = GetFileAttributesA(lpCFileName);
  437. free(lpCFileName);
  438. return ret;
  439. }
  440. BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
  441. {
  442. struct stat st;
  443. if (stat(lpFileName, &st) != 0)
  444. {
  445. return FALSE;
  446. }
  447. if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
  448. {
  449. st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  450. }
  451. else
  452. {
  453. st.st_mode |= S_IWUSR;
  454. }
  455. if (chmod(lpFileName, st.st_mode) != 0)
  456. {
  457. return FALSE;
  458. }
  459. return TRUE;
  460. }
  461. BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
  462. {
  463. BOOL ret;
  464. LPSTR lpCFileName;
  465. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
  466. {
  467. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  468. return FALSE;
  469. }
  470. ret = SetFileAttributesA(lpCFileName, dwFileAttributes);
  471. free(lpCFileName);
  472. return ret;
  473. }
  474. BOOL SetEndOfFile(HANDLE hFile)
  475. {
  476. ULONG Type;
  477. WINPR_HANDLE* handle;
  478. if (hFile == INVALID_HANDLE_VALUE)
  479. return FALSE;
  480. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  481. return FALSE;
  482. handle = (WINPR_HANDLE*)hFile;
  483. if (handle->ops->SetEndOfFile)
  484. return handle->ops->SetEndOfFile(handle);
  485. WLog_ERR(TAG, "SetEndOfFile operation not implemented");
  486. return FALSE;
  487. }
  488. DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
  489. {
  490. ULONG Type;
  491. WINPR_HANDLE* handle;
  492. if (hFile == INVALID_HANDLE_VALUE)
  493. return FALSE;
  494. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  495. return FALSE;
  496. handle = (WINPR_HANDLE*)hFile;
  497. if (handle->ops->GetFileSize)
  498. return handle->ops->GetFileSize(handle, lpFileSizeHigh);
  499. WLog_ERR(TAG, "GetFileSize operation not implemented");
  500. return 0;
  501. }
  502. BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime)
  503. {
  504. ULONG Type;
  505. WINPR_HANDLE* handle;
  506. if(hFile == INVALID_HANDLE_VALUE) {
  507. return FALSE;
  508. }
  509. if(!winpr_Handle_GetInfo(hFile, &Type, &handle)) {
  510. return FALSE;
  511. }
  512. handle = (WINPR_HANDLE*)hFile;
  513. if(handle->ops->GetFileTime)
  514. return handle->ops->GetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
  515. WLog_ERR(TAG, "GetFileTime operation not implemented");
  516. return FALSE;
  517. }
  518. DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
  519. DWORD dwMoveMethod)
  520. {
  521. ULONG Type;
  522. WINPR_HANDLE* handle;
  523. if (hFile == INVALID_HANDLE_VALUE)
  524. return FALSE;
  525. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  526. return FALSE;
  527. handle = (WINPR_HANDLE*)hFile;
  528. if (handle->ops->SetFilePointer)
  529. return handle->ops->SetFilePointer(handle, lDistanceToMove, lpDistanceToMoveHigh,
  530. dwMoveMethod);
  531. WLog_ERR(TAG, "SetFilePointer operation not implemented");
  532. return 0;
  533. }
  534. BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
  535. DWORD dwMoveMethod)
  536. {
  537. ULONG Type;
  538. WINPR_HANDLE* handle;
  539. if (hFile == INVALID_HANDLE_VALUE)
  540. return FALSE;
  541. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  542. return FALSE;
  543. handle = (WINPR_HANDLE*)hFile;
  544. if (handle->ops->SetFilePointerEx)
  545. return handle->ops->SetFilePointerEx(handle, liDistanceToMove, lpNewFilePointer,
  546. dwMoveMethod);
  547. WLog_ERR(TAG, "SetFilePointerEx operation not implemented");
  548. return 0;
  549. }
  550. BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
  551. DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
  552. {
  553. ULONG Type;
  554. WINPR_HANDLE* handle;
  555. if (hFile == INVALID_HANDLE_VALUE)
  556. return FALSE;
  557. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  558. return FALSE;
  559. handle = (WINPR_HANDLE*)hFile;
  560. if (handle->ops->LockFile)
  561. return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
  562. nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
  563. WLog_ERR(TAG, "LockFile operation not implemented");
  564. return FALSE;
  565. }
  566. BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow,
  567. DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)
  568. {
  569. ULONG Type;
  570. WINPR_HANDLE* handle;
  571. if (hFile == INVALID_HANDLE_VALUE)
  572. return FALSE;
  573. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  574. return FALSE;
  575. handle = (WINPR_HANDLE*)hFile;
  576. if (handle->ops->LockFileEx)
  577. return handle->ops->LockFileEx(handle, dwFlags, dwReserved, nNumberOfBytesToLockLow,
  578. nNumberOfBytesToLockHigh, lpOverlapped);
  579. WLog_ERR(TAG, "LockFileEx operation not implemented");
  580. return FALSE;
  581. }
  582. BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
  583. DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
  584. {
  585. ULONG Type;
  586. WINPR_HANDLE* handle;
  587. if (hFile == INVALID_HANDLE_VALUE)
  588. return FALSE;
  589. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  590. return FALSE;
  591. handle = (WINPR_HANDLE*)hFile;
  592. if (handle->ops->UnlockFile)
  593. return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
  594. nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
  595. WLog_ERR(TAG, "UnLockFile operation not implemented");
  596. return FALSE;
  597. }
  598. BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
  599. DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
  600. {
  601. ULONG Type;
  602. WINPR_HANDLE* handle;
  603. if (hFile == INVALID_HANDLE_VALUE)
  604. return FALSE;
  605. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  606. return FALSE;
  607. handle = (WINPR_HANDLE*)hFile;
  608. if (handle->ops->UnlockFileEx)
  609. return handle->ops->UnlockFileEx(handle, dwReserved, nNumberOfBytesToUnlockLow,
  610. nNumberOfBytesToUnlockHigh, lpOverlapped);
  611. WLog_ERR(TAG, "UnLockFileEx operation not implemented");
  612. return FALSE;
  613. }
  614. BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
  615. const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
  616. {
  617. ULONG Type;
  618. WINPR_HANDLE* handle;
  619. if (hFile == INVALID_HANDLE_VALUE)
  620. return FALSE;
  621. if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
  622. return FALSE;
  623. handle = (WINPR_HANDLE*)hFile;
  624. if (handle->ops->SetFileTime)
  625. return handle->ops->SetFileTime(handle, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
  626. WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
  627. return FALSE;
  628. }
  629. struct _WIN32_FILE_SEARCH
  630. {
  631. DIR* pDir;
  632. LPSTR lpPath;
  633. LPSTR lpPattern;
  634. struct dirent* pDirent;
  635. };
  636. typedef struct _WIN32_FILE_SEARCH WIN32_FILE_SEARCH;
  637. static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
  638. LPWIN32_FIND_DATAA lpFindFileData)
  639. {
  640. UINT64 ft;
  641. char* lastSep;
  642. lpFindFileData->dwFileAttributes = 0;
  643. if (S_ISDIR(fileStat->st_mode))
  644. lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  645. if (lpFindFileData->dwFileAttributes == 0)
  646. lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
  647. lastSep = strrchr(path, '/');
  648. if (lastSep)
  649. {
  650. const char* name = lastSep + 1;
  651. const size_t namelen = strlen(name);
  652. if ((namelen > 1) && (name[0] == '.') && (name[1] != '.'))
  653. lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
  654. }
  655. if (!(fileStat->st_mode & S_IWUSR))
  656. lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
  657. #ifdef _DARWIN_FEATURE_64_BIT_INODE
  658. ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
  659. #else
  660. ft = STAT_TIME_TO_FILETIME(fileStat->st_ctime);
  661. #endif
  662. lpFindFileData->ftCreationTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
  663. lpFindFileData->ftCreationTime.dwLowDateTime = ft & 0xFFFFFFFF;
  664. ft = STAT_TIME_TO_FILETIME(fileStat->st_mtime);
  665. lpFindFileData->ftLastWriteTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
  666. lpFindFileData->ftLastWriteTime.dwLowDateTime = ft & 0xFFFFFFFF;
  667. ft = STAT_TIME_TO_FILETIME(fileStat->st_atime);
  668. lpFindFileData->ftLastAccessTime.dwHighDateTime = ((UINT64)ft) >> 32ULL;
  669. lpFindFileData->ftLastAccessTime.dwLowDateTime = ft & 0xFFFFFFFF;
  670. lpFindFileData->nFileSizeHigh = ((UINT64)fileStat->st_size) >> 32ULL;
  671. lpFindFileData->nFileSizeLow = fileStat->st_size & 0xFFFFFFFF;
  672. return TRUE;
  673. }
  674. HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
  675. {
  676. BOOL isDir = FALSE;
  677. struct stat fileStat;
  678. WIN32_FILE_SEARCH* pFileSearch;
  679. if (!lpFindFileData || !lpFileName)
  680. {
  681. SetLastError(ERROR_BAD_ARGUMENTS);
  682. return INVALID_HANDLE_VALUE;
  683. }
  684. ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
  685. pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH));
  686. if (!pFileSearch)
  687. {
  688. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  689. return INVALID_HANDLE_VALUE;
  690. }
  691. if (stat(lpFileName, &fileStat) >= 0)
  692. {
  693. isDir = (S_ISDIR(fileStat.st_mode) != 0);
  694. }
  695. else
  696. errno = 0;
  697. if (isDir)
  698. {
  699. pFileSearch->lpPath = _strdup(lpFileName);
  700. pFileSearch->lpPattern = _strdup(".");
  701. }
  702. else
  703. {
  704. LPSTR p;
  705. size_t index;
  706. size_t length;
  707. /* Separate lpFileName into path and pattern components */
  708. p = strrchr(lpFileName, '/');
  709. if (!p)
  710. p = strrchr(lpFileName, '\\');
  711. index = (p - lpFileName);
  712. length = (p - lpFileName) + 1;
  713. pFileSearch->lpPath = (LPSTR)malloc(length + 1);
  714. if (!pFileSearch->lpPath)
  715. {
  716. free(pFileSearch);
  717. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  718. return INVALID_HANDLE_VALUE;
  719. }
  720. CopyMemory(pFileSearch->lpPath, lpFileName, length);
  721. pFileSearch->lpPath[length] = '\0';
  722. length = strlen(lpFileName) - index;
  723. pFileSearch->lpPattern = (LPSTR)malloc(length + 1);
  724. if (!pFileSearch->lpPattern)
  725. {
  726. free(pFileSearch->lpPath);
  727. free(pFileSearch);
  728. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  729. return INVALID_HANDLE_VALUE;
  730. }
  731. CopyMemory(pFileSearch->lpPattern, &lpFileName[index + 1], length);
  732. pFileSearch->lpPattern[length] = '\0';
  733. /* Check if the path is a directory */
  734. if (stat(pFileSearch->lpPath, &fileStat) < 0)
  735. {
  736. FindClose(pFileSearch);
  737. SetLastError(map_posix_err(errno));
  738. errno = 0;
  739. return INVALID_HANDLE_VALUE; /* stat error */
  740. }
  741. if (S_ISDIR(fileStat.st_mode) == 0)
  742. {
  743. FindClose(pFileSearch);
  744. return INVALID_HANDLE_VALUE; /* not a directory */
  745. }
  746. }
  747. /* Open directory for reading */
  748. pFileSearch->pDir = opendir(pFileSearch->lpPath);
  749. if (!pFileSearch->pDir)
  750. {
  751. FindClose(pFileSearch);
  752. SetLastError(map_posix_err(errno));
  753. errno = 0;
  754. return INVALID_HANDLE_VALUE; /* failed to open directory */
  755. }
  756. if (FindNextFileA((HANDLE)pFileSearch, lpFindFileData))
  757. {
  758. if (isDir)
  759. {
  760. const char* name = strrchr(lpFileName, '/');
  761. if (!name)
  762. name = lpFileName;
  763. else
  764. name++;
  765. pFileSearch->lpPattern[0] = '*';
  766. sprintf_s(lpFindFileData->cFileName, ARRAYSIZE(lpFindFileData->cFileName), "%s", name);
  767. }
  768. return (HANDLE)pFileSearch;
  769. }
  770. FindClose(pFileSearch);
  771. return INVALID_HANDLE_VALUE;
  772. }
  773. static BOOL ConvertFindDataAToW(LPWIN32_FIND_DATAA lpFindFileDataA,
  774. LPWIN32_FIND_DATAW lpFindFileDataW)
  775. {
  776. size_t length;
  777. WCHAR* unicodeFileName;
  778. if (!lpFindFileDataA || !lpFindFileDataW)
  779. return FALSE;
  780. lpFindFileDataW->dwFileAttributes = lpFindFileDataA->dwFileAttributes;
  781. lpFindFileDataW->ftCreationTime = lpFindFileDataA->ftCreationTime;
  782. lpFindFileDataW->ftLastAccessTime = lpFindFileDataA->ftLastAccessTime;
  783. lpFindFileDataW->ftLastWriteTime = lpFindFileDataA->ftLastWriteTime;
  784. lpFindFileDataW->nFileSizeHigh = lpFindFileDataA->nFileSizeHigh;
  785. lpFindFileDataW->nFileSizeLow = lpFindFileDataA->nFileSizeLow;
  786. lpFindFileDataW->dwReserved0 = lpFindFileDataA->dwReserved0;
  787. lpFindFileDataW->dwReserved1 = lpFindFileDataA->dwReserved1;
  788. unicodeFileName = NULL;
  789. length = ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cFileName, -1, &unicodeFileName, 0);
  790. if (length == 0)
  791. return FALSE;
  792. if (length > MAX_PATH)
  793. length = MAX_PATH;
  794. CopyMemory(lpFindFileDataW->cFileName, unicodeFileName, length * sizeof(WCHAR));
  795. free(unicodeFileName);
  796. length =
  797. ConvertToUnicode(CP_UTF8, 0, lpFindFileDataA->cAlternateFileName, -1, &unicodeFileName, 0);
  798. if (length == 0)
  799. return TRUE;
  800. if (length > 14)
  801. length = 14;
  802. CopyMemory(lpFindFileDataW->cAlternateFileName, unicodeFileName, length * sizeof(WCHAR));
  803. free(unicodeFileName);
  804. return TRUE;
  805. }
  806. HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)
  807. {
  808. LPSTR utfFileName = NULL;
  809. HANDLE h;
  810. LPWIN32_FIND_DATAA fd = (LPWIN32_FIND_DATAA)calloc(1, sizeof(WIN32_FIND_DATAA));
  811. if (!fd)
  812. {
  813. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  814. return INVALID_HANDLE_VALUE;
  815. }
  816. if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &utfFileName, 0, NULL, NULL) <= 0)
  817. {
  818. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  819. free(fd);
  820. return INVALID_HANDLE_VALUE;
  821. }
  822. h = FindFirstFileA(utfFileName, fd);
  823. free(utfFileName);
  824. if (h != INVALID_HANDLE_VALUE)
  825. {
  826. if (!ConvertFindDataAToW(fd, lpFindFileData))
  827. {
  828. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  829. FindClose(h);
  830. h = INVALID_HANDLE_VALUE;
  831. goto out;
  832. }
  833. }
  834. out:
  835. free(fd);
  836. return h;
  837. }
  838. HANDLE FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
  839. FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
  840. {
  841. return INVALID_HANDLE_VALUE;
  842. }
  843. HANDLE FindFirstFileExW(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData,
  844. FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags)
  845. {
  846. return INVALID_HANDLE_VALUE;
  847. }
  848. BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
  849. {
  850. WIN32_FILE_SEARCH* pFileSearch;
  851. struct stat fileStat;
  852. char* fullpath;
  853. size_t pathlen;
  854. size_t namelen;
  855. if (!hFindFile || !lpFindFileData)
  856. return FALSE;
  857. if (hFindFile == INVALID_HANDLE_VALUE)
  858. return FALSE;
  859. ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
  860. pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
  861. while ((pFileSearch->pDirent = readdir(pFileSearch->pDir)) != NULL)
  862. {
  863. if (FilePatternMatchA(pFileSearch->pDirent->d_name, pFileSearch->lpPattern))
  864. {
  865. BOOL success;
  866. strncpy(lpFindFileData->cFileName, pFileSearch->pDirent->d_name, MAX_PATH);
  867. namelen = strnlen(lpFindFileData->cFileName, MAX_PATH);
  868. pathlen = strlen(pFileSearch->lpPath);
  869. fullpath = (char*)malloc(pathlen + namelen + 2);
  870. if (fullpath == NULL)
  871. {
  872. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  873. return FALSE;
  874. }
  875. memcpy(fullpath, pFileSearch->lpPath, pathlen);
  876. /* Ensure path is terminated with a separator, but prevent
  877. * duplicate separators */
  878. if (fullpath[pathlen - 1] != '/')
  879. fullpath[pathlen++] = '/';
  880. memcpy(fullpath + pathlen, pFileSearch->pDirent->d_name, namelen);
  881. fullpath[pathlen + namelen] = 0;
  882. if (stat(fullpath, &fileStat) != 0)
  883. {
  884. free(fullpath);
  885. SetLastError(map_posix_err(errno));
  886. errno = 0;
  887. continue;
  888. }
  889. /* Skip FIFO entries. */
  890. if (S_ISFIFO(fileStat.st_mode))
  891. {
  892. free(fullpath);
  893. continue;
  894. }
  895. success = FindDataFromStat(fullpath, &fileStat, lpFindFileData);
  896. free(fullpath);
  897. return success;
  898. }
  899. }
  900. SetLastError(ERROR_NO_MORE_FILES);
  901. return FALSE;
  902. }
  903. BOOL FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData)
  904. {
  905. LPWIN32_FIND_DATAA fd = (LPWIN32_FIND_DATAA)calloc(1, sizeof(WIN32_FIND_DATAA));
  906. if (!fd)
  907. {
  908. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  909. return FALSE;
  910. }
  911. if (FindNextFileA(hFindFile, fd))
  912. {
  913. if (!ConvertFindDataAToW(fd, lpFindFileData))
  914. {
  915. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  916. free(fd);
  917. return FALSE;
  918. }
  919. free(fd);
  920. return TRUE;
  921. }
  922. free(fd);
  923. return FALSE;
  924. }
  925. BOOL FindClose(HANDLE hFindFile)
  926. {
  927. WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)hFindFile;
  928. /* Since INVALID_HANDLE_VALUE != NULL the analyzer guesses that there
  929. * is a initialized HANDLE that is not freed properly.
  930. * Disable this return to stop confusing the analyzer. */
  931. #ifndef __clang_analyzer__
  932. if (!pFileSearch || (pFileSearch == INVALID_HANDLE_VALUE))
  933. return FALSE;
  934. #endif
  935. free(pFileSearch->lpPath);
  936. free(pFileSearch->lpPattern);
  937. if (pFileSearch->pDir)
  938. closedir(pFileSearch->pDir);
  939. free(pFileSearch);
  940. return TRUE;
  941. }
  942. BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  943. {
  944. if (!mkdir(lpPathName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
  945. SetLastError(STATUS_SUCCESS);
  946. UnixChangeFileMode(lpPathName, 0xFFF);
  947. return TRUE;
  948. }
  949. SetLastError(map_posix_err(errno));
  950. return FALSE;
  951. }
  952. BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  953. {
  954. char* utfPathName = NULL;
  955. BOOL ret;
  956. if (ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL) <= 0)
  957. {
  958. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  959. return FALSE;
  960. }
  961. ret = CreateDirectoryA(utfPathName, lpSecurityAttributes);
  962. free(utfPathName);
  963. return ret;
  964. }
  965. BOOL RemoveDirectoryA(LPCSTR lpPathName)
  966. {
  967. int ret = rmdir(lpPathName);
  968. if (ret != 0)
  969. SetLastError(map_posix_err(errno));
  970. else
  971. SetLastError(STATUS_SUCCESS);
  972. return ret == 0;
  973. }
  974. BOOL RemoveDirectoryW(LPCWSTR lpPathName)
  975. {
  976. char* utfPathName = NULL;
  977. BOOL ret;
  978. if (ConvertFromUnicode(CP_UTF8, 0, lpPathName, -1, &utfPathName, 0, NULL, NULL) <= 0)
  979. {
  980. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  981. return FALSE;
  982. }
  983. ret = RemoveDirectoryA(utfPathName);
  984. free(utfPathName);
  985. return ret;
  986. }
  987. BOOL MoveFileExA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
  988. {
  989. struct stat st;
  990. int ret;
  991. ret = stat(lpNewFileName, &st);
  992. if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == 0)
  993. {
  994. if (ret == 0)
  995. {
  996. SetLastError(ERROR_ALREADY_EXISTS);
  997. return FALSE;
  998. }
  999. }
  1000. else
  1001. {
  1002. if (ret == 0 && (st.st_mode & S_IWUSR) == 0)
  1003. {
  1004. SetLastError(ERROR_ACCESS_DENIED);
  1005. return FALSE;
  1006. }
  1007. }
  1008. ret = rename(lpExistingFileName, lpNewFileName);
  1009. UnixChangeFileMode(lpNewFileName, 0xFFF);
  1010. if (ret != 0)
  1011. SetLastError(map_posix_err(errno));
  1012. return ret == 0;
  1013. }
  1014. BOOL MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags)
  1015. {
  1016. LPSTR lpCExistingFileName;
  1017. LPSTR lpCNewFileName;
  1018. BOOL ret;
  1019. if (ConvertFromUnicode(CP_UTF8, 0, lpExistingFileName, -1, &lpCExistingFileName, 0, NULL,
  1020. NULL) <= 0)
  1021. {
  1022. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1023. return FALSE;
  1024. }
  1025. if (ConvertFromUnicode(CP_UTF8, 0, lpNewFileName, -1, &lpCNewFileName, 0, NULL, NULL) <= 0)
  1026. {
  1027. free(lpCExistingFileName);
  1028. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1029. return FALSE;
  1030. }
  1031. ret = MoveFileExA(lpCExistingFileName, lpCNewFileName, dwFlags);
  1032. free(lpCNewFileName);
  1033. free(lpCExistingFileName);
  1034. return ret;
  1035. }
  1036. BOOL MoveFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
  1037. {
  1038. return MoveFileExA(lpExistingFileName, lpNewFileName, 0);
  1039. }
  1040. BOOL MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  1041. {
  1042. return MoveFileExW(lpExistingFileName, lpNewFileName, 0);
  1043. }
  1044. BOOL CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName,BOOL bFailIfExists)
  1045. {
  1046. char buffer[1024];
  1047. int len, n;
  1048. int fd_to_read, fd_to_write;
  1049. int exist = 0;
  1050. if (access(lpNewFileName, F_OK) == 0)
  1051. exist = 1;
  1052. if (!!exist && bFailIfExists) {
  1053. SetLastError(ERROR_ALREADY_EXISTS);
  1054. return FALSE;
  1055. }
  1056. fd_to_read = open(lpExistingFileName, O_RDONLY);
  1057. if(fd_to_read == -1) {
  1058. WLog_WARN(TAG, "open the source file %s failed: %s", lpExistingFileName, strerror(errno));
  1059. SetLastError(ERROR_FILE_NOT_FOUND);
  1060. return FALSE;
  1061. }
  1062. fd_to_write = open(lpNewFileName, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR|S_IXUSR);
  1063. if(fd_to_write == -1) {
  1064. WLog_ERR(TAG, "open the dest file %s failed: %s", lpNewFileName, strerror(errno));
  1065. SetLastError(ERROR_CREATE_FAILED);
  1066. close(fd_to_read);
  1067. return FALSE;
  1068. }
  1069. if (exist) {
  1070. ftruncate(fd_to_write, 0);
  1071. lseek(fd_to_write, 0, SEEK_SET);
  1072. }
  1073. while((len = read(fd_to_read, buffer, 1024))) {
  1074. n = write(fd_to_write, buffer, len);
  1075. if(n != len) {
  1076. SetLastError(ERROR_PARTIAL_COPY);
  1077. WLog_ERR(TAG, "cp stream from src file %s to file %s failed: %s", lpExistingFileName, lpNewFileName, strerror(errno));
  1078. close(fd_to_read);
  1079. close(fd_to_write);
  1080. return FALSE;
  1081. }
  1082. }
  1083. close(fd_to_read);
  1084. close(fd_to_write);
  1085. UnixChangeFileMode(lpNewFileName, 0xFFF);
  1086. #ifdef _DEBUG
  1087. struct stat statsrc;
  1088. if (stat(lpExistingFileName, &statsrc) == 0) {
  1089. WLog_DBG(TAG, "src file %s size: %d", lpExistingFileName, statsrc.st_size);
  1090. }
  1091. struct stat statdst;
  1092. if (stat(lpNewFileName, &statdst) == 0) {
  1093. WLog_DBG(TAG, "dst file %s size: %d", lpNewFileName, statsrc.st_size);
  1094. }
  1095. #endif // _DEBUG
  1096. return TRUE;
  1097. }
  1098. BOOL CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
  1099. {
  1100. LPSTR lpCExistingFileName;
  1101. LPSTR lpCNewFileName;
  1102. BOOL ret;
  1103. if (ConvertFromUnicode(CP_UTF8, 0, lpExistingFileName, -1, &lpCExistingFileName, 0, NULL,
  1104. NULL) <= 0)
  1105. {
  1106. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1107. return FALSE;
  1108. }
  1109. if (ConvertFromUnicode(CP_UTF8, 0, lpNewFileName, -1, &lpCNewFileName, 0, NULL, NULL) <= 0)
  1110. {
  1111. free(lpCExistingFileName);
  1112. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1113. return FALSE;
  1114. }
  1115. ret = CopyFileA(lpCExistingFileName, lpCNewFileName, bFailIfExists);
  1116. free(lpCNewFileName);
  1117. free(lpCExistingFileName);
  1118. return ret;
  1119. }
  1120. //BOOL SystemTimeToFileTime(CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime)
  1121. //{
  1122. // SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1123. // return FALSE;
  1124. //}
  1125. #if 0
  1126. BOOL FileTimeToLocalFileTime(CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime)
  1127. {
  1128. LARGE_INTEGER local, utc;
  1129. LONG bias;
  1130. TIME_ZONE_INFORMATION tz;
  1131. DWORD dwRes;
  1132. utc.u.LowPart = lpFileTime->dwLowDateTime;
  1133. utc.u.HighPart = lpFileTime->dwHighDateTime;
  1134. {
  1135. dwRes = GetTimeZoneInformation(&tz);
  1136. if(dwRes != 0) {
  1137. bias = tz.Bias;
  1138. /* 1 ... TIME_ZONE_ID_STANDARD
  1139. * 2 ... TIME_ZONE_ID_DAYLIGHT
  1140. */
  1141. bias += dwRes == 1 ? tz.StandardBias : tz.DaylightBias;
  1142. bias *= SECSPERMIN;
  1143. }
  1144. local.QuadPart = utc.QuadPart - bias * (LONGLONG)TICKSPERSEC;
  1145. }
  1146. lpLocalFileTime->dwLowDateTime = local.u.LowPart;
  1147. lpLocalFileTime->dwHighDateTime = local.u.HighPart;
  1148. return TRUE;
  1149. }
  1150. #else
  1151. //BOOL FileTimeToLocalFileTime(CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime)
  1152. //{
  1153. // LARGE_INTEGER local, utc;
  1154. // LONG bias;
  1155. // TIME_ZONE_INFORMATION tz;
  1156. // DWORD dwRes;
  1157. //
  1158. // utc.u.LowPart = lpFileTime->dwLowDateTime;
  1159. // utc.u.HighPart = lpFileTime->dwHighDateTime;
  1160. //
  1161. // {
  1162. // dwRes = GetTimeZoneInformation(&tz);
  1163. // if(dwRes != 0) {
  1164. // bias = tz.Bias;
  1165. // /* 1 ... TIME_ZONE_ID_STANDARD
  1166. // * 2 ... TIME_ZONE_ID_DAYLIGHT
  1167. // */
  1168. // bias += dwRes == 2 ? tz.DaylightBias : tz.StandardBias;
  1169. // bias *= SECSPERMIN;
  1170. // } else {
  1171. // WLog_DBG(TAG, "GetTimeZoneInformation return zero !");
  1172. // bias = tz.Bias;
  1173. // bias += tz.StandardBias;
  1174. // bias *= SECSPERMIN;
  1175. // }
  1176. //
  1177. // local.QuadPart = utc.QuadPart - bias * (LONGLONG)TICKSPERSEC;
  1178. // }
  1179. //
  1180. // lpLocalFileTime->dwLowDateTime = local.u.LowPart;
  1181. // lpLocalFileTime->dwHighDateTime = local.u.HighPart;
  1182. //
  1183. // return TRUE;
  1184. //}
  1185. #endif
  1186. BOOL LocalFileTimeToFileTime(CONST FILETIME *lpLocalFileTime, LPFILETIME lpFileTime)
  1187. {
  1188. WLog_ERR(TAG, "TODO: %s not implemented!", __FUNCTION__);
  1189. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1190. return FALSE;
  1191. }
  1192. //BOOL FileTimeToSystemTime(CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime)
  1193. //{
  1194. // SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1195. // return FALSE;
  1196. //}
  1197. LONG CompareFileTime(CONST FILETIME *lpFileTime1, CONST FILETIME *lpFileTime2)
  1198. {
  1199. WLog_ERR(TAG, "TODO: %s not implemented!", __FUNCTION__);
  1200. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1201. return FALSE;
  1202. }
  1203. BOOL FileTimeToDosDateTime(CONST FILETIME *lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime)
  1204. {
  1205. WLog_ERR(TAG, "TODO: %s not implemented!", __FUNCTION__);
  1206. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1207. *lpFatDate = 0;
  1208. *lpFatTime = 0;
  1209. return FALSE;
  1210. }
  1211. BOOL DosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime)
  1212. {
  1213. WLog_ERR(TAG, "TODO: %s not implemented!", __FUNCTION__);
  1214. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1215. return FALSE;
  1216. }
  1217. #endif
  1218. /* Extended API */
  1219. int UnixChangeFileMode(const char* filename, int flags)
  1220. {
  1221. #ifndef _WIN32
  1222. mode_t fl = 0;
  1223. int res = 0;
  1224. mode_t fm = umask(0);
  1225. fl |= (flags & 0x4000) ? S_ISUID : 0;
  1226. fl |= (flags & 0x2000) ? S_ISGID : 0;
  1227. fl |= (flags & 0x1000) ? S_ISVTX : 0;
  1228. fl |= (flags & 0x0400) ? S_IRUSR : 0;
  1229. fl |= (flags & 0x0200) ? S_IWUSR : 0;
  1230. fl |= (flags & 0x0100) ? S_IXUSR : 0;
  1231. fl |= (flags & 0x0040) ? S_IRGRP : 0;
  1232. fl |= (flags & 0x0020) ? S_IWGRP : 0;
  1233. fl |= (flags & 0x0010) ? S_IXGRP : 0;
  1234. fl |= (flags & 0x0004) ? S_IROTH : 0;
  1235. fl |= (flags & 0x0002) ? S_IWOTH : 0;
  1236. fl |= (flags & 0x0001) ? S_IXOTH : 0;
  1237. res = chmod(filename, fl);
  1238. umask(fm);
  1239. return res;
  1240. #else
  1241. int rc;
  1242. WCHAR* wfl = NULL;
  1243. int fl = 0;
  1244. if (ConvertToUnicode(CP_UTF8, 0, filename, -1, &wfl, 0) <= 0)
  1245. return -1;
  1246. /* Check for unsupported flags. */
  1247. if (flags & ~(_S_IREAD | _S_IWRITE))
  1248. WLog_WARN(TAG, "Unsupported file mode %d for _wchmod", flags);
  1249. rc = _wchmod(wfl, flags);
  1250. free(wfl);
  1251. return rc;
  1252. #endif
  1253. }