.Close = NativeFS_Close\r
};\r
tVFS_Driver gNativeFS_Driver = {\r
- "nativefs", 0,\r
- NativeFS_Mount, NativeFS_Unmount,\r
- NULL,\r
+ .Name = "nativefs",\r
+ .InitDevice = NativeFS_Mount,\r
+ .Unmount = NativeFS_Unmount\r
};\r
\r
// === CODE ===\r
else {
num = Length / BlockSize;
tailings = Length % BlockSize;
+ leading = 0;
}
// Read central blocks
LOG("Reading %i blocks", num);
ret = ReadBlocks(block, num, Buffer, Argument);
if(ret != num ) {
+ LOG("Incomplete read (%i != %i)", ret, num);
LEAVE('X', leading + ret * BlockSize);
return leading + ret * BlockSize;
}
*/
Uint Flags;
+ /**
+ * \brief Detect if a volume is accessible using this driver
+ * \return Boolean success (with higher numbers being higher priority)
+ *
+ * E.g. FAT would return 1 as it's the lowest common denominator while ext2 might return 2,
+ * because it can be embedded in a FAT volume (and is a more fully featured filesystem).
+ */
+ int (*Detect)(int FD);
+
/**
* \brief Callback to mount a device
*/
// === GLOBALS ===
extern tRWLock glVFS_MountList;
extern tVFS_Mount *gVFS_Mounts;
+extern tVFS_Driver *gVFS_Drivers;
// === PROTOTYPES ===
// --- open.c ---
// === GLOBALS ===
tVFS_Driver gDevFS_Info = {
- "devfs", 0, DevFS_InitDevice, DevFS_Unmount, NULL
+ .Name = "devfs",
+ .InitDevice = DevFS_InitDevice,
+ .Unmount = DevFS_Unmount
};
tVFS_NodeType gDevFS_DirType = {
.TypeName = "DevFS-Dir",
// === GLOBALS ===
tVFS_Driver gRootFS_Info = {
- "rootfs", 0, Root_InitDevice, NULL, NULL
+ .Name = "rootfs",
+ .InitDevice = Root_InitDevice
};
tRamFS_File RootFS_Files[MAX_FILES];
tVFS_ACL RootFS_DirACLs[3] = {
/*
* Acess Micro - VFS Server version 1
*/
-#define DEBUG 1
+#define DEBUG 0
#include <acess.h>
#include <vfs.h>
#include <vfs_int.h>
#if 0
int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options);
#endif
+void VFS_int_Unmount(tVFS_Mount *Mount);
void VFS_UpdateMountFile(void);
// === GLOBALS ===
int argLen = strlen(Options);
// Get the filesystem
- fs = VFS_GetFSByName(Filesystem);
- if(!fs) {
- Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem);
- return -1;
+ if( Filesystem && Filesystem[0] )
+ {
+ fs = VFS_GetFSByName(Filesystem);
+ if(!fs) {
+ Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem);
+ return -ENOENT;
+ }
}
-
- // Create mount information
- mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 );
- if(!mnt) {
- return -2;
+ else
+ {
+ int fd = VFS_Open(Device, VFS_OPENFLAG_READ);
+ if( fd == -1 ) {
+ Log_Warning("VFS", "VFS_Mount - Unable to open '%s' for autodetect", Device);
+ return -ENOENT;
+ }
+
+ tVFS_Driver *bestfs = NULL;
+ int bestrank, rank;
+ for( fs = gVFS_Drivers; fs; fs = fs->Next )
+ {
+ if(!fs->Detect) continue ;
+ rank = fs->Detect(fd);
+ if(!rank) continue ;
+ if(!bestfs || rank > bestrank) {
+ bestfs = fs;
+ bestrank = rank;
+ }
+ }
+ VFS_Close(fd);
+ if( bestfs == NULL ) {
+ Log_Warning("VFS", "VFS_Mount - Filesystem autodetection failed");
+ return -1;
+ }
+
+ fs = bestfs;
}
-
+
// Validate the mountpoint target
// - Only if / is mounted
if( gVFS_Mounts )
}
}
+ // Create mount information
+ mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 );
+ if(!mnt) {
+ parent_mnt->OpenHandleCount --;
+ return -2;
+ }
+
// HACK: Forces VFS_ParsePath to fall back on root
if(mountLen == 1 && MountPoint[0] == '/')
mnt->MountPointLen = 0;
}
RWLock_Release( &glVFS_MountList );
- Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem);
+ Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, fs->Name);
VFS_UpdateMountFile();
return 0;
}
+void VFS_int_Unmount(tVFS_Mount *Mount)
+{
+ // Decrease the open handle count for the mountpoint filesystem.
+ if( Mount != gVFS_RootMount )
+ {
+ tVFS_Mount *mpmnt;
+ for( mpmnt = gVFS_Mounts; mpmnt; mpmnt = mpmnt->Next )
+ {
+ if( strncmp(mpmnt->MountPoint, Mount->MountPoint, mpmnt->MountPointLen) != 0 )
+ continue ;
+ if( Mount->MountPoint[ mpmnt->MountPointLen ] != '/' )
+ continue ;
+ break;
+ }
+ if(mpmnt) {
+ mpmnt->OpenHandleCount -= 1;
+ }
+ else {
+ Log_Notice("VFS", "Mountpoint '%s' has no parent", Mount->MountPoint);
+ }
+ }
+
+ if( Mount->Filesystem->Unmount )
+ Mount->Filesystem->Unmount( Mount->RootNode );
+ LOG("%p (%s) unmounted", Mount, Mount->MountPoint);
+ free(Mount);
+}
+
int VFS_Unmount(const char *Mountpoint)
{
tVFS_Mount *mount, *prev = NULL;
LOG("Mountpoint not found");
return ENOENT;
}
-
- Log_Warning("VFS", "TODO: Impliment unmount");
-
- // Decrease the open handle count for the mountpoint filesystem.
- tVFS_Mount *mpmnt;
- tVFS_Node *mpnode = VFS_ParsePath(mount->MountPoint, NULL, &mpmnt);
- if(mpnode)
- {
- mpmnt->OpenHandleCount -= 2; // -1 for _ParsePath here, -1 for in _Mount
- }
- mount->Filesystem->Unmount( mount->RootNode );
- free(mount);
+ VFS_int_Unmount(mount);
+ VFS_UpdateMountFile();
+
return EOK;
}
else
gVFS_Mounts = mount->Next;
- if( mount->Filesystem->Unmount ) {
- mount->Filesystem->Unmount( mount->RootNode );
- }
- else {
- Log_Error("VFS", "%s (%s) does not have an unmount method, not calling it",
- mount->MountPoint, mount->Filesystem->Name);
- }
- free(mount);
+ VFS_int_Unmount(mount);
mount = prev;
nUnmounted ++;
}
RWLock_Release( &glVFS_MountList );
+ VFS_UpdateMountFile();
+
return nUnmounted;
}
// Search Cache
ent = cache->FirstNode;
- prev = (tCachedInode*) &cache->FirstNode; // Special case removal
+ prev = NULL;
for( ; ent; prev = ent, ent = ent->Next )
{
if(ent->Node.Inode < Inode) continue;
// Check if node needs to be freed
if(ent->Node.ReferenceCount == 0)
{
- prev->Next = ent->Next;
+ if( prev )
+ prev->Next = ent->Next;
+ else
+ cache->FirstNode = ent->Next;
if(ent->Node.Inode == cache->MaxCached)
{
- if(ent != cache->FirstNode)
+ if(ent != cache->FirstNode && prev)
cache->MaxCached = prev->Node.Inode;
else
cache->MaxCached = 0;
*TruePath = malloc( gVFS_RootMount->MountPointLen+1 );
strcpy(*TruePath, gVFS_RootMount->MountPoint);
}
+ gVFS_RootMount->OpenHandleCount ++;
if(MountPoint) *MountPoint = gVFS_RootMount;
LEAVE('p', gVFS_RootMount->RootNode);
return gVFS_RootMount->RootNode;
int Ext2_Install(char **Arguments);\r
int Ext2_Cleanup(void);\r
// - Interface Functions\r
+ int Ext2_Detect(int FD);\r
tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options);\r
void Ext2_Unmount(tVFS_Node *Node);\r
void Ext2_CloseFile(tVFS_Node *Node);\r
tExt2_Disk gExt2_disks[6];\r
int giExt2_count = 0;\r
tVFS_Driver gExt2_FSInfo = {\r
- "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
+ .Name = "ext2",\r
+ .Detect = Ext2_Detect,\r
+ .InitDevice = Ext2_InitDevice,\r
+ .Unmount = Ext2_Unmount,\r
+ .GetNodeFromINode = NULL\r
};\r
\r
// === CODE ===\r
return 0;\r
}\r
\r
+/**\r
+ * Detect if a volume is Ext2 formatted\r
+ */\r
+int Ext2_Detect(int FD)\r
+{\r
+ tExt2_SuperBlock sb;\r
+ size_t len;\r
+ \r
+ len = VFS_ReadAt(FD, 1024, 1024, &sb);\r
+\r
+ if( len != 1024 ) {\r
+ Log_Debug("Ext2", "_Detect: Read failed? (0x%x != 1024)", len);\r
+ return 0;\r
+ }\r
+ \r
+ switch(sb.s_magic)\r
+ {\r
+ case 0xEF53:\r
+ return 2;\r
+ default:\r
+ Log_Debug("Ext2", "_Detect: s_magic = 0x%x", sb.s_magic);\r
+ return 0;\r
+ }\r
+}\r
+\r
/**\r
\brief Initializes a device to be read by by the driver\r
\param Device String - Device to read from\r
// === PROTOTYPES ===\r
// --- Driver Core\r
int FAT_Install(char **Arguments);\r
+ int FAT_Detect(int FD);\r
tVFS_Node *FAT_InitDevice(const char *device, const char **options);\r
void FAT_Unmount(tVFS_Node *Node);\r
// --- Helpers\r
MODULE_DEFINE(0, VER2(0,80) /*v0.80*/, VFAT, FAT_Install, NULL, NULL);\r
tFAT_VolInfo gFAT_Disks[8];\r
int giFAT_PartCount = 0;\r
-tVFS_Driver gFAT_FSInfo = {"fat", 0, FAT_InitDevice, FAT_Unmount, FAT_GetNodeFromINode, NULL};\r
+tVFS_Driver gFAT_FSInfo = {\r
+ .Name = "fat",\r
+ .Detect = FAT_Detect,\r
+ .InitDevice = FAT_InitDevice,\r
+ .Unmount = FAT_Unmount,\r
+ .GetNodeFromINode = FAT_GetNodeFromINode\r
+};\r
tVFS_NodeType gFAT_DirType = {\r
.TypeName = "FAT-Dir",\r
.ReadDir = FAT_ReadDir,\r
return MODULE_ERR_OK;\r
}\r
\r
+/**\r
+ * \brief Detect if a file is a FAT device\r
+ */\r
+int FAT_Detect(int FD)\r
+{\r
+ fat_bootsect bs;\r
+ \r
+ if( VFS_ReadAt(FD, 0, 512, &bs) != 512) {\r
+ return 0;\r
+ }\r
+\r
+ if(bs.bps == 0 || bs.spc == 0)\r
+ return 0;\r
+ \r
+ return 1;\r
+}\r
/**\r
* \brief Reads the boot sector of a disk and prepares the structures for it\r
*/\r
// === GLOBALS ===
MODULE_DEFINE(0, 0x0A /*v0.1*/, FS_NTFS, NTFS_Install, NULL);
-tVFS_Driver gNTFS_FSInfo = {"ntfs", 0, NTFS_InitDevice, NTFS_Unmount, NULL};
+tVFS_Driver gNTFS_FSInfo = {
+ .Name = "ntfs",
+ .InitDevice = NTFS_InitDevice,
+ .Unmount = NTFS_Unmount,
+ .GetNodeFromINode = NULL
+};
tVFS_NodeType gNTFS_DirType = {
.TypeName = "NTFS-File",
.ReadDir = NTFS_ReadDir,
* lvm.h
* - LVM Core definitions
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERSION VER2(0,1)
#include "lvm_int.h"
#include <fs_devfs.h>
size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
size_t LVM_SubVol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
size_t LVM_SubVol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
+void LVM_CloseNode(tVFS_Node *Node);
Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument);
Uint LVM_int_DrvUtil_WriteBlock(Uint64 Address, Uint Count, const void *Buffer, void *Argument);
.ReadDir = LVM_Vol_ReadDir,
.FindDir = LVM_Vol_FindDir,
.Read = LVM_Vol_Read,
- .Write = LVM_Vol_Write
+ .Write = LVM_Vol_Write,
+ .Close = LVM_CloseNode
};
tVFS_NodeType gLVM_SubVolNodeType = {
.Read = LVM_SubVol_Read,
- .Write = LVM_SubVol_Write
+ .Write = LVM_SubVol_Write,
+ .Close = LVM_CloseNode
};
tDevFS_Driver gLVM_DevFS = {
NULL, "LVM",
if(sv->Node.ReferenceCount == 0) {
nFree ++;
vol->SubVolumes[i] = NULL;
+ Mutex_Release(&sv->Node.Lock);
}
- Mutex_Release(&sv->Node.Lock);
-
+ else {
+ Mutex_Release(&sv->Node.Lock);
+ continue ;
+ }
+
Mutex_Acquire(&sv->Node.Lock);
LOG("Removed subvolume %s:%s", vol->Name, sv->Name);
free(sv);
{
if( strcmp(vol->Name, Name) == 0 )
{
+ vol->DirNode.ReferenceCount ++;
return &vol->DirNode;
}
}
{
if( strcmp(vol->SubVolumes[i]->Name, Name) == 0 )
{
+ vol->SubVolumes[i]->Node.ReferenceCount ++;
return &vol->SubVolumes[i]->Node;
}
}
);
}
+void LVM_CloseNode(tVFS_Node *Node)
+{
+ Node->ReferenceCount --;
+}
+
Uint LVM_int_DrvUtil_ReadBlock(Uint64 Address, Uint Count, void *Buffer, void *Argument)
{
return LVM_int_ReadVolume( Argument, Address, Count, Buffer );
K_OBJ += vfs/fs/root.o vfs/fs/devfs.o
K_OBJ += drvutil_disk.o drv/proc.o
# Modules
-MODULES := Storage/LVM Filesystems/FAT Filesystems/Ext2
+MODULES := Storage/LVM Filesystems/FAT Filesystems/Ext2 Filesystems/NTFS
# Local kernel soruces (same as above, but located in same directory as Makefile)
L_OBJ = vfs_handles.o threads.o nativefs.o time.o actions.o
# Native Sources (compiled as usual)
int DiskTool_RegisterLVM(const char *Identifier, const char *Path)
{
int fd = DiskTool_int_TranslateOpen(Path, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);
- if(fd == -1)
+ if(fd == -1) {
+ Log_Notice("DiskTool", "Can't open '%s' for LVM %s", Path, Identifier);
return -1;
+ }
VFS_Seek(fd, 0, SEEK_END);
LVM_AddVolume( &gDiskTool_VolumeType, Identifier, (void*)(tVAddr)fd, 512, VFS_Tell(fd)/512);
+ Log_Debug("DiskTool", "Registered '%s' for LVM %s", Path, Identifier);
return 0;
}
// Call mount
VFS_MkDir(mountpoint);
// TODO: Detect filesystem?
- return VFS_Mount(tpath, mountpoint, "fat", "");
+ return VFS_Mount(tpath, mountpoint, "", "");
}
int DiskTool_Copy(const char *Source, const char *Destination)
int DiskTool_LVM_Read(void *Handle, Uint64 Block, size_t BlockCount, void *Dest)
{
- VFS_ReadAt( (int)(tVAddr)Handle, Block*512, BlockCount*512, Dest);
- return 0;
+ return VFS_ReadAt( (int)(tVAddr)Handle, Block*512, BlockCount*512, Dest) / 512;
}
int DiskTool_LVM_Write(void *Handle, Uint64 Block, size_t BlockCount, const void *Dest)
{
- VFS_WriteAt( (int)(tVAddr)Handle, Block*512, BlockCount*512, Dest);
- return 0;
+ return VFS_WriteAt( (int)(tVAddr)Handle, Block*512, BlockCount*512, Dest) / 512;
}
void DiskTool_LVM_Cleanup(void *Handle)
{
#include <stdint.h>
#include <acess_logging.h>
#include <ctype.h>
+#include <inttypes.h>
#define LOGHDR(col,type) fprintf(stderr, "\e["col"m[%-8.8s]"type" ", Ident)
#define LOGTAIL() fprintf(stderr, "\e[0m\n")
// === CODE ===
void Log_KernelPanic(const char *Ident, const char *Message, ...) {
PUTERR("35", "k")
- exit(-1);
+ abort();
}
void Log_Panic(const char *Ident, const char *Message, ...)
PUTERR("34", "p")
case 'x':
fprintf(stderr, "0x%x", va_arg(args,unsigned int));
break;
+ case 'X':
+ fprintf(stderr, "0x%"PRIx64, va_arg(args,uint64_t));
+ break;
default:
va_arg(args,uintptr_t);
fprintf(stderr, "?");
case 'x':
fprintf(stderr, " 0x%x", va_arg(args, unsigned int));
break;
+ case 'X':
+ fprintf(stderr, " 0x%"PRIx64, va_arg(args,uint64_t));
+ break;
case 's':
fprintf(stderr, " \"%s\"", va_arg(args, const char *));
break;
i += 2;
continue ;
}
+
+ fprintf(stderr, "Unknown command '%s'\n", argv[i]);
}
DiskTool_Cleanup();