file.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * File Functions
  4. *
  5. * Copyright 2015 Thincast Technologies GmbH
  6. * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
  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 /* HAVE_CONFIG_H */
  24. #if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
  25. #define _GNU_SOURCE
  26. #define KFREEBSD
  27. #endif
  28. #include <winpr/wtypes.h>
  29. #include <winpr/crt.h>
  30. #include <winpr/file.h>
  31. #ifdef _WIN32
  32. #include <io.h>
  33. #else /* _WIN32 */
  34. #include "../log.h"
  35. #define TAG WINPR_TAG("file")
  36. #include <winpr/wlog.h>
  37. #include <winpr/string.h>
  38. #include "file.h"
  39. #include <errno.h>
  40. #include <fcntl.h>
  41. #include <sys/file.h>
  42. #include <sys/stat.h>
  43. #include <sys/time.h>
  44. #ifdef ANDROID
  45. #include <sys/vfs.h>
  46. #else
  47. #include <sys/statvfs.h>
  48. #endif
  49. #define EPOCH_DIFF_MACRO 11644473600LL
  50. #define STAT_TIME_TO_FILETIME(_t) (((UINT64)(_t) + EPOCH_DIFF_MACRO) * 10000000LL)
  51. static BOOL FileIsHandled(HANDLE handle)
  52. {
  53. WINPR_FILE* pFile = (WINPR_FILE*)handle;
  54. if (!pFile || (pFile->Type != HANDLE_TYPE_FILE))
  55. {
  56. SetLastError(ERROR_INVALID_HANDLE);
  57. return FALSE;
  58. }
  59. return TRUE;
  60. }
  61. static int FileGetFd(HANDLE handle)
  62. {
  63. WINPR_FILE* file = (WINPR_FILE*)handle;
  64. if (!FileIsHandled(handle))
  65. return -1;
  66. return fileno(file->fp);
  67. }
  68. static BOOL FileCloseHandle(HANDLE handle)
  69. {
  70. WINPR_FILE* file = (WINPR_FILE*)handle;
  71. if (!FileIsHandled(handle))
  72. return FALSE;
  73. if (file->fp)
  74. {
  75. /* Don't close stdin/stdout/stderr */
  76. if (fileno(file->fp) > 2)
  77. {
  78. fclose(file->fp);
  79. file->fp = NULL;
  80. }
  81. }
  82. free(file->lpFileName);
  83. free(file);
  84. return TRUE;
  85. }
  86. static BOOL FileSetEndOfFile(HANDLE hFile)
  87. {
  88. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  89. INT64 size;
  90. if (!hFile)
  91. return FALSE;
  92. size = _ftelli64(pFile->fp);
  93. if (ftruncate(fileno(pFile->fp), size) < 0)
  94. {
  95. WLog_ERR(TAG, "ftruncate %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
  96. errno);
  97. SetLastError(map_posix_err(errno));
  98. return FALSE;
  99. }
  100. return TRUE;
  101. }
  102. static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
  103. DWORD dwMoveMethod)
  104. {
  105. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  106. INT64 offset;
  107. int whence;
  108. if (!hFile)
  109. return INVALID_SET_FILE_POINTER;
  110. /* If there is a high part, the sign is contained in that
  111. * and the low integer must be interpreted as unsigned. */
  112. if (lpDistanceToMoveHigh)
  113. {
  114. offset = (INT64)(((UINT64)*lpDistanceToMoveHigh << 32U) | (UINT64)lDistanceToMove);
  115. }
  116. else
  117. offset = lDistanceToMove;
  118. switch (dwMoveMethod)
  119. {
  120. case FILE_BEGIN:
  121. whence = SEEK_SET;
  122. break;
  123. case FILE_END:
  124. whence = SEEK_END;
  125. break;
  126. case FILE_CURRENT:
  127. whence = SEEK_CUR;
  128. break;
  129. default:
  130. return INVALID_SET_FILE_POINTER;
  131. }
  132. if (_fseeki64(pFile->fp, offset, whence))
  133. {
  134. WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
  135. errno);
  136. return INVALID_SET_FILE_POINTER;
  137. }
  138. return _ftelli64(pFile->fp);
  139. }
  140. static BOOL FileSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
  141. PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
  142. {
  143. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  144. int whence;
  145. if (!hFile)
  146. return FALSE;
  147. switch (dwMoveMethod)
  148. {
  149. case FILE_BEGIN:
  150. whence = SEEK_SET;
  151. break;
  152. case FILE_END:
  153. whence = SEEK_END;
  154. break;
  155. case FILE_CURRENT:
  156. whence = SEEK_CUR;
  157. break;
  158. default:
  159. return FALSE;
  160. }
  161. if (_fseeki64(pFile->fp, liDistanceToMove.QuadPart, whence))
  162. {
  163. WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
  164. errno);
  165. return FALSE;
  166. }
  167. if (lpNewFilePointer)
  168. lpNewFilePointer->QuadPart = _ftelli64(pFile->fp);
  169. return TRUE;
  170. }
  171. static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
  172. LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
  173. {
  174. size_t io_status;
  175. WINPR_FILE* file;
  176. BOOL status = TRUE;
  177. if (lpOverlapped)
  178. {
  179. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  180. SetLastError(ERROR_NOT_SUPPORTED);
  181. return FALSE;
  182. }
  183. if (!Object)
  184. return FALSE;
  185. file = (WINPR_FILE*)Object;
  186. clearerr(file->fp);
  187. io_status = fread(lpBuffer, 1, nNumberOfBytesToRead, file->fp);
  188. if (io_status == 0 ) {
  189. if (ferror(file->fp)) {
  190. status = FALSE;
  191. switch (errno) {
  192. case EWOULDBLOCK:
  193. SetLastError(ERROR_NO_DATA);
  194. break;
  195. default:
  196. SetLastError(map_posix_err(errno));
  197. }
  198. }
  199. WLog_ERR(TAG, "fread(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno);
  200. }
  201. if (lpNumberOfBytesRead)
  202. *lpNumberOfBytesRead = io_status;
  203. return status;
  204. }
  205. static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
  206. LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  207. {
  208. size_t io_status;
  209. WINPR_FILE* file;
  210. if (lpOverlapped)
  211. {
  212. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  213. SetLastError(ERROR_NOT_SUPPORTED);
  214. return FALSE;
  215. }
  216. if (!Object)
  217. return FALSE;
  218. file = (WINPR_FILE*)Object;
  219. clearerr(file->fp);
  220. io_status = fwrite(lpBuffer, 1, nNumberOfBytesToWrite, file->fp);
  221. if (io_status == 0 && ferror(file->fp))
  222. {
  223. SetLastError(map_posix_err(errno));
  224. return FALSE;
  225. }
  226. *lpNumberOfBytesWritten = io_status;
  227. return TRUE;
  228. }
  229. static BOOL FileBufferFlush(PVOID Object)
  230. {
  231. WINPR_FILE* file;
  232. INT64 cur, size;
  233. if (!Object)
  234. return FALSE;
  235. file = (WINPR_FILE*)Object;
  236. /*commit buffer cache to disk.*/
  237. if(syncfs(file->fp) == 0)
  238. {
  239. WLog_ERR(TAG, "syncfs(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno), errno);
  240. return FALSE;
  241. }
  242. return TRUE;
  243. }
  244. static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
  245. {
  246. WINPR_FILE* file;
  247. INT64 cur, size;
  248. if (!Object)
  249. return 0;
  250. file = (WINPR_FILE*)Object;
  251. cur = _ftelli64(file->fp);
  252. if (cur < 0)
  253. {
  254. WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
  255. errno);
  256. return INVALID_FILE_SIZE;
  257. }
  258. if (_fseeki64(file->fp, 0, SEEK_END) != 0)
  259. {
  260. WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
  261. errno);
  262. return INVALID_FILE_SIZE;
  263. }
  264. size = _ftelli64(file->fp);
  265. if (size < 0)
  266. {
  267. WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
  268. errno);
  269. return INVALID_FILE_SIZE;
  270. }
  271. if (_fseeki64(file->fp, cur, SEEK_SET) != 0)
  272. {
  273. WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
  274. errno);
  275. return INVALID_FILE_SIZE;
  276. }
  277. if (lpFileSizeHigh)
  278. *lpFileSizeHigh = 0;
  279. return size;
  280. }
  281. static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
  282. DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
  283. LPOVERLAPPED lpOverlapped)
  284. {
  285. #ifdef __sun
  286. struct flock lock;
  287. int lckcmd;
  288. #else
  289. int lock;
  290. #endif
  291. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  292. if (lpOverlapped)
  293. {
  294. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  295. SetLastError(ERROR_NOT_SUPPORTED);
  296. return FALSE;
  297. }
  298. if (!hFile)
  299. return FALSE;
  300. if (pFile->bLocked)
  301. {
  302. WLog_ERR(TAG, "File %s already locked!", pFile->lpFileName);
  303. return FALSE;
  304. }
  305. #ifdef __sun
  306. lock.l_start = 0;
  307. lock.l_len = 0;
  308. lock.l_whence = SEEK_SET;
  309. if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
  310. lock.l_type = F_WRLCK;
  311. else
  312. lock.l_type = F_WRLCK;
  313. if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
  314. lckcmd = F_SETLK;
  315. else
  316. lckcmd = F_SETLKW;
  317. if (fcntl(fileno(pFile->fp), lckcmd, &lock) == -1)
  318. {
  319. WLog_ERR(TAG, "F_SETLK failed with %s [0x%08X]", strerror(errno), errno);
  320. return FALSE;
  321. }
  322. #else
  323. if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
  324. lock = LOCK_EX;
  325. else
  326. lock = LOCK_SH;
  327. if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
  328. lock |= LOCK_NB;
  329. if (flock(fileno(pFile->fp), lock) < 0)
  330. {
  331. WLog_ERR(TAG, "flock failed with %s [0x%08X]", strerror(errno), errno);
  332. return FALSE;
  333. }
  334. #endif
  335. pFile->bLocked = TRUE;
  336. return TRUE;
  337. }
  338. static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
  339. DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
  340. {
  341. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  342. #ifdef __sun
  343. struct flock lock;
  344. #endif
  345. if (!hFile)
  346. return FALSE;
  347. if (!pFile->bLocked)
  348. {
  349. WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName);
  350. return FALSE;
  351. }
  352. #ifdef __sun
  353. lock.l_start = 0;
  354. lock.l_len = 0;
  355. lock.l_whence = SEEK_SET;
  356. lock.l_type = F_UNLCK;
  357. if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
  358. {
  359. WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
  360. errno);
  361. return FALSE;
  362. }
  363. #else
  364. if (flock(fileno(pFile->fp), LOCK_UN) < 0)
  365. {
  366. WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
  367. strerror(errno), errno);
  368. return FALSE;
  369. }
  370. #endif
  371. return TRUE;
  372. }
  373. static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
  374. DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
  375. {
  376. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  377. #ifdef __sun
  378. struct flock lock;
  379. #endif
  380. if (lpOverlapped)
  381. {
  382. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  383. SetLastError(ERROR_NOT_SUPPORTED);
  384. return FALSE;
  385. }
  386. if (!hFile)
  387. return FALSE;
  388. if (!pFile->bLocked)
  389. {
  390. WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName);
  391. return FALSE;
  392. }
  393. #ifdef __sun
  394. lock.l_start = 0;
  395. lock.l_len = 0;
  396. lock.l_whence = SEEK_SET;
  397. lock.l_type = F_UNLCK;
  398. if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
  399. {
  400. WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
  401. errno);
  402. return FALSE;
  403. }
  404. #else
  405. if (flock(fileno(pFile->fp), LOCK_UN) < 0)
  406. {
  407. WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
  408. strerror(errno), errno);
  409. return FALSE;
  410. }
  411. #endif
  412. return TRUE;
  413. }
  414. static UINT64 FileTimeToUS(const FILETIME* ft)
  415. {
  416. const UINT64 EPOCH_DIFF = 11644473600ULL * 1000000ULL;
  417. UINT64 tmp = ((UINT64)ft->dwHighDateTime) << 32 | ft->dwLowDateTime;
  418. tmp /= 10; /* 100ns steps to 1us step */
  419. tmp -= EPOCH_DIFF;
  420. return tmp;
  421. }
  422. static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
  423. const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
  424. {
  425. int rc;
  426. #if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
  427. struct stat buf;
  428. /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */
  429. struct timeval timevals[2];
  430. #else
  431. struct timespec times[2]; /* last access, last modification */
  432. #endif
  433. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  434. if (!hFile)
  435. return FALSE;
  436. #if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
  437. rc = fstat(fileno(pFile->fp), &buf);
  438. if (rc < 0)
  439. return FALSE;
  440. #endif
  441. if (!lpLastAccessTime)
  442. {
  443. #if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
  444. timevals[0].tv_sec = buf.st_atime;
  445. #ifdef _POSIX_SOURCE
  446. TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim);
  447. #else
  448. TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atimespec);
  449. #endif
  450. #elif defined(ANDROID)
  451. timevals[0].tv_sec = buf.st_atime;
  452. timevals[0].tv_usec = buf.st_atimensec / 1000UL;
  453. #else
  454. times[0].tv_sec = UTIME_OMIT;
  455. times[0].tv_nsec = UTIME_OMIT;
  456. #endif
  457. }
  458. else
  459. {
  460. UINT64 tmp = FileTimeToUS(lpLastAccessTime);
  461. #if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
  462. timevals[0].tv_sec = tmp / 1000000ULL;
  463. timevals[0].tv_usec = tmp % 1000000ULL;
  464. #else
  465. times[0].tv_sec = tmp / 1000000ULL;
  466. times[0].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
  467. #endif
  468. }
  469. if (!lpLastWriteTime)
  470. {
  471. #if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
  472. timevals[1].tv_sec = buf.st_mtime;
  473. #ifdef _POSIX_SOURCE
  474. TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim);
  475. #else
  476. TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtimespec);
  477. #endif
  478. #elif defined(ANDROID)
  479. timevals[1].tv_sec = buf.st_mtime;
  480. timevals[1].tv_usec = buf.st_mtimensec / 1000UL;
  481. #else
  482. times[1].tv_sec = UTIME_OMIT;
  483. times[1].tv_nsec = UTIME_OMIT;
  484. #endif
  485. }
  486. else
  487. {
  488. UINT64 tmp = FileTimeToUS(lpLastWriteTime);
  489. #if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
  490. timevals[1].tv_sec = tmp / 1000000ULL;
  491. timevals[1].tv_usec = tmp % 1000000ULL;
  492. #else
  493. times[1].tv_sec = tmp / 1000000ULL;
  494. times[1].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
  495. #endif
  496. }
  497. // TODO: Creation time can not be handled!
  498. #if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
  499. rc = utimes(pFile->lpFileName, timevals);
  500. #else
  501. rc = futimens(fileno(pFile->fp), times);
  502. #endif
  503. if (rc != 0)
  504. return FALSE;
  505. return TRUE;
  506. }
  507. static BOOL FileGetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime)
  508. {
  509. int rc;
  510. UINT64 ft;
  511. struct stat buf;
  512. WINPR_FILE* pFile = (WINPR_FILE*)hFile;
  513. if(!hFile) {
  514. return FALSE;
  515. }
  516. rc = fstat(fileno(pFile->fp), &buf);
  517. if(rc < 0) {
  518. return FALSE;
  519. }
  520. if(lpCreationTime) {
  521. ft = STAT_TIME_TO_FILETIME(buf.st_ctime);
  522. lpCreationTime->dwHighDateTime = ((UINT64)ft) >> 32ULL;
  523. lpCreationTime->dwLowDateTime = ft & 0xFFFFFFFF;
  524. }
  525. if(lpLastAccessTime) {
  526. ft = STAT_TIME_TO_FILETIME(buf.st_atime);
  527. lpLastAccessTime->dwHighDateTime = ((UINT64)ft) >> 32ULL;
  528. lpLastAccessTime->dwLowDateTime = ft & 0xFFFFFFFF;
  529. }
  530. if(lpLastWriteTime) {
  531. ft = STAT_TIME_TO_FILETIME(buf.st_mtime);
  532. lpLastWriteTime->dwHighDateTime = ((UINT64)ft) >> 32ULL;
  533. lpLastWriteTime->dwLowDateTime = ft & 0xFFFFFFFF;
  534. }
  535. return TRUE;
  536. }
  537. static HANDLE_OPS fileOps = { FileIsHandled,
  538. FileCloseHandle,
  539. FileGetFd,
  540. NULL, /* CleanupHandle */
  541. FileRead,
  542. NULL, /* FileReadEx */
  543. NULL, /* FileReadScatter */
  544. FileWrite,
  545. NULL, /* FileWriteEx */
  546. NULL, /* FileWriteGather */
  547. FileGetFileSize,
  548. FileBufferFlush, /* FlushFileBuffers */
  549. FileSetEndOfFile,
  550. FileSetFilePointer,
  551. FileSetFilePointerEx,
  552. NULL, /* FileLockFile */
  553. FileLockFileEx,
  554. FileUnlockFile,
  555. FileUnlockFileEx,
  556. FileSetFileTime,
  557. FileGetFileTime
  558. };
  559. static HANDLE_OPS shmOps = {
  560. FileIsHandled, FileCloseHandle,
  561. FileGetFd, NULL, /* CleanupHandle */
  562. FileRead, NULL, /* FileReadEx */
  563. NULL, /* FileReadScatter */
  564. FileWrite, NULL, /* FileWriteEx */
  565. NULL, /* FileWriteGather */
  566. NULL, /* FileGetFileSize */
  567. NULL, /* FlushFileBuffers */
  568. NULL, /* FileSetEndOfFile */
  569. NULL, /* FileSetFilePointer */
  570. NULL, /* SetFilePointerEx */
  571. NULL, /* FileLockFile */
  572. NULL, /* FileLockFileEx */
  573. NULL, /* FileUnlockFile */
  574. NULL, /* FileUnlockFileEx */
  575. NULL /* FileSetFileTime */
  576. };
  577. static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create)
  578. {
  579. BOOL writeable = (dwDesiredAccess & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
  580. switch (dwCreationDisposition)
  581. {
  582. case CREATE_ALWAYS:
  583. *create = TRUE;
  584. return (writeable) ? "wb+" : "rwb";
  585. case CREATE_NEW:
  586. *create = TRUE;
  587. return "wb+";
  588. case OPEN_ALWAYS:
  589. *create = TRUE;
  590. return "rb+";
  591. case OPEN_EXISTING:
  592. *create = FALSE;
  593. return (writeable) ? "rb+" : "rb";
  594. case TRUNCATE_EXISTING:
  595. *create = FALSE;
  596. return "wb+";
  597. default:
  598. *create = FALSE;
  599. return "";
  600. }
  601. }
  602. UINT32 map_posix_err(int fs_errno)
  603. {
  604. UINT32 rc;
  605. /* try to return NTSTATUS version of error code */
  606. switch (fs_errno)
  607. {
  608. case 0:
  609. rc = STATUS_SUCCESS;
  610. break;
  611. case ENOTCONN:
  612. case ENODEV:
  613. case ENOTDIR:
  614. case ENXIO:
  615. rc = ERROR_FILE_NOT_FOUND;
  616. break;
  617. case EROFS:
  618. case EPERM:
  619. case EACCES:
  620. rc = ERROR_ACCESS_DENIED;
  621. break;
  622. case ENOENT:
  623. rc = ERROR_FILE_NOT_FOUND;
  624. break;
  625. case EBUSY:
  626. rc = ERROR_BUSY_DRIVE;
  627. break;
  628. case EEXIST:
  629. rc = ERROR_FILE_EXISTS;
  630. break;
  631. case EISDIR:
  632. rc = STATUS_FILE_IS_A_DIRECTORY;
  633. break;
  634. case ENOTEMPTY:
  635. rc = STATUS_DIRECTORY_NOT_EMPTY;
  636. break;
  637. default:
  638. WLog_ERR(TAG, "Missing ERRNO mapping %s [%d]", strerror(fs_errno), fs_errno);
  639. rc = STATUS_UNSUCCESSFUL;
  640. break;
  641. }
  642. return rc;
  643. }
  644. static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
  645. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  646. DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
  647. HANDLE hTemplateFile)
  648. {
  649. WINPR_FILE* pFile;
  650. BOOL create;
  651. const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create);
  652. #ifdef __sun
  653. struct flock lock;
  654. #else
  655. int lock = 0;
  656. #endif
  657. FILE* fp = NULL;
  658. struct stat st;
  659. if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
  660. {
  661. WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
  662. SetLastError(ERROR_NOT_SUPPORTED);
  663. return INVALID_HANDLE_VALUE;
  664. }
  665. pFile = (WINPR_FILE*)calloc(1, sizeof(WINPR_FILE));
  666. if (!pFile)
  667. {
  668. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  669. return INVALID_HANDLE_VALUE;
  670. }
  671. WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
  672. pFile->ops = &fileOps;
  673. pFile->lpFileName = _strdup(lpFileName);
  674. if (!pFile->lpFileName)
  675. {
  676. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  677. free(pFile);
  678. return INVALID_HANDLE_VALUE;
  679. }
  680. pFile->dwOpenMode = dwDesiredAccess;
  681. pFile->dwShareMode = dwShareMode;
  682. pFile->dwFlagsAndAttributes = dwFlagsAndAttributes;
  683. pFile->lpSecurityAttributes = lpSecurityAttributes;
  684. pFile->dwCreationDisposition = dwCreationDisposition;
  685. pFile->hTemplateFile = hTemplateFile;
  686. if (create)
  687. {
  688. if (dwCreationDisposition == CREATE_NEW)
  689. {
  690. if (stat(pFile->lpFileName, &st) == 0)
  691. {
  692. SetLastError(ERROR_FILE_EXISTS);
  693. free(pFile->lpFileName);
  694. free(pFile);
  695. return INVALID_HANDLE_VALUE;
  696. }
  697. }
  698. fp = fopen(pFile->lpFileName, "ab");
  699. if (!fp)
  700. {
  701. SetLastError(map_posix_err(errno));
  702. free(pFile->lpFileName);
  703. free(pFile);
  704. return INVALID_HANDLE_VALUE;
  705. }
  706. fp = freopen(pFile->lpFileName, mode, fp);
  707. }
  708. else
  709. {
  710. if (stat(pFile->lpFileName, &st) != 0)
  711. {
  712. SetLastError(map_posix_err(errno));
  713. free(pFile->lpFileName);
  714. free(pFile);
  715. return INVALID_HANDLE_VALUE;
  716. }
  717. /* FIFO (named pipe) would block the following fopen
  718. * call if not connected. This renders the channel unusable,
  719. * therefore abort early. */
  720. if (S_ISFIFO(st.st_mode))
  721. {
  722. SetLastError(ERROR_FILE_NOT_FOUND);
  723. free(pFile->lpFileName);
  724. free(pFile);
  725. return INVALID_HANDLE_VALUE;
  726. }
  727. }
  728. if (NULL == fp)
  729. fp = fopen(pFile->lpFileName, mode);
  730. pFile->fp = fp;
  731. if (!pFile->fp)
  732. {
  733. /* This case can occur when trying to open a
  734. * not existing file without create flag. */
  735. SetLastError(map_posix_err(errno));
  736. free(pFile->lpFileName);
  737. free(pFile);
  738. return INVALID_HANDLE_VALUE;
  739. }
  740. setvbuf(fp, NULL, _IONBF, 0);
  741. #ifdef __sun
  742. lock.l_start = 0;
  743. lock.l_len = 0;
  744. lock.l_whence = SEEK_SET;
  745. if (dwShareMode & FILE_SHARE_READ)
  746. lock.l_type = F_RDLCK;
  747. if (dwShareMode & FILE_SHARE_WRITE)
  748. lock.l_type = F_RDLCK;
  749. #else
  750. if (dwShareMode & FILE_SHARE_READ)
  751. lock = LOCK_SH;
  752. if (dwShareMode & FILE_SHARE_WRITE)
  753. lock = LOCK_EX;
  754. #endif
  755. if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE))
  756. {
  757. #ifdef __sun
  758. if (fcntl(fileno(pFile->fp), F_SETLKW, &lock) == -1)
  759. #else
  760. if (flock(fileno(pFile->fp), lock) < 0)
  761. #endif
  762. {
  763. #ifdef __sun
  764. WLog_ERR(TAG, "F_SETLKW failed with %s [0x%08X]",
  765. #else
  766. WLog_ERR(TAG, "flock failed with %s [0x%08X]",
  767. #endif
  768. strerror(errno), errno);
  769. SetLastError(map_posix_err(errno));
  770. FileCloseHandle(pFile);
  771. return INVALID_HANDLE_VALUE;
  772. }
  773. pFile->bLocked = TRUE;
  774. }
  775. if (fstat(fileno(pFile->fp), &st) == 0 && dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
  776. {
  777. st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  778. fchmod(fileno(pFile->fp), st.st_mode);
  779. }
  780. SetLastError(STATUS_SUCCESS);
  781. return pFile;
  782. }
  783. static BOOL IsFileDevice(LPCTSTR lpDeviceName)
  784. {
  785. return TRUE;
  786. }
  787. HANDLE_CREATOR _FileHandleCreator = { IsFileDevice, FileCreateFileA };
  788. HANDLE_CREATOR* GetFileHandleCreator(void)
  789. {
  790. return &_FileHandleCreator;
  791. }
  792. static WINPR_FILE* FileHandle_New(FILE* fp)
  793. {
  794. WINPR_FILE* pFile;
  795. char name[MAX_PATH];
  796. _snprintf(name, sizeof(name), "device_%d", fileno(fp));
  797. pFile = (WINPR_FILE*)calloc(1, sizeof(WINPR_FILE));
  798. if (!pFile)
  799. {
  800. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  801. return NULL;
  802. }
  803. pFile->fp = fp;
  804. pFile->ops = &shmOps;
  805. pFile->lpFileName = _strdup(name);
  806. WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
  807. return pFile;
  808. }
  809. HANDLE GetStdHandle(DWORD nStdHandle)
  810. {
  811. FILE* fp;
  812. WINPR_FILE* pFile;
  813. switch (nStdHandle)
  814. {
  815. case STD_INPUT_HANDLE:
  816. fp = stdin;
  817. break;
  818. case STD_OUTPUT_HANDLE:
  819. fp = stdout;
  820. break;
  821. case STD_ERROR_HANDLE:
  822. fp = stderr;
  823. break;
  824. default:
  825. return INVALID_HANDLE_VALUE;
  826. }
  827. pFile = FileHandle_New(fp);
  828. if (!pFile)
  829. return INVALID_HANDLE_VALUE;
  830. return (HANDLE)pFile;
  831. }
  832. BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
  833. {
  834. return FALSE;
  835. }
  836. BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
  837. {
  838. return FALSE;
  839. }
  840. BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
  841. LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
  842. {
  843. #if defined(ANDROID)
  844. #define STATVFS statfs
  845. #else
  846. #define STATVFS statvfs
  847. #endif
  848. struct STATVFS svfst;
  849. STATVFS(lpRootPathName, &svfst);
  850. *lpSectorsPerCluster = svfst.f_frsize;
  851. *lpBytesPerSector = 1;
  852. *lpNumberOfFreeClusters = svfst.f_bavail;
  853. *lpTotalNumberOfClusters = svfst.f_blocks;
  854. return TRUE;
  855. }
  856. BOOL GetDiskFreeSpaceW(LPCWSTR lpwRootPathName, LPDWORD lpSectorsPerCluster,
  857. LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
  858. LPDWORD lpTotalNumberOfClusters)
  859. {
  860. LPSTR lpRootPathName;
  861. BOOL ret;
  862. if (ConvertFromUnicode(CP_UTF8, 0, lpwRootPathName, -1, &lpRootPathName, 0, NULL, NULL) <= 0)
  863. {
  864. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  865. return FALSE;
  866. }
  867. ret = GetDiskFreeSpaceA(lpRootPathName, lpSectorsPerCluster, lpBytesPerSector,
  868. lpNumberOfFreeClusters, lpTotalNumberOfClusters);
  869. free(lpRootPathName);
  870. return ret;
  871. }
  872. /**
  873. * Check if a file name component is valid.
  874. *
  875. * Some file names are not valid on Windows. See "Naming Files, Paths, and Namespaces":
  876. * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
  877. */
  878. BOOL ValidFileNameComponent(LPCWSTR lpFileName)
  879. {
  880. LPCWSTR c = NULL;
  881. if (!lpFileName)
  882. return FALSE;
  883. /* CON */
  884. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'C' || lpFileName[0] == L'c')) &&
  885. (lpFileName[1] != L'\0' && (lpFileName[1] == L'O' || lpFileName[1] == L'o')) &&
  886. (lpFileName[2] != L'\0' && (lpFileName[2] == L'N' || lpFileName[2] == L'n')) &&
  887. (lpFileName[3] == L'\0'))
  888. {
  889. return FALSE;
  890. }
  891. /* PRN */
  892. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'P' || lpFileName[0] == L'p')) &&
  893. (lpFileName[1] != L'\0' && (lpFileName[1] == L'R' || lpFileName[1] == L'r')) &&
  894. (lpFileName[2] != L'\0' && (lpFileName[2] == L'N' || lpFileName[2] == L'n')) &&
  895. (lpFileName[3] == L'\0'))
  896. {
  897. return FALSE;
  898. }
  899. /* AUX */
  900. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'A' || lpFileName[0] == L'a')) &&
  901. (lpFileName[1] != L'\0' && (lpFileName[1] == L'U' || lpFileName[1] == L'u')) &&
  902. (lpFileName[2] != L'\0' && (lpFileName[2] == L'X' || lpFileName[2] == L'x')) &&
  903. (lpFileName[3] == L'\0'))
  904. {
  905. return FALSE;
  906. }
  907. /* NUL */
  908. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'N' || lpFileName[0] == L'n')) &&
  909. (lpFileName[1] != L'\0' && (lpFileName[1] == L'U' || lpFileName[1] == L'u')) &&
  910. (lpFileName[2] != L'\0' && (lpFileName[2] == L'L' || lpFileName[2] == L'l')) &&
  911. (lpFileName[3] == L'\0'))
  912. {
  913. return FALSE;
  914. }
  915. /* LPT0-9 */
  916. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'L' || lpFileName[0] == L'l')) &&
  917. (lpFileName[1] != L'\0' && (lpFileName[1] == L'P' || lpFileName[1] == L'p')) &&
  918. (lpFileName[2] != L'\0' && (lpFileName[2] == L'T' || lpFileName[2] == L't')) &&
  919. (lpFileName[3] != L'\0' && (L'0' <= lpFileName[3] && lpFileName[3] <= L'9')) &&
  920. (lpFileName[4] == L'\0'))
  921. {
  922. return FALSE;
  923. }
  924. /* COM0-9 */
  925. if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'C' || lpFileName[0] == L'c')) &&
  926. (lpFileName[1] != L'\0' && (lpFileName[1] == L'O' || lpFileName[1] == L'o')) &&
  927. (lpFileName[2] != L'\0' && (lpFileName[2] == L'M' || lpFileName[2] == L'm')) &&
  928. (lpFileName[3] != L'\0' && (L'0' <= lpFileName[3] && lpFileName[3] <= L'9')) &&
  929. (lpFileName[4] == L'\0'))
  930. {
  931. return FALSE;
  932. }
  933. /* Reserved characters */
  934. for (c = lpFileName; *c; c++)
  935. {
  936. if ((*c == L'<') || (*c == L'>') || (*c == L':') || (*c == L'"') || (*c == L'/') ||
  937. (*c == L'\\') || (*c == L'|') || (*c == L'?') || (*c == L'*'))
  938. {
  939. return FALSE;
  940. }
  941. }
  942. return TRUE;
  943. }
  944. #endif /* _WIN32 */
  945. #ifdef _UWP
  946. HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
  947. LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
  948. DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  949. {
  950. HANDLE hFile;
  951. CREATEFILE2_EXTENDED_PARAMETERS params;
  952. ZeroMemory(&params, sizeof(CREATEFILE2_EXTENDED_PARAMETERS));
  953. params.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
  954. if (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
  955. params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
  956. if (dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
  957. params.dwFileFlags |= FILE_FLAG_DELETE_ON_CLOSE;
  958. if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
  959. params.dwFileFlags |= FILE_FLAG_NO_BUFFERING;
  960. if (dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
  961. params.dwFileFlags |= FILE_FLAG_OPEN_NO_RECALL;
  962. if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
  963. params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
  964. if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REQUIRING_OPLOCK)
  965. params.dwFileFlags |= FILE_FLAG_OPEN_REQUIRING_OPLOCK;
  966. if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
  967. params.dwFileFlags |= FILE_FLAG_OVERLAPPED;
  968. if (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)
  969. params.dwFileFlags |= FILE_FLAG_POSIX_SEMANTICS;
  970. if (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
  971. params.dwFileFlags |= FILE_FLAG_RANDOM_ACCESS;
  972. if (dwFlagsAndAttributes & FILE_FLAG_SESSION_AWARE)
  973. params.dwFileFlags |= FILE_FLAG_SESSION_AWARE;
  974. if (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
  975. params.dwFileFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
  976. if (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
  977. params.dwFileFlags |= FILE_FLAG_WRITE_THROUGH;
  978. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ARCHIVE)
  979. params.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
  980. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_COMPRESSED)
  981. params.dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
  982. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DEVICE)
  983. params.dwFileAttributes |= FILE_ATTRIBUTE_DEVICE;
  984. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY)
  985. params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
  986. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ENCRYPTED)
  987. params.dwFileAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
  988. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_HIDDEN)
  989. params.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
  990. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM)
  991. params.dwFileAttributes |= FILE_ATTRIBUTE_INTEGRITY_STREAM;
  992. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NORMAL)
  993. params.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
  994. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
  995. params.dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
  996. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA)
  997. params.dwFileAttributes |= FILE_ATTRIBUTE_NO_SCRUB_DATA;
  998. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_OFFLINE)
  999. params.dwFileAttributes |= FILE_ATTRIBUTE_OFFLINE;
  1000. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
  1001. params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
  1002. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  1003. params.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
  1004. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SPARSE_FILE)
  1005. params.dwFileAttributes |= FILE_ATTRIBUTE_SPARSE_FILE;
  1006. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM)
  1007. params.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
  1008. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_TEMPORARY)
  1009. params.dwFileAttributes |= FILE_ATTRIBUTE_TEMPORARY;
  1010. if (dwFlagsAndAttributes & FILE_ATTRIBUTE_VIRTUAL)
  1011. params.dwFileAttributes |= FILE_ATTRIBUTE_VIRTUAL;
  1012. if (dwFlagsAndAttributes & SECURITY_ANONYMOUS)
  1013. params.dwSecurityQosFlags |= SECURITY_ANONYMOUS;
  1014. if (dwFlagsAndAttributes & SECURITY_CONTEXT_TRACKING)
  1015. params.dwSecurityQosFlags |= SECURITY_CONTEXT_TRACKING;
  1016. if (dwFlagsAndAttributes & SECURITY_DELEGATION)
  1017. params.dwSecurityQosFlags |= SECURITY_DELEGATION;
  1018. if (dwFlagsAndAttributes & SECURITY_EFFECTIVE_ONLY)
  1019. params.dwSecurityQosFlags |= SECURITY_EFFECTIVE_ONLY;
  1020. if (dwFlagsAndAttributes & SECURITY_IDENTIFICATION)
  1021. params.dwSecurityQosFlags |= SECURITY_IDENTIFICATION;
  1022. if (dwFlagsAndAttributes & SECURITY_IMPERSONATION)
  1023. params.dwSecurityQosFlags |= SECURITY_IMPERSONATION;
  1024. params.lpSecurityAttributes = lpSecurityAttributes;
  1025. params.hTemplateFile = hTemplateFile;
  1026. hFile = CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, &params);
  1027. return hFile;
  1028. }
  1029. HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
  1030. LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
  1031. DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  1032. {
  1033. HANDLE hFile;
  1034. WCHAR* lpFileNameW = NULL;
  1035. ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
  1036. if (!lpFileNameW)
  1037. return NULL;
  1038. hFile = CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
  1039. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  1040. free(lpFileNameW);
  1041. return hFile;
  1042. }
  1043. DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
  1044. {
  1045. BOOL status;
  1046. LARGE_INTEGER fileSize = { 0, 0 };
  1047. if (!lpFileSizeHigh)
  1048. return INVALID_FILE_SIZE;
  1049. status = GetFileSizeEx(hFile, &fileSize);
  1050. if (!status)
  1051. return INVALID_FILE_SIZE;
  1052. *lpFileSizeHigh = fileSize.HighPart;
  1053. return fileSize.LowPart;
  1054. }
  1055. /*move the file pointer of an open file*/
  1056. DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
  1057. DWORD dwMoveMethod)
  1058. {
  1059. BOOL status;
  1060. LARGE_INTEGER liDistanceToMove = { 0, 0 };
  1061. LARGE_INTEGER liNewFilePointer = { 0, 0 };
  1062. liDistanceToMove.LowPart = lDistanceToMove;
  1063. status = SetFilePointerEx(hFile, liDistanceToMove, &liNewFilePointer, dwMoveMethod);
  1064. if (!status)
  1065. return INVALID_SET_FILE_POINTER;
  1066. if (lpDistanceToMoveHigh)
  1067. *lpDistanceToMoveHigh = liNewFilePointer.HighPart;
  1068. return liNewFilePointer.LowPart;
  1069. }
  1070. HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
  1071. {
  1072. return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
  1073. NULL, 0);
  1074. }
  1075. HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)
  1076. {
  1077. return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
  1078. NULL, 0);
  1079. }
  1080. DWORD GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
  1081. {
  1082. DWORD dwStatus;
  1083. WCHAR* lpFileNameW = NULL;
  1084. WCHAR* lpBufferW = NULL;
  1085. WCHAR* lpFilePartW = NULL;
  1086. DWORD nBufferLengthW = nBufferLength * 2;
  1087. if (!lpFileName || (nBufferLength < 1))
  1088. return 0;
  1089. ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
  1090. if (!lpFileNameW)
  1091. return 0;
  1092. lpBufferW = (WCHAR*)malloc(nBufferLengthW);
  1093. if (!lpBufferW)
  1094. return 0;
  1095. dwStatus = GetFullPathNameW(lpFileNameW, nBufferLengthW, lpBufferW, &lpFilePartW);
  1096. ConvertFromUnicode(CP_UTF8, 0, lpBufferW, nBufferLengthW, &lpBuffer, nBufferLength, NULL, NULL);
  1097. if (lpFilePart)
  1098. lpFilePart = lpBuffer + (lpFilePartW - lpBufferW);
  1099. free(lpFileNameW);
  1100. free(lpBufferW);
  1101. return dwStatus * 2;
  1102. }
  1103. BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
  1104. LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
  1105. {
  1106. BOOL status;
  1107. ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
  1108. ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
  1109. ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
  1110. status = GetDiskFreeSpaceExA(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
  1111. &TotalNumberOfFreeBytes);
  1112. if (!status)
  1113. return FALSE;
  1114. *lpBytesPerSector = 1;
  1115. *lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
  1116. *lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
  1117. *lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
  1118. return TRUE;
  1119. }
  1120. BOOL GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
  1121. LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
  1122. LPDWORD lpTotalNumberOfClusters)
  1123. {
  1124. BOOL status;
  1125. ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
  1126. ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
  1127. ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
  1128. status = GetDiskFreeSpaceExW(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
  1129. &TotalNumberOfFreeBytes);
  1130. if (!status)
  1131. return FALSE;
  1132. *lpBytesPerSector = 1;
  1133. *lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
  1134. *lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
  1135. *lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
  1136. return TRUE;
  1137. }
  1138. DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
  1139. {
  1140. SetLastError(ERROR_INVALID_FUNCTION);
  1141. return 0;
  1142. }
  1143. DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer)
  1144. {
  1145. SetLastError(ERROR_INVALID_FUNCTION);
  1146. return 0;
  1147. }
  1148. BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
  1149. {
  1150. return FALSE;
  1151. }
  1152. UINT GetACP(void)
  1153. {
  1154. return CP_UTF8;
  1155. }
  1156. #endif
  1157. /* Extended API */
  1158. #ifdef _WIN32
  1159. #include <io.h>
  1160. #endif
  1161. HANDLE GetFileHandleForFileDescriptor(int fd)
  1162. {
  1163. #ifdef _WIN32
  1164. return (HANDLE)_get_osfhandle(fd);
  1165. #else /* _WIN32 */
  1166. WINPR_FILE* pFile;
  1167. FILE* fp;
  1168. int flags;
  1169. /* Make sure it's a valid fd */
  1170. if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
  1171. return INVALID_HANDLE_VALUE;
  1172. flags = fcntl(fd, F_GETFL);
  1173. if (flags == -1)
  1174. return INVALID_HANDLE_VALUE;
  1175. if (flags & O_WRONLY)
  1176. fp = fdopen(fd, "wb");
  1177. else
  1178. fp = fdopen(fd, "rb");
  1179. if (!fp)
  1180. return INVALID_HANDLE_VALUE;
  1181. setvbuf(fp, NULL, _IONBF, 0);
  1182. pFile = FileHandle_New(fp);
  1183. if (!pFile)
  1184. return INVALID_HANDLE_VALUE;
  1185. return (HANDLE)pFile;
  1186. #endif /* _WIN32 */
  1187. }