3 * - By John Hodge (thePowersGang)
6 * - VFS IO Handling (Read/Write)
8 * TODO: VFS-level caching to support non-blocking IO?
18 * \fn Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
19 * \brief Read data from a node (file)
21 size_t VFS_Read(int FD, size_t Length, void *Buffer)
26 ENTER("xFD xLength pBuffer", FD, Length, Buffer);
28 h = VFS_GetHandle(FD);
34 if( !(h->Mode & VFS_OPENFLAG_READ) ) {
38 if( (h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
39 LOG("Reading directory");
43 if(!h->Node->Type || !h->Node->Type->Read) {
44 LOG("No read method");
48 if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
49 Log_Error("VFS", "Node type %p(%s) read method is junk %p",
50 h->Node->Type, h->Node, h->Node->Type->TypeName,
55 LOG("Position=%llx", h->Position);
57 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
58 ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer, flags);
59 if(ret == (size_t)-1) LEAVE_RET('i', -1);
67 * \fn Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
68 * \brief Read data from a given offset (atomic)
70 size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer)
75 h = VFS_GetHandle(FD);
78 if( !(h->Mode & VFS_OPENFLAG_READ) ) return -1;
79 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1;
81 if( !h->Node->Type || !h->Node->Type->Read) {
82 Warning("VFS_ReadAt - Node %p, does not have a read method", h->Node);
86 if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
87 Log_Error("VFS", "Node type %p(%s) read method is junk %p",
88 h->Node->Type, h->Node->Type->TypeName,
94 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
95 ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer, flags);
96 if(ret == (size_t)-1) return -1;
101 * \fn Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
102 * \brief Read data from a node (file)
104 size_t VFS_Write(int FD, size_t Length, const void *Buffer)
109 h = VFS_GetHandle(FD);
112 if( !(h->Mode & VFS_OPENFLAG_WRITE) ) {
113 LOG("FD%i not opened for writing", FD);
116 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) {
117 LOG("FD%i is a director", FD);
121 if( !h->Node->Type || !h->Node->Type->Write ) {
122 LOG("FD%i has no write method", FD);
126 if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
127 Log_Error("VFS", "Node type %p(%s) write method is junk %p",
128 h->Node->Type, h->Node->Type->TypeName,
129 h->Node->Type->Write);
134 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
135 ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer, flags);
136 if(ret == (size_t)-1) return -1;
143 * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
144 * \brief Write data to a file at a given offset
146 size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
151 h = VFS_GetHandle(FD);
154 if( !(h->Mode & VFS_OPENFLAG_WRITE) ) return -1;
155 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1;
157 if(!h->Node->Type || !h->Node->Type->Write) return 0;
159 if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
160 Log_Error("VFS", "Node type %p(%s) write method is junk %p",
161 h->Node->Type, h->Node->Type->TypeName,
162 h->Node->Type->Write);
166 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
167 ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags);
168 if(ret == (size_t)-1) return -1;
173 * \fn Uint64 VFS_Tell(int FD)
174 * \brief Returns the current file position
176 Uint64 VFS_Tell(int FD)
180 h = VFS_GetHandle(FD);
187 * \fn int VFS_Seek(int FD, Sint64 Offset, int Whence)
188 * \brief Seek to a new location
189 * \param FD File descriptor
190 * \param Offset Where to go
191 * \param Whence From where
193 int VFS_Seek(int FD, Sint64 Offset, int Whence)
197 h = VFS_GetHandle(FD);
200 // Set relative to current position
202 LOG("(FD%x)->Position += %lli", FD, Offset);
203 h->Position += Offset;
207 // Set relative to end of file
209 if( h->Node->Size == (Uint64)-1 ) return -1;
211 LOG("(FD%x)->Position = %llx - %llx", FD, h->Node->Size, Offset);
212 h->Position = h->Node->Size - Offset;
216 // Set relative to start of file
217 LOG("(FD%x)->Position = %llx", FD, Offset);
218 h->Position = Offset;
223 * \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
224 * \brief Call an IO Control on a file
226 int VFS_IOCtl(int FD, int ID, void *Buffer)
230 h = VFS_GetHandle(FD);
233 if(!h->Node->Type || !h->Node->Type->IOCtl) return -1;
234 return h->Node->Type->IOCtl(h->Node, ID, Buffer);
238 * \fn int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
239 * \brief Retrieve file information
240 * \return Number of ACLs stored
242 int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
247 h = VFS_GetHandle(FD);
251 Dest->mount = h->Mount->Identifier;
254 Dest->inode = h->Node->Inode;
255 Dest->uid = h->Node->UID;
256 Dest->gid = h->Node->GID;
257 Dest->size = h->Node->Size;
258 Dest->atime = h->Node->ATime;
259 Dest->ctime = h->Node->MTime;
260 Dest->mtime = h->Node->CTime;
261 Dest->numacls = h->Node->NumACLs;
264 if(h->Node->Flags & VFS_FFLAG_DIRECTORY) Dest->flags |= 0x10;
265 if(h->Node->Flags & VFS_FFLAG_SYMLINK) Dest->flags |= 0x20;
267 max = (MaxACLs < h->Node->NumACLs) ? MaxACLs : h->Node->NumACLs;
268 memcpy(&Dest->acls, h->Node->ACLs, max*sizeof(tVFS_ACL));