Kernel - Added 'Flags' param to VFS Read/Write/FindDir
[tpg/acess2.git] / KernelLand / Kernel / vfs / io.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * vfs/io.c
6  * - VFS IO Handling (Read/Write)
7  *
8  * TODO: VFS-level caching to support non-blocking IO?
9  */
10 #define DEBUG   0
11 #include <acess.h>
12 #include <vfs.h>
13 #include <vfs_ext.h>
14 #include <vfs_int.h>
15
16 // === CODE ===
17 /**
18  * \fn Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
19  * \brief Read data from a node (file)
20  */
21 size_t VFS_Read(int FD, size_t Length, void *Buffer)
22 {
23         tVFS_Handle     *h;
24         size_t  ret;
25         
26         ENTER("xFD xLength pBuffer", FD, Length, Buffer);
27         
28         h = VFS_GetHandle(FD);
29         if(!h) {
30                 LOG("Bad Handle");
31                 LEAVE_RET('i', -1);
32         }
33         
34         if( !(h->Mode & VFS_OPENFLAG_READ) ) {
35                 LOG("Bad mode");
36                 LEAVE_RET('i', -1);
37         }
38         if( (h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
39                 LOG("Reading directory");
40                 LEAVE_RET('i', -1);
41         }
42
43         if(!h->Node->Type || !h->Node->Type->Read) {
44                 LOG("No read method");
45                 LEAVE_RET('i', -1);
46         }
47
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,
51                         h->Node->Type->Read);
52                 LEAVE_RET('i', -1);
53         }
54         
55         LOG("Position=%llx", h->Position);
56         Uint    flags = 0;
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);
60         
61         h->Position += ret;
62         LEAVE('x', ret);
63         return ret;
64 }
65
66 /**
67  * \fn Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
68  * \brief Read data from a given offset (atomic)
69  */
70 size_t VFS_ReadAt(int FD, Uint64 Offset, size_t Length, void *Buffer)
71 {
72         tVFS_Handle     *h;
73         size_t  ret;
74         
75         h = VFS_GetHandle(FD);
76         if(!h)  return -1;
77         
78         if( !(h->Mode & VFS_OPENFLAG_READ) )    return -1;
79         if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
80
81         if( !h->Node->Type || !h->Node->Type->Read) {
82                 Warning("VFS_ReadAt - Node %p, does not have a read method", h->Node);
83                 return 0;
84         }
85
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,
89                         h->Node->Type->Read);
90                 LEAVE_RET('i', -1);
91         }
92         
93         Uint    flags = 0;
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;
97         return ret;
98 }
99
100 /**
101  * \fn Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
102  * \brief Read data from a node (file)
103  */
104 size_t VFS_Write(int FD, size_t Length, const void *Buffer)
105 {
106         tVFS_Handle     *h;
107         size_t  ret;
108         
109         h = VFS_GetHandle(FD);
110         if(!h)  return -1;
111         
112         if( !(h->Mode & VFS_OPENFLAG_WRITE) ) {
113                 LOG("FD%i not opened for writing", FD);
114                 return -1;
115         }
116         if( h->Node->Flags & VFS_FFLAG_DIRECTORY ) {
117                 LOG("FD%i is a director", FD);
118                 return -1;
119         }
120
121         if( !h->Node->Type || !h->Node->Type->Write ) {
122                 LOG("FD%i has no write method", FD);
123                 return 0;
124         }
125
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);
130                 return -1;
131         }
132         
133         Uint flags = 0;
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;
137
138         h->Position += ret;
139         return ret;
140 }
141
142 /**
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
145  */
146 size_t VFS_WriteAt(int FD, Uint64 Offset, size_t Length, const void *Buffer)
147 {
148         tVFS_Handle     *h;
149         size_t  ret;
150         
151         h = VFS_GetHandle(FD);
152         if(!h)  return -1;
153         
154         if( !(h->Mode & VFS_OPENFLAG_WRITE) )   return -1;
155         if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
156
157         if(!h->Node->Type || !h->Node->Type->Write)     return 0;
158
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);
163                 return -1;
164         }
165         Uint flags = 0;
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;
169         return ret;
170 }
171
172 /**
173  * \fn Uint64 VFS_Tell(int FD)
174  * \brief Returns the current file position
175  */
176 Uint64 VFS_Tell(int FD)
177 {
178         tVFS_Handle     *h;
179         
180         h = VFS_GetHandle(FD);
181         if(!h)  return -1;
182         
183         return h->Position;
184 }
185
186 /**
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
192  */
193 int VFS_Seek(int FD, Sint64 Offset, int Whence)
194 {
195         tVFS_Handle     *h;
196         
197         h = VFS_GetHandle(FD);
198         if(!h)  return -1;
199         
200         // Set relative to current position
201         if(Whence == 0) {
202                 LOG("(FD%x)->Position += %lli", FD, Offset);
203                 h->Position += Offset;
204                 return 0;
205         }
206         
207         // Set relative to end of file
208         if(Whence < 0) {
209                 if( h->Node->Size == (Uint64)-1 )       return -1;
210
211                 LOG("(FD%x)->Position = %llx - %llx", FD, h->Node->Size, Offset);
212                 h->Position = h->Node->Size - Offset;
213                 return 0;
214         }
215         
216         // Set relative to start of file
217         LOG("(FD%x)->Position = %llx", FD, Offset);
218         h->Position = Offset;
219         return 0;
220 }
221
222 /**
223  * \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
224  * \brief Call an IO Control on a file
225  */
226 int VFS_IOCtl(int FD, int ID, void *Buffer)
227 {
228         tVFS_Handle     *h;
229         
230         h = VFS_GetHandle(FD);
231         if(!h)  return -1;
232
233         if(!h->Node->Type || !h->Node->Type->IOCtl)     return -1;
234         return h->Node->Type->IOCtl(h->Node, ID, Buffer);
235 }
236
237 /**
238  * \fn int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
239  * \brief Retrieve file information
240  * \return Number of ACLs stored
241  */
242 int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
243 {
244         tVFS_Handle     *h;
245          int    max;
246         
247         h = VFS_GetHandle(FD);
248         if(!h)  return -1;
249
250         if( h->Mount )
251                 Dest->mount = h->Mount->Identifier;
252         else
253                 Dest->mount = 0;
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;
262         
263         Dest->flags = 0;
264         if(h->Node->Flags & VFS_FFLAG_DIRECTORY)        Dest->flags |= 0x10;
265         if(h->Node->Flags & VFS_FFLAG_SYMLINK)  Dest->flags |= 0x20;
266         
267         max = (MaxACLs < h->Node->NumACLs) ? MaxACLs : h->Node->NumACLs;
268         memcpy(&Dest->acls, h->Node->ACLs, max*sizeof(tVFS_ACL));
269         
270         return max;
271 }
272
273 // === EXPORTS ===
274 EXPORT(VFS_Read);
275 EXPORT(VFS_Write);
276 EXPORT(VFS_ReadAt);
277 EXPORT(VFS_WriteAt);
278 EXPORT(VFS_IOCtl);
279 EXPORT(VFS_Seek);
280 EXPORT(VFS_Tell);

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