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

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