tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments);\r
void NativeFS_Unmount(tVFS_Node *Node);\r
tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name);\r
-char *NativeFS_ReadDir(tVFS_Node *Node, int Position);\r
+ int NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX]);\r
size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer);\r
size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer);\r
void NativeFS_Close(tVFS_Node *Node);\r
return Inode_CacheNode(info->InodeHandle, &baseRet);\r
}\r
\r
-char *NativeFS_ReadDir(tVFS_Node *Node, int Position)\r
+int NativeFS_ReadDir(tVFS_Node *Node, int Position, char Dest[FILENAME_MAX])\r
{\r
struct dirent *ent;\r
DIR *dp = (void*)(tVAddr)Node->Inode;\r
- char *ret;\r
\r
ENTER("pNode iPosition", Node, Position);\r
\r
} while(Position-- && ent);\r
\r
if( !ent ) {\r
- LEAVE('n');\r
- return NULL;\r
+ LEAVE('i', -ENOENT);\r
+ return -ENOENT;\r
}\r
\r
- ret = strdup(ent->d_name);\r
+ strncpy(Dest, ent->d_name, FILENAME_MAX);\r
\r
// TODO: Unlock node \r
\r
- LEAVE('s', ret);\r
- return ret;\r
+ LEAVE('i', 0);\r
+ return 0;\r
}\r
\r
size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void *Buffer)\r
// === PROTOTYPES ===
int FIFO_Install(char **Arguments);
int FIFO_IOCtl(tVFS_Node *Node, int Id, void *Data);
-char *FIFO_ReadDir(tVFS_Node *Node, int Id);
+ int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
- int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
void FIFO_Reference(tVFS_Node *Node);
void FIFO_Close(tVFS_Node *Node);
int FIFO_Unlink(tVFS_Node *Node, const char *OldName);
* \fn char *FIFO_ReadDir(tVFS_Node *Node, int Id)
* \brief Reads from the FIFO root
*/
-char *FIFO_ReadDir(tVFS_Node *Node, int Id)
+int FIFO_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX])
{
tPipe *tmp = gFIFO_NamedPipes;
// Entry 0 is Anon Pipes
- if(Id == 0) return strdup("anon");
+ if(Id == 0) {
+ strcpy(Dest, "anon");
+ return 0;
+ }
// Find the id'th node
while(--Id && tmp) tmp = tmp->Next;
- // If node found, return it
- if(tmp) return strdup(tmp->Name);
- // else error return
- return NULL;
+ // If the list ended, error return
+ if(!tmp)
+ return -EINVAL;
+ // Return good
+ strncpy(Dest, tmp->Name, FILENAME_MAX);
+ return 0;
}
/**
/**
* \fn int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
*/
-int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+tVFS_Node *FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
{
return 0;
}
int PCI_Install(char **Arguments);\r
int PCI_ScanBus(int ID, int bFill);\r
\r
-char *PCI_int_ReadDirRoot(tVFS_Node *node, int pos);\r
+ int PCI_int_ReadDirRoot(tVFS_Node *node, int pos, char Dest[FILENAME_MAX]);\r
tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename);\r
Uint32 PCI_int_GetBusAddr(Uint16 Bus, Uint16 Slot, Uint16 Fcn, Uint8 Offset);\r
size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *buffer);\r
/**\r
* \brief Read from Root of PCI Driver\r
*/\r
-char *PCI_int_ReadDirRoot(tVFS_Node *Node, int Pos)\r
+int PCI_int_ReadDirRoot(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])\r
{\r
ENTER("pNode iPos", Node, Pos);\r
if(Pos < 0 || Pos >= giPCI_DeviceCount) {\r
- LEAVE('n');\r
- return NULL;\r
+ LEAVE_RET('i', -EINVAL);\r
}\r
\r
- LEAVE('s', gPCI_Devices[Pos].Name);\r
- return strdup( gPCI_Devices[Pos].Name );\r
+ LOG("Name = %s", gPCI_Devices[Pos].Name);\r
+ strncpy(Dest, gPCI_Devices[Pos].Name, FILENAME_MAX);\r
+ LEAVE_RET('i', 0);\r
}\r
/**\r
*/\r
int SysFS_RemoveFile(int ID);
#endif
-char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Id);
+ int SysFS_Comm_ReadDir(tVFS_Node *Node, int Id, char Dest[FILENAME_MAX]);
tVFS_Node *SysFS_Comm_FindDir(tVFS_Node *Node, const char *Filename);
size_t SysFS_Comm_ReadFile(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
void SysFS_Comm_CloseFile(tVFS_Node *Node);
for( ent = gSysFS_FileList; ent; ent = ent->Next )
{
// It's a reverse sorted list
- if(ent->Node.Inode < ID) return 0;
- if(ent->Node.Inode == ID)
+ if(ent->Node.Inode < (Uint64)ID)
+ return 0;
+ if(ent->Node.Inode == (Uint64)ID)
{
ent->Node.ImplPtr = (void*)Data;
ent->Node.Size = Length;
for( ent = gSysFS_FileList; ent; prev = ent, ent = ent->Next )
{
// It's a reverse sorted list
- if(ent->Node.Inode < ID) return 0;
- if(ent->Node.Inode == ID) break;
+ if(ent->Node.Inode < (Uint64)ID) return 0;
+ if(ent->Node.Inode == (Uint64)ID) break;
}
if(!ent) return 0;
* \fn char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Pos)
* \brief Reads from a SysFS directory
*/
-char *SysFS_Comm_ReadDir(tVFS_Node *Node, int Pos)
+int SysFS_Comm_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tSysFS_Ent *child = (tSysFS_Ent*)Node->ImplPtr;
- if(Pos < 0 || Pos >= Node->Size) return NULL;
+ if(Pos < 0 || (Uint64)Pos >= Node->Size)
+ return -EINVAL;
for( ; child; child = child->Next, Pos-- )
{
- if( Pos == 0 ) return strdup(child->Name);
+ if( Pos == 0 ) {
+ strncpy(Dest, child->Name, FILENAME_MAX);
+ return 0;
+ }
}
- return NULL;
+ return -ENOENT;
}
/**
// === PROTOTYPES ===
int VT_Install(char **Arguments);
-char *VT_ReadDir(tVFS_Node *Node, int Pos);
+ int VT_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *VT_FindDir(tVFS_Node *Node, const char *Name);
int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data);
size_t VT_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
* \fn char *VT_ReadDir(tVFS_Node *Node, int Pos)
* \brief Read from the VTerm Directory
*/
-char *VT_ReadDir(tVFS_Node *Node, int Pos)
+int VT_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- if(Pos < 0) return NULL;
- if(Pos >= NUM_VTS) return NULL;
- return strdup( gVT_Terminals[Pos].Name );
+ if(Pos < 0) return -EINVAL;
+ if(Pos >= NUM_VTS) return -EINVAL;
+ strncpy(Dest, gVT_Terminals[Pos].Name, FILENAME_MAX);
+ return 0;
}
/**
#include <api_drv_disk.h>
// --- Disk Driver Helpers ---
-Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
- tDrvUtil_Read_Callback ReadBlocks, Uint64 BlockSize, void *Argument)
+size_t DrvUtil_ReadBlock(Uint64 Start, size_t Length, void *Buffer,
+ tDrvUtil_Read_Callback ReadBlocks, size_t BlockSize, void *Argument)
{
Uint8 tmp[BlockSize]; // C99
Uint64 block = Start / BlockSize;
int offset = Start - block * BlockSize;
- int leading = BlockSize - offset;
+ size_t leading = BlockSize - offset;
Uint64 num;
int tailings;
- Uint64 ret;
+ size_t ret;
ENTER("XStart XLength pBuffer pReadBlocks XBlockSize pArgument",
Start, Length, Buffer, ReadBlocks, BlockSize, Argument);
return Length;
}
-Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, const void *Buffer,
+size_t DrvUtil_WriteBlock(Uint64 Start, size_t Length, const void *Buffer,
tDrvUtil_Read_Callback ReadBlocks, tDrvUtil_Write_Callback WriteBlocks,
- Uint64 BlockSize, void *Argument)
+ size_t BlockSize, void *Argument)
{
Uint8 tmp[BlockSize]; // C99
Uint64 block = Start / BlockSize;
- int offset = Start - block * BlockSize;
- int leading = BlockSize - offset;
+ size_t offset = Start - block * BlockSize;
+ size_t leading = BlockSize - offset;
Uint64 num;
int tailings;
- Uint64 ret;
+ size_t ret;
ENTER("XStart XLength pBuffer pReadBlocks pWriteBlocks XBlockSize pArgument",
Start, Length, Buffer, ReadBlocks, WriteBlocks, BlockSize, Argument);
extern char *_strdup(const char *File, int Line, const char *Str);
extern char **str_split(const char *__str, char __ch);
extern char *strchr(const char *__s, int __c);
+extern char *strrchr(const char *__s, int __c);
extern int strpos(const char *Str, char Ch);
extern int strpos8(const char *str, Uint32 search);
extern void itoa(char *buf, Uint64 num, int base, int minLength, char pad);
* \param Argument An argument to pass to \a ReadBlocks\r
* \return Number of bytes read\r
*/\r
-extern Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,\r
- tDrvUtil_Read_Callback ReadBlocks, Uint64 BlockSize, void *Argument);\r
+extern size_t DrvUtil_ReadBlock(Uint64 Start, size_t Length, void *Buffer,\r
+ tDrvUtil_Read_Callback ReadBlocks, size_t BlockSize, void *Argument);\r
/**\r
* \brief Writes a range to a block device using aligned writes\r
* \param Start Base byte offset\r
* \param Argument An argument to pass to \a ReadBlocks and \a WriteBlocks\r
* \return Number of bytes written\r
*/\r
-extern Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, const void *Buffer,\r
+extern size_t DrvUtil_WriteBlock(Uint64 Start, size_t Length, const void *Buffer,\r
tDrvUtil_Read_Callback ReadBlocks, tDrvUtil_Write_Callback WriteBlocks,\r
- Uint64 BlockSize, void *Argument);\r
+ size_t BlockSize, void *Argument);\r
\r
/**\r
* \}\r
EEXIST, // Already exists
ENFILE, // Too many open files
ENOTDIR, // Not a directory
+ EIO, // IO Error
EALREADY, // Operation was a NOP
EINTERNAL, // Internal Error
* \brief Read from a directory
* \param Node Pointer to this node
* \param Pos Offset in the directory
- * \return Pointer to the name of the item on the heap (will be freed
- * by the caller). If the directory end has been reached, NULL
- * will be returned.
- * If an item is required to be skipped either &::NULLNode,
- * ::VFS_SKIP or ::VFS_SKIPN(0...1023) will be returned.
+ * \param Dest Destination for filename
+ * \return Zero on success, negative on error or +ve for ignore entry
*/
- char *(*ReadDir)(struct sVFS_Node *Node, int Pos);
+ int (*ReadDir)(struct sVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
/**
* \brief Create a node in a directory
* \param Node Pointer to this node
* \param Name Name of the new child
* \param Flags Flags to apply to the new child (directory or symlink)
- * \return Zero on Success, non-zero on error (see errno.h)
+ * \return Created node or NULL on error
*/
- int (*MkNod)(struct sVFS_Node *Node, const char *Name, Uint Flags);
+ tVFS_Node *(*MkNod)(struct sVFS_Node *Node, const char *Name, Uint Flags);
/**
* \brief Relink (Rename/Remove) a file/directory
typedef Uint32 tMount;
// === CONSTANTS ===
+#define FILENAME_MAX 256
//! Maximum size of a Memory Path generated by VFS_GetMemPath
#define VFS_MEMPATH_SIZE (3 + (BITS/4)*2)
/**
* \param Buffer Destination of read data
* \return Number of read bytes
*/
-extern Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer);
+extern size_t VFS_Read(int FD, size_t Length, void *Buffer);
/**
* \brief Writes data to a file
* \param FD File handle returned by ::VFS_Open
* \param Buffer Source of written data
* \return Number of bytes written
*/
-extern Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer);
+extern size_t VFS_Write(int FD, size_t Length, const void *Buffer);
/**
* \brief Reads from a specific offset in the file
* \param Buffer Source of read data
* \return Number of bytes read
*/
-extern Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer);
+extern size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer);
/**
* \brief Writes to a specific offset in the file
* \param FD File handle returned by ::VFS_Open
* \param Buffer Source of written data
* \return Number of bytes written
*/
-extern Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer);
+extern size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer);
/**
* \brief Sends an IOCtl request to the driver
/**
* \brief Read from a directory
* \param FD File handle returned by ::VFS_Open
- * \param Dest Destination array for the file name (max 255 bytes)
+ * \param Dest Destination array for the file name (max FILENAME_MAX bytes)
* \return Boolean Success
*/
-extern int VFS_ReadDir(int FD, char *Dest);
+extern int VFS_ReadDir(int FD, char Dest[FILENAME_MAX]);
/**
* \brief Wait for an aciton on a file descriptor
* \param MaxHandle Maximum set handle in \a *Handles
{
// ASCII Range
if(Search < 128) {
- if(str[pos] == Search) return pos;
+ if(str[pos] == (char)Search) return pos;
continue;
}
if(*(Uint8*)(str+pos) < 128) continue;
int Hex(char *Dest, size_t Size, const Uint8 *SourceData)
{
- int i;
+ size_t i;
for( i = 0; i < Size; i ++ )
{
sprintf(Dest + i*2, "%02x", SourceData[i]);
*/
int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString)
{
- int i;
-
+ size_t i;
for( i = 0; i < DestSize*2; i += 2 )
{
Uint8 val = 0;
EXPORT(strucmp);
EXPORT(strchr);
+EXPORT(strrchr);
EXPORT(strpos);
EXPORT(strlen);
EXPORT(strcpy);
return NULL;
}
+char *strrchr(const char *__s, int __c)
+{
+ size_t ofs = strlen(__s);
+ while(--ofs && __s[ofs] != __c);
+ if( __s[ofs] == __c )
+ return (char*)__s + ofs;
+ return NULL;
+}
+
/**
* \fn int strpos(const char *Str, char Ch)
* \brief Search a string for an ascii character
int pos = 0, oldpos = 0;
int next = 0;
tVFS_Node *parent;
- int ret;
+ tVFS_Node *ret;
ENTER("sPath xFlags", Path, Flags);
// Create node
ret = parent->Type->MkNod(parent, name, Flags);
+ _CloseNode(ret);
// Free allocated string
free(absPath);
_CloseNode(parent);
// Return whatever the driver said
- LEAVE('i', ret);
- return ret;
+ LEAVE('i', ret==NULL);
+ return ret==NULL;
}
/**
int VFS_ReadDir(int FD, char *Dest)
{
tVFS_Handle *h = VFS_GetHandle(FD);
- char *tmp;
+ int rv;
//ENTER("ph pDest", h, Dest);
return 0;
}
- if(h->Node->Size != -1 && h->Position >= h->Node->Size) {
+ if(h->Node->Size != (Uint64)-1 && h->Position >= h->Node->Size) {
//LEAVE('i', 0);
return 0;
}
do {
- tmp = h->Node->Type->ReadDir(h->Node, h->Position);
- if((Uint)tmp < (Uint)VFS_MAXSKIP)
- h->Position += (Uint)tmp;
+ rv = h->Node->Type->ReadDir(h->Node, h->Position, Dest);
+ if(rv > 0)
+ h->Position += rv;
else
h->Position ++;
- } while(tmp != NULL && (Uint)tmp < (Uint)VFS_MAXSKIP);
+ } while(rv > 0);
- //LOG("tmp = '%s'", tmp);
-
- if(!tmp) {
+ if(rv < 0) {
//LEAVE('i', 0);
return 0;
}
- strcpy(Dest, tmp);
- free(tmp);
-
//LEAVE('i', 1);
return 1;
}
#endif
tVFS_Node *DevFS_InitDevice(const char *Device, const char **Options);
void DevFS_Unmount(tVFS_Node *RootNode);
-char *DevFS_ReadDir(tVFS_Node *Node, int Pos);
+ int DevFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name);
// === GLOBALS ===
/**
* \fn char *DevFS_ReadDir(tVFS_Node *Node, int Pos)
*/
-char *DevFS_ReadDir(tVFS_Node *Node, int Pos)
+int DevFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tDevFS_Driver *dev;
- if(Pos < 0) return NULL;
+ if(Pos < 0) return -EINVAL;
for(dev = gDevFS_Drivers;
dev && Pos--;
dev = dev->Next
);
- if(dev)
- return strdup(dev->Name);
- else
- return NULL;
+ if(dev) {
+ strncpy(Dest, dev->Name, FILENAME_MAX);
+ return 0;
+ }
+ else {
+ return -ENOENT;
+ }
}
/**
// === PROTOTYPES ===
tVFS_Node *Root_InitDevice(const char *Device, const char **Options);
- int Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
tVFS_Node *Root_FindDir(tVFS_Node *Node, const char *Name);
-char *Root_ReadDir(tVFS_Node *Node, int Pos);
+ int Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
size_t Root_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
size_t Root_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
tRamFS_File *Root_int_AllocFile(void);
* \fn int Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
* \brief Create an entry in the root directory
*/
-int Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+tVFS_Node *Root_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
{
tRamFS_File *parent = Node->ImplPtr;
tRamFS_File *child;
ENTER("pNode sName xFlags", Node, Name, Flags);
LOG("Sanity check name length - %i > %i", strlen(Name)+1, sizeof(child->Name));
- if(strlen(Name) + 1 > sizeof(child->Name))
- LEAVE_RET('i', EINVAL);
+ if(strlen(Name) + 1 > sizeof(child->Name)) {
+ errno = EINVAL;
+ LEAVE_RET('n', NULL);
+ }
// Find last child, while we're at it, check for duplication
for( child = parent->Data.FirstChild; child; prev = child, child = child->Next )
{
if(strcmp(child->Name, Name) == 0) {
LOG("Duplicate");
- LEAVE('i', EEXIST);
- return EEXIST;
+ errno = EEXIST;
+ LEAVE_RET('n', NULL);
}
}
parent->Node.Size ++;
- LEAVE('i', EOK);
- return EOK;
+ LEAVE('n', &child->Node);
+ return &child->Node;
}
/**
* \fn char *Root_ReadDir(tVFS_Node *Node, int Pos)
* \brief Get an entry from the filesystem
*/
-char *Root_ReadDir(tVFS_Node *Node, int Pos)
+int Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tRamFS_File *parent = Node->ImplPtr;
tRamFS_File *child = parent->Data.FirstChild;
for( ; child && Pos--; child = child->Next ) ;
- if(child) return strdup(child->Name);
+ if(child) {
+ strncpy(Dest, child->Name, FILENAME_MAX);
+ return 0;
+ }
- return NULL;
+ return -ENOENT;
}
/**
*/
#define DEBUG 0
#include <acess.h>
-#include "vfs.h"
-#include "vfs_int.h"
+#include <vfs.h>
+#include <vfs_ext.h>
+#include <vfs_int.h>
// === CODE ===
/**
* \fn Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
* \brief Read data from a node (file)
*/
-Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
+size_t VFS_Read(int FD, size_t Length, void *Buffer)
{
tVFS_Handle *h;
- Uint64 ret;
+ size_t ret;
ENTER("iFD XLength pBuffer", FD, Length, Buffer);
}
ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer);
- if(ret == -1) LEAVE_RET('i', -1);
+ if(ret == (size_t)-1) LEAVE_RET('i', -1);
h->Position += ret;
LEAVE('X', ret);
* \fn Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
* \brief Read data from a given offset (atomic)
*/
-Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
+size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer)
{
tVFS_Handle *h;
- Uint64 ret;
+ size_t ret;
h = VFS_GetHandle(FD);
if(!h) return -1;
}
ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer);
- if(ret == -1) return -1;
+ if(ret == (size_t)-1) return -1;
return ret;
}
* \fn Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
* \brief Read data from a node (file)
*/
-Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
+size_t VFS_Write(int FD, size_t Length, const void *Buffer)
{
tVFS_Handle *h;
- Uint64 ret;
+ size_t ret;
h = VFS_GetHandle(FD);
if(!h) return -1;
}
ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer);
- if(ret == -1) return -1;
+ if(ret == (size_t)-1) return -1;
h->Position += ret;
return ret;
* \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
* \brief Write data to a file at a given offset
*/
-Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
+size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
{
tVFS_Handle *h;
- Uint64 ret;
+ size_t ret;
h = VFS_GetHandle(FD);
if(!h) return -1;
return -1;
}
ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer);
- if(ret == -1) return -1;
+ if(ret == (size_t)-1) return -1;
return ret;
}
// Set relative to end of file
if(Whence < 0) {
- if( h->Node->Size == -1 ) return -1;
+ if( h->Node->Size == (Uint64)-1 ) return -1;
h->Position = h->Node->Size - Offset;
return 0;
EXPORT(VFS_AddDriver);
// === GLOBALS ===
-tVFS_Node NULLNode = {0};
+tVFS_Node NULLNode = {.Type=NULL};
tShortSpinlock slDriverListLock;
tVFS_Driver *gVFS_Drivers = NULL;
char *gsVFS_DriverFile = NULL;
}
if( !curNode->Type->FindDir )
{
- LOG("Finddir failure on '%s' - No FindDir method in %s", Path, curNode->Type->Name);
+ LOG("Finddir failure on '%s' - No FindDir method in %s", Path, curNode->Type->TypeName);
goto _error;
}
LOG("FindDir{=%p}(%p, '%s')", curNode->Type->FindDir, curNode, pathEle);
path_buffer[ curNode->Size ] = '\0';
LOG("path_buffer = '%s'", path_buffer);
strcat(path_buffer, Path + ofs+nextSlash);
+ // TODO: Pass to VFS_GetAbsPath to handle ../. in the symlink
Path = path_buffer;
// Log_Debug("VFS", "VFS_ParsePath: Symlink translated to '%s'", Path);
LOG("tmpNode = %p", tmpNode);
// Check if file was found
if(!tmpNode) {
- LOG("Node '%s' not found in dir '%s'", &Path[ofs], Path);
+ LOG("Node '%s' not found in dir '%.*s'", &Path[ofs], ofs, Path);
goto _error;
}
_CloseNode( curNode );
if( !node && (Flags & VFS_OPENFLAG_CREATE) )
{
// TODO: Translate `Mode` into ACL and node flags
- // Get parent, create node
- if( VFS_MkNod(absPath, 0) ) {
+ Uint new_flags = 0;
+
+ // Split path at final separator
+ char *file = strrchr(absPath, '/');
+ *file = '\0';
+ file ++;
+
+ // Get parent node
+ tVFS_Mount *pmnt;
+ tVFS_Node *pnode = VFS_ParsePath(absPath, NULL, &pmnt);
+ if(!pnode) {
+ LOG("Unable to open parent '%s'", absPath);
+ free(absPath);
+ errno = ENOENT;
+ LEAVE_RET('i', -1);
+ }
+
+ // TODO: Check ACLs on the parent
+ if( !VFS_CheckACL(pnode, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) {
+ _CloseNode(pnode);
+ pmnt->OpenHandleCount --;
free(absPath);
+ LEAVE('i', -1);
return -1;
}
- node = VFS_ParsePath(absPath, NULL, &mnt);
+
+ // Check that there's a MkNod method
+ if( !pnode->Type || !pnode->Type->MkNod ) {
+ Log_Warning("VFS", "VFS_Open - Directory has no MkNod method");
+ errno = EINVAL;
+ LEAVE_RET('i', -1);
+ }
+
+ node = pnode->Type->MkNod(pnode, file, new_flags);
+ // Fall through on error check
+
+ _CloseNode(pnode);
+ pmnt->OpenHandleCount --;
}
// Free generated path
* dir.c
* - Directory Handling
*/
-#define DEBUG 0
+#define DEBUG 1
#define VERBOSE 0
#include "ext2_common.h"
// === MACROS ===
-#define BLOCK_DIR_OFS(_data, _block) ((Uint16*)(_data)[(_block)])
+#define BLOCK_DIR_OFS(_data, _block) (((Uint16*)(_data))[(_block)])
// === PROTOTYPES ===
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos);
+ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
- int Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int Ext2_Unlink(tVFS_Node *Node, const char *OldName);
int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
// --- Helpers ---
* \param Node Directory node
* \param Pos Position of desired element
*/
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tExt2_Inode inode;
tExt2_DirEnt dirent;
// Check for the end of the list
if(size <= 0 || size > inode.i_size) {
- LEAVE('n');
- return NULL;
+ LEAVE('i', -ENOENT);
+ return -ENOENT;
}
// Read Entry
dirent.name[ dirent.name_len ] = '\0'; // Cap off string
if( dirent.name_len == 0 ) {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE('i', 1);
+ return 1;
}
// Ignore . and .. (these are done in the VFS)
if( (dirent.name[0] == '.' && dirent.name[1] == '\0')
|| (dirent.name[0] == '.' && dirent.name[1] == '.' && dirent.name[2]=='\0')) {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP; // Skip
+ LEAVE('i', 1);
+ return 1; // Skip
}
- LEAVE('s', dirent.name);
- // Create new node
- return strdup(dirent.name);
+ LOG("Name '%s'", dirent.name);
+ strncpy(Dest, dirent.name, FILENAME_MAX);
+ LEAVE('i', 0);
+ return 0;
}
/**
* \fn int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
* \brief Create a new node
*/
-int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
+tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
{
ENTER("pParent sName xFlags", Parent, Name, Flags);
Uint64 inodeNum = Ext2_int_AllocateInode(Parent->ImplPtr, Parent->Inode);
if( inodeNum == 0 ) {
- return -1;
+ LOG("Inode allocation failed");
+ LEAVE_RET('n', NULL);
}
tVFS_Node *child = Ext2_int_CreateNode(Parent->ImplPtr, inodeNum);
if( !child ) {
Ext2_int_DereferenceInode(Parent->ImplPtr, inodeNum);
- return -1;
+ Log_Warning("Ext2", "Ext2_MkNod - Node creation failed");
+ LEAVE_RET('n', NULL);
}
child->Flags = Flags & (VFS_FFLAG_DIRECTORY|VFS_FFLAG_SYMLINK|VFS_FFLAG_READONLY);
// TODO: Set up ACLs
int rv = Ext2_Link(Parent, Name, child);
- child->Type->Close(child);
- LEAVE('i', rv);
- return rv;
+ if( rv ) {
+ Ext2_CloseFile(child);
+ return NULL;
+ }
+ LEAVE_RET('p', child);
}
/**
*/
int Ext2_Unlink(tVFS_Node *Node, const char *OldName)
{
+ Log_Warning("Ext2", "TODO: Impliment Ext2_Unlink");
return 1;
}
*/
int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
{
- #if 0
+ #if 1
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
- tExt2_DirEnt dirent;
+ tExt2_DirEnt *dirent;
tExt2_DirEnt newEntry;
- Uint64 Base; // Block's Base Address
+ Uint64 base; // Block's Base Address
int block = 0, ofs = 0;
Uint size;
void *blockData;
- int bestMatch = -1, bestSize, bestBlock, bestOfs;
+ int bestMatch = -1;
+ int bestSize=0, bestBlock=0, bestOfs=0, bestNeedsSplit=0;
int nEntries;
+
+ ENTER("pNode sName pChild",
+ Node, Name, Child);
blockData = malloc(disk->BlockSize);
// Create a stub entry
newEntry.inode = Child->Inode;
newEntry.name_len = strlen(Name);
- newEntry.rec_len = (newEntry.name_len+3+8)&~3;
+ newEntry.rec_len = ((newEntry.name_len+3)&~3) + EXT2_DIRENT_SIZE;
newEntry.type = inode.i_mode >> 12;
memcpy(newEntry.name, Name, newEntry.name_len);
size = inode.i_size;
// Get a lock on the inode
- Ext2_int_LockInode(disk, Node->Inode);
-
+ //Ext2_int_LockInode(disk, Node->Inode);
+ Mutex_Acquire(&Node->Lock);
+
+// if( !Node->Data ) {
+// }
+
// Get First Block
// - Do this ourselves as it is a simple operation
base = inode.i_block[0] * disk->BlockSize;
VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
block = 0;
+ nEntries = 0;
// Find File
while(size > 0)
{
"Directory entry %i of inode 0x%x extends over a block boundary",
nEntries, (Uint)Node->Inode);
}
- else {
-
+ else
+ {
+ LOG("Entry %i: %x %i bytes", nEntries, dirent->type, dirent->rec_len);
// Free entry
- if(dirent->type == 0) {
+ if(dirent->type == 0)
+ {
if( dirent->rec_len >= newEntry.rec_len
&& (bestMatch == -1 || bestSize > dirent->rec_len) )
{
bestSize = dirent->rec_len;
bestBlock = block;
bestOfs = ofs;
+ bestNeedsSplit = 0;
}
}
// Non free - check name to avoid duplicates
- else {
+ else
+ {
+ LOG(" name='%.*s'", dirent->name_len, dirent->name);
if(strncmp(Name, dirent->name, dirent->name_len) == 0) {
- Ext2_int_UnlockInode(disk, Node->Inode);
+ //Ext2_int_UnlockInode(disk, Node->Inode);
+ Mutex_Release(&Node->Lock);
+ LEAVE('i', 1);
return 1; // ERR_???
}
+
+ int spare_space = dirent->rec_len - (dirent->name_len + EXT2_DIRENT_SIZE);
+ if( spare_space > newEntry.rec_len
+ && (bestMatch == -1 || bestSize > spare_space) )
+ {
+ bestMatch = nEntries;
+ bestSize = spare_space;
+ bestBlock = block;
+ bestOfs = ofs;
+ bestNeedsSplit = 1;
+ }
}
}
// Increment the pointer
nEntries ++;
ofs += dirent->rec_len;
- if( ofs >= disk->BlockSize ) {
+ size -= dirent->rec_len;
+ if( size > 0 && ofs >= disk->BlockSize ) {
// Read the next block if needed
- BLOCK_DIR_OFS(Node->Data, block) = nEntries;
+ // BLOCK_DIR_OFS(Node->Data, block) = nEntries;
block ++;
ofs = 0;
base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
}
}
+ LOG("bestMatch = %i", bestMatch);
+ // If EOF was reached with no space, check if we can fit one on the end
+ if( bestMatch < 0 && ofs + newEntry.rec_len < disk->BlockSize ) {
+ Node->Size += newEntry.rec_len;
+ Node->Flags |= VFS_FFLAG_DIRTY;
+ bestBlock = block;
+ bestOfs = ofs;
+ bestSize = newEntry.rec_len;
+ bestNeedsSplit = 0;
+ }
// Check if a free slot was found
- if( bestMatch >= 0 ) {
+ if( bestMatch >= 0 )
+ {
// Read-Modify-Write
- bestBlock = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
- if( block > 0 )
- bestMatch = BLOCK_DIR_OFS(Node->Data, bestBlock);
+ base = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
dirent = blockData + bestOfs;
- memcpy(dirent, newEntry, newEntry.rec_len);
+ // Shorten a pre-existing entry
+ if(bestNeedsSplit)
+ {
+ dirent->rec_len = EXT2_DIRENT_SIZE + dirent->name_len;
+ bestOfs += dirent->rec_len;
+ //bestSize -= dirent->rec_len; // (not needed, bestSize is the spare space after)
+ dirent = blockData + bestOfs;
+ }
+ // Insert new file entry
+ memcpy(dirent, &newEntry, newEntry.rec_len);
+ // Create a new blank entry
+ if( bestSize != newEntry.rec_len )
+ {
+ bestOfs += newEntry.rec_len;
+ dirent = blockData + bestOfs;
+
+ dirent->rec_len = bestSize - newEntry.rec_len;
+ dirent->type = 0;
+ }
+ // Save changes
VFS_WriteAt( disk->FD, base, disk->BlockSize, blockData );
}
else {
// Allocate block, Write
- block = Ext2_int_AllocateBlock(Disk, block);
- Log_Warning("EXT2", "");
+ Uint32 newblock = Ext2_int_AllocateBlock(disk, base / disk->BlockSize);
+ Ext2_int_AppendBlock(disk, &inode, newblock);
+ base = newblock * disk->BlockSize;
+ Node->Size += newEntry.rec_len;
+ Node->Flags |= VFS_FFLAG_DIRTY;
+ memcpy(blockData, &newEntry, newEntry.rec_len);
+ memset(blockData + newEntry.rec_len, 0, disk->BlockSize - newEntry.rec_len);
+ VFS_WriteAt( disk->FD, base, disk->BlockSize, blockData );
}
- Ext2_int_UnlockInode(disk, Node->Inode);
+ Child->ImplInt ++;
+ Child->Flags |= VFS_FFLAG_DIRTY;
+
+ //Ext2_int_UnlockInode(disk, Node->Inode);
+ Mutex_Release(&Node->Lock);
+ LEAVE('i', 0);
return 0;
#else
+ Log_Warning("Ext2", "TODO: Impliment Ext2_Link");
return 1;
#endif
}
// Set identifiers
retNode.Inode = InodeID;
retNode.ImplPtr = Disk;
+ retNode.ImplInt = inode.i_links_count;
// Set file length
retNode.Size = inode.i_size;
// Save in node cache and return saved node
return Inode_CacheNode(Disk->CacheID, &retNode);
}
+
+int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)
+{
+ Log_Warning("Ext2","TODO: Impliment Ext2_int_WritebackNode");
+ return 0;
+}
+
#include "ext2_common.h"\r
#include <modules.h>\r
\r
+#define MIN_BLOCKS_PER_GROUP 2\r
+#define MAX_BLOCK_LOG_SIZE 10 // 1024 << 10 = 1MiB\r
+\r
// === IMPORTS ===\r
extern tVFS_NodeType gExt2_DirType;\r
\r
*/\r
tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)\r
{\r
- tExt2_Disk *disk;\r
+ tExt2_Disk *disk = NULL;\r
int fd;\r
int groupCount;\r
tExt2_SuperBlock sb;\r
if(sb.s_magic != 0xEF53) {\r
Log_Warning("EXT2", "Volume '%s' is not an EXT2 volume (0x%x != 0xEF53)",\r
Device, sb.s_magic);\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
+ goto _error;\r
}\r
- \r
+\r
+ if( sb.s_blocks_per_group < MIN_BLOCKS_PER_GROUP ) {\r
+ Log_Warning("Ext2", "Blocks per group is too small (%i < %i)",\r
+ sb.s_blocks_per_group, MIN_BLOCKS_PER_GROUP);\r
+ goto _error;\r
+ } \r
+\r
// Get Group count\r
groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
LOG("groupCount = %i", groupCount);\r
disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
if(!disk) {\r
Log_Warning("EXT2", "Unable to allocate disk structure");\r
- VFS_Close(fd);\r
- LEAVE('n');\r
- return NULL;\r
+ goto _error;\r
}\r
disk->FD = fd;\r
memcpy(&disk->SuperBlock, &sb, 1024);\r
disk->CacheID = Inode_GetHandle();\r
\r
// Get Block Size\r
+ if( sb.s_log_block_size > MAX_BLOCK_LOG_SIZE ) {\r
+ Log_Warning("Ext2", "Block size (log2) too large (%i > %i)",\r
+ sb.s_log_block_size, MAX_BLOCK_LOG_SIZE);\r
+ goto _error;\r
+ }\r
disk->BlockSize = 1024 << sb.s_log_block_size;\r
LOG("Disk->BlockSie = 0x%x (1024 << %i)", disk->BlockSize, sb.s_log_block_size);\r
\r
\r
LEAVE('p', &disk->RootNode);\r
return &disk->RootNode;\r
+_error:\r
+ if( disk )\r
+ free(disk);\r
+ VFS_Close(fd);\r
+ LEAVE('n');\r
+ return NULL;\r
}\r
\r
/**\r
void Ext2_CloseFile(tVFS_Node *Node)\r
{\r
tExt2_Disk *disk = Node->ImplPtr;\r
+ ENTER("pNode", Node);\r
\r
if( Mutex_Acquire(&Node->Lock) != 0 )\r
{\r
+ LEAVE('-');\r
return ;\r
}\r
\r
if( Node->Flags & VFS_FFLAG_DIRTY )\r
{\r
// Commit changes\r
+ Log_Warning("Ext2", "TODO: Commit node changes");\r
}\r
\r
int was_not_referenced = (Node->ImplInt == 0);\r
tVFS_ACL *acls = Node->ACLs;\r
- if( Inode_UncacheNode(disk->CacheID, Node->Inode) )\r
+ if( Inode_UncacheNode(disk->CacheID, Node->Inode) == 1 )\r
{\r
if( was_not_referenced )\r
{\r
+ LOG("Removng inode");\r
// Remove inode\r
+ Log_Warning("Ext2", "TODO: Remove inode when not referenced");\r
}\r
if( acls != &gVFS_ACL_EveryoneRW ) {\r
free(acls);\r
}\r
+ LOG("Node cleaned");\r
+ }\r
+ else {\r
+ LOG("Still referenced, releasing lock");\r
+ Mutex_Release(&Node->Lock);\r
}\r
+ LEAVE('-');\r
return ;\r
}\r
\r
*/\r
Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
{\r
-// Uint block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
- Log_Warning("EXT2", "Ext2_int_AllocateInode is unimplemented");\r
+ Uint start_group = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
+ Uint group = start_group;\r
+\r
+ if( Disk->SuperBlock.s_free_inodes_count == 0 ) \r
+ {\r
+ Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes on %p", Disk);\r
+ return 0;\r
+ }\r
+\r
+ while( group < Disk->GroupCount && Disk->Groups[group].bg_free_inodes_count == 0 )\r
+ group ++;\r
+ if( group == Disk->GroupCount )\r
+ {\r
+ group = 0;\r
+ while( group < start_group && Disk->Groups[group].bg_free_inodes_count == 0 )\r
+ group ++;\r
+ }\r
+ \r
+ if( Disk->Groups[group].bg_free_inodes_count == 0 )\r
+ {\r
+ Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes on %p, but superblock says some free", Disk);\r
+ return 0;\r
+ }\r
+\r
+ // Load bitmap for group\r
+ // (s_inodes_per_group / 8) bytes worth\r
+ // - Allocate a buffer the size of a sector/block\r
+ // - Read in part of the bitmap\r
+ // - Search for a free inode\r
+ tExt2_Group *bg = &Disk->Groups[group];\r
+ int ofs = 0;\r
+ do {\r
+ const int sector_size = 512;\r
+ Uint8 buf[sector_size];\r
+ VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_inode_bitmap+ofs, sector_size, buf);\r
+\r
+ int byte, bit;\r
+ for( byte = 0; byte < sector_size && buf[byte] != 0xFF; byte ++ )\r
+ ;\r
+ if( byte < sector_size )\r
+ {\r
+ for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)\r
+ ;\r
+ ASSERT(bit != 8);\r
+ buf[byte] |= 1 << bit;\r
+ VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_inode_bitmap+ofs, sector_size, buf);\r
+\r
+ bg->bg_free_inodes_count --;\r
+ Disk->SuperBlock.s_free_inodes_count --;\r
+\r
+ Uint32 ret = group * Disk->SuperBlock.s_inodes_per_group + byte * 8 + bit + 1;\r
+ Log_Debug("Ext2", "Ext2_int_AllocateInode - Allocated 0x%x", ret);\r
+ return ret;\r
+ }\r
+\r
+ ofs += sector_size;\r
+ } while(ofs < Disk->SuperBlock.s_inodes_per_group / 8);\r
+\r
+ Log_Notice("Ext2", "Ext2_int_AllocateInode - Out of inodes in group %p:%i but header reported free",\r
+ Disk, group);\r
+\r
return 0;\r
}\r
\r
*/\r
void Ext2_int_DereferenceInode(tExt2_Disk *Disk, Uint32 Inode)\r
{\r
- \r
+ Log_Warning("Ext2", "TODO: Impliment Ext2_int_DereferenceInode");\r
}\r
\r
/**\r
* 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>
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 int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
-extern int Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+extern tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
extern int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
// --- Read ---
extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer);
// --- Write ---
extern size_t Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer);
+extern Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 LastBlock);
+extern void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
+extern int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
#endif
Uint8 type; //!< File Type (Duplicate of ext2_inode_s.i_mode)\r
char name[EXT2_NAME_LEN+1]; //!< File name\r
};\r
-#define EXT2_DIRENT_SIZE (sizeof(struct ext2_dir_entry_s)-EXT2_NAME_LEN+1)\r
+#define EXT2_DIRENT_SIZE (sizeof(struct ext2_dir_entry_s)-(EXT2_NAME_LEN+1))\r
\r
#endif\r
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) ) {
+ if( Ext2_int_AppendBlock(disk, &inode, block) ) {
+ Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
+ block, disk, Node->Inode);
Ext2_int_DeallocateBlock(disk, block);
goto ret;
}
// Last block :D
block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
if(!block) goto ret;
- if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
+ if( Ext2_int_AppendBlock(disk, &inode, block) ) {
+ Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
+ block, disk, Node->Inode);
Ext2_int_DeallocateBlock(disk, block);
goto ret;
}
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;
-
+ Uint firstgroup = PrevBlock / bpg;
+ Uint blockgroup = firstgroup;
+ tExt2_Group *bg;
+
+ // TODO: Need to do locking on the bitmaps
+
// Are there any free blocks?
- if(Disk->SuperBlock.s_free_blocks_count == 0) return 0;
-
- if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
+ if(Disk->SuperBlock.s_free_blocks_count == 0)
+ return 0;
+
+ // First: Check the next block after \a PrevBlock
+ if( (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group != 0
+ && Disk->Groups[blockgroup].bg_free_blocks_count > 0 )
{
- // Search block group's bitmap
- for(i = 0; i < bpg; i++)
+ bg = &Disk->Groups[blockgroup];
+ const int sector_size = 512;
+ Uint8 buf[sector_size];
+ int iblock = (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group;
+ int byte = iblock / 8;
+ int ofs = byte / sector_size * sector_size;
+ byte %= sector_size;
+ VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+ if( (buf[byte] & (1 << (iblock%8))) == 0 )
{
- // 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] == 0xFFFFFFFF ) {
- 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
+ // Free block - nice and contig allocation
+ buf[byte] |= (1 << (iblock%8));
+ VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+ bg->bg_free_blocks_count --;
+ Disk->SuperBlock.s_free_blocks_count --;
+ #if EXT2_UPDATE_WRITEBACK
+ Ext2_int_UpdateSuperblock(Disk);
+ #endif
+ return PrevBlock + 1;
}
-
- // 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
+ // Used... darnit
+ // Fall through and search further
}
- else
+
+ // Second: Search for a group with free blocks
+ while( blockgroup < Disk->GroupCount && Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
+ blockgroup ++;
+ if( Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
{
- checkAll:
- Log_Warning("EXT2", "TODO - Implement using blocks outside the current block group");
+ blockgroup = 0;
+ while( blockgroup < firstgroup && Disk->Groups[blockgroup].bg_free_blocks_count == 0 )
+ blockgroup ++;
+ }
+ if( Disk->Groups[blockgroup].bg_free_blocks_count == 0 ) {
+ Log_Notice("Ext2", "Ext2_int_AllocateBlock - Out of blockss on %p, but superblock says some free",
+ Disk);
return 0;
}
+
+ // Search the bitmap for a free block
+ bg = &Disk->Groups[blockgroup];
+ int ofs = 0;
+ do {
+ const int sector_size = 512;
+ Uint8 buf[sector_size];
+ VFS_ReadAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+ int byte, bit;
+ for( byte = 0; byte < sector_size && buf[byte] != 0xFF; byte ++ )
+ ;
+ if( byte < sector_size )
+ {
+ for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)
+ ;
+ ASSERT(bit != 8);
+ buf[byte] |= 1 << bit;
+ VFS_WriteAt(Disk->FD, Disk->BlockSize*bg->bg_block_bitmap+ofs, sector_size, buf);
+
+ bg->bg_free_blocks_count --;
+ Disk->SuperBlock.s_free_blocks_count --;
+
+ #if EXT2_UPDATE_WRITEBACK
+ Ext2_int_UpdateSuperblock(Disk);
+ #endif
+
+ Uint32 ret = blockgroup * Disk->SuperBlock.s_blocks_per_group + byte * 8 + bit;
+ Log_Debug("Ext2", "Ext2_int_AllocateBlock - Allocated 0x%x", ret);
+ return ret;
+ }
+ } while(ofs < Disk->SuperBlock.s_blocks_per_group / 8);
- // Reduce global count
- Disk->SuperBlock.s_free_blocks_count --;
- #if EXT2_UPDATE_WRITEBACK
- Ext2_int_UpdateSuperblock(Disk);
- #endif
-
- return block;
+ Log_Notice("Ext2", "Ext2_int_AllocateBlock - Out of block in group %p:%i but header reported free",
+ Disk, blockgroup);
+ return 0;
}
/**
*/
void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
{
+ Log_Warning("Ext2", "TODO: Impliment Ext2_int_DeallocateBlock");
}
/**
if( nBlocks == 0 ) {
Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
if( !Inode->i_block[12] ) {
+ Log_Warning("Ext2", "Allocating indirect block failed");
free(blocks);
return 1;
}
if( nBlocks == 0 ) {
Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
if( !Inode->i_block[13] ) {
+ Log_Warning("Ext2", "Allocating double indirect block failed");
free(blocks);
return 1;
}
id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
if( !id1 ) {
free(blocks);
+ Log_Warning("Ext2", "Allocating double indirect block (l2) failed");
return 1;
}
blocks[nBlocks/dwPerBlock] = id1;
if( nBlocks == 0 ) {
Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
if( !Inode->i_block[14] ) {
+ Log_Warning("Ext2", "Allocating triple indirect block failed");
free(blocks);
return 1;
}
{
id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
if( !id1 ) {
+ Log_Warning("Ext2", "Allocating triple indirect block (l2) failed");
free(blocks);
return 1;
}
if( nBlocks % dwPerBlock == 0 ) {
id2 = Ext2_int_AllocateBlock(Disk, id1);
if( !id2 ) {
+ Log_Warning("Ext2", "Allocating triple indirect block (l3) failed");
free(blocks);
return 1;
}
return 0;
}
- Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
+ Log_Warning("Ext2", "Inode ?? cannot have a block appended to it, all indirects used");
free(blocks);
return 1;
}
Uint32 ClusterCount; //!< Total Cluster Count
fat_bootsect bootsect; //!< Boot Sector
tVFS_Node rootNode; //!< Root Node
- int BytesPerCluster;
+ size_t BytesPerCluster;
tMutex lNodeCache;
tFAT_CachedNode *NodeCache;
extern void FAT_int_WriteCluster(tFAT_VolInfo *Disk, Uint32 Cluster, const void *Buffer);
// --- Directory Access ---
-extern char *FAT_ReadDir(tVFS_Node *Node, int ID);
+extern int FAT_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
extern tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name);
extern tVFS_Node *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
extern int FAT_int_GetEntryByCluster(tVFS_Node *DirNode, Uint32 Cluster, fat_filetable *Entry);
#if SUPPORT_WRITE
extern int FAT_int_WriteDirEntry(tVFS_Node *Node, int ID, fat_filetable *Entry);
-extern int FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);
+extern tVFS_Node *FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);
extern int FAT_Link(tVFS_Node *DirNode, const char *NewName, tVFS_Node *Node);
extern int FAT_Unlink(tVFS_Node *DirNode, const char *OldName);
#endif
// === PROTOTYPES ===
void FAT_int_ProperFilename(char *dest, const char *src);
-char *FAT_int_CreateName(fat_filetable *ft, const Uint16 *LongFileName);
+ int FAT_int_CreateName(fat_filetable *ft, const Uint16 *LongFileName, char *Dest);
int FAT_int_ConvertUTF16_to_UTF8(Uint8 *Dest, const Uint16 *Source);
int FAT_int_ConvertUTF8_to_UTF16(Uint16 *Dest, const Uint8 *Source);
Uint16 *FAT_int_GetLFN(tVFS_Node *Node, int ID);
void FAT_int_DelLFN(tVFS_Node *Node, int ID);
#endif
-char *FAT_ReadDir(tVFS_Node *Node, int ID);
+ int FAT_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
tVFS_Node *FAT_FindDir(tVFS_Node *Node, const char *Name);
tVFS_Node *FAT_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
#if SUPPORT_WRITE
- int FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *FAT_Mknod(tVFS_Node *Node, const char *Name, Uint Flags);
int FAT_int_IsValid83Filename(const char *Name);
int FAT_Link(tVFS_Node *DirNode, const char *NewName, tVFS_Node *Node);
int FAT_Relink(tVFS_Node *node, const char *OldName, const char *NewName);
* \param LongFileName Long file name pointer
* \return Filename as a heap string
*/
-char *FAT_int_CreateName(fat_filetable *ft, const Uint16 *LongFileName)
+int FAT_int_CreateName(fat_filetable *ft, const Uint16 *LongFileName, char *Dest)
{
- char *ret;
ENTER("pft sLongFileName", ft, LongFileName);
- //Log_Debug("FAT", "FAT_int_CreateName(ft=%p, LongFileName=%p'%s')", ft, LongFileName);
#if USE_LFN
if(LongFileName && LongFileName[0] != 0)
{
int len = FAT_int_ConvertUTF16_to_UTF8(NULL, LongFileName);
- ret = malloc( len + 1 );
- FAT_int_ConvertUTF16_to_UTF8((Uint8*)ret, LongFileName);
+ if( len > FILENAME_MAX ) {
+ return -1;
+ }
+ FAT_int_ConvertUTF16_to_UTF8((Uint8*)Dest, LongFileName);
}
else
{
#endif
- ret = (char*) malloc(13);
- if( !ret ) {
- Log_Warning("FAT", "FAT_int_CreateName: malloc(13) failed");
- return NULL;
- }
- FAT_int_ProperFilename(ret, ft->name);
+ FAT_int_ProperFilename(Dest, ft->name);
#if USE_LFN
}
#endif
- LEAVE('s', ret);
- return ret;
+ return 0;
}
#if USE_LFN
* \param ID Directory position
* \return Filename as a heap string, NULL or VFS_SKIP
*/
-char *FAT_ReadDir(tVFS_Node *Node, int ID)
+int FAT_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
{
fat_filetable fileinfo[16]; // sizeof(fat_filetable)=32, so 16 per sector
int a;
- char *ret;
#if USE_LFN
Uint16 *lfn = NULL;
#endif
if(FAT_int_ReadDirSector(Node, ID/16, fileinfo))
{
LOG("End of chain, end of dir");
- LEAVE('n');
- return NULL;
+ LEAVE('i', -EIO);
+ return -EIO;
}
// Offset in sector
if( fileinfo[a].name[0] == '\0' ) {
Node->Size = ID;
LOG("End of list");
- LEAVE('n');
- return NULL; // break
+ LEAVE('i', -ENOENT);
+ return -ENOENT; // break
}
// Check for empty entry
if( (Uint8)fileinfo[a].name[0] == 0xE5 ) {
LOG("Empty Entry");
- #if 0 // Stop on empty entry?
- LEAVE('n');
- return NULL; // Stop
- #else
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP; // Skip
- #endif
+ LEAVE_RET('i', 1); // Skip
}
#if USE_LFN
a = FAT_int_ParseLFN(&fileinfo[a], lfn);
if( a < 0 ) {
LOG("Invalid LFN, error");
- LEAVE('n');
- return NULL;
+ LEAVE_RET('i', -EIO);
}
-// LOG("lfn = '%s'", lfn);
- //Log_Debug("FAT", "lfn = '%s'", lfn);
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE_RET('i', 1); // Skip
}
#endif
// Check if it is a volume entry
if(fileinfo[a].attrib & 0x08) {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE_RET('i', 1); // Skip
}
// Ignore .
if(fileinfo[a].name[0] == '.' && fileinfo[a].name[1] == ' ') {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE_RET('i', 1); // Skip
}
// and ..
if(fileinfo[a].name[0] == '.' && fileinfo[a].name[1] == '.' && fileinfo[a].name[2] == ' ') {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE_RET('i', 1); // Skip
}
LOG("name='%c%c%c%c%c%c%c%c.%c%c%c'",
#if USE_LFN
lfn = FAT_int_GetLFN(Node, ID);
//Log_Debug("FAT", "lfn = %p'%s'", lfn, lfn);
- ret = FAT_int_CreateName(&fileinfo[a], lfn);
+ FAT_int_CreateName(&fileinfo[a], lfn, Dest);
#else
- ret = FAT_int_CreateName(&fileinfo[a], NULL);
+ FAT_int_CreateName(&fileinfo[a], NULL, Dest);
#endif
- LEAVE('s', ret);
- return ret;
+ LEAVE('i', 0);
+ return 0;
}
/**
/**
* \brief Create a new node
*/
-int FAT_Mknod(tVFS_Node *DirNode, const char *Name, Uint Flags)
+tVFS_Node *FAT_Mknod(tVFS_Node *DirNode, const char *Name, Uint Flags)
{
tFAT_VolInfo *disk = DirNode->ImplPtr;
int rv;
tVFS_Node *newnode = FAT_int_CreateNode(DirNode, &ft);
if( !newnode ) {
- return -1;
+ errno = -EINTERNAL;
+ return NULL;
}
LOG("newnode = %p", newnode);
if( (rv = FAT_Link(DirNode, Name, newnode)) ) {
newnode->ImplInt |= FAT_FLAG_DELETE;
}
- FAT_CloseFile(newnode);
- LEAVE('i', rv);
- return rv;
+ LEAVE('p', newnode);
+ return newnode;
}
/**
// === Functions ===
-extern size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
-extern char *InitRD_ReadDir(tVFS_Node *Node, int ID);
-extern tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name);
+//extern size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
+//extern int InitRD_ReadDir(tVFS_Node *Node, int ID);
+//extern tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name);
// === Globals ===
tVFS_NodeType gInitRD_DirType;
void InitRD_Unmount(tVFS_Node *Node);
tVFS_Node *InitRD_GetNodeFromINode(tVFS_Node *Root, Uint64 Inode);
size_t InitRD_ReadFile(tVFS_Node *Node, off_t Offset, size_t Size, void *Buffer);
-char *InitRD_ReadDir(tVFS_Node *Node, int ID);
+ int InitRD_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
tVFS_Node *InitRD_FindDir(tVFS_Node *Node, const char *Name);
void InitRD_DumpDir(tVFS_Node *Node, int Indent);
/**
* \brief Read from a directory
*/
-char *InitRD_ReadDir(tVFS_Node *Node, int ID)
+int InitRD_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
{
tInitRD_File *dir = Node->ImplPtr;
if(ID >= Node->Size)
- return NULL;
+ return -EINVAL;
- return strdup(dir[ID].Name);
+ strncpy(Dest, dir[ID].Name, FILENAME_MAX);
+ return 0;
}
/**
};
} PACKED tNTFS_FILE_Attrib;
+extern int NTFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+extern tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name);
+
#endif
#include "index.h"
// === PROTOTYPES ===
-char *NTFS_ReadDir(tVFS_Node *Node, int Pos);
+ int NTFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name);
Uint64 NTFS_int_IndexLookup(Uint64 Inode, const char *IndexName, const char *Str);
/**
* \brief Get the name of an indexed directory entry
*/
-char *NTFS_ReadDir(tVFS_Node *Node, int Pos)
+int NTFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- return NULL;
+ return -ENOTIMPL;
}
/**
#include "common.h"
#include <modules.h>
-// === IMPORTS ===
-extern char *NTFS_ReadDir(tVFS_Node *Node, int Pos);
-extern tVFS_Node *NTFS_FindDir(tVFS_Node *Node, const char *Name);
-
// === PROTOTYPES ===
int NTFS_Install(char **Arguments);
tVFS_Node *NTFS_InitDevice(const char *Devices, const char **Options);
tVFS_Node *RAMFS_InitDevice(const char *Device, const char **Options);
void RAMFS_Unmount(tVFS_Node *Node);
// --- Directories ---
-char *RAMFS_ReadDir(tVFS_Node *Node, int Index);
+ int RAMFS_ReadDir(tVFS_Node *Node, int Index, char Dest[256]);
tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name);
- int RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int RAMFS_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *Node);
int RAMFS_Unlink(tVFS_Node *Node, const char *Name);
// --- Files ---
}
// --- Directories ---
-char *RAMFS_ReadDir(tVFS_Node *Node, int Index)
+int RAMFS_ReadDir(tVFS_Node *Node, int Index, char Dest[FILENAME_MAX])
{
tRAMFS_Dir *dir = Node->ImplPtr;
for( tRAMFS_DirEnt *d = dir->FirstEnt; d; d = d->Next )
{
if( Index -- == 0 ) {
LOG("Return %s", d->Name);
- return strdup(d->Name);
+ strncpy(Dest, d->Name, FILENAME_MAX);
+ return 0;
}
}
- LOG("Return NULL");
- return NULL;
+ LOG("Return -ENOENT");
+ return -ENOENT;
}
tVFS_Node *RAMFS_FindDir(tVFS_Node *Node, const char *Name)
return NULL;
}
-int RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+tVFS_Node *RAMFS_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
{
tRAMFS_Dir *dir = Node->ImplPtr;
if( RAMFS_FindDir(Node, Name) != NULL )
- return -1;
+ return NULL;
tRAMFS_DirEnt *de = malloc( sizeof(tRAMFS_DirEnt) + strlen(Name) + 1 );
de->Next = NULL;
dir->FirstEnt = de;
dir->LastEnt = de;
- return 0;
+ return &de->Inode->Node;
}
int RAMFS_Link(tVFS_Node *DirNode, const char *Name, tVFS_Node *FileNode)
void *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr);
void IPStack_Adapter_Del(void *Handle);
// --- VFS API ---
-char *Adapter_ReadDir(tVFS_Node *Node, int Pos);
+ int Adapter_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name);
int Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data);
int Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data);
}
// --- VFS API ---
-char *Adapter_ReadDir(tVFS_Node *Node, int Pos)
+int Adapter_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- if( Pos < 0 ) return NULL;
+ if( Pos < 0 ) return -EINVAL;
// Loopback
if( Pos == 0 ) {
- return strdup("lo");
+ strcpy(Dest, "lo");
+ return 0;
}
Pos --;
tAdapter *a; int i;\
for(i=0,a=list; i < Pos && a; i ++, a = a->Next ); \
if( a ) { \
- return Adapter_GetName(a);\
+ strncpy(Dest, Adapter_GetName(a), FILENAME_MAX);\
+ return 0;\
} \
Pos -= i; \
} while(0);
CHECK_LIST(gpIP_AdapterList, "eth");
// TODO: Support other types of adapters (wifi, tap, ...)
- return NULL;
+ return -EINVAL;
}
tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name)
--- /dev/null
+
+#ifndef _IPSTACK__INIT_H_
+#define _IPSTACK__INIT_H_
+
+extern int ARP_Initialise();
+extern void UDP_Initialise();
+extern void TCP_Initialise();
+extern int IPv4_Initialise();
+extern int IPv6_Initialise();
+
+#endif
+
#include "link.h"
#include <api_drv_common.h>
#include "include/adapters.h"
+#include "interface.h"
// === CONSTANTS ===
//! Default timeout value, 5 seconds
extern tVFS_Node gIP_AdaptersNode;
// === PROTOTYPES ===
-char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
+ int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
int IPStack_AddFile(tSocketFile *File);
tInterface *IPStack_AddInterface(const char *Device, const char *Name);
-char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
+ int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data);
// === GLOBALS ===
+tVFS_NodeType gIP_RootNodeType = {
+ .ReadDir = IPStack_Root_ReadDir,
+ .FindDir = IPStack_Root_FindDir,
+ .IOCtl = IPStack_Root_IOCtl
+};
tVFS_NodeType gIP_InterfaceNodeType = {
.ReadDir = IPStack_Iface_ReadDir,
.FindDir = IPStack_Iface_FindDir,
/**
* \brief Read from the IP Stack's Device Directory
*/
-char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tInterface *iface;
- char *name;
ENTER("pNode iPos", Node, Pos);
// Routing Subdir
if( Pos == 0 ) {
- LEAVE('s', "routes");
- return strdup("routes");
+ strcpy(Dest, "routes");
+ return 0;
}
// Adapters
if( Pos == 1 ) {
- LEAVE('s', "adapters");
- return strdup("adapters");
+ strcpy(Dest, "adapters");
+ return 0;
}
// Pseudo Interfaces
if( Pos == 2 ) {
- LEAVE('s', "lo");
- return strdup("lo");
+ strcpy(Dest, "lo");
+ return 0;
}
Pos -= 3;
// Did we run off the end?
if(!iface) {
- LEAVE('n');
- return NULL;
- }
-
- name = malloc(4);
- if(!name) {
- Log_Warning("IPStack", "IPStack_Root_ReadDir - malloc error");
- LEAVE('n');
- return NULL;
+ LEAVE('i', -EINTERNAL);
+ return -EINVAL;
}
// Create the name
Pos = iface->Node.ImplInt;
- if(Pos < 10) {
- name[0] = '0' + Pos;
- name[1] = '\0';
- }
- else if(Pos < 100) {
- name[0] = '0' + Pos/10;
- name[1] = '0' + Pos%10;
- name[2] = '\0';
- }
- else {
- name[0] = '0' + Pos/100;
- name[1] = '0' + (Pos/10)%10;
- name[2] = '0' + Pos%10;
- name[3] = '\0';
- }
+ snprintf(Dest, FILENAME_MAX, "%i", Pos);
- LEAVE('s', name);
- // Return the pre-generated name
- return name;
+ LEAVE('i', 0);
+ return 0;
}
/**
/**
* \brief Read from an interface's directory
*/
-char *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tSocketFile *file = gIP_FileTemplates;
while(Pos-- && file) {
file = file->Next;
}
- if(!file) return NULL;
+ if(!file)
+ return -EINVAL;
- return strdup(file->Name);
+ strncpy(Dest, file->Name, FILENAME_MAX);
+ return 0;
}
/**
--- /dev/null
+
+#ifndef _IPSTACK__INTERFACE_H_
+#define _IPSTACK__INTERFACE_H_
+
+extern tInterface gIP_LoopInterface;
+extern tVFS_NodeType gIP_RootNodeType;
+extern tInterface *IPStack_AddInterface(const char *Device, const char *Name);
+
+#endif
+
#include <modules.h>
#include <fs_devfs.h>
#include "include/adapters.h"
+#include "interface.h"
+#include "init.h"
// === IMPORTS ===
-extern int ARP_Initialise();
-extern void UDP_Initialise();
-extern void TCP_Initialise();
-extern int IPv4_Initialise();
-extern int IPv6_Initialise();
-
-extern char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
-extern tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
-extern int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
-extern tInterface gIP_LoopInterface;
-extern tInterface *IPStack_AddInterface(const char *Device, const char *Name);
extern tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, void *NextHop, int Metric);
// === PROTOTYPES ===
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL);
-tVFS_NodeType gIP_RootNodeType = {
- .ReadDir = IPStack_Root_ReadDir,
- .FindDir = IPStack_Root_FindDir,
- .IOCtl = IPStack_Root_IOCtl
-};
tDevFS_Driver gIP_DriverInfo = {
NULL, "ip",
{
// === PROTOTYPES ===
// - Routes directory
-char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos);
+ int IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name);
- int IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+tVFS_Node *IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int IPStack_RouteDir_Unlink(tVFS_Node *Node, const char *OldName);
tRoute *_Route_FindExactRoute(int Type, void *Network, int Subnet, int Metric);
int _Route_ParseRouteName(const char *Name, void *Addr, int *SubnetBits, int *Metric);
/**
* \brief ReadDir for the /Devices/ip/routes/ directory
*/
-char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos)
+int IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tRoute *rt;
for(rt = gIP_Routes; rt && Pos --; rt = rt->Next);
- if( !rt ) return NULL;
+ if( !rt ) return -EINVAL;
{
int addrlen = IPStack_GetAddressSize(rt->AddressType);
- int len = sprintf(NULL, "%i::%i:%i", rt->AddressType, rt->SubnetBits, rt->Metric) + addrlen*2;
- char buf[len+1];
int ofs;
- ofs = sprintf(buf, "%i:", rt->AddressType);
- ofs += Hex(buf+ofs, addrlen, rt->Network);
- sprintf(buf+ofs, ":%i:%i", rt->SubnetBits, rt->Metric);
- return strdup(buf);
+ ofs = sprintf(Dest, "%i:", rt->AddressType);
+ ofs += Hex(Dest+ofs, addrlen, rt->Network);
+ sprintf(Dest+ofs, ":%i:%i", rt->SubnetBits, rt->Metric);
+ return 0;
}
}
/**
* \brief Create a new route node
*/
-int IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
+tVFS_Node *IPStack_RouteDir_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
{
- if( Flags ) return -EINVAL;
- if( Threads_GetUID() != 0 ) return -EACCES;
+ if( Flags ) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if( Threads_GetUID() != 0 ) {
+ errno = EACCES;
+ return NULL;
+ }
int type = _Route_ParseRouteName(Name, NULL, NULL, NULL);
- if( type <= 0 ) return -EINVAL;
+ if( type <= 0 ) {
+ errno = EINVAL;
+ return NULL;
+ }
int size = IPStack_GetAddressSize(type);
Uint8 addrdata[size];
_Route_ParseRouteName(Name, addrdata, &subnet, &metric);
// Check for duplicates
- if( _Route_FindExactRoute(type, addrdata, subnet, metric) )
- return -EEXIST;
+ if( _Route_FindExactRoute(type, addrdata, subnet, metric) ) {
+ errno = EEXIST;
+ return NULL;
+ }
- IPStack_Route_Create(type, addrdata, subnet, metric);
+ tRoute *rt = IPStack_Route_Create(type, addrdata, subnet, metric);
+ rt->Node.ReferenceCount ++;
- return 0;
+ return &rt->Node;
}
/**
int TCP_DeallocatePort(Uint16 Port);
// --- Server
tVFS_Node *TCP_Server_Init(tInterface *Interface);
-char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos);
+ int TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Name[FILENAME_MAX]);
tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name);
int TCP_Server_IOCtl(tVFS_Node *Node, int ID, void *Data);
void TCP_Server_Close(tVFS_Node *Node);
* \param Node Server node
* \param Pos Position (ignored)
*/
-char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
+int TCP_Server_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tTCPListener *srv = Node->ImplPtr;
tTCPConnection *conn;
- char *ret;
ENTER("pNode iPos", Node, Pos);
LOG("srv->NewConnections = %p", srv->NewConnections);
LOG("srv->ConnectionsTail = %p", srv->ConnectionsTail);
- ret = malloc(9);
- itoa(ret, conn->Node.ImplInt, 16, 8, '0');
- Log_Log("TCP", "Thread %i got '%s'", Threads_GetTID(), ret);
- LEAVE('s', ret);
- return ret;
+ itoa(Dest, conn->Node.ImplInt, 16, 8, '0');
+ Log_Log("TCP", "Thread %i got connection '%s'", Threads_GetTID(), Dest);
+ LEAVE('i', 0);
+ return 0;
}
/**
int Mouse_Install(char **Arguments);
int Mouse_Cleanup(void);
// - "User" side
-char *Mouse_Root_ReadDir(tVFS_Node *Node, int Pos);
+ int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data);
}
// --- VFS Interface ---
-char *Mouse_Root_ReadDir(tVFS_Node *Node, int Pos)
+int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- if( Pos != 0 ) return NULL;
- return strdup("system");
+ if( Pos != 0 )
+ return -EINVAL;
+ strcpy(Dest, "system");
+ return 0;
}
tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
// Needed out of io.c because it's the max for Read/WriteDMA
#define MAX_DMA_SECTORS (0x1000 / SECTOR_SIZE)
-// === STRUCTURES ===
-typedef struct
-{
- Uint8 BootCode[0x1BE];
- struct {
- Uint8 Boot;
- Uint8 Unused1; // Also CHS Start
- Uint16 StartHi; // Also CHS Start
- Uint8 SystemID;
- Uint8 Unused2; // Also CHS Length
- Uint16 LengthHi; // Also CHS Length
- Uint32 LBAStart;
- Uint32 LBALength;
- } __attribute__ ((packed)) Parts[4];
- Uint16 BootFlag; // = 0xAA 55
-} __attribute__ ((packed)) tMBR;
-
-typedef struct
-{
- Uint64 Start;
- Uint64 Length;
- char Name[4];
- tVFS_Node Node;
-} tATA_Partition;
-
-typedef struct
-{
- Uint64 Sectors;
-} tATA_Disk;
-
-// === GLOBALS ===
-extern tATA_Disk gATA_Disks[];
-
// === FUNCTIONS ===
-// --- Common ---
-extern void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
-
-// --- MBR Parsing ---
-extern void ATA_ParseMBR(int Disk, tMBR *MBR);
-
// --- IO Functions ---
extern int ATA_SetupIO(void);
extern Uint64 ATA_GetDiskSize(int Disk);
#include <modules.h> // Needed for error codes
#include <drv_pci.h>
#include "common.h"
+#include <events.h>
+#include <timers.h>
// === MACROS ===
#define IO_DELAY() do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
int gATA_IRQPri = 14;
int gATA_IRQSec = 15;
volatile int gaATA_IRQs[2] = {0};
+tThread *gATA_WaitingThreads[2];
// - Locks to avoid tripping
tMutex glaATA_ControllerLock[2];
// - Buffers!
-Uint8 gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata")));
+void *gATA_Buffers[2];
// - PRDTs
tPRDT_Ent gATA_PRDTs[2] = {
{0, 512, IDE_PRDT_LAST},
IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri, NULL );
IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec, NULL );
- gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( &gATA_Buffers[0] );
- gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( &gATA_Buffers[1] );
+ tPAddr paddr;
+ gATA_Buffers[0] = (void*)MM_AllocDMA(1, 32, &paddr);
+ gATA_PRDTs[0].PBufAddr = paddr;
+ gATA_Buffers[1] = (void*)MM_AllocDMA(1, 32, &paddr);
+ gATA_PRDTs[1].PBufAddr = paddr;
LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
+ // TODO: Ensure that this is within 32-bits
gaATA_PRDT_PAddrs[0] = MM_GetPhysAddr( &gATA_PRDTs[0] );
- LOG("gaATA_PRDT_PAddrs[0] = 0x%x", gaATA_PRDT_PAddrs[0]);
- ATA_int_BusMasterWriteDWord(4, gaATA_PRDT_PAddrs[0]);
-
gaATA_PRDT_PAddrs[1] = MM_GetPhysAddr( &gATA_PRDTs[1] );
- LOG("gaATA_PRDT_PAddrs[1] = 0x%x", gaATA_PRDT_PAddrs[1]);
+ LOG("gaATA_PRDT_PAddrs = {0x%P, 0x%P}", gaATA_PRDT_PAddrs[0], gaATA_PRDT_PAddrs[1]);
+ #if PHYS_BITS > 32
+ if( gaATA_PRDT_PAddrs[0] >> 32 || gaATA_PRDT_PAddrs[1] >> 32 ) {
+ Log_Error("ATA", "Physical addresses of PRDTs are not in 32-bits (%P and %P)",
+ gaATA_PRDT_PAddrs[0], gaATA_PRDT_PAddrs[1]);
+ LEAVE('i', MODULE_ERR_MISC);
+ return MODULE_ERR_MISC;
+ }
+ #endif
+ ATA_int_BusMasterWriteDWord(4, gaATA_PRDT_PAddrs[0]);
ATA_int_BusMasterWriteDWord(12, gaATA_PRDT_PAddrs[1]);
// Enable controllers
return 0;
}
-/**
- * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
- * \return Boolean Failure
- */
-int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+int ATA_DoDMA(Uint8 Disk, Uint64 Address, Uint Count, int bWrite, void *Buffer)
{
int cont = (Disk>>1)&1; // Controller ID
int disk = Disk & 1;
Uint16 base;
- Sint64 timeoutTime;
+ int bUseBounceBuffer;
- ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
+ ENTER("iDisk XAddress iCount bbWrite pBuffer", Disk, Address, Count, bWrite, Buffer);
// Check if the count is small enough
if(Count > MAX_DMA_SECTORS) {
- Log_Warning("ATA", "Passed too many sectors for a bulk DMA read (%i > %i)",
+ Log_Warning("ATA", "Passed too many sectors for a bulk DMA (%i > %i)",
Count, MAX_DMA_SECTORS);
LEAVE('i');
return 1;
// Set Size
gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
+
+ // Detemine if the transfer can be done directly
+ tPAddr buf_ps = MM_GetPhysAddr(Buffer);
+ tPAddr buf_pe = MM_GetPhysAddr((char*)Buffer + Count * SECTOR_SIZE - 1);
+ if( buf_pe == buf_ps + Count * SECTOR_SIZE - 1 ) {
+ // Contiguous, nice
+ #if PHYS_BITS > 32
+ if( buf_pe >> 32 ) {
+ // Over 32-bits, need to copy anyway
+ bUseBounceBuffer = 1;
+ LOG("%P over 32-bit, using bounce buffer", buf_pe);
+ }
+ #endif
+ }
+ else {
+ // TODO: Handle splitting the read into two?
+ bUseBounceBuffer = 1;
+ LOG("%P + 0x%x != %P, using bounce buffer", buf_ps, Count * SECTOR_SIZE, buf_pe);
+ }
+
+ // Set up destination / source buffers
+ if( bUseBounceBuffer ) {
+ gATA_PRDTs[cont].PBufAddr = MM_GetPhysAddr(gATA_Buffers[cont]);
+ if( bWrite )
+ memcpy(gATA_Buffers[cont], Buffer, Count * SECTOR_SIZE);
+ }
+ else {
+ gATA_PRDTs[cont].PBufAddr = MM_GetPhysAddr(Buffer);
+ }
// Get Port Base
base = ATA_GetBasePort(Disk);
// Reset IRQ Flag
gaATA_IRQs[cont] = 0;
+
+ // TODO: What the ____ does this do?
#if 1
if( cont == 0 ) {
outb(IDE_PRI_CTRL, 4);
LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes);
if( Address > 0x0FFFFFFF )
- outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
+ outb(base+0x07, bWrite ? HDD_DMA_W48 : HDD_DMA_R48); // Command (LBA48)
else
- outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
+ outb(base+0x07, bWrite ? HDD_DMA_W28 : HDD_DMA_R28); // Command (LBA28)
+ // Intialise timeout timer
+ Threads_ClearEvent(THREAD_EVENT_SHORTWAIT|THREAD_EVENT_TIMER);
+ tTimer *timeout = Time_AllocateTimer(NULL, NULL);
+ Time_ScheduleTimer(timeout, ATA_TIMEOUT);
+ gATA_WaitingThreads[cont] = Proc_GetCurThread();
+
// Start transfer
- ATA_int_BusMasterWriteByte( cont * 8, 9 ); // Read and start
+ ATA_int_BusMasterWriteByte( cont * 8, (bWrite ? 0 : 8) | 1 ); // Write(0)/Read(8) and start
// Wait for transfer to complete
- timeoutTime = now() + ATA_TIMEOUT;
- while( gaATA_IRQs[cont] == 0 && now() < timeoutTime)
- {
- HALT();
- }
-
- if( now() >= timeoutTime ) {
+ Uint32 ev = Threads_WaitEvents(THREAD_EVENT_SHORTWAIT|THREAD_EVENT_TIMER);
+ Time_FreeTimer(timeout);
+
+ if( ev & THREAD_EVENT_TIMER ) {
Log_Notice("ATA", "Timeout of %i ms exceeded", ATA_TIMEOUT);
}
// Complete Transfer
- ATA_int_BusMasterWriteByte( cont * 8, 8 ); // Read and stop
+ ATA_int_BusMasterWriteByte( cont * 8, (bWrite ? 0 : 8) ); // Write/Read and stop
#if DEBUG
{
if( ATA_int_BusMasterReadByte(cont * 8 + 2) & 0x4 ) {
Log_Error("ATA", "BM Status reports an interrupt, but none recieved");
ATA_int_BusMasterWriteByte(cont*8 + 2, 4); // Clear interrupt
- memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
- LEAVE('i', 0);
- return 0;
+ goto _success;
}
#if 1
// Release controller lock
Mutex_Release( &glaATA_ControllerLock[ cont ] );
Log_Warning("ATA",
- "Read timeout on disk %i (Reading sector 0x%llx)",
- Disk, Address);
+ "Timeout on disk %i (%s sector 0x%llx)",
+ Disk, bWrite ? "Writing" : "Reading", Address);
// Return error
LEAVE('i', 1);
return 1;
}
- else {
- LOG("Transfer Completed & Acknowledged");
- // Copy to destination buffer
+
+ LOG("Transfer Completed & Acknowledged");
+_success:
+ // Copy to destination buffer (if bounce was used and it was a read)
+ if( bUseBounceBuffer && !bWrite )
memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
- // Release controller lock
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
+ // Release controller lock
+ Mutex_Release( &glaATA_ControllerLock[ cont ] );
- LEAVE('i', 0);
- return 0;
- }
+ LEAVE('i', 0);
+ return 0;
+}
+
+/**
+ * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+ * \return Boolean Failure
+ */
+int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
+{
+ return ATA_DoDMA(Disk, Address, Count, 0, Buffer);
}
+
/**
* \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
* \brief Write up to \a MAX_DMA_SECTORS to a disk
*/
int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer)
{
- int cont = (Disk>>1)&1; // Controller ID
- int disk = Disk & 1;
- Uint16 base;
- Sint64 timeoutTime;
-
- // Check if the count is small enough
- if(Count > MAX_DMA_SECTORS) return 1;
-
- // Get exclusive access to the disk controller
- Mutex_Acquire( &glaATA_ControllerLock[ cont ] );
-
- // Set Size
- gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
-
- // Get Port Base
- base = ATA_GetBasePort(Disk);
-
- // Reset IRQ Flag
- gaATA_IRQs[cont] = 0;
-
- // Set up transfer
- outb(base+0x01, 0x00);
- if( Address > 0x0FFFFFFF ) // Use LBA48
- {
- outb(base+0x6, 0x40 | (disk << 4));
- outb(base+0x2, 0 >> 8); // Upper Sector Count
- outb(base+0x3, Address >> 24); // Low 2 Addr
- outb(base+0x3, Address >> 28); // Mid 2 Addr
- outb(base+0x3, Address >> 32); // High 2 Addr
- }
- else
- {
- // Magic, Disk, High Address nibble
- outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
- }
-
- outb(base+0x02, (Uint8) Count); // Sector Count
- outb(base+0x03, (Uint8) Address); // Low Addr
- outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
- outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
- if( Address > 0x0FFFFFFF )
- outb(base+0x07, HDD_DMA_W48); // Write Command (LBA48)
- else
- outb(base+0x07, HDD_DMA_W28); // Write Command (LBA28)
-
- // Copy to output buffer
- memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
-
- // Start transfer
- ATA_int_BusMasterWriteByte( cont << 3, 1 ); // Write and start
-
- // Wait for transfer to complete
- timeoutTime = now() + ATA_TIMEOUT;
- while( gaATA_IRQs[cont] == 0 && now() < timeoutTime)
- {
- HALT();
- }
-
- // Complete Transfer
- ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
-
- // If the IRQ is unset, return error
- if( gaATA_IRQs[cont] == 0 ) {
- // Release controller lock
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
- return 1; // Error
- }
- else {
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
- return 0;
- }
+ return ATA_DoDMA(Disk, Address, Count, 1, (void*)Buffer);
}
/**
// IRQ bit set for Primary Controller
val = ATA_int_BusMasterReadByte( 0x2 );
LOG("IRQ val = 0x%x", val);
- if(val & 4) {
+ if(val & 4)
+ {
LOG("IRQ hit (val = 0x%x)", val);
ATA_int_BusMasterWriteByte( 0x2, 4 );
gaATA_IRQs[0] = 1;
+ Threads_PostEvent(gATA_WaitingThreads[0], THREAD_EVENT_SHORTWAIT);
return ;
}
}
LOG("IRQ hit (val = 0x%x)", val);
ATA_int_BusMasterWriteByte( 0xA, 4 );
gaATA_IRQs[1] = 1;
+ Threads_PostEvent(gATA_WaitingThreads[1], THREAD_EVENT_SHORTWAIT);
return ;
}
}
void ATA_SetupPartitions(void);
int ATA_ScanDisk(int Disk);
void ATA_ParseGPT(int Disk);
-void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
Uint16 ATA_GetBasePort(int Disk);
// Read/Write Interface/Quantiser
int ATA_ReadRaw(void *Ptr, Uint64 Address, size_t Count, void *Buffer);
int FDD_Install(char **Arguments);
int FDD_RegisterFS(void);
// --- VFS
-char *FDD_ReadDir(tVFS_Node *Node, int pos);
+ int FDD_ReadDir(tVFS_Node *Node, int pos, char dest[FILENAME_MAX]);
tVFS_Node *FDD_FindDir(tVFS_Node *dirNode, const char *Name);
int FDD_IOCtl(tVFS_Node *Node, int ID, void *Data);
size_t FDD_ReadFS(tVFS_Node *node, off_t Offset, size_t Len, void *buffer);
* \param Pos Position
* \return Heap string of node name
*/
-char *FDD_ReadDir(tVFS_Node *Node, int Pos)
+int FDD_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- char ret_tpl[2];
if(Pos < 0 || Pos > MAX_DISKS )
- return NULL;
+ return -ENOENT;
if(gaFDD_Disks[Pos].bValid)
- return VFS_SKIP;
+ return 1;
- ret_tpl[0] = '0' + Pos;
- ret_tpl[1] = '\0';
- return strdup(ret_tpl);
+ Dest[0] = '0' + Pos;
+ Dest[1] = '\0';
+ return 0;
}
/**
int LVM_Initialise(char **Arguments);
int LVM_Cleanup(void);
// ---
-char *LVM_Root_ReadDir(tVFS_Node *Node, int ID);
+ int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name);
-char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID);
+ int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX]);
tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name);
size_t LVM_Vol_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
size_t LVM_Vol_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
// --------------------------------------------------------------------
// VFS Inteface
// --------------------------------------------------------------------
-char *LVM_Root_ReadDir(tVFS_Node *Node, int ID)
+int LVM_Root_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
{
tLVM_Vol *vol;
- if( ID < 0 ) return NULL;
+ if( ID < 0 ) return -EINVAL;
for( vol = gpLVM_FirstVolume; vol && ID --; vol = vol->Next );
- if(vol)
- return strdup(vol->Name);
+ if(vol) {
+ strncpy(Dest, vol->Name, FILENAME_MAX);
+ return 0;
+ }
else
- return NULL;
+ return -ENOENT;
}
tVFS_Node *LVM_Root_FindDir(tVFS_Node *Node, const char *Name)
{
return NULL;
}
-char *LVM_Vol_ReadDir(tVFS_Node *Node, int ID)
+int LVM_Vol_ReadDir(tVFS_Node *Node, int ID, char Dest[FILENAME_MAX])
{
tLVM_Vol *vol = Node->ImplPtr;
+ const char *src;
if( ID < 0 || ID >= vol->nSubVolumes+1 )
- return NULL;
+ return -EINVAL;
- if( ID == 0 )
- return strdup("ROOT");
- else
- return strdup( vol->SubVolumes[ID-1]->Name );
+ if( ID == 0 ) {
+ src = "ROOT";
+ }
+ else {
+ src = vol->SubVolumes[ID-1]->Name;
+ }
+ strncpy(Dest, src, FILENAME_MAX);
+ return 0;
}
tVFS_Node *LVM_Vol_FindDir(tVFS_Node *Node, const char *Name)
{
while(extendedLBA != 0)
{
extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
- if( extendedLBA == -1 ) break;
+ if( extendedLBA == (Uint64)-1 )
+ break;
numPartitions ++;
}
LOG("numPartitions = %i", numPartitions);
while(extendedLBA != 0)
{
extendedLBA = LVM_MBR_int_ReadExt(Volume, extendedLBA, &base, &len);
- if(extendedLBA == -1) break;
+ if(extendedLBA == (Uint64)-1)
+ break;
LVM_int_SetSubvolume_Anon( Volume, j, base, len );
j ++ ;
}
// === PROTOTYPES ===
int USB_Install(char **Arguments);
void USB_Cleanup(void);
-char *USB_ReadDir(tVFS_Node *Node, int Pos);
+ int USB_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
tVFS_Node *USB_FindDir(tVFS_Node *Node, const char *Name);
int USB_IOCtl(tVFS_Node *Node, int Id, void *Data);
* \fn char *USB_ReadDir(tVFS_Node *Node, int Pos)
* \brief Read from the USB root
*/
-char *USB_ReadDir(tVFS_Node *Node, int Pos)
+int USB_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- return NULL;
+ return -ENOTIMPL;
}
/**
- UniChrome Driver
+- Sound Stack
+ > Intel 82801AA AC97 Audio (qemu)
+
- Init Scripts
> With an argument to init passed from the kernel?
> Allow hooks on PCI config accesses (to emulate power management etc)
- VFS Path caching
+ > Is it needed?
> Use a trie of path elements
+ - Trie on path content (with '/' included)
+ - Prefixed to reduce load
+ - Able to split
> Maintain backwards cache of elements
> Support symlink caching too
- USB Stack
> Check validity
- > Rework HC API to support structure used by OHCI/ECHI
+ > (DONE) Rework HC API to support structure used by OHCI/ECHI
- LVM Usablity
> /Devices/LVM/by-id/ and /Devices/LVM/by-label
- Omnispeak
> Debug speed issues (tracing agian)
> Port to AxWin3
- > Trace memory corruption
+ > (DONE) Trace memory corruption
- Port dropbear!
// Translate path
size_t tpath_len = DiskTool_int_TranslatePath(NULL, Path);
- if(tpath_len == -1)
- return -1;
char tpath[tpath_len-1];
DiskTool_int_TranslatePath(tpath, Path);
return 0;
}
+int DiskTool_Cat(const char *File)
+{
+ int src = DiskTool_int_TranslateOpen(File, VFS_OPENFLAG_READ);
+ if( src == -1 ) {
+ Log_Error("DiskTool", "Unable to open %s for reading", File);
+ return -1;
+ }
+
+ char buf[1024];
+ size_t len, total = 0;
+ while( (len = VFS_Read(src, sizeof(buf), buf)) == sizeof(buf) ) {
+ _fwrite_stdout(len, buf);
+ total += len;
+ }
+ _fwrite_stdout(len, buf);
+ total += len;
+
+ Log_Notice("DiskTool", "%i bytes from %s", total, File);
+
+ VFS_Close(src);
+ return 0;
+}
+
int DiskTool_LVM_Read(void *Handle, Uint64 Block, size_t BlockCount, void *Dest)
{
return VFS_ReadAt( (int)(tVAddr)Handle, Block*512, BlockCount*512, Dest) / 512;
int DiskTool_int_TranslateOpen(const char *File, int Flags)
{
size_t tpath_len = DiskTool_int_TranslatePath(NULL, File);
- if(tpath_len == -1)
+ if(tpath_len == 0)
return -1;
char tpath[tpath_len-1];
DiskTool_int_TranslatePath(tpath, File);
extern int DiskTool_MountImage(const char *Identifier, const char *Path);
extern int DiskTool_Copy(const char *Source, const char *Destination);
extern int DiskTool_ListDirectory(const char *Directory);
+extern int DiskTool_Cat(const char *File);
extern size_t DiskTool_int_TranslatePath(char *Buffer, const char *Path);
+extern size_t _fwrite_stdout(size_t bytes, const void *data);
+
#endif
continue ;
}
- if( strcmp("mountlvm", argv[i]) == 0 ) {
+ if( strcmp("mountlvm", argv[i]) == 0 || strcmp("lvm", argv[i]) == 0 ) {
if( argc - i < 3 ) {
- fprintf(stderr, "mountlvm takes 2 arguments (iamge and ident)\n");
+ fprintf(stderr, "lvm takes 2 arguments (iamge and ident)\n");
exit(-1);
}
if( strcmp("ls", argv[i]) == 0 ) {
if( argc - i < 2 ) {
- fprintf(stderr, "ls 1 argument (path)\n");
+ fprintf(stderr, "ls takes 1 argument (path)\n");
break;
}
i += 2;
continue ;
}
+
+ if( strcmp("cat", argv[i]) == 0 ) {
+
+ if( argc - 1 < 2 ) {
+ fprintf(stderr, "cat takes 1 argument (path)\n");
+ break;
+ }
+
+ DiskTool_Cat(argv[i+1]);
+
+ i += 1;
+ continue;
+ }
fprintf(stderr, "Unknown command '%s'\n", argv[i]);
}
return value / divisor;
}
+size_t _fwrite_stdout(size_t bytes, const void *data)
+{
+ return fwrite(data, bytes, 1, stdout);
+}
#include <stdio.h>
#define MOUNTABLE_FILE "/Acess/Conf/Mountable"
-#define MOUNTED_FILE "/Devices/System/VFS/Mounts"
+#define MOUNTED_FILE "/Devices/system/VFS/Mounts"
// === PROTOTYPES ===
void ShowUsage(char *ProgName);
// - This is cheating, isn't it?
if(argc == 1) {
// Dump the contents of /Devices/system/VFS/Mounts
- FILE *fp = fopen("/Devices/system/VFS/Mounts", "r");
+ FILE *fp = fopen(MOUNTED_FILE, "r");
char buf[1024];
int len;
while( (len = fread(buf, 1024, 1, fp)) )
else
{
// Check that we were passed a filesystem type
- if(sType == NULL) {
- fprintf(stderr, "Please pass a filesystem type\n");
- return EXIT_FAILURE;
- }
+// if(sType == NULL) {
+// fprintf(stderr, "Please pass a filesystem type\n");
+// return EXIT_FAILURE;
+// }
}
// Check Device
if(sOptions == NULL) sOptions = "";
// Let's Mount!
- _SysMount(sDevice, sDir, sType, sOptions);
+ if( _SysMount(sDevice, sDir, sType, sOptions) ) {
+ if( !sType )
+ fprintf(stderr, "Filesystem autodetection failed, please pass a type\n");
+ }
return 0;
}