13 #define IS_ALUNDER(ch) ((ch) == '_' || isalnum((ch)))
15 #if defined(ECERE_BOOTSTRAP)
22 #ifndef ECERE_BOOTSTRAP
23 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
25 #include <sys/types.h>
30 #if defined(__unix__) || defined(__APPLE__)
34 #if defined(__WIN32__) || defined(__WATCOMC__)
40 #if defined(__WIN32__)
41 #define WIN32_LEAN_AND_MEAN
45 BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
47 // Missing function...
49 #ifndef WNetGetResourceInformation
50 DWORD APIENTRY WNetGetResourceInformationA(LPNETRESOURCE lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPTSTR* lplpSystem);
52 #define WNetGetResourceInformation WNetGetResourceInformationW
54 #define WNetGetResourceInformation WNetGetResourceInformationA
66 #endif //#ifndef ECERE_BOOTSTRAP
74 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET) && !defined(ECERE_BOOTSTRAP)
80 // IMPLEMENTATION OF THESE IS IN _File.c
83 uint FILE_GetSize(FILE * input);
84 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait);
85 void FILE_set_buffered(FILE * input, FILE * output, bool value);
86 FileAttribs FILE_FileExists(char * fileName);
87 bool FILE_FileGetSize(char * fileName, FileSize * size);
88 bool FILE_FileGetStats(char * fileName, FileStats stats);
89 void FILE_FileFixCase(char * file);
90 void FILE_FileOpen(char * fileName, FileOpenMode mode, FILE ** input, FILE **output);
94 FileSystem httpFileSystem;
96 public class FileSize : uint
98 // defaultAlignment = Right;
100 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, int alignment, DataDisplayFlags displayFlags)
104 eUtils_PrintSize(string, *size, 2);
105 len = strlen(string);
106 surface.WriteTextDots(alignment, x, y, width, string, len);
109 int OnCompare(FileSize data2)
116 else if(this < data2)
122 char * OnGetString(char * string, void * fieldData, bool * needClass)
124 PrintSize(string, this, 2);
128 bool OnGetDataFromString(char * string)
131 double value = strtod(string, &end);
133 if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint)1024 * 1024 * 1024;
134 else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint)1024 * 1024;
135 else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024;
137 this = (uint)(multiplier * value);
142 public class FileSize64 : uint64
144 int OnCompare(FileSize64 data2)
151 else if(this < data2)
157 char * OnGetString(char * string, void * fieldData, bool * needClass)
159 PrintBigSize(string, this, 2);
163 bool OnGetDataFromString(char * string)
166 double value = strtod(string, &end);
167 uint64 multiplier = 1;
168 if(strstr(end, "PB") || strstr(end, "pb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024;
169 else if(strstr(end, "TB") || strstr(end, "tb")) multiplier = (uint64)1024 * 1024 * 1024 * 1024;
170 else if(strstr(end, "GB") || strstr(end, "gb")) multiplier = (uint64)1024 * 1024 * 1024;
171 else if(strstr(end, "MB") || strstr(end, "mb")) multiplier = (uint64)1024 * 1024;
172 else if(strstr(end, "KB") || strstr(end, "kb")) multiplier = 1024;
174 this = (uint64)(multiplier * value);
181 virtual File ::Open(char * archive, char * name, FileOpenMode mode);
184 virtual FileAttribs ::Exists(char * archive, char * fileName);
185 virtual bool ::GetSize(char * archive, char * fileName, FileSize * size);
186 virtual bool ::Stats(char * archive, char * fileName, FileStats stats);
187 virtual void ::FixCase(char * archive, char * fileName);
190 virtual bool ::Find(FileDesc file, char * archive, char * name);
191 virtual bool ::FindNext(FileDesc file);
192 virtual void ::CloseDir(FileDesc file);
194 // Archive manipulation
195 virtual Archive ::OpenArchive(char * fileName, ArchiveOpenFlags create);
196 virtual bool ::QuerySize(char * fileName, FileSize * size);
199 public enum FileOpenMode { read = 1, write, append, readWrite, writeRead, appendRead };
200 public enum FileSeekMode { start, current, end };
202 #if !defined(ECERE_BOOTSTRAP)
203 static FileDialog fileDialog { text = $"Select File" };
208 unlocked = 0, // LOCK_UN _SH_DENYNO
209 shared = 1, // LOCK_SH _SH_DENYWR
210 exclusive = 2 // LOCK_EX _SH_DENYRW
213 public class File : IOChannel
215 FILE * input, * output;
217 uint ReadData(byte * bytes, uint numBytes)
219 return Read(bytes, 1, numBytes);
222 uint WriteData(byte * bytes, uint numBytes)
224 return Write(bytes, 1, numBytes);
229 if(output && output != input)
243 bool OnGetDataFromString(char * string)
252 File f = FileOpen(string, read);
259 uint read = f.Read(buffer, 1, sizeof(buffer));
260 Write(buffer, 1, read);
269 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
273 PrintSize(tempString, GetSize(), 2);
279 #ifndef ECERE_BOOTSTRAP
280 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
282 Window editData = class::OnEdit(dataBox, obsolete, x + 24, y, w - 48, h, userData);
285 dataBox, inactive = true, text = $"Imp", hotKey = f2,
286 position = { Max(x + 24, x + w - 24), y }, size = { 24, h };
288 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
290 fileDialog.master = rootWindow;
291 fileDialog.filePath = "";
292 fileDialog.type = open;
294 if(fileDialog.Modal() == ok)
296 char * filePath = fileDialog.filePath;
298 if(output.OnGetDataFromString(filePath))
300 SetData(output, false);
309 dataBox, inactive = true, text = $"Exp", hotKey = f2,
310 position = { Max(x + 24, x + w - 48), y }, size = { 24, h };
312 bool DataBox::NotifyClicked(Button button, int x, int y, Modifiers mods)
314 fileDialog.master = rootWindow;
315 fileDialog.type = save;
316 fileDialog.filePath = "";
317 if(fileDialog.Modal() == ok)
319 char * filePath = fileDialog.filePath;
320 File f = FileOpen(filePath, write);
323 File input = *(void **)data;
324 input.Seek(0, start);
328 uint read = input.Read(buffer, 1, sizeof(buffer));
329 f.Write(buffer, 1, read);
341 #endif //#ifndef ECERE_BOOTSTRAP
343 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOARCHIVE) && !defined(ECERE_BOOTSTRAP)
344 void OnSerialize(IOChannel channel)
346 uint size = this ? GetSize() : MAXDWORD;
349 byte * uncompressed = new byte[size];
351 if(uncompressed || !size)
353 uint count = Read(uncompressed, 1, size);
356 uint cSize = size + size / 1000 + 12;
357 byte * compressed = new byte[cSize];
360 compress2(compressed, &cSize, uncompressed, size, 9);
362 size.OnSerialize(channel);
363 cSize.OnSerialize(channel);
364 channel.WriteData(compressed, cSize);
373 size.OnSerialize(channel);
378 size.OnSerialize(channel);
380 // Will add position...
384 for(c = 0; c<size; c += sizeof(data))
386 uint count = Read(data, 1, sizeof(data));
387 buffer.WriteData(data, count);
393 void OnUnserialize(IOChannel channel)
399 size.OnUnserialize(channel);
403 cSize.OnUnserialize(channel);
405 compressed = new byte[cSize];
408 if(channel.ReadData(compressed, cSize) == cSize)
410 byte * uncompressed = new byte[size];
411 if(uncompressed || !size)
414 uncompress(uncompressed, &size, compressed, cSize);
415 Write(uncompressed, 1, size);
429 size.OnUnserialize(channel);
433 for(c = 0; c<size; c += sizeof(data))
435 uint count = Min(size - c, sizeof(data));
436 channel.ReadData(data, count);
437 Write(data, 1, count);
450 virtual bool Seek(int pos, FileSeekMode mode)
452 uint fmode = SEEK_SET;
455 case start: fmode = SEEK_SET; break;
456 case end: fmode = SEEK_END; break;
457 case current: fmode = SEEK_CUR; break;
459 return fseek(input ? input : output, pos, fmode) != EOF;
462 virtual uint Tell(void)
464 return input ? ftell(input) : ftell(output);
467 virtual int Read(void * buffer, uint size, uint count)
469 return input ? (int)fread(buffer, size, count, input) : 0;
472 virtual int Write(void * buffer, uint size, uint count)
474 return output ? (int)fwrite(buffer, size, count, output) : 0;
478 virtual bool Getc(char * ch)
480 int ich = fgetc(input);
483 if(ch) *ch = (char)ich;
489 virtual bool Putc(char ch)
491 return (fputc((int)ch, output) == EOF) ? false : true;
494 virtual bool Puts(const char * string)
499 result = (fputs(string, output) == EOF) ? false : true;
500 // TODO: Check if any repercusions of commenting out fflush here
501 // This is what broke the debugger in 0.44d2 , it is required for outputting things to the DualPipe
502 // Added an explicit flush call in DualPipe::Puts
508 virtual bool Eof(void)
510 return input ? feof(input) : true;
513 virtual bool Truncate(FileSize size)
515 #ifdef ECERE_BOOTSTRAP
516 fprintf(stderr, "WARNING: File::Truncate unimplemented in ecereBootstrap.\n");
519 #if defined(__WIN32__)
520 return output ? (_chsize(fileno(output), size) == 0) : false;
522 return output ? (ftruncate(fileno(output), size) == 0) : false;
527 virtual uint GetSize(void)
529 return FILE_GetSize(input);
532 virtual void CloseInput(void)
543 virtual void CloseOutput(void)
554 virtual bool Lock(FileLock type, uint64 start, uint64 length, bool wait)
556 return FILE_Lock(input, output, type, start, length, wait);
559 virtual bool Unlock(uint64 start, uint64 length, bool wait)
561 return Lock(unlocked, start, length, wait);
565 int Printf(char * format, ...)
570 char text[MAX_F_STRING];
572 va_start(args, format);
573 vsprintf(text, format, args);
575 result = strlen(text);
581 public void PrintLn(typed_object object, ...)
585 va_start(args, object);
586 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
592 public void Print(typed_object object, ...)
596 va_start(args, object);
597 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
608 bool GetLine(char *s, int max)
624 if(/*!Peek() || */ !Getc(&ch))
636 return result || c > 1;
639 // Strings and numbers separated by spaces, commas, tabs, or CR/LF, handling quotes
640 bool GetString(char * string, int max)
652 if( (ch!='\n') && (ch!='\r') && (ch!=' ') && (ch!=',') && (ch!='\t'))
658 for(c=0; c<max-1; c++)
660 if(!quoted && ((ch=='\n')||(ch=='\r')||(ch==' ')||(ch==',')||(ch=='\t')))
688 GetString(string,sizeof(string));
692 unsigned int GetHexValue(void)
695 GetString(string, sizeof(string));
696 return strtoul(string, null, 16);
702 GetString(string, sizeof(string));
703 return (float)FloatFromString(string);
706 double GetDouble(void)
709 GetString(string, sizeof(string));
710 return FloatFromString(string);
713 property void * input { set { input = value; } get { return input; } }
714 property void * output { set { output = value; } get { return output; } }
715 property bool buffered
719 FILE_set_buffered(input, output, value);
722 property bool eof { get { return Eof(); } }
724 int GetLineEx(char *s, int max, bool *hasNewLineChar)
734 if(/*!Peek() || */ !Getc(&ch))
742 *hasNewLineChar = (ch == '\n');
748 bool CopyTo(char * outputFileName)
751 File f = FileOpen(outputFileName, write);
760 uint count = Read(buffer, 1, sizeof(buffer));
761 if(count && !f.Write(buffer, 1, count))
774 virtual bool Open(char * fileName, FileOpenMode mode)
779 FILE_FileOpen(fileName, mode, &input, &output);
782 if(!input && !output);
787 // TESTING ENABLING FILE BUFFERING BY DEFAULT... DOCUMENT ANY ISSUE
790 setvbuf(file.input, null, _IONBF, 0);
792 setvbuf(file.output, null, _IONBF, 0);
798 LogErrorCode((mode == Read || mode == ReadWrite) ?
799 ERR_FILE_NOT_FOUND : ERR_FILE_WRITE_FAILED, fileName);
814 public class ConsoleFile : File
825 public class FileAttribs : bool
828 bool isFile:1, isArchive:1, isHidden:1, isReadOnly:1, isSystem:1, isTemporary:1, isDirectory:1;
829 bool isDrive:1, isCDROM:1, isRemote:1, isRemovable:1, isServer:1, isShare:1;
830 // property bool { };
833 public struct FileStats
837 SecSince1970 accessed;
838 SecSince1970 modified;
839 SecSince1970 created;
842 #if defined(__WIN32__)
844 // --- FileName functions ---
846 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime)
848 // TIME_ZONE_INFORMATION tz = { 0 };
852 FileTimeToSystemTime(fileTime, <);
855 GetTimeZoneInformation(&tz);
857 _TzSpecificLocalTimeToSystemTime(&tz, <, &st);
862 t.month = (Month)(st.wMonth - 1);
865 t.minute = st.wMinute;
866 t.second = st.wSecond;
870 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime)
872 // TIME_ZONE_INFORMATION tz = { 0 };
878 st.wYear = (short)tm.year;
879 st.wMonth = (short)tm.month + 1;
880 st.wDay = (short)tm.day;
881 st.wHour = (short)tm.hour;
882 st.wMinute = (short)tm.minute;
883 st.wSecond = (short)tm.second;
884 st.wMilliseconds = 0;
888 GetTimeZoneInformation(&tz);
890 SystemTimeToTzSpecificLocalTime(&tz, &st, <);
894 SystemTimeToFileTime(<, fileTime);
897 default TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
898 default void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
900 default bool WinReviveNetworkResource(uint16 * _wfileName);
904 public FileAttribs FileExists(char * fileName)
906 char archiveName[MAX_LOCATION], * archiveFile;
907 #if !defined(ECERE_BOOTSTRAP)
908 if(SplitArchivePath(fileName, archiveName, &archiveFile))
910 return EARFileSystem::Exists(archiveName, archiveFile);
912 else if(strstr(fileName, "http://") == fileName)
914 return FileAttribs { isFile = true };
918 return FILE_FileExists(fileName);
921 static int openCount;
923 public File FileOpen(char * fileName, FileOpenMode mode)
928 char archiveName[MAX_LOCATION], * archiveFile;
929 #if !defined(ECERE_BOOTSTRAP)
930 if(SplitArchivePath(fileName, archiveName, &archiveFile))
932 result = EARFileSystem::Open(archiveName, archiveFile, mode);
934 #if !defined(ECERE_VANILLA) && !defined(ECERE_NONET)
935 else if(strstr(fileName, "http://") == fileName)
937 result = FileOpenURL(fileName);
942 if(strstr(fileName, "File://") == fileName)
944 result = (File)strtoul(fileName+7, null, 16);
947 if(result._class && eClass_IsDerived(result._class, class(File)))
949 if(!result._refCount) incref result;
951 result.Seek(0, start);
962 FILE_FileOpen(fileName, mode, &file.input, &file.output);
965 if(!file.input && !file.output);
970 // TESTING ENABLING FILE BUFFERING BY DEFAULT... DOCUMENT ANY ISSUE
973 setvbuf(file.input, null, _IONBF, 0);
975 setvbuf(file.output, null, _IONBF, 0);
982 LogErrorCode((mode == Read || mode == ReadWrite) ?
983 ERR_FILE_NOT_FOUND : ERR_FILE_WRITE_FAILED, fileName);
992 public void FileFixCase(char * file)
994 FILE_FileFixCase(file);
997 #if !defined(ECERE_BOOTSTRAP)
998 public bool FileTruncate(char * fileName, FileSize size)
1000 #if defined(__WIN32__)
1001 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1002 int f = _wopen(_wfileName, _O_RDWR|_O_CREAT, _S_IREAD|_S_IWRITE);
1003 bool result = false;
1006 if(!_chsize(f, size))
1013 return truncate(fileName, size) == 0;
1018 public bool FileGetSize(char * fileName, FileSize * size)
1020 bool result = false;
1026 #if !defined(ECERE_BOOTSTRAP)
1027 char archiveName[MAX_LOCATION], * archiveFile;
1028 if(SplitArchivePath(fileName, archiveName, &archiveFile))
1029 return EARFileSystem::GetSize(archiveName, archiveFile, size);
1032 result = FILE_FileGetSize(fileName, size);
1038 public bool FileGetStats(char * fileName, FileStats stats)
1040 bool result = false;
1041 if(stats && fileName)
1043 #if !defined(ECERE_BOOTSTRAP)
1044 char archiveName[MAX_LOCATION], * archiveFile;
1045 if(SplitArchivePath(fileName, archiveName, &archiveFile))
1046 result = EARFileSystem::Stats(archiveName, archiveFile, stats);
1049 return FILE_FileGetStats(fileName, stats);
1054 #ifndef ECERE_BOOTSTRAP
1056 public bool FileSetAttribs(char * fileName, FileAttribs attribs)
1059 uint winAttribs = 0;
1060 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1062 if(attribs.isHidden) winAttribs |= FILE_ATTRIBUTE_HIDDEN;
1063 if(attribs.isReadOnly) winAttribs |= FILE_ATTRIBUTE_READONLY;
1065 SetFileAttributes(_wfileName, winAttribs);
1071 public bool FileSetTime(char * fileName, TimeStamp created, TimeStamp accessed, TimeStamp modified)
1073 bool result = false;
1074 TimeStamp currentTime = time(null);
1075 if(!created) created = currentTime;
1076 if(!accessed) accessed = currentTime;
1077 if(!modified) modified = currentTime;
1081 uint16 * _wfileName = UTF8toUTF16(fileName, null);
1082 HANDLE hFile = CreateFile(_wfileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, null,
1083 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
1085 if(hFile != INVALID_HANDLE_VALUE)
1089 TimeStampToWin32FileTime(created, &c);
1090 TimeStampToWin32FileTime(accessed, &a);
1091 TimeStampToWin32FileTime(modified, &m);
1097 cc = Win32FileTimeToTimeStamp(&c);
1098 aa = Win32FileTimeToTimeStamp(&a);
1099 mm = Win32FileTimeToTimeStamp(&m);
1103 if(SetFileTime(hFile, &c, &a, &m))
1109 struct utimbuf t = { (int)accessed, (int)modified };
1110 if(!utime(fileName, &t))
1117 /****************************************************************************
1119 ****************************************************************************/
1120 // Directory Description for file listing
1121 private class Dir : struct
1123 #if defined(__WIN32__)
1127 NETRESOURCE * resources;
1131 NETRESOURCE * workGroups;
1136 char name[MAX_LOCATION];
1139 static FileDesc FileFind(char * path, char * extensions)
1141 FileDesc result = null;
1144 if((file = FileDesc {}))
1146 char archiveName[MAX_LOCATION], * archiveFile;
1147 if(SplitArchivePath(path, archiveName, &archiveFile))
1149 if(EARFileSystem::Find(file, archiveName, archiveFile))
1151 file.system = class(EARFileSystem);
1159 if((d = file.dir = Dir {}))
1161 #if defined(__WIN32__)
1162 if(!strcmp(path, "/"))
1165 d.fHandle = (void *)0xFFFFFFFF; //GetLogicalDrives();
1166 for(c = 0; c<26; c++)
1167 if(((uint)d.fHandle) & (1<<c))
1169 char volume[MAX_FILENAME] = "";
1170 uint16 _wvolume[MAX_FILENAME];
1172 uint16 _wfilePath[4];
1174 strcpy(d.name, path);
1175 file.stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1176 _wfilePath[0] = file.path[0] = (char)('A' + c);
1177 _wfilePath[1] = file.path[1] = ':';
1178 _wfilePath[2] = file.path[2] = '\\';
1179 _wfilePath[3] = file.path[3] = '\0';
1180 file.stats.size = 0;
1181 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1182 driveType = GetDriveType(_wfilePath);
1185 case DRIVE_REMOVABLE: file.stats.attribs.isRemovable = true; break;
1186 case DRIVE_REMOTE: file.stats.attribs.isRemote = true; break;
1187 case DRIVE_CDROM: file.stats.attribs.isCDROM = true; break;
1189 *((uint *)&d.fHandle) ^= (1<<c);
1190 if(driveType == DRIVE_NO_ROOT_DIR) continue;
1192 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1193 GetVolumeInformation(_wfilePath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1195 file.path[2] = '\0';
1196 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1197 sprintf(file.name, "%s [%s]", file.path, volume);
1201 file.path[2] = '\0';
1202 strcpy(file.name, file.path);
1209 else if(path[0] != '\\' || path[1] != '\\' || strstr(path+2, "\\"))
1211 WIN32_FIND_DATA winFile;
1212 uint16 dir[MAX_PATH];
1214 UTF8toUTF16Buffer(path, dir, MAX_LOCATION);
1215 if(path[0]) wcscat(dir, L"\\");
1216 wcscat(dir, L"*.*");
1218 d.fHandle = FindFirstFile(dir, &winFile);
1219 if(d.fHandle == INVALID_HANDLE_VALUE && WinReviveNetworkResource(dir))
1220 d.fHandle = FindFirstFile(dir, &winFile);
1221 if(d.fHandle != INVALID_HANDLE_VALUE)
1223 UTF16toUTF8Buffer(winFile.cFileName, file.name, MAX_FILENAME);
1224 strcpy(file.path, path);
1225 PathCat(file.path, file.name);
1227 strcat(file.path, DIR_SEPS);
1228 strcat(file.path, file.name);*/
1229 // file.sizeHigh = winFile.nFileSizeHigh;
1230 file.stats.size = winFile.nFileSizeLow;
1232 file.stats.attribs = FileAttribs { };
1233 file.stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1234 file.stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1235 file.stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1236 file.stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1237 file.stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1238 file.stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1239 file.stats.attribs.isFile = !(winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1240 strcpy(d.name, path);
1242 file.stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1243 file.stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1244 file.stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1251 int count = 0xFFFFFFFF;
1252 uint size = 512 * sizeof(NETRESOURCE);
1253 NETRESOURCE * buffer = (NETRESOURCE *)new0 byte[size];
1254 NETRESOURCE nr = {0};
1257 nr.dwScope = RESOURCE_GLOBALNET;
1258 nr.dwType = RESOURCETYPE_DISK;
1259 nr.lpProvider = L"Microsoft Windows Network";
1261 strcpy(d.name, path);
1264 nr.lpRemoteName = UTF8toUTF16(path, null);
1267 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1270 WinReviveNetworkResource(nr.lpRemoteName);
1271 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1278 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1279 if(returnCode != ERROR_MORE_DATA)
1282 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1284 WNetCloseEnum(handle);
1287 delete nr.lpRemoteName;
1290 file.stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1291 file.stats.size = 0;
1292 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1294 UTF16toUTF8Buffer(buffer->lpRemoteName, file.path, MAX_LOCATION);
1295 GetLastDirectory(file.path, file.name);
1298 d.resources = buffer;
1299 d.numResources = count;
1308 nr.lpProvider = L"Microsoft Windows Network";
1311 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
1314 int returnCode = WNetEnumResource(handle, &count, buffer, &size);
1315 if(returnCode != ERROR_MORE_DATA)
1318 buffer = (NETRESOURCE *)renew0 buffer byte[size];
1320 WNetCloseEnum(handle);
1322 for(c = 0; c<count; c++)
1324 NETRESOURCE * resources;
1325 int countInGroup = 0xFFFFFFFF;
1327 size = 512 * sizeof(NETRESOURCE);
1328 resources = (NETRESOURCE *)new0 byte[size];
1331 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &buffer[c], &handle);
1334 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1335 if(returnCode != ERROR_MORE_DATA)
1337 countInGroup = 0xFFFFFFFF;
1338 resources = (NETRESOURCE *)renew0 resources byte[size];
1340 WNetCloseEnum(handle);
1344 file.stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1345 file.stats.size = 0;
1346 file.stats.accessed = file.stats.created = file.stats.modified = 0;
1348 UTF16toUTF8Buffer(resources->lpRemoteName, file.path, MAX_LOCATION);
1350 file.path[2] = (char)toupper(file.path[2]);
1351 GetLastDirectory(file.path, file.name);
1355 d.resources = resources;
1356 d.numResources = countInGroup;
1359 d.workGroups = buffer;
1360 d.numWorkGroups = count;
1367 if(c >= count && buffer) delete buffer;
1374 d.d = opendir((path && path[0]) ? path : ".");
1375 if(d.d && (de = readdir(d.d)))
1379 strcpy(file.path, path);
1381 strcat(file.path, DIR_SEPS);
1383 strcpy(file.name,de->d_name);
1384 strcat(file.path, file.name);
1385 stat(file.path, &s);
1386 file.stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true };
1387 file.stats.size = s.st_size;
1388 file.stats.accessed = s.st_atime;
1389 file.stats.modified = s.st_mtime;
1390 file.stats.created = s.st_ctime;
1392 strcpy(d.name, path);
1407 while(result && !result.Validate(extensions))
1408 result = result.FindNext(extensions);
1413 private class FileDesc : struct
1416 char name[MAX_FILENAME];
1417 char path[MAX_LOCATION];
1419 subclass(FileSystem) system;
1422 bool Validate(char * extensions)
1424 if(strcmp(name, "..") && strcmp(name, ".") && strcmp(name, ""))
1426 if(extensions && !stats.attribs.isDirectory)
1428 char extension[MAX_EXTENSION], compared[MAX_EXTENSION];
1431 GetExtension(name, extension);
1432 for(c = 0; extensions[c];)
1436 for(;(ch = extensions[c]) && !IS_ALUNDER(ch); c++);
1437 for(;(ch = extensions[c]) && IS_ALUNDER(ch); c++)
1438 compared[len++] = ch;
1439 compared[len] = '\0';
1441 if(!strcmpi(extension, compared))
1451 FileDesc FindNext(char * extensions)
1453 FileDesc result = null;
1459 while(!Validate(extensions))
1465 if(system.FindNext(this))
1472 #if defined(__WIN32__)
1473 if(!strcmp(d.name, "/"))
1476 for(c = 0; c<26; c++)
1478 if(((uint)d.fHandle) & (1<<c))
1480 char volume[MAX_FILENAME] = "";
1483 uint16 _wvolume[MAX_FILENAME];
1485 stats.attribs = FileAttribs { isDirectory = true, isDrive = true };
1487 stats.accessed = stats.created = stats.modified = 0;
1488 _wpath[0] = path[0] = (char)('A' + c);
1489 _wpath[1] = path[1] = ':';
1490 _wpath[2] = path[2] = '\\';
1491 _wpath[3] = path[3] = 0;
1492 driveType = GetDriveType(_wpath);
1493 *((uint *)&d.fHandle) ^= (1<<c);
1497 case DRIVE_REMOVABLE: stats.attribs.isRemovable = true; break;
1498 case DRIVE_REMOTE: stats.attribs.isRemote = true; break;
1499 case DRIVE_CDROM: stats.attribs.isCDROM = true; break;
1501 if(driveType == DRIVE_NO_ROOT_DIR)
1503 uint16 remoteName[1024];
1508 status = WNetGetConnection(_wpath, remoteName, &size);
1509 if(status != ERROR_CONNECTION_UNAVAIL)
1516 if(driveType != DRIVE_REMOVABLE && driveType != DRIVE_REMOTE &&
1517 GetVolumeInformation(_wpath, _wvolume, MAX_FILENAME - 1, null, null, null, null, 0))
1519 UTF16toUTF8Buffer(_wvolume, volume, MAX_FILENAME);
1521 sprintf(name, "%s [%s]", path, volume);
1534 else if(d.name[0] != '\\' || d.name[1] != '\\' || strstr(d.name+2, "\\"))
1536 WIN32_FIND_DATA winFile;
1537 if(FindNextFile(d.fHandle, &winFile))
1539 UTF16toUTF8Buffer(winFile.cFileName, name, MAX_FILENAME);
1540 stats.attribs = FileAttribs { };
1541 stats.attribs.isArchive = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? true : false;
1542 stats.attribs.isHidden = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false;
1543 stats.attribs.isReadOnly = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? true : false;
1544 stats.attribs.isSystem = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? true : false;
1545 stats.attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
1546 stats.attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
1547 stats.attribs.isFile = !(winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1548 stats.size = winFile.nFileSizeLow;
1550 stats.accessed = Win32FileTimeToTimeStamp(&winFile.ftLastAccessTime);
1551 stats.modified = Win32FileTimeToTimeStamp(&winFile.ftLastWriteTime);
1552 stats.created = Win32FileTimeToTimeStamp(&winFile.ftCreationTime);
1554 strcpy(path, d.name);
1555 PathCat(path, name);
1557 strcat(path, DIR_SEPS);
1558 strcat(path, name);*/
1568 if(d.resource < d.numResources)
1570 stats.attribs = FileAttribs { isDirectory = true, isShare = true };
1572 stats.accessed = stats.created = stats.modified = 0;
1574 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1575 GetLastDirectory(path, name);
1590 for(c = d.workGroup; c<d.numWorkGroups; c++)
1592 if(c != d.workGroup)
1594 int countInGroup = 0xFFFFFFFF;
1596 NETRESOURCE * resources;
1597 uint size = 512 * sizeof(NETRESOURCE);
1599 resources = (NETRESOURCE *)new0 byte[size];
1601 WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &d.workGroups[c], &handle);
1604 int returnCode = WNetEnumResource(handle, &countInGroup, resources, &size);
1605 if(returnCode != ERROR_MORE_DATA)
1607 countInGroup = 0xFFFFFFFF;
1608 resources = (NETRESOURCE *)renew0 resources byte[size];
1611 WNetCloseEnum(handle);
1612 d.numResources = countInGroup;
1613 d.resources = resources;
1617 if(d.resource < d.numResources)
1619 stats.attribs = FileAttribs { isDirectory = true, isServer = true };
1621 stats.accessed = stats.created = stats.modified = 0;
1623 UTF16toUTF8Buffer(d.resources[d.resource].lpRemoteName, path, MAX_LOCATION);
1625 path[2] = (char)toupper(path[2]);
1626 GetLastDirectory(path, name);
1640 if(d.workGroup == d.numWorkGroups && d.resource == d.numResources)
1642 delete d.workGroups;
1654 strcpy(name,de->d_name);
1655 strcpy(path, d.name);
1656 if(d.name[0] && d.name[1])
1657 strcat(path, DIR_SEPS);
1660 stats.attribs = FileAttribs { };
1661 stats.attribs = (s.st_mode&S_IFDIR) ? FileAttribs { isDirectory = true } : FileAttribs { isFile = true };
1662 stats.size = s.st_size;
1663 stats.accessed = s.st_atime;
1664 stats.modified = s.st_mtime;
1665 stats.created = s.st_ctime;
1681 system.CloseDir(this);
1687 #if defined(__WIN32__)
1688 if(d.fHandle && strcmp(d.name, "/"))
1689 FindClose(d.fHandle);
1700 public struct FileListing
1708 bool result = false;
1710 desc = desc.FindNext(extensions);
1712 desc = FileFind(directory, extensions);
1725 property char * name { get { return (char *)(desc ? desc.name : null); } };
1726 property char * path { get { return (char *)(desc ? desc.path : null); } };
1727 property FileStats stats { get { value = desc ? desc.stats : FileStats { }; } };
1734 public File CreateTemporaryFile(char * tempFileName, char * template)
1736 #ifndef ECERE_BOOTSTRAP // quick fix for now
1738 #if defined(__unix__) || defined(__APPLE__)
1739 char buffer[MAX_FILENAME];
1741 strcpy(buffer, "/tmp/");
1742 strcat(buffer, template);
1743 //strcpy(buffer, template);
1744 strcat(buffer, "XXXXXX");
1746 fd = mkstemp(buffer);
1747 strcpy(tempFileName, buffer);
1749 f.output = f.input = fdopen(fd, "r+");
1751 char tempPath[MAX_LOCATION];
1752 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1753 GetTempFileNameA(tempPath, template, 0, tempFileName);
1754 f = FileOpen(tempFileName, readWrite);
1762 public void CreateTemporaryDir(char * tempFileName, char * template)
1764 #ifndef ECERE_BOOTSTRAP // quick fix for now
1765 #if defined(__unix__) || defined(__APPLE__)
1766 char buffer[MAX_FILENAME];
1767 strcpy(buffer, "/tmp/");
1768 strcat(buffer, template);
1769 //strcpy(buffer, template);
1770 strcat(buffer, "XXXXXX");
1773 strcpy(tempFileName, buffer);
1775 char tempPath[MAX_LOCATION];
1776 GetTempPathA(MAX_LOCATION, tempPath); // TODO: Patch this whole thing to support Unicode temp path
1777 GetTempFileNameA(tempPath, template, 0, tempFileName);
1778 DeleteFile(tempFileName);
1779 MakeDir(tempFileName);
1784 public void MakeSlashPath(char * p)
1788 ChangeCh(p, '\\', '/');
1792 public void MakeSystemPath(char * p)
1797 public char * CopySystemPath(char * p)
1799 char * d = CopyString(p);
1805 public char * CopyUnixPath(char * p)
1807 char * d = CopyString(p);
1813 public char * GetSystemPathBuffer(char * d, char * p)
1816 strcpy(d, p ? p : "");
1821 public char * GetSlashPathBuffer(char * d, char * p)
1824 strcpy(d, p ? p : "");