Codebase list bcmatroska2 / d9596de
Import upstream version 5.1.20 Dennis Filder authored 1 year, 7 months ago Debian Janitor committed 1 year, 7 months ago
6 changed file(s) with 980 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
4343 endif()
4444
4545 configure_file(config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
46
47 find_package(bctoolbox REQUIRED CONFIG)
4648
4749 include_directories(
4850 ${CMAKE_BINARY_DIR}
1919 License: BSD-3
2020 Source0: %{name}-%{version}.tar.gz
2121 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
22
23 Requires: %{pkg_prefix}bctoolbox
2224
2325 %description
2426 A libary to parse Matroska files (.mkv and .mka).
4343 list(APPEND COREC_SOURCES
4444 helpers/charconvert/charconvert_win32.c
4545 helpers/date/date_win32.c
46 helpers/file/file_win32.c
46 helpers/file/file_bctbx_win32.c
4747 helpers/system/ccsystem_win32.c
4848 multithread/multithread_win32.c
4949 str/str_win32.c
5252 list(APPEND COREC_SOURCES
5353 helpers/date/date_libc.c
5454 helpers/file/file_libc.c
55 helpers/file/file_bctbx.c
5556 multithread/multithread_pthread.c
5657 )
5758 if (NOT IOS)
9091
9192 add_library(corec-objects OBJECT ${COREC_SOURCES})
9293 set_target_properties(corec-objects PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
94 target_link_libraries(corec-objects bctoolbox)
9395
9496 install(FILES
9597 banned.h
1010 SOURCE streams.c {class Streams_Class:1}
1111 SOURCE tools.c
1212
13 SOURCE(TARGET_LINUX || TARGET_OSX || TARGET_ANDROID) file_libc.c {class File_Class:1}
13 SOURCE(TARGET_LINUX || TARGET_OSX || TARGET_ANDROID) file_bctbx.c {class File_Class:1}
1414 SOURCE(TARGET_PALMOS) file_palmos.c {class File_Class:1}
1515 SOURCE(TARGET_PALMOS) filedb_palmos.c {class FileDb_Class:1}
1616 SOURCE(TARGET_PALMOS) filevfs_palmos.c {class VFS_Class:1}
1717 SOURCE(TARGET_PS2SDK) file_ps2sdk.c {class File_Class:1 reg FileXio:2}
1818 SOURCE(TARGET_SYMBIAN) file_symbian.cpp {class File_Class:1}
19 SOURCE(TARGET_WIN) file_win32.c {class File_Class:1}
19 SOURCE(TARGET_WIN) file_bctbx_win32.c {class File_Class:1}
2020 SOURCE(CONFIG_STDIO && !TARGET_PALMOS) stream_stdio.c {class Stdio_Class:2}
2121
2222 USE(TARGET_PS2SDK) ps2sdk_filexio
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 "config.h"
30
31 #ifdef CONFIG_FILEPOS_64
32 #define __USE_FILE_OFFSET64
33 #endif
34
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include <dirent.h>
41 #include <errno.h>
42
43 #define bool_t bctbx_bool_t
44 #include <bctoolbox/vfs.h>
45 #undef bool_t
46
47 // Do not move. Define TARGET_*.
48 #include "file.h"
49
50 #if defined(TARGET_OSX)
51 #include <sys/mount.h>
52 #elif defined(TARGET_QNX)
53 #include <sys/statvfs.h>
54 #else
55 #include <sys/vfs.h>
56 #endif
57
58 #if defined(O_ACCMODE)
59 #define _RW_ACCESS_FILE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
60 #define _RW_ACCESS_DIR (S_IRWXU|S_IRWXG|S_IRWXO)
61 #elif defined(S_IREAD) && defined(S_IWRITE)
62 #define _RW_ACCESS_FILE (S_IREAD|S_IWRITE)
63 #define _RW_ACCESS_DIR (S_IREAD|S_IWRITE|S_IEXEC)
64 #endif
65
66 typedef struct filestream
67 {
68 stream Stream;
69 bctbx_vfs_file_t *fp;
70 tchar_t URL[MAXPATH]; // TODO: turn into a dynamic data
71 filepos_t Length;
72 int Flags;
73
74 tchar_t DirPath[MAXPATH]; // TODO: turn into a dynamic data
75 DIR *FindDir;
76
77 } filestream;
78
79 static err_t Open(filestream* p, const tchar_t* URL, int Flags)
80 {
81 if (p->fp != -1)
82 bctbx_file_close(p->fp);
83
84 p->Length = INVALID_FILEPOS_T;
85 p->fp = NULL;
86
87 if (URL && URL[0])
88 {
89 struct stat file_stats;
90 int mode = 0;
91
92 if (Flags & SFLAG_WRONLY && !(Flags & SFLAG_RDONLY))
93 mode = O_WRONLY;
94 else if (Flags & SFLAG_RDONLY && !(Flags & SFLAG_WRONLY))
95 mode = O_RDONLY;
96 else
97 mode = O_RDWR;
98
99 if (Flags & SFLAG_CREATE)
100 mode |= O_CREAT|O_TRUNC;
101
102 //TODO: verify it works with Unicode files too
103 p->fp = bctbx_file_open2(bctbx_vfs_get_default(), URL, mode);
104 if (p->fp == NULL)
105 {
106 if ((Flags & (SFLAG_REOPEN|SFLAG_SILENT))==0)
107 NodeReportError(p,NULL,ERR_ID,ERR_FILE_NOT_FOUND,URL);
108 return ERR_FILE_NOT_FOUND;
109 }
110
111 tcscpy_s(p->URL,TSIZEOF(p->URL),URL);
112
113 if (stat(URL, &file_stats) == 0)
114 p->Length = file_stats.st_size;
115
116 }
117 return ERR_NONE;
118 }
119
120 static err_t Read(filestream* p,void* Data,size_t Size,size_t* Readed)
121 {
122 err_t Err;
123 int n = bctbx_file_read2(p->fp, Data, (unsigned int)Size);
124 if (n<0)
125 {
126 n=0;
127 Err = ERR_READ;
128 }
129 else
130 Err = ((size_t)n != Size) ? ERR_END_OF_FILE:ERR_NONE;
131
132 if (Readed)
133 *Readed = n;
134 return Err;
135 }
136
137 static err_t ReadBlock(filestream* p,block* Block,size_t Ofs,size_t Size,size_t* Readed)
138 {
139 return Read(p,(void*)(Block->Ptr+Ofs),Size,Readed);
140 }
141
142 static err_t Write(filestream* p,const void* Data,size_t Size,size_t* Written)
143 {
144 err_t Err;
145 int n = bctbx_file_write2(p->fp, Data, (unsigned int)Size);
146
147 if (n<0)
148 {
149 n=0;
150 Err = ERR_WRITE;
151 }
152 else
153 Err = (n != Size) ? ERR_WRITE:ERR_NONE;
154
155 if (Written)
156 *Written = n;
157 return Err;
158 }
159
160 static filepos_t Seek(filestream* p,filepos_t Pos,int SeekMode)
161 {
162 off_t NewPos = bctbx_file_seek(p->fp, Pos, SeekMode);
163 if (NewPos<0)
164 return INVALID_FILEPOS_T;
165 return NewPos;
166 }
167
168 static err_t SetLength(filestream* p,dataid Id,const filepos_t* Data,size_t Size)
169 {
170 if (Size != sizeof(filepos_t))
171 return ERR_INVALID_DATA;
172
173 if (bctbx_file_truncate(p->fp, *Data)!=0)
174 return ERR_BUFFER_FULL;
175
176 return ERR_NONE;
177 }
178
179 static err_t OpenDir(filestream* p,const tchar_t* Path,int UNUSED_PARAM(Flags))
180 {
181 if (p->FindDir)
182 closedir(p->FindDir);
183
184 if (Path[0]==0)
185 Path = T("/");
186
187 p->FindDir = opendir(Path);
188 if (!p->FindDir)
189 {
190 if (errno == ENOTDIR)
191 return ERR_NOT_DIRECTORY;
192 else
193 return ERR_FILE_NOT_FOUND;
194 }
195
196 tcscpy_s(p->DirPath,TSIZEOF(p->DirPath),Path);
197 AddPathDelimiter(p->DirPath,TSIZEOF(p->DirPath));
198 return ERR_NONE;
199 }
200
201 extern datetime_t LinuxToDateTime(time_t);
202
203 static err_t EnumDir(filestream* p,const tchar_t* Exts,bool_t ExtFilter,streamdir* Item)
204 {
205 struct dirent *Dirent;
206
207 if (!p->FindDir)
208 return ERR_END_OF_FILE;
209
210 Item->FileName[0] = 0;
211 Item->Size = INVALID_FILEPOS_T;
212
213 while (!Item->FileName[0] && (Dirent = readdir(p->FindDir)) != NULL)
214 {
215 tchar_t FilePath[MAXPATH];
216 struct stat file_stats;
217
218 if (Dirent->d_name[0]=='.') // skip hidden files and current directory
219 continue;
220
221 tcscpy_s(FilePath, TSIZEOF(FilePath), p->DirPath);
222 tcscat_s(FilePath, TSIZEOF(FilePath), Dirent->d_name);
223 tcscpy_s(Item->FileName,TSIZEOF(Item->FileName), Dirent->d_name);
224
225 stat(FilePath, &file_stats);
226
227 Item->ModifiedDate = LinuxToDateTime(file_stats.st_mtime);
228 if (S_ISDIR(file_stats.st_mode))
229 {
230 Item->Type = FTYPE_DIR;
231 Item->Size = INVALID_FILEPOS_T;
232 }
233 else
234 {
235 Item->Size = file_stats.st_size;
236 Item->Type = CheckExts(Item->FileName,Exts);
237
238 if (!Item->Type && ExtFilter)
239 Item->FileName[0] = 0; // skip
240 }
241 }
242
243 if (!Item->FileName[0])
244 {
245 closedir(p->FindDir);
246 p->FindDir = NULL;
247 return ERR_END_OF_FILE;
248 }
249
250 return ERR_NONE;
251 }
252
253 static void Delete(filestream* p)
254 {
255 if (p->fp != NULL)
256 {
257 bctbx_file_close(p->fp);
258 p->fp = NULL;
259 }
260 if (p->FindDir)
261 closedir(p->FindDir);
262 }
263
264 META_START(File_Class,FILE_CLASS)
265 META_CLASS(SIZE,sizeof(filestream))
266 META_CLASS(PRIORITY,PRI_MINIMUM)
267 META_CLASS(DELETE,Delete)
268 META_VMT(TYPE_FUNC,stream_vmt,Open,Open)
269 META_VMT(TYPE_FUNC,stream_vmt,Read,Read)
270 META_VMT(TYPE_FUNC,stream_vmt,ReadBlock,ReadBlock)
271 META_VMT(TYPE_FUNC,stream_vmt,Write,Write)
272 META_VMT(TYPE_FUNC,stream_vmt,Seek,Seek)
273 META_VMT(TYPE_FUNC,stream_vmt,OpenDir,OpenDir)
274 META_VMT(TYPE_FUNC,stream_vmt,EnumDir,EnumDir)
275 META_CONST(TYPE_INT,filestream,fp,NULL)
276 META_DATA_RDONLY(TYPE_INT,STREAM_FLAGS,filestream,Flags)
277 META_DATA_RDONLY(TYPE_STRING,STREAM_URL,filestream,URL)
278 META_DATA_RDONLY(TYPE_STRING,STREAM_ENUM_BASE,filestream,DirPath)
279 META_PARAM(SET,STREAM_LENGTH,SetLength)
280 META_DATA(TYPE_FILEPOS,STREAM_LENGTH,filestream,Length)
281 META_PARAM(STRING,NODE_PROTOCOL,T("file"))
282 META_END(STREAM_CLASS)
283
284 bool_t FileExists(nodecontext *p,const tchar_t* Path)
285 {
286 struct stat file_stats;
287 return stat(Path, &file_stats) == 0;
288 }
289
290 bool_t FileErase(nodecontext *p,const tchar_t* Path, bool_t Force, bool_t Safe)
291 {
292 if (Force)
293 {
294 struct stat file_stats;
295 if (stat(Path, &file_stats) == 0)
296 {
297 if ((file_stats.st_mode & S_IWUSR)==0)
298 {
299 file_stats.st_mode |= S_IWUSR;
300 chmod(Path,file_stats.st_mode);
301 }
302 }
303 }
304 return unlink(Path) == 0;
305 }
306
307 bool_t FolderErase(nodecontext *p,const tchar_t* Path, bool_t Force, bool_t Safe)
308 {
309 if (Force)
310 {
311 struct stat file_stats;
312 if (stat(Path, &file_stats) == 0)
313 {
314 if ((file_stats.st_mode & S_IWUSR)==0)
315 {
316 file_stats.st_mode |= S_IWUSR;
317 chmod(Path,file_stats.st_mode);
318 }
319 }
320 }
321 return rmdir(Path) == 0;
322 }
323
324 bool_t PathIsFolder(nodecontext *p,const tchar_t* Path)
325 {
326 struct stat file_stats;
327 if (stat(Path, &file_stats) == 0)
328 {
329 return (file_stats.st_mode & S_IFDIR) == S_IFDIR;
330 }
331 return 0;
332 }
333
334 datetime_t FileDateTime(nodecontext *p,const tchar_t* Path)
335 {
336 datetime_t Date = INVALID_DATETIME_T;
337 struct stat file_stats;
338 if (stat(Path, &file_stats) == 0)
339 Date = LinuxToDateTime(file_stats.st_mtime);
340 return Date;
341 }
342
343 bool_t FileMove(nodecontext *p,const tchar_t* In,const tchar_t* Out)
344 {
345 return rename(In,Out) == 0;
346 }
347
348 bool_t FolderCreate(nodecontext *p,const tchar_t* Path)
349 {
350 return mkdir(Path,_RW_ACCESS_DIR) == 0;
351 }
352
353 void FindFiles(nodecontext *p,const tchar_t* Path, const tchar_t* Mask,void(*Process)(const tchar_t*,void*),void* Param)
354 {
355 DIR* Directory;
356 struct dirent* DirectoryInfo;
357 tchar_t TPathToFile[MAXPATH];
358
359 Directory = opendir(Path);
360 if (Directory)
361 {
362 while ( (DirectoryInfo = readdir(Directory)) != NULL )
363 {
364 char* FileExtension = 0;
365 FileExtension = strrchr(DirectoryInfo->d_name, '.');
366 if(FileExtension)
367 {
368 if (strcmp(Mask, FileExtension ) == 0 )
369 {
370 tcscpy_s(TPathToFile, TSIZEOF(TPathToFile), Path);
371 tcscat_s(TPathToFile, TSIZEOF(TPathToFile), DirectoryInfo->d_name);
372 Process(TPathToFile, Param);
373 }
374 }
375 }
376
377 closedir(Directory);
378 }
379
380 }
381
382 stream *FileTemp(anynode *Any)
383 {
384 #ifndef TODO
385 assert(NULL); // not supported yet
386 #endif
387 return NULL;
388 }
389
390 bool_t FileTempName(anynode *Any,tchar_t *Out, size_t OutLen)
391 {
392 #ifndef TODO
393 assert(NULL); // not supported yet
394 #endif
395 return 0;
396 }
397
398 int64_t GetPathFreeSpace(nodecontext* UNUSED_PARAM(p), const tchar_t* Path)
399 {
400 #ifndef TODO
401 // need to an include (see at includes)
402 #if defined(TARGET_QNX)
403 struct statvfs st;
404 if (statvfs(Path, &st) < 0)
405 #else
406 struct statfs st;
407 if (statfs(Path, &st) < 0)
408 #endif
409 return -1;
410 return (int64_t)st.f_bsize * (int64_t)st.f_bavail;
411 #else
412 return -1;
413 #endif
414 }
415
416
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