Merge branch 'master' of git://localhost/acess2
[tpg/acess2.git] / KernelLand / Kernel / vfs / io.c
1 /*
2  * AcessMicro VFS
3  * - File IO Passthru's
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include "vfs.h"
8 #include "vfs_int.h"
9
10 // === CODE ===
11 /**
12  * \fn Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
13  * \brief Read data from a node (file)
14  */
15 Uint64 VFS_Read(int FD, Uint64 Length, void *Buffer)
16 {
17         tVFS_Handle     *h;
18         Uint64  ret;
19         
20         ENTER("iFD XLength pBuffer", FD, Length, Buffer);
21         
22         h = VFS_GetHandle(FD);
23         if(!h) {
24                 LOG("Bad Handle");
25                 LEAVE_RET('i', -1);
26         }
27         
28         if( !(h->Mode & VFS_OPENFLAG_READ) ) {
29                 LOG("Bad mode");
30                 LEAVE_RET('i', -1);
31         }
32         if( (h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
33                 LOG("Reading directory");
34                 LEAVE_RET('i', -1);
35         }
36
37         if(!h->Node->Type || !h->Node->Type->Read) {
38                 LOG("No read method");
39                 LEAVE_RET('i', -1);
40         }
41
42         if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
43                 Log_Error("VFS", "Node type %p(%s) read method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
44                         h->Node->Type->Read);
45                 LEAVE_RET('i', -1);
46         }
47         
48         ret = h->Node->Type->Read(h->Node, h->Position, Length, Buffer);
49         if(ret == -1)   LEAVE_RET('i', -1);
50         
51         h->Position += ret;
52         LEAVE('X', ret);
53         return ret;
54 }
55
56 /**
57  * \fn Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
58  * \brief Read data from a given offset (atomic)
59  */
60 Uint64 VFS_ReadAt(int FD, Uint64 Offset, Uint64 Length, void *Buffer)
61 {
62         tVFS_Handle     *h;
63         Uint64  ret;
64         
65         h = VFS_GetHandle(FD);
66         if(!h)  return -1;
67         
68         if( !(h->Mode & VFS_OPENFLAG_READ) )    return -1;
69         if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
70
71         if( !h->Node->Type || !h->Node->Type->Read) {
72                 Warning("VFS_ReadAt - Node %p, does not have a read method", h->Node);
73                 return 0;
74         }
75
76         if( !MM_GetPhysAddr(h->Node->Type->Read) ) {
77                 Log_Error("VFS", "Node type %p(%s) read method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
78                         h->Node->Type->Read);
79                 LEAVE_RET('i', -1);
80         }
81         
82         ret = h->Node->Type->Read(h->Node, Offset, Length, Buffer);
83         if(ret == -1)   return -1;
84         return ret;
85 }
86
87 /**
88  * \fn Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
89  * \brief Read data from a node (file)
90  */
91 Uint64 VFS_Write(int FD, Uint64 Length, const void *Buffer)
92 {
93         tVFS_Handle     *h;
94         Uint64  ret;
95         
96         h = VFS_GetHandle(FD);
97         if(!h)  return -1;
98         
99         if( !(h->Mode & VFS_OPENFLAG_WRITE) )   return -1;
100         if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
101
102         if( !h->Node->Type || !h->Node->Type->Write )   return 0;
103
104         if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
105                 Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
106                         h->Node->Type->Write);
107                 return -1;
108         }
109         
110         ret = h->Node->Type->Write(h->Node, h->Position, Length, Buffer);
111         if(ret == -1)   return -1;
112
113         h->Position += ret;
114         return ret;
115 }
116
117 /**
118  * \fn Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
119  * \brief Write data to a file at a given offset
120  */
121 Uint64 VFS_WriteAt(int FD, Uint64 Offset, Uint64 Length, const void *Buffer)
122 {
123         tVFS_Handle     *h;
124         Uint64  ret;
125         
126         h = VFS_GetHandle(FD);
127         if(!h)  return -1;
128         
129         if( !(h->Mode & VFS_OPENFLAG_WRITE) )   return -1;
130         if( h->Node->Flags & VFS_FFLAG_DIRECTORY )      return -1;
131
132         if(!h->Node->Type || !h->Node->Type->Write)     return 0;
133
134         if( !MM_GetPhysAddr(h->Node->Type->Write) ) {
135                 Log_Error("VFS", "Node type %p(%s) write method is junk %p", h->Node->Type, h->Node, h->Node->Type->TypeName,
136                         h->Node->Type->Write);
137                 return -1;
138         }
139         ret = h->Node->Type->Write(h->Node, Offset, Length, Buffer);
140         if(ret == -1)   return -1;
141         return ret;
142 }
143
144 /**
145  * \fn Uint64 VFS_Tell(int FD)
146  * \brief Returns the current file position
147  */
148 Uint64 VFS_Tell(int FD)
149 {
150         tVFS_Handle     *h;
151         
152         h = VFS_GetHandle(FD);
153         if(!h)  return -1;
154         
155         return h->Position;
156 }
157
158 /**
159  * \fn int VFS_Seek(int FD, Sint64 Offset, int Whence)
160  * \brief Seek to a new location
161  * \param FD    File descriptor
162  * \param Offset        Where to go
163  * \param Whence        From where
164  */
165 int VFS_Seek(int FD, Sint64 Offset, int Whence)
166 {
167         tVFS_Handle     *h;
168         
169         h = VFS_GetHandle(FD);
170         if(!h)  return -1;
171         
172         //Log_Debug("VFS", "VFS_Seek: (fd=0x%x, Offset=0x%llx, Whence=%i)",
173         //      FD, Offset, Whence);
174         
175         // Set relative to current position
176         if(Whence == 0) {
177                 h->Position += Offset;
178                 return 0;
179         }
180         
181         // Set relative to end of file
182         if(Whence < 0) {
183                 if( h->Node->Size == -1 )       return -1;
184
185                 h->Position = h->Node->Size - Offset;
186                 return 0;
187         }
188         
189         // Set relative to start of file
190         h->Position = Offset;
191         return 0;
192 }
193
194 /**
195  * \fn int VFS_IOCtl(int FD, int ID, void *Buffer)
196  * \brief Call an IO Control on a file
197  */
198 int VFS_IOCtl(int FD, int ID, void *Buffer)
199 {
200         tVFS_Handle     *h;
201         
202         h = VFS_GetHandle(FD);
203         if(!h)  return -1;
204
205         if(!h->Node->Type || !h->Node->Type->IOCtl)     return -1;
206         return h->Node->Type->IOCtl(h->Node, ID, Buffer);
207 }
208
209 /**
210  * \fn int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
211  * \brief Retrieve file information
212  * \return Number of ACLs stored
213  */
214 int VFS_FInfo(int FD, tFInfo *Dest, int MaxACLs)
215 {
216         tVFS_Handle     *h;
217          int    max;
218         
219         h = VFS_GetHandle(FD);
220         if(!h)  return -1;
221
222         if( h->Mount )
223                 Dest->mount = h->Mount->Identifier;
224         else
225                 Dest->mount = 0;
226         Dest->inode = h->Node->Inode;   
227         Dest->uid = h->Node->UID;
228         Dest->gid = h->Node->GID;
229         Dest->size = h->Node->Size;
230         Dest->atime = h->Node->ATime;
231         Dest->ctime = h->Node->MTime;
232         Dest->mtime = h->Node->CTime;
233         Dest->numacls = h->Node->NumACLs;
234         
235         Dest->flags = 0;
236         if(h->Node->Flags & VFS_FFLAG_DIRECTORY)        Dest->flags |= 0x10;
237         if(h->Node->Flags & VFS_FFLAG_SYMLINK)  Dest->flags |= 0x20;
238         
239         max = (MaxACLs < h->Node->NumACLs) ? MaxACLs : h->Node->NumACLs;
240         memcpy(&Dest->acls, h->Node->ACLs, max*sizeof(tVFS_ACL));
241         
242         return max;
243 }
244
245 // === EXPORTS ===
246 EXPORT(VFS_Read);
247 EXPORT(VFS_Write);
248 EXPORT(VFS_ReadAt);
249 EXPORT(VFS_WriteAt);
250 EXPORT(VFS_IOCtl);
251 EXPORT(VFS_Seek);
252 EXPORT(VFS_Tell);

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