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.
23 #include "ke/errors.h"
27 #include "fs/request.h"
31 typedef struct FsDriverEntry
33 FsFileSystemDriver
*driver
;
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;
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
);
57 int fsUnregisterDriver(FsFileSystemDriver
*driver
)
59 return KE_ERROR_NOTIMPLEMENTED
;
61 FsFileSystemDriver
*fsGetDriver(const char *name
)
64 for (i
= 0; i
< driver_count
; i
++)
66 if (!strcmp(drivers
[i
].name
, name
)) return drivers
[i
].driver
;
70 int fsMount(FsFileSystemDriver
*driver
, const char *path
, const char *device
,
73 if (!driver
) return KE_ERROR_UNKNOWN
;
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
;
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");
96 // Get file system from path
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];
113 memset(&request, 0, sizeof(request));
114 request.type = FS_REQUEST_OPEN;
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;
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");
139 // Get file system from path
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
];
156 memset(&request
, 0, sizeof(request
));
157 request
.type
= FS_REQUEST_OPEN
;
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;
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
)
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
;
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");
206 // Get file system from path
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
];
221 // Send mknod request
223 memset(&request
, 0, sizeof(request
));
224 request
.type
= FS_REQUEST_MKNOD
;
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
;
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
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
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");
293 if (!file
) return -1;
296 memset(&request
, 0, sizeof(request
));
297 request
.type
= FS_REQUEST_SEEK
;
298 request
.fs
= file
->file
->fs
;
299 request
.file
= file
->file
;
301 request
.offset
= file
->position
+ offset
;
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");
320 // Send ioctl 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");
341 // Send ioctl size 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
;