Various changes, most of them involving the FAT and Ext2 Drivers, adding write support
authorJohn Hodge <[email protected]>
Wed, 17 Mar 2010 06:08:43 +0000 (14:08 +0800)
committerJohn Hodge <[email protected]>
Wed, 17 Mar 2010 06:08:43 +0000 (14:08 +0800)
- FAT Now has rudimentary write support (file size still isn't updated)
- Added InitRD to the tree
- Slight changes to the Module build system
- Set modules to use -O3 and fixed the bugs that showed

39 files changed:
Kernel/Makefile.BuildNum
Kernel/vfs/fs/fat.c [deleted file]
Kernel/vfs/fs/fs_fat.h [deleted file]
Makefile.cfg
Modules/Display/Makefile.tpl
Modules/Filesystems/Ext2/Makefile [new file with mode: 0644]
Modules/Filesystems/Ext2/dir.c [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2.c [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2_common.h [new file with mode: 0644]
Modules/Filesystems/Ext2/ext2fs.h [new file with mode: 0644]
Modules/Filesystems/Ext2/read.c [new file with mode: 0644]
Modules/Filesystems/Ext2/write.c [new file with mode: 0644]
Modules/Filesystems/FAT/Makefile [new file with mode: 0644]
Modules/Filesystems/FAT/fat.c [new file with mode: 0644]
Modules/Filesystems/FAT/fs_fat.h [new file with mode: 0644]
Modules/Filesystems/FS_Ext2/Makefile [deleted file]
Modules/Filesystems/FS_Ext2/dir.c [deleted file]
Modules/Filesystems/FS_Ext2/ext2.c [deleted file]
Modules/Filesystems/FS_Ext2/ext2_common.h [deleted file]
Modules/Filesystems/FS_Ext2/ext2fs.h [deleted file]
Modules/Filesystems/FS_Ext2/read.c [deleted file]
Modules/Filesystems/FS_Ext2/write.c [deleted file]
Modules/Filesystems/FS_NFS/Makefile [deleted file]
Modules/Filesystems/FS_NFS/common.h [deleted file]
Modules/Filesystems/FS_NFS/main.c [deleted file]
Modules/Filesystems/InitRD/GenerateInitRD.php [new file with mode: 0644]
Modules/Filesystems/InitRD/Makefile [new file with mode: 0644]
Modules/Filesystems/InitRD/files.lst [new file with mode: 0644]
Modules/Filesystems/InitRD/initrd.h [new file with mode: 0644]
Modules/Filesystems/InitRD/main.c [new file with mode: 0644]
Modules/Filesystems/Makefile.tpl
Modules/Filesystems/NFS/Makefile [new file with mode: 0644]
Modules/Filesystems/NFS/common.h [new file with mode: 0644]
Modules/Filesystems/NFS/main.c [new file with mode: 0644]
Modules/IPStack/icmp.c
Modules/IPStack/tcp.c
Modules/Makefile.tpl
Modules/Storage/Makefile.tpl
Usermode/Libraries/crt0.o_src/Makefile

index c43737f..db4b72b 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1526
+BUILD_NUM = 1531
diff --git a/Kernel/vfs/fs/fat.c b/Kernel/vfs/fs/fat.c
deleted file mode 100644 (file)
index 32bff8d..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-/*\r
- * Acess 2\r
- * FAT12/16/32 Driver Version (Incl LFN)\r
- */\r
-#define DEBUG  0\r
-#define VERBOSE        1\r
-\r
-#define CACHE_FAT      1       //!< Caches the FAT in memory\r
-#define USE_LFN                1       //!< Enables the use of Long File Names\r
-\r
-#include <acess.h>\r
-#include <modules.h>\r
-#include <vfs.h>\r
-#include "fs_fat.h"\r
-\r
-\r
-// === TYPES ===\r
-#if USE_LFN\r
-typedef struct s_lfncache {\r
-       Uint    Inode, Impl;\r
-        int    id;\r
-       char    Name[256];\r
-       struct s_lfncache       *Next;\r
-}      t_lfncache;\r
-#endif\r
-\r
-// === PROTOTYPES ===\r
- int   FAT_Install(char **Arguments);\r
-tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
-void   FAT_Unmount(tVFS_Node *Node);\r
-Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-char   *FAT_ReadDir(tVFS_Node *dirNode, int dirpos);\r
-tVFS_Node      *FAT_FindDir(tVFS_Node *dirNode, char *file);\r
- int   FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags);\r
- int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
-void   FAT_CloseFile(tVFS_Node *node);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x51 /*v0.80*/, VFAT, FAT_Install, NULL, NULL);\r
-tFAT_VolInfo   gFAT_Disks[8];\r
- int   giFAT_PartCount = 0;\r
-#if USE_LFN\r
-t_lfncache     *fat_lfncache;\r
-#endif\r
-tVFS_Driver    gFAT_FSInfo = {\r
-       "fat", 0, FAT_InitDevice, FAT_Unmount, NULL\r
-       };\r
-\r
-// === CODE ===\r
-/**\r
- * \fn int FAT_Install(char **Arguments)\r
- * \brief \r
- */\r
-int FAT_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-       return MODULE_ERR_OK;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
- * \brief Reads the boot sector of a disk and prepares the structures for it\r
- */\r
-tVFS_Node *FAT_InitDevice(char *Device, char **options)\r
-{\r
-       fat_bootsect *bs;\r
-        int    i;\r
-       Uint32  FATSz, RootDirSectors, TotSec, CountofClusters;\r
-       tVFS_Node       *node = NULL;\r
-       tFAT_VolInfo    *diskInfo = &gFAT_Disks[giFAT_PartCount];\r
-       \r
-       //Temporary Pointer\r
-       bs = &diskInfo->bootsect;\r
-       \r
-       //Open device and read boot sector\r
-       diskInfo->fileHandle = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);\r
-       if(diskInfo->fileHandle == -1) {\r
-               Warning("FAT_InitDisk - Unable to open device '%s'", Device);\r
-               return NULL;\r
-       }\r
-       \r
-       VFS_ReadAt(diskInfo->fileHandle, 0, 512, bs);\r
-       \r
-       if(bs->bps == 0 || bs->spc == 0) {\r
-               Warning("FAT_InitDisk - Error in FAT Boot Sector\n");\r
-               return NULL;\r
-       }\r
-       \r
-       //FAT Type Determining\r
-       // From Microsoft FAT Specifcation\r
-       RootDirSectors = ((bs->files_in_root*32) + (bs->bps - 1)) / bs->bps;\r
-       \r
-       if(bs->fatSz16 != 0)            FATSz = bs->fatSz16;\r
-       else                                    FATSz = bs->spec.fat32.fatSz32;\r
-       \r
-       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
-       else                                            TotSec = bs->totalSect32;\r
-       \r
-       CountofClusters = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
-       \r
-       if(CountofClusters < 4085)\r
-               diskInfo->type = FAT12;\r
-       else if(CountofClusters < 65525)\r
-               diskInfo->type = FAT16;\r
-       else\r
-               diskInfo->type = FAT32;\r
-       \r
-       #if VERBOSE\r
-       {\r
-               char    *sFatType, *sSize;\r
-               Uint    iSize = CountofClusters * bs->spc / 2;\r
-               \r
-               switch(diskInfo->type)\r
-               {\r
-               case FAT12:     sFatType = "FAT12";     break;\r
-               case FAT16:     sFatType = "FAT16";     break;\r
-               case FAT32:     sFatType = "FAT32";     break;\r
-               default:        sFatType = "UNKNOWN";   break;\r
-               }\r
-               if(iSize <= 2*1024) {\r
-                       sSize = "KiB";\r
-               }\r
-               else if(iSize <= 2*1024*1024) {\r
-                       sSize = "MiB";\r
-                       iSize >>= 10;\r
-               }\r
-               else {\r
-                       sSize = "GiB";\r
-                       iSize >>= 20;\r
-               }\r
-               Log("[FAT ] '%s' %s, %i %s", Device, sFatType, iSize, sSize);\r
-       }\r
-       #endif\r
-       \r
-       //Get Name\r
-       if(diskInfo->type == FAT32) {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat32.label[i] == ' ' ? '\0' : bs->spec.fat32.label[i]);\r
-       }\r
-       else {\r
-               for(i=0;i<11;i++)\r
-                       diskInfo->name[i] = (bs->spec.fat16.label[i] == ' ' ? '\0' : bs->spec.fat16.label[i]);\r
-       }\r
-       diskInfo->name[11] = '\0';\r
-       \r
-       //Compute Root directory offset\r
-       if(diskInfo->type == FAT32)\r
-               diskInfo->rootOffset = bs->spec.fat32.rootClust;\r
-       else\r
-               diskInfo->rootOffset = (FATSz * bs->fatCount) / bs->spc;\r
-       \r
-       diskInfo->clusterCount = CountofClusters;\r
-       \r
-       diskInfo->firstDataSect = bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors;\r
-       \r
-       //Allow for Caching the FAT\r
-       #if CACHE_FAT\r
-       {\r
-       Uint32  Ofs;\r
-       diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*CountofClusters);\r
-       if(diskInfo->FATCache == NULL) {\r
-               Warning("FAT_InitDisk - Heap Exhausted\n");\r
-               return NULL;\r
-       }\r
-       Ofs = bs->resvSectCount*512;\r
-       if(diskInfo->type == FAT12) {\r
-               Uint32  val;\r
-                int    j;\r
-               char    buf[1536];\r
-               for(i=0;i<CountofClusters/2;i++) {\r
-                       j = i & 511;    //%512\r
-                       if( j == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
-                               Ofs += 3*512;\r
-                       }\r
-                       val = *((int*)(buf+j*3));\r
-                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
-                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT16) {\r
-               Uint16  buf[256];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 255) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&255];\r
-               }\r
-       }\r
-       if(diskInfo->type == FAT32) {\r
-               Uint32  buf[128];\r
-               for(i=0;i<CountofClusters;i++) {\r
-                       if( (i & 127) == 0 ) {\r
-                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
-                               Ofs += 512;\r
-                       }\r
-                       diskInfo->FATCache[i] = buf[i&127];\r
-               }\r
-       }\r
-       LOG("FAT Fully Cached");\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       \r
-       //Initalise inode cache for FAT\r
-       diskInfo->inodeHandle = Inode_GetHandle();\r
-       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
-       \r
-       // == VFS Interface\r
-       node = &diskInfo->rootNode;\r
-       node->Inode = diskInfo->rootOffset;\r
-       node->Size = bs->files_in_root; // Unknown - To be set on readdir\r
-       node->ImplInt = giFAT_PartCount;\r
-       \r
-       node->ReferenceCount = 1;\r
-       \r
-       node->UID = 0;  node->GID = 0;\r
-       node->NumACLs = 1;\r
-       node->ACLs = &gVFS_ACL_EveryoneRWX;\r
-       node->Flags = VFS_FFLAG_DIRECTORY;\r
-       node->CTime = node->MTime = node->ATime = now();\r
-       \r
-       node->Read = node->Write = NULL;\r
-       node->ReadDir = FAT_ReadDir;\r
-       node->FindDir = FAT_FindDir;\r
-       node->Relink = FAT_Relink;\r
-       node->MkNod = FAT_Mknod;\r
-       //node->Close = FAT_CloseDevice;\r
-       \r
-       giFAT_PartCount ++;\r
-       return node;\r
-}\r
-\r
-/**\r
- * \fn void FAT_Unmount(tVFS_Node *Node)\r
- * \brief Closes a mount and marks it as free\r
- */\r
-void FAT_Unmount(tVFS_Node *Node)\r
-{\r
-       // Close Disk Handle\r
-       VFS_Close( gFAT_Disks[Node->ImplInt].fileHandle );\r
-       // Clear Node Cache\r
-       Inode_ClearCache(gFAT_Disks[Node->ImplInt].inodeHandle);\r
-       // Mark as unused\r
-       gFAT_Disks[Node->ImplInt].fileHandle = -2;\r
-       return;\r
-}\r
-\r
-/**\r
- * \fn static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
- * \brief Fetches a value from the FAT\r
- */\r
-static Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
-{\r
-       Uint32  val = 0;\r
-       #if !CACHE_FAT\r
-       Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
-       #endif\r
-       ENTER("pDisk xCluster", Disk, cluster);\r
-       #if CACHE_FAT\r
-       val = Disk->FATCache[cluster];\r
-       if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
-       if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
-       if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
-       #else\r
-       if(Disk->type == FAT12) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
-               val = (cluster&1 ? val&0xFFF : val>>12);\r
-               if(val == EOC_FAT12)    val = -1;\r
-       } else if(Disk->type == FAT16) {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
-               if(val == EOC_FAT16)    val = -1;\r
-       } else {\r
-               VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
-               if(val == EOC_FAT32)    val = -1;\r
-       }\r
-       #endif /*CACHE_FAT*/\r
-       LEAVE('x', val);\r
-       return val;\r
-}\r
-\r
-/* Reads a cluster's data\r
- */\r
-static void FAT_int_ReadCluster(int Handle, Uint32 Cluster, int Length, void *Buffer)\r
-{\r
-       ENTER("iHandle xCluster iLength pBuffer", Handle, Cluster, Length, Buffer);\r
-       //Log("Cluster = %i (0x%x)", Cluster, Cluster);\r
-       VFS_ReadAt(\r
-               gFAT_Disks[Handle].fileHandle,\r
-               (gFAT_Disks[Handle].firstDataSect + (Cluster-2)*gFAT_Disks[Handle].bootsect.spc )\r
-                       * gFAT_Disks[Handle].bootsect.bps,\r
-               Length,\r
-               Buffer\r
-               );\r
-       LEAVE('-');\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- * \brief Reads data from a specified file\r
- */\r
-Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-        int    preSkip, count;\r
-        int    handle = node->ImplInt;\r
-        int    i, cluster, pos;\r
-        int    bpc;\r
-       void    *tmpBuf;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       \r
-       ENTER("Xoffset Xlength pbuffer", offset, length, buffer);\r
-       \r
-       // Calculate and Allocate Bytes Per Cluster\r
-       bpc = disk->bootsect.spc * disk->bootsect.bps;\r
-       tmpBuf = (void*) malloc(bpc);\r
-       LOG("malloc'd %i bytes", bpc);\r
-       \r
-       // Cluster is stored in Inode Field\r
-       cluster = node->Inode;\r
-       \r
-       // Sanity Check offset\r
-       if(offset > node->Size) {\r
-               //LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
-               LEAVE('i', 0);\r
-               return 0;\r
-       }\r
-       // Clamp Size\r
-       if(offset + length > node->Size) {\r
-               //LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
-               //      offset, length, node->Size, node->Size - offset);\r
-               length = node->Size - offset;\r
-       }\r
-       \r
-       // Single Cluster including offset\r
-       if(length + offset < bpc)\r
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
-               free(tmpBuf);\r
-               LEAVE('i', 1);\r
-               return length;\r
-       }\r
-       \r
-       preSkip = offset / bpc;\r
-       \r
-       //Skip previous clusters\r
-       for(i=preSkip;i--;)     {\r
-               cluster = FAT_int_GetFatValue(disk, cluster);\r
-               if(cluster == -1) {\r
-                       Warning("FAT_Read - Offset is past end of cluster chain mark");\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
-               }\r
-       }\r
-       \r
-       // Get Count of Clusters to read\r
-       count = ((offset%bpc+length) / bpc) + 1;\r
-       \r
-       // Get buffer Position after 1st cluster\r
-       pos = bpc - offset%bpc;\r
-       \r
-       // Read 1st Cluster\r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy(\r
-               buffer,\r
-               (void*)( tmpBuf + (bpc-pos) ),\r
-               (pos < length ? pos : length)\r
-               );\r
-       \r
-       if (count == 1) {\r
-               free(tmpBuf);\r
-               LEAVE('i', 1);\r
-               return length;\r
-       }\r
-       \r
-       cluster = FAT_int_GetFatValue(disk, cluster);\r
-       \r
-       #if DEBUG\r
-       LOG("pos=%i\n", pos);\r
-       LOG("Reading the rest of the clusters\n");\r
-       #endif\r
-       \r
-       \r
-       //Read the rest of the cluster data\r
-       for( i = 1; i < count-1; i++ )\r
-       {\r
-               FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-               memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
-               pos += bpc;\r
-               cluster = FAT_int_GetFatValue(disk, cluster);\r
-               if(cluster == -1) {\r
-                       Warning("FAT_Read - Read past End of Cluster Chain");\r
-                       free(tmpBuf);\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
-               }\r
-       }\r
-       \r
-       FAT_int_ReadCluster(handle, cluster, bpc, tmpBuf);\r
-       memcpy((void*)(buffer+pos), tmpBuf, length-pos);\r
-       \r
-       #if DEBUG\r
-       LOG("Free tmpBuf(0x%x) and Return\n", tmpBuf);\r
-       #endif\r
-       \r
-       free(tmpBuf);\r
-       LEAVE('X', length);\r
-       return length;\r
-}\r
-\r
-/**\r
- * \fn Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
- */\r
-Uint64 FAT_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn static void FAT_int_ProperFilename(char *dest, char *src)\r
- * \brief Converts a FAT directory entry name into a proper filename\r
- */\r
-static void FAT_int_ProperFilename(char *dest, char *src)\r
-{\r
-        int    a, b;\r
-       \r
-       for( a = 0; a < 8; a++) {\r
-               if(src[a] == ' ')       break;\r
-               dest[a] = src[a];\r
-       }\r
-       b = a;\r
-       a = 8;\r
-       if(src[8] != ' ')\r
-               dest[b++] = '.';\r
-       for( ; a < 11; a++, b++)        {\r
-               if(src[a] == ' ')       break;\r
-               dest[b] = src[a];\r
-       }\r
-       dest[b] = '\0';\r
-       #if DEBUG\r
-       //Log("FAT_int_ProperFilename: dest='%s'", dest);\r
-       #endif\r
-}\r
-\r
-/**\r
- * \fn char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Converts either a LFN or a 8.3 Name into a proper name\r
- */\r
-char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       char    *ret;\r
-        int    len;\r
-       #if USE_LFN\r
-       if(LongFileName && LongFileName[0] != '\0')\r
-       {       \r
-               len = strlen(LongFileName);\r
-               ret = malloc(len+1);\r
-               strcpy(ret, LongFileName);\r
-       }\r
-       else\r
-       {\r
-       #endif\r
-               ret = (char*) malloc(13);\r
-               memset(ret, 13, '\0');\r
-               FAT_int_ProperFilename(ret, ft->name);\r
-       #if USE_LFN\r
-       }\r
-       #endif\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
- * \brief Creates a tVFS_Node structure for a given file entry\r
- */\r
-tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
-{\r
-       tVFS_Node       node = {0};\r
-       tVFS_Node       *ret;\r
-       \r
-       ENTER("pParent pFT sLongFileName", parent, ft, LongFileName);\r
-       \r
-       // Set Other Data\r
-       node.Inode = ft->cluster | (ft->clusterHi<<16);\r
-       node.Size = ft->size;\r
-       LOG("ft->size = %i", ft->size);\r
-       node.ImplInt = parent->ImplInt;\r
-       node.UID = 0;   node.GID = 0;\r
-       node.NumACLs = 1;\r
-       node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX\r
-       \r
-       node.Flags = 0;\r
-       if(ft->attrib & ATTR_DIRECTORY) node.Flags |= VFS_FFLAG_DIRECTORY;\r
-       if(ft->attrib & ATTR_READONLY)  node.Flags |= VFS_FFLAG_READONLY;\r
-       \r
-       node.ATime = timestamp(0,0,0,\r
-                       ((ft->adate&0x1F)-1),   //Days\r
-                       ((ft->adate&0x1E0)-1),          //Months\r
-                       1980+((ft->adate&0xFF00)>>8));  //Years\r
-       \r
-       node.CTime = ft->ctimems * 10;  //Miliseconds\r
-       node.CTime += timestamp(\r
-                       (ft->ctime&0x1F)<<1,    //Seconds\r
-                       ((ft->ctime&0x3F0)>>5), //Minutes\r
-                       ((ft->ctime&0xF800)>>11),       //Hours\r
-                       ((ft->cdate&0x1F)-1),           //Days\r
-                       ((ft->cdate&0x1E0)-1),          //Months\r
-                       1980+((ft->cdate&0xFF00)>>8));  //Years\r
-                       \r
-       node.MTime = timestamp(\r
-                       (ft->mtime&0x1F)<<1,    //Seconds\r
-                       ((ft->mtime&0x3F0)>>5), //Minuites\r
-                       ((ft->mtime&0xF800)>>11),       //Hours\r
-                       ((ft->mdate&0x1F)-1),           //Days\r
-                       ((ft->mdate&0x1E0)-1),          //Months\r
-                       1980+((ft->mdate&0xFF00)>>8));  //Years\r
-       \r
-       if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
-               node.ReadDir = FAT_ReadDir;\r
-               node.FindDir = FAT_FindDir;\r
-               node.MkNod = FAT_Mknod;\r
-               node.Size = -1;\r
-       } else {\r
-               node.Read = FAT_Read;\r
-               node.Write = FAT_Write;\r
-       }\r
-       node.Close = FAT_CloseFile;\r
-       node.Relink = FAT_Relink;\r
-       \r
-       ret = Inode_CacheNode(gFAT_Disks[parent->ImplInt].inodeHandle, &node);\r
-       LEAVE('p', ret);\r
-       return ret;\r
-}\r
-\r
-#if USE_LFN\r
-/**\r
- \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
- \brief Return pointer to LFN cache entry\r
- */\r
-char *FAT_int_GetLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       tmp = fat_lfncache;\r
-       while(tmp)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-                       return tmp->Name;\r
-               tmp = tmp->Next;\r
-       }\r
-       tmp = malloc(sizeof(t_lfncache));\r
-       tmp->Inode = node->Inode;\r
-       tmp->Impl = node->ImplInt;\r
-       memset(tmp->Name, 0, 256);\r
-       \r
-       tmp->Next = fat_lfncache;\r
-       fat_lfncache = tmp;\r
-       \r
-       return tmp->Name;\r
-}\r
-\r
-/**\r
- \fn void FAT_int_DelLFN(tVFS_Node *node)\r
- \brief Delete a LFN cache entry\r
-*/\r
-void FAT_int_DelLFN(tVFS_Node *node)\r
-{\r
-       t_lfncache      *tmp;\r
-       \r
-       if(!fat_lfncache)       return;\r
-       \r
-       if(!fat_lfncache->Next)\r
-       {\r
-               tmp = fat_lfncache;\r
-               fat_lfncache = tmp->Next;\r
-               free(tmp);\r
-               return;\r
-       }\r
-       tmp = fat_lfncache;\r
-       while(tmp && tmp->Next)\r
-       {\r
-               if(tmp->Inode == node->Inode && tmp->Impl == node->ImplInt)\r
-               {\r
-                       free(tmp->Next);\r
-                       tmp->Next = tmp->Next->Next;\r
-                       return;\r
-               }\r
-               tmp = tmp->Next;\r
-       }\r
-}\r
-#endif\r
-\r
-/**\r
- \fn char *FAT_ReadDir(tVFS_Node *dirNode, int dirPos)\r
- \param dirNode        Node structure of directory\r
- \param dirPos Directory position\r
-**/\r
-char *FAT_ReadDir(tVFS_Node *dirNode, int dirpos)\r
-{\r
-       fat_filetable   fileinfo[16];   //Sizeof=32, 16 per sector\r
-        int    a=0;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[dirNode->ImplInt&7];\r
-       Uint32  cluster, offset;\r
-        int    preSkip;\r
-       char    *ret;\r
-       #if USE_LFN\r
-       char    *lfn = NULL;\r
-       #endif\r
-       \r
-       ENTER("pDirNode iDirPos", dirNode, dirpos);\r
-       \r
-       // Get Byte Offset and skip\r
-       offset = dirpos * sizeof(fat_filetable);\r
-       preSkip = offset / (512 * disk->bootsect.spc);\r
-       LOG("disk->bootsect.spc = %i", disk->bootsect.spc);\r
-       LOG("dirNode->size = %i", dirNode->Size);\r
-       cluster = dirNode->Inode;       // Cluster ID\r
-       \r
-       // Do Cluster Skip\r
-       // - Pre FAT32 had a reserved area for the root.\r
-       if( disk->type == FAT32 || cluster != disk->rootOffset )\r
-       {\r
-               //Skip previous clusters\r
-               for(a=preSkip;a--;)     {\r
-                       cluster = FAT_int_GetFatValue(disk, cluster);\r
-                       // Check for end of cluster chain\r
-                       if(cluster == -1) {     LEAVE('n');     return NULL;}\r
-               }\r
-       }\r
-       \r
-       // Bounds Checking (Used to spot heap overflows)\r
-       if(cluster > disk->clusterCount + 2)\r
-       {\r
-               Warning("FAT_ReadDir - Cluster ID is over cluster count (0x%x>0x%x)",\r
-                       cluster, disk->clusterCount+2);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       LOG("cluster=0x%x, dirpos=%i", cluster, dirpos);\r
-       \r
-       // Compute Offsets\r
-       // - Pre FAT32 cluster base (in sectors)\r
-       if( cluster == disk->rootOffset && disk->type != FAT32 )\r
-               offset = disk->bootsect.resvSectCount + cluster*disk->bootsect.spc;\r
-       else\r
-       {       // FAT32 cluster base (in sectors)\r
-               offset = disk->firstDataSect;\r
-               offset += (cluster - 2) * disk->bootsect.spc;\r
-       }\r
-       // Sector in cluster\r
-       if(disk->bootsect.spc != 1)\r
-               offset += (dirpos / 16) % disk->bootsect.spc;\r
-       // Offset in sector\r
-       a = dirpos % 16;\r
-\r
-       LOG("offset=%i, a=%i", offset, a);\r
-       \r
-       // Read Sector\r
-       VFS_ReadAt(disk->fileHandle, offset*512, 512, fileinfo);        // Read Dir Data\r
-       \r
-       LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]);\r
-       //Check if this is the last entry\r
-       if( fileinfo[a].name[0] == '\0' ) {\r
-               dirNode->Size = dirpos;\r
-               LOG("End of list");\r
-               LEAVE('n');\r
-               return NULL;    // break\r
-       }\r
-       \r
-       // Check for empty entry\r
-       if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
-               LOG("Empty Entry");\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;        // Skip\r
-       }\r
-       \r
-       #if USE_LFN\r
-       // Get Long File Name Cache\r
-       lfn = FAT_int_GetLFN(dirNode);\r
-       if(fileinfo[a].attrib == ATTR_LFN)\r
-       {\r
-               fat_longfilename        *lfnInfo;\r
-                int    len;\r
-               \r
-               lfnInfo = (fat_longfilename *) &fileinfo[a];\r
-               if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
-               // Get the current length\r
-               len = strlen(lfn);\r
-               \r
-               // Sanity Check (FAT implementations should not allow >255 bytes)\r
-               if(len + 13 > 255)      return VFS_SKIP;\r
-               // Rebase all bytes\r
-               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
-               \r
-               // Append new bytes\r
-               lfn[ 0] = lfnInfo->name1[0];    lfn[ 1] = lfnInfo->name1[1];\r
-               lfn[ 2] = lfnInfo->name1[2];    lfn[ 3] = lfnInfo->name1[3];\r
-               lfn[ 4] = lfnInfo->name1[4];    \r
-               lfn[ 5] = lfnInfo->name2[0];    lfn[ 6] = lfnInfo->name2[1];\r
-               lfn[ 7] = lfnInfo->name2[2];    lfn[ 8] = lfnInfo->name2[3];\r
-               lfn[ 9] = lfnInfo->name2[4];    lfn[10] = lfnInfo->name2[5];\r
-               lfn[11] = lfnInfo->name3[0];    lfn[12] = lfnInfo->name3[1];\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       #endif\r
-       \r
-       //Check if it is a volume entry\r
-       if(fileinfo[a].attrib & 0x08) {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }\r
-       // Ignore . and ..\r
-       if(fileinfo[a].name[0] == '.') {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;\r
-       }       \r
-       \r
-       LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'\n",\r
-               fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
-               fileinfo[a].name[4], fileinfo[a].name[5], fileinfo[a].name[6], fileinfo[a].name[7],\r
-               fileinfo[a].name[8], fileinfo[a].name[9], fileinfo[a].name[10] );\r
-       \r
-       #if USE_LFN\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], lfn);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], lfn);\r
-       lfn[0] = '\0';\r
-       #else\r
-       //node = FAT_int_CreateNode(dirNode, &fileinfo[a], NULL);\r
-       ret = FAT_int_CreateName(dirNode, &fileinfo[a], NULL);\r
-       #endif\r
-       \r
-       LEAVE('s', ret);\r
-       return ret;\r
-}\r
-\r
-/**\r
- * \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
- * \brief Finds an entry in the current directory\r
- */\r
-tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
-{\r
-       fat_filetable   fileinfo[16];\r
-       char    tmpName[11];\r
-       #if USE_LFN\r
-       fat_longfilename        *lfnInfo;\r
-       char    *lfn = NULL;\r
-        int    lfnPos=255, lfnId = -1;\r
-       #endif\r
-        int    i=0;\r
-       tVFS_Node       *tmpNode;\r
-       Uint64  diskOffset;\r
-       tFAT_VolInfo    *disk = &gFAT_Disks[node->ImplInt];\r
-       Uint32  dirCluster;\r
-       Uint32  cluster;\r
-       \r
-       ENTER("pnode sname", node, name);\r
-       \r
-       // Fast Returns\r
-       if(!name || name[0] == '\0') {\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       #if USE_LFN\r
-       lfn = FAT_int_GetLFN(node);\r
-       #endif\r
-       \r
-       dirCluster = node->Inode;\r
-       // Seek to Directory\r
-       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-               diskOffset = (disk->bootsect.resvSectCount+dirCluster*disk->bootsect.spc) << 9;\r
-       else\r
-               diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc) << 9;\r
-       \r
-       for(;;i++)\r
-       {\r
-               // Load sector\r
-               if((i & 0xF) == 0) {\r
-                       //Log("FAT_FindDir: diskOffset = 0x%x", diskOffset);\r
-                       VFS_ReadAt(disk->fileHandle, diskOffset, 512, fileinfo);\r
-                       diskOffset += 512;\r
-               }\r
-               \r
-               //Check if the files are free\r
-               if(fileinfo[i&0xF].name[0] == '\0')     break;          //Free and last\r
-               if(fileinfo[i&0xF].name[0] == '\xE5')   goto loadCluster;       //Free\r
-               \r
-               \r
-               #if USE_LFN\r
-               // Long File Name Entry\r
-               if(fileinfo[i&0xF].attrib == ATTR_LFN)\r
-               {\r
-                       lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
-                       if(lfnInfo->id & 0x40) {\r
-                               memset(lfn, 0, 256);\r
-                               lfnPos = 255;\r
-                       }\r
-                       lfn[lfnPos--] = lfnInfo->name3[1];      lfn[lfnPos--] = lfnInfo->name3[0];\r
-                       lfn[lfnPos--] = lfnInfo->name2[5];      lfn[lfnPos--] = lfnInfo->name2[4];\r
-                       lfn[lfnPos--] = lfnInfo->name2[3];      lfn[lfnPos--] = lfnInfo->name2[2];\r
-                       lfn[lfnPos--] = lfnInfo->name2[1];      lfn[lfnPos--] = lfnInfo->name2[0];\r
-                       lfn[lfnPos--] = lfnInfo->name1[4];      lfn[lfnPos--] = lfnInfo->name1[3];\r
-                       lfn[lfnPos--] = lfnInfo->name1[2];      lfn[lfnPos--] = lfnInfo->name1[1];\r
-                       lfn[lfnPos--] = lfnInfo->name1[0];\r
-                       if((lfnInfo->id&0x3F) == 1)\r
-                       {\r
-                               memcpy(lfn, lfn+lfnPos+1, 256-lfnPos);\r
-                               lfnId = i+1;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       // Remove LFN if it does not apply\r
-                       if(lfnId != i)  lfn[0] = '\0';\r
-               #endif\r
-                       // Get Real Filename\r
-                       FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
-               \r
-                       LOG("tmpName = '%s'", tmpName);\r
-               \r
-                       //Only Long name is case sensitive, 8.3 is not\r
-                       #if USE_LFN\r
-                       if(strucmp(tmpName, name) == 0 || strcmp(lfn, name) == 0) {\r
-                       #else\r
-                       if(strucmp(tmpName, name) == 0) {\r
-                       #endif\r
-                               cluster = fileinfo[i&0xF].cluster | (fileinfo[i&0xF].clusterHi << 16);\r
-                               tmpNode = Inode_GetCache(disk->inodeHandle, cluster);\r
-                               if(tmpNode == NULL)     // Node is not cached\r
-                               {\r
-                                       #if USE_LFN\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], lfn);\r
-                                       #else\r
-                                       tmpNode = FAT_int_CreateNode(node, &fileinfo[i&0xF], NULL);\r
-                                       #endif\r
-                               }\r
-                               #if USE_LFN\r
-                               lfn[0] = '\0';\r
-                               #endif\r
-                               LEAVE('p', tmpNode);\r
-                               return tmpNode;\r
-                       }\r
-               #if USE_LFN\r
-               }\r
-               #endif\r
-               \r
-       loadCluster:\r
-               //Load Next cluster?\r
-               if( ((i+1) >> 4) % disk->bootsect.spc == 0 && ((i+1) & 0xF) == 0)\r
-               {\r
-                       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
-                               continue;\r
-                       dirCluster = FAT_int_GetFatValue(disk, dirCluster);\r
-                       if(dirCluster == -1)    break;\r
-                       diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc)*512;\r
-               }\r
-       }\r
-       \r
-       LEAVE('n');\r
-       return NULL;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
- * \brief Create a new node\r
- */\r
-int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
- * \brief Rename / Delete a file\r
- */\r
-int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
-{\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void FAT_CloseFile(tVFS_Node *Node)\r
- * \brief Close an open file\r
- */\r
-void FAT_CloseFile(tVFS_Node *Node)\r
-{\r
-       if(Node == NULL)        return ;\r
-       \r
-       Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #if USE_LFN\r
-       if(     !Inode_GetCache(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode)\r
-       &&      Node->Flags & VFS_FFLAG_DIRECTORY)\r
-               FAT_int_DelLFN(Node);\r
-       else    // Get Cache references the node, so dereference it\r
-               Inode_UncacheNode(gFAT_Disks[Node->ImplInt].inodeHandle, Node->Inode);\r
-       #endif\r
-       return ;\r
-}\r
-\r
-/**\r
- * \fn void fat_install()\r
- * \brief Add the FAT Filesystem to the VFS\r
- */\r
-void fat_install()\r
-{\r
-       VFS_AddDriver( &gFAT_FSInfo );\r
-}\r
diff --git a/Kernel/vfs/fs/fs_fat.h b/Kernel/vfs/fs/fs_fat.h
deleted file mode 100644 (file)
index a4f7f7b..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*\r
- * Acess2\r
- * FAT12/16/32 Driver\r
- * vfs/fs/fs_fat.h\r
- */\r
-#ifndef _FS_FAT_H_\r
-#define _FS_FAT_H_\r
-\r
-// === On Disk Structures ===\r
-/**\r
- * \struct fat_bootsect_s\r
- * \brief Bootsector format\r
- */\r
-struct fat_bootsect_s\r
-{\r
-       Uint8   jmp[3]; //!< Jump Instruction\r
-       char    oemname[8];     //!< OEM Name. Typically MSDOS1.1\r
-       Uint16  bps;    //!< Bytes per Sector. Assumed to be 512\r
-       Uint8   spc;            //!< Sectors per Cluster\r
-       Uint16  resvSectCount;  //!< Number of reserved sectors at beginning of volume\r
-       Uint8   fatCount;       //!< Number of copies of the FAT\r
-       Uint16  files_in_root;  //!< Count of files in the root directory\r
-       Uint16  totalSect16;    //!< Total sector count (FAT12/16)\r
-       Uint8   mediaDesc;      //!< Media Desctiptor\r
-       Uint16  fatSz16;        //!< FAT Size (FAT12/16)\r
-       Uint16  spt;    //!< Sectors per track. Ignored (Acess uses LBA)\r
-       Uint16  heads;  //!< Heads. Ignored (Acess uses LBA)\r
-       Uint32  hiddenCount;    //!< ???\r
-       Uint32  totalSect32;    //!< Total sector count (FAT32)\r
-       union {\r
-               struct {\r
-                       Uint8   drvNum; //!< Drive Number. BIOS Drive ID (E.g. 0x80)\r
-                       Uint8   resv;   //!< Reserved byte\r
-                       Uint8   bootSig;        //!< Boot Signature. ???\r
-                       Uint32  volId;  //!< Volume ID\r
-                       char    label[11];      //!< Disk Label\r
-                       char    fsType[8];      //!< FS Type. ???\r
-               } __attribute__((packed)) fat16;        //!< FAT16 Specific information\r
-               struct {\r
-                       Uint32  fatSz32;        //!< 32-Bit FAT Size\r
-                       Uint16  extFlags;       //!< Extended flags\r
-                       Uint16  fsVer;  //!< Filesystem Version\r
-                       Uint32  rootClust;      //!< Root Cluster ID\r
-                       Uint16  fsInfo; //!< FS Info. ???\r
-                       Uint16  backupBS;       //!< Backup Bootsector Sector Offset\r
-                       char    resv[12];       //!< Reserved Data\r
-                       Uint8   drvNum; //!< Drive Number\r
-                       char    resv2;  //!< Reserved Data\r
-                       Uint8   bootSig;        //!< Boot Signature. ???\r
-                       Uint32  volId;  //!< Volume ID\r
-                       char    label[11];      //!< Disk Label\r
-                       char    fsType[8];      //!< Filesystem Type. ???\r
-               } __attribute__((packed)) fat32;        //!< FAT32 Specific Information\r
-       }__attribute__((packed)) spec;  //!< Non Shared Data\r
-       char pad[512-90];       //!< Bootsector Data (Code/Boot Signature 0xAA55)\r
-} __attribute__((packed));\r
-\r
-/**\r
- \struct fat_filetable_s\r
- \brief Format of a 8.3 file entry on disk\r
-*/\r
-struct fat_filetable_s {\r
-       char    name[11];       //!< 8.3 Name\r
-       Uint8   attrib; //!< File Attributes.\r
-       Uint8   ntres;  //!< Reserved for NT - Set to 0\r
-       Uint8   ctimems;        //!< 10ths of a second ranging from 0-199 (2 seconds)\r
-       Uint16  ctime;  //!< Creation Time\r
-       Uint16  cdate;  //!< Creation Date\r
-       Uint16  adate;  //!< Accessed Data. No Time feild though\r
-       Uint16  clusterHi;      //!< High Cluster. 0 for FAT12 and FAT16\r
-       Uint16  mtime;  //!< Last Modified Time\r
-       Uint16  mdate;  //!< Last Modified Date\r
-       Uint16  cluster;        //!< Low Word of First cluster\r
-       Uint32  size;   //!< Size of file\r
-} __attribute__((packed));\r
-\r
-/**\r
- \struct fat_longfilename_s\r
- \brief Format of a long file name entry on disk\r
-*/\r
-struct fat_longfilename_s {\r
-       Uint8   id;     //!< ID of entry. Bit 6 is set for last entry\r
-       Uint16  name1[5];       //!< 5 characters of name\r
-       Uint8   attrib; //!< Attributes. Must be ATTR_LFN\r
-       Uint8   type;   //!< Type. ???\r
-       Uint8   checksum;       //!< Checksum\r
-       Uint16  name2[6];       //!< 6 characters of name\r
-       Uint16  firstCluster;   //!< Used for non LFN compatability. Set to 0\r
-       Uint16  name3[2];       //!< Last 2 characters of name\r
-} __attribute__((packed));\r
-\r
-/**\r
- * \name File Attributes\r
- * \brief Flag values for ::fat_filetable_s.attrib\r
- * \{\r
- */\r
-#define ATTR_READONLY  0x01    //!< Read-only file\r
-#define ATTR_HIDDEN            0x02    //!< Hidden File\r
-#define ATTR_SYSTEM            0x04    //!< System File\r
-#define ATTR_VOLUMEID  0x08    //!< Volume ID (Deprecated)\r
-#define ATTR_DIRECTORY 0x10    //!< Directory\r
-/**\r
- * \brief File needs archiving\r
- * \note User set flag, no significance to the FS driver\r
- */\r
-#define ATTR_ARCHIVE   0x20\r
-/**\r
- * \brief Meta Attribute \r
- * \r
- * If ::fat_filetable_s.attrib equals ATTR_LFN the file is a LFN entry\r
- */\r
-#define        ATTR_LFN                (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMEID)\r
-/**\r
- * \}\r
- */\r
-\r
-/**\r
- * \brief Internal IDs for FAT types\r
- */\r
-enum eFatType\r
-{\r
-       FAT12,  //!< FAT12 Volume\r
-       FAT16,  //!< FAT16 Volume\r
-       FAT32,  //!< FAT32 Volume\r
-};\r
-\r
-/**\r
- * \name End of Cluster marks\r
- * \brief FAT values that indicate the end of a cluster chain in\r
- *        different versions.\r
- * \{\r
- */\r
-#define        EOC_FAT12       0x0FFF  //!< FAT-12 Mark\r
-#define        EOC_FAT16       0xFFFF  //!< FAT-16 Mark\r
-#define        EOC_FAT32       0x0FFFFFF       //!< FAT-32 Mark\r
-/**\r
- * \}\r
- */\r
-\r
-typedef struct fat_bootsect_s fat_bootsect;\r
-typedef struct fat_filetable_s fat_filetable;\r
-typedef struct fat_longfilename_s fat_longfilename;\r
-\r
-// === Memory Structures ===\r
-/**\r
- * \struct drv_fat_volinfo_s\r
- * \brief Representation of a volume in memory\r
- */\r
-struct drv_fat_volinfo_s\r
-{\r
-        int    fileHandle;     //!< File Handle\r
-        int    type;   //!< FAT Type. See eFatType\r
-       char    name[12];       //!< Volume Name (With NULL Terminator)\r
-       Uint32  firstDataSect;  //!< First data sector\r
-       Uint32  rootOffset;     //!< Root Offset (clusters)\r
-       Uint32  clusterCount;   //!< Total Cluster Count\r
-       fat_bootsect    bootsect;       //!< Boot Sector\r
-       tVFS_Node       rootNode;       //!< Root Node\r
-        int            inodeHandle;    //!< Inode Cache Handle\r
-       #if CACHE_FAT\r
-       Uint32  *FATCache;      //!< FAT Cache\r
-       #endif\r
-};\r
-\r
-typedef struct drv_fat_volinfo_s tFAT_VolInfo;\r
-\r
-#endif\r
index 348206f..a12ea15 100644 (file)
@@ -23,12 +23,13 @@ ifeq ($(ARCHDIR),)
        ARCHDIR = x86
 endif
 
-FILESYSTEMS = fat
+FILESYSTEMS = 
 DRIVERS = 
 MODULES  = Storage/ATA Storage/FDD
 MODULES += Network/NE2000
 MODULES += Display/BochsGA
-MODULES += Filesystems/FS_Ext2
+MODULES += Filesystems/Ext2
+MODULES += Filesystems/FAT
 MODULES += IPStack
 DYNMODS = USB Interfaces/UDI
 
index 80c6d4d..b543160 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Video
+
 -include ../../Makefile.tpl
diff --git a/Modules/Filesystems/Ext2/Makefile b/Modules/Filesystems/Ext2/Makefile
new file mode 100644 (file)
index 0000000..471ba49
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = ext2.o read.o dir.o write.o
+NAME = Ext2
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/Ext2/dir.c b/Modules/Filesystems/Ext2/dir.c
new file mode 100644 (file)
index 0000000..0ab3ed3
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file dir.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+
+// === PROTOTYPES ===
+char           *Ext2_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *Ext2_FindDir(tVFS_Node *Node, char *FileName);
+ int           Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
+tVFS_Node      *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);
+
+// === CODE ===
+/**
+ \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+ \brief Reads a directory entry
+*/
+char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+{
+       tExt2_Inode     inode;
+       char    namebuf[EXT2_NAME_LEN+1];
+       tExt2_DirEnt    dirent;
+       Uint64  Base;   // Block's Base Address
+        int    block = 0, ofs = 0;
+        int    entNum = 0;
+       tExt2_Disk      *disk = Node->ImplPtr;
+       Uint    size;
+       
+       ENTER("pNode iPos", Node, Pos);
+       
+       // Read directory's inode
+       //Ext2_int_GetInode(Node, &inode);
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       size = inode.i_size;
+       
+       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
+       
+       // Find Entry
+       // Get First Block
+       // - Do this ourselves as it is a simple operation
+       Base = inode.i_block[0] * disk->BlockSize;
+       while(Pos -- && size > 0)
+       {
+               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
+               ofs += dirent.rec_len;
+               size -= dirent.rec_len;
+               entNum ++;
+               
+               if(ofs >= disk->BlockSize) {
+                       block ++;
+                       if( ofs > disk->BlockSize ) {
+                               Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",
+                                       entNum-1, Node->Inode);
+                       }
+                       ofs = 0;
+                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+               }
+       }
+       
+       // Check for the end of the list
+       if(size <= 0) {
+               LEAVE('n');
+               return NULL;
+       }
+       
+       // Read Entry
+       VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
+       //LOG("dirent.inode = %i", dirent.inode);
+       //LOG("dirent.rec_len = %i", dirent.rec_len);
+       //LOG("dirent.name_len = %i", dirent.name_len);
+       VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
+       namebuf[ dirent.name_len ] = '\0';      // Cap off string
+       
+       
+       // Ignore . and .. (these are done in the VFS)
+       if( (namebuf[0] == '.' && namebuf[1] == '\0')
+       ||  (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
+               LEAVE('p', VFS_SKIP);
+               return VFS_SKIP;        // Skip
+       }
+       
+       LEAVE('s', namebuf);
+       // Create new node
+       return strdup(namebuf);
+}
+
+/**
+ \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)
+ \brief Gets information about a file
+ \param node   vfs node - Parent Node
+ \param filename       String - Name of file
+ \return VFS Node of file
+*/
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       char    namebuf[EXT2_NAME_LEN+1];
+       tExt2_DirEnt    dirent;
+       Uint64  Base;   // Block's Base Address
+        int    block = 0, ofs = 0;
+        int    entNum = 0;
+       Uint    size;
+       
+       // Read directory's inode
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       size = inode.i_size;
+       
+       // Get First Block
+       // - Do this ourselves as it is a simple operation
+       Base = inode.i_block[0] * disk->BlockSize;
+       // Find File
+       while(size > 0)
+       {
+               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
+               VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
+               namebuf[ dirent.name_len ] = '\0';      // Cap off string
+               // If it matches, create a node and return it
+               if(strcmp(namebuf, Filename) == 0)
+                       return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
+               // Increment pointers
+               ofs += dirent.rec_len;
+               size -= dirent.rec_len;
+               entNum ++;
+               
+               // Check for end of block
+               if(ofs >= disk->BlockSize) {
+                       block ++;
+                       if( ofs > disk->BlockSize ) {
+                               Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",
+                                       entNum-1, Node->Inode);
+                       }
+                       ofs = 0;
+                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+               }
+       }
+       
+       return NULL;
+}
+
+/**
+ * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
+ * \brief Create a new node
+ */
+int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
+{
+       return 0;
+}
+
+// ---- INTERNAL FUNCTIONS ----
+/**
+ * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
+ * \brief Create a new VFS Node
+ */
+tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
+{
+       tExt2_Inode     inode;
+       tVFS_Node       retNode;
+       tVFS_Node       *tmpNode;
+       
+       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
+               return NULL;
+       
+       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
+               return tmpNode;
+       
+       
+       // Set identifiers
+       retNode.Inode = InodeID;
+       retNode.ImplPtr = Disk;
+       
+       // Set file length
+       retNode.Size = inode.i_size;
+       
+       // Set Access Permissions
+       retNode.UID = inode.i_uid;
+       retNode.GID = inode.i_gid;
+       retNode.NumACLs = 3;
+       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
+       
+       //  Set Function Pointers
+       retNode.Read = Ext2_Read;
+       retNode.Write = Ext2_Write;
+       retNode.Close = Ext2_CloseFile;
+       
+       switch(inode.i_mode & EXT2_S_IFMT)
+       {
+       // Symbolic Link
+       case EXT2_S_IFLNK:
+               retNode.Flags = VFS_FFLAG_SYMLINK;
+               break;
+       // Regular File
+       case EXT2_S_IFREG:
+               retNode.Flags = 0;
+               retNode.Size |= (Uint64)inode.i_dir_acl << 32;
+               break;
+       // Directory
+       case EXT2_S_IFDIR:
+               retNode.ReadDir = Ext2_ReadDir;
+               retNode.FindDir = Ext2_FindDir;
+               retNode.MkNod = Ext2_MkNod;
+               //retNode.Relink = Ext2_Relink;
+               retNode.Flags = VFS_FFLAG_DIRECTORY;
+               break;
+       // Unknown, Write protect and hide it to be safe 
+       default:
+               retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
+               break;
+       }
+       
+       // Check if the file should be hidden
+       //if(Name[0] == '.')    retNode.Flags |= VFS_FFLAG_HIDDEN;
+       
+       // Set Timestamps
+       retNode.ATime = now();
+       retNode.MTime = inode.i_mtime * 1000;
+       retNode.CTime = inode.i_ctime * 1000;
+       
+       // Save in node cache and return saved node
+       return Inode_CacheNode(Disk->CacheID, &retNode);
+}
diff --git a/Modules/Filesystems/Ext2/ext2.c b/Modules/Filesystems/Ext2/ext2.c
new file mode 100644 (file)
index 0000000..c2c2df9
--- /dev/null
@@ -0,0 +1,330 @@
+/*\r
+ * Acess OS\r
+ * Ext2 Driver Version 1\r
+ */\r
+/**\r
+ * \file fs/ext2.c\r
+ * \brief Second Extended Filesystem Driver\r
+ * \todo Implement file full write support\r
+ */\r
+#define DEBUG  1\r
+#define VERBOSE        0\r
+#include "ext2_common.h"\r
+#include <modules.h>\r
+\r
+// === PROTOTYPES ===\r
+ int   Ext2_Install(char **Arguments);\r
+// Interface Functions\r
+tVFS_Node      *Ext2_InitDevice(char *Device, char **Options);\r
+void           Ext2_Unmount(tVFS_Node *Node);\r
+void           Ext2_CloseFile(tVFS_Node *Node);\r
+// Internal Helpers\r
+ int           Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+Uint64         Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
+Uint32         Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
+void           Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\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
+       };\r
+\r
+// === CODE ===\r
+\r
+/**\r
+ * \fn int Ext2_Install(char **Arguments)\r
+ * \brief Install the Ext2 Filesystem Driver\r
+ */\r
+int Ext2_Install(char **Arguments)\r
+{\r
+       VFS_AddDriver( &gExt2_FSInfo );\r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+ \brief Initializes a device to be read by by the driver\r
+ \param Device String - Device to read from\r
+ \param Options        NULL Terminated array of option strings\r
+ \return Root Node\r
+*/\r
+tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
+{\r
+       tExt2_Disk      *disk;\r
+        int    fd;\r
+        int    groupCount;\r
+       tExt2_SuperBlock        sb;\r
+       tExt2_Inode     inode;\r
+       \r
+       ENTER("sDevice pOptions", Device, Options);\r
+       \r
+       // Open Disk\r
+       fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);            //Open Device\r
+       if(fd == -1) {\r
+               Warning("[EXT2 ] Unable to open '%s'", Device);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Read Superblock at offset 1024\r
+       VFS_ReadAt(fd, 1024, 1024, &sb);        // Read Superblock\r
+       \r
+       // Sanity Check Magic value\r
+       if(sb.s_magic != 0xEF53) {\r
+               Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
+               VFS_Close(fd);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       // Get Group count\r
+       groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
+       LOG("groupCount = %i", groupCount);\r
+       \r
+       // Allocate Disk Information\r
+       disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
+       if(!disk) {\r
+               Warning("[EXT2 ] Unable to allocate disk structure");\r
+               VFS_Close(fd);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       disk->FD = fd;\r
+       memcpy(&disk->SuperBlock, &sb, 1024);\r
+       disk->GroupCount = groupCount;\r
+       \r
+       // Get an inode cache handle\r
+       disk->CacheID = Inode_GetHandle();\r
+       \r
+       // Get Block Size\r
+       LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
+       disk->BlockSize = 1024 << sb.s_log_block_size;\r
+       \r
+       // Read Group Information\r
+       VFS_ReadAt(\r
+               disk->FD,\r
+               sb.s_first_data_block * disk->BlockSize + 1024,\r
+               sizeof(tExt2_Group)*groupCount,\r
+               disk->Groups\r
+               );\r
+       \r
+       #if VERBOSE\r
+       LOG("Block Group 0");\r
+       LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
+       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
+       LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
+       LOG("Block Group 1");\r
+       LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
+       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
+       LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
+       #endif\r
+       \r
+       // Get root Inode\r
+       Ext2_int_ReadInode(disk, 2, &inode);\r
+       \r
+       // Create Root Node\r
+       memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
+       disk->RootNode.Inode = 2;       // Root inode ID\r
+       disk->RootNode.ImplPtr = disk;  // Save disk pointer\r
+       disk->RootNode.Size = -1;       // Fill in later (on readdir)\r
+       disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
+       \r
+       disk->RootNode.ReadDir = Ext2_ReadDir;\r
+       disk->RootNode.FindDir = Ext2_FindDir;\r
+       //disk->RootNode.Relink = Ext2_Relink;\r
+       \r
+       // Complete root node\r
+       disk->RootNode.UID = inode.i_uid;\r
+       disk->RootNode.GID = inode.i_gid;\r
+       disk->RootNode.NumACLs = 1;\r
+       disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
+       \r
+       #if DEBUG\r
+       LOG("inode.i_size = 0x%x", inode.i_size);\r
+       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
+       #endif\r
+       \r
+       LEAVE('p', &disk->RootNode);\r
+       return &disk->RootNode;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_Unmount(tVFS_Node *Node)\r
+ * \brief Close a mounted device\r
+ */\r
+void Ext2_Unmount(tVFS_Node *Node)\r
+{\r
+       tExt2_Disk      *disk = Node->ImplPtr;\r
+       \r
+       VFS_Close( disk->FD );\r
+       Inode_ClearCache( disk->CacheID );\r
+       memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
+       free(disk);\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
+ * \brief Close a file (Remove it from the cache)\r
+ */\r
+void Ext2_CloseFile(tVFS_Node *Node)\r
+{\r
+       tExt2_Disk      *disk = Node->ImplPtr;\r
+       Inode_UncacheNode(disk->CacheID, Node->Inode);\r
+       return ;\r
+}\r
+\r
+//==================================\r
+//=       INTERNAL FUNCTIONS       =\r
+//==================================\r
+/**\r
+ * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
+ * \brief Read an inode into memory\r
+ */\r
+int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
+{\r
+        int    group, subId;\r
+       \r
+       //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+       \r
+       if(InodeId == 0)        return 0;\r
+       \r
+       InodeId --;     // Inodes are numbered starting at 1\r
+       \r
+       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+       \r
+       //LOG("group=%i, subId = %i", group, subId);\r
+       \r
+       // Read Inode\r
+       VFS_ReadAt(Disk->FD,\r
+               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+               sizeof(tExt2_Inode),\r
+               Inode);\r
+       \r
+       //LEAVE('i', 1);\r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \brief Write a modified inode out to disk\r
+ */\r
+int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
+{\r
+        int    group, subId;\r
+       ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
+       \r
+       if(InodeId == 0)        return 0;\r
+       \r
+       InodeId --;     // Inodes are numbered starting at 1\r
+       \r
+       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
+       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
+       \r
+       LOG("group=%i, subId = %i", group, subId);\r
+       \r
+       // Write Inode\r
+       VFS_WriteAt(Disk->FD,\r
+               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
+               sizeof(tExt2_Inode),\r
+               Inode);\r
+       \r
+       LEAVE('i', 1);\r
+       return 1;\r
+}\r
+\r
+/**\r
+ * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+ * \brief Get the address of a block from an inode's list\r
+ * \param Disk Disk information structure\r
+ * \param Blocks       Pointer to an inode's block list\r
+ * \param BlockNum     Block index in list\r
+ */\r
+Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
+{\r
+       Uint32  *iBlocks;\r
+        int    dwPerBlock = Disk->BlockSize / 4;\r
+       \r
+       // Direct Blocks\r
+       if(BlockNum < 12)\r
+               return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
+       \r
+       // Single Indirect Blocks\r
+       iBlocks = malloc( Disk->BlockSize );\r
+       VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       \r
+       BlockNum -= 12;\r
+       if(BlockNum < dwPerBlock)\r
+       {\r
+               BlockNum = iBlocks[BlockNum];\r
+               free(iBlocks);\r
+               return (Uint64)BlockNum * Disk->BlockSize;\r
+       }\r
+       \r
+       BlockNum -= dwPerBlock;\r
+       // Double Indirect Blocks\r
+       if(BlockNum < dwPerBlock*dwPerBlock)\r
+       {\r
+               VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+               VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+               BlockNum = iBlocks[BlockNum%dwPerBlock];\r
+               free(iBlocks);\r
+               return (Uint64)BlockNum * Disk->BlockSize;\r
+       }\r
+       \r
+       BlockNum -= dwPerBlock*dwPerBlock;\r
+       // Triple Indirect Blocks\r
+       VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(dwPerBlock*dwPerBlock)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/dwPerBlock)%dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
+       BlockNum = iBlocks[BlockNum%dwPerBlock];\r
+       free(iBlocks);\r
+       return (Uint64)BlockNum * Disk->BlockSize;\r
+}\r
+\r
+/**\r
+ * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+ * \brief Allocate an inode (from the current group preferably)\r
+ * \param Disk EXT2 Disk Information Structure\r
+ * \param Parent       Inode ID of the parent (used to locate the child nearby)\r
+ */\r
+Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
+{\r
+//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+ * \brief Updates the superblock\r
+ */\r
+void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
+{\r
+        int    bpg = Disk->SuperBlock.s_blocks_per_group;\r
+        int    ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
+        int    i;\r
+        \r
+       // Update Primary\r
+       VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
+       \r
+       // Secondaries\r
+       // at Block Group 1, 3^n, 5^n, 7^n\r
+       \r
+       // 1\r
+       if(ngrp <= 1)   return;\r
+       VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 3\r
+       for( i = 3; i < ngrp; i *= 3 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 5\r
+       for( i = 5; i < ngrp; i *= 5 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+       \r
+       // Powers of 7\r
+       for( i = 7; i < ngrp; i *= 7 )\r
+               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
+}\r
diff --git a/Modules/Filesystems/Ext2/ext2_common.h b/Modules/Filesystems/Ext2/ext2_common.h
new file mode 100644 (file)
index 0000000..877b71d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file ext2_common.h
+ * \brief Second Extended Filesystem Driver
+ */
+#ifndef _EXT2_COMMON_H
+#define _EXT2_COMMON_H
+#include <acess.h>
+#include <vfs.h>
+#include "ext2fs.h"
+
+#define EXT2_UPDATE_WRITEBACK  1
+
+// === STRUCTURES ===
+typedef struct {
+        int    FD;
+        int    CacheID;
+       tVFS_Node       RootNode;
+       
+       tExt2_SuperBlock        SuperBlock;
+        int    BlockSize;
+        
+        int    GroupCount;
+       tExt2_Group             Groups[];
+} tExt2_Disk;
+
+// === FUNCTIONS ===
+// --- Common ---
+extern void    Ext2_CloseFile(tVFS_Node *Node);
+extern Uint64  Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);
+extern void    Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);
+extern int     Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
+extern int     Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
+// --- Dir ---
+extern char    *Ext2_ReadDir(tVFS_Node *Node, int Pos);
+extern tVFS_Node       *Ext2_FindDir(tVFS_Node *Node, char *FileName);
+extern int     Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
+// --- Read ---
+extern Uint64  Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+// --- Write ---
+extern Uint64  Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+
+#endif
diff --git a/Modules/Filesystems/Ext2/ext2fs.h b/Modules/Filesystems/Ext2/ext2fs.h
new file mode 100644 (file)
index 0000000..8fd87ce
--- /dev/null
@@ -0,0 +1,156 @@
+/**\r
+ * Acess2\r
+ * \file ext2fs.h\r
+ * \brief EXT2 Filesystem Driver\r
+ */\r
+#ifndef _EXT2FS_H_\r
+#define _EXT2FS_H_\r
+\r
+/**\r
+ \name Inode Flag Values\r
+ \{\r
+*/\r
+#define EXT2_S_IFMT            0xF000  //!< Format Mask\r
+#define EXT2_S_IFSOCK  0xC000  //!< Socket\r
+#define EXT2_S_IFLNK   0xA000  //!< Symbolic Link\r
+#define EXT2_S_IFREG   0x8000  //!< Regular File\r
+#define EXT2_S_IFBLK   0x6000  //!< Block Device\r
+#define EXT2_S_IFDIR   0x4000  //!< Directory\r
+#define EXT2_S_IFCHR   0x2000  //!< Character Device\r
+#define EXT2_S_IFIFO   0x1000  //!< FIFO\r
+#define EXT2_S_ISUID   0x0800  //!< SUID\r
+#define EXT2_S_ISGID   0x0400  //!< SGID\r
+#define EXT2_S_ISVTX   0x0200  //!< sticky bit\r
+#define EXT2_S_IRWXU   0700    //!< user access rights mask\r
+#define EXT2_S_IRUSR   0400    //!< Owner Read\r
+#define EXT2_S_IWUSR   0200    //!< Owner Write\r
+#define EXT2_S_IXUSR   0100    //!< Owner Execute\r
+#define EXT2_S_IRWXG   0070    //!< Group Access rights mask\r
+#define EXT2_S_IRGRP   0040    //!< Group Read\r
+#define EXT2_S_IWGRP   0020    //!< Group Write\r
+#define EXT2_S_IXGRP   0010    //!< Group Execute\r
+#define EXT2_S_IRWXO   0007    //!< Global Access rights mask\r
+#define EXT2_S_IROTH   0004    //!< Global Read\r
+#define EXT2_S_IWOTH   0002    //!< Global Write\r
+#define EXT2_S_IXOTH   0001    //!< Global Execute\r
+//! \}\r
+\r
+#define EXT2_NAME_LEN 255      //!< Maximum Name Length\r
+\r
+// === TYPEDEFS ===\r
+typedef struct ext2_inode_s                    tExt2_Inode;    //!< Inode Type\r
+typedef struct ext2_super_block_s      tExt2_SuperBlock;       //!< Superblock Type\r
+typedef struct ext2_group_desc_s       tExt2_Group;    //!< Group Descriptor Type\r
+typedef struct ext2_dir_entry_s                tExt2_DirEnt;   //!< Directory Entry Type\r
+\r
+// === STRUCTURES ===\r
+/**\r
+ * \brief EXT2 Superblock Structure\r
+ */\r
+struct ext2_super_block_s {\r
+       Uint32  s_inodes_count;         //!< Inodes count\r
+       Uint32  s_blocks_count;         //!< Blocks count\r
+       Uint32  s_r_blocks_count;       //!< Reserved blocks count\r
+       Uint32  s_free_blocks_count;    //!< Free blocks count\r
+       Uint32  s_free_inodes_count;    //!< Free inodes count\r
+       Uint32  s_first_data_block;     //!< First Data Block\r
+       Uint32  s_log_block_size;       //!< Block size\r
+       Sint32  s_log_frag_size;        //!< Fragment size\r
+       Uint32  s_blocks_per_group;     //!< Number Blocks per group\r
+       Uint32  s_frags_per_group;      //!< Number Fragments per group\r
+       Uint32  s_inodes_per_group;     //!< Number Inodes per group\r
+       Uint32  s_mtime;                        //!< Mount time\r
+       Uint32  s_wtime;                        //!< Write time\r
+       Uint16  s_mnt_count;            //!< Mount count\r
+       Sint16  s_max_mnt_count;        //!< Maximal mount count\r
+       Uint16  s_magic;                        //!< Magic signature\r
+       Uint16  s_state;                        //!< File system state\r
+       Uint16  s_errors;                       //!< Behaviour when detecting errors\r
+       Uint16  s_pad;                          //!< Padding\r
+       Uint32  s_lastcheck;            //!< time of last check\r
+       Uint32  s_checkinterval;        //!< max. time between checks\r
+       Uint32  s_creator_os;           //!< Formatting OS\r
+       Uint32  s_rev_level;            //!< Revision level\r
+       Uint16  s_def_resuid;           //!< Default uid for reserved blocks\r
+       Uint16  s_def_resgid;           //!< Default gid for reserved blocks\r
+       Uint32  s_reserved[235];        //!< Padding to the end of the block\r
+};\r
+\r
+/**\r
+ * \struct ext2_inode_s\r
+ * \brief EXT2 Inode Definition\r
+ */\r
+struct ext2_inode_s {\r
+       Uint16 i_mode;  //!< File mode\r
+       Uint16 i_uid;   //!< Owner Uid\r
+       Uint32 i_size;  //!< Size in bytes\r
+       Uint32 i_atime; //!< Access time\r
+       Uint32 i_ctime; //!< Creation time\r
+       Uint32 i_mtime; //!< Modification time\r
+       Uint32 i_dtime; //!< Deletion Time\r
+       Uint16 i_gid;   //!< Group Id\r
+       Uint16 i_links_count;   //!< Links count\r
+       Uint32 i_blocks;        //!< Number of blocks allocated for the file\r
+       Uint32 i_flags; //!< File flags\r
+       union {\r
+               Uint32 linux_reserved1; //!< Linux: Reserved\r
+               Uint32 hurd_translator; //!< HURD: Translator\r
+               Uint32 masix_reserved1; //!< Masix: Reserved\r
+       } osd1; //!< OS dependent 1\r
+       Uint32 i_block[15];     //!< Pointers to blocks\r
+       Uint32 i_version;       //!< File version (for NFS)\r
+       Uint32 i_file_acl;      //!< File ACL\r
+       Uint32 i_dir_acl;       //!< Directory ACL / Extended File Size\r
+       Uint32 i_faddr;         //!< Fragment address\r
+       union {\r
+               struct {\r
+                       Uint8 l_i_frag; //!< Fragment number\r
+                       Uint8 l_i_fsize;        //!< Fragment size\r
+                       Uint16 i_pad1;  //!< Padding\r
+                       Uint32 l_i_reserved2[2];        //!< Reserved\r
+               } linux2;\r
+               struct {\r
+                       Uint8 h_i_frag; //!< Fragment number\r
+                       Uint8 h_i_fsize; //!< Fragment size\r
+                       Uint16 h_i_mode_high;   //!< Mode High Bits\r
+                       Uint16 h_i_uid_high;    //!< UID High Bits\r
+                       Uint16 h_i_gid_high;    //!< GID High Bits\r
+                       Uint32 h_i_author;      //!< Creator ID\r
+               } hurd2;\r
+               struct {\r
+                       Uint8 m_i_frag; //!< Fragment number\r
+                       Uint8 m_i_fsize;        //!< Fragment size\r
+                       Uint16 m_pad1;  //!< Padding\r
+                       Uint32 m_i_reserved2[2];        //!< reserved\r
+               } masix2;\r
+       } osd2; //!< OS dependent 2\r
+};\r
+\r
+/**\r
+ * \struct ext2_group_desc_s\r
+ * \brief EXT2 Group Descriptor\r
+ */\r
+struct ext2_group_desc_s {\r
+       Uint32  bg_block_bitmap;        //!< Blocks bitmap block\r
+       Uint32  bg_inode_bitmap;        //!< Inodes bitmap block\r
+       Uint32  bg_inode_table; //!< Inodes table block\r
+       Uint16  bg_free_blocks_count;   //!< Free blocks count\r
+       Uint16  bg_free_inodes_count;   //!< Free inodes count\r
+       Uint16  bg_used_dirs_count;     //!< Directories count\r
+       Uint16  bg_pad; //!< Padding\r
+       Uint32  bg_reserved[3]; //!< Reserved\r
+};\r
+\r
+/**\r
+ * \brief EXT2 Directory Entry\r
+ * \note The name may take up less than 255 characters\r
+ */\r
+struct ext2_dir_entry_s {\r
+       Uint32  inode;          //!< Inode number\r
+       Uint16  rec_len;        //!< Directory entry length\r
+       Uint8   name_len;       //!< Short Name Length\r
+       Uint8   type;           //!< File Type\r
+       char    name[];         //!< File name\r
+};\r
+\r
+#endif\r
diff --git a/Modules/Filesystems/Ext2/read.c b/Modules/Filesystems/Ext2/read.c
new file mode 100644 (file)
index 0000000..81f5ee6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file read.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+// === PROTOTYPES ===
+Uint64         Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+
+// === CODE ===
+/**
+ * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Read from a file
+ */
+Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       Uint64  base;
+       Uint    block;
+       Uint64  remLen;
+       
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
+       // Get Inode
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       
+       // Sanity Checks
+       if(Offset >= inode.i_size) {
+               LEAVE('i', 0);
+               return 0;
+       }
+       if(Offset + Length > inode.i_size)
+               Length = inode.i_size - Offset;
+       
+       block = Offset / disk->BlockSize;
+       Offset = Offset / disk->BlockSize;
+       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       if(base == 0) {
+               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+               LEAVE('i', 0);
+               return 0;
+       }
+       
+       // Read only block
+       if(Length <= disk->BlockSize - Offset)
+       {
+               VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);
+               LEAVE('X', Length);
+               return Length;
+       }
+       
+       // Read first block
+       remLen = Length;
+       VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);
+       remLen -= disk->BlockSize - Offset;
+       Buffer += disk->BlockSize - Offset;
+       block ++;
+       
+       // Read middle blocks
+       while(remLen > disk->BlockSize)
+       {
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               if(base == 0) {
+                       Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+                       LEAVE('i', 0);
+                       return 0;
+               }
+               VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);
+               Buffer += disk->BlockSize;
+               remLen -= disk->BlockSize;
+               block ++;
+       }
+       
+       // Read last block
+       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+       VFS_ReadAt( disk->FD, base, remLen, Buffer);
+       
+       LEAVE('X', Length);
+       return Length;
+}
diff --git a/Modules/Filesystems/Ext2/write.c b/Modules/Filesystems/Ext2/write.c
new file mode 100644 (file)
index 0000000..ba8b61c
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Acess OS
+ * Ext2 Driver Version 1
+ */
+/**
+ * \file write.c
+ * \brief Second Extended Filesystem Driver
+ * \todo Implement file full write support
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "ext2_common.h"
+
+// === PROTOYPES ===
+Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
+Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
+void   Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
+ int   Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
+
+// === CODE ===
+/**
+ * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Write to a file
+ */
+Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tExt2_Disk      *disk = Node->ImplPtr;
+       tExt2_Inode     inode;
+       Uint64  base;
+       Uint64  retLen;
+       Uint    block;
+       Uint64  allocSize;
+        int    bNewBlocks = 0;
+       
+       Debug_HexDump("Ext2_Write", Buffer, Length);
+       
+       Ext2_int_ReadInode(disk, Node->Inode, &inode);
+       
+       // Get the ammount of space already allocated
+       // - Round size up to block size
+       // - block size is a power of two, so this will work
+       allocSize = (inode.i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
+       
+       // Are we writing to inside the allocated space?
+       if( Offset > allocSize )        return 0;
+       
+       if( Offset < allocSize )
+       {
+               // Will we go out of it?
+               if(Offset + Length > allocSize) {
+                       bNewBlocks = 1;
+                       retLen = allocSize - Offset;
+               } else
+                       retLen = Length;
+               
+               // Within the allocated space
+               block = Offset / disk->BlockSize;
+               Offset %= disk->BlockSize;
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               
+               // Write only block (if only one)
+               if(Offset + retLen <= disk->BlockSize) {
+                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
+                       if(!bNewBlocks) return Length;
+                       goto addBlocks; // Ugh! A goto, but it seems unavoidable
+               }
+               
+               // Write First Block
+               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
+               Buffer += disk->BlockSize-Offset;
+               retLen -= disk->BlockSize-Offset;
+               block ++;
+               
+               // Write middle blocks
+               while(retLen > disk->BlockSize)
+               {
+                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+                       Buffer += disk->BlockSize;
+                       retLen -= disk->BlockSize;
+                       block ++;
+               }
+               
+               // Write last block
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+               VFS_WriteAt(disk->FD, base, retLen, Buffer);
+               if(!bNewBlocks) return Length;  // Writing in only allocated space
+       }
+       else
+               base = Ext2_int_GetBlockAddr(disk, inode.i_block, allocSize/disk->BlockSize-1);
+       
+addBlocks:
+       Warning("[EXT2 ] File extending is untested");
+       
+       // Allocate blocks and copy data to them
+       retLen = Length - (allocSize-Offset);
+       while( retLen > disk->BlockSize )
+       {
+               // Allocate a block
+               block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
+               if(!block)      return Length - retLen;
+               // Add it to this inode
+               if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+                       Ext2_int_DeallocateBlock(disk, block);
+                       goto ret;
+               }
+               // Copy data to the node
+               base = block * disk->BlockSize;
+               VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+               // Update pointer and size remaining
+               inode.i_size += disk->BlockSize;
+               Buffer += disk->BlockSize;
+               retLen -= disk->BlockSize;
+       }
+       // Last block :D
+       block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
+       if(!block)      goto ret;
+       if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+               Ext2_int_DeallocateBlock(disk, block);
+               goto ret;
+       }
+       base = block * disk->BlockSize;
+       VFS_WriteAt(disk->FD, base, retLen, Buffer);
+       inode.i_size += retLen;
+       retLen = 0;
+
+ret:   // Makes sure the changes to the inode are committed
+       Ext2_int_WriteInode(disk, Node->Inode, &inode);
+       return Length - retLen;
+}
+
+/**
+ * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
+ * \brief Allocate a block from the best possible location
+ * \param Disk EXT2 Disk Information Structure
+ * \param PrevBlock    Previous block ID in the file
+ */
+Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
+{
+        int    bpg = Disk->SuperBlock.s_blocks_per_group;
+       Uint    blockgroup = PrevBlock / bpg;
+       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
+       Uint    bitsperblock = 8*Disk->BlockSize;
+        int    i, j = 0;
+       Uint    block;
+       
+       // Are there any free blocks?
+       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
+       
+       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
+       {
+               // Search block group's bitmap
+               for(i = 0; i < bpg; i++)
+               {
+                       // Get the block in the bitmap block
+                       j = i & (bitsperblock-1);
+                       
+                       // Read in if needed
+                       if(j == 0) {
+                               VFS_ReadAt(
+                                       Disk->FD,
+                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
+                                       Disk->BlockSize,
+                                       bitmap
+                                       );
+                       }
+                       
+                       // Fast Check
+                       if( bitmap[j/32] == -1 ) {
+                               j = (j + 31) & ~31;
+                               continue;
+                       }
+                       
+                       // Is the bit set?
+                       if( bitmap[j/32] & (1 << (j%32)) )
+                               continue;
+                       
+                       // Ooh! We found one
+                       break;
+               }
+               if( i < bpg ) {
+                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
+                       goto    checkAll;       // Search the entire filesystem for a free block
+                       // Goto needed for neatness
+               }
+               
+               // Mark as used
+               bitmap[j/32] |= (1 << (j%32));
+               VFS_WriteAt(
+                       Disk->FD,
+                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
+                       Disk->BlockSize,
+                       bitmap
+                       );
+               block = i;
+               Disk->Groups[blockgroup].bg_free_blocks_count --;
+               #if EXT2_UPDATE_WRITEBACK
+               //Ext2_int_UpdateBlockGroup(Disk, blockgroup);
+               #endif
+       }
+       else
+       {
+       checkAll:
+               Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");
+               return 0;
+       }
+       
+       // Reduce global count
+       Disk->SuperBlock.s_free_blocks_count --;
+       #if EXT2_UPDATE_WRITEBACK
+       Ext2_int_UpdateSuperblock(Disk);
+       #endif
+       
+       return block;
+}
+
+/**
+ * \brief Deallocates a block
+ */
+void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
+{
+}
+
+/**
+ * \brief Append a block to an inode
+ */
+int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
+{
+        int    nBlocks;
+        int    dwPerBlock = Disk->BlockSize / 4;
+       Uint32  *blocks;
+       Uint32  id1, id2;
+       
+       nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
+       
+       // Direct Blocks
+       if( nBlocks < 12 ) {
+               Inode->i_block[nBlocks] = Block;
+               return 0;
+       }
+       
+       blocks = malloc( Disk->BlockSize );
+       if(!blocks)     return 1;
+       
+       nBlocks -= 12;
+       // Single Indirect
+       if( nBlocks < dwPerBlock)
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[12] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize); 
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               blocks[nBlocks] = Block;
+               
+               VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       nBlocks += dwPerBlock;
+       // Double Indirect
+       if( nBlocks < dwPerBlock*dwPerBlock )
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[13] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               // Allocate / Get Indirect lvl2 Block
+               if( nBlocks % dwPerBlock == 0 ) {
+                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !id1 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[nBlocks/dwPerBlock] = id1;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id1 = blocks[nBlocks / dwPerBlock];
+                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               blocks[nBlocks % dwPerBlock] = Block;
+               
+               VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       nBlocks -= dwPerBlock*dwPerBlock;
+       // Triple Indirect
+       if( nBlocks < dwPerBlock*dwPerBlock*dwPerBlock )
+       {
+               // Allocate/Get Indirect block
+               if( nBlocks == 0 ) {
+                       Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !Inode->i_block[14] ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else
+                       VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
+               
+               // Allocate / Get Indirect lvl2 Block
+               if( (nBlocks/dwPerBlock) % dwPerBlock == 0 && nBlocks % dwPerBlock == 0 )
+               {
+                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
+                       if( !id1 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[nBlocks/dwPerBlock] = id1;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id1 = blocks[nBlocks / (dwPerBlock*dwPerBlock)];
+                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               // Allocate / Get Indirect Level 3 Block
+               if( nBlocks % dwPerBlock == 0 ) {
+                       id2 = Ext2_int_AllocateBlock(Disk, id1);
+                       if( !id2 ) {
+                               free(blocks);
+                               return 1;
+                       }
+                       blocks[(nBlocks/dwPerBlock)%dwPerBlock] = id2;
+                       // Write back indirect 1 block
+                       VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
+                       memset(blocks, 0, Disk->BlockSize);
+               }
+               else {
+                       id2 = blocks[(nBlocks/dwPerBlock)%dwPerBlock];
+                       VFS_ReadAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
+               }
+               
+               blocks[nBlocks % dwPerBlock] = Block;
+               
+               VFS_WriteAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
+               free(blocks);
+               return 0;
+       }
+       
+       Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
+       free(blocks);
+       return 1;
+}
diff --git a/Modules/Filesystems/FAT/Makefile b/Modules/Filesystems/FAT/Makefile
new file mode 100644 (file)
index 0000000..dfa290b
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = fat.o
+NAME = FAT
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/FAT/fat.c b/Modules/Filesystems/FAT/fat.c
new file mode 100644 (file)
index 0000000..f41b9ea
--- /dev/null
@@ -0,0 +1,1128 @@
+/*\r
+ * Acess 2\r
+ * FAT12/16/32 Driver Version (Incl LFN)\r
+ */\r
+#define DEBUG  0\r
+#define VERBOSE        1\r
+\r
+#define CACHE_FAT      1       //!< Caches the FAT in memory\r
+#define USE_LFN                1       //!< Enables the use of Long File Names\r
+\r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include "fs_fat.h"\r
+\r
+\r
+// === TYPES ===\r
+#if USE_LFN\r
+typedef struct s_lfncache\r
+{\r
+       Uint    Inode;\r
+       tFAT_VolInfo    *Disk;\r
+        int    id;\r
+       char    Name[256];\r
+       struct s_lfncache       *Next;\r
+}      t_lfncache;\r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+ int   FAT_Install(char **Arguments);\r
+tVFS_Node      *FAT_InitDevice(char *device, char **options);\r
+void   FAT_Unmount(tVFS_Node *Node);\r
+\r
+Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 Cluster);\r
+Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous);\r
+\r
+void   FAT_int_ReadCluster(tFAT_VolInfo *Disk, Uint32 Cluster, int Length, void *Buffer);\r
+void   FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, void *Buffer);\r
+\r
+Uint64 FAT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+char   *FAT_ReadDir(tVFS_Node *Node, int ID);\r
+tVFS_Node      *FAT_FindDir(tVFS_Node *Node, char *Name);\r
+ int   FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags);\r
+ int   FAT_Relink(tVFS_Node *node, char *OldName, char *NewName);\r
+void   FAT_CloseFile(tVFS_Node *node);\r
+\r
+// === SEMI-GLOBALS ===\r
+MODULE_DEFINE(0, (0<<8)|50 /*v0.50*/, VFAT, FAT_Install, NULL, NULL);\r
+tFAT_VolInfo   gFAT_Disks[8];\r
+ int   giFAT_PartCount = 0;\r
+#if USE_LFN\r
+t_lfncache     *fat_lfncache;\r
+#endif\r
+tVFS_Driver    gFAT_FSInfo = {"fat", 0, FAT_InitDevice, FAT_Unmount, NULL};\r
+\r
+// === CODE ===\r
+/**\r
+ * \fn int FAT_Install(char **Arguments)\r
+ * \brief \r
+ */\r
+int FAT_Install(char **Arguments)\r
+{\r
+       VFS_AddDriver( &gFAT_FSInfo );\r
+       return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_InitDevice(char *Device, char **Options)\r
+ * \brief Reads the boot sector of a disk and prepares the structures for it\r
+ */\r
+tVFS_Node *FAT_InitDevice(char *Device, char **Options)\r
+{\r
+       fat_bootsect *bs;\r
+        int    i;\r
+       Uint32  FATSz, RootDirSectors, TotSec;\r
+       tVFS_Node       *node = NULL;\r
+       tFAT_VolInfo    *diskInfo = &gFAT_Disks[giFAT_PartCount];\r
+       \r
+       // Temporary Pointer\r
+       bs = &diskInfo->bootsect;\r
+       \r
+       //Open device and read boot sector\r
+       diskInfo->fileHandle = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);\r
+       if(diskInfo->fileHandle == -1) {\r
+               Warning("FAT_InitDisk - Unable to open device '%s'", Device);\r
+               return NULL;\r
+       }\r
+       \r
+       VFS_ReadAt(diskInfo->fileHandle, 0, 512, bs);\r
+       \r
+       if(bs->bps == 0 || bs->spc == 0) {\r
+               Warning("FAT_InitDisk - Error in FAT Boot Sector\n");\r
+               return NULL;\r
+       }\r
+       \r
+       // FAT Type Determining\r
+       // - From Microsoft FAT Specifcation\r
+       RootDirSectors = ((bs->files_in_root*32) + (bs->bps - 1)) / bs->bps;\r
+       \r
+       if(bs->fatSz16 != 0)            FATSz = bs->fatSz16;\r
+       else                                    FATSz = bs->spec.fat32.fatSz32;\r
+       \r
+       if(bs->totalSect16 != 0)                TotSec = bs->totalSect16;\r
+       else                                            TotSec = bs->totalSect32;\r
+       \r
+       diskInfo->ClusterCount = (TotSec - (bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors)) / bs->spc;\r
+       \r
+       if(diskInfo->ClusterCount < 4085)\r
+               diskInfo->type = FAT12;\r
+       else if(diskInfo->ClusterCount < 65525)\r
+               diskInfo->type = FAT16;\r
+       else\r
+               diskInfo->type = FAT32;\r
+       \r
+       #if VERBOSE\r
+       {\r
+               char    *sFatType, *sSize;\r
+               Uint    iSize = diskInfo->ClusterCount * bs->spc * bs->bps / 1024;\r
+               \r
+               switch(diskInfo->type)\r
+               {\r
+               case FAT12:     sFatType = "FAT12";     break;\r
+               case FAT16:     sFatType = "FAT16";     break;\r
+               case FAT32:     sFatType = "FAT32";     break;\r
+               default:        sFatType = "UNKNOWN";   break;\r
+               }\r
+               if(iSize <= 2*1024) {\r
+                       sSize = "KiB";\r
+               }\r
+               else if(iSize <= 2*1024*1024) {\r
+                       sSize = "MiB";\r
+                       iSize >>= 10;\r
+               }\r
+               else {\r
+                       sSize = "GiB";\r
+                       iSize >>= 20;\r
+               }\r
+               Log("[FAT ] '%s' %s, %i %s", Device, sFatType, iSize, sSize);\r
+       }\r
+       #endif\r
+       \r
+       // Get Name\r
+       if(diskInfo->type == FAT32) {\r
+               for(i=0;i<11;i++)\r
+                       diskInfo->name[i] = (bs->spec.fat32.label[i] == ' ' ? '\0' : bs->spec.fat32.label[i]);\r
+       }\r
+       else {\r
+               for(i=0;i<11;i++)\r
+                       diskInfo->name[i] = (bs->spec.fat16.label[i] == ' ' ? '\0' : bs->spec.fat16.label[i]);\r
+       }\r
+       diskInfo->name[11] = '\0';\r
+       \r
+       // Compute Root directory offset\r
+       if(diskInfo->type == FAT32)\r
+               diskInfo->rootOffset = bs->spec.fat32.rootClust;\r
+       else\r
+               diskInfo->rootOffset = (FATSz * bs->fatCount) / bs->spc;\r
+       \r
+       diskInfo->firstDataSect = bs->resvSectCount + (bs->fatCount * FATSz) + RootDirSectors;\r
+       \r
+       //Allow for Caching the FAT\r
+       #if CACHE_FAT\r
+       {\r
+       Uint32  Ofs;\r
+       diskInfo->FATCache = (Uint32*)malloc(sizeof(Uint32)*diskInfo->ClusterCount);\r
+       if(diskInfo->FATCache == NULL) {\r
+               Warning("FAT_InitDisk - Heap Exhausted\n");\r
+               return NULL;\r
+       }\r
+       Ofs = bs->resvSectCount*512;\r
+       if(diskInfo->type == FAT12)\r
+       {\r
+               Uint32  val;\r
+                int    j;\r
+               char    buf[1536];\r
+               for(i = 0; i < diskInfo->ClusterCount/2; i++) {\r
+                       j = i & 511;    //%512\r
+                       if( j == 0 ) {\r
+                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 3*512, buf);\r
+                               Ofs += 3*512;\r
+                       }\r
+                       val = *((int*)(buf+j*3));\r
+                       diskInfo->FATCache[i*2] = val & 0xFFF;\r
+                       diskInfo->FATCache[i*2+1] = (val>>12) & 0xFFF;\r
+               }\r
+       }\r
+       else if(diskInfo->type == FAT16)\r
+       {\r
+               Uint16  buf[256];\r
+               for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                       if( (i & 255) == 0 ) {\r
+                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                               Ofs += 512;\r
+                       }\r
+                       diskInfo->FATCache[i] = buf[i&255];\r
+               }\r
+       }\r
+       else if(diskInfo->type == FAT32)\r
+       {\r
+               Uint32  buf[128];\r
+               for(i=0;i<diskInfo->ClusterCount;i++) {\r
+                       if( (i & 127) == 0 ) {\r
+                               VFS_ReadAt(diskInfo->fileHandle, Ofs, 512, buf);\r
+                               Ofs += 512;\r
+                       }\r
+                       diskInfo->FATCache[i] = buf[i&127];\r
+               }\r
+       }\r
+       LOG("FAT Fully Cached");\r
+       }\r
+       #endif /*CACHE_FAT*/\r
+       \r
+       diskInfo->BytesPerCluster = bs->spc * bs->bps;\r
+       \r
+       // Initalise inode cache for filesystem\r
+       diskInfo->inodeHandle = Inode_GetHandle();\r
+       LOG("Inode Cache handle is %i", diskInfo->inodeHandle);\r
+       \r
+       // == VFS Interface\r
+       node = &diskInfo->rootNode;\r
+       node->Size = bs->files_in_root;\r
+       node->Inode = diskInfo->rootOffset;     // 0:31 - Cluster, 32:63 - Parent Directory Cluster\r
+       node->ImplPtr = diskInfo;       // Disk info pointer\r
+       node->ImplInt = 0;      // 0:15 - Directory Index, 16: Dirty Flag\r
+       \r
+       node->ReferenceCount = 1;\r
+       \r
+       node->UID = 0;  node->GID = 0;\r
+       node->NumACLs = 1;\r
+       node->ACLs = &gVFS_ACL_EveryoneRWX;\r
+       node->Flags = VFS_FFLAG_DIRECTORY;\r
+       node->CTime = node->MTime = node->ATime = now();\r
+       \r
+       node->Read = node->Write = NULL;\r
+       node->ReadDir = FAT_ReadDir;\r
+       node->FindDir = FAT_FindDir;\r
+       node->Relink = FAT_Relink;\r
+       node->MkNod = FAT_Mknod;\r
+       //node->Close = FAT_Unmount;\r
+       \r
+       giFAT_PartCount ++;\r
+       return node;\r
+}\r
+\r
+/**\r
+ * \brief Closes a mount and marks it as free\r
+ * \param Node Mount Root\r
+ * \r
+ * \todo Remove FAT Cache\r
+ * \todo Clear LFN Cache\r
+ * \todo Check that all files are closed and flushed\r
+ */\r
+void FAT_Unmount(tVFS_Node *Node)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       // Close Disk Handle\r
+       VFS_Close( disk->fileHandle );\r
+       // Clear Node Cache\r
+       Inode_ClearCache(disk->inodeHandle);\r
+       // Mark as unused\r
+       disk->fileHandle = -2;\r
+       return;\r
+}\r
+\r
+/*\r
+ * === FILE IO ===\r
+ */\r
+/**\r
+ * \fn Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
+ * \brief Fetches a value from the FAT\r
+ */\r
+Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 cluster)\r
+{\r
+       Uint32  val = 0;\r
+       #if !CACHE_FAT\r
+       Uint32  ofs = Disk->bootsect.resvSectCount*512;\r
+       #endif\r
+       ENTER("pDisk xCluster", Disk, cluster);\r
+       LOCK( &Disk->lFAT );\r
+       #if CACHE_FAT\r
+       val = Disk->FATCache[cluster];\r
+       if(Disk->type == FAT12 && val == EOC_FAT12)     val = -1;\r
+       if(Disk->type == FAT16 && val == EOC_FAT16)     val = -1;\r
+       if(Disk->type == FAT32 && val == EOC_FAT32)     val = -1;\r
+       #else\r
+       if(Disk->type == FAT12) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+(cluster>>1)*3, 3, &val);\r
+               val = (cluster&1 ? val&0xFFF : val>>12);\r
+               if(val == EOC_FAT12)    val = -1;\r
+       } else if(Disk->type == FAT16) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);\r
+               if(val == EOC_FAT16)    val = -1;\r
+       } else {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);\r
+               if(val == EOC_FAT32)    val = -1;\r
+       }\r
+       #endif /*CACHE_FAT*/\r
+       RELEASE( &Disk->lFAT );\r
+       LEAVE('x', val);\r
+       return val;\r
+}\r
+\r
+/**\r
+ * \brief Allocate a new cluster\r
+ */\r
+Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous)\r
+{\r
+       Uint32  ret = Previous;\r
+       #if CACHE_FAT\r
+       Uint32  eoc;\r
+       \r
+       LOCK(Disk->lFAT);\r
+       for(ret = Previous; ret < Disk->ClusterCount; ret++)\r
+       {\r
+               if(Disk->FATCache[ret] == 0)\r
+                       goto append;\r
+       }\r
+       for(ret = 0; ret < Previous; ret++)\r
+       {\r
+               if(Disk->FATCache[ret] == 0)\r
+                       goto append;\r
+       }\r
+       \r
+       RELEASE(Disk->lFAT);\r
+       return 0;\r
+       \r
+append:\r
+       switch(Disk->type)\r
+       {\r
+       case FAT12:     eoc = EOC_FAT12;        break;\r
+       case FAT16:     eoc = EOC_FAT16;        break;\r
+       case FAT32:     eoc = EOC_FAT32;        break;\r
+       default:        return 0;\r
+       }\r
+       \r
+       Disk->FATCache[ret] = eoc;\r
+       Disk->FATCache[Previous] = ret;\r
+       \r
+       RELEASE(Disk->lFAT);\r
+       return ret;\r
+       #else\r
+       Uint32  val;\r
+       //Uint8 buf[512];\r
+       Warning("[FAT  ] TODO: Implement cluster allocation with non cached FAT");\r
+       return 0;\r
+       \r
+       if(Disk->type == FAT12) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+               if( Previous & 1 ) {\r
+                       val &= 0xFFF000;\r
+                       val |= ret;\r
+               }\r
+               else {\r
+                       val &= 0xFFF;\r
+                       val |= ret<<12;\r
+               }\r
+               VFS_WriteAt(Disk->fileHandle, ofs+(Previous>>1)*3, 3, &val);\r
+               \r
+               VFS_ReadAt(Disk->fileHandle, ofs+(Cluster>>1)*3, 3, &val);\r
+               if( Cluster & 1 ) {\r
+                       val &= 0xFFF000;\r
+                       val |= eoc;\r
+               }\r
+               else {\r
+                       val &= 0x000FFF;\r
+                       val |= eoc<<12;\r
+               }\r
+               VFS_WriteAt(Disk->fileHandle, ofs+(Cluster>>1)*3, 3, &val);\r
+       } else if(Disk->type == FAT16) {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+Previous*2, 2, &ret);\r
+               VFS_ReadAt(Disk->fileHandle, ofs+Cluster*2, 2, &eoc);\r
+       } else {\r
+               VFS_ReadAt(Disk->fileHandle, ofs+Previous*4, 4, &ret);\r
+               VFS_ReadAt(Disk->fileHandle, ofs+Cluster*4, 4, &eoc);\r
+       }\r
+       return ret;\r
+       #endif\r
+}\r
+\r
+/**\r
+ * \brief Read a cluster\r
+ */\r
+void FAT_int_ReadCluster(tFAT_VolInfo *Disk, Uint32 Cluster, int Length, void *Buffer)\r
+{\r
+       ENTER("pDisk xCluster iLength pBuffer", Disk, Cluster, Length, Buffer);\r
+       //Log("Cluster = %i (0x%x)", Cluster, Cluster);\r
+       VFS_ReadAt(\r
+               Disk->fileHandle,\r
+               (Disk->firstDataSect + (Cluster-2)*Disk->bootsect.spc )\r
+                       * Disk->bootsect.bps,\r
+               Length,\r
+               Buffer\r
+               );\r
+       LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \brief Write a cluster to disk\r
+ */\r
+void FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, void *Buffer)\r
+{\r
+       ENTER("pDisk xCluster pBuffer", Disk, Cluster, Buffer);\r
+       VFS_ReadAt(\r
+               Disk->fileHandle,\r
+               (Disk->firstDataSect + (Cluster-2)*Disk->bootsect.spc )\r
+                       * Disk->bootsect.bps,\r
+               Disk->BytesPerCluster,\r
+               Buffer\r
+               );\r
+       LEAVE('-');\r
+}\r
+\r
+/**\r
+ * \fn Uint64 FAT_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer)\r
+ * \brief Reads data from a specified file\r
+ */\r
+Uint64 FAT_Read(tVFS_Node *Node, Uint64 offset, Uint64 length, void *buffer)\r
+{\r
+        int    preSkip, count;\r
+        int    i, cluster, pos;\r
+        int    bpc;\r
+       void    *tmpBuf;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       \r
+       ENTER("pNode Xoffset Xlength pbuffer", Node, offset, length, buffer);\r
+       \r
+       // Calculate and Allocate Bytes Per Cluster\r
+       bpc = disk->BytesPerCluster;\r
+       tmpBuf = (void*) malloc(bpc);\r
+       if( !tmpBuf )   return 0;\r
+       \r
+       // Cluster is stored in Inode Field\r
+       cluster = Node->Inode & 0xFFFFFFFF;\r
+       \r
+       // Sanity Check offset\r
+       if(offset > Node->Size) {\r
+               //LOG("Reading past EOF (%i > %i)", offset, node->Size);\r
+               LEAVE('i', 0);\r
+               return 0;\r
+       }\r
+       // Clamp Size\r
+       if(offset + length > Node->Size) {\r
+               //LOG("Reading past EOF (%lli + %lli > %lli), clamped to %lli",\r
+               //      offset, length, node->Size, node->Size - offset);\r
+               length = Node->Size - offset;\r
+       }\r
+       \r
+       // Single Cluster including offset\r
+       if(length + offset < bpc)\r
+       {\r
+               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+               memcpy( buffer, (void*)( tmpBuf + offset%bpc ), length );\r
+               free(tmpBuf);\r
+               LEAVE('i', 1);\r
+               return length;\r
+       }\r
+       \r
+       preSkip = offset / bpc;\r
+       \r
+       //Skip previous clusters\r
+       for(i=preSkip;i--;)     {\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
+                       Warning("FAT_Read - Offset is past end of cluster chain mark");\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+       }\r
+       \r
+       // Get Count of Clusters to read\r
+       count = ((offset%bpc+length) / bpc) + 1;\r
+       \r
+       // Get buffer Position after 1st cluster\r
+       pos = bpc - offset%bpc;\r
+       \r
+       // Read 1st Cluster\r
+       FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+       memcpy(\r
+               buffer,\r
+               (void*)( tmpBuf + (bpc-pos) ),\r
+               (pos < length ? pos : length)\r
+               );\r
+       \r
+       if (count == 1) {\r
+               free(tmpBuf);\r
+               LEAVE('i', 1);\r
+               return length;\r
+       }\r
+       \r
+       cluster = FAT_int_GetFatValue(disk, cluster);\r
+       \r
+       #if DEBUG\r
+       LOG("pos=%i\n", pos);\r
+       LOG("Reading the rest of the clusters\n");\r
+       #endif\r
+       \r
+       \r
+       //Read the rest of the cluster data\r
+       for( i = 1; i < count-1; i++ )\r
+       {\r
+               FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+               memcpy((void*)(buffer+pos), tmpBuf, bpc);\r
+               pos += bpc;\r
+               cluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(cluster == -1) {\r
+                       Warning("FAT_Read - Read past End of Cluster Chain");\r
+                       free(tmpBuf);\r
+                       LEAVE('i', 0);\r
+                       return 0;\r
+               }\r
+       }\r
+       \r
+       FAT_int_ReadCluster(disk, cluster, bpc, tmpBuf);\r
+       memcpy((void*)(buffer+pos), tmpBuf, length-pos);\r
+       \r
+       #if DEBUG\r
+       LOG("Free tmpBuf(0x%x) and Return\n", tmpBuf);\r
+       #endif\r
+       \r
+       free(tmpBuf);\r
+       LEAVE('X', length);\r
+       return length;\r
+}\r
+\r
+/**\r
+ * \brief Write to a file\r
+ * \param Node File Node\r
+ * \param Offset       Offset within file\r
+ * \param Length       Size of data to write\r
+ * \param Buffer       Data source\r
+ */\r
+Uint64 FAT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       void    *tmpBuf;\r
+        int    remLength = Length;\r
+       Uint32  cluster, tmpCluster;\r
+        int    bNewCluster = 0;\r
+       \r
+       if(Offset > Node->Size) return 0;\r
+       \r
+       // Seek Clusters\r
+       cluster = Node->Inode & 0xFFFFFFFF;\r
+       while( Offset > disk->BytesPerCluster )\r
+       {\r
+               cluster = FAT_int_GetFatValue( disk, cluster );\r
+               if(cluster == -1) {\r
+                       Warning("[FAT  ] EOC Unexpectedly Reached");\r
+                       return 0;\r
+               }\r
+               Offset -= disk->BytesPerCluster;\r
+       }\r
+       if( Offset == disk->BytesPerCluster )\r
+       {\r
+               Uint32  tmp = FAT_int_AllocateCluster(disk, cluster);\r
+               if(!tmp)        return 0;\r
+               cluster = tmp;\r
+               Offset -= disk->BytesPerCluster;\r
+       }\r
+       \r
+       if( Offset + Length < disk->BytesPerCluster )\r
+       {\r
+               tmpBuf = malloc( disk->BytesPerCluster );\r
+               \r
+               // Read-Modify-Write\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+               memcpy( tmpBuf + Offset, Buffer, Length );\r
+               FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+               \r
+               free(tmpBuf);\r
+               return Length;\r
+       }\r
+       \r
+       // Clean up changes within a cluster\r
+       if( Offset )\r
+       {\r
+               tmpBuf = malloc( disk->BytesPerCluster );\r
+               \r
+               // Read-Modify-Write\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+               memcpy( tmpBuf + Offset, Buffer, disk->BytesPerCluster - Offset );\r
+               FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+               \r
+               free(tmpBuf);\r
+               \r
+               remLength -= disk->BytesPerCluster - Offset;\r
+               Buffer += disk->BytesPerCluster - Offset;\r
+               \r
+               // Get next cluster (allocating if needed)\r
+               tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(tmpCluster == -1) {\r
+                       tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
+                       if( tmpCluster == 0 ) {\r
+                               return Length - remLength;\r
+                       }\r
+               }\r
+               cluster = tmpCluster;\r
+       }\r
+       \r
+       while( remLength > disk->BytesPerCluster )\r
+       {\r
+               FAT_int_WriteCluster( disk, cluster, Buffer );\r
+               Buffer += disk->BytesPerCluster;\r
+               \r
+               // Get next cluster (allocating if needed)\r
+               tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
+               if(tmpCluster == -1) {\r
+                       bNewCluster = 1;\r
+                       tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
+                       if( tmpCluster == 0 ) {\r
+                               return Length - remLength;\r
+                       }\r
+               }\r
+               cluster = tmpCluster;\r
+       }\r
+       \r
+       // Finish off\r
+       tmpBuf = malloc( disk->BytesPerCluster );\r
+       if( bNewCluster )\r
+               memset(tmpBuf, 0, disk->BytesPerCluster);\r
+       else\r
+               FAT_int_ReadCluster( disk, cluster, disk->BytesPerCluster, tmpBuf );\r
+       memcpy( tmpBuf, Buffer, remLength );\r
+       FAT_int_WriteCluster( disk, cluster, tmpBuf );\r
+       free( tmpBuf );\r
+       \r
+       return Length;\r
+}\r
+\r
+/**\r
+ * \fn void FAT_int_ProperFilename(char *dest, char *src)\r
+ * \brief Converts a FAT directory entry name into a proper filename\r
+ */\r
+void FAT_int_ProperFilename(char *dest, char *src)\r
+{\r
+        int    a, b;\r
+       \r
+       for( a = 0; a < 8; a++) {\r
+               if(src[a] == ' ')       break;\r
+               dest[a] = src[a];\r
+       }\r
+       b = a;\r
+       a = 8;\r
+       if(src[8] != ' ')\r
+               dest[b++] = '.';\r
+       for( ; a < 11; a++, b++)        {\r
+               if(src[a] == ' ')       break;\r
+               dest[b] = src[a];\r
+       }\r
+       dest[b] = '\0';\r
+       #if DEBUG\r
+       //LOG("dest='%s'", dest);\r
+       #endif\r
+}\r
+\r
+/**\r
+ * \fn char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
+ * \brief Converts either a LFN or a 8.3 Name into a proper name\r
+ */\r
+char *FAT_int_CreateName(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
+{\r
+       char    *ret;\r
+        int    len;\r
+       #if USE_LFN\r
+       if(LongFileName && LongFileName[0] != '\0')\r
+       {       \r
+               len = strlen(LongFileName);\r
+               ret = malloc(len+1);\r
+               strcpy(ret, LongFileName);\r
+       }\r
+       else\r
+       {\r
+       #endif\r
+               ret = (char*) malloc(13);\r
+               memset(ret, 13, '\0');\r
+               FAT_int_ProperFilename(ret, ft->name);\r
+       #if USE_LFN\r
+       }\r
+       #endif\r
+       return ret;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
+ * \brief Creates a tVFS_Node structure for a given file entry\r
+ */\r
+tVFS_Node *FAT_int_CreateNode(tVFS_Node *parent, fat_filetable *ft, char *LongFileName)\r
+{\r
+       tVFS_Node       node = {0};\r
+       tVFS_Node       *ret;\r
+       tFAT_VolInfo    *disk = parent->ImplPtr;\r
+       \r
+       ENTER("pParent pFT sLongFileName", parent, ft, LongFileName);\r
+       \r
+       // Set Other Data\r
+       node.Inode = ft->cluster | (ft->clusterHi<<16);\r
+       node.Size = ft->size;\r
+       LOG("ft->size = %i", ft->size);\r
+       node.ImplPtr = parent->ImplPtr;\r
+       node.UID = 0;   node.GID = 0;\r
+       node.NumACLs = 1;\r
+       \r
+       node.Flags = 0;\r
+       if(ft->attrib & ATTR_DIRECTORY) node.Flags |= VFS_FFLAG_DIRECTORY;\r
+       if(ft->attrib & ATTR_READONLY) {\r
+               node.Flags |= VFS_FFLAG_READONLY;\r
+               node.ACLs = &gVFS_ACL_EveryoneRX;       // R-XR-XR-X\r
+       }\r
+       else {\r
+               node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX\r
+       }\r
+       \r
+       node.ATime = timestamp(0,0,0,\r
+                       ((ft->adate&0x1F)-1),   //Days\r
+                       ((ft->adate&0x1E0)-1),          //Months\r
+                       1980+((ft->adate&0xFF00)>>8));  //Years\r
+       \r
+       node.CTime = ft->ctimems * 10;  //Miliseconds\r
+       node.CTime += timestamp(\r
+                       (ft->ctime&0x1F)<<1,    //Seconds\r
+                       ((ft->ctime&0x3F0)>>5), //Minutes\r
+                       ((ft->ctime&0xF800)>>11),       //Hours\r
+                       ((ft->cdate&0x1F)-1),           //Days\r
+                       ((ft->cdate&0x1E0)-1),          //Months\r
+                       1980+((ft->cdate&0xFF00)>>8));  //Years\r
+                       \r
+       node.MTime = timestamp(\r
+                       (ft->mtime&0x1F)<<1,    //Seconds\r
+                       ((ft->mtime&0x3F0)>>5), //Minuites\r
+                       ((ft->mtime&0xF800)>>11),       //Hours\r
+                       ((ft->mdate&0x1F)-1),           //Days\r
+                       ((ft->mdate&0x1E0)-1),          //Months\r
+                       1980+((ft->mdate&0xFF00)>>8));  //Years\r
+       \r
+       if(node.Flags & VFS_FFLAG_DIRECTORY) {\r
+               node.ReadDir = FAT_ReadDir;\r
+               node.FindDir = FAT_FindDir;\r
+               node.MkNod = FAT_Mknod;\r
+               node.Size = -1;\r
+       } else {\r
+               node.Read = FAT_Read;\r
+               node.Write = FAT_Write;\r
+       }\r
+       node.Close = FAT_CloseFile;\r
+       node.Relink = FAT_Relink;\r
+       \r
+       ret = Inode_CacheNode(disk->inodeHandle, &node);\r
+       LEAVE('p', ret);\r
+       return ret;\r
+}\r
+\r
+#if USE_LFN\r
+/**\r
+ \fn char *FAT_int_GetLFN(tVFS_Node *node)\r
+ \brief Return pointer to LFN cache entry\r
+ */\r
+char *FAT_int_GetLFN(tVFS_Node *node)\r
+{\r
+       t_lfncache      *tmp;\r
+       tmp = fat_lfncache;\r
+       while(tmp)\r
+       {\r
+               if(tmp->Inode == node->Inode && tmp->Disk == node->ImplPtr)\r
+                       return tmp->Name;\r
+               tmp = tmp->Next;\r
+       }\r
+       tmp = malloc(sizeof(t_lfncache));\r
+       tmp->Inode = node->Inode;\r
+       tmp->Disk = node->ImplPtr;\r
+       memset(tmp->Name, 0, 256);\r
+       \r
+       tmp->Next = fat_lfncache;\r
+       fat_lfncache = tmp;\r
+       \r
+       return tmp->Name;\r
+}\r
+\r
+/**\r
+ \fn void FAT_int_DelLFN(tVFS_Node *node)\r
+ \brief Delete a LFN cache entry\r
+*/\r
+void FAT_int_DelLFN(tVFS_Node *node)\r
+{\r
+       t_lfncache      *tmp;\r
+       \r
+       if(!fat_lfncache)       return;\r
+       \r
+       if(!fat_lfncache->Next)\r
+       {\r
+               tmp = fat_lfncache;\r
+               fat_lfncache = tmp->Next;\r
+               free(tmp);\r
+               return;\r
+       }\r
+       tmp = fat_lfncache;\r
+       while(tmp && tmp->Next)\r
+       {\r
+               if(tmp->Inode == node->Inode && tmp->Disk == node->ImplPtr)\r
+               {\r
+                       free(tmp->Next);\r
+                       tmp->Next = tmp->Next->Next;\r
+                       return;\r
+               }\r
+               tmp = tmp->Next;\r
+       }\r
+}\r
+#endif\r
+\r
+/**\r
+ \fn char *FAT_ReadDir(tVFS_Node *Node, int ID)\r
+ \param Node   Node structure of directory\r
+ \param ID     Directory position\r
+**/\r
+char *FAT_ReadDir(tVFS_Node *Node, int ID)\r
+{\r
+       fat_filetable   fileinfo[16];   //Sizeof=32, 16 per sector\r
+        int    a=0;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       Uint32  cluster, offset;\r
+        int    preSkip;\r
+       char    *ret;\r
+       #if USE_LFN\r
+       char    *lfn = NULL;\r
+       #endif\r
+       \r
+       ENTER("pNode iID", Node, ID);\r
+       \r
+       // Get Byte Offset and skip\r
+       offset = ID * sizeof(fat_filetable);\r
+       preSkip = offset / (512 * disk->bootsect.spc);\r
+       LOG("disk->bootsect.spc = %i", disk->bootsect.spc);\r
+       LOG("Node->size = %i", Node->Size);\r
+       cluster = Node->Inode & 0xFFFFFFFF;     // Cluster ID\r
+       \r
+       // Do Cluster Skip\r
+       // - Pre FAT32 had a reserved area for the root.\r
+       if( disk->type == FAT32 || cluster != disk->rootOffset )\r
+       {\r
+               //Skip previous clusters\r
+               for(a=preSkip;a--;)     {\r
+                       cluster = FAT_int_GetFatValue(disk, cluster);\r
+                       // Check for end of cluster chain\r
+                       if(cluster == -1) {     LEAVE('n');     return NULL;}\r
+               }\r
+       }\r
+       \r
+       // Bounds Checking (Used to spot heap overflows)\r
+       if(cluster > disk->ClusterCount + 2)\r
+       {\r
+               Warning("FAT_ReadDir - Cluster ID is over cluster count (0x%x>0x%x)",\r
+                       cluster, disk->ClusterCount+2);\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       LOG("cluster=0x%x, ID=%i", cluster, ID);\r
+       \r
+       // Compute Offsets\r
+       // - Pre FAT32 cluster base (in sectors)\r
+       if( cluster == disk->rootOffset && disk->type != FAT32 )\r
+               offset = disk->bootsect.resvSectCount + cluster*disk->bootsect.spc;\r
+       else\r
+       {       // FAT32 cluster base (in sectors)\r
+               offset = disk->firstDataSect;\r
+               offset += (cluster - 2) * disk->bootsect.spc;\r
+       }\r
+       // Sector in cluster\r
+       if(disk->bootsect.spc != 1)\r
+               offset += (ID / 16) % disk->bootsect.spc;\r
+       // Offset in sector\r
+       a = ID % 16;\r
+\r
+       LOG("offset=%i, a=%i", offset, a);\r
+       \r
+       // Read Sector\r
+       VFS_ReadAt(disk->fileHandle, offset*512, 512, fileinfo);        // Read Dir Data\r
+       \r
+       LOG("name[0] = 0x%x", (Uint8)fileinfo[a].name[0]);\r
+       //Check if this is the last entry\r
+       if( fileinfo[a].name[0] == '\0' ) {\r
+               Node->Size = ID;\r
+               LOG("End of list");\r
+               LEAVE('n');\r
+               return NULL;    // break\r
+       }\r
+       \r
+       // Check for empty entry\r
+       if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {\r
+               LOG("Empty Entry");\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;        // Skip\r
+       }\r
+       \r
+       #if USE_LFN\r
+       // Get Long File Name Cache\r
+       lfn = FAT_int_GetLFN(Node);\r
+       if(fileinfo[a].attrib == ATTR_LFN)\r
+       {\r
+               fat_longfilename        *lfnInfo;\r
+                int    len;\r
+               \r
+               lfnInfo = (fat_longfilename *) &fileinfo[a];\r
+               if(lfnInfo->id & 0x40)  memset(lfn, 0, 256);\r
+               // Get the current length\r
+               len = strlen(lfn);\r
+               \r
+               // Sanity Check (FAT implementations should not allow >255 bytes)\r
+               if(len + 13 > 255)      return VFS_SKIP;\r
+               // Rebase all bytes\r
+               for(a=len+1;a--;)       lfn[a+13] = lfn[a];\r
+               \r
+               // Append new bytes\r
+               lfn[ 0] = lfnInfo->name1[0];    lfn[ 1] = lfnInfo->name1[1];\r
+               lfn[ 2] = lfnInfo->name1[2];    lfn[ 3] = lfnInfo->name1[3];\r
+               lfn[ 4] = lfnInfo->name1[4];    \r
+               lfn[ 5] = lfnInfo->name2[0];    lfn[ 6] = lfnInfo->name2[1];\r
+               lfn[ 7] = lfnInfo->name2[2];    lfn[ 8] = lfnInfo->name2[3];\r
+               lfn[ 9] = lfnInfo->name2[4];    lfn[10] = lfnInfo->name2[5];\r
+               lfn[11] = lfnInfo->name3[0];    lfn[12] = lfnInfo->name3[1];\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }\r
+       #endif\r
+       \r
+       //Check if it is a volume entry\r
+       if(fileinfo[a].attrib & 0x08) {\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }\r
+       // Ignore . and ..\r
+       if(fileinfo[a].name[0] == '.') {\r
+               LEAVE('p', VFS_SKIP);\r
+               return VFS_SKIP;\r
+       }       \r
+       \r
+       LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'\n",\r
+               fileinfo[a].name[0], fileinfo[a].name[1], fileinfo[a].name[2], fileinfo[a].name[3],\r
+               fileinfo[a].name[4], fileinfo[a].name[5], fileinfo[a].name[6], fileinfo[a].name[7],\r
+               fileinfo[a].name[8], fileinfo[a].name[9], fileinfo[a].name[10] );\r
+       \r
+       #if USE_LFN\r
+       //node = FAT_int_CreateNode(Node, &fileinfo[a], lfn);\r
+       ret = FAT_int_CreateName(Node, &fileinfo[a], lfn);\r
+       lfn[0] = '\0';\r
+       #else\r
+       //node = FAT_int_CreateNode(Node, &fileinfo[a], NULL);\r
+       ret = FAT_int_CreateName(Node, &fileinfo[a], NULL);\r
+       #endif\r
+       \r
+       LEAVE('s', ret);\r
+       return ret;\r
+}\r
+\r
+/**\r
+ * \fn tVFS_Node *FAT_FindDir(tVFS_Node *node, char *name)\r
+ * \brief Finds an entry in the current directory\r
+ */\r
+tVFS_Node *FAT_FindDir(tVFS_Node *Node, char *name)\r
+{\r
+       fat_filetable   fileinfo[16];\r
+       char    tmpName[11];\r
+       #if USE_LFN\r
+       fat_longfilename        *lfnInfo;\r
+       char    *lfn = NULL;\r
+        int    lfnPos=255, lfnId = -1;\r
+       #endif\r
+        int    i=0;\r
+       tVFS_Node       *tmpNode;\r
+       Uint64  diskOffset;\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       Uint32  dirCluster;\r
+       Uint32  cluster;\r
+       \r
+       ENTER("pNode sname", Node, name);\r
+       \r
+       // Fast Returns\r
+       if(!name || name[0] == '\0') {\r
+               LEAVE('n');\r
+               return NULL;\r
+       }\r
+       \r
+       #if USE_LFN\r
+       lfn = FAT_int_GetLFN(Node);\r
+       #endif\r
+       \r
+       dirCluster = Node->Inode & 0xFFFFFFFF;\r
+       // Seek to Directory\r
+       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
+               diskOffset = (disk->bootsect.resvSectCount+dirCluster*disk->bootsect.spc) << 9;\r
+       else\r
+               diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc) << 9;\r
+       \r
+       for(;;i++)\r
+       {\r
+               // Load sector\r
+               if((i & 0xF) == 0) {\r
+                       //Log("FAT_FindDir: diskOffset = 0x%x", diskOffset);\r
+                       VFS_ReadAt(disk->fileHandle, diskOffset, 512, fileinfo);\r
+                       diskOffset += 512;\r
+               }\r
+               \r
+               //Check if the files are free\r
+               if(fileinfo[i&0xF].name[0] == '\0')     break;          //Free and last\r
+               if(fileinfo[i&0xF].name[0] == '\xE5')   goto loadCluster;       //Free\r
+               \r
+               \r
+               #if USE_LFN\r
+               // Long File Name Entry\r
+               if(fileinfo[i&0xF].attrib == ATTR_LFN)\r
+               {\r
+                       lfnInfo = (fat_longfilename *) &fileinfo[i&0xF];\r
+                       if(lfnInfo->id & 0x40) {\r
+                               memset(lfn, 0, 256);\r
+                               lfnPos = 255;\r
+                       }\r
+                       lfn[lfnPos--] = lfnInfo->name3[1];      lfn[lfnPos--] = lfnInfo->name3[0];\r
+                       lfn[lfnPos--] = lfnInfo->name2[5];      lfn[lfnPos--] = lfnInfo->name2[4];\r
+                       lfn[lfnPos--] = lfnInfo->name2[3];      lfn[lfnPos--] = lfnInfo->name2[2];\r
+                       lfn[lfnPos--] = lfnInfo->name2[1];      lfn[lfnPos--] = lfnInfo->name2[0];\r
+                       lfn[lfnPos--] = lfnInfo->name1[4];      lfn[lfnPos--] = lfnInfo->name1[3];\r
+                       lfn[lfnPos--] = lfnInfo->name1[2];      lfn[lfnPos--] = lfnInfo->name1[1];\r
+                       lfn[lfnPos--] = lfnInfo->name1[0];\r
+                       if((lfnInfo->id&0x3F) == 1)\r
+                       {\r
+                               memcpy(lfn, lfn+lfnPos+1, 256-lfnPos);\r
+                               lfnId = i+1;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // Remove LFN if it does not apply\r
+                       if(lfnId != i)  lfn[0] = '\0';\r
+               #endif\r
+                       // Get Real Filename\r
+                       FAT_int_ProperFilename(tmpName, fileinfo[i&0xF].name);\r
+               \r
+                       LOG("tmpName = '%s'", tmpName);\r
+               \r
+                       //Only Long name is case sensitive, 8.3 is not\r
+                       #if USE_LFN\r
+                       if(strucmp(tmpName, name) == 0 || strcmp(lfn, name) == 0) {\r
+                       #else\r
+                       if(strucmp(tmpName, name) == 0) {\r
+                       #endif\r
+                               cluster = fileinfo[i&0xF].cluster | (fileinfo[i&0xF].clusterHi << 16);\r
+                               tmpNode = Inode_GetCache(disk->inodeHandle, cluster);\r
+                               if(tmpNode == NULL)     // Node is not cached\r
+                               {\r
+                                       #if USE_LFN\r
+                                       tmpNode = FAT_int_CreateNode(Node, &fileinfo[i&0xF], lfn);\r
+                                       #else\r
+                                       tmpNode = FAT_int_CreateNode(Node, &fileinfo[i&0xF], NULL);\r
+                                       #endif\r
+                               }\r
+                               #if USE_LFN\r
+                               lfn[0] = '\0';\r
+                               #endif\r
+                               LEAVE('p', tmpNode);\r
+                               return tmpNode;\r
+                       }\r
+               #if USE_LFN\r
+               }\r
+               #endif\r
+               \r
+       loadCluster:\r
+               //Load Next cluster?\r
+               if( ((i+1) >> 4) % disk->bootsect.spc == 0 && ((i+1) & 0xF) == 0)\r
+               {\r
+                       if( dirCluster == disk->rootOffset && disk->type != FAT32 )\r
+                               continue;\r
+                       dirCluster = FAT_int_GetFatValue(disk, dirCluster);\r
+                       if(dirCluster == -1)    break;\r
+                       diskOffset = (disk->firstDataSect+(dirCluster-2)*disk->bootsect.spc)*512;\r
+               }\r
+       }\r
+       \r
+       LEAVE('n');\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * \fn int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
+ * \brief Create a new node\r
+ */\r
+int FAT_Mknod(tVFS_Node *Node, char *Name, Uint Flags)\r
+{\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \fn int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
+ * \brief Rename / Delete a file\r
+ */\r
+int FAT_Relink(tVFS_Node *Node, char *OldName, char *NewName)\r
+{\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \fn void FAT_CloseFile(tVFS_Node *Node)\r
+ * \brief Close an open file\r
+ */\r
+void FAT_CloseFile(tVFS_Node *Node)\r
+{\r
+       tFAT_VolInfo    *disk = Node->ImplPtr;\r
+       if(Node == NULL)        return ;\r
+       \r
+       Inode_UncacheNode(disk->inodeHandle, Node->Inode);\r
+       #if USE_LFN\r
+       // If node has been uncached and is a directory, delete the LFN cache\r
+       if(     !Inode_GetCache(disk->inodeHandle, Node->Inode) && Node->Flags & VFS_FFLAG_DIRECTORY)\r
+               FAT_int_DelLFN(Node);\r
+       else    // Get Cache references the node, so dereference it\r
+               Inode_UncacheNode(disk->inodeHandle, Node->Inode);\r
+       #endif\r
+       return ;\r
+}\r
+\r
+/**\r
+ * \fn void fat_install()\r
+ * \brief Add the FAT Filesystem to the VFS\r
+ */\r
+void fat_install()\r
+{\r
+       VFS_AddDriver( &gFAT_FSInfo );\r
+}\r
diff --git a/Modules/Filesystems/FAT/fs_fat.h b/Modules/Filesystems/FAT/fs_fat.h
new file mode 100644 (file)
index 0000000..84eee1d
--- /dev/null
@@ -0,0 +1,169 @@
+/*\r
+ * Acess2\r
+ * FAT12/16/32 Driver\r
+ * vfs/fs/fs_fat.h\r
+ */\r
+#ifndef _FS_FAT_H_\r
+#define _FS_FAT_H_\r
+\r
+// === On Disk Structures ===\r
+/**\r
+ * \struct fat_bootsect_s\r
+ * \brief Bootsector format\r
+ */\r
+struct fat_bootsect_s\r
+{\r
+       Uint8   jmp[3]; //!< Jump Instruction\r
+       char    oemname[8];     //!< OEM Name. Typically MSDOS1.1\r
+       Uint16  bps;    //!< Bytes per Sector. Assumed to be 512\r
+       Uint8   spc;            //!< Sectors per Cluster\r
+       Uint16  resvSectCount;  //!< Number of reserved sectors at beginning of volume\r
+       Uint8   fatCount;       //!< Number of copies of the FAT\r
+       Uint16  files_in_root;  //!< Count of files in the root directory\r
+       Uint16  totalSect16;    //!< Total sector count (FAT12/16)\r
+       Uint8   mediaDesc;      //!< Media Desctiptor\r
+       Uint16  fatSz16;        //!< FAT Size (FAT12/16)\r
+       Uint16  spt;    //!< Sectors per track. Ignored (Acess uses LBA)\r
+       Uint16  heads;  //!< Heads. Ignored (Acess uses LBA)\r
+       Uint32  hiddenCount;    //!< ???\r
+       Uint32  totalSect32;    //!< Total sector count (FAT32)\r
+       union {\r
+               struct {\r
+                       Uint8   drvNum; //!< Drive Number. BIOS Drive ID (E.g. 0x80)\r
+                       Uint8   resv;   //!< Reserved byte\r
+                       Uint8   bootSig;        //!< Boot Signature. ???\r
+                       Uint32  volId;  //!< Volume ID\r
+                       char    label[11];      //!< Disk Label\r
+                       char    fsType[8];      //!< FS Type. ???\r
+               } __attribute__((packed)) fat16;        //!< FAT16 Specific information\r
+               struct {\r
+                       Uint32  fatSz32;        //!< 32-Bit FAT Size\r
+                       Uint16  extFlags;       //!< Extended flags\r
+                       Uint16  fsVer;  //!< Filesystem Version\r
+                       Uint32  rootClust;      //!< Root Cluster ID\r
+                       Uint16  fsInfo; //!< FS Info. ???\r
+                       Uint16  backupBS;       //!< Backup Bootsector Sector Offset\r
+                       char    resv[12];       //!< Reserved Data\r
+                       Uint8   drvNum; //!< Drive Number\r
+                       char    resv2;  //!< Reserved Data\r
+                       Uint8   bootSig;        //!< Boot Signature. ???\r
+                       Uint32  volId;  //!< Volume ID\r
+                       char    label[11];      //!< Disk Label\r
+                       char    fsType[8];      //!< Filesystem Type. ???\r
+               } __attribute__((packed)) fat32;        //!< FAT32 Specific Information\r
+       }__attribute__((packed)) spec;  //!< Non Shared Data\r
+       char pad[512-90];       //!< Bootsector Data (Code/Boot Signature 0xAA55)\r
+} __attribute__((packed));\r
+\r
+/**\r
+ \struct fat_filetable_s\r
+ \brief Format of a 8.3 file entry on disk\r
+*/\r
+struct fat_filetable_s {\r
+       char    name[11];       //!< 8.3 Name\r
+       Uint8   attrib; //!< File Attributes.\r
+       Uint8   ntres;  //!< Reserved for NT - Set to 0\r
+       Uint8   ctimems;        //!< 10ths of a second ranging from 0-199 (2 seconds)\r
+       Uint16  ctime;  //!< Creation Time\r
+       Uint16  cdate;  //!< Creation Date\r
+       Uint16  adate;  //!< Accessed Data. No Time feild though\r
+       Uint16  clusterHi;      //!< High Cluster. 0 for FAT12 and FAT16\r
+       Uint16  mtime;  //!< Last Modified Time\r
+       Uint16  mdate;  //!< Last Modified Date\r
+       Uint16  cluster;        //!< Low Word of First cluster\r
+       Uint32  size;   //!< Size of file\r
+} __attribute__((packed));\r
+\r
+/**\r
+ \struct fat_longfilename_s\r
+ \brief Format of a long file name entry on disk\r
+*/\r
+struct fat_longfilename_s {\r
+       Uint8   id;     //!< ID of entry. Bit 6 is set for last entry\r
+       Uint16  name1[5];       //!< 5 characters of name\r
+       Uint8   attrib; //!< Attributes. Must be ATTR_LFN\r
+       Uint8   type;   //!< Type. ???\r
+       Uint8   checksum;       //!< Checksum\r
+       Uint16  name2[6];       //!< 6 characters of name\r
+       Uint16  firstCluster;   //!< Used for non LFN compatability. Set to 0\r
+       Uint16  name3[2];       //!< Last 2 characters of name\r
+} __attribute__((packed));\r
+\r
+/**\r
+ * \name File Attributes\r
+ * \brief Flag values for ::fat_filetable_s.attrib\r
+ * \{\r
+ */\r
+#define ATTR_READONLY  0x01    //!< Read-only file\r
+#define ATTR_HIDDEN            0x02    //!< Hidden File\r
+#define ATTR_SYSTEM            0x04    //!< System File\r
+#define ATTR_VOLUMEID  0x08    //!< Volume ID (Deprecated)\r
+#define ATTR_DIRECTORY 0x10    //!< Directory\r
+/**\r
+ * \brief File needs archiving\r
+ * \note User set flag, no significance to the FS driver\r
+ */\r
+#define ATTR_ARCHIVE   0x20\r
+/**\r
+ * \brief Meta Attribute \r
+ * \r
+ * If ::fat_filetable_s.attrib equals ATTR_LFN the file is a LFN entry\r
+ */\r
+#define        ATTR_LFN                (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMEID)\r
+/**\r
+ * \}\r
+ */\r
+\r
+/**\r
+ * \brief Internal IDs for FAT types\r
+ */\r
+enum eFatType\r
+{\r
+       FAT12,  //!< FAT12 Volume\r
+       FAT16,  //!< FAT16 Volume\r
+       FAT32,  //!< FAT32 Volume\r
+};\r
+\r
+/**\r
+ * \name End of Cluster marks\r
+ * \brief FAT values that indicate the end of a cluster chain in\r
+ *        different versions.\r
+ * \{\r
+ */\r
+#define        EOC_FAT12       0x0FFF  //!< FAT-12 Mark\r
+#define        EOC_FAT16       0xFFFF  //!< FAT-16 Mark\r
+#define        EOC_FAT32       0x00FFFFFF      //!< FAT-32 Mark\r
+/**\r
+ * \}\r
+ */\r
+\r
+typedef struct fat_bootsect_s fat_bootsect;\r
+typedef struct fat_filetable_s fat_filetable;\r
+typedef struct fat_longfilename_s fat_longfilename;\r
+\r
+// === Memory Structures ===\r
+/**\r
+ * \struct drv_fat_volinfo_s\r
+ * \brief Representation of a volume in memory\r
+ */\r
+struct drv_fat_volinfo_s\r
+{\r
+        int    fileHandle;     //!< File Handle\r
+        int    type;   //!< FAT Type. See eFatType\r
+       char    name[12];       //!< Volume Name (With NULL Terminator)\r
+       tSpinlock       lFAT;   //!< Lock to prevent double-writing to the FAT\r
+       Uint32  firstDataSect;  //!< First data sector\r
+       Uint32  rootOffset;     //!< Root Offset (clusters)\r
+       Uint32  ClusterCount;   //!< Total Cluster Count\r
+       fat_bootsect    bootsect;       //!< Boot Sector\r
+       tVFS_Node       rootNode;       //!< Root Node\r
+        int    BytesPerCluster;\r
+        int    inodeHandle;    //!< Inode Cache Handle\r
+       #if CACHE_FAT\r
+       Uint32  *FATCache;      //!< FAT Cache\r
+       #endif\r
+};\r
+\r
+typedef struct drv_fat_volinfo_s tFAT_VolInfo;\r
+\r
+#endif\r
diff --git a/Modules/Filesystems/FS_Ext2/Makefile b/Modules/Filesystems/FS_Ext2/Makefile
deleted file mode 100644 (file)
index 806e638..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#
-
-OBJ = ext2.o read.o dir.o write.o
-NAME = FS_Ext2
-
--include ../Makefile.tpl
diff --git a/Modules/Filesystems/FS_Ext2/dir.c b/Modules/Filesystems/FS_Ext2/dir.c
deleted file mode 100644 (file)
index 0ab3ed3..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file dir.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-
-// === PROTOTYPES ===
-char           *Ext2_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *Ext2_FindDir(tVFS_Node *Node, char *FileName);
- int           Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
-tVFS_Node      *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);
-
-// === CODE ===
-/**
- \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
- \brief Reads a directory entry
-*/
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
-{
-       tExt2_Inode     inode;
-       char    namebuf[EXT2_NAME_LEN+1];
-       tExt2_DirEnt    dirent;
-       Uint64  Base;   // Block's Base Address
-        int    block = 0, ofs = 0;
-        int    entNum = 0;
-       tExt2_Disk      *disk = Node->ImplPtr;
-       Uint    size;
-       
-       ENTER("pNode iPos", Node, Pos);
-       
-       // Read directory's inode
-       //Ext2_int_GetInode(Node, &inode);
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       size = inode.i_size;
-       
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
-       
-       // Find Entry
-       // Get First Block
-       // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
-       while(Pos -- && size > 0)
-       {
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
-               ofs += dirent.rec_len;
-               size -= dirent.rec_len;
-               entNum ++;
-               
-               if(ofs >= disk->BlockSize) {
-                       block ++;
-                       if( ofs > disk->BlockSize ) {
-                               Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",
-                                       entNum-1, Node->Inode);
-                       }
-                       ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
-               }
-       }
-       
-       // Check for the end of the list
-       if(size <= 0) {
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Read Entry
-       VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
-       //LOG("dirent.inode = %i", dirent.inode);
-       //LOG("dirent.rec_len = %i", dirent.rec_len);
-       //LOG("dirent.name_len = %i", dirent.name_len);
-       VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
-       namebuf[ dirent.name_len ] = '\0';      // Cap off string
-       
-       
-       // Ignore . and .. (these are done in the VFS)
-       if( (namebuf[0] == '.' && namebuf[1] == '\0')
-       ||  (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
-               LEAVE('p', VFS_SKIP);
-               return VFS_SKIP;        // Skip
-       }
-       
-       LEAVE('s', namebuf);
-       // Create new node
-       return strdup(namebuf);
-}
-
-/**
- \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)
- \brief Gets information about a file
- \param node   vfs node - Parent Node
- \param filename       String - Name of file
- \return VFS Node of file
-*/
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       char    namebuf[EXT2_NAME_LEN+1];
-       tExt2_DirEnt    dirent;
-       Uint64  Base;   // Block's Base Address
-        int    block = 0, ofs = 0;
-        int    entNum = 0;
-       Uint    size;
-       
-       // Read directory's inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       size = inode.i_size;
-       
-       // Get First Block
-       // - Do this ourselves as it is a simple operation
-       Base = inode.i_block[0] * disk->BlockSize;
-       // Find File
-       while(size > 0)
-       {
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
-               VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
-               namebuf[ dirent.name_len ] = '\0';      // Cap off string
-               // If it matches, create a node and return it
-               if(strcmp(namebuf, Filename) == 0)
-                       return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
-               // Increment pointers
-               ofs += dirent.rec_len;
-               size -= dirent.rec_len;
-               entNum ++;
-               
-               // Check for end of block
-               if(ofs >= disk->BlockSize) {
-                       block ++;
-                       if( ofs > disk->BlockSize ) {
-                               Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",
-                                       entNum-1, Node->Inode);
-                       }
-                       ofs = 0;
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
-               }
-       }
-       
-       return NULL;
-}
-
-/**
- * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
- * \brief Create a new node
- */
-int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
-{
-       return 0;
-}
-
-// ---- INTERNAL FUNCTIONS ----
-/**
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
- * \brief Create a new VFS Node
- */
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
-{
-       tExt2_Inode     inode;
-       tVFS_Node       retNode;
-       tVFS_Node       *tmpNode;
-       
-       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
-               return NULL;
-       
-       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
-               return tmpNode;
-       
-       
-       // Set identifiers
-       retNode.Inode = InodeID;
-       retNode.ImplPtr = Disk;
-       
-       // Set file length
-       retNode.Size = inode.i_size;
-       
-       // Set Access Permissions
-       retNode.UID = inode.i_uid;
-       retNode.GID = inode.i_gid;
-       retNode.NumACLs = 3;
-       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
-       
-       //  Set Function Pointers
-       retNode.Read = Ext2_Read;
-       retNode.Write = Ext2_Write;
-       retNode.Close = Ext2_CloseFile;
-       
-       switch(inode.i_mode & EXT2_S_IFMT)
-       {
-       // Symbolic Link
-       case EXT2_S_IFLNK:
-               retNode.Flags = VFS_FFLAG_SYMLINK;
-               break;
-       // Regular File
-       case EXT2_S_IFREG:
-               retNode.Flags = 0;
-               retNode.Size |= (Uint64)inode.i_dir_acl << 32;
-               break;
-       // Directory
-       case EXT2_S_IFDIR:
-               retNode.ReadDir = Ext2_ReadDir;
-               retNode.FindDir = Ext2_FindDir;
-               retNode.MkNod = Ext2_MkNod;
-               //retNode.Relink = Ext2_Relink;
-               retNode.Flags = VFS_FFLAG_DIRECTORY;
-               break;
-       // Unknown, Write protect and hide it to be safe 
-       default:
-               retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
-               break;
-       }
-       
-       // Check if the file should be hidden
-       //if(Name[0] == '.')    retNode.Flags |= VFS_FFLAG_HIDDEN;
-       
-       // Set Timestamps
-       retNode.ATime = now();
-       retNode.MTime = inode.i_mtime * 1000;
-       retNode.CTime = inode.i_ctime * 1000;
-       
-       // Save in node cache and return saved node
-       return Inode_CacheNode(Disk->CacheID, &retNode);
-}
diff --git a/Modules/Filesystems/FS_Ext2/ext2.c b/Modules/Filesystems/FS_Ext2/ext2.c
deleted file mode 100644 (file)
index c2c2df9..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*\r
- * Acess OS\r
- * Ext2 Driver Version 1\r
- */\r
-/**\r
- * \file fs/ext2.c\r
- * \brief Second Extended Filesystem Driver\r
- * \todo Implement file full write support\r
- */\r
-#define DEBUG  1\r
-#define VERBOSE        0\r
-#include "ext2_common.h"\r
-#include <modules.h>\r
-\r
-// === PROTOTYPES ===\r
- int   Ext2_Install(char **Arguments);\r
-// Interface Functions\r
-tVFS_Node      *Ext2_InitDevice(char *Device, char **Options);\r
-void           Ext2_Unmount(tVFS_Node *Node);\r
-void           Ext2_CloseFile(tVFS_Node *Node);\r
-// Internal Helpers\r
- int           Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
-Uint64         Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
-Uint32         Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
-void           Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, FS_Ext2, Ext2_Install, NULL);\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
-       };\r
-\r
-// === CODE ===\r
-\r
-/**\r
- * \fn int Ext2_Install(char **Arguments)\r
- * \brief Install the Ext2 Filesystem Driver\r
- */\r
-int Ext2_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gExt2_FSInfo );\r
-       return MODULE_ERR_OK;\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
- \brief Initializes a device to be read by by the driver\r
- \param Device String - Device to read from\r
- \param Options        NULL Terminated array of option strings\r
- \return Root Node\r
-*/\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
-{\r
-       tExt2_Disk      *disk;\r
-        int    fd;\r
-        int    groupCount;\r
-       tExt2_SuperBlock        sb;\r
-       tExt2_Inode     inode;\r
-       \r
-       ENTER("sDevice pOptions", Device, Options);\r
-       \r
-       // Open Disk\r
-       fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);            //Open Device\r
-       if(fd == -1) {\r
-               Warning("[EXT2 ] Unable to open '%s'", Device);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Read Superblock at offset 1024\r
-       VFS_ReadAt(fd, 1024, 1024, &sb);        // Read Superblock\r
-       \r
-       // Sanity Check Magic value\r
-       if(sb.s_magic != 0xEF53) {\r
-               Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Get Group count\r
-       groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
-       LOG("groupCount = %i", groupCount);\r
-       \r
-       // Allocate Disk Information\r
-       disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
-       if(!disk) {\r
-               Warning("[EXT2 ] Unable to allocate disk structure");\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       disk->FD = fd;\r
-       memcpy(&disk->SuperBlock, &sb, 1024);\r
-       disk->GroupCount = groupCount;\r
-       \r
-       // Get an inode cache handle\r
-       disk->CacheID = Inode_GetHandle();\r
-       \r
-       // Get Block Size\r
-       LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
-       disk->BlockSize = 1024 << sb.s_log_block_size;\r
-       \r
-       // Read Group Information\r
-       VFS_ReadAt(\r
-               disk->FD,\r
-               sb.s_first_data_block * disk->BlockSize + 1024,\r
-               sizeof(tExt2_Group)*groupCount,\r
-               disk->Groups\r
-               );\r
-       \r
-       #if VERBOSE\r
-       LOG("Block Group 0");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
-       LOG("Block Group 1");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
-       #endif\r
-       \r
-       // Get root Inode\r
-       Ext2_int_ReadInode(disk, 2, &inode);\r
-       \r
-       // Create Root Node\r
-       memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
-       disk->RootNode.Inode = 2;       // Root inode ID\r
-       disk->RootNode.ImplPtr = disk;  // Save disk pointer\r
-       disk->RootNode.Size = -1;       // Fill in later (on readdir)\r
-       disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
-       \r
-       disk->RootNode.ReadDir = Ext2_ReadDir;\r
-       disk->RootNode.FindDir = Ext2_FindDir;\r
-       //disk->RootNode.Relink = Ext2_Relink;\r
-       \r
-       // Complete root node\r
-       disk->RootNode.UID = inode.i_uid;\r
-       disk->RootNode.GID = inode.i_gid;\r
-       disk->RootNode.NumACLs = 1;\r
-       disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
-       \r
-       #if DEBUG\r
-       LOG("inode.i_size = 0x%x", inode.i_size);\r
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
-       #endif\r
-       \r
-       LEAVE('p', &disk->RootNode);\r
-       return &disk->RootNode;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_Unmount(tVFS_Node *Node)\r
- * \brief Close a mounted device\r
- */\r
-void Ext2_Unmount(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       \r
-       VFS_Close( disk->FD );\r
-       Inode_ClearCache( disk->CacheID );\r
-       memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
-       free(disk);\r
-}\r
-\r
-/**\r
- * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
- * \brief Close a file (Remove it from the cache)\r
- */\r
-void Ext2_CloseFile(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       Inode_UncacheNode(disk->CacheID, Node->Inode);\r
-       return ;\r
-}\r
-\r
-//==================================\r
-//=       INTERNAL FUNCTIONS       =\r
-//==================================\r
-/**\r
- * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
- * \brief Read an inode into memory\r
- */\r
-int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
-{\r
-        int    group, subId;\r
-       \r
-       //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
-       \r
-       if(InodeId == 0)        return 0;\r
-       \r
-       InodeId --;     // Inodes are numbered starting at 1\r
-       \r
-       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
-       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
-       \r
-       //LOG("group=%i, subId = %i", group, subId);\r
-       \r
-       // Read Inode\r
-       VFS_ReadAt(Disk->FD,\r
-               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
-               sizeof(tExt2_Inode),\r
-               Inode);\r
-       \r
-       //LEAVE('i', 1);\r
-       return 1;\r
-}\r
-\r
-/**\r
- * \brief Write a modified inode out to disk\r
- */\r
-int Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode)\r
-{\r
-        int    group, subId;\r
-       ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
-       \r
-       if(InodeId == 0)        return 0;\r
-       \r
-       InodeId --;     // Inodes are numbered starting at 1\r
-       \r
-       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
-       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
-       \r
-       LOG("group=%i, subId = %i", group, subId);\r
-       \r
-       // Write Inode\r
-       VFS_WriteAt(Disk->FD,\r
-               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
-               sizeof(tExt2_Inode),\r
-               Inode);\r
-       \r
-       LEAVE('i', 1);\r
-       return 1;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
- * \brief Get the address of a block from an inode's list\r
- * \param Disk Disk information structure\r
- * \param Blocks       Pointer to an inode's block list\r
- * \param BlockNum     Block index in list\r
- */\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
-{\r
-       Uint32  *iBlocks;\r
-        int    dwPerBlock = Disk->BlockSize / 4;\r
-       \r
-       // Direct Blocks\r
-       if(BlockNum < 12)\r
-               return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
-       \r
-       // Single Indirect Blocks\r
-       iBlocks = malloc( Disk->BlockSize );\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       \r
-       BlockNum -= 12;\r
-       if(BlockNum < dwPerBlock)\r
-       {\r
-               BlockNum = iBlocks[BlockNum];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       \r
-       BlockNum -= dwPerBlock;\r
-       // Double Indirect Blocks\r
-       if(BlockNum < dwPerBlock*dwPerBlock)\r
-       {\r
-               VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               BlockNum = iBlocks[BlockNum%dwPerBlock];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       \r
-       BlockNum -= dwPerBlock*dwPerBlock;\r
-       // Triple Indirect Blocks\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(dwPerBlock*dwPerBlock)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/dwPerBlock)%dwPerBlock]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       BlockNum = iBlocks[BlockNum%dwPerBlock];\r
-       free(iBlocks);\r
-       return (Uint64)BlockNum * Disk->BlockSize;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
- * \brief Allocate an inode (from the current group preferably)\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param Parent       Inode ID of the parent (used to locate the child nearby)\r
- */\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
-{\r
-//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
- * \brief Updates the superblock\r
- */\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
-{\r
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;\r
-        int    ngrp = Disk->SuperBlock.s_blocks_count / bpg;\r
-        int    i;\r
-        \r
-       // Update Primary\r
-       VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
-       \r
-       // Secondaries\r
-       // at Block Group 1, 3^n, 5^n, 7^n\r
-       \r
-       // 1\r
-       if(ngrp <= 1)   return;\r
-       VFS_WriteAt(Disk->FD, 1*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 3\r
-       for( i = 3; i < ngrp; i *= 3 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 5\r
-       for( i = 5; i < ngrp; i *= 5 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-       \r
-       // Powers of 7\r
-       for( i = 7; i < ngrp; i *= 7 )\r
-               VFS_WriteAt(Disk->FD, i*bpg*Disk->BlockSize, 1024, &Disk->SuperBlock);\r
-}\r
diff --git a/Modules/Filesystems/FS_Ext2/ext2_common.h b/Modules/Filesystems/FS_Ext2/ext2_common.h
deleted file mode 100644 (file)
index 877b71d..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file ext2_common.h
- * \brief Second Extended Filesystem Driver
- */
-#ifndef _EXT2_COMMON_H
-#define _EXT2_COMMON_H
-#include <acess.h>
-#include <vfs.h>
-#include "ext2fs.h"
-
-#define EXT2_UPDATE_WRITEBACK  1
-
-// === STRUCTURES ===
-typedef struct {
-        int    FD;
-        int    CacheID;
-       tVFS_Node       RootNode;
-       
-       tExt2_SuperBlock        SuperBlock;
-        int    BlockSize;
-        
-        int    GroupCount;
-       tExt2_Group             Groups[];
-} tExt2_Disk;
-
-// === FUNCTIONS ===
-// --- Common ---
-extern void    Ext2_CloseFile(tVFS_Node *Node);
-extern Uint64  Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);
-extern void    Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);
-extern int     Ext2_int_ReadInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
-extern int     Ext2_int_WriteInode(tExt2_Disk *Disk, Uint32 InodeId, tExt2_Inode *Inode);
-// --- Dir ---
-extern char    *Ext2_ReadDir(tVFS_Node *Node, int Pos);
-extern tVFS_Node       *Ext2_FindDir(tVFS_Node *Node, char *FileName);
-extern int     Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
-// --- Read ---
-extern Uint64  Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-// --- Write ---
-extern Uint64  Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-
-#endif
diff --git a/Modules/Filesystems/FS_Ext2/ext2fs.h b/Modules/Filesystems/FS_Ext2/ext2fs.h
deleted file mode 100644 (file)
index 8fd87ce..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/**\r
- * Acess2\r
- * \file ext2fs.h\r
- * \brief EXT2 Filesystem Driver\r
- */\r
-#ifndef _EXT2FS_H_\r
-#define _EXT2FS_H_\r
-\r
-/**\r
- \name Inode Flag Values\r
- \{\r
-*/\r
-#define EXT2_S_IFMT            0xF000  //!< Format Mask\r
-#define EXT2_S_IFSOCK  0xC000  //!< Socket\r
-#define EXT2_S_IFLNK   0xA000  //!< Symbolic Link\r
-#define EXT2_S_IFREG   0x8000  //!< Regular File\r
-#define EXT2_S_IFBLK   0x6000  //!< Block Device\r
-#define EXT2_S_IFDIR   0x4000  //!< Directory\r
-#define EXT2_S_IFCHR   0x2000  //!< Character Device\r
-#define EXT2_S_IFIFO   0x1000  //!< FIFO\r
-#define EXT2_S_ISUID   0x0800  //!< SUID\r
-#define EXT2_S_ISGID   0x0400  //!< SGID\r
-#define EXT2_S_ISVTX   0x0200  //!< sticky bit\r
-#define EXT2_S_IRWXU   0700    //!< user access rights mask\r
-#define EXT2_S_IRUSR   0400    //!< Owner Read\r
-#define EXT2_S_IWUSR   0200    //!< Owner Write\r
-#define EXT2_S_IXUSR   0100    //!< Owner Execute\r
-#define EXT2_S_IRWXG   0070    //!< Group Access rights mask\r
-#define EXT2_S_IRGRP   0040    //!< Group Read\r
-#define EXT2_S_IWGRP   0020    //!< Group Write\r
-#define EXT2_S_IXGRP   0010    //!< Group Execute\r
-#define EXT2_S_IRWXO   0007    //!< Global Access rights mask\r
-#define EXT2_S_IROTH   0004    //!< Global Read\r
-#define EXT2_S_IWOTH   0002    //!< Global Write\r
-#define EXT2_S_IXOTH   0001    //!< Global Execute\r
-//! \}\r
-\r
-#define EXT2_NAME_LEN 255      //!< Maximum Name Length\r
-\r
-// === TYPEDEFS ===\r
-typedef struct ext2_inode_s                    tExt2_Inode;    //!< Inode Type\r
-typedef struct ext2_super_block_s      tExt2_SuperBlock;       //!< Superblock Type\r
-typedef struct ext2_group_desc_s       tExt2_Group;    //!< Group Descriptor Type\r
-typedef struct ext2_dir_entry_s                tExt2_DirEnt;   //!< Directory Entry Type\r
-\r
-// === STRUCTURES ===\r
-/**\r
- * \brief EXT2 Superblock Structure\r
- */\r
-struct ext2_super_block_s {\r
-       Uint32  s_inodes_count;         //!< Inodes count\r
-       Uint32  s_blocks_count;         //!< Blocks count\r
-       Uint32  s_r_blocks_count;       //!< Reserved blocks count\r
-       Uint32  s_free_blocks_count;    //!< Free blocks count\r
-       Uint32  s_free_inodes_count;    //!< Free inodes count\r
-       Uint32  s_first_data_block;     //!< First Data Block\r
-       Uint32  s_log_block_size;       //!< Block size\r
-       Sint32  s_log_frag_size;        //!< Fragment size\r
-       Uint32  s_blocks_per_group;     //!< Number Blocks per group\r
-       Uint32  s_frags_per_group;      //!< Number Fragments per group\r
-       Uint32  s_inodes_per_group;     //!< Number Inodes per group\r
-       Uint32  s_mtime;                        //!< Mount time\r
-       Uint32  s_wtime;                        //!< Write time\r
-       Uint16  s_mnt_count;            //!< Mount count\r
-       Sint16  s_max_mnt_count;        //!< Maximal mount count\r
-       Uint16  s_magic;                        //!< Magic signature\r
-       Uint16  s_state;                        //!< File system state\r
-       Uint16  s_errors;                       //!< Behaviour when detecting errors\r
-       Uint16  s_pad;                          //!< Padding\r
-       Uint32  s_lastcheck;            //!< time of last check\r
-       Uint32  s_checkinterval;        //!< max. time between checks\r
-       Uint32  s_creator_os;           //!< Formatting OS\r
-       Uint32  s_rev_level;            //!< Revision level\r
-       Uint16  s_def_resuid;           //!< Default uid for reserved blocks\r
-       Uint16  s_def_resgid;           //!< Default gid for reserved blocks\r
-       Uint32  s_reserved[235];        //!< Padding to the end of the block\r
-};\r
-\r
-/**\r
- * \struct ext2_inode_s\r
- * \brief EXT2 Inode Definition\r
- */\r
-struct ext2_inode_s {\r
-       Uint16 i_mode;  //!< File mode\r
-       Uint16 i_uid;   //!< Owner Uid\r
-       Uint32 i_size;  //!< Size in bytes\r
-       Uint32 i_atime; //!< Access time\r
-       Uint32 i_ctime; //!< Creation time\r
-       Uint32 i_mtime; //!< Modification time\r
-       Uint32 i_dtime; //!< Deletion Time\r
-       Uint16 i_gid;   //!< Group Id\r
-       Uint16 i_links_count;   //!< Links count\r
-       Uint32 i_blocks;        //!< Number of blocks allocated for the file\r
-       Uint32 i_flags; //!< File flags\r
-       union {\r
-               Uint32 linux_reserved1; //!< Linux: Reserved\r
-               Uint32 hurd_translator; //!< HURD: Translator\r
-               Uint32 masix_reserved1; //!< Masix: Reserved\r
-       } osd1; //!< OS dependent 1\r
-       Uint32 i_block[15];     //!< Pointers to blocks\r
-       Uint32 i_version;       //!< File version (for NFS)\r
-       Uint32 i_file_acl;      //!< File ACL\r
-       Uint32 i_dir_acl;       //!< Directory ACL / Extended File Size\r
-       Uint32 i_faddr;         //!< Fragment address\r
-       union {\r
-               struct {\r
-                       Uint8 l_i_frag; //!< Fragment number\r
-                       Uint8 l_i_fsize;        //!< Fragment size\r
-                       Uint16 i_pad1;  //!< Padding\r
-                       Uint32 l_i_reserved2[2];        //!< Reserved\r
-               } linux2;\r
-               struct {\r
-                       Uint8 h_i_frag; //!< Fragment number\r
-                       Uint8 h_i_fsize; //!< Fragment size\r
-                       Uint16 h_i_mode_high;   //!< Mode High Bits\r
-                       Uint16 h_i_uid_high;    //!< UID High Bits\r
-                       Uint16 h_i_gid_high;    //!< GID High Bits\r
-                       Uint32 h_i_author;      //!< Creator ID\r
-               } hurd2;\r
-               struct {\r
-                       Uint8 m_i_frag; //!< Fragment number\r
-                       Uint8 m_i_fsize;        //!< Fragment size\r
-                       Uint16 m_pad1;  //!< Padding\r
-                       Uint32 m_i_reserved2[2];        //!< reserved\r
-               } masix2;\r
-       } osd2; //!< OS dependent 2\r
-};\r
-\r
-/**\r
- * \struct ext2_group_desc_s\r
- * \brief EXT2 Group Descriptor\r
- */\r
-struct ext2_group_desc_s {\r
-       Uint32  bg_block_bitmap;        //!< Blocks bitmap block\r
-       Uint32  bg_inode_bitmap;        //!< Inodes bitmap block\r
-       Uint32  bg_inode_table; //!< Inodes table block\r
-       Uint16  bg_free_blocks_count;   //!< Free blocks count\r
-       Uint16  bg_free_inodes_count;   //!< Free inodes count\r
-       Uint16  bg_used_dirs_count;     //!< Directories count\r
-       Uint16  bg_pad; //!< Padding\r
-       Uint32  bg_reserved[3]; //!< Reserved\r
-};\r
-\r
-/**\r
- * \brief EXT2 Directory Entry\r
- * \note The name may take up less than 255 characters\r
- */\r
-struct ext2_dir_entry_s {\r
-       Uint32  inode;          //!< Inode number\r
-       Uint16  rec_len;        //!< Directory entry length\r
-       Uint8   name_len;       //!< Short Name Length\r
-       Uint8   type;           //!< File Type\r
-       char    name[];         //!< File name\r
-};\r
-\r
-#endif\r
diff --git a/Modules/Filesystems/FS_Ext2/read.c b/Modules/Filesystems/FS_Ext2/read.c
deleted file mode 100644 (file)
index 81f5ee6..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file read.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-// === PROTOTYPES ===
-Uint64         Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-
-// === CODE ===
-/**
- * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Read from a file
- */
-Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       Uint64  base;
-       Uint    block;
-       Uint64  remLen;
-       
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
-       
-       // Get Inode
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       
-       // Sanity Checks
-       if(Offset >= inode.i_size) {
-               LEAVE('i', 0);
-               return 0;
-       }
-       if(Offset + Length > inode.i_size)
-               Length = inode.i_size - Offset;
-       
-       block = Offset / disk->BlockSize;
-       Offset = Offset / disk->BlockSize;
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-       if(base == 0) {
-               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
-               LEAVE('i', 0);
-               return 0;
-       }
-       
-       // Read only block
-       if(Length <= disk->BlockSize - Offset)
-       {
-               VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);
-               LEAVE('X', Length);
-               return Length;
-       }
-       
-       // Read first block
-       remLen = Length;
-       VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);
-       remLen -= disk->BlockSize - Offset;
-       Buffer += disk->BlockSize - Offset;
-       block ++;
-       
-       // Read middle blocks
-       while(remLen > disk->BlockSize)
-       {
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               if(base == 0) {
-                       Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
-                       LEAVE('i', 0);
-                       return 0;
-               }
-               VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);
-               Buffer += disk->BlockSize;
-               remLen -= disk->BlockSize;
-               block ++;
-       }
-       
-       // Read last block
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-       VFS_ReadAt( disk->FD, base, remLen, Buffer);
-       
-       LEAVE('X', Length);
-       return Length;
-}
diff --git a/Modules/Filesystems/FS_Ext2/write.c b/Modules/Filesystems/FS_Ext2/write.c
deleted file mode 100644 (file)
index 950f6d5..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file write.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-// === PROTOYPES ===
-Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
-void   Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
- int   Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
-
-// === CODE ===
-/**
- * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Write to a file
- */
-Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       Uint64  base;
-       Uint64  retLen;
-       Uint    block;
-       Uint64  allocSize;
-        int    bNewBlocks = 0;
-       
-       Debug_HexDump("Ext2_Write", Buffer, Length);
-       
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       
-       // Get the ammount of space already allocated
-       // - Round size up to block size
-       // - block size is a power of two, so this will work
-       allocSize = (inode.i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
-       
-       // Are we writing to inside the allocated space?
-       if( Offset < allocSize )
-       {
-               // Will we go out of it?
-               if(Offset + Length > allocSize) {
-                       bNewBlocks = 1;
-                       retLen = allocSize - Offset;
-               } else
-                       retLen = Length;
-               
-               // Within the allocated space
-               block = Offset / disk->BlockSize;
-               Offset %= disk->BlockSize;
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               
-               // Write only block (if only one)
-               if(Offset + retLen <= disk->BlockSize) {
-                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
-                       if(!bNewBlocks) return Length;
-                       goto addBlocks; // Ugh! A goto, but it seems unavoidable
-               }
-               
-               // Write First Block
-               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
-               Buffer += disk->BlockSize-Offset;
-               retLen -= disk->BlockSize-Offset;
-               block ++;
-               
-               // Write middle blocks
-               while(retLen > disk->BlockSize)
-               {
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
-                       Buffer += disk->BlockSize;
-                       retLen -= disk->BlockSize;
-                       block ++;
-               }
-               
-               // Write last block
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               VFS_WriteAt(disk->FD, base, retLen, Buffer);
-               if(!bNewBlocks) return Length;  // Writing in only allocated space
-       }
-       
-addBlocks:
-       Warning("[EXT2 ] File extending is untested");
-       
-       // Allocate blocks and copy data to them
-       retLen = Length - allocSize;
-       while( retLen > disk->BlockSize )
-       {
-               // Allocate a block
-               block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
-               if(!block)      return Length - retLen;
-               // Add it to this inode
-               if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
-                       Ext2_int_DeallocateBlock(disk, block);
-                       goto ret;
-               }
-               // Copy data to the node
-               base = block * disk->BlockSize;
-               VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
-               // Update pointer and size remaining
-               inode.i_size += disk->BlockSize;
-               Buffer += disk->BlockSize;
-               retLen -= disk->BlockSize;
-       }
-       // Last block :D
-       block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
-       if(!block)      goto ret;
-       if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
-               Ext2_int_DeallocateBlock(disk, block);
-               goto ret;
-       }
-       base = block * disk->BlockSize;
-       VFS_WriteAt(disk->FD, base, retLen, Buffer);
-       inode.i_size += retLen;
-       retLen = 0;
-
-ret:   // Makes sure the changes to the inode are committed
-       Ext2_int_WriteInode(disk, Node->Inode, &inode);
-       return Length - retLen;
-}
-
-/**
- * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
- * \brief Allocate a block from the best possible location
- * \param Disk EXT2 Disk Information Structure
- * \param PrevBlock    Previous block ID in the file
- */
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
-{
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;
-       Uint    blockgroup = PrevBlock / bpg;
-       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
-       Uint    bitsperblock = 8*Disk->BlockSize;
-        int    i, j = 0;
-       Uint    block;
-       
-       // Are there any free blocks?
-       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
-       
-       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
-       {
-               // Search block group's bitmap
-               for(i = 0; i < bpg; i++)
-               {
-                       // Get the block in the bitmap block
-                       j = i & (bitsperblock-1);
-                       
-                       // Read in if needed
-                       if(j == 0) {
-                               VFS_ReadAt(
-                                       Disk->FD,
-                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                                       Disk->BlockSize,
-                                       bitmap
-                                       );
-                       }
-                       
-                       // Fast Check
-                       if( bitmap[j/32] == -1 ) {
-                               j = (j + 31) & ~31;
-                               continue;
-                       }
-                       
-                       // Is the bit set?
-                       if( bitmap[j/32] & (1 << (j%32)) )
-                               continue;
-                       
-                       // Ooh! We found one
-                       break;
-               }
-               if( i < bpg ) {
-                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
-                       goto    checkAll;       // Search the entire filesystem for a free block
-                       // Goto needed for neatness
-               }
-               
-               // Mark as used
-               bitmap[j/32] |= (1 << (j%32));
-               VFS_WriteAt(
-                       Disk->FD,
-                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                       Disk->BlockSize,
-                       bitmap
-                       );
-               block = i;
-               Disk->Groups[blockgroup].bg_free_blocks_count --;
-               #if EXT2_UPDATE_WRITEBACK
-               //Ext2_int_UpdateBlockGroup(Disk, blockgroup);
-               #endif
-       }
-       else
-       {
-       checkAll:
-               Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");
-               return 0;
-       }
-       
-       // Reduce global count
-       Disk->SuperBlock.s_free_blocks_count --;
-       #if EXT2_UPDATE_WRITEBACK
-       Ext2_int_UpdateSuperblock(Disk);
-       #endif
-       
-       return block;
-}
-
-/**
- * \brief Deallocates a block
- */
-void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
-{
-}
-
-/**
- * \brief Append a block to an inode
- */
-int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
-{
-        int    nBlocks;
-        int    dwPerBlock = Disk->BlockSize / 4;
-       Uint32  *blocks;
-       Uint32  id1, id2;
-       
-       nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
-       
-       // Direct Blocks
-       if( nBlocks < 12 ) {
-               Inode->i_block[nBlocks] = Block;
-               return 0;
-       }
-       
-       blocks = malloc( Disk->BlockSize );
-       if(!blocks)     return 1;
-       
-       nBlocks -= 12;
-       // Single Indirect
-       if( nBlocks < dwPerBlock)
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[12] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize); 
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               blocks[nBlocks] = Block;
-               
-               VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       nBlocks += dwPerBlock;
-       // Double Indirect
-       if( nBlocks < dwPerBlock*dwPerBlock )
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[13] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               // Allocate / Get Indirect lvl2 Block
-               if( nBlocks % dwPerBlock == 0 ) {
-                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !id1 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[nBlocks/dwPerBlock] = id1;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id1 = blocks[nBlocks / dwPerBlock];
-                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               blocks[nBlocks % dwPerBlock] = Block;
-               
-               VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       nBlocks -= dwPerBlock*dwPerBlock;
-       // Triple Indirect
-       if( nBlocks < dwPerBlock*dwPerBlock*dwPerBlock )
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[14] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               // Allocate / Get Indirect lvl2 Block
-               if( (nBlocks/dwPerBlock) % dwPerBlock == 0 && nBlocks % dwPerBlock == 0 )
-               {
-                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !id1 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[nBlocks/dwPerBlock] = id1;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id1 = blocks[nBlocks / (dwPerBlock*dwPerBlock)];
-                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               // Allocate / Get Indirect Level 3 Block
-               if( nBlocks % dwPerBlock == 0 ) {
-                       id2 = Ext2_int_AllocateBlock(Disk, id1);
-                       if( !id2 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[(nBlocks/dwPerBlock)%dwPerBlock] = id2;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id2 = blocks[(nBlocks/dwPerBlock)%dwPerBlock];
-                       VFS_ReadAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               blocks[nBlocks % dwPerBlock] = Block;
-               
-               VFS_WriteAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
-       free(blocks);
-       return 1;
-}
diff --git a/Modules/Filesystems/FS_NFS/Makefile b/Modules/Filesystems/FS_NFS/Makefile
deleted file mode 100644 (file)
index 6fa2e6e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#
-
-OBJ = main.o
-NAME = FS_NFS
-
--include ../Makefile.tpl
diff --git a/Modules/Filesystems/FS_NFS/common.h b/Modules/Filesystems/FS_NFS/common.h
deleted file mode 100644 (file)
index d73592f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Acess2 - NFS Driver
- * By John Hodge (thePowersGang)
- * This file is published under the terms of the Acess licence. See the
- * file COPYING for details.
- *
- * common.h - Common definitions
- */
-#ifndef _COMMON_H_
-#define _COMMON_H_
-
-typedef struct sNFS_Connection
-{
-        int    FD;
-       tIPAddr Host;
-       char    *Base;
-       tVFS_Node       Node;
-}      tNFS_Connection;
-
-#endif
diff --git a/Modules/Filesystems/FS_NFS/main.c b/Modules/Filesystems/FS_NFS/main.c
deleted file mode 100644 (file)
index 459945f..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Acess2 - NFS Driver
- * By John Hodge (thePowersGang)
- * This file is published under the terms of the Acess licence. See the
- * file COPYING for details.
- *
- * main.c - Driver core
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "common.h"
-#include <modules.h>
-
-// === PROTOTYPES ===
- int   NFS_Install(char **Arguments);
-tVFS_Node      *NFS_InitDevice(char *Devices, char **Options);
-void   NFS_Unmount(tVFS_Node *Node);
-
-// === GLOBALS ===
-MODULE_DEFINE(0, 0x32 /*v0.5*/, FS_NFS, NFS_Install, NULL);
-tVFS_Driver    gNFS_FSInfo = {"nfs", 0, NFS_InitDevice, NFS_Unmount, NULL};
-
-tNFS_Connection        *gpNFS_Connections;
-
-// === CODE ===
-/**
- * \brief Installs the NFS driver
- */
-int NFS_Install(char **Arguments)
-{
-       VFS_AddDriver( &gNFS_FSInfo );
-       return 1;
-}
-
-/**
- * \brief Mount a NFS share
- */
-tVFS_Node *NFS_InitDevice(char *Device, char **Options)
-{
-       char    *path, *host;
-       tNFS_Connection *conn;
-       
-       path = strchr( Device, ':' ) + 1;
-       host = strndup( Device, (int)(path-Device)-1 );
-       
-       conn = malloc( sizeof(tNFS_Connection) );
-       
-       if( !IPTools_GetAddress(host, &conn->IP) ) {
-               free(conn);
-               return NULL;
-       }
-       free(host);
-       
-       conn->FD = IPTools_OpenUdpClient( &conn->Host );
-       if(conn->FD == -1) {
-               free(conn);
-               return NULL;
-       }
-       
-       conn->Base = strdup( path );
-       conn->RootNode.ImplPtr = conn;
-       conn->RootNode.Flags = VFS_FFLAG_DIRECTORY;
-       
-       conn->RootNode.ReadDir = NFS_ReadDir;
-       conn->RootNode.FindDir = NFS_FindDir;
-       conn->RootNode.Close = NULL;
-       
-       return &conn->RootNode;
-}
-
-void NFS_Unmount(tVFS_Node *Node)
-{
-       
-}
diff --git a/Modules/Filesystems/InitRD/GenerateInitRD.php b/Modules/Filesystems/InitRD/GenerateInitRD.php
new file mode 100644 (file)
index 0000000..d89d6e9
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Acess2 InitRD
+ * InitRD Data
+ * Generated <?php echo date("Y-m-d H:i"),"\n"; ?>
+ */
+#include "initrd.h"
+<?php
+$lines = file($argv[1]);
+
+$lDepth = 0;
+$lTree = array();
+$lStack = array( array("",array()) );
+foreach($lines as $line)
+{
+       $line = trim($line);
+       if(preg_match('/^Dir\s+"([^"]+)"\s+{$/', $line, $matches))
+       {
+               $new = array($matches[1], array());
+               array_push($lStack, $new);
+               $lDepth ++;
+               continue;
+       }
+       if($line == "}")
+       {
+               $lDepth --;
+               $lStack[$lDepth][1][] = array_pop($lStack);
+               continue;
+       }
+       if(preg_match('/^File\s+"([^"]+)"\s+"([^"]+)"$/', $line, $matches))
+       {
+               $lStack[$lDepth][1][] = array($matches[1], $matches[2]);
+               continue;
+       }
+}
+
+function hd($fp)
+{
+       return "0x".str_pad( dechex(ord(fgetc($fp))), 2, "0", STR_PAD_LEFT );
+}
+
+function ProcessFolder($prefix, $items)
+{
+       foreach($items as $i=>$item)
+       {
+               if(is_array($item[1])) {
+                       
+                       ProcessFolder("{$prefix}_{$i}", $item[1]);
+                       
+                       echo "tInitRD_File {$prefix}_{$i}_entries[] = {\n";
+                       foreach($item[1] as $j=>$child)
+                       {
+                               if($j)  echo ",\n";
+                               echo "\t{\"".addslashes($child[0])."\",&{$prefix}_{$i}_{$j}}";
+                       }
+                       echo "\n};\n";
+                       
+                       $size = count($item[1]);
+                       echo <<<EOF
+tVFS_Node {$prefix}_{$i} = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = VFS_FFLAG_DIRECTORY,
+       .Size = $size,
+       .ImplPtr = {$prefix}_{$i}_entries,
+       .ReadDir = InitRD_ReadDir,
+       .FindDir = InitRD_FindDir
+};
+
+EOF;
+               }
+               else {
+                       $size = filesize($item[1]);
+                       
+                       echo "Uint8 {$prefix}_{$i}_data[] = {\n";
+                       $fp = fopen($item[1], "rb");
+                       for( $j = 0; $j + 16 < $size; $j += 16 )
+                       {
+                               echo "\t";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",";
+                               echo hd($fp),",",hd($fp),",\n";
+                       }
+                       echo "\t";
+                       for( ; $j < $size; $j ++ )
+                       {
+                               if( $j & 15 )   echo ",";
+                               echo hd($fp);
+                       }
+                       fclose($fp);
+                       echo "\n};\n";
+                       echo <<<EOF
+tVFS_Node {$prefix}_{$i} = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = 0,
+       .Size = $size,
+       .ImplPtr = {$prefix}_{$i}_data,
+       .Read = InitRD_ReadFile
+};
+
+EOF;
+               }
+       }
+}
+
+ProcessFolder("gInitRD_Files", $lStack[0][1]);
+
+echo "tInitRD_File gInitRD_Root_Files[] = {\n";
+foreach($lStack[0][1] as $j=>$child)
+{
+       if($j)  echo ",\n";
+       echo "\t{\"".addslashes($child[0])."\",&gInitRD_Files_{$j}}";
+}
+echo "\n};\n";
+?>
+tVFS_Node gInitRD_RootNode = {
+       .NumACLs = 1,
+       .ACLs = &gVFS_ACL_EveryoneRX,
+       .Flags = VFS_FFLAG_DIRECTORY,
+       .Size = <?php echo count($lStack[0][1]);?>,
+       .ImplPtr = gInitRD_Root_Files,
+       .ReadDir = InitRD_ReadDir,
+       .FindDir = InitRD_FindDir
+};
diff --git a/Modules/Filesystems/InitRD/Makefile b/Modules/Filesystems/InitRD/Makefile
new file mode 100644 (file)
index 0000000..18dbc59
--- /dev/null
@@ -0,0 +1,10 @@
+# InitRD Filesystem Driver
+#
+
+OBJ = main.o files.o
+NAME = FS_InitRD
+
+-include ../Makefile.tpl
+
+files.c:
+       php GenerateInitRD.php files.lst > files.c
diff --git a/Modules/Filesystems/InitRD/files.lst b/Modules/Filesystems/InitRD/files.lst
new file mode 100644 (file)
index 0000000..bf36527
--- /dev/null
@@ -0,0 +1,8 @@
+Dir "SBin" {
+       File "init" "../../../Usermode/Applications/init"
+       File "login" "../../../Usermode/Applications/login"
+}
+Dir "Bin" {
+       File "CLIShell" "../../../Usermode/Applications/CLIShell"
+       File "ls" "../../../Usermode/Applications/ls"
+}
diff --git a/Modules/Filesystems/InitRD/initrd.h b/Modules/Filesystems/InitRD/initrd.h
new file mode 100644 (file)
index 0000000..8ae97ae
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ */
+#ifndef _INITRD_H_
+#define _INITRD_H_
+
+#include <acess.h>
+#include <vfs.h>
+
+typedef struct sInitRD_File
+{
+       char    *Name;
+       tVFS_Node       *Node;
+}      tInitRD_File;
+
+
+// === Functions ===
+extern Uint64  InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Size, void *Buffer);
+extern char    *InitRD_ReadDir(tVFS_Node *Node, int ID);
+extern tVFS_Node       *InitRD_FindDir(tVFS_Node *Node, char *Name);
+
+#endif
diff --git a/Modules/Filesystems/InitRD/main.c b/Modules/Filesystems/InitRD/main.c
new file mode 100644 (file)
index 0000000..1485058
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Acess OS
+ * InitRD Driver Version 1
+ */
+#include "initrd.h"
+#include <modules.h>
+
+// === IMPORTS ==
+extern tVFS_Node       gInitRD_RootNode;
+
+// === PROTOTYPES ===
+ int   InitRD_Install(char **Arguments);
+tVFS_Node      *InitRD_InitDevice(char *Device, char **Arguments);
+void   InitRD_Unmount(tVFS_Node *Node);
+Uint64 InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Size, void *Buffer);
+char   *InitRD_ReadDir(tVFS_Node *Node, int ID);
+tVFS_Node      *InitRD_FindDir(tVFS_Node *Node, char *Name);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0A, FS_InitRD, InitRD_Install, NULL);
+tVFS_Driver    gInitRD_FSInfo = {
+       "initrd", 0, InitRD_InitDevice, InitRD_Unmount, NULL
+       };
+
+/**
+ * \brief Register initrd with the kernel
+ */
+int InitRD_Install(char **Arguments)
+{
+       VFS_AddDriver( &gInitRD_FSInfo );
+       return MODULE_ERR_OK;
+}
+
+/**
+ * \brief Mount the InitRD
+ */
+tVFS_Node *InitRD_InitDevice(char *Device, char **Arguments)
+{
+       return &gInitRD_RootNode;
+}
+
+/**
+ * \brief Unmount the InitRD
+ */
+void InitRD_Unmount(tVFS_Node *Node)
+{
+}
+
+/**
+ * \brief Read from a file
+ */
+Uint64 InitRD_ReadFile(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       if(Offset > Node->Size)
+               return 0;
+       if(Offset + Length > Node->Size)
+               Length = Node->Size - Offset;
+       
+       memcpy(Buffer, Node->ImplPtr, Length);
+       
+       return Length;
+}
+
+/**
+ * \brief Read from a directory
+ */
+char *InitRD_ReadDir(tVFS_Node *Node, int ID)
+{
+       tInitRD_File    *dir = Node->ImplPtr;
+       
+       if(ID >= Node->Size)
+               return NULL;
+       
+       return strdup(dir[ID].Name);
+}
+
+/**
+ * \brief Find an element in a directory
+ */
+tVFS_Node *InitRD_FindDir(tVFS_Node *Node, char *Name)
+{
+        int    i;
+       tInitRD_File    *dir = Node->ImplPtr;
+       
+       for( i = 0; i < Node->Size; i++ )
+       {
+               if(strcmp(Name, dir[i].Name) == 0)
+                       return dir[i].Node;
+       }
+       
+       return NULL;
+}
index 80c6d4d..77dfc2c 100644 (file)
@@ -1 +1,2 @@
+CATEGORY = FS
 -include ../../Makefile.tpl
diff --git a/Modules/Filesystems/NFS/Makefile b/Modules/Filesystems/NFS/Makefile
new file mode 100644 (file)
index 0000000..0b2019f
--- /dev/null
@@ -0,0 +1,7 @@
+#
+#
+
+OBJ = main.o
+NAME = NFS
+
+-include ../Makefile.tpl
diff --git a/Modules/Filesystems/NFS/common.h b/Modules/Filesystems/NFS/common.h
new file mode 100644 (file)
index 0000000..d73592f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Acess2 - NFS Driver
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess licence. See the
+ * file COPYING for details.
+ *
+ * common.h - Common definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+typedef struct sNFS_Connection
+{
+        int    FD;
+       tIPAddr Host;
+       char    *Base;
+       tVFS_Node       Node;
+}      tNFS_Connection;
+
+#endif
diff --git a/Modules/Filesystems/NFS/main.c b/Modules/Filesystems/NFS/main.c
new file mode 100644 (file)
index 0000000..459945f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Acess2 - NFS Driver
+ * By John Hodge (thePowersGang)
+ * This file is published under the terms of the Acess licence. See the
+ * file COPYING for details.
+ *
+ * main.c - Driver core
+ */
+#define DEBUG  1
+#define VERBOSE        0
+#include "common.h"
+#include <modules.h>
+
+// === PROTOTYPES ===
+ int   NFS_Install(char **Arguments);
+tVFS_Node      *NFS_InitDevice(char *Devices, char **Options);
+void   NFS_Unmount(tVFS_Node *Node);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x32 /*v0.5*/, FS_NFS, NFS_Install, NULL);
+tVFS_Driver    gNFS_FSInfo = {"nfs", 0, NFS_InitDevice, NFS_Unmount, NULL};
+
+tNFS_Connection        *gpNFS_Connections;
+
+// === CODE ===
+/**
+ * \brief Installs the NFS driver
+ */
+int NFS_Install(char **Arguments)
+{
+       VFS_AddDriver( &gNFS_FSInfo );
+       return 1;
+}
+
+/**
+ * \brief Mount a NFS share
+ */
+tVFS_Node *NFS_InitDevice(char *Device, char **Options)
+{
+       char    *path, *host;
+       tNFS_Connection *conn;
+       
+       path = strchr( Device, ':' ) + 1;
+       host = strndup( Device, (int)(path-Device)-1 );
+       
+       conn = malloc( sizeof(tNFS_Connection) );
+       
+       if( !IPTools_GetAddress(host, &conn->IP) ) {
+               free(conn);
+               return NULL;
+       }
+       free(host);
+       
+       conn->FD = IPTools_OpenUdpClient( &conn->Host );
+       if(conn->FD == -1) {
+               free(conn);
+               return NULL;
+       }
+       
+       conn->Base = strdup( path );
+       conn->RootNode.ImplPtr = conn;
+       conn->RootNode.Flags = VFS_FFLAG_DIRECTORY;
+       
+       conn->RootNode.ReadDir = NFS_ReadDir;
+       conn->RootNode.FindDir = NFS_FindDir;
+       conn->RootNode.Close = NULL;
+       
+       return &conn->RootNode;
+}
+
+void NFS_Unmount(tVFS_Node *Node)
+{
+       
+}
index 77bc691..088caaa 100644 (file)
@@ -111,7 +111,7 @@ int ICMP_Ping(tInterface *Interface, tIPv4 Addr)
                {
                        if(gICMP_PingSlots[i].Interface == NULL)        break;
                }
