|
0 |
/*****************************************************************************
|
|
1 |
*
|
|
2 |
* Copyright (c) 2008-2010, CoreCodec, Inc.
|
|
3 |
* All rights reserved.
|
|
4 |
*
|
|
5 |
* Redistribution and use in source and binary forms, with or without
|
|
6 |
* modification, are permitted provided that the following conditions are met:
|
|
7 |
* * Redistributions of source code must retain the above copyright
|
|
8 |
* notice, this list of conditions and the following disclaimer.
|
|
9 |
* * Redistributions in binary form must reproduce the above copyright
|
|
10 |
* notice, this list of conditions and the following disclaimer in the
|
|
11 |
* documentation and/or other materials provided with the distribution.
|
|
12 |
* * Neither the name of CoreCodec, Inc. nor the
|
|
13 |
* names of its contributors may be used to endorse or promote products
|
|
14 |
* derived from this software without specific prior written permission.
|
|
15 |
*
|
|
16 |
* THIS SOFTWARE IS PROVIDED BY CoreCodec, Inc. ``AS IS'' AND ANY
|
|
17 |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
18 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19 |
* DISCLAIMED. IN NO EVENT SHALL CoreCodec, Inc. BE LIABLE FOR ANY
|
|
20 |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
21 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
22 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
23 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
24 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
25 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26 |
*
|
|
27 |
****************************************************************************/
|
|
28 |
|
|
29 |
#include "file.h"
|
|
30 |
|
|
31 |
#define bool_t bctbx_bool_t
|
|
32 |
#include <bctoolbox/vfs.h>
|
|
33 |
#undef bool_t
|
|
34 |
|
|
35 |
#if defined(TARGET_WIN)
|
|
36 |
|
|
37 |
#define FILE_FUNC_ID FOURCC('F','L','I','D')
|
|
38 |
|
|
39 |
#ifndef STRICT
|
|
40 |
#define STRICT
|
|
41 |
#endif
|
|
42 |
#define WIN32_LEAN_AND_MEAN
|
|
43 |
#include <windows.h>
|
|
44 |
#include <shellapi.h>
|
|
45 |
#include <fileapi.h>
|
|
46 |
|
|
47 |
#ifndef FO_DELETE
|
|
48 |
#define FO_DELETE 3
|
|
49 |
#endif
|
|
50 |
#ifndef FOF_NO_UI
|
|
51 |
#define FOF_NO_UI (0x04|0x10|0x400|0x200)
|
|
52 |
#endif
|
|
53 |
|
|
54 |
#if defined(TARGET_WINCE)
|
|
55 |
static HMODULE CEShellDLL = NULL;
|
|
56 |
#endif
|
|
57 |
#ifdef WINDOWS_DESKTOP
|
|
58 |
static int (WINAPI* FuncSHFileOperation)(SHFILEOPSTRUCT*) = NULL;
|
|
59 |
#else
|
|
60 |
static void *FuncSHFileOperation = NULL;
|
|
61 |
#endif
|
|
62 |
|
|
63 |
#ifndef ERROR_INVALID_DRIVE_OBJECT
|
|
64 |
#define ERROR_INVALID_DRIVE_OBJECT 4321L
|
|
65 |
#endif
|
|
66 |
|
|
67 |
#ifndef ERROR_DEVICE_NOT_AVAILABLE
|
|
68 |
#define ERROR_DEVICE_NOT_AVAILABLE 4319L
|
|
69 |
#endif
|
|
70 |
|
|
71 |
#ifndef ERROR_DEVICE_REMOVED
|
|
72 |
#define ERROR_DEVICE_REMOVED 1617L
|
|
73 |
#endif
|
|
74 |
|
|
75 |
#ifndef INVALID_SET_FILE_POINTER
|
|
76 |
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
|
77 |
#endif
|
|
78 |
|
|
79 |
typedef struct filestream
|
|
80 |
{
|
|
81 |
stream Stream;
|
|
82 |
tchar_t URL[MAXPATH];
|
|
83 |
bctbx_vfs_file_t *fp;
|
|
84 |
filepos_t Length;
|
|
85 |
filepos_t Pos;
|
|
86 |
int Flags;
|
|
87 |
|
|
88 |
void* Find;
|
|
89 |
WIN32_FIND_DATA FindData;
|
|
90 |
int DriveNo;
|
|
91 |
|
|
92 |
} filestream;
|
|
93 |
|
|
94 |
static err_t Open(filestream* p, const tchar_t* URL, int Flags)
|
|
95 |
{
|
|
96 |
if (p->fp != -1)
|
|
97 |
bctbx_file_close(p->fp);
|
|
98 |
|
|
99 |
p->Length = INVALID_FILEPOS_T;
|
|
100 |
p->fp = NULL;
|
|
101 |
|
|
102 |
if (URL && URL[0])
|
|
103 |
{
|
|
104 |
struct stat file_stats;
|
|
105 |
int mode = 0;
|
|
106 |
|
|
107 |
if (Flags & SFLAG_WRONLY && !(Flags & SFLAG_RDONLY))
|
|
108 |
mode = O_WRONLY;
|
|
109 |
else if (Flags & SFLAG_RDONLY && !(Flags & SFLAG_WRONLY))
|
|
110 |
mode = O_RDONLY;
|
|
111 |
else
|
|
112 |
mode = O_RDWR;
|
|
113 |
|
|
114 |
if (Flags & SFLAG_CREATE)
|
|
115 |
mode |= O_CREAT|O_TRUNC;
|
|
116 |
|
|
117 |
//bctbx_file_open2 doesn't work with Unicode files
|
|
118 |
#ifdef UNICODE
|
|
119 |
char fileStr[1024];
|
|
120 |
memset(fileStr, 0, 1024);
|
|
121 |
#ifdef _WIN32
|
|
122 |
WideCharToMultiByte(CP_ACP, 0, URL, -1, fileStr, sizeof(fileStr), 0, 0);
|
|
123 |
#else
|
|
124 |
wcstombs(fileStr, URL, 1024);
|
|
125 |
#endif
|
|
126 |
p->fp = bctbx_file_open2(bctbx_vfs_get_default(), fileStr, mode);
|
|
127 |
#else
|
|
128 |
p->fp = bctbx_file_open2(bctbx_vfs_get_default(), URL, mode);
|
|
129 |
#endif
|
|
130 |
|
|
131 |
if (p->fp == NULL)
|
|
132 |
{
|
|
133 |
if ((Flags & (SFLAG_REOPEN|SFLAG_SILENT))==0)
|
|
134 |
NodeReportError(p,NULL,ERR_ID,ERR_FILE_NOT_FOUND,URL);
|
|
135 |
return ERR_FILE_NOT_FOUND;
|
|
136 |
}
|
|
137 |
|
|
138 |
tcscpy_s(p->URL,TSIZEOF(p->URL),URL);
|
|
139 |
|
|
140 |
if (stat(URL, &file_stats) == 0)
|
|
141 |
p->Length = file_stats.st_size;
|
|
142 |
|
|
143 |
}
|
|
144 |
return ERR_NONE;
|
|
145 |
}
|
|
146 |
|
|
147 |
static err_t Read(filestream* p,void* Data,size_t Size,size_t* Readed)
|
|
148 |
{
|
|
149 |
err_t Err;
|
|
150 |
int n = bctbx_file_read2(p->fp, Data, (unsigned int)Size);
|
|
151 |
if (n<0)
|
|
152 |
{
|
|
153 |
n=0;
|
|
154 |
Err = ERR_READ;
|
|
155 |
}
|
|
156 |
else
|
|
157 |
Err = ((size_t)n != Size) ? ERR_END_OF_FILE:ERR_NONE;
|
|
158 |
|
|
159 |
if (Readed)
|
|
160 |
*Readed = n;
|
|
161 |
return Err;
|
|
162 |
}
|
|
163 |
|
|
164 |
static err_t ReadBlock(filestream* p,block* Block,size_t Ofs,size_t Size,size_t* Readed)
|
|
165 |
{
|
|
166 |
return Read(p,(void*)(Block->Ptr+Ofs),Size,Readed);
|
|
167 |
}
|
|
168 |
|
|
169 |
static err_t Write(filestream* p,const void* Data,size_t Size,size_t* Written)
|
|
170 |
{
|
|
171 |
err_t Err;
|
|
172 |
int n = bctbx_file_write2(p->fp, Data, (unsigned int)Size);
|
|
173 |
|
|
174 |
if (n<0)
|
|
175 |
{
|
|
176 |
n=0;
|
|
177 |
Err = ERR_WRITE;
|
|
178 |
}
|
|
179 |
else
|
|
180 |
Err = (n != Size) ? ERR_WRITE:ERR_NONE;
|
|
181 |
|
|
182 |
if (Written)
|
|
183 |
*Written = n;
|
|
184 |
return Err;
|
|
185 |
}
|
|
186 |
|
|
187 |
static filepos_t Seek(filestream* p,filepos_t Pos,int SeekMode)
|
|
188 |
{
|
|
189 |
off_t NewPos = bctbx_file_seek(p->fp, Pos, SeekMode);
|
|
190 |
if (NewPos<0)
|
|
191 |
return INVALID_FILEPOS_T;
|
|
192 |
return NewPos;
|
|
193 |
}
|
|
194 |
|
|
195 |
static err_t SetLength(filestream* p,dataid Id,const filepos_t* Data,size_t Size)
|
|
196 |
{
|
|
197 |
if (Size != sizeof(filepos_t))
|
|
198 |
return ERR_INVALID_DATA;
|
|
199 |
|
|
200 |
if (bctbx_file_truncate(p->fp, *Data)!=0)
|
|
201 |
return ERR_BUFFER_FULL;
|
|
202 |
|
|
203 |
return ERR_NONE;
|
|
204 |
}
|
|
205 |
|
|
206 |
static err_t OpenDir(filestream* p,const tchar_t* URL,int UNUSED_PARAM(Flags))
|
|
207 |
{
|
|
208 |
#ifndef WINDOWS_DESKTOP
|
|
209 |
WIN32_FILE_ATTRIBUTE_DATA attr_data;
|
|
210 |
#else
|
|
211 |
DWORD Attrib;
|
|
212 |
#endif
|
|
213 |
tchar_t Path[MAXPATHFULL];
|
|
214 |
|
|
215 |
if (p->Find != INVALID_HANDLE_VALUE)
|
|
216 |
{
|
|
217 |
FindClose(p->Find);
|
|
218 |
p->Find = INVALID_HANDLE_VALUE;
|
|
219 |
}
|
|
220 |
p->DriveNo = -1;
|
|
221 |
|
|
222 |
#if !defined(TARGET_WINCE)
|
|
223 |
if (!URL[0])
|
|
224 |
{
|
|
225 |
p->DriveNo = 0;
|
|
226 |
}
|
|
227 |
else
|
|
228 |
#endif
|
|
229 |
{
|
|
230 |
#ifndef WINDOWS_DESKTOP
|
|
231 |
if (GetFileAttributesEx(URL, GetFileExInfoStandard, &attr_data) == 0)
|
|
232 |
return ERR_FILE_NOT_FOUND;
|
|
233 |
|
|
234 |
if (!(attr_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
235 |
return ERR_NOT_DIRECTORY;
|
|
236 |
#else
|
|
237 |
Attrib = GetFileAttributes(URL);
|
|
238 |
if (Attrib == (DWORD)-1)
|
|
239 |
return ERR_FILE_NOT_FOUND;
|
|
240 |
|
|
241 |
if (!(Attrib & FILE_ATTRIBUTE_DIRECTORY))
|
|
242 |
return ERR_NOT_DIRECTORY;
|
|
243 |
#endif
|
|
244 |
|
|
245 |
tcscpy_s(Path,TSIZEOF(Path),URL);
|
|
246 |
AddPathDelimiter(Path,TSIZEOF(Path));
|
|
247 |
tcscat_s(Path,TSIZEOF(Path),T("*.*"));
|
|
248 |
#ifndef WINDOWS_DESKTOP
|
|
249 |
WIN32_FIND_DATA FileData;
|
|
250 |
p->Find = FindFirstFileEx(Path, FindExInfoStandard, &FileData, FindExSearchNameMatch, NULL, 0);
|
|
251 |
#else
|
|
252 |
p->Find = FindFirstFile(Path, &p->FindData);
|
|
253 |
#endif
|
|
254 |
}
|
|
255 |
|
|
256 |
return ERR_NONE;
|
|
257 |
}
|
|
258 |
|
|
259 |
extern datetime_t FileTimeToRel(FILETIME*);
|
|
260 |
|
|
261 |
static err_t EnumDir(filestream* p,const tchar_t* Exts,bool_t ExtFilter,streamdir* Item)
|
|
262 |
{
|
|
263 |
Item->FileName[0] = 0;
|
|
264 |
Item->DisplayName[0] = 0;
|
|
265 |
|
|
266 |
#if !defined(TARGET_WINCE) && defined(WINDOWS_DESKTOP)
|
|
267 |
if (p->DriveNo>=0)
|
|
268 |
{
|
|
269 |
size_t n = GetLogicalDriveStrings(0,NULL);
|
|
270 |
tchar_t* Drives = alloca((n+1)*sizeof(tchar_t));
|
|
271 |
if (GetLogicalDriveStrings((DWORD)n,Drives))
|
|
272 |
{
|
|
273 |
int No = p->DriveNo++;
|
|
274 |
|
|
275 |
while (Drives[0] && --No>=0)
|
|
276 |
Drives += tcslen(Drives)+1;
|
|
277 |
|
|
278 |
if (Drives[0])
|
|
279 |
{
|
|
280 |
size_t n = tcslen(Drives);
|
|
281 |
if (Drives[n-1] == '\\')
|
|
282 |
Drives[n-1] = 0;
|
|
283 |
tcscpy_s(Item->FileName,TSIZEOF(Item->FileName),Drives);
|
|
284 |
Item->ModifiedDate = INVALID_DATETIME_T;
|
|
285 |
Item->Size = INVALID_FILEPOS_T;
|
|
286 |
Item->Type = FTYPE_DIR;
|
|
287 |
}
|
|
288 |
}
|
|
289 |
}
|
|
290 |
else
|
|
291 |
#endif
|
|
292 |
{
|
|
293 |
while (!Item->FileName[0] && p->Find != INVALID_HANDLE_VALUE)
|
|
294 |
{
|
|
295 |
if (p->FindData.cFileName[0]!='.' && // skip unix/mac hidden files and . .. directory entries
|
|
296 |
!(p->FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
|
|
297 |
{
|
|
298 |
tcscpy_s(Item->FileName,TSIZEOF(Item->FileName),p->FindData.cFileName);
|
|
299 |
|
|
300 |
Item->ModifiedDate = FileTimeToRel(&p->FindData.ftLastWriteTime);
|
|
301 |
|
|
302 |
if (p->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
303 |
{
|
|
304 |
Item->Size = INVALID_FILEPOS_T;
|
|
305 |
Item->Type = FTYPE_DIR;
|
|
306 |
}
|
|
307 |
else
|
|
308 |
{
|
|
309 |
Item->Size = (filepos_t)(((int64_t)p->FindData.nFileSizeHigh << 32) | p->FindData.nFileSizeLow);
|
|
310 |
Item->Type = CheckExts(Item->FileName,Exts);
|
|
311 |
|
|
312 |
if (!Item->Type && ExtFilter)
|
|
313 |
Item->FileName[0] = 0; // skip
|
|
314 |
}
|
|
315 |
}
|
|
316 |
|
|
317 |
if (!FindNextFile(p->Find,&p->FindData))
|
|
318 |
{
|
|
319 |
FindClose(p->Find);
|
|
320 |
p->Find = INVALID_HANDLE_VALUE;
|
|
321 |
}
|
|
322 |
}
|
|
323 |
}
|
|
324 |
|
|
325 |
if (!Item->FileName[0])
|
|
326 |
{
|
|
327 |
if (p->Find != INVALID_HANDLE_VALUE)
|
|
328 |
{
|
|
329 |
FindClose(p->Find);
|
|
330 |
p->Find = INVALID_HANDLE_VALUE;
|
|
331 |
}
|
|
332 |
p->DriveNo = -1;
|
|
333 |
return ERR_END_OF_FILE;
|
|
334 |
}
|
|
335 |
|
|
336 |
return ERR_NONE;
|
|
337 |
}
|
|
338 |
|
|
339 |
static void Delete(filestream* p)
|
|
340 |
{
|
|
341 |
Open(p,NULL,0);
|
|
342 |
if (p->Find != INVALID_HANDLE_VALUE)
|
|
343 |
FindClose(p->Find);
|
|
344 |
}
|
|
345 |
|
|
346 |
static err_t CreateFunc(node* UNUSED_PARAM(p))
|
|
347 |
{
|
|
348 |
#if defined(TARGET_WINCE)
|
|
349 |
CEShellDLL = LoadLibrary(T("ceshell.dll"));
|
|
350 |
if (CEShellDLL)
|
|
351 |
*(FARPROC*)(void*)&FuncSHFileOperation = GetProcAddress(CEShellDLL,MAKEINTRESOURCE(14));
|
|
352 |
#elif defined(ENABLE_MICROSOFT_STORE_APP)
|
|
353 |
FuncSHFileOperation = NULL;
|
|
354 |
#elif defined(WINDOWS_DESKTOP)
|
|
355 |
FuncSHFileOperation = SHFileOperation;
|
|
356 |
#endif
|
|
357 |
|
|
358 |
return ERR_NONE;
|
|
359 |
}
|
|
360 |
|
|
361 |
static void DeleteFunc(node* UNUSED_PARAM(p))
|
|
362 |
{
|
|
363 |
#if defined(TARGET_WINCE)
|
|
364 |
if (CEShellDLL) FreeLibrary(CEShellDLL);
|
|
365 |
#endif
|
|
366 |
}
|
|
367 |
|
|
368 |
META_START(File_Class,FILE_CLASS)
|
|
369 |
META_CLASS(SIZE,sizeof(filestream))
|
|
370 |
META_CLASS(PRIORITY,PRI_MINIMUM)
|
|
371 |
META_CLASS(DELETE,Delete)
|
|
372 |
META_VMT(TYPE_FUNC,stream_vmt,Open,Open)
|
|
373 |
META_VMT(TYPE_FUNC,stream_vmt,Read,Read)
|
|
374 |
META_VMT(TYPE_FUNC,stream_vmt,ReadBlock,ReadBlock)
|
|
375 |
META_VMT(TYPE_FUNC,stream_vmt,Write,Write)
|
|
376 |
META_VMT(TYPE_FUNC,stream_vmt,Seek,Seek)
|
|
377 |
META_VMT(TYPE_FUNC,stream_vmt,OpenDir,OpenDir)
|
|
378 |
META_VMT(TYPE_FUNC,stream_vmt,EnumDir,EnumDir)
|
|
379 |
META_CONST(TYPE_PTR,filestream,Find,INVALID_HANDLE_VALUE)
|
|
380 |
META_DATA_RDONLY(TYPE_INT,STREAM_FLAGS,filestream,Flags)
|
|
381 |
META_DATA_RDONLY(TYPE_STRING,STREAM_URL,filestream,URL)
|
|
382 |
META_PARAM(SET,STREAM_LENGTH,SetLength)
|
|
383 |
META_DATA(TYPE_FILEPOS,STREAM_LENGTH,filestream,Length)
|
|
384 |
META_PARAM(STRING,NODE_PROTOCOL,T("file"))
|
|
385 |
META_END_CONTINUE(STREAM_CLASS)
|
|
386 |
|
|
387 |
META_START_CONTINUE(FILE_FUNC_ID)
|
|
388 |
META_CLASS(FLAGS,CFLAG_SINGLETON)
|
|
389 |
META_CLASS(CREATE,CreateFunc)
|
|
390 |
META_CLASS(DELETE,DeleteFunc)
|
|
391 |
META_END(NODE_CLASS)
|
|
392 |
|
|
393 |
bool_t FolderCreate(nodecontext* UNUSED_PARAM(p),const tchar_t* Path)
|
|
394 |
{
|
|
395 |
return CreateDirectory(Path,NULL) != FALSE;
|
|
396 |
}
|
|
397 |
|
|
398 |
bool_t FileExists(nodecontext* UNUSED_PARAM(p),const tchar_t* Path)
|
|
399 |
{
|
|
400 |
#ifndef WINDOWS_DESKTOP
|
|
401 |
WIN32_FILE_ATTRIBUTE_DATA attr_data;
|
|
402 |
return GetFileAttributesEx(Path, GetFileExInfoStandard, &attr_data) != 0;
|
|
403 |
#else
|
|
404 |
return GetFileAttributes(Path) != (DWORD)-1;
|
|
405 |
#endif
|
|
406 |
}
|
|
407 |
|
|
408 |
#ifdef WINDOWS_DESKTOP
|
|
409 |
static bool_t FileRecycle(const tchar_t* Path)
|
|
410 |
{
|
|
411 |
tchar_t PathEnded[MAXPATHFULL];
|
|
412 |
SHFILEOPSTRUCT DelStruct;
|
|
413 |
int Ret;
|
|
414 |
size_t l;
|
|
415 |
|
|
416 |
memset(&DelStruct,0,sizeof(DelStruct));
|
|
417 |
DelStruct.wFunc = FO_DELETE;
|
|
418 |
l = min(tcslen(Path)+1,TSIZEOF(PathEnded)-1);
|
|
419 |
tcscpy_s(PathEnded,TSIZEOF(PathEnded),Path);
|
|
420 |
PathEnded[l]=0;
|
|
421 |
DelStruct.pFrom = PathEnded;
|
|
422 |
DelStruct.fFlags = FOF_ALLOWUNDO|FOF_NO_UI;
|
|
423 |
Ret = FuncSHFileOperation(&DelStruct);
|
|
424 |
return Ret == 0;
|
|
425 |
}
|
|
426 |
#endif
|
|
427 |
|
|
428 |
bool_t FileErase(nodecontext* UNUSED_PARAM(p),const tchar_t* Path, bool_t Force, bool_t Safe)
|
|
429 |
{
|
|
430 |
if (Force)
|
|
431 |
{
|
|
432 |
#ifndef WINDOWS_DESKTOP
|
|
433 |
WIN32_FILE_ATTRIBUTE_DATA attr_data;
|
|
434 |
if ((GetFileAttributesEx(Path, GetFileExInfoStandard, &attr_data) != 0) && (attr_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
|
435 |
attr_data.dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
|
|
436 |
SetFileAttributes(Path, attr_data.dwFileAttributes);
|
|
437 |
}
|
|
438 |
#else
|
|
439 |
DWORD attr = GetFileAttributes(Path);
|
|
440 |
if ((attr != (DWORD)-1) && (attr & FILE_ATTRIBUTE_READONLY))
|
|
441 |
{
|
|
442 |
attr ^= FILE_ATTRIBUTE_READONLY;
|
|
443 |
SetFileAttributes(Path,attr);
|
|
444 |
}
|
|
445 |
#endif
|
|
446 |
}
|
|
447 |
|
|
448 |
#ifndef WINDOWS_DESKTOP
|
|
449 |
return DeleteFile(Path) != FALSE;
|
|
450 |
#else
|
|
451 |
if (!Safe || !FuncSHFileOperation)
|
|
452 |
return DeleteFile(Path) != FALSE;
|
|
453 |
else
|
|
454 |
return FileRecycle(Path);
|
|
455 |
#endif
|
|
456 |
}
|
|
457 |
|
|
458 |
bool_t FolderErase(nodecontext* UNUSED_PARAM(p),const tchar_t* Path, bool_t Force, bool_t Safe)
|
|
459 |
{
|
|
460 |
if (Force)
|
|
461 |
{
|
|
462 |
#ifndef WINDOWS_DESKTOP
|
|
463 |
WIN32_FILE_ATTRIBUTE_DATA attr_data;
|
|
464 |
if ((GetFileAttributesEx(Path, GetFileExInfoStandard, &attr_data) != 0) && (attr_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
|
465 |
attr_data.dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
|
|
466 |
SetFileAttributes(Path, attr_data.dwFileAttributes);
|
|
467 |
}
|
|
468 |
#else
|
|
469 |
DWORD attr = GetFileAttributes(Path);
|
|
470 |
if ((attr != (DWORD)-1) && (attr & FILE_ATTRIBUTE_READONLY))
|
|
471 |
{
|
|
472 |
attr ^= FILE_ATTRIBUTE_READONLY;
|
|
473 |
SetFileAttributes(Path,attr);
|
|
474 |
}
|
|
475 |
#endif
|
|
476 |
}
|
|
477 |
|
|
478 |
#ifndef WINDOWS_DESKTOP
|
|
479 |
return RemoveDirectory(Path) != FALSE;
|
|
480 |
#else
|
|
481 |
if (!Safe || !FuncSHFileOperation)
|
|
482 |
return RemoveDirectory(Path) != FALSE;
|
|
483 |
else
|
|
484 |
return FileRecycle(Path);
|
|
485 |
#endif
|
|
486 |
}
|
|
487 |
|
|
488 |
bool_t PathIsFolder(nodecontext* UNUSED_PARAM(p),const tchar_t* Path)
|
|
489 |
{
|
|
490 |
#ifndef WINDOWS_DESKTOP
|
|
491 |
WIN32_FILE_ATTRIBUTE_DATA attr_data;
|
|
492 |
return (GetFileAttributesEx(Path, GetFileExInfoStandard, &attr_data) != 0) && ((attr_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
|
493 |
#else
|
|
494 |
DWORD attr = GetFileAttributes(Path);
|
|
495 |
return (attr != (DWORD)-1) && (attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
|
|
496 |
#endif
|
|
497 |
}
|
|
498 |
|
|
499 |
datetime_t FileDateTime(nodecontext* UNUSED_PARAM(p),const tchar_t* Path)
|
|
500 |
{
|
|
501 |
datetime_t Date = INVALID_DATETIME_T;
|
|
502 |
HANDLE Find;
|
|
503 |
WIN32_FIND_DATA FindData;
|
|
504 |
|
|
505 |
#ifndef WINDOWS_DESKTOP
|
|
506 |
WIN32_FIND_DATA FileData;
|
|
507 |
Find = FindFirstFileEx(Path, FindExInfoStandard, &FileData, FindExSearchNameMatch, NULL, 0);
|
|
508 |
#else
|
|
509 |
Find = FindFirstFile(Path, &FindData);
|
|
510 |
#endif
|
|
511 |
if (Find != INVALID_HANDLE_VALUE)
|
|
512 |
{
|
|
513 |
Date = FileTimeToRel(&FindData.ftLastWriteTime);
|
|
514 |
FindClose(Find);
|
|
515 |
}
|
|
516 |
return Date;
|
|
517 |
}
|
|
518 |
|
|
519 |
bool_t FileMove(nodecontext* UNUSED_PARAM(p),const tchar_t* In,const tchar_t* Out)
|
|
520 |
{
|
|
521 |
#ifndef WINDOWS_DESKTOP
|
|
522 |
return MoveFileEx(In, Out, 0);
|
|
523 |
#else
|
|
524 |
return MoveFile(In,Out) != 0;
|
|
525 |
#endif
|
|
526 |
}
|
|
527 |
|
|
528 |
stream *FileTemp(anynode* UNUSED_PARAM(Any))
|
|
529 |
{
|
|
530 |
#ifndef TODO
|
|
531 |
assert(NULL); // not supported yet
|
|
532 |
#endif
|
|
533 |
return NULL;
|
|
534 |
}
|
|
535 |
|
|
536 |
bool_t FileTempName(anynode* UNUSED_PARAM(Any),tchar_t* UNUSED_PARAM(Out), size_t UNUSED_PARAM(OutLen))
|
|
537 |
{
|
|
538 |
#ifndef TODO
|
|
539 |
assert(NULL); // not supported yet
|
|
540 |
#endif
|
|
541 |
return 0;
|
|
542 |
}
|
|
543 |
|
|
544 |
FILE_DLL int64_t GetPathFreeSpace(nodecontext* UNUSED_PARAM(p), const tchar_t* Path)
|
|
545 |
{
|
|
546 |
ULARGE_INTEGER lpFreeBytesAvailable;
|
|
547 |
ULARGE_INTEGER lpTotal;
|
|
548 |
|
|
549 |
if (!GetDiskFreeSpaceEx(Path, &lpFreeBytesAvailable, &lpTotal, NULL))
|
|
550 |
return -1;
|
|
551 |
return (int64_t)lpFreeBytesAvailable.QuadPart;
|
|
552 |
}
|
|
553 |
#endif
|