14 #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch)))
16 #if defined(ECERE_BOOTSTRAP)
23 #ifndef ECERE_BOOTSTRAP
24 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
26 #include <sys/types.h>
31 #if defined(__unix__) || defined(__APPLE__)
35 #if defined(__WIN32__) || defined(__WATCOMC__)
41 #if defined(__WIN32__)
42 #define WIN32_LEAN_AND_MEAN
43 #define String String_
48 BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
50 // Missing function...
52 #ifndef WNetGetResourceInformation
53 DWORD APIENTRY WNetGetResourceInformationA(LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPTSTR* lplpSystem);
55 #define WNetGetResourceInformation WNetGetResourceInformationW
57 #define WNetGetResourceInformation WNetGetResourceInformationA
69 #endif //#ifndef ECERE_BOOTSTRAP
78 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET) && !defined(ECERE_BOOTSTRAP)
84 // IMPLEMENTATION OF THESE IS IN _File.c
87 uint FILE_GetSize(FILE * input);
88 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait);
89 void FILE_set_buffered(FILE * input, FILE * output, bool value);
90 FileAttribs FILE_FileExists(char * fileName);
91 bool FILE_FileGetSize(char * fileName, FileSize * size);
92 bool FILE_FileGetStats(char * fileName, FileStats stats);
93 void FILE_FileFixCase(char * file);
94 void FILE_FileOpen(char * fileName, FileOpenMode mode, FILE ** input, FILE **output);
98 FileSystem httpFileSystem;
100 public class FileSize : uint
102 // defaultAlignment = Right;
104 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, int alignment, DataDisplayFlags displayFlags)
108 eUtils_PrintSize(string, *size, 2);
109 len = strlen(string);
110 surface.WriteTextDots(alignment, x, y, width, string, len);
113 int OnCompare(FileSize data2)
120 else if(this < data2)
126 char * OnGetString(char * string, void * fieldData, bool * needClass)
128 PrintSize(string, this, 2);
132 bool OnGetDataFromString(char * string)
135 double value = strtod(string, &end);
137 if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint)1024 * 1024 * 1024;
138 else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint)1024 * 1024;
139 else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024;
141 this = (uint)(multiplier * value);
146 public class FileSize64 : uint64
148 int OnCompare(FileSize64 data2)
155 else if(this < data2)
161 char * OnGetString(char * string, void * fieldData, bool * needClass)
163 PrintBigSize(string, this, 2);
167 bool OnGetDataFromString(char * string)
170 double value = strtod(string, &end);
171 uint64 multiplier = 1;
172 if(strstr(end, "PB") || strstr(end, "pb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024;
173 else if(strstr(end, "TB") || strstr(end, "tb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024;
174 else if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint64)1024 * 1024 * 1024;
175 else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint64)1024 * 1024;
176 else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024;
178 this = (uint64)(multiplier * value);
185 virtual File ::Open(char * archive, char * name, FileOpenMode mode);
188 virtual FileAttribs ::Exists(char * archive, char * fileName);
189 virtual bool ::GetSize(char * archive, char * fileName, FileSize * size);
190 virtual bool ::Stats(char * archive, char * fileName, FileStats stats);
191 virtual void ::FixCase(char * archive, char * fileName);
194 virtual bool ::Find(FileDesc file, char * archive, char * name);
195 virtual bool ::FindNext(FileDesc file);
196 virtual void ::CloseDir(FileDesc file);
198 // Archive manipulation
199 virtual Archive ::OpenArchive(char * fileName, ArchiveOpenFlags create);
200 virtual bool ::QuerySize(char * fileName, FileSize * size);
203 public enum FileOpenMode { read = 1, write, append, readWrite, writeRead, appendRead };
204 public enum FileSeekMode { start, current, end };
206 #if !defined(ECERE_BOOTSTRAP)
207 static FileDialog fileDialog { text = $"Select File" };
212 unlocked = 0, // LOCK_UN _SH_DENYNO
213 shared = 1, // LOCK_SH _SH_DENYWR
214 exclusive = 2 // LOCK_EX _SH_DENYRW
217 public class File : IOChannel
219 FILE * input, * output;
221 uint ReadData(byte * bytes, uint numBytes)
223 return Read(bytes, 1, numBytes);
226 uint WriteData(byte * bytes, uint numBytes)
228 return Write(bytes, 1, numBytes);
233 if(output && output != input)
247 bool OnGetDataFromString(char * string)
256 File f = FileOpen(string, read);
263 uint read = f.Read(buffer, 1, sizeof(buffer));
264 Write(buffer, 1, read);
273 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
277 PrintSize(tempString, GetSize(), 2);
283 #ifndef ECERE_BOOTSTRAP
284 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
286 Window editData = class::OnEdit(dataBox, obsolete, x + 24, y, w - 48, h, userData);
289 dataBox, inactive = true, text = $"Imp", hotKey = f2,
290 position = { Max(x + 24, x + w - 24), y }, size = { 24, h };
292 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
294 fileDialog.master = rootWindow;
295 fileDialog.filePath = "";
296 fileDialog.type = open;
298 if(fileDialog.Modal() == ok)
300 char * filePath = fileDialog.filePath;
302 if(output.OnGetDataFromString(filePath))
304 SetData(output, false);
313 dataBox, inactive = true, text = $"Exp", hotKey = f2,
314 position = { Max(x + 24, x + w - 48), y }, size = { 24, h };
316 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
318 fileDialog.master = rootWindow;
319 fileDialog.type = save;
320 fileDialog.filePath = "";
321 if(fileDialog.Modal() == ok)
323 char * filePath = fileDialog.filePath;
324 File f = FileOpen(filePath, write);
327 File input = *(void **)data;
328 input.Seek(0, start);
332 uint read = input.Read(buffer, 1, sizeof(buffer));
333 f.Write(buffer, 1, read);
345 #endif //#ifndef ECERE_BOOTSTRAP
347 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOARCHIVE) && !defined(ECERE_BOOTSTRAP)
348 void OnSerialize(IOChannel channel)
350 uint size = this ? GetSize() : MAXDWORD;
353 byte * uncompressed = new byte[size];
355 if(uncompressed || !size)
357 uint count = Read(uncompressed, 1, size);
360 uint cSize = size + size / 1000 + 12;
361 byte * compressed = new byte[cSize];
364 compress2(compressed, &cSize, uncompressed, size, 9);
366 size.OnSerialize(channel);
367 cSize.OnSerialize(channel);
368 channel.WriteData(compressed, cSize);
377 size.OnSerialize(channel);
382 size.OnSerialize(channel);
384 // Will add position...
388 for(c = 0; c<size; c += sizeof(data))
390 uint count = Read(data, 1, sizeof(data));
391 buffer.WriteData(data, count);
397 void OnUnserialize(IOChannel channel)
403 size.OnUnserialize(channel);
407 cSize.OnUnserialize(channel);
409 compressed = new byte[cSize];
412 if(channel.ReadData(compressed, cSize) == cSize)
414 byte * uncompressed = new byte[size];
415 if(uncompressed || !size)
418 uncompress(uncompressed, &size, compressed, cSize);
419 Write(uncompressed, 1, size);
433 size.OnUnserialize(channel);
437 for(c = 0; c<size; c += sizeof(data))
439 uint count = Min(size - c, sizeof(data));
440 channel.ReadData(data, count);
441 Write(data, 1, count);
454 virtual bool Seek(int pos, FileSeekMode mode)
456 uint fmode = SEEK_SET;
459 case start: fmode = SEEK_SET; break;
460 case end: fmode = SEEK_END; break;
461 case current: fmode = SEEK_CUR; break;
463 return fseek(input ? input : output, pos, fmode) != EOF;
466 virtual uint Tell(void)
468 return input ? ftell(input) : ftell(output);
471 virtual int Read(void * buffer, uint size, uint count)
473 return input ? (int)fread(buffer, size, count, input) : 0;
476 virtual int Write(void * buffer, uint size, uint count)
478 return output ? (int)fwrite(buffer, size, count, output) : 0;
482 virtual bool Getc(char * ch)
484 int ich = fgetc(input);
487 if(ch) *ch = (char)ich;
493 virtual bool Putc(char ch)
495 return (fputc((int)ch, output) == EOF) ? false : true;
498 virtual bool Puts(const char * string)
503 result = (fputs(string, output) == EOF) ? false : true;
504 // TODO: Check if any repercusions of commenting out fflush here
505 // This is what broke the debugger in 0.44d2 , it is required for outputting things to the DualPipe
506 // Added an explicit flush call in DualPipe::Puts
512 virtual bool Eof(void)
514 return input ? feof(input) : true;
517 virtual bool Truncate(FileSize size)
519 #ifdef ECERE_BOOTSTRAP
520 fprintf(stderr, "WARNING: File::Truncate unimplemented in ecereBootstrap.\n");
523 #if defined(__WIN32__)
524 return output ? (_chsize(fileno(output), size) == 0) : false;
526 return output ? (ftruncate(fileno(output), size) == 0) : false;
531 virtual uint GetSize(void)
533 return FILE_GetSize(input);
536 virtual void CloseInput(void)
547 virtual void CloseOutput(void)
558 virtual bool Lock(FileLock type, uint64 start, uint64 length, bool wait)
560 return FILE_Lock(input, output, type, start, length, wait);
563 virtual bool Unlock(uint64 start, uint64 length, bool wait)
565 return Lock(unlocked, start, length, wait);
569 int Printf(char * format, ...)
574 char text[MAX_F_STRING];
576 va_start(args, format);
577 vsnprintf(text, sizeof(text), format, args);
578 text[sizeof(text)-1] = 0;
580 result = strlen(text);
586 public void PrintLn(typed_object object, ...)
590 va_start(args, object);
591 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
597 public void Print(typed_object object, ...)
601 va_start(args, object);
602 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
613 bool GetLine(char *s, int max)
629 if(/*!Peek() || */ !Getc(&ch))
641 return result || c > 1;
644 // Strings and numbers separated by spaces, commas, tabs, or CR/LF, handling quotes
645 bool GetString(char * string, int max)
657 if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t'))
663 for(c=0; c<max-1; c++)
665 if(!quoted && ((ch=='\n')||(ch=='\r')||(ch==' ')||(ch==',')||(ch=='\t')))
693 GetString(string,sizeof(string));
697 unsigned int GetHexValue(void)
700 GetString(string, sizeof(string));
701 return strtoul(string, null, 16);
707 GetString(string, sizeof(string));
708 return (float)FloatFromString(string);
711 double GetDouble(void)
714 GetString(string, sizeof(string));
715 return FloatFromString(string);
718 property void * input { set { input = value; } get { return input; } }
719 property void * output { set { output = value; } get { return output; } }
720 property bool buffered
724 FILE_set_buffered(input, output, value);
727 property bool eof { get { return Eof(); } }
729 int GetLineEx(char *s, int max, bool *hasNewLineChar)
739 if(/*!Peek() || */ !Getc(&ch))
747 *hasNewLineChar = (ch == '\n');
753 bool CopyTo(char * outputFileName)
756 File f = FileOpen(outputFileName, write);
765 uint count = Read(buffer, 1, sizeof(buffer));
766 if(count && !f.Write(buffer, 1, count))
779 virtual bool Open(char * fileName, FileOpenMode mode)
784 FILE_FileOpen(fileName, mode, &input, &output);
787 if(!input && !output);
792 // TESTING ENABLING FILE BUFFERING BY DEFAULT... DOCUMENT ANY ISSUE
795 setvbuf(file.input, null, _IONBF, 0);
797 setvbuf(file.output, null, _IONBF, 0);
803 LogErrorCode((mode == Read || mode == ReadWrite) ?
804 ERR_FILE_NOT_FOUND : ERR_FILE_WRITE_FAILED, fileName);
819 public class ConsoleFile : File
830 public class FileAttribs : bool
833 bool isFile:1, isArchive:1, isHidden:1, isReadOnly:1, isSystem:1, isTemporary:1, isDirectory:1;
834 bool isDrive:1, isCDROM:1, isRemote:1, isRemovable:1, isServer:1, isShare:1;
835 // property bool { };
838 public struct FileStats
842 SecSince1970 accessed;
843 SecSince1970 modified;
844 SecSince1970 created;
847 #if defined(__WIN32__)
849 // --- FileName functions ---
851 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime)
853 // TIME_ZONE_INFORMATION tz = { 0 };
857 FileTimeToSystemTime(fileTime, <);
860 GetTimeZoneInformation(&tz);
862 _TzSpecificLocalTimeToSystemTime(&tz, <, &st);
867 t.month = (Month)(st.wMonth - 1);
870 t.minute = st.wMinute;
871 t.second = st.wSecond;
875 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime)
877 // TIME_ZONE_INFORMATION tz = { 0 };
883 st.wYear = (short)tm.year;
884 st.wMonth = (short)tm.month + 1;
885 st.wDay = (short)tm.day;
886 st.wHour = (short)tm.hour;
887 st.wMinute = (short)tm.minute;
888 st.wSecond = (short)tm.second;
889 st.wMilliseconds = 0;
893 GetTimeZoneInformation(&tz);
895 SystemTimeToTzSpecificLocalTime(&tz, &st, <);
899 SystemTimeToFileTime(<, fileTime);
902 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
903 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
905 default bool WinReviveNetworkResource(uint16 * _wfileName);
909 public FileAttribs FileExists(char * fileName)
911 char archiveName[MAX_LOCATION], * archiveFile;
912 #if !defined(ECERE_BOOTSTRAP)
913 if(SplitArchivePath(fileName, archiveName, &archiveFile))
915 return EARFileSystem::Exists(archiveName, archiveFile);
917 else if(strstr(fileName, "http://") == fileName)
919 return FileAttribs { isFile = true };
923 return FILE_FileExists(fileName);
926 static int openCount;
928 public File FileOpen(char * fileName, FileOpenMode mode)
933 char archiveName[MAX_LOCATION], * archiveFile;
934 #if !defined(ECERE_BOOTSTRAP)
935 if(SplitArchivePath(fileName, archiveName, &archiveFile))
937 result = EARFileSystem::Open(archiveName, archiveFile, mode);
939 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
940 else if(strstr(fileName, "http://") == fileName)
942 result = FileOpenURL(fileName);
947 if(strstr(fileName, "File://") == fileName)
949 result = (File)strtoul(fileName+7, null, 16);
952 if(result._class && eClass_IsDerived(result._class, class(File)))
954 if(!result._refCount) incref result;
956 result.Seek(0, start);
967 FILE_FileOpen(fileName, mode, &file.input, &file.output);
970 if(!file.input && !file.output);
975 // TESTING ENABLING FILE BUFFERING BY DEFAULT... DOCUMENT ANY ISSUE
978 setvbuf(file.input, null, _IONBF, 0);
980 setvbuf(file.output, null, _IONBF, 0);
987 LogErrorCode((mode == Read || mode == ReadWrite) ?
988 ERR_FILE_NOT_FOUND : ERR_FILE_WRITE_FAILED, fileName);
997 public void FileFixCase(char * file)
999 FILE_FileFixCase(file);
1002 #if !defined(ECERE_BOOTSTRAP)
1003 public bool FileTruncate(char * fileName, FileSize size)
1005 #if defined(__WIN32__)
1006 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1007 int f = _wopen(_wfileName, _O_RDWR|_O_CREAT, _S_IREAD|_S_IWRITE);
1008 bool result = false;
1011 if(!_chsize(f, size))
1018 return truncate(fileName, size) == 0;
1023 public bool FileGetSize(char * fileName, FileSize * size)
1025 bool result = false;
1031 #if !defined(ECERE_BOOTSTRAP)
1032 char archiveName[MAX_LOCATION], * archiveFile;
1033 if(SplitArchivePath(fileName, archiveName, &archiveFile))
1034 return EARFileSystem::GetSize(archiveName, archiveFile, size);
1037 result = FILE_FileGetSize(fileName, size);
1043 public bool FileGetStats(char * fileName, FileStats stats)
1045 bool result = false;
1046 if(stats && fileName)
1048 #if !defined(ECERE_BOOTSTRAP)
1049 char archiveName[MAX_LOCATION], * archiveFile;
1050 if(SplitArchivePath(fileName, archiveName, &archiveFile))
1051 result = EARFileSystem::Stats(archiveName, archiveFile, stats);
1054 return FILE_FileGetStats(fileName, stats);
1059 #ifndef ECERE_BOOTSTRAP
1061 public bool FileSetAttribs(char * fileName, FileAttribs attribs)
1064 uint winAttribs = 0;
1065 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1067 if(attribs.isHidden) winAttribs |= FILE_ATTRIBUTE_HIDDEN;
1068 if(attribs.isReadOnly) winAttribs |= FILE_ATTRIBUTE_READONLY;
1070 SetFileAttributes(_wfileName, winAttribs);
1076 public bool FileSetTime(char * fileName, TimeStamp created, TimeStamp accessed, TimeStamp modified)
1078 bool result = false;
1079 TimeStamp currentTime = time(null);
1080 if(!created) created = currentTime;
1081 if(!accessed) accessed = currentTime;
1082 if(!modified) modified = currentTime;
1086 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1087 HANDLE hFile = CreateFile(_wfileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, null,
1088 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
1090 if(hFile != INVALID_HANDLE_VALUE)
1094 TimeStampToWin32FileTime(created, &c);
1095 TimeStampToWin32FileTime(accessed, &a);
1096 TimeStampToWin32FileTime(modified, &m);
1102 cc = Win32FileTimeToTimeStamp(&c);
1103 aa = Win32FileTimeToTimeStamp(&a);
1104 mm = Win32FileTimeToTimeStamp(&m);
1108 if(SetFileTime(hFile, &c, &a, &m))
1114 struct utimbuf t = { (int)accessed, (int)modified };
1115 if(!utime(fileName, &t))
1122 /****************************************************************************
1124 ****************************************************************************/
1125 // Directory Description for file listing
1126 private class Dir : struct
1128 #if defined(__WIN32__)
1132 NETRESOURCE * resources;
1136 NETRESOURCE * workGroups;
1141 char name[MAX_LOCATION];
1144 static FileDesc FileFind(char * path, char * extensions)
1146 FileDesc result = null;
1149 if((file = FileDesc {}))
1151 char archiveName[MAX_LOCATION], * archiveFile;
1152 if(SplitArchivePath(path, archiveName, &archiveFile))
1154 if(EARFileSystem::Find(file, archiveName, archiveFile))
1156 file.system = class(EARFileSystem);
1164 if((d = file.dir = Dir {}))
1166 #if defined(__WIN32__)
1167 if(!strcmp(path, "/"))
1170 d.fHandle = (void *)0xFFFFFFFF; //GetLogicalDrives();
1171 for(c = 0; c<26; c++)
1172 if(((uint)d.fHandle) & (1<<c))
1174 char volume[MAX_FILENAME] = "";
1175 uint16 _wvolume[MAX_FILENAME];
1177 uint16 _wfilePath[4];
1179 strcpy(d.name, path);
1180 file.stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1181 _wfilePath[0] = file.path[0] = (char)('A' + c);
1182 _wfilePath[1] = file.path[1] = ':';
1183 _wfilePath[2] = file.path[2] = '\\';
1184 _wfilePath[3] = file.path[3] = '\0';
1185 file.stats.size = 0;
1186 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1187 driveType = GetDriveType(_wfilePath);
1190 case DRIVE_REMOVABLE: file.stats.attribs.isRemovable = true; break;
1191 case DRIVE_REMOTE: file.stats.attribs.isRemote = true; break;
1192 case DRIVE_CDROM: file.stats.attribs.isCDROM = true; break;
1194 *((uint *)&d.fHandle) ^= (1<<c);
1195 if(driveType == DRIVE_NO_ROOT_DIR) continue;
1197 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1198 GetVolumeInformation(_wfilePath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1200 file.path[2] = '\0';
1201 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1202 sprintf(file.name, "%s [%s]", file.path, volume);
1206 file.path[2] = '\0';
1207 strcpy(file.name, file.path);
1214 else if(path[0] != '\\' || path[1] != '\\' || strstr(path+2, "\\"))
1216 WIN32_FIND_DATA winFile;
1217 uint16 dir[MAX_PATH];
1219 UTF8toUTF16Buffer(path, dir, MAX_LOCATION);
1220 if(path[0]) wcscat(dir, L"\\");
1221 wcscat(dir, L"*.*");
1223 d.fHandle = FindFirstFile(dir, &winFile);
1224 if(d.fHandle == INVALID_HANDLE_VALUE && WinReviveNetworkResource(dir))
1225 d.fHandle = FindFirstFile(dir, &winFile);
1226 if(d.fHandle != INVALID_HANDLE_VALUE)
1228 UTF16toUTF8Buffer(winFile.cFileName, file.name, MAX_FILENAME);
1229 strcpy(file.path, path);
1230 PathCat(file.path, file.name);
1232 strcat(file.path, DIR_SEPS);
1233 strcat(file.path, file.name);*/
1234 // file.sizeHigh = winFile.nFileSizeHigh;
1235 file.stats.size = winFile.nFileSizeLow;
1237 file.stats.attribs = FileAttribs { };
1238 file.stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1239 file.stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1240 file.stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1241 file.stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1242 file.stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1243 file.stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1244 file.stats.attribs.isFile = !(winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1245 strcpy(d.name, path);
1247 file.stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1248 file.stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1249 file.stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1256 int count = 0xFFFFFFFF;
1257 uint size = 512 * sizeof(NETRESOURCE);
1258 NETRESOURCE * buffer = (NETRESOURCE *)new0 byte[size];
1259 NETRESOURCE nr = {0};
1262 nr.dwScope = RESOURCE_GLOBALNET;
1263 nr.dwType = RESOURCETYPE_DISK;
1264 nr.lpProvider = L"Microsoft Windows Network";
1266 strcpy(d.name, path);
1269 nr.lpRemoteName = UTF8toUTF16(path, null);
1272 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1275 WinReviveNetworkResource(nr.lpRemoteName);
1276 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1283 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1284 if(returnCode != ERROR_MORE_DATA)
1287 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1289 WNetCloseEnum(handle);
1292 delete nr.lpRemoteName;
1295 file.stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1296 file.stats.size = 0;
1297 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1299 UTF16toUTF8Buffer(buffer->lpRemoteName, file.path, MAX_LOCATION);
1300 GetLastDirectory(file.path, file.name);
1303 d.resources = buffer;
1304 d.numResources = count;
1313 nr.lpProvider = L"Microsoft Windows Network";
1316 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1319 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1320 if(returnCode != ERROR_MORE_DATA)
1323 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1325 WNetCloseEnum(handle);
1327 for(c = 0; c<count; c++)
1329 NETRESOURCE * resources;
1330 int countInGroup = 0xFFFFFFFF;
1332 size = 512 * sizeof(NETRESOURCE);
1333 resources = (NETRESOURCE *)new0 byte[size];
1336 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &buffer[c], &handle);
1339 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1340 if(returnCode != ERROR_MORE_DATA)
1342 countInGroup = 0xFFFFFFFF;
1343 resources = (NETRESOURCE *)renew0 resources byte[size];
1345 WNetCloseEnum(handle);
1349 file.stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1350 file.stats.size = 0;
1351 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1353 UTF16toUTF8Buffer(resources->lpRemoteName, file.path, MAX_LOCATION);
1355 file.path[2] = (char)toupper(file.path[2]);
1356 GetLastDirectory(file.path, file.name);
1360 d.resources = resources;
1361 d.numResources = countInGroup;
1364 d.workGroups = buffer;
1365 d.numWorkGroups = count;
1372 if(c >= count && buffer) delete buffer;
1379 d.d = opendir((path && path[0]) ? path : ".");
1380 if(d.d && (de = readdir(d.d)))
1384 strcpy(file.path, path);
1386 strcat(file.path, DIR_SEPS);
1388 strcpy(file.name,de->d_name);
1389 strcat(file.path, file.name);
1390 if(!stat(file.path, &s))
1392 file.stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true };
1393 file.stats.size = s.st_size;
1394 file.stats.accessed = s.st_atime;
1395 file.stats.modified = s.st_mtime;
1396 file.stats.created = s.st_ctime;
1398 strcpy(d.name, path);
1413 while(result && !result.Validate(extensions))
1414 result = result.FindNext(extensions);
1419 private class FileDesc : struct
1422 char name[MAX_FILENAME];
1423 char path[MAX_LOCATION];
1425 subclass(FileSystem) system;
1428 bool Validate(char * extensions)
1430 if(strcmp(name, "..") && strcmp(name, ".") && strcmp(name, ""))
1432 if(extensions && !stats.attribs.isDirectory)
1434 char extension[MAX_EXTENSION], compared[MAX_EXTENSION];
1437 GetExtension(name, extension);
1438 for(c = 0; extensions[c];)
1442 for(;(ch = extensions[c]) && !IS_ALUNDER(ch); c++);
1443 for(;(ch = extensions[c]) && IS_ALUNDER(ch); c++)
1444 compared[len++] = ch;
1445 compared[len] = '\0';
1447 if(!strcmpi(extension, compared))
1457 FileDesc FindNext(char * extensions)
1459 FileDesc result = null;
1465 while(!Validate(extensions))
1471 if(system.FindNext(this))
1478 #if defined(__WIN32__)
1479 if(!strcmp(d.name, "/"))
1482 for(c = 0; c<26; c++)
1484 if(((uint)d.fHandle) & (1<<c))
1486 char volume[MAX_FILENAME] = "";
1489 uint16 _wvolume[MAX_FILENAME];
1491 stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1493 stats.accessed = stats.created = stats.modified = 0;
1494 _wpath[0] = path[0] = (char)('A' + c);
1495 _wpath[1] = path[1] = ':';
1496 _wpath[2] = path[2] = '\\';
1497 _wpath[3] = path[3] = 0;
1498 driveType = GetDriveType(_wpath);
1499 *((uint *)&d.fHandle) ^= (1<<c);
1503 case DRIVE_REMOVABLE: stats.attribs.isRemovable = true; break;
1504 case DRIVE_REMOTE: stats.attribs.isRemote = true; break;
1505 case DRIVE_CDROM: stats.attribs.isCDROM = true; break;
1507 if(driveType == DRIVE_NO_ROOT_DIR)
1509 uint16 remoteName[1024];
1514 status = WNetGetConnection(_wpath, remoteName, &size);
1515 if(status != ERROR_CONNECTION_UNAVAIL)
1522 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1523 GetVolumeInformation(_wpath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1525 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1527 sprintf(name, "%s [%s]", path, volume);
1540 else if(d.name[0] != '\\' || d.name[1] != '\\' || strstr(d.name+2, "\\"))
1542 WIN32_FIND_DATA winFile;
1543 if(FindNextFile(d.fHandle, &winFile))
1545 UTF16toUTF8Buffer(winFile.cFileName, name, MAX_FILENAME);
1546 stats.attribs = FileAttribs { };
1547 stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1548 stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1549 stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1550 stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1551 stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1552 stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1553 stats.attribs.isFile = !(winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1554 stats.size = winFile.nFileSizeLow;
1556 stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1557 stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1558 stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1560 strcpy(path, d.name);
1561 PathCat(path, name);
1563 strcat(path, DIR_SEPS);
1564 strcat(path, name);*/
1574 if(d.resource < d.numResources)
1576 stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1578 stats.accessed = stats.created = stats.modified = 0;
1580 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1581 GetLastDirectory(path, name);
1596 for(c = d.workGroup; c<d.numWorkGroups; c++)
1598 if(c != d.workGroup)
1600 int countInGroup = 0xFFFFFFFF;
1602 NETRESOURCE * resources;
1603 uint size = 512 * sizeof(NETRESOURCE);
1605 resources = (NETRESOURCE *)new0 byte[size];
1607 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &d.workGroups[c], &handle);
1610 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1611 if(returnCode != ERROR_MORE_DATA)
1613 countInGroup = 0xFFFFFFFF;
1614 resources = (NETRESOURCE *)renew0 resources byte[size];
1617 WNetCloseEnum(handle);
1618 d.numResources = countInGroup;
1619 d.resources = resources;
1623 if(d.resource < d.numResources)
1625 stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1627 stats.accessed = stats.created = stats.modified = 0;
1629 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1631 path[2] = (char)toupper(path[2]);
1632 GetLastDirectory(path, name);
1646 if(d.workGroup == d.numWorkGroups && d.resource == d.numResources)
1648 delete d.workGroups;
1660 strcpy(name,de->d_name);
1661 strcpy(path, d.name);
1662 if(d.name[0] && d.name[1])
1663 strcat(path, DIR_SEPS);
1667 stats.attribs = FileAttribs { };
1668 stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true };
1669 stats.size = s.st_size;
1670 stats.accessed = s.st_atime;
1671 stats.modified = s.st_mtime;
1672 stats.created = s.st_ctime;
1689 system.CloseDir(this);
1695 #if defined(__WIN32__)
1696 if(d.fHandle && strcmp(d.name, "/"))
1697 FindClose(d.fHandle);
1708 public struct FileListing
1716 bool result = false;
1718 desc = desc.FindNext(extensions);
1720 desc = FileFind(directory, extensions);
1733 property char * name { get { return (char *)(desc ? desc.name : null); } };
1734 property char * path { get { return (char *)(desc ? desc.path : null); } };
1735 property FileStats stats { get { value = desc ? desc.stats : FileStats { }; } };
1742 public File CreateTemporaryFile(char * tempFileName, char * template)
1744 #ifndef ECERE_BOOTSTRAP // quick fix for now
1746 #if defined(__unix__) || defined(__APPLE__)
1747 char buffer[MAX_FILENAME];
1749 strcpy(buffer, "/tmp/");
1750 strcat(buffer, template);
1751 //strcpy(buffer, template);
1752 strcat(buffer, "XXXXXX");
1754 fd = mkstemp(buffer);
1755 strcpy(tempFileName, buffer);
1757 f.output = f.input = fdopen(fd, "r+");
1759 char tempPath[MAX_LOCATION];
1760 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1761 GetTempFileNameA(tempPath, template, 0, tempFileName);
1762 f = FileOpen(tempFileName, readWrite);
1770 public void CreateTemporaryDir(char * tempFileName, char * template)
1772 #ifndef ECERE_BOOTSTRAP // quick fix for now
1773 #if defined(__unix__) || defined(__APPLE__)
1774 char buffer[MAX_FILENAME];
1775 strcpy(buffer, "/tmp/");
1776 strcat(buffer, template);
1777 //strcpy(buffer, template);
1778 strcat(buffer, "XXXXXX");
1781 strcpy(tempFileName, buffer);
1783 char tempPath[MAX_LOCATION];
1784 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1785 GetTempFileNameA(tempPath, template, 0, tempFileName);
1786 DeleteFile(tempFileName);
1787 MakeDir(tempFileName);
1792 public void MakeSlashPath(char * p)
1796 ChangeCh(p, '\\', '/');
1800 public void MakeSystemPath(char * p)
1805 public char * CopySystemPath(char * p)
1807 char * d = CopyString(p);
1813 public char * CopyUnixPath(char * p)
1815 char * d = CopyString(p);
1821 public char * GetSystemPathBuffer(char * d, char * p)
1824 strcpy(d, p ? p : "");
1829 public char * GetSlashPathBuffer(char * d, char * p)
1832 strcpy(d, p ? p : "");