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

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