10 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
12 #include <sys/types.h>
17 #if defined(__unix__) || defined(__APPLE__)
21 #if defined(__WIN32__)
22 #define WIN32_LEAN_AND_MEAN
32 typedef unsigned char byte;
33 typedef unsigned short uint16;
34 typedef unsigned int uint;
35 typedef unsigned int FileSize;
36 typedef long long int64;
37 typedef unsigned long long uint64;
42 #define null ((void *)0)
44 #define MAX_LOCATION 797
45 #define MAX_FILENAME 274
47 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
48 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
49 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
50 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
51 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(const char * source, int * wordCount);
52 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(const char * source, uint16 * dest, int max);
53 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(const uint16 * source);
54 void __ecereNameSpace__ecere__sys__ChangeCh(char * string, char ch1, char ch2);
56 #if defined(__WIN32__) || defined(__WATCOMC__)
58 __declspec(dllimport) BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
63 typedef unsigned int FileAttribs;
64 typedef int64 SecSince1970;
65 typedef SecSince1970 TimeStamp;
79 unlocked = 0, // LOCK_UN _SH_DENYNO
80 shared = 1, // LOCK_SH _SH_DENYWR
81 exclusive = 2 // LOCK_EX _SH_DENYRW
85 #define isArchive 0x0002
86 #define isHidden 0x0004
87 #define isReadOnly 0x0008
88 #define isSystem 0x0010
89 #define isTemporary 0x0020
90 #define isDirectory 0x0040
91 #define isDrive 0x0080
92 #define isCDROM 0x0100
93 #define isRemote 0x0200
94 #define isRemovable 0x0400
95 #define isServer 0x0800
96 #define isShare 0x1000
102 SecSince1970 accessed;
103 SecSince1970 modified;
104 SecSince1970 created;
107 char * __ecereNameSpace__ecere__sys__GetLastDirectory(const char * string, char * output);
108 bool __ecereNameSpace__ecere__sys__SplitArchivePath(const char * fileName, char * archiveName, char ** archiveFile);
110 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
111 void __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(const char * archive, char * name);
113 static BOOL CALLBACK EnumThreadWindowsProc(HWND hwnd, LPARAM lParam)
116 if(IsWindowVisible(hwnd) && GetWindowThreadProcessId(hwnd, &pid) && pid == GetCurrentProcessId())
118 *(void **)lParam = hwnd;
123 bool WinReviveNetworkResource(uint16 * _wfileName)
126 HWND windowHandle = null;
127 NETRESOURCE nr = { 0 };
128 nr.dwType = RESOURCETYPE_DISK;
129 nr.lpRemoteName = _wfileName;
130 if(_wfileName[0] != '\\' || _wfileName[1] == '\\')
132 uint16 volumePathName[MAX_LOCATION];
133 if(GetVolumePathName(_wfileName, volumePathName, MAX_LOCATION))
135 uint16 remoteName[MAX_LOCATION];
136 DWORD size = MAX_LOCATION;
137 volumePathName[wcslen(volumePathName)-1] = 0;
138 if(WNetGetConnection(volumePathName, remoteName, &size) == ERROR_CONNECTION_UNAVAIL)
140 nr.lpRemoteName = remoteName;
141 nr.lpLocalName = volumePathName;
149 EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsProc, (LPARAM)&windowHandle);
152 EnumWindows(EnumThreadWindowsProc, (LPARAM)&windowHandle);
155 if(WNetAddConnection3(windowHandle, &nr, null, null, CONNECT_INTERACTIVE|CONNECT_PROMPT) == NO_ERROR)
160 TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
161 void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
165 uint FILE_GetSize(FILE * input)
170 int fd = fileno(input);
177 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait)
179 if(!output && !input)
183 #if defined(__WIN32__)
184 int handle = fileno(output ? output : input);
185 HANDLE hFile = (HANDLE)_get_osfhandle(handle);
186 OVERLAPPED overlapped = { 0 };
187 overlapped.Offset = (uint)(start & 0xFFFFFFFF);
188 overlapped.OffsetHigh = (uint)((start & 0xFFFFFFFF00000000LL) >> 32);
190 return UnlockFileEx(hFile, 0,
191 (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
192 (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
195 return LockFileEx(hFile, ((type == exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0) | (wait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), 0,
196 (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
197 (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
203 fl.l_type = (type == unlocked) ? F_UNLCK : ((type == exclusive) ? F_WRLCK : F_RDLCK);
204 fl.l_whence = SEEK_SET;
209 fd = fileno(output ? output : input);
210 return fcntl(fd, wait ? F_SETLKW : F_SETLK, &fl) != -1;
215 void FILE_set_buffered(FILE * input, FILE * output, bool value)
217 #if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
219 setvbuf(input, null, value ? _IOFBF : _IONBF, 0);
220 if(output && output != input)
221 setvbuf(output, null, value ? _IOFBF : _IONBF, 0);
225 FileAttribs FILE_FileExists(const char * fileName)
228 FileAttribs result = 0;
229 uint attribute = 0; // Initialization isn't actually required here but GCC complains about it.
230 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
231 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\\\"))
233 result = (FileAttribs)(isDirectory);
236 attribute = GetFileAttributes(_wfileName);
237 #if !defined(ECERE_BOOTSTRAP)
238 if(!result && attribute == 0xFFFFFFFF)
240 if(WinReviveNetworkResource(_wfileName))
241 attribute = GetFileAttributes(_wfileName);
242 if(attribute == 0xFFFFFFFF)
244 if(fileName[0] == '\\' && fileName[1] == '\\')
246 NETRESOURCE nr = { 0 };
247 NETRESOURCE * buffer = null;
248 unsigned int size = sizeof(NETRESOURCE);
251 nr.dwScope = RESOURCE_GLOBALNET;
252 nr.dwType = RESOURCETYPE_DISK;
253 nr.lpRemoteName = _wfileName;
254 nr.lpProvider = L"Microsoft Windows Network";
256 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
259 int returnCode = WNetGetResourceInformationW(&nr, buffer, (DWORD *)&size, &dir);
260 if(returnCode == WN_MORE_DATA)
261 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
264 if(returnCode == WN_SUCCESS)
266 if(!_wcsicmp(buffer->lpRemoteName, _wfileName))
267 result = (FileAttribs)( isDirectory | isServer );
272 __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
277 if(!result && attribute != 0xFFFFFFFF)
279 if(attribute & FILE_ATTRIBUTE_DIRECTORY)
280 result = (FileAttribs)( isDirectory );
282 result = (FileAttribs)(isFile);
284 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
287 if(!access(fileName, F_OK))
291 return S_ISDIR(s.st_mode) ? (FileAttribs) ( isDirectory ) : (FileAttribs) ( isFile );
296 return (FileAttribs) 0;
301 bool FILE_FileGetSize(const char * fileName, FileSize * size)
304 #if defined(__WIN32__)
306 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
307 if(!_wstat(_wfileName, &s))
310 if(!stat(fileName, &s))
316 #if defined(__WIN32__)
317 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
322 bool FILE_FileGetStats(const char * fileName, FileStats * stats)
325 #if defined(__WIN32__)
326 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
328 if(!_wstat(_wfileName, &s))
331 if(!stat(fileName, &s))
334 stats->size = s.st_size;
335 stats->attribs = (s.st_mode & S_IFDIR) ? ((FileAttribs) (isDirectory)): ((FileAttribs) 0);
337 #if defined(__WIN32__)
339 HANDLE hFile = CreateFile(_wfileName, 0, FILE_SHARE_READ, null,
340 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
341 if(hFile != INVALID_HANDLE_VALUE)
343 #if defined(ECERE_BOOTSTRAP)
349 GetFileTime(hFile, &c, &a, &m);
350 stats->created = Win32FileTimeToTimeStamp(&c);
351 stats->accessed = Win32FileTimeToTimeStamp(&a);
352 stats->modified = Win32FileTimeToTimeStamp(&m);
359 stats->accessed = s.st_atime;
360 stats->created = s.st_ctime;
361 stats->modified = s.st_mtime;
364 stats->attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
365 stats->attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
366 stats->attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
367 stats->attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
368 stats->attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
369 stats->attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
373 #if defined(__WIN32__)
374 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
379 void FILE_FileFixCase(char * file)
381 #if defined(__WIN32__)
382 #ifndef ECERE_BOOTSTRAP
383 char archive[MAX_LOCATION], * name;
384 if(__ecereNameSpace__ecere__sys__SplitArchivePath(file, archive, &name))
386 char fileName[MAX_LOCATION];
387 strcpy(fileName, name);
388 __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(archive, fileName);
389 if(archive[0] != ':')
390 FILE_FileFixCase(archive);
391 sprintf(file, "<%s>%s", archive, fileName);
397 char parent[MAX_LOCATION] = "";
399 // Skip network protocols
400 if(strstr(file, "http://") == file) return;
402 // Copy drive letter to new path
403 if(file[0] && file[1] == ':')
405 parent[0] = (char)toupper(file[0]);
410 // Copy Microsoft Network string to new path
411 else if(file[0] == '\\' && file[1] == '\\')
413 parent[0] = parent[1] = '\\';
417 else if(file[0] == '/' && file[1] == '/')
419 parent[0] = parent[1] = '\\';
423 // Copy Entire Computer to new path
424 else if(file[0] == '/' && !file[1])
434 // Get next directory
435 char directory[MAX_FILENAME];
438 for(;(ch = file[c]) && (ch == '/' || ch == '\\'); c++);
439 for(;(ch = file[c]) && (ch != '/' && ch != '\\'); c++)
441 if(len < MAX_FILENAME)
442 directory[len++] = ch;
444 directory[len] = '\0';
447 if(parent[0] != '\\' || parent[1] != '\\' || strstr(parent+2, "\\"))
449 if(strcmp(directory, "..") && strcmp(directory, "."))
451 WIN32_FIND_DATA winFile;
452 uint16 dir[MAX_PATH];
455 __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(parent, dir, MAX_PATH);
456 if(dir[0]) wcscat(dir, L"\\");
458 uint16 * _wdirectory = __ecereNameSpace__ecere__sys__UTF8toUTF16(directory, null);
459 wcscat(dir, _wdirectory);
460 __ecereNameSpace__ecere__com__eSystem_Delete(_wdirectory);
463 handle = FindFirstFile(dir, &winFile);
464 if(parent[0] || (file[0] == '\\' || file[0] == '/'))
465 strcat(parent, "\\");
466 if(handle != INVALID_HANDLE_VALUE)
468 char * utf8 = __ecereNameSpace__ecere__sys__UTF16toUTF8(winFile.cFileName);
469 strcat(parent, utf8);
470 __ecereNameSpace__ecere__com__eSystem_Delete(utf8);
474 strcat(parent, directory);
478 if(parent[0] || (file[0] == '\\' || file[0] == '/'))
479 strcat(parent, "\\");
481 strcat(parent, directory);
484 #ifndef ECERE_BOOTSTRAP
491 DWORD count = 0xFFFFFFFF;
492 DWORD size = 512 * sizeof(NETRESOURCE);
493 NETRESOURCE * buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
494 NETRESOURCE nr = {0};
497 nr.dwScope = RESOURCE_GLOBALNET;
498 nr.dwType = RESOURCETYPE_DISK;
500 nr.lpRemoteName = __ecereNameSpace__ecere__sys__UTF8toUTF16(parent, null);
501 nr.lpProvider = L"Microsoft Windows Network";
504 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
509 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
510 if(returnCode != ERROR_MORE_DATA)
513 buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
515 WNetCloseEnum(handle);
520 for(c = 0; c<count; c++)
522 char shareName[MAX_FILENAME];
523 char * remoteName = __ecereNameSpace__ecere__sys__UTF16toUTF8(buffer[c].lpRemoteName);
524 __ecereNameSpace__ecere__sys__GetLastDirectory(remoteName, shareName);
525 __ecereNameSpace__ecere__com__eSystem_Delete(remoteName);
526 if(!strcmpi(directory, shareName))
528 strcpy(directory, shareName);
535 __ecereNameSpace__ecere__com__eSystem_Delete(nr.lpRemoteName);
536 __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
538 strcat(parent, "\\");
539 strcat(parent, directory);
545 directory[0] = (char)toupper(directory[0]);
546 strcat(parent, directory);
551 strcpy(file, parent);
554 __ecereNameSpace__ecere__sys__ChangeCh(file, '\\', '/');
558 void FILE_FileOpen(const char * fileName, FileOpenMode mode, FILE ** input, FILE **output)
560 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
561 uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
563 file.handle = CreateFile(_wfileName,
564 ((mode == FOM_read || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_READ : 0) |
565 ((mode == FOM_write || mode == FOM_append || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_WRITE: 0),
566 FILE_SHARE_READ|FILE_SHARE_WRITE,
568 (mode == write || mode == writeRead) ? TRUNCATE_EXISTING : ((mode == read || mode == readWrite) ? OPEN_EXISTING : OPEN_ALWAYS), 0, null);
575 case FOM_read: handle = _open_osfhandle((int)file.handle, _O_RDONLY); break;
576 case FOM_write: handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_TRUNC); break;
577 case FOM_append: handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_APPEND); break;
578 case FOM_readWrite: handle = _open_osfhandle((int)file.handle, _O_RDWR); break;
579 case FOM_writeRead: handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_CREAT | _O_TRUNC); break;
580 case FOM_appendRead: handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_APPEND | _O_CREAT); break;
586 case FOM_read: *input = _fdopen(handle, "rb"); break;
587 case FOM_write: *output = _fdopen(handle, "wb"); break;
588 case FOM_append: *output = _fdopen(handle, "ab"); break;
589 case FOM_readWrite: *input = *output = _fdopen(handle, "r+b"); break;
590 case FOM_writeRead: *input = *output = _fdopen(handle, "w+b"); break;
591 case FOM_appendRead: *input = *output = _fdopen(handle, "a+b"); break;
598 case FOM_read: *input = _wfopen(_wfileName, L"rb"); break;
599 case FOM_write: *output = _wfopen(_wfileName, L"wb"); break;
600 case FOM_append: *output = _wfopen(_wfileName, L"ab"); break;
601 case FOM_readWrite: *input = *output = _wfopen(_wfileName, L"r+b"); break;
602 case FOM_writeRead: *input = *output = _wfopen(_wfileName, L"w+b"); break;
603 case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
605 if(!mode && WinReviveNetworkResource(_wfileName))
609 case FOM_read: *input = _wfopen(_wfileName, L"rb"); break;
610 case FOM_write: *output = _wfopen(_wfileName, L"wb"); break;
611 case FOM_append: *output = _wfopen(_wfileName, L"ab"); break;
612 case FOM_readWrite: *input = *output = _wfopen(_wfileName, L"r+b"); break;
613 case FOM_writeRead: *input = *output = _wfopen(_wfileName, L"w+b"); break;
614 case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
617 __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
621 case FOM_read: *input = fopen(fileName, "rb"); break;
622 case FOM_write: *output = fopen(fileName, "wb"); break;
623 case FOM_append: *output = fopen(fileName, "ab"); break;
624 case FOM_readWrite: *input = *output = fopen(fileName, "r+b"); break;
625 case FOM_writeRead: *input = *output = fopen(fileName, "w+b"); break;
626 case FOM_appendRead: *input = *output = fopen(fileName, "a+b"); break;