12 #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch)))
14 #if defined(ECERE_BOOTSTRAP)
21 #ifndef ECERE_BOOTSTRAP
22 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
24 #include <sys/types.h>
29 #if defined(__unix__) || defined(__APPLE__)
33 #if defined(__WIN32__) || defined(__WATCOMC__)
39 #if defined(__WIN32__)
40 #define WIN32_LEAN_AND_MEAN
44 BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
46 // Missing function...
48 #ifndef WNetGetResourceInformation
49 DWORD APIENTRY WNetGetResourceInformationA(LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPTSTR* lplpSystem);
51 #define WNetGetResourceInformation WNetGetResourceInformationW
53 #define WNetGetResourceInformation WNetGetResourceInformationA
65 #endif //#ifndef ECERE_BOOTSTRAP
73 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET) && !defined(ECERE_BOOTSTRAP)
79 // IMPLEMENTATION OF THESE IS IN _File.c
82 uint FILE_GetSize(FILE * input);
83 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait);
84 void FILE_set_buffered(FILE * input, FILE * output, bool value);
85 FileAttribs FILE_FileExists(char * fileName);
86 bool FILE_FileGetSize(char * fileName, FileSize * size);
87 bool FILE_FileGetStats(char * fileName, FileStats stats);
88 void FILE_FileFixCase(char * file);
89 void FILE_FileOpen(char * fileName, FileOpenMode mode, FILE ** input, FILE **output);
93 FileSystem httpFileSystem;
95 public class FileSize : uint
97 // defaultAlignment = Right;
99 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, int alignment, DataDisplayFlags displayFlags)
103 eUtils_PrintSize(string, *size, 2);
104 len = strlen(string);
105 surface.WriteTextDots(alignment, x, y, width, string, len);
108 int OnCompare(FileSize data2)
115 else if(this < data2)
121 char * OnGetString(char * string, void * fieldData, bool * needClass)
123 PrintSize(string, this, 2);
127 bool OnGetDataFromString(char * string)
130 double value = strtod(string, &end);
132 if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint)1024 * 1024 * 1024;
133 else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint)1024 * 1024;
134 else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024;
136 this = (uint)(multiplier * value);
143 virtual File ::Open(char * archive, char * name, FileOpenMode mode);
146 virtual FileAttribs ::Exists(char * archive, char * fileName);
147 virtual bool ::GetSize(char * archive, char * fileName, FileSize * size);
148 virtual bool ::Stats(char * archive, char * fileName, FileStats stats);
149 virtual void ::FixCase(char * archive, char * fileName);
152 virtual bool ::Find(FileDesc file, char * archive, char * name);
153 virtual bool ::FindNext(FileDesc file);
154 virtual void ::CloseDir(FileDesc file);
156 // Archive manipulation
157 virtual Archive ::OpenArchive(char * fileName, ArchiveOpenFlags create);
158 virtual bool ::QuerySize(char * fileName, FileSize * size);
161 public enum FileOpenMode { read = 1, write, append, readWrite, writeRead, appendRead };
162 public enum FileSeekMode { start, current, end };
164 #if !defined(ECERE_BOOTSTRAP)
165 static FileDialog fileDialog { text = "Select File" };
170 unlocked = 0, // LOCK_UN _SH_DENYNO
171 shared = 1, // LOCK_SH _SH_DENYWR
172 exclusive = 2 // LOCK_EX _SH_DENYRW
175 public class File : IOChannel
177 FILE * input, * output;
179 uint ReadData(byte * bytes, uint numBytes)
181 return Read(bytes, 1, numBytes);
184 uint WriteData(byte * bytes, uint numBytes)
186 return Write(bytes, 1, numBytes);
191 if(output && output != input)
205 bool OnGetDataFromString(char * string)
214 File f = FileOpen(string, read);
221 uint read = f.Read(buffer, 1, sizeof(buffer));
222 Write(buffer, 1, read);
231 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
235 PrintSize(tempString, GetSize(), 2);
241 #ifndef ECERE_BOOTSTRAP
242 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
244 Window editData = class::OnEdit(dataBox, obsolete, x + 24, y, w - 48, h, userData);
247 dataBox, inactive = true, text = "Imp", hotKey = f2,
248 position = { Max(x + 24, x + w - 24), y }, size = { 24, h };
250 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
252 fileDialog.master = rootWindow;
253 fileDialog.filePath = "";
254 fileDialog.type = open;
256 if(fileDialog.Modal() == ok)
258 char * filePath = fileDialog.filePath;
260 if(output.OnGetDataFromString(filePath))
262 SetData(output, false);
271 dataBox, inactive = true, text = "Exp", hotKey = f2,
272 position = { Max(x + 24, x + w - 48), y }, size = { 24, h };
274 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
276 fileDialog.master = rootWindow;
277 fileDialog.type = save;
278 fileDialog.filePath = "";
279 if(fileDialog.Modal() == ok)
281 char * filePath = fileDialog.filePath;
282 File f = FileOpen(filePath, write);
285 File input = *(void **)data;
286 input.Seek(0, start);
290 uint read = input.Read(buffer, 1, sizeof(buffer));
291 f.Write(buffer, 1, read);
303 #endif //#ifndef ECERE_BOOTSTRAP
305 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOARCHIVE) && !defined(ECERE_BOOTSTRAP)
306 void OnSerialize(IOChannel channel)
308 uint size = this ? GetSize() : MAXDWORD;
311 byte * uncompressed = new byte[size];
313 if(uncompressed || !size)
315 uint count = Read(uncompressed, 1, size);
318 uint cSize = size + size / 1000 + 12;
319 byte * compressed = new byte[cSize];
322 compress2(compressed, &cSize, uncompressed, size, 9);
324 size.OnSerialize(channel);
325 cSize.OnSerialize(channel);
326 channel.WriteData(compressed, cSize);
335 size.OnSerialize(channel);
340 size.OnSerialize(channel);
342 // Will add position...
346 for(c = 0; c<size; c += sizeof(data))
348 uint count = Read(data, 1, sizeof(data));
349 buffer.WriteData(data, count);
355 void OnUnserialize(IOChannel channel)
361 size.OnUnserialize(channel);
365 cSize.OnUnserialize(channel);
367 compressed = new byte[cSize];
370 if(channel.ReadData(compressed, cSize) == cSize)
372 byte * uncompressed = new byte[size];
373 if(uncompressed || !size)
376 uncompress(uncompressed, &size, compressed, cSize);
377 Write(uncompressed, 1, size);
391 size.OnUnserialize(channel);
395 for(c = 0; c<size; c += sizeof(data))
397 uint count = Min(size - c, sizeof(data));
398 channel.ReadData(data, count);
399 Write(data, 1, count);
412 virtual bool Seek(int pos, FileSeekMode mode)
414 uint fmode = SEEK_SET;
417 case start: fmode = SEEK_SET; break;
418 case end: fmode = SEEK_END; break;
419 case current: fmode = SEEK_CUR; break;
421 return fseek(input ? input : output, pos, fmode) != EOF;
424 virtual uint Tell(void)
426 return input ? ftell(input) : ftell(output);
429 virtual int Read(void * buffer, uint size, uint count)
431 return input ? (int)fread(buffer, size, count, input) : 0;
434 virtual int Write(void * buffer, uint size, uint count)
436 return output ? (int)fwrite(buffer, size, count, output) : 0;
440 virtual bool Getc(char * ch)
442 int ich = fgetc(input);
445 if(ch) *ch = (char)ich;
451 virtual bool Putc(char ch)
453 return (fputc((int)ch, output) == EOF) ? false : true;
456 virtual bool Puts(const char * string)
461 result = (fputs(string, output) == EOF) ? false : true;
462 // TODO: Check if any repercusions of commenting out fflush here
463 // This is what broke the debugger in 0.44d2 , it is required for outputting things to the DualPipe
464 // Added an explicit flush call in DualPipe::Puts
470 virtual bool Eof(void)
472 return input ? feof(input) : true;
475 virtual bool Truncate(FileSize size)
477 #ifdef ECERE_BOOTSTRAP
478 fprintf(stderr, "WARNING: File::Truncate unimplemented in ecereBootstrap.\n");
481 #if defined(__WIN32__)
482 return output ? (_chsize(fileno(output), size) == 0) : false;
484 return output ? (ftruncate(fileno(output), size) == 0) : false;
489 virtual uint GetSize(void)
491 return FILE_GetSize(input);
494 virtual void CloseInput(void)
505 virtual void CloseOutput(void)
516 virtual bool Lock(FileLock type, uint64 start, uint64 length, bool wait)
518 return FILE_Lock(input, output, type, start, length, wait);
521 virtual bool Unlock(uint64 start, uint64 length, bool wait)
523 return Lock(unlocked, start, length, wait);
527 int Printf(char * format, ...)
530 char text[MAX_F_STRING];
532 va_start(args, format);
533 vsprintf(text, format, args);
535 result = strlen(text);
540 public void PrintLn(typed_object object, ...)
544 va_start(args, object);
545 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
551 public void Print(typed_object object, ...)
555 va_start(args, object);
556 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
567 bool GetLine(char *s, int max)
583 if(/*!Peek() || */ !Getc(&ch))
595 return result || c > 1;
598 // Strings and numbers separated by spaces, commas, tabs, or CR/LF, handling quotes
599 bool GetString(char * string, int max)
611 if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t'))
617 for(c=0; c<max-1; c++)
619 if(!quoted && ((ch=='\n')||(ch=='\r')||(ch==' ')||(ch==',')||(ch=='\t')))
647 GetString(string,sizeof(string));
651 unsigned int GetHexValue(void)
654 GetString(string, sizeof(string));
655 return strtoul(string, null, 16);
661 GetString(string, sizeof(string));
662 return (float)FloatFromString(string);
665 double GetDouble(void)
668 GetString(string, sizeof(string));
669 return FloatFromString(string);
672 property void * input { set { input = value; } get { return input; } }
673 property void * output { set { output = value; } get { return output; } }
674 property bool buffered
678 FILE_set_buffered(input, output, value);
681 property bool eof { get { return Eof(); } }
683 int GetLineEx(char *s, int max, bool *hasNewLineChar)
693 if(/*!Peek() || */ !Getc(&ch))
701 *hasNewLineChar = (ch == '\n');
707 bool CopyTo(char * outputFileName)
710 File f = FileOpen(outputFileName, write);
719 uint count = Read(buffer, 1, sizeof(buffer));
720 if(count && !f.Write(buffer, 1, count))
731 virtual bool Open(char * fileName, FileOpenMode mode)
736 FILE_FileOpen(fileName, mode, &input, &output);
739 if(!input && !output);
744 // TESTING ENABLING FILE BUFFERING BY DEFAULT... DOCUMENT ANY ISSUE
747 setvbuf(file.input, null, _IONBF, 0);
749 setvbuf(file.output, null, _IONBF, 0);
755 LogErrorCode((mode == Read || mode == ReadWrite) ?
756 ERR_FILE_NOT_FOUND : ERR_FILE_WRITE_FAILED, fileName);
770 public class ConsoleFile : File
781 public class FileAttribs : bool
784 bool isFile:1, isArchive:1, isHidden:1, isReadOnly:1, isSystem:1, isTemporary:1, isDirectory:1;
785 bool isDrive:1, isCDROM:1, isRemote:1, isRemovable:1, isServer:1, isShare:1;
786 // property bool { };
789 public struct FileStats
793 SecSince1970 accessed;
794 SecSince1970 modified;
795 SecSince1970 created;
798 #if defined(__WIN32__)
800 // --- FileName functions ---
802 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime)
804 // TIME_ZONE_INFORMATION tz = { 0 };
808 FileTimeToSystemTime(fileTime, <);
811 GetTimeZoneInformation(&tz);
813 _TzSpecificLocalTimeToSystemTime(&tz, <, &st);
818 t.month = (Month)(st.wMonth - 1);
821 t.minute = st.wMinute;
822 t.second = st.wSecond;
826 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime)
828 // TIME_ZONE_INFORMATION tz = { 0 };
834 st.wYear = (short)tm.year;
835 st.wMonth = (short)tm.month + 1;
836 st.wDay = (short)tm.day;
837 st.wHour = (short)tm.hour;
838 st.wMinute = (short)tm.minute;
839 st.wSecond = (short)tm.second;
840 st.wMilliseconds = 0;
844 GetTimeZoneInformation(&tz);
846 SystemTimeToTzSpecificLocalTime(&tz, &st, <);
850 SystemTimeToFileTime(<, fileTime);
853 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
854 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
856 default bool WinReviveNetworkResource(uint16 * _wfileName);
860 public FileAttribs FileExists(char * fileName)
862 char archiveName[MAX_LOCATION], * archiveFile;
863 #if !defined(ECERE_BOOTSTRAP)
864 if(SplitArchivePath(fileName, archiveName, &archiveFile))
866 return EARFileSystem::Exists(archiveName, archiveFile);
868 else if(strstr(fileName, "http://") == fileName)
870 return FileAttribs { isFile = true };
874 return FILE_FileExists(fileName);
877 static int openCount;
879 public File FileOpen(char * fileName, FileOpenMode mode)
884 char archiveName[MAX_LOCATION], * archiveFile;
885 #if !defined(ECERE_BOOTSTRAP)
886 if(SplitArchivePath(fileName, archiveName, &archiveFile))
888 result = EARFileSystem::Open(archiveName, archiveFile, mode);
890 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
891 else if(strstr(fileName, "http://") == fileName)
893 result = FileOpenURL(fileName);
898 if(strstr(fileName, "File://") == fileName)
900 result = (File)strtoul(fileName+7, null, 16);
903 if(result._class && eClass_IsDerived(result._class, class(File)))
905 if(!result._refCount) incref result;
907 result.Seek(0, start);
918 if(file.Open(fileName, mode))
928 public void FileFixCase(char * file)
930 FILE_FileFixCase(file);
933 #if !defined(ECERE_BOOTSTRAP)
934 public bool FileTruncate(char * fileName, FileSize size)
936 #if defined(__WIN32__)
937 uint16 * _wfileName = UTF8toUTF16(fileName, null);
938 int f = _wopen(_wfileName, _O_RDWR|_O_CREAT, _S_IREAD|_S_IWRITE);
942 if(!_chsize(f, size))
949 return truncate(fileName, size) == 0;
954 public bool FileGetSize(char * fileName, FileSize * size)
962 #if !defined(ECERE_BOOTSTRAP)
963 char archiveName[MAX_LOCATION], * archiveFile;
964 if(SplitArchivePath(fileName, archiveName, &archiveFile))
965 return EARFileSystem::GetSize(archiveName, archiveFile, size);
968 result = FILE_FileGetSize(fileName, size);
974 public bool FileGetStats(char * fileName, FileStats stats)
977 if(stats && fileName)
979 #if !defined(ECERE_BOOTSTRAP)
980 char archiveName[MAX_LOCATION], * archiveFile;
981 if(SplitArchivePath(fileName, archiveName, &archiveFile))
982 result = EARFileSystem::Stats(archiveName, archiveFile, stats);
985 return FILE_FileGetStats(fileName, stats);
990 #ifndef ECERE_BOOTSTRAP
992 public bool FileSetAttribs(char * fileName, FileAttribs attribs)
996 uint16 * _wfileName = UTF8toUTF16(fileName, null);
998 if(attribs.isHidden) winAttribs |= FILE_ATTRIBUTE_HIDDEN;
999 if(attribs.isReadOnly) winAttribs |= FILE_ATTRIBUTE_READONLY;
1001 SetFileAttributes(_wfileName, winAttribs);
1007 public bool FileSetTime(char * fileName, TimeStamp created, TimeStamp accessed, TimeStamp modified)
1009 bool result = false;
1010 TimeStamp currentTime = time(null);
1011 if(!created) created = currentTime;
1012 if(!accessed) accessed = currentTime;
1013 if(!modified) modified = currentTime;
1017 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1018 HANDLE hFile = CreateFile(_wfileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, null,
1019 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
1021 if(hFile != INVALID_HANDLE_VALUE)
1025 TimeStampToWin32FileTime(created, &c);
1026 TimeStampToWin32FileTime(accessed, &a);
1027 TimeStampToWin32FileTime(modified, &m);
1033 cc = Win32FileTimeToTimeStamp(&c);
1034 aa = Win32FileTimeToTimeStamp(&a);
1035 mm = Win32FileTimeToTimeStamp(&m);
1039 if(SetFileTime(hFile, &c, &a, &m))
1045 struct utimbuf t = { (int)accessed, (int)modified };
1046 if(!utime(fileName, &t))
1053 /****************************************************************************
1055 ****************************************************************************/
1056 // Directory Description for file listing
1057 private class Dir : struct
1059 #if defined(__WIN32__)
1063 NETRESOURCE * resources;
1067 NETRESOURCE * workGroups;
1072 char name[MAX_LOCATION];
1075 static FileDesc FileFind(char * path, char * extensions)
1077 FileDesc result = null;
1080 if((file = FileDesc {}))
1082 char archiveName[MAX_LOCATION], * archiveFile;
1083 if(SplitArchivePath(path, archiveName, &archiveFile))
1085 if(EARFileSystem::Find(file, archiveName, archiveFile))
1087 file.system = class(EARFileSystem);
1095 if((d = file.dir = Dir {}))
1097 #if defined(__WIN32__)
1098 if(!strcmp(path, "/"))
1101 d.fHandle = (void *)0xFFFFFFFF; //GetLogicalDrives();
1102 for(c = 0; c<26; c++)
1103 if(((uint)d.fHandle) & (1<<c))
1105 char volume[MAX_FILENAME] = "";
1106 uint16 _wvolume[MAX_FILENAME];
1108 uint16 _wfilePath[4];
1110 strcpy(d.name, path);
1111 file.stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1112 _wfilePath[0] = file.path[0] = (char)('A' + c);
1113 _wfilePath[1] = file.path[1] = ':';
1114 _wfilePath[2] = file.path[2] = '\\';
1115 _wfilePath[3] = file.path[3] = '\0';
1116 file.stats.size = 0;
1117 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1118 driveType = GetDriveType(_wfilePath);
1121 case DRIVE_REMOVABLE: file.stats.attribs.isRemovable = true; break;
1122 case DRIVE_REMOTE: file.stats.attribs.isRemote = true; break;
1123 case DRIVE_CDROM: file.stats.attribs.isCDROM = true; break;
1125 *((uint *)&d.fHandle) ^= (1<<c);
1126 if(driveType == DRIVE_NO_ROOT_DIR) continue;
1128 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1129 GetVolumeInformation(_wfilePath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1131 file.path[2] = '\0';
1132 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1133 sprintf(file.name, "%s [%s]", file.path, volume);
1137 file.path[2] = '\0';
1138 strcpy(file.name, file.path);
1145 else if(path[0] != '\\' || path[1] != '\\' || strstr(path+2, "\\"))
1147 WIN32_FIND_DATA winFile;
1148 uint16 dir[MAX_PATH];
1150 UTF8toUTF16Buffer(path, dir, MAX_LOCATION);
1151 if(path[0]) wcscat(dir, L"\\");
1152 wcscat(dir, L"*.*");
1154 d.fHandle = FindFirstFile(dir, &winFile);
1155 if(d.fHandle == INVALID_HANDLE_VALUE && WinReviveNetworkResource(dir))
1156 d.fHandle = FindFirstFile(dir, &winFile);
1157 if(d.fHandle != INVALID_HANDLE_VALUE)
1159 UTF16toUTF8Buffer(winFile.cFileName, file.name, MAX_FILENAME);
1160 strcpy(file.path, path);
1161 PathCat(file.path, file.name);
1163 strcat(file.path, DIR_SEPS);
1164 strcat(file.path, file.name);*/
1165 // file.sizeHigh = winFile.nFileSizeHigh;
1166 file.stats.size = winFile.nFileSizeLow;
1168 file.stats.attribs = FileAttribs { };
1169 file.stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1170 file.stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1171 file.stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1172 file.stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1173 file.stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1174 file.stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1175 strcpy(d.name, path);
1177 file.stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1178 file.stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1179 file.stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1186 int count = 0xFFFFFFFF;
1187 uint size = 512 * sizeof(NETRESOURCE);
1188 NETRESOURCE * buffer = (NETRESOURCE *)new0 byte[size];
1189 NETRESOURCE nr = {0};
1192 nr.dwScope = RESOURCE_GLOBALNET;
1193 nr.dwType = RESOURCETYPE_DISK;
1194 nr.lpProvider = L"Microsoft Windows Network";
1196 strcpy(d.name, path);
1199 nr.lpRemoteName = UTF8toUTF16(path, null);
1202 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1205 WinReviveNetworkResource(nr.lpRemoteName);
1206 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1213 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1214 if(returnCode != ERROR_MORE_DATA)
1217 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1219 WNetCloseEnum(handle);
1222 delete nr.lpRemoteName;
1225 file.stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1226 file.stats.size = 0;
1227 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1229 UTF16toUTF8Buffer(buffer->lpRemoteName, file.path, MAX_LOCATION);
1230 GetLastDirectory(file.path, file.name);
1233 d.resources = buffer;
1234 d.numResources = count;
1243 nr.lpProvider = L"Microsoft Windows Network";
1246 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1249 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1250 if(returnCode != ERROR_MORE_DATA)
1253 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1255 WNetCloseEnum(handle);
1257 for(c = 0; c<count; c++)
1259 NETRESOURCE * resources;
1260 int countInGroup = 0xFFFFFFFF;
1262 size = 512 * sizeof(NETRESOURCE);
1263 resources = (NETRESOURCE *)new0 byte[size];
1266 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &buffer[c], &handle);
1269 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1270 if(returnCode != ERROR_MORE_DATA)
1272 countInGroup = 0xFFFFFFFF;
1273 resources = (NETRESOURCE *)renew0 resources byte[size];
1275 WNetCloseEnum(handle);
1279 file.stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1280 file.stats.size = 0;
1281 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1283 UTF16toUTF8Buffer(resources->lpRemoteName, file.path, MAX_LOCATION);
1285 file.path[2] = (char)toupper(file.path[2]);
1286 GetLastDirectory(file.path, file.name);
1290 d.resources = resources;
1291 d.numResources = countInGroup;
1294 d.workGroups = buffer;
1295 d.numWorkGroups = count;
1302 if(c >= count && buffer) delete buffer;
1309 d.d = opendir((path && path[0]) ? path : ".");
1310 if(d.d && (de = readdir(d.d)))
1314 strcpy(file.path, path);
1315 strcat(file.path, DIR_SEPS);
1317 strcpy(file.name,de->d_name);
1318 strcat(file.path, file.name);
1319 stat(file.path, &s);
1320 file.stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true };
1321 file.stats.size = s.st_size;
1322 file.stats.accessed = s.st_atime;
1323 file.stats.modified = s.st_mtime;
1324 file.stats.created = s.st_ctime;
1326 strcpy(d.name, path);
1341 while(result && !result.Validate(extensions))
1342 result = result.FindNext(extensions);
1347 private class FileDesc : struct
1350 char name[MAX_FILENAME];
1351 char path[MAX_LOCATION];
1353 subclass(FileSystem) system;
1356 bool Validate(char * extensions)
1358 if(strcmp(name, "..") && strcmp(name, ".") && strcmp(name, ""))
1360 if(extensions && !stats.attribs.isDirectory)
1362 char extension[MAX_EXTENSION], compared[MAX_EXTENSION];
1365 GetExtension(name, extension);
1366 for(c = 0; extensions[c];)
1370 for(;(ch = extensions[c]) && !IS_ALUNDER(ch); c++);
1371 for(;(ch = extensions[c]) && IS_ALUNDER(ch); c++)
1372 compared[len++] = ch;
1373 compared[len] = '\0';
1375 if(!strcmpi(extension, compared))
1385 FileDesc FindNext(char * extensions)
1387 FileDesc result = null;
1393 while(!Validate(extensions))
1399 if(system.FindNext(this))
1406 #if defined(__WIN32__)
1407 if(!strcmp(d.name, "/"))
1410 for(c = 0; c<26; c++)
1412 if(((uint)d.fHandle) & (1<<c))
1414 char volume[MAX_FILENAME] = "";
1417 uint16 _wvolume[MAX_FILENAME];
1419 stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1421 stats.accessed = stats.created = stats.modified = 0;
1422 _wpath[0] = path[0] = (char)('A' + c);
1423 _wpath[1] = path[1] = ':';
1424 _wpath[2] = path[2] = '\\';
1425 _wpath[3] = path[3] = 0;
1426 driveType = GetDriveType(_wpath);
1427 *((uint *)&d.fHandle) ^= (1<<c);
1431 case DRIVE_REMOVABLE: stats.attribs.isRemovable = true; break;
1432 case DRIVE_REMOTE: stats.attribs.isRemote = true; break;
1433 case DRIVE_CDROM: stats.attribs.isCDROM = true; break;
1435 if(driveType == DRIVE_NO_ROOT_DIR)
1437 uint16 remoteName[1024];
1442 status = WNetGetConnection(_wpath, remoteName, &size);
1443 if(status != ERROR_CONNECTION_UNAVAIL)
1450 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1451 GetVolumeInformation(_wpath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1453 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1455 sprintf(name, "%s [%s]", path, volume);
1468 else if(d.name[0] != '\\' || d.name[1] != '\\' || strstr(d.name+2, "\\"))
1470 WIN32_FIND_DATA winFile;
1471 if(FindNextFile(d.fHandle, &winFile))
1473 UTF16toUTF8Buffer(winFile.cFileName, name, MAX_FILENAME);
1474 stats.attribs = FileAttribs { };
1475 stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1476 stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1477 stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1478 stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1479 stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1480 stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1481 stats.size = winFile.nFileSizeLow;
1483 stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1484 stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1485 stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1487 strcpy(path, d.name);
1488 PathCat(path, name);
1490 strcat(path, DIR_SEPS);
1491 strcat(path, name);*/
1501 if(d.resource < d.numResources)
1503 stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1505 stats.accessed = stats.created = stats.modified = 0;
1507 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1508 GetLastDirectory(path, name);
1523 for(c = d.workGroup; c<d.numWorkGroups; c++)
1525 if(c != d.workGroup)
1527 int countInGroup = 0xFFFFFFFF;
1529 NETRESOURCE * resources;
1530 uint size = 512 * sizeof(NETRESOURCE);
1532 resources = (NETRESOURCE *)new0 byte[size];
1534 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &d.workGroups[c], &handle);
1537 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1538 if(returnCode != ERROR_MORE_DATA)
1540 countInGroup = 0xFFFFFFFF;
1541 resources = (NETRESOURCE *)renew0 resources byte[size];
1544 WNetCloseEnum(handle);
1545 d.numResources = countInGroup;
1546 d.resources = resources;
1550 if(d.resource < d.numResources)
1552 stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1554 stats.accessed = stats.created = stats.modified = 0;
1556 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1558 path[2] = (char)toupper(path[2]);
1559 GetLastDirectory(path, name);
1573 if(d.workGroup == d.numWorkGroups && d.resource == d.numResources)
1575 delete d.workGroups;
1587 strcpy(name,de->d_name);
1588 strcpy(path, d.name);
1589 if(d.name[0] && d.name[0])
1590 strcat(path, DIR_SEPS);
1593 stats.attribs = FileAttribs { };
1594 if(s.st_mode & S_IFDIR) stats.attribs.isDirectory = true;
1595 stats.size = s.st_size;
1596 stats.accessed = s.st_atime;
1597 stats.modified = s.st_mtime;
1598 stats.created = s.st_ctime;
1614 system.CloseDir(this);
1620 #if defined(__WIN32__)
1621 if(d.fHandle && strcmp(d.name, "/"))
1622 FindClose(d.fHandle);
1633 public struct FileListing
1641 bool result = false;
1643 desc = desc.FindNext(extensions);
1645 desc = FileFind(directory, extensions);
1658 property char * name { get { return (char *)(desc ? desc.name : null); } };
1659 property char * path { get { return (char *)(desc ? desc.path : null); } };
1660 property FileStats stats { get { value = desc ? desc.stats : FileStats { }; } };
1667 public File CreateTemporaryFile(char * tempFileName, char * template)
1669 #ifndef ECERE_BOOTSTRAP // quick fix for now
1671 #if defined(__unix__) || defined(__APPLE__)
1672 char buffer[MAX_FILENAME];
1674 strcpy(buffer, "/tmp/");
1675 strcat(buffer, template);
1676 //strcpy(buffer, template);
1677 strcat(buffer, "XXXXXX");
1679 fd = mkstemp(buffer);
1680 strcpy(tempFileName, buffer);
1682 f.output = f.input = fdopen(fd, "r+");
1684 char tempPath[MAX_LOCATION];
1685 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1686 GetTempFileNameA(tempPath, template, 0, tempFileName);
1687 f = FileOpen(tempFileName, readWrite);
1695 public void CreateTemporaryDir(char * tempFileName, char * template)
1697 #ifndef ECERE_BOOTSTRAP // quick fix for now
1698 #if defined(__unix__) || defined(__APPLE__)
1699 char buffer[MAX_FILENAME];
1700 strcpy(buffer, "/tmp/");
1701 strcat(buffer, template);
1702 //strcpy(buffer, template);
1703 strcat(buffer, "XXXXXX");
1706 strcpy(tempFileName, buffer);
1708 char tempPath[MAX_LOCATION];
1709 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1710 GetTempFileNameA(tempPath, template, 0, tempFileName);
1711 DeleteFile(tempFileName);
1712 MakeDir(tempFileName);