- Implemented execp*.
[planlOS.git] / system / kernel / fs / fs.c
blob4bd677e61f2694e256edd2ddae12bf238cc53e9c
1 /*
2 Copyright (C) 2008 Mathias Gottschlag
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in the
6 Software without restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #include "fs/fs.h"
23 #include "ke/errors.h"
24 #include "ke/cpu.h"
25 #include "ke/level.h"
26 #include "ke/debug.h"
27 #include "fs/request.h"
28 #include <stdlib.h>
29 #include <string.h>
31 typedef struct FsDriverEntry
33 FsFileSystemDriver *driver;
34 char *name;
35 } FsDriverEntry;
37 static FsDriverEntry *drivers = 0;
38 static uint32_t driver_count = 0;
40 static FsFileSystem **file_systems = 0;
41 static uint32_t fs_count = 0;
43 int fsInit(void)
45 return KE_ERROR_NOTIMPLEMENTED;
48 int fsRegisterDriver(FsFileSystemDriver *driver, const char *name)
50 // Add driver to driver list
51 drivers = realloc(drivers, (driver_count + 1) * sizeof(FsDriverEntry));
52 drivers[driver_count].driver = driver;
53 drivers[driver_count].name = strdup(name);
54 driver_count++;
55 return 0;
57 int fsUnregisterDriver(FsFileSystemDriver *driver)
59 return KE_ERROR_NOTIMPLEMENTED;
61 FsFileSystemDriver *fsGetDriver(const char *name)
63 uint32_t i;
64 for (i = 0; i < driver_count; i++)
66 if (!strcmp(drivers[i].name, name)) return drivers[i].driver;
68 return 0;
70 int fsMount(FsFileSystemDriver *driver, const char *path, const char *device,
71 uint32_t flags)
73 if (!driver) return KE_ERROR_UNKNOWN;
74 // Call driver
75 FsFileSystem *fs = driver->mount(driver, path, device, flags);
76 if (!fs) return KE_ERROR_UNKNOWN;
77 // Add file system to list
78 file_systems = realloc(file_systems, (fs_count + 1) * sizeof(FsFileSystem*));
79 file_systems[fs_count] = fs;
80 fs_count++;
81 return 0;
83 int fsUnmount(const char *path)
85 return KE_ERROR_NOTIMPLEMENTED;
88 FsFileHandle *fsOpen(const char *filename, uint32_t mode)
90 /*KeExecLevel level = keGetExecutionLevel();
91 if (level == KE_LEVEL_HIGH)
93 kePrint("fsOpen called at KE_LEVEL_HIGH!\n");
94 return 0;
96 // Get file system from path
97 uint32_t i = 0;
98 FsFileSystem *fs = 0;
99 uint32_t matched = 0;
100 for (i = 0; i < fs_count; i++)
102 if (strlen(file_systems[i]->path) <= matched) continue;
103 if (!strncmp(file_systems[i]->path, filename, strlen(file_systems[i]->path)))
105 matched = strlen(file_systems[i]->path);
106 fs = file_systems[i];
109 if (!fs) return 0;
110 filename += matched;
111 // Send open request
112 FsRequest request;
113 memset(&request, 0, sizeof(request));
114 request.type = FS_REQUEST_OPEN;
115 request.fs = fs;
116 request.bufferlength = strlen(filename) + 1;
117 request.buffer = (char*)filename;
118 request.flags = mode;
119 int status = fsCreateRequest(&request, 1);
120 if (status) return 0;
121 if (request.status || request.return_value) return 0;
122 // Create file handle
123 FsFileHandle *fh = malloc(sizeof(FsFileHandle));
124 fh->file = request.file;
125 fh->file->refcount = 1;
126 fh->position = 0;
127 fh->flags = mode;
128 return fh;*/
129 return fsProcessOpen(0, filename, mode);
131 FsFileHandle *fsProcessOpen(struct KeProcess *process, const char *filename, uint32_t mode)
133 KeExecLevel level = keGetExecutionLevel();
134 if (level == KE_LEVEL_HIGH)
136 kePrint("fsProcessOpen called at KE_LEVEL_HIGH!\n");
137 return 0;
139 // Get file system from path
140 uint32_t i = 0;
141 FsFileSystem *fs = 0;
142 uint32_t matched = 0;
143 for (i = 0; i < fs_count; i++)
145 if (strlen(file_systems[i]->path) <= matched) continue;
146 if (!strncmp(file_systems[i]->path, filename, strlen(file_systems[i]->path)))
148 matched = strlen(file_systems[i]->path);
149 fs = file_systems[i];
152 if (!fs) return 0;
153 filename += matched;
154 // Send open request
155 FsRequest request;
156 memset(&request, 0, sizeof(request));
157 request.type = FS_REQUEST_OPEN;
158 request.fs = fs;
159 request.bufferlength = strlen(filename) + 1;
160 request.buffer = (char*)filename;
161 request.flags = mode;
162 int status = fsCreateRequest(&request, 1, process);
163 if (status) return 0;
164 if (request.status || request.return_value) return 0;
165 // Create file handle
166 FsFileHandle *fh = malloc(sizeof(FsFileHandle));
167 fh->file = request.file;
168 fh->file->refcount = 1;
169 fh->position = 0;
170 fh->flags = mode;
171 return fh;
173 int fsClose(FsFileHandle *file)
175 KeExecLevel level = keGetExecutionLevel();
176 if (level == KE_LEVEL_HIGH)
178 kePrint("fsClose called at KE_LEVEL_HIGH!\n");
179 return KE_ERROR_UNKNOWN;
181 if (!file) return KE_ERROR_UNKNOWN;
182 // Send close request
183 file->file->refcount--;
184 if (!file->file->refcount)
186 FsRequest request;
187 memset(&request, 0, sizeof(request));
188 request.type = FS_REQUEST_CLOSE;
189 request.fs = file->file->fs;
190 request.file = file->file;
191 int status = fsCreateRequest(&request, 1, 0);
192 if (status) return KE_ERROR_UNKNOWN;
193 if (request.status || request.return_value) return KE_ERROR_UNKNOWN;
195 free(file);
196 return 0;
198 int fsMknod(const char *filename, uint32_t mode)
200 KeExecLevel level = keGetExecutionLevel();
201 if (level == KE_LEVEL_HIGH)
203 kePrint("fsMknod called at KE_LEVEL_HIGH!\n");
204 return -1;
206 // Get file system from path
207 uint32_t i = 0;
208 FsFileSystem *fs = 0;
209 uint32_t matched = 0;
210 for (i = 0; i < fs_count; i++)
212 if (strlen(file_systems[i]->path) <= matched) continue;
213 if (!strncmp(file_systems[i]->path, filename, strlen(file_systems[i]->path)))
215 matched = strlen(file_systems[i]->path);
216 fs = file_systems[i];
219 if (!fs) return 0;
220 filename += matched;
221 // Send mknod request
222 FsRequest request;
223 memset(&request, 0, sizeof(request));
224 request.type = FS_REQUEST_MKNOD;
225 request.fs = fs;
226 request.bufferlength = strlen(filename) + 1;
227 request.buffer = (char*)filename;
228 request.flags = mode;
229 int status = fsCreateRequest(&request, 1, 0);
230 if (status) return -1;
231 if (request.status) return -1;
232 if (request.return_value) return request.return_value;
233 return 0;
237 int fsWrite(FsFileHandle *file, void *buffer, int size)
239 KeExecLevel level = keGetExecutionLevel();
240 if (level == KE_LEVEL_HIGH)
242 kePrint("fsWrite called at KE_LEVEL_HIGH!\n");
243 return KE_ERROR_UNKNOWN;
245 if (!file) return -1;
246 // Send close request
247 FsRequest request;
248 memset(&request, 0, sizeof(request));
249 request.type = FS_REQUEST_WRITE;
250 request.fs = file->file->fs;
251 request.file = file->file;
252 request.bufferlength = size;
253 request.buffer = buffer;
254 request.offset = file->position;
255 int status = fsCreateRequest(&request, 1, 0);
256 if (status) return -1;
257 if (request.status) return -1;
258 if (request.return_value > 0) file->position += request.return_value;
259 return request.return_value;
261 int fsRead(FsFileHandle *file, void *buffer, int size, int blocking)
263 KeExecLevel level = keGetExecutionLevel();
264 if (level == KE_LEVEL_HIGH)
266 kePrint("fsRead called at KE_LEVEL_HIGH!\n");
267 return KE_ERROR_UNKNOWN;
269 if (!file) return -1;
270 // Send close request
271 FsRequest request;
272 memset(&request, 0, sizeof(request));
273 request.type = FS_REQUEST_READ;
274 request.fs = file->file->fs;
275 request.file = file->file;
276 request.bufferlength = size;
277 request.buffer = buffer;
278 request.offset = file->position;
279 int status = fsCreateRequest(&request, 1, 0);
280 if (status) return -1;
281 if (request.status) return -1;
282 if (request.return_value > 0) file->position += request.return_value;
283 return request.return_value;
285 uint64_t fsSeek(FsFileHandle *file, int64_t offset, int whence)
287 KeExecLevel level = keGetExecutionLevel();
288 if (level == KE_LEVEL_HIGH)
290 kePrint("fsSeek called at KE_LEVEL_HIGH!\n");
291 return 0;
293 if (!file) return -1;
294 // Send seek request
295 FsRequest request;
296 memset(&request, 0, sizeof(request));
297 request.type = FS_REQUEST_SEEK;
298 request.fs = file->file->fs;
299 request.file = file->file;
300 if (whence == 1)
301 request.offset = file->position + offset;
302 else
303 request.offset = offset;
304 request.whence = whence;
305 int status = fsCreateRequest(&request, 1, 0);
306 if (status) return -1;
307 if (request.status) return -1;
308 file->position = request.offset;
309 return request.offset;
311 int fsIOCTL(FsFileHandle *file, int requestno, ...)
313 uintptr_t param = *(uintptr_t*)(&requestno + 1);
314 KeExecLevel level = keGetExecutionLevel();
315 if (level == KE_LEVEL_HIGH)
317 kePrint("fsIOCTL called at KE_LEVEL_HIGH!\n");
318 return -1;
320 // Send ioctl request
321 FsRequest request;
322 memset(&request, 0, sizeof(request));
323 request.type = FS_REQUEST_IOCTL;
324 request.fs = file->file->fs;
325 request.file = file->file;
326 request.offset = requestno;
327 request.buffer = (void*)param;
328 int status = fsCreateRequest(&request, 1, 0);
329 if (status) return -1;
330 if (request.status) return -1;
331 return request.return_value;
333 int fsGetIOCTLSize(FsFileHandle *file, int requestno)
335 KeExecLevel level = keGetExecutionLevel();
336 if (level == KE_LEVEL_HIGH)
338 kePrint("fsGetIOCTLSize called at KE_LEVEL_HIGH!\n");
339 return -1;
341 // Send ioctl size request
342 FsRequest request;
343 memset(&request, 0, sizeof(request));
344 request.type = FS_REQUEST_IOCTLSIZE;
345 request.fs = file->file->fs;
346 request.file = file->file;
347 request.offset = requestno;
348 int status = fsCreateRequest(&request, 1, 0);
349 if (status) return -1;
350 if (request.status) return -1;
351 return request.return_value;