7 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
14 #if defined(__unix__) || defined(__APPLE__)
18 #if defined(__WIN32__)
19 #define WIN32_LEAN_AND_MEAN
29 typedef unsigned char byte;
30 typedef unsigned short uint16;
31 typedef unsigned int uint;
32 typedef unsigned int FileSize;
33 typedef long long int64;
34 typedef unsigned long long uint64;
39 #define null ((void *)0)
41 #define MAX_LOCATION 797
42 #define MAX_FILENAME 274
44 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
45 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
46 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
47 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
48 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(char * source, int * wordCount);
49 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(char * source, uint16 * dest, int max);
50 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(uint16 * source);
52 #if defined(__WIN32__) || defined(__WATCOMC__)
54 __declspec(dllimport) BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
59 typedef unsigned int FileAttribs;
60 typedef int64 SecSince1970;
61 typedef SecSince1970 TimeStamp;
75 unlocked = 0, // LOCK_UN _SH_DENYNO
76 shared = 1, // LOCK_SH _SH_DENYWR
77 exclusive = 2 // LOCK_EX _SH_DENYRW
81 #define isArchive 0x0002
82 #define isHidden 0x0004
83 #define isReadOnly 0x0008
84 #define isSystem 0x0010
85 #define isTemporary 0x0020
86 #define isDirectory 0x0040
87 #define isDrive 0x0080
88 #define isCDROM 0x0100
89 #define isRemote 0x0200
90 #define isRemovable 0x0400
91 #define isServer 0x0800
92 #define isShare 0x1000
98 SecSince1970 accessed;
99 SecSince1970 modified;
100 SecSince1970 created;
103 char * __ecereNameSpace__ecere__sys__GetLastDirectory(char * string, char * output);
104 bool __ecereNameSpace__ecere__sys__SplitArchivePath(char * fileName, char * archiveName, char ** archiveFile);
106 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
107 void __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(char * archive, char * name);
109 static BOOL CALLBACK EnumThreadWindowsProc(HWND hwnd, LPARAM lParam)
112 if(IsWindowVisible(hwnd) && GetWindowThreadProcessId(hwnd, &pid) && pid == GetCurrentProcessId())
114 *(void **)lParam = hwnd;
119 bool WinReviveNetworkResource(uint16 * _wfileName)
122 HWND windowHandle = null;
123 NETRESOURCE nr = { 0 };
124 nr.dwType = RESOURCETYPE_DISK;
125 nr.lpRemoteName = _wfileName;
126 if(_wfileName[0] != '\\' || _wfileName[1] == '\\')
128 uint16 volumePathName[MAX_LOCATION];
129 if(GetVolumePathName(_wfileName, volumePathName, MAX_LOCATION))
131 uint16 remoteName[MAX_LOCATION];
132 DWORD size = MAX_LOCATION;
133 volumePathName[wcslen(volumePathName)-1] = 0;
134 if(WNetGetConnection(volumePathName, remoteName, &size) == ERROR_CONNECTION_UNAVAIL)
136 nr.lpRemoteName = remoteName;
137 nr.lpLocalName = volumePathName;
145 EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsProc, (LPARAM)&windowHandle);
148 EnumWindows(EnumThreadWindowsProc, (LPARAM)&windowHandle);
151 if(WNetAddConnection3(windowHandle, &nr, null, null, CONNECT_INTERACTIVE|CONNECT_PROMPT) == NO_ERROR)
156 TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
157 void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
161 uint FILE_GetSize(FILE * input)
166 int fd = fileno(input);
173 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait)
175 if(!output && !input)
179 #if defined(__WIN32__)
180 int handle = fileno(output ? output : input);
181 HANDLE hFile = (HANDLE)_get_osfhandle(handle);
182 OVERLAPPED overlapped = { 0 };
183 overlapped.Offset = (uint)(start & 0xFFFFFFFF);
184 overlapped.OffsetHigh = (uint)((start & 0xFFFFFFFF00000000LL) >> 32);
186 return UnlockFileEx(hFile, 0,
187 (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
188 (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
191 return LockFileEx(hFile, ((type == exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0) | (wait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), 0,
192 (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
193 (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
199 fl.l_type = (type == unlocked) ? F_UNLCK : ((type == exclusive) ? F_WRLCK : F_RDLCK);
200 fl.l_whence = SEEK_SET;
205 fd = fileno(output ? output : input);
206 return fcntl(fd, wait ? F_SETLKW : F_SETLK, &fl) != -1;
211 void FILE_set_buffered(FILE * input, FILE * output, bool value)
213 #if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
215 setvbuf(input, null, value ? _IOFBF : _IONBF, 0);
216 if(output && output != input)
217 setvbuf(output, null, value ? _IOFBF : _IONBF, 0);
221 FileAttribs FILE_FileExists(char * fileName)
224 FileAttribs result = 0;
225 uint attribute = 0; // Initialization isn't actually required here but GCC complains about it.
226 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
227 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\\\"))
229 result = (FileAttribs)(isDirectory);
232 attribute = GetFileAttributes(_wfileName);
233 #if !defined(ECERE_BOOTSTRAP)
234 if(!result && attribute == 0xFFFFFFFF)
236 if(WinReviveNetworkResource(_wfileName))
237 attribute = GetFileAttributes(_wfileName);
238 if(attribute == 0xFFFFFFFF)
240 if(fileName[0] == '\\' && fileName[1] == '\\')
242 NETRESOURCE nr = { 0 };
243 NETRESOURCE * buffer = null;
244 unsigned int size = sizeof(NETRESOURCE);
247 nr.dwScope = RESOURCE_GLOBALNET;
248 nr.dwType = RESOURCETYPE_DISK;
249 nr.lpRemoteName = _wfileName;
250 nr.lpProvider = L"Microsoft Windows Network";
252 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
255 int returnCode = WNetGetResourceInformationW(&nr, buffer, (DWORD *)&size, &dir);
256 if(returnCode == WN_MORE_DATA)
257 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
260 if(returnCode == WN_SUCCESS)
262 if(!_wcsicmp(buffer->lpRemoteName, _wfileName))
263 result = (FileAttribs)( isDirectory | isServer );
268 __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
273 if(!result && attribute != 0xFFFFFFFF)
275 if(attribute & FILE_ATTRIBUTE_DIRECTORY)
276 result = (FileAttribs)( isDirectory );
278 result = (FileAttribs)(isFile);
280 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
283 if(!access(fileName, F_OK))
287 return S_ISDIR(s.st_mode) ? (FileAttribs) ( isDirectory ) : (FileAttribs) ( isFile );
292 return (FileAttribs) 0;
297 bool FILE_FileGetSize(char * fileName, FileSize * size)
300 #if defined(__WIN32__)
302 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
303 if(!_wstat(_wfileName, &s))
306 if(!stat(fileName, &s))
312 #if defined(__WIN32__)
313 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
318 bool FILE_FileGetStats(char * fileName, FileStats * stats)
321 #if defined(__WIN32__)
322 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
324 if(!_wstat(_wfileName, &s))
327 if(!stat(fileName, &s))
330 stats->size = s.st_size;
331 stats->attribs = (s.st_mode & S_IFDIR) ? ((FileAttribs) (isDirectory)): ((FileAttribs) 0);
333 #if defined(__WIN32__)
335 HANDLE hFile = CreateFile(_wfileName, 0, FILE_SHARE_READ, null,
336 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
337 if(hFile != INVALID_HANDLE_VALUE)
339 #if defined(ECERE_BOOTSTRAP)
345 GetFileTime(hFile, &c, &a, &m);
346 stats->created = Win32FileTimeToTimeStamp(&c);
347 stats->accessed = Win32FileTimeToTimeStamp(&a);
348 stats->modified = Win32FileTimeToTimeStamp(&m);
355 stats->accessed = s.st_atime;
356 stats->created = s.st_ctime;
357 stats->modified = s.st_mtime;
360 stats->attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
361 stats->attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
362 stats->attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
363 stats->attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
364 stats->attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
365 stats->attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
369 #if defined(__WIN32__)
370 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
375 void FILE_FileFixCase(char * file)
377 #if defined(__WIN32__)
378 #ifndef ECERE_BOOTSTRAP
379 char archive[MAX_LOCATION], * name;
380 if(__ecereNameSpace__ecere__sys__SplitArchivePath(file, archive, &name))
382 char fileName[MAX_LOCATION];
383 strcpy(fileName, name);
384 __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(archive, fileName);
385 FILE_FileFixCase(archive);
386 sprintf(file, "<%s>%s", archive, fileName);
392 char parent[MAX_LOCATION] = "";
394 // Skip network protocols
395 if(strstr(file, "http://") == file) return;
397 // Copy drive letter to new path
398 if(file[0] && file[1] == ':')
400 parent[0] = (char)toupper(file[0]);
405 // Copy Microsoft Network string to new path
406 else if(file[0] == '\\' && file[1] == '\\')
408 parent[0] = parent[1] = '\\';
412 // Copy Entire Computer to new path
413 else if(file[0] == '/' && !file[1])
423 // Get next directory
424 char directory[MAX_FILENAME];
427 for(;(ch = file[c]) && (ch == '/' || ch == '\\'); c++);
428 for(;(ch = file[c]) && (ch != '/' && ch != '\\'); c++)
430 if(len < MAX_FILENAME)
431 directory[len++] = ch;
433 directory[len] = '\0';
436 if(parent[0] != '\\' || parent[1] != '\\' || strstr(parent+2, "\\"))
438 if(strcmp(directory, "..") && strcmp(directory, "."))
440 WIN32_FIND_DATA winFile;
441 uint16 dir[MAX_PATH];
444 __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(parent, dir, MAX_PATH);
445 if(dir[0]) wcscat(dir, L"\\");
447 uint16 * _wdirectory = __ecereNameSpace__ecere__sys__UTF8toUTF16(directory, null);
448 wcscat(dir, _wdirectory);
449 __ecereNameSpace__ecere__com__eSystem_Delete(_wdirectory);
452 handle = FindFirstFile(dir, &winFile);
453 if(parent[0] || (file[0] == '\\' || file[0] == '/'))
454 strcat(parent, "\\");
455 if(handle != INVALID_HANDLE_VALUE)
457 char * utf8 = __ecereNameSpace__ecere__sys__UTF16toUTF8(winFile.cFileName);
458 strcat(parent, utf8);
459 __ecereNameSpace__ecere__com__eSystem_Delete(utf8);
463 strcat(parent, directory);
467 if(parent[0] || (file[0] == '\\' || file[0] == '/'))
468 strcat(parent, "\\");
470 strcat(parent, directory);
473 #ifndef ECERE_BOOTSTRAP
480 DWORD count = 0xFFFFFFFF;
481 DWORD size = 512 * sizeof(NETRESOURCE);
482 NETRESOURCE * buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
483 NETRESOURCE nr = {0};
486 nr.dwScope = RESOURCE_GLOBALNET;
487 nr.dwType = RESOURCETYPE_DISK;
489 nr.lpRemoteName = __ecereNameSpace__ecere__sys__UTF8toUTF16(parent, null);
490 nr.lpProvider = L"Microsoft Windows Network";
493 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
498 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
499 if(returnCode != ERROR_MORE_DATA)
502 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
504 WNetCloseEnum(handle);
509 for(c = 0; c<count; c++)
511 char shareName[MAX_FILENAME];
512 char * remoteName = __ecereNameSpace__ecere__sys__UTF16toUTF8(buffer[c].lpRemoteName);
513 __ecereNameSpace__ecere__sys__GetLastDirectory(remoteName, shareName);
514 __ecereNameSpace__ecere__com__eSystem_Delete(remoteName);
515 if(!strcmpi(directory, shareName))
517 strcpy(directory, shareName);
524 __ecereNameSpace__ecere__com__eSystem_Delete(nr.lpRemoteName);
525 __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
527 strcat(parent, "\\");
528 strcat(parent, directory);
534 directory[0] = (char)toupper(directory[0]);
535 strcat(parent, directory);
540 strcpy(file, parent);
545 void FILE_FileOpen(char * fileName, FileOpenMode mode, FILE ** input, FILE **output)
547 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
548 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
550 file.handle = CreateFile(_wfileName,
551 ((mode == FOM_read || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_READ : 0) |
552 ((mode == FOM_write || mode == FOM_append || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_WRITE: 0),
553 FILE_SHARE_READ|FILE_SHARE_WRITE,
555 (mode == write || mode == writeRead) ? TRUNCATE_EXISTING : ((mode == read || mode == readWrite) ? OPEN_EXISTING : OPEN_ALWAYS), 0, null);
562 case FOM_read: handle = _open_osfhandle((int)file.handle, _O_RDONLY); break;
563 case FOM_write: handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_TRUNC); break;
564 case FOM_append: handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_APPEND); break;
565 case FOM_readWrite: handle = _open_osfhandle((int)file.handle, _O_RDWR); break;
566 case FOM_writeRead: handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_CREAT | _O_TRUNC); break;
567 case FOM_appendRead: handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_APPEND | _O_CREAT); break;
573 case FOM_read: *input = _fdopen(handle, "rb"); break;
574 case FOM_write: *output = _fdopen(handle, "wb"); break;
575 case FOM_append: *output = _fdopen(handle, "ab"); break;
576 case FOM_readWrite: *input = *output = _fdopen(handle, "r+b"); break;
577 case FOM_writeRead: *input = *output = _fdopen(handle, "w+b"); break;
578 case FOM_appendRead: *input = *output = _fdopen(handle, "a+b"); break;
585 case FOM_read: *input = _wfopen(_wfileName, L"rb"); break;
586 case FOM_write: *output = _wfopen(_wfileName, L"wb"); break;
587 case FOM_append: *output = _wfopen(_wfileName, L"ab"); break;
588 case FOM_readWrite: *input = *output = _wfopen(_wfileName, L"r+b"); break;
589 case FOM_writeRead: *input = *output = _wfopen(_wfileName, L"w+b"); break;
590 case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
592 if(!mode && WinReviveNetworkResource(_wfileName))
596 case FOM_read: *input = _wfopen(_wfileName, L"rb"); break;
597 case FOM_write: *output = _wfopen(_wfileName, L"wb"); break;
598 case FOM_append: *output = _wfopen(_wfileName, L"ab"); break;
599 case FOM_readWrite: *input = *output = _wfopen(_wfileName, L"r+b"); break;
600 case FOM_writeRead: *input = *output = _wfopen(_wfileName, L"w+b"); break;
601 case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
604 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
608 case FOM_read: *input = fopen(fileName, "rb"); break;
609 case FOM_write: *output = fopen(fileName, "wb"); break;
610 case FOM_append: *output = fopen(fileName, "ab"); break;
611 case FOM_readWrite: *input = *output = fopen(fileName, "r+b"); break;
612 case FOM_writeRead: *input = *output = fopen(fileName, "w+b"); break;
613 case FOM_appendRead: *input = *output = fopen(fileName, "a+b"); break;