-               if(gICMP_PingSlots[i].Interface == NULL)        break;
+               if( i < PING_SLOTS )    break;
                Threads_Yield();
        }
        gICMP_PingSlots[i].Interface = Interface;
index fef9065..9c26767 100644 (file)
@@ -315,7 +315,7 @@ void TCP_INT_HandleConnectionPacket(tTCPConnection *Connection, tTCPHeader *Head
        // Is this packet the next expected packet?
        if( pkt->Sequence != Connection->NextSequenceRcv )
        {
-               tTCPStoredPacket        *tmp, *prev;
+               tTCPStoredPacket        *tmp, *prev = NULL;
                
                Log("[TCP  ] Out of sequence packet (0x%08x != 0x%08x)",
                        pkt->Sequence, Connection->NextSequenceRcv);
index 964f5ce..8f548c5 100644 (file)
@@ -12,10 +12,10 @@ CFGFILES += $(shell test -f Makefile.cfg && echo Makefile.cfg)
 -include $(CFGFILES)
 
 CPPFLAGS = -I$(ACESSDIR)/Kernel/include -I$(ACESSDIR)/Kernel/arch/$(ARCHDIR)/include -DARCH=$(ARCH) $(_CPPFLAGS)
-CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS)
+CFLAGS = -Wall -Werror -fno-stack-protector $(CPPFLAGS) -O3
 
 OBJ := $(addsuffix .$(ARCH),$(OBJ))
-BIN = ../$(NAME).kmd.$(ARCH)
+BIN = ../$(CATEGORY)_$(NAME).kmd.$(ARCH)
 KOBJ = ../$(NAME).xo.$(ARCH)
 
 DEPFILES  = $(filter %.o.$(ARCH),$(OBJ))
index 80c6d4d..d5291f6 100644 (file)
@@ -1 +1,3 @@
+CATEGORY = Storage
+
 -include ../../Makefile.tpl
index 324836b..f191556 100644 (file)
@@ -2,8 +2,7 @@
 #
 #
 
-AS = nasm
-RM = rm -f
+-include ../Makefile.cfg
 
 ASFLAGS = -felf
 

UCC git Repository :: git.ucc.asn.au