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 h = VFS_GetHandle(FD);
28 LOG("FD%i is a bad Handle", FD);
32 if( !(h->Mode & VFS_OPENFLAG_READ) ) {
33 LOG("FD%i not open for reading", FD);
36 if( (h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
37 LOG("FD%i is a directory", FD);
41 if(!h->Node->Type || !h->Node->Type->Read) {
42 LOG("FD%i has no read method", FD);
46 if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
47 Log_Error("VFS", "Node type %p(%s) read method is junk %p",
48 h->Node->Type, h->Node, h->Node->Type->TypeName,
54 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
55 ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer, flags);
56 if(ret != Length) LOG("%i/%i read", ret, Length);
57 if(ret == (size_t)-1) return -1;
64 * \fn Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
65 * \brief Read data from a given offset (atomic)
67 size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer)
72 h = VFS_GetHandle(FD);
75 if( !(h->Mode & VFS_OPENFLAG_READ) ) return -1;
76 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1;
78 if( !h->Node->Type || !h->Node->Type->Read) {
79 Warning("VFS_ReadAt - Node %p, does not have a read method", h->Node);
83 if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
84 Log_Error("VFS", "Node type %p(%s) read method is junk %p",
85 h->Node->Type, h->Node->Type->TypeName,
90 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
91 ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer, flags);
92 if(ret != Length) LOG("%i/%i read", ret, Length);
93 if(ret == (size_t)-1) return -1;
98 * \fn Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
99 * \brief Read data from a node (file)
101 size_t VFS_Write(int FD, size_t Length, const void *Buffer)
106 h = VFS_GetHandle(FD);
108 LOG("FD%i is not open", FD);
113 if( !(h->Mode & VFS_OPENFLAG_WRITE) ) {
114 LOG("FD%i not opened for writing", FD);
118 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) {
119 LOG("FD%i is a directory", FD);
124 if( !h->Node->Type || !h->Node->Type->Write ) {
125 LOG("FD%i has no write method", FD);
130 if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
131 Log_Error("VFS", "Node type %p(%s) write method is junk %p",
132 h->Node->Type, h->Node->Type->TypeName,
133 h->Node->Type->Write);
139 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
140 ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer, flags);
141 if(ret != Length) LOG("%i/%i written", ret, Length);
142 if(ret == (size_t)-1) return -1;
149 * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
150 * \brief Write data to a file at a given offset
152 size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
157 h = VFS_GetHandle(FD);
160 if( !(h->Mode & VFS_OPENFLAG_WRITE) ) return -1;
161 if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) return -1;
163 if(!h->Node->Type || !h->Node->Type->Write) return 0;
165 if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
166 Log_Error("VFS", "Node type %p(%s) write method is junk %p",
167 h->Node->Type, h->Node->Type->TypeName,
168 h->Node->Type->Write);
172 flags |= (h->Mode & VFS_OPENFLAG_NONBLOCK) ? VFS_IOFLAG_NOBLOCK : 0;
173 ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer, flags);
174 if(ret == (size_t)-1) return -1;
179 * \fn Uint64 VFS_Tell(int FD)
180 * \brief Returns the current file position
182 Uint64 VFS_Tell(int FD)
186 h = VFS_GetHandle(FD);
193 * \fn int VFS_Seek(int FD, Sint64 Offset, int Whence)
194 * \brief Seek to a new location
195 * \param FD File descriptor
196 * \param Offset Where to go
197 * \param Whence From where
199 int VFS_Seek(int FD, Sint64 Offset, int Whence)
203 h = VFS_GetHandle(FD);
206 // Set relative to current position
208 LOG("(FD%x)->Position += %lli", FD, Offset);
209 h->Position += Offset;
213 // Set relative to end of file
215 if( h->Node->Size == (Uint64)-1 ) return -1;
217 LOG("(FD%x)->Position = %llx - %llx", FD, h->Node->Size, Offset);
218 h->Position = h->Node->Size - Offset;
222 // Set relative to start of file
223 LOG("(FD%x)->Position = %llx", FD, Offset);
224 h->Position = Offset;
229 * \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
230 * \brief Call an IO Control on a file
232 int VFS_IOCtl(int FD, int ID, void *Buffer)
236 h = VFS_GetHandle(FD);
238 LOG("FD%i is invalid", FD);
243 if(!h->Node->Type || !h->Node->Type->IOCtl) {
244 LOG("FD%i does not have an IOCtl method");
248 return h->Node->Type->IOCtl(h->Node, ID, Buffer);
252 * \fn int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
253 * \brief Retrieve file information
254 * \return Number of ACLs stored
256 int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
261 h = VFS_GetHandle(FD);
265 Dest->mount = h->Mount->Identifier;
268 Dest->inode = h->Node->Inode;
269 Dest->uid = h->Node->UID;
270 Dest->gid = h->Node->GID;
271 Dest->size = h->Node->Size;
272 Dest->atime = h->Node->ATime;
273 Dest->ctime = h->Node->MTime;
274 Dest->mtime = h->Node->CTime;
275 Dest->numacls = h->Node->NumACLs;
278 if(h->Node->Flags & VFS_FFLAG_DIRECTORY) Dest->flags |= 0x10;
279 if(h->Node->Flags & VFS_FFLAG_SYMLINK) Dest->flags |= 0x20;
281 max = (MaxACLs < h->Node->NumACLs) ? MaxACLs : h->Node->NumACLs;
282 memcpy(&Dest->acls, h->Node->ACLs, max*sizeof(tVFS_ACL));