1 /* Copyright (c) MediaArea.net SARL. All Rights Reserved.
2 *
3 * Use of this source code is governed by a zlib-style license that can
4 * be found in the License.txt file in the root of the source tree.
5 */
6
7 //---------------------------------------------------------------------------
8 #include "ZenLib/PreComp.h"
9 #ifdef __BORLANDC__
10 #pragma hdrstop
11 #endif
12 //---------------------------------------------------------------------------
13
14 //---------------------------------------------------------------------------
15 #include "ZenLib/Conf_Internal.h"
16 //---------------------------------------------------------------------------
17
18 #include "ZenLib/FileName.h"
19 //---------------------------------------------------------------------------
20 #ifdef ZENLIB_USEWX
21 #include <wx/file.h>
22 #include <wx/filename.h>
23 #include <wx/utils.h>
24 #else //ZENLIB_USEWX
25 #ifdef ZENLIB_STANDARD
26 #ifdef WINDOWS
27 #else
28 #include <cstdio>
29 #endif
30 #include <sys/stat.h>
31 #if !defined(WINDOWS)
32 #include <unistd.h>
33 #endif //!defined(WINDOWS)
34 #include <fstream>
35 using namespace std;
36 #ifndef S_ISDIR
37 #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
38 #endif
39 #ifndef S_ISREG
40 #define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
41 #endif
42 #elif defined WINDOWS
43 #undef __TEXT
44 #include <windows.h>
45 #ifdef WINDOWS_UWP
46 #include <wrl.h>
47 #include <windows.foundation.h>
48 #include <windows.storage.h>
49 #include <windows.storage.accesscache.h>
50 using namespace Microsoft::WRL;
51 using namespace Microsoft::WRL::Wrappers;
52 using namespace ABI::Windows::Foundation;
53 using namespace ABI::Windows::Foundation::Collections;
54 using namespace ABI::Windows::Storage;
55 using namespace ABI::Windows::Storage::Streams;
56 using namespace ABI::Windows::Storage::FileProperties;
57 #endif
58 #endif
59 #endif //ZENLIB_USEWX
60 #include "ZenLib/OS_Utils.h"
61 #include "ZenLib/File.h"
62
63 //---------------------------------------------------------------------------
64 #ifdef WINDOWS_UWP
65 struct WrtFile
66 {
67 ComPtr<IStorageFile> File;
68 ComPtr<IRandomAccessStream> Buffer;
69 };
70 #endif
71
72 //---------------------------------------------------------------------------
73 namespace ZenLib
74 {
75
76 //---------------------------------------------------------------------------
77 // Debug
78 #ifdef ZENLIB_DEBUG
79 #include <stdio.h>
80 #include <windows.h>
81 namespace ZenLib_File_Debug
82 {
83 FILE* F;
84 std::string Debug;
85 SYSTEMTIME st_In;
86
Debug_Open(bool Out)87 void Debug_Open(bool Out)
88 {
89 F=fopen("C:\\Temp\\ZenLib_Debug.txt", "a+t");
90 Debug.clear();
91 SYSTEMTIME st;
92 GetLocalTime( &st );
93
94 char Duration[100];
95 if (Out)
96 {
97 FILETIME ft_In;
98 if (SystemTimeToFileTime(&st_In, &ft_In))
99 {
100 FILETIME ft_Out;
101 if (SystemTimeToFileTime(&st, &ft_Out))
102 {
103 ULARGE_INTEGER UI_In;
104 UI_In.HighPart=ft_In.dwHighDateTime;
105 UI_In.LowPart=ft_In.dwLowDateTime;
106
107 ULARGE_INTEGER UI_Out;
108 UI_Out.HighPart=ft_Out.dwHighDateTime;
109 UI_Out.LowPart=ft_Out.dwLowDateTime;
110
111 ULARGE_INTEGER UI_Diff;
112 UI_Diff.QuadPart=UI_Out.QuadPart-UI_In.QuadPart;
113
114 FILETIME ft_Diff;
115 ft_Diff.dwHighDateTime=UI_Diff.HighPart;
116 ft_Diff.dwLowDateTime=UI_Diff.LowPart;
117
118 SYSTEMTIME st_Diff;
119 if (FileTimeToSystemTime(&ft_Diff, &st_Diff))
120 {
121 sprintf(Duration, "%02hd:%02hd:%02hd.%03hd", st_Diff.wHour, st_Diff.wMinute, st_Diff.wSecond, st_Diff.wMilliseconds);
122 }
123 else
124 strcpy(Duration, " ");
125 }
126 else
127 strcpy(Duration, " ");
128
129 }
130 else
131 strcpy(Duration, " ");
132 }
133 else
134 {
135 st_In=st;
136 strcpy(Duration, " ");
137 }
138
139 fprintf(F," %02hd:%02hd:%02hd.%03hd %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, Duration);
140 }
141
Debug_Close()142 void Debug_Close()
143 {
144 Debug += "\r\n";
145 fwrite(Debug.c_str(), Debug.size(), 1, F); \
146 fclose(F);
147 }
148 }
149 using namespace ZenLib_File_Debug;
150
151 #define ZENLIB_DEBUG1(_NAME,_TOAPPEND) \
152 Debug_Open(false); \
153 Debug+=", ";Debug+=_NAME; \
154 _TOAPPEND; \
155 Debug_Close();
156
157 #define ZENLIB_DEBUG2(_NAME,_TOAPPEND) \
158 Debug_Open(true); \
159 Debug+=", ";Debug+=_NAME; \
160 _TOAPPEND; \
161 Debug_Close();
162 #else // ZENLIB_DEBUG
163 #define ZENLIB_DEBUG1(_NAME,_TOAPPEND)
164 #define ZENLIB_DEBUG2(_NAME,_TOAPPEND)
165 #endif // ZENLIB_DEBUG
166
167 //***************************************************************************
168 // Constructor/Destructor
169 //***************************************************************************
170
171 //---------------------------------------------------------------------------
File()172 File::File()
173 {
174 #ifdef ZENLIB_USEWX
175 File_Handle=NULL;
176 #else //ZENLIB_USEWX
177 #ifdef ZENLIB_STANDARD
178 File_Handle=NULL;
179 #elif defined WINDOWS
180 #ifdef WINDOWS_UWP
181 File_Handle=NULL;
182 #else
183 File_Handle=INVALID_HANDLE_VALUE;
184 #endif
185 #endif
186 #endif //ZENLIB_USEWX
187 Position=(int64u)-1;
188 Size=(int64u)-1;
189 }
190
File(Ztring File_Name,access_t Access)191 File::File(Ztring File_Name, access_t Access)
192 {
193 #ifdef ZENLIB_USEWX
194 File_Handle=NULL;
195 #else //ZENLIB_USEWX
196 #ifdef ZENLIB_STANDARD
197 File_Handle=NULL;
198 #elif defined WINDOWS
199 #ifdef WINDOWS_UWP
200 File_Handle=NULL;
201 #else
202 File_Handle=INVALID_HANDLE_VALUE;
203 #endif
204 #endif
205 #endif //ZENLIB_USEWX
206 Position=(int64u)-1;
207 Size=(int64u)-1;
208 Open(File_Name, Access);
209 }
210
211 //---------------------------------------------------------------------------
~File()212 File::~File()
213 {
214 Close();
215 }
216
217 //***************************************************************************
218 // Open/Close
219 //***************************************************************************
220
221 //---------------------------------------------------------------------------
Open(const tstring & File_Name_,access_t Access)222 bool File::Open (const tstring &File_Name_, access_t Access)
223 {
224 Close();
225
226 ZENLIB_DEBUG1( "File Open",
227 Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
228
229 File_Name=File_Name_;
230
231 #ifdef ZENLIB_USEWX
232 File_Handle=(void*)new wxFile();
233 if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
234 {
235 //Sometime the file is locked for few milliseconds, we try again later
236 wxMilliSleep(1000);
237 if (((wxFile*)File_Handle)->Open(File_Name.c_str(), (wxFile::OpenMode)Access)==0)
238 //File is not openable
239 return false;
240 }
241 return true;
242 #else //ZENLIB_USEWX
243 #ifdef ZENLIB_STANDARD
244 /*
245 int access;
246 switch (Access)
247 {
248 case Access_Read : access=O_BINARY|O_RDONLY ; break;
249 case Access_Write : access=O_BINARY|O_WRONLY|O_CREAT|O_TRUNC ; break;
250 case Access_Read_Write : access=O_BINARY|O_RDWR |O_CREAT ; break;
251 case Access_Write_Append : access=O_BINARY|O_WRONLY|O_CREAT|O_APPEND ; break;
252 default : access=0 ;
253 }
254 #ifdef UNICODE
255 File_Handle=open(File_Name.To_Local().c_str(), access);
256 #else
257 File_Handle=open(File_Name.c_str(), access);
258 #endif //UNICODE
259 return File_Handle!=-1;
260 */
261 ios_base::openmode mode;
262 switch (Access)
263 {
264 case Access_Write : mode=ios_base::binary|ios_base::in|ios_base::out; break;
265 case Access_Read_Write : mode=ios_base::binary|ios_base::in|ios_base::out; break;
266 case Access_Write_Append : if (!Exists(File_Name))
267 mode=ios_base::binary|ios_base::out;
268 else
269 mode=ios_base::binary|ios_base::out|ios_base::app;
270 break;
271 default : mode = ios_base::binary | ios_base::in;
272 }
273 #ifdef UNICODE
274 File_Handle=new fstream(File_Name.To_Local().c_str(), mode);
275 #else
276 File_Handle=new fstream(File_Name.c_str(), mode);
277 #endif //UNICODE
278 if (!((fstream*)File_Handle)->is_open())
279 {
280 delete (fstream*)File_Handle; File_Handle=NULL;
281 return false;
282 }
283 return true;
284 #elif defined WINDOWS
285 #ifdef WINDOWS_UWP
286 File_Handle=new WrtFile();
287
288 FileAccessMode Desired_Mode;
289 StorageOpenOptions Share_Mode;
290 switch (Access)
291 {
292 case Access_Read: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
293 case Access_Write:
294 case Access_Read_Write:
295 case Access_Write_Append: Desired_Mode=FileAccessMode_ReadWrite; Share_Mode=StorageOpenOptions_AllowReadersAndWriters; break;
296 default: Desired_Mode=FileAccessMode_Read; Share_Mode=StorageOpenOptions_None;
297 }
298
299 // Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
300 File_Name.FindAndReplace(__T("/"), __T("\\"));
301
302 if (FAILED(Get_File(HStringReference(File_Name.c_str(), (unsigned int)File_Name.size()), ((WrtFile*)File_Handle)->File)))
303 {
304 if (Access==Access_Write || Access==Access_Read_Write || Access==Access_Write_Append)
305 {
306 if (!Create(File_Name, false))
307 {
308 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
309 return false;
310 }
311
312 if (Access==Access_Write_Append)
313 {
314 Size_Get();
315 if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
316 {
317 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
318 return false;
319 }
320 }
321
322 return true;
323 }
324
325 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
326 return false;
327 }
328
329 //IStorageFile don't provide OpenWithOptionsAsync
330 ComPtr<IStorageFile2> File2;
331 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
332 {
333 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
334 return false;
335 }
336
337 ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open;
338 if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open)) ||
339 FAILED(Await(Async_Open)) ||
340 FAILED(Async_Open->GetResults(&((WrtFile*)File_Handle)->Buffer))
341 || !((WrtFile*)File_Handle)->Buffer)
342 {
343 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
344 return false;
345 }
346
347 if (Access==Access_Write_Append)
348 {
349 Size_Get();
350 if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(Size)))
351 {
352 ZENLIB_DEBUG2("File Open", Debug += ", returns 0";)
353 return false;
354 }
355 }
356 else
357 Position=0;
358 #else
359 DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
360 switch (Access)
361 {
362 case Access_Read : dwDesiredAccess=FILE_READ_DATA; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_EXISTING; break;
363 case Access_Write : dwDesiredAccess=GENERIC_WRITE; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS; break;
364 case Access_Read_Write : dwDesiredAccess=FILE_READ_DATA|GENERIC_WRITE; dwShareMode=FILE_SHARE_READ|FILE_SHARE_WRITE; dwCreationDisposition=OPEN_ALWAYS; break;
365 case Access_Write_Append : dwDesiredAccess = FILE_APPEND_DATA; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; dwCreationDisposition = OPEN_ALWAYS; break;
366 default : dwDesiredAccess=0; dwShareMode=0; dwCreationDisposition=0; break;
367 }
368
369 #ifdef UNICODE
370 File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
371 #else
372 File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
373 #endif //UNICODE
374 #if 0 //Disabled
375 if (File_Handle==INVALID_HANDLE_VALUE)
376 {
377 //Sometimes the file is locked for few milliseconds, we try again later
378 DWORD dw = GetLastError();
379 if (dw!=ERROR_FILE_NOT_FOUND)
380 {
381 /*
382 char lpMsgBuf[1000];
383 FormatMessageA(
384 FORMAT_MESSAGE_FROM_SYSTEM,
385 NULL,
386 dw,
387 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
388 lpMsgBuf,
389 1000, NULL );
390 */
391 Sleep(1000);
392 #ifdef UNICODE
393 File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
394 #else
395 File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
396 #endif //UNICODE
397 }
398 }
399 #endif //0
400 if (File_Handle==INVALID_HANDLE_VALUE)
401 {
402 ZENLIB_DEBUG2( "File Open",
403 Debug+=", returns 0";)
404
405 //File is not openable
406 return false;
407 }
408
409 ZENLIB_DEBUG2( "File Open",
410 Debug+=", returns 1";)
411
412 if (Access == Access_Write_Append)
413 Size_Get();
414 else
415 Position = 0;
416 #endif
417 return true;
418 #endif
419 #endif //ZENLIB_USEWX
420 }
421
422 //---------------------------------------------------------------------------
Create(const Ztring & File_Name_,bool OverWrite)423 bool File::Create (const Ztring &File_Name_, bool OverWrite)
424 {
425 Close();
426
427 ZENLIB_DEBUG1( "File Create",
428 Debug+=", File_Name="; Debug +=Ztring(File_Name_).To_UTF8();)
429
430 File_Name=File_Name_;
431
432 #ifdef ZENLIB_USEWX
433 File_Handle=(void*)new wxFile();
434 if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
435 {
436 //Sometime the file is locked for few milliseconds, we try again later
437 wxMilliSleep(3000);
438 if (((wxFile*)File_Handle)->Create(File_Name.c_str(), OverWrite)==0)
439 //File is not openable
440 return false;
441 }
442 return true;
443 #else //ZENLIB_USEWX
444 #ifdef ZENLIB_STANDARD
445 /*
446 int access;
447 switch (OverWrite)
448 {
449 case false : access=O_BINARY|O_CREAT|O_WRONLY|O_EXCL ; break;
450 default : access=O_BINARY|O_CREAT|O_WRONLY|O_TRUNC; break;
451 }
452 #ifdef UNICODE
453 File_Handle=open(File_Name.To_Local().c_str(), access);
454 #else
455 File_Handle=open(File_Name.c_str(), access);
456 #endif //UNICODE
457 return File_Handle!=-1;
458 */
459 /*ios_base::openmode mode;
460
461 switch (OverWrite)
462 {
463 //case false : mode= ; break;
464 default : mode=0 ; break;
465 }*/
466 ios_base::openmode access;
467
468 if (!OverWrite && Exists(File_Name))
469 return false;
470
471 access=ios_base::binary|ios_base::in|ios_base::out|ios_base::trunc;
472
473 #ifdef UNICODE
474 File_Handle=new fstream(File_Name.To_Local().c_str(), access);
475 #else
476 File_Handle=new fstream(File_Name.c_str(), access);
477 #endif //UNICODE
478 return ((fstream*)File_Handle)->is_open();
479 #elif defined WINDOWS
480 #ifdef WINDOWS_UWP
481 File_Handle=new WrtFile();
482
483 FileAccessMode Desired_Mode=FileAccessMode_ReadWrite;
484 StorageOpenOptions Share_Mode=StorageOpenOptions_AllowReadersAndWriters;
485 CreationCollisionOption Collision_Option=CreationCollisionOption_FailIfExists;
486 if (OverWrite)
487 Collision_Option=CreationCollisionOption_ReplaceExisting;
488
489 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
490 File_Name.FindAndReplace(__T("/"), __T("\\"));
491
492 //Split file and folder
493 tstring Destination_Dir=FileName::Path_Get(File_Name);
494 tstring Destination_File=FileName::Name_Get(File_Name);
495
496 //Open dst folder
497 ComPtr<IStorageFolder> Folder;
498 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
499 return false;
500
501 //Create file
502 ComPtr<IAsyncOperation<StorageFile*> > Async_Create;
503 ComPtr<IStorageFile> File;
504 if (FAILED(Folder->CreateFileAsync(HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Create)) ||
505 FAILED(Await(Async_Create)) ||
506 FAILED(Async_Create->GetResults(&((WrtFile*)File_Handle)->File)) ||
507 !((WrtFile*)File_Handle)->File)
508 return false;
509
510 //IStorageFile don't provide OpenWithOptionsAsync
511 ComPtr<IStorageFile2> File2;
512 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&File2))) || !File2)
513 return false;
514
515 ComPtr<IAsyncOperation<IRandomAccessStream*> > Async_Open_File;
516 if (FAILED(File2->OpenWithOptionsAsync(Desired_Mode, Share_Mode, &Async_Open_File)) ||
517 FAILED(Await(Async_Open_File)) ||
518 FAILED(Async_Open_File->GetResults(&((WrtFile*)File_Handle)->Buffer)) ||
519 !((WrtFile*)File_Handle)->Buffer)
520 return false;
521
522 return true;
523 #else
524 DWORD dwDesiredAccess, dwShareMode, dwCreationDisposition;
525 if (OverWrite) {
526 dwDesiredAccess=GENERIC_WRITE;
527 dwCreationDisposition=CREATE_ALWAYS;
528 } else {
529 dwDesiredAccess=GENERIC_WRITE;
530 dwCreationDisposition=CREATE_NEW;
531 }
532 dwShareMode=0;
533
534 #ifdef UNICODE
535 File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
536 #else
537 File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
538 #endif //UNICODE
539 #if 0 //Disabled
540 if (File_Handle==INVALID_HANDLE_VALUE)
541 {
542 //Sometime the file is locked for few milliseconds, we try again later
543 Sleep(3000);
544 #ifdef UNICODE
545 File_Handle=CreateFileW(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
546 #else
547 File_Handle=CreateFile(File_Name.c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
548 #endif //UNICODE
549 }
550 #endif //0
551 if (File_Handle==INVALID_HANDLE_VALUE)
552 {
553 ZENLIB_DEBUG2( "File Create",
554 Debug+=", returns 0";)
555
556 //File is not openable
557 return false;
558 }
559
560 ZENLIB_DEBUG2( "File Create",
561 Debug+=", returns 1";)
562 #endif
563 return true;
564 #endif
565 #endif //ZENLIB_USEWX
566 }
567
568 //---------------------------------------------------------------------------
Close()569 void File::Close ()
570 {
571 #ifdef ZENLIB_DEBUG
572 bool isOpen=false;
573 #ifdef ZENLIB_USEWX
574 if (File_Handle!=NULL)
575 #else //ZENLIB_USEWX
576 #ifdef ZENLIB_STANDARD
577 if (File_Handle!=NULL)
578 #elif defined WINDOWS
579 #ifdef WINDOWS_UWP
580 if (File_Handle)
581 #else
582 if (File_Handle!=INVALID_HANDLE_VALUE)
583 #endif
584 #endif
585 #endif //ZENLIB_USEWX
586 {
587 ZENLIB_DEBUG1( "File Close",
588 Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8();)
589 isOpen=true;
590 }
591 #endif
592
593 #ifdef ZENLIB_USEWX
594 delete (wxFile*)File_Handle; File_Handle=NULL;
595 #else //ZENLIB_USEWX
596 #ifdef ZENLIB_STANDARD
597 //close(File_Handle); File_Handle=-1;
598 delete (fstream*)File_Handle; File_Handle=NULL;
599 #elif defined WINDOWS
600 #ifdef WINDOWS_UWP
601 delete(WrtFile*)File_Handle; File_Handle=NULL;
602 #else
603 CloseHandle(File_Handle); File_Handle=INVALID_HANDLE_VALUE;
604 #endif
605 #endif
606 #endif //ZENLIB_USEWX
607 Position=(int64u)-1;
608 Size=(int64u)-1;
609
610 #ifdef ZENLIB_DEBUG
611 if (isOpen)
612 {
613 ZENLIB_DEBUG2( "File Close",
614 )
615 }
616 #endif
617 }
618
619 //***************************************************************************
620 // Read/Write
621 //***************************************************************************
622
623 //---------------------------------------------------------------------------
Read(int8u * Buffer,size_t Buffer_Size_Max)624 size_t File::Read (int8u* Buffer, size_t Buffer_Size_Max)
625 {
626 ZENLIB_DEBUG1("File Read",
627 Debug += ", File_Name="; Debug += Ztring(File_Name).To_UTF8(); Debug += ", MaxSize="; Debug += Ztring::ToZtring(Buffer_Size_Max).To_UTF8())
628
629 #ifdef ZENLIB_USEWX
630 if (File_Handle == NULL)
631 #else //ZENLIB_USEWX
632 #ifdef ZENLIB_STANDARD
633 if (File_Handle == NULL)
634 #elif defined WINDOWS
635 #ifdef WINDOWS_UWP
636 boolean Can_Read=FALSE;
637 if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanRead(&Can_Read)) || !Can_Read)
638 #else
639 if (File_Handle == INVALID_HANDLE_VALUE)
640 #endif
641 #endif
642 #endif //ZENLIB_USEWX
643 return 0;
644
645 #ifdef ZENLIB_USEWX
646 size_t ByteRead=((wxFile*)File_Handle)->Read(Buffer, Buffer_Size_Max);
647 Position+=ByteRead;
648 return ByteRead;
649 #else //ZENLIB_USEWX
650 #ifdef ZENLIB_STANDARD
651 //return read((int)File_Handle, Buffer, Buffer_Size_Max);
652 if (Position==(int64u)-1)
653 Position_Get();
654 if (Size==(int64u)-1)
655 Size_Get();
656 if (Position!=(int64u)-1 && Position+Buffer_Size_Max>Size)
657 Buffer_Size_Max=(size_t)(Size-Position); //We don't want to enable eofbit (impossible to seek after)
658 ((fstream*)File_Handle)->read((char*)Buffer, Buffer_Size_Max);
659 size_t ByteRead=((fstream*)File_Handle)->gcount();
660 Position+=ByteRead;
661 return ByteRead;
662 #elif defined WINDOWS
663 #ifdef WINDOWS_UWP
664 ComPtr<IInputStream> Stream;
665 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
666 return 0;
667
668 ComPtr<IDataReaderFactory> Reader_Factory;
669 if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &Reader_Factory)) || !Reader_Factory)
670 return 0;
671
672 ComPtr<IDataReader> Reader;
673 if (FAILED(Reader_Factory->CreateDataReader(*Stream.GetAddressOf(), &Reader)) || !Reader)
674 return 0;
675
676 UINT32 Readed=0;
677 ComPtr<IAsyncOperation<UINT32> > Async_Read;
678 if (FAILED(Reader->LoadAsync((UINT32)Buffer_Size_Max, &Async_Read)) ||
679 FAILED(Await(Async_Read)) ||
680 FAILED(Async_Read->GetResults(&Readed)))
681 return 0;
682
683 if (FAILED(Reader->ReadBytes((UINT32)Buffer_Size_Max, (BYTE*)Buffer)))
684 return 0;
685
686 Reader->DetachStream(&Stream);
687
688 return (size_t)Readed;
689 #else
690 DWORD Buffer_Size;
691 if (ReadFile(File_Handle, Buffer, (DWORD)Buffer_Size_Max, &Buffer_Size, NULL))
692 {
693 Position+=Buffer_Size;
694
695 ZENLIB_DEBUG2( "File Read",
696 Debug+=", new position ";Debug+=Ztring::ToZtring(Position).To_UTF8();;Debug+=", returns ";Debug+=Ztring::ToZtring((int64u)Buffer_Size).To_UTF8();)
697
698 return Buffer_Size;
699 }
700 else
701 {
702 ZENLIB_DEBUG2( "File Read",
703 Debug+=", returns 0";)
704 return 0;
705 }
706 #endif
707 #endif
708 #endif //ZENLIB_USEWX
709 }
710
711 //---------------------------------------------------------------------------
Write(const int8u * Buffer,size_t Buffer_Size)712 size_t File::Write (const int8u* Buffer, size_t Buffer_Size)
713 {
714 #ifdef ZENLIB_USEWX
715 if (File_Handle==NULL)
716 #else //ZENLIB_USEWX
717 #ifdef ZENLIB_STANDARD
718 if (File_Handle==NULL)
719 #elif defined WINDOWS
720 #ifdef WINDOWS_UWP
721 boolean Can_Write=FALSE;
722 if (!File_Handle || !((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
723 #else
724 if (File_Handle==INVALID_HANDLE_VALUE)
725 #endif
726 #endif
727 #endif //ZENLIB_USEWX
728 return 0;
729
730 #ifdef ZENLIB_USEWX
731 return ((wxFile*)File_Handle)->Write(Buffer, Buffer_Size);
732 #else //ZENLIB_USEWX
733 #ifdef ZENLIB_STANDARD
734 //return write(File_Handle, Buffer, Buffer_Size);
735 ((fstream*)File_Handle)->write((char*)Buffer, Buffer_Size);
736 if (((fstream*)File_Handle)->bad())
737 {
738 Position=(int64u)-1;
739 return 0;
740 }
741 else
742 {
743 if (Position!=(int64u)-1)
744 Position+=Buffer_Size;
745 return Buffer_Size;
746 }
747 #elif defined WINDOWS
748 #ifdef WINDOWS_UWP
749 ComPtr<IOutputStream> Stream;
750 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
751 return 0;
752
753 ComPtr<IDataWriterFactory> Writer_Factory;
754 if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(), &Writer_Factory)) || !Writer_Factory)
755 return 0;
756
757 ComPtr<IDataWriter> Writer;
758 if (FAILED(Writer_Factory->CreateDataWriter(*Stream.GetAddressOf(), &Writer)) || !Writer)
759 return 0;
760
761 if (FAILED(Writer->WriteBytes((UINT32)Buffer_Size, (BYTE*)Buffer)))
762 return 0;
763
764 UINT32 Written=0;
765 ComPtr<IAsyncOperation<UINT32> > Async_Write;
766 if (FAILED(Writer->StoreAsync(&Async_Write)) ||
767 FAILED(Await(Async_Write)) ||
768 FAILED(Async_Write->GetResults(&Written)))
769 return 0;
770
771 Writer->DetachStream(&Stream);
772
773 return (size_t)Written;
774 #else
775 DWORD Buffer_Size_Written;
776 if (WriteFile(File_Handle, Buffer, (DWORD)Buffer_Size, &Buffer_Size_Written, NULL))
777 {
778 if (Position!=(int64u)-1)
779 Position+=Buffer_Size_Written;
780 return Buffer_Size_Written;
781 }
782 else
783 {
784 Position=(int64u)-1;
785 return 0;
786 }
787 #endif
788 #endif
789 #endif //ZENLIB_USEWX
790 }
791
792 //---------------------------------------------------------------------------
Truncate(int64u Offset)793 bool File::Truncate (int64u Offset)
794 {
795 if (File_Handle==NULL)
796 return false;
797
798 #ifdef ZENLIB_USEWX
799 return false; //Not supported
800 #else //ZENLIB_USEWX
801 #ifdef ZENLIB_STANDARD
802 #if defined(WINDOWS)
803 return false; //Not supported
804 #else //defined(WINDOWS)
805 //Need to close the file, use truncate, reopen it
806 #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 21
807 if (Offset==(int64u)-1)
808 Offset=Position_Get();
809 Ztring File_Name_Sav=File_Name;
810 Close();
811 truncate(File_Name_Sav.To_Local().c_str(), Offset);
812 if (!Open(File_Name_Sav, Access_Read_Write))
813 return false;
814 GoTo(0, FromEnd);
815 return true;
816 #else
817 return false; //Not supported
818 #endif
819 #endif //!defined(WINDOWS)
820 #elif defined WINDOWS
821 #ifdef WINDOWS_UWP
822 boolean Can_Write=FALSE;
823 if (!((WrtFile*)File_Handle)->Buffer || FAILED(((WrtFile*)File_Handle)->Buffer->get_CanWrite(&Can_Write)) || !Can_Write)
824 return false;
825
826 ComPtr<IOutputStream> Stream;
827 if (FAILED(((WrtFile*)File_Handle)->Buffer->QueryInterface(IID_PPV_ARGS(&Stream))) || !Stream)
828 return false;
829
830 if (Offset==(int64u)-1)
831 {
832 if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Position_Get())))
833 return false;
834 }
835 else
836 {
837 if (FAILED(((WrtFile*)File_Handle)->Buffer->put_Size((UINT64)Offset)))
838 return false;
839 }
840
841 return true;
842 #else
843 if(Offset!=(int64u)-1 && Offset!=Position_Get())
844 if (!GoTo(Offset))
845 return false;
846 SetEndOfFile(File_Handle);
847 return true;
848 #endif
849 #endif
850 #endif //ZENLIB_USEWX
851 }
852
853 //---------------------------------------------------------------------------
Write(const Ztring & ToWrite)854 size_t File::Write (const Ztring &ToWrite)
855 {
856 std::string AnsiString=ToWrite.To_UTF8();
857 return Write((const int8u*)AnsiString.c_str(), AnsiString.size());
858 }
859
860 //***************************************************************************
861 // Moving
862 //***************************************************************************
863
864 //---------------------------------------------------------------------------
GoTo(int64s Position_ToMove,move_t MoveMethod)865 bool File::GoTo (int64s Position_ToMove, move_t MoveMethod)
866 {
867 ZENLIB_DEBUG1( "File GoTo",
868 Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8(); Debug+="File GoTo: "; Debug +=Ztring(File_Name).To_UTF8(); Debug+=", MoveMethod="; Debug +=Ztring::ToZtring(MoveMethod).To_UTF8(); Debug+=", MaxSize="; Debug +=Ztring::ToZtring(Position_ToMove).To_UTF8())
869
870 #ifdef ZENLIB_USEWX
871 if (File_Handle==NULL)
872 #else //ZENLIB_USEWX
873 #ifdef ZENLIB_STANDARD
874 if (File_Handle==NULL)
875 #elif defined WINDOWS
876 #ifdef WINDOWS_UWP
877 if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
878 #else
879 if (File_Handle==INVALID_HANDLE_VALUE)
880 #endif
881 #endif
882 #endif //ZENLIB_USEWX
883 return false;
884
885 Position=(int64u)-1; //Disabling memory
886 #ifdef ZENLIB_USEWX
887 return ((wxFile*)File_Handle)->Seek(Position, (wxSeekMode)MoveMethod)!=wxInvalidOffset; //move_t and wxSeekMode are same
888 #else //ZENLIB_USEWX
889 #ifdef ZENLIB_STANDARD
890 /*
891 int fromwhere;
892 switch (MoveMethod)
893 {
894 case FromBegin : fromwhere=SEEK_SET; break;
895 case FromCurrent : fromwhere=SEEK_CUR; break;
896 case FromEnd : fromwhere=SEEK_END; break;
897 default : fromwhere=SEEK_CUR; break;
898 }
899 return lseek(File_Handle, Position, fromwhere)!=-1;
900 */
901 ios_base::seekdir dir;
902 switch (MoveMethod)
903 {
904 case FromBegin : dir=ios_base::beg; break;
905 case FromCurrent : dir=ios_base::cur; break;
906 case FromEnd : dir=ios_base::end; break;
907 default : dir=ios_base::beg;
908 }
909 ((fstream*)File_Handle)->seekg((streamoff)Position_ToMove, dir);
910 return !((fstream*)File_Handle)->fail();
911 #elif defined WINDOWS
912 #ifdef WINDOWS_UWP
913 UINT64 New_Position=0;
914 switch (MoveMethod)
915 {
916 case FromBegin : New_Position=Position_ToMove; break;
917 case FromCurrent : New_Position=Position_Get()+Position_ToMove; break;
918 case FromEnd : New_Position=Size_Get()-Position_ToMove; break;
919 default : New_Position=Position_ToMove;
920 }
921
922 if (FAILED(((WrtFile*)File_Handle)->Buffer->Seek(New_Position)))
923 return false;
924
925 return true;
926 #else
927 LARGE_INTEGER GoTo;
928 GoTo.QuadPart=Position_ToMove;
929 BOOL i=SetFilePointerEx(File_Handle, GoTo, NULL, MoveMethod);
930
931 #ifdef ZENLIB_DEBUG
932 LARGE_INTEGER Temp; Temp.QuadPart=0;
933 SetFilePointerEx(File_Handle, Temp, &Temp, FILE_CURRENT);
934 ZENLIB_DEBUG2( "File GoTo",
935 Debug+=", new position ";Debug+=Ztring::ToZtring(Temp.QuadPart).To_UTF8();Debug+=", returns ";Debug+=i?'1':'0';)
936 #endif //ZENLIB_DEBUG
937
938 return i?true:false;
939 #endif
940 #endif
941 #endif //ZENLIB_USEWX
942 }
943
944 //---------------------------------------------------------------------------
Position_Get()945 int64u File::Position_Get ()
946 {
947 if (Position!=(int64u)-1)
948 return Position;
949
950 ZENLIB_DEBUG1( "File Position_Get",
951 Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
952
953 #ifdef ZENLIB_USEWX
954 if (File_Handle==NULL)
955 #else //ZENLIB_USEWX
956 #ifdef ZENLIB_STANDARD
957 if (File_Handle==NULL)
958 #elif defined WINDOWS
959 #ifdef WINDOWS_UWP
960 if (!File_Handle || !((WrtFile*)File_Handle)->File || !((WrtFile*)File_Handle)->Buffer)
961 #else
962 if (File_Handle == INVALID_HANDLE_VALUE)
963 #endif
964 #endif
965 #endif //ZENLIB_USEWX
966 return (int64u)-1;
967
968 #ifdef ZENLIB_USEWX
969 return (int64u)-1;
970 #else //ZENLIB_USEWX
971 #ifdef ZENLIB_STANDARD
972 Position=((fstream*)File_Handle)->tellg();
973 return Position;
974 #elif defined WINDOWS
975 #ifdef WINDOWS_UWP
976 if (FAILED(((WrtFile*)File_Handle)->Buffer->get_Position((UINT64*)&Position)))
977 return (int64u)-1;
978 #else
979 LARGE_INTEGER GoTo; GoTo.QuadPart=0;
980 GoTo.LowPart=SetFilePointer(File_Handle, GoTo.LowPart, &GoTo.HighPart, FILE_CURRENT);
981 Position=GoTo.QuadPart;
982
983 ZENLIB_DEBUG2( "File GoTo",
984 Debug+=", new position ";Debug+=Ztring::ToZtring(GoTo.QuadPart).To_UTF8();Debug+=", returns 1";)
985 #endif
986 return Position;
987 #endif
988 #endif //ZENLIB_USEWX
989 }
990
991 //***************************************************************************
992 // Attributes
993 //***************************************************************************
994
995 //---------------------------------------------------------------------------
Size_Get()996 int64u File::Size_Get()
997 {
998 #ifdef ZENLIB_USEWX
999 if (File_Handle==NULL)
1000 #else //ZENLIB_USEWX
1001 #ifdef ZENLIB_STANDARD
1002 if (File_Handle==NULL)
1003 #elif defined WINDOWS
1004 #ifdef WINDOWS_UWP
1005 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1006 #else
1007 if (File_Handle==INVALID_HANDLE_VALUE)
1008 #endif
1009 #endif
1010 #endif //ZENLIB_USEWX
1011 return 0;
1012
1013 #ifdef ZENLIB_USEWX
1014 return ((wxFile*)File_Handle)->Length();
1015 #else //ZENLIB_USEWX
1016 #ifdef ZENLIB_STANDARD
1017 /*
1018 int CurrentPos=lseek(File_Handle, 0, SEEK_CUR);
1019 int64u File_Size;
1020 File_Size=lseek(File_Handle, 0, SEEK_END);
1021 lseek(File_Handle, CurrentPos, SEEK_SET);
1022 */
1023 fstream::pos_type CurrentPos=((fstream*)File_Handle)->tellg();
1024 if (CurrentPos!=(fstream::pos_type)-1)
1025 {
1026 ((fstream*)File_Handle)->seekg(0, ios_base::end);
1027 Size=((fstream*)File_Handle)->tellg();
1028 ((fstream*)File_Handle)->seekg(CurrentPos);
1029 }
1030 else
1031 Size=(int64u)-1;
1032 #elif defined WINDOWS
1033 #ifdef WINDOWS_UWP
1034 ComPtr<IStorageItem> Item;
1035 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1036 return (int64u)-1;
1037
1038 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1039 ComPtr<IBasicProperties> Properties;
1040 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1041 FAILED(Await(Async_Properties)) ||
1042 FAILED(Async_Properties->GetResults(&Properties)) ||
1043 !Properties)
1044 return (int64u)-1;
1045
1046 if (FAILED(Properties->get_Size(&Size)))
1047 return (int64u)-1;
1048 #else
1049 LARGE_INTEGER x = {0};
1050 BOOL bRet = ::GetFileSizeEx(File_Handle, &x);
1051 if (bRet == FALSE)
1052 return (int64u)-1;
1053 Size=x.QuadPart;
1054 #endif
1055 #endif
1056 return Size;
1057 #endif //ZENLIB_USEWX
1058 }
1059
1060 //---------------------------------------------------------------------------
Created_Get()1061 Ztring File::Created_Get()
1062 {
1063 #ifdef ZENLIB_USEWX
1064 if (File_Handle==NULL)
1065 #else //ZENLIB_USEWX
1066 #ifdef ZENLIB_STANDARD
1067 if (File_Handle==NULL)
1068 #elif defined WINDOWS
1069 #ifdef WINDOWS_UWP
1070 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1071 #else
1072 if (File_Handle==INVALID_HANDLE_VALUE)
1073 #endif
1074 #endif
1075 #endif //ZENLIB_USEWX
1076 return Ztring();
1077
1078 #ifdef ZENLIB_USEWX
1079 return __T(""); //Not implemented
1080 #else //ZENLIB_USEWX
1081 #ifdef ZENLIB_STANDARD
1082 return __T(""); //Not implemented
1083 #elif defined WINDOWS
1084 #ifdef WINDOWS_UWP
1085 ComPtr<IStorageItem> Item;
1086 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1087 return __T("");
1088
1089 DateTime Time;
1090 if (FAILED(Item->get_DateCreated(&Time)))
1091 return __T("");
1092
1093 return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
1094 #else
1095 FILETIME TimeFT;
1096 if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
1097 {
1098 int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
1099 Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
1100 return Time;
1101 }
1102 else
1103 return __T(""); //There was a problem
1104 #endif
1105 #endif
1106 #endif //ZENLIB_USEWX
1107 }
1108
1109 //---------------------------------------------------------------------------
1110 #if defined WINDOWS
Calc_Time(const FILETIME & TimeFT)1111 static Ztring Calc_Time(const FILETIME& TimeFT)
1112 {
1113 int64u Time64 = 0x100000000ULL * TimeFT.dwHighDateTime + TimeFT.dwLowDateTime;
1114 TIME_ZONE_INFORMATION Info;
1115 DWORD Result = GetTimeZoneInformation(&Info);
1116 if (Result != TIME_ZONE_ID_INVALID)
1117 {
1118 Time64 -= ((int64s)Info.Bias) * 60 * 1000 * 1000 * 10;
1119 if (Result == TIME_ZONE_ID_DAYLIGHT)
1120 Time64 -= ((int64s)Info.DaylightBias) * 60 * 1000 * 1000 * 10;
1121 else
1122 Time64 -= ((int64s)Info.StandardBias) * 60 * 1000 * 1000 * 10;
1123 }
1124 Ztring Time; Time.Date_From_Milliseconds_1601(Time64 / 10000);
1125 Time.FindAndReplace(__T("UTC "), __T(""));
1126 return Time;
1127 }
1128 #endif
1129 //---------------------------------------------------------------------------
Created_Local_Get()1130 Ztring File::Created_Local_Get()
1131 {
1132 #ifdef ZENLIB_USEWX
1133 if (File_Handle==NULL)
1134 #else //ZENLIB_USEWX
1135 #ifdef ZENLIB_STANDARD
1136 if (File_Handle==NULL)
1137 #elif defined WINDOWS
1138 #ifdef WINDOWS_UWP
1139 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1140 #else
1141 if (File_Handle==INVALID_HANDLE_VALUE)
1142 #endif
1143 #endif
1144 #endif //ZENLIB_USEWX
1145 return Ztring();
1146
1147 #ifdef ZENLIB_USEWX
1148 return __T(""); //Not implemented
1149 #else //ZENLIB_USEWX
1150 #ifdef ZENLIB_STANDARD
1151 return __T(""); //Not implemented
1152 #elif defined WINDOWS
1153 #ifdef WINDOWS_UWP
1154 ComPtr<IStorageItem> Item;
1155 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1156 return __T("");
1157
1158 DateTime Time;
1159 if (FAILED(Item->get_DateCreated(&Time)))
1160 return __T("");
1161
1162 FILETIME File_Time;
1163 ULARGE_INTEGER Time_Union;
1164 Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
1165 File_Time.dwHighDateTime=Time_Union.HighPart;
1166 File_Time.dwLowDateTime=Time_Union.LowPart;
1167
1168 return Calc_Time(File_Time);
1169 #else
1170 FILETIME TimeFT;
1171 if (GetFileTime(File_Handle, &TimeFT, NULL, NULL))
1172 {
1173 return Calc_Time(TimeFT);
1174 }
1175 else
1176 return __T(""); //There was a problem
1177 #endif
1178 #endif
1179 #endif //ZENLIB_USEWX
1180 }
1181
1182 //---------------------------------------------------------------------------
Modified_Get()1183 Ztring File::Modified_Get()
1184 {
1185 #ifdef ZENLIB_USEWX
1186 if (File_Handle==NULL)
1187 #else //ZENLIB_USEWX
1188 #ifdef ZENLIB_STANDARD
1189 if (File_Handle==NULL)
1190 #elif defined WINDOWS
1191 #ifdef WINDOWS_UWP
1192 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1193 #else
1194 if (File_Handle==INVALID_HANDLE_VALUE)
1195 #endif
1196 #endif
1197 #endif //ZENLIB_USEWX
1198 return Ztring();
1199
1200 #ifdef ZENLIB_USEWX
1201 return __T(""); //Not implemented
1202 #else //ZENLIB_USEWX
1203 #ifdef ZENLIB_STANDARD
1204 struct stat Stat;
1205 int Result=stat(File_Name.To_Local().c_str(), &Stat);
1206 if (Result<0)
1207 return __T(""); //Error
1208 Ztring Time; Time.Date_From_Seconds_1970((int64s)Stat.st_mtime);
1209 return Time;
1210 #elif defined WINDOWS
1211 #ifdef WINDOWS_UWP
1212 ComPtr<IStorageItem> Item;
1213 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1214 return __T("");
1215
1216 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1217 ComPtr<IBasicProperties> Properties;
1218 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1219 FAILED(Await(Async_Properties)) ||
1220 FAILED(Async_Properties->GetResults(&Properties)) ||
1221 !Properties)
1222 return __T("");
1223
1224 DateTime Time;
1225 if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
1226 return __T("");
1227
1228 return Ztring().Date_From_Milliseconds_1601((int64u)(Time.UniversalTime/10000));
1229 #else
1230 FILETIME TimeFT;
1231 if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
1232 {
1233 int64u Time64=0x100000000ULL*TimeFT.dwHighDateTime+TimeFT.dwLowDateTime;
1234 Ztring Time; Time.Date_From_Milliseconds_1601(Time64/10000);
1235 return Time;
1236 }
1237 else
1238 return __T(""); //There was a problem
1239 #endif
1240 #endif
1241 #endif //ZENLIB_USEWX
1242 }
1243
1244 //---------------------------------------------------------------------------
Modified_Local_Get()1245 Ztring File::Modified_Local_Get()
1246 {
1247 #ifdef ZENLIB_USEWX
1248 if (File_Handle==NULL)
1249 #else //ZENLIB_USEWX
1250 #ifdef ZENLIB_STANDARD
1251 if (File_Handle==NULL)
1252 #elif defined WINDOWS
1253 #ifdef WINDOWS_UWP
1254 if (!File_Handle || !((WrtFile*)File_Handle)->File)
1255 #else
1256 if (File_Handle==INVALID_HANDLE_VALUE)
1257 #endif
1258 #endif
1259 #endif //ZENLIB_USEWX
1260 return Ztring();
1261
1262 #ifdef ZENLIB_USEWX
1263 return __T(""); //Not implemented
1264 #else //ZENLIB_USEWX
1265 #ifdef ZENLIB_STANDARD
1266 struct stat Stat;
1267 int Result=stat(File_Name.To_Local().c_str(), &Stat);
1268 if (Result<0)
1269 return __T(""); //Error
1270 Ztring Time; Time.Date_From_Seconds_1970_Local(Stat.st_mtime);
1271 return Time;
1272 #elif defined WINDOWS
1273 #ifdef WINDOWS_UWP
1274 ComPtr<IStorageItem> Item;
1275 if (FAILED(((WrtFile*)File_Handle)->File->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1276 return __T("");
1277
1278 ComPtr<IAsyncOperation<BasicProperties*> > Async_Properties;
1279 ComPtr<IBasicProperties> Properties;
1280 if (FAILED(Item->GetBasicPropertiesAsync(&Async_Properties)) ||
1281 FAILED(Await(Async_Properties)) ||
1282 FAILED(Async_Properties->GetResults(&Properties)) ||
1283 !Properties)
1284 return __T("");
1285
1286 DateTime Time;
1287 if (FAILED(Properties->get_DateModified(&Time)) || Time.UniversalTime==0)
1288 return __T("");
1289
1290 FILETIME File_Time;
1291 ULARGE_INTEGER Time_Union;
1292 Time_Union.QuadPart=(ULONGLONG)Time.UniversalTime;
1293 File_Time.dwHighDateTime=Time_Union.HighPart;
1294 File_Time.dwLowDateTime=Time_Union.LowPart;
1295
1296 return Calc_Time(File_Time);
1297 #else
1298 FILETIME TimeFT;
1299 if (GetFileTime(File_Handle, NULL, NULL, &TimeFT))
1300 {
1301 return Calc_Time(TimeFT);
1302 }
1303 else
1304 return __T(""); //There was a problem
1305 #endif
1306 #endif
1307 #endif //ZENLIB_USEWX
1308 }
1309
1310 //---------------------------------------------------------------------------
Opened_Get()1311 bool File::Opened_Get()
1312 {
1313 #ifdef ZENLIB_USEWX
1314 return File_Handle!=NULL;
1315 #else //ZENLIB_USEWX
1316 #ifdef ZENLIB_STANDARD
1317 //return File_Handle!=-1;
1318 return File_Handle!=NULL && ((fstream*)File_Handle)->is_open();
1319 #elif defined WINDOWS
1320 #ifdef WINDOWS_UWP
1321 return File_Handle && ((WrtFile*)File_Handle)->File && ((WrtFile*)File_Handle)->Buffer;
1322 #else
1323 return File_Handle!=INVALID_HANDLE_VALUE;
1324 #endif
1325 #endif
1326 #endif //ZENLIB_USEWX
1327 }
1328
1329 //***************************************************************************
1330 // Helpers
1331 //***************************************************************************
1332
1333 //---------------------------------------------------------------------------
Size_Get(const Ztring & File_Name)1334 int64u File::Size_Get(const Ztring &File_Name)
1335 {
1336 File F(File_Name);
1337 return F.Size_Get();
1338 }
1339
1340 //---------------------------------------------------------------------------
Created_Get(const Ztring & File_Name)1341 Ztring File::Created_Get(const Ztring &File_Name)
1342 {
1343 File F(File_Name);
1344 return F.Created_Get();
1345 }
1346
1347 //---------------------------------------------------------------------------
Modified_Get(const Ztring & File_Name)1348 Ztring File::Modified_Get(const Ztring &File_Name)
1349 {
1350 File F(File_Name);
1351 return F.Modified_Get();
1352 }
1353
1354 //---------------------------------------------------------------------------
Exists(const Ztring & File_Name)1355 bool File::Exists(const Ztring &File_Name)
1356 {
1357 ZENLIB_DEBUG1( "File Exists",
1358 Debug+=", File_Name="; Debug+=Ztring(File_Name).To_UTF8())
1359
1360 #ifdef ZENLIB_USEWX
1361 wxFileName FN(File_Name.c_str());
1362 return FN.FileExists();
1363 #else //ZENLIB_USEWX
1364 #ifdef ZENLIB_STANDARD
1365 #if defined WINDOWS
1366 if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
1367 return false;
1368 #endif //defined WINDOWS
1369 struct stat buffer;
1370 int status;
1371 #ifdef UNICODE
1372 status=stat(File_Name.To_Local().c_str(), &buffer);
1373 #else
1374 status=stat(File_Name.c_str(), &buffer);
1375 #endif //UNICODE
1376 return status==0 && S_ISREG(buffer.st_mode);
1377 #elif defined WINDOWS
1378 if (File_Name.find(__T('*'))!=std::string::npos || (File_Name.find(__T("\\\\?\\"))!=0 && File_Name.find(__T('?'))!=std::string::npos) || (File_Name.find(__T("\\\\?\\"))==0 && File_Name.find(__T('?'), 4)!=std::string::npos))
1379 return false;
1380 #ifdef WINDOWS_UWP
1381 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1382 Ztring File_Name_=File_Name;
1383 File_Name_.FindAndReplace(__T("/"), __T("\\"));
1384
1385 //Try to access file directly
1386 ComPtr<IStorageFile> File;
1387 if (SUCCEEDED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File)))
1388 return true;
1389
1390 //Try directory access methods
1391 tstring Dir_=FileName::Path_Get(File_Name_);
1392 tstring File_=FileName::Name_Get(File_Name_);
1393
1394 ComPtr<IStorageFolder> Folder;
1395 if (FAILED(Get_Folder(HStringReference(Dir_.c_str(), (unsigned int)Dir_.size()), Folder)))
1396 return false;
1397
1398 //IStorageFolder don't provide TryGetItemAsync
1399 ComPtr<IStorageFolder2> Folder2;
1400 if (FAILED(Folder->QueryInterface(IID_PPV_ARGS(&Folder2))) || !Folder2)
1401 return false;
1402
1403 ComPtr<IAsyncOperation<IStorageItem*> > Async_GetItem;
1404 ComPtr<IStorageItem> Item;
1405 ComPtr<IStorageFile> AsFile;
1406 if (SUCCEEDED(Folder2->TryGetItemAsync(HStringReference(File_.c_str(), (unsigned int)File_.size()).Get(), &Async_GetItem)) &&
1407 SUCCEEDED(Await(Async_GetItem)) &&
1408 SUCCEEDED(Async_GetItem->GetResults(&Item)) &&
1409 Item &&
1410 SUCCEEDED(Item.As(&AsFile)))
1411 return true;
1412
1413 return false;
1414 #else
1415 #ifdef UNICODE
1416 DWORD FileAttributes=GetFileAttributesW(File_Name.c_str());
1417 #else
1418 DWORD FileAttributes=GetFileAttributes(File_Name.c_str());
1419 #endif //UNICODE
1420
1421 ZENLIB_DEBUG2( "File Exists",
1422 Debug+=", File_Name="; Debug+=Ztring::ToZtring(((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY))?1:0).To_UTF8())
1423
1424 return ((FileAttributes!=INVALID_FILE_ATTRIBUTES) && !(FileAttributes&FILE_ATTRIBUTE_DIRECTORY));
1425 #endif
1426 #endif
1427 #endif //ZENLIB_USEWX
1428 }
1429
1430 //---------------------------------------------------------------------------
Copy(const Ztring & Source,const Ztring & Destination,bool OverWrite)1431 bool File::Copy(const Ztring &Source, const Ztring &Destination, bool OverWrite)
1432 {
1433 #ifdef ZENLIB_USEWX
1434 return wxCopyFile(Source.c_str(), Destination.c_str(), OverWrite);
1435 #else //ZENLIB_USEWX
1436 #ifdef ZENLIB_STANDARD
1437 return false;
1438 #elif defined WINDOWS
1439 #ifdef WINDOWS_UWP
1440 NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
1441 if (OverWrite)
1442 Collision_Option=NameCollisionOption_ReplaceExisting;
1443
1444 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1445 Ztring Source_=Source;
1446 Source_.FindAndReplace(__T("/"), __T("\\"));
1447
1448 Ztring Destination_=Destination;
1449 Destination_.FindAndReplace(__T("/"), __T("\\"));
1450
1451 //Split destination file and folder
1452 tstring Destination_Dir=FileName::Path_Get(Destination_);
1453 tstring Destination_File=FileName::Name_Get(Destination_);
1454
1455 //Open src file
1456 ComPtr<IStorageFile> File;
1457 if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
1458 return false;
1459
1460 //Open dst folder
1461 ComPtr<IStorageFolder> Folder;
1462 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
1463 return false;
1464
1465 //Copy file
1466 ComPtr<IAsyncOperation<StorageFile*> > Async_Copy;
1467 ComPtr<IStorageFile> New_File;
1468 if (FAILED(File->CopyOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Copy)) ||
1469 FAILED(Await(Async_Copy)) ||
1470 FAILED(Async_Copy->GetResults(&New_File)) ||
1471 !New_File)
1472 return false;
1473
1474 return true;
1475 #else
1476 #ifdef UNICODE
1477 return CopyFileW(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
1478 #else
1479 return CopyFile(Source.c_str(), Destination.c_str(), !OverWrite)!=0;
1480 #endif //UNICODE
1481 #endif
1482 #endif
1483 #endif //ZENLIB_USEWX
1484 }
1485
1486 //---------------------------------------------------------------------------
Move(const Ztring & Source,const Ztring & Destination,bool OverWrite)1487 bool File::Move(const Ztring &Source, const Ztring &Destination, bool OverWrite)
1488 {
1489 if (OverWrite && Exists(Source))
1490 Delete(Destination);
1491 #ifdef ZENLIB_USEWX
1492 if (OverWrite && Exists(Destination))
1493 wxRemoveFile(Destination.c_str());
1494 return wxRenameFile(Source.c_str(), Destination.c_str());
1495 #else //ZENLIB_USEWX
1496 #ifdef ZENLIB_STANDARD
1497 return !std::rename(Source.To_Local().c_str(), Destination.To_Local().c_str());
1498 #elif defined WINDOWS
1499 #ifdef WINDOWS_UWP
1500 NameCollisionOption Collision_Option=NameCollisionOption_FailIfExists;
1501 if (OverWrite)
1502 Collision_Option=NameCollisionOption_ReplaceExisting;
1503
1504 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1505 Ztring Source_=Source;
1506 Source_.FindAndReplace(__T("/"), __T("\\"));
1507
1508 Ztring Destination_=Destination;
1509 Destination_.FindAndReplace(__T("/"), __T("\\"));
1510
1511 //Split destination file and folder
1512 tstring Destination_Dir=FileName::Path_Get(Destination_);
1513 tstring Destination_File=FileName::Name_Get(Destination_);
1514
1515 //Open src file
1516 ComPtr<IStorageFile> File;
1517 if (FAILED(Get_File(HStringReference(Source_.c_str(), (unsigned int)Source_.size()), File)))
1518 return false;
1519
1520 //Open dst folder
1521 ComPtr<IStorageFolder> Folder;
1522 if (FAILED(Get_Folder(HStringReference(Destination_Dir.c_str(), (unsigned int)Destination_Dir.size()), Folder)))
1523 return false;
1524
1525 //Move file
1526 ComPtr<IAsyncAction> Async_Move;
1527 if (FAILED(File->MoveOverload(*Folder.GetAddressOf(), HStringReference(Destination_File.c_str(), (unsigned int)Destination_File.size()).Get(), Collision_Option, &Async_Move)) ||
1528 FAILED(Await(Async_Move)) ||
1529 FAILED(Async_Move->GetResults()))
1530 return false;
1531
1532 return true;
1533 #else
1534 #ifdef UNICODE
1535 return MoveFileExW(Source.c_str(), Destination.c_str(), 0)!=0;
1536 #else
1537 return MoveFileEx(Source.c_str(), Destination.c_str(), 0)!=0;
1538 #endif //UNICODE
1539 #endif
1540 #endif
1541 #endif //ZENLIB_USEWX
1542 }
1543
1544 //---------------------------------------------------------------------------
Delete(const Ztring & File_Name)1545 bool File::Delete(const Ztring &File_Name)
1546 {
1547 #ifdef ZENLIB_USEWX
1548 return wxRemoveFile(File_Name.c_str());
1549 #else //ZENLIB_USEWX
1550 #ifdef ZENLIB_STANDARD
1551 #ifdef UNICODE
1552 return unlink(File_Name.To_Local().c_str())==0;
1553 #else
1554 return unlink(File_Name.c_str())==0;
1555 #endif //UNICODE
1556 #elif defined WINDOWS
1557 #ifdef WINDOWS_UWP
1558 //Ensure all slashs are converted to backslashs (WinRT file API don't like slashs)
1559 Ztring File_Name_=File_Name;
1560 File_Name_.FindAndReplace(__T("/"), __T("\\"));
1561
1562 ComPtr<IStorageFile> File_;
1563 if (FAILED(Get_File(HStringReference(File_Name_.c_str(), (unsigned int)File_Name_.size()), File_)))
1564 return false;
1565
1566 ComPtr<IStorageItem> Item;
1567 if (FAILED(File_->QueryInterface(IID_PPV_ARGS(&Item))) || !Item)
1568 return false;
1569
1570 ComPtr<IAsyncAction> Async_Delete;
1571 if (FAILED(Item->DeleteAsync(StorageDeleteOption_Default, &Async_Delete)) ||
1572 FAILED(Await(Async_Delete)) ||
1573 FAILED(Async_Delete->GetResults()))
1574 return false;
1575
1576 return true;
1577 #else
1578 #ifdef UNICODE
1579 return DeleteFileW(File_Name.c_str())!=0;
1580 #else
1581 return DeleteFile(File_Name.c_str())!=0;
1582 #endif //UNICODE
1583 #endif
1584 #endif
1585 #endif //ZENLIB_USEWX
1586 }
1587
1588 //***************************************************************************
1589 //
1590 //***************************************************************************
1591
1592 } //namespace
1593