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

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