#include #include #include #include #include #define BAD 0xffffffff DynamicArray fsList; DynamicArray mpList; FileSystem* fsArray; MountPoint* mpArray; void VfsInstall () { DynamicArrayCreate(sizeof(FileSystem), &fsList); DynamicArrayCreate(sizeof(MountPoint), &mpList); fsArray = (FileSystem*) fsList.Data; mpArray = (MountPoint*) mpList.Data; Log("VFS", "%#Vfs now in business.\n", ColorLightGreen); } void VfsInstallFs (FileSystem* fs) { fs->Id = fsList.Size; DynamicArrayPush(fs, &fsList); Log("VFS", "Installed file system %#%s%# (id=%u).\n", ColorWhite, fs->Name, ColorLightGray, fs->Id); } int32 _VfsFindDevice (string name) { int32 i; for (i = 0; (uint32)i < mpList.Size; i++) if (mpArray[i].Id != BAD && strcmp (name, mpArray[i].Name) == 0) return i; return -1; } string _VfsGetDevice (string path, int32* dev) { // Make sure path is valid if (!path || *path != '/') { *dev = -1; return NULL; } // Do we need to return root? path++; if (*path == '\0') return NULL; // Yes, but not implemented yet // Find the next '/' int32 i, index = -1, len = strlen(path); for (i = 0; i < len && index == -1; i++) if (path[i] == '/') index = i; if (index == -1) index = len; // Find the device *dev = -1; for (i = 0; (uint32)i < mpList.Size && *dev == -1; i++) if (mpArray[i].Id != BAD && strncmp(path, mpArray[i].Name, index) == 0) *dev = i; return &path[index]; } int32 _VfsDetectFs (MountPoint* mp) { int32 i; for (i = 0; (uint32)i < fsList.Size; i++) if (fsArray[i].Detect && fsArray[i].Detect(mp)) return i; return -1; } int32 VfsTestDevname (string name) { // Check if name exists uint8 success = (_VfsFindDevice(name) == -1); // Set up for search char find; uint32 len = strlen(name); name[len+1] = '\0'; // Name exists? Try a number for (find = '0'; find <= '9' && !success; find++) { name[len] = find; success = (_VfsFindDevice(name) == -1); } // Whoa... nothing? Try the alphabet. for (find = 'a'; find <= 'z' && !success; find++) { name[len] = find; success = (_VfsFindDevice(name) == -1); } return success; } MountPoint* VfsMount (string devname, DevReadRoutine R, DevWriteRoutine W, uint32 bs) { // Create a mount point MountPoint mp ; strcpy(mp.Name, devname); mp.BlockSize = bs; mp.Read = R; mp.Write = W; // Detect file system int32 fsid = _VfsDetectFs(&mp); if (fsid == -1) { Error("VFS", "%#Failed to mount device %s: could not find a file system.\n", ColorLightRed, devname); return NULL; } mp.FsId = (uint32) fsid; // Rename if it has problems if (!VfsTestDevname(mp.Name)) { Error("VFS", "%#Failed to mount device %s: bad name.\n", ColorLightRed, devname); return NULL; } // Find an empty slot uint32 empty = BAD, i; for (i = 0; i < mpList.Size && empty == BAD; i++) if (mpArray[i].Id == BAD) empty = i; // Mount it if (empty == BAD) { mp.Id = mpList.Size; DynamicArrayPush(&mp, &mpList); } else { mp.Id = empty; memcpy ( &mpArray[empty], &mp, sizeof(MountPoint)); } // Tell the FS to mount the device if (fsArray[fsid].MountDevice) fsArray[fsid].MountDevice(&mpArray[mp.Id]); // Log Log("VFS", "Mounted device %#%s%# using the %#%s%# file system.\n", ColorWhite, mp.Name, ColorLightGray, ColorWhite, fsArray[fsid].Name, ColorLightGray); return &mpArray[mp.Id]; } void VfsUnmount (uint32 devid) { if (fsArray[mpArray[devid].FsId].UnmountDevice) fsArray[mpArray[devid].FsId].UnmountDevice(&mpArray[devid],0); // Invalidate ID mpArray[devid].Id = BAD; // We shouldn't remove it from the array, because it will invalidate // all other devices' IDs. } // Returns pointer to FILE structure that was inputed if success, null otherwise FILE* VfsOpen (FILE* file, string path) { if (!file) return NULL; // Parse string int32 dev; string temp; temp = _VfsGetDevice(path, &dev); file->DeviceId = dev; // Device not found, or Open routine doesn't exist if (dev == -1 || !fsArray[mpArray[dev].FsId].Open) return NULL; // Ask the FS to do the 'opening' return fsArray[mpArray[dev].FsId].Open(&mpArray[dev],file,temp); } DirectoryEntry* VfsTest (string path) { // Parse string int32 dev; path = _VfsGetDevice(path, &dev); // Device not found, or Open routine doesn't exist if (dev == -1 || !fsArray[mpArray[dev].FsId].Test) return NULL; // Ask the FS to do the 'opening' return fsArray[mpArray[dev].FsId].Test(&mpArray[dev],path); } FILE* VfsClose (FILE* file) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Close) return NULL; return fsArray[mp->FsId].Close(mp,file); } uint32 VfsRead (FILE* file, uint32 bsz, uint32 n, uint8* buffer) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Read) return NULL; return fsArray[mp->FsId].Read(mp, file, bsz, n, buffer); } uint32 VfsWrite (FILE* file, uint32 bsz, uint32 n, uint8* buffer) { if (!file) return NULL; MountPoint* mp = &(mpArray[file->DeviceId]); if (!fsArray[mp->FsId].Write) return NULL; return fsArray[mp->FsId].Write(mp, file, bsz, n, buffer); } DirectoryEntry* VfsReadDirectory (FILE* handle, uint32 index) { if (!handle) return NULL; MountPoint* mp = &(mpArray[handle->DeviceId]); // Don't try to read files as directories if ((handle->Flags & 0x7) == FileFile) return NULL; // Ask FS to make the read if (!fsArray[mp->FsId].ReadDirectory) return NULL; return fsArray[mp->FsId].ReadDirectory(mp, handle, index); } MountPoint* VfsGetMountPoint (uint32 dev_id) { if (dev_id < mpList.Size) return &mpArray[dev_id]; return NULL; }