2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-2019 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
27 struct filesys *fsfat_create(int dev, uint64_t start, uint64_t size);
28 struct filesys *fsmem_create(int dev, uint64_t start, uint64_t size);
30 static struct filesys *(*createfs[])(int, uint64_t, uint64_t) = {
35 struct filesys *fs_mount(int dev, uint64_t start, uint64_t size, struct fs_node *parent)
40 if(!parent && rootfs) {
41 printf("fs_mount error: root filesystem already mounted!\n");
45 for(i=0; i<NUM_FSTYPES; i++) {
46 if((fs = createfs[i](dev, start, size))) {
59 printf("failed to mount filesystem dev: %d, start %llu\n", dev, (unsigned long long)start);
63 static char cwdpath[1024];
64 static char *cwdpath_end = cwdpath;
66 int fs_chdir(const char *path)
76 if(strcmp(path, ".") == 0) {
79 if(strcmp(path, "..") == 0) {
82 if(cwdpath_end <= cwdpath + 1) {
86 endptr = cwdpath + (cwdpath_end - cwdpath);
87 while(endptr > cwdpath && *--endptr != '/');
88 if(endptr == cwdpath) endptr++;
90 uplen = endptr - cwdpath;
91 uppath = alloca(uplen + 1);
92 memcpy(uppath, cwdpath, uplen);
98 if(!(node = fs_open(path, 0))) {
101 if(node->type != FSNODE_DIR) {
107 memcpy(cwdpath, uppath, uplen + 1);
108 cwdpath_end = cwdpath + uplen;
111 int len = strlen(path);
112 if(cwdpath_end - cwdpath + len > sizeof cwdpath) {
113 panic("fs_chdir: path too long: %s\n", path);
116 memcpy(cwdpath, path, len + 1);
117 cwdpath_end = cwdpath + len;
119 if(cwdpath_end > cwdpath + 1) {
120 *cwdpath_end++ = '/';
122 memcpy(cwdpath_end, path, len + 1);
132 char *fs_getcwd(void)
137 /* TODO normalize path */
138 struct fs_node *fs_open(const char *path, unsigned int flags)
141 struct fs_node *node;
143 if(!path || !*path) {
150 if(!cwdnode) return 0;
154 if(!(node = fs->fsop->open(fs, path, flags))) {
160 int fs_close(struct fs_node *node)
162 struct fs_operations *fsop;
166 fsop = node->fs->fsop;
171 int fs_rename(struct fs_node *node, const char *name)
173 struct fs_operations *fsop = node->fs->fsop;
174 return fsop->rename(node, name);
177 int fs_remove(struct fs_node *node)
179 struct fs_operations *fsop = node->fs->fsop;
180 return fsop->remove(node);
183 long fs_filesize(struct fs_node *node)
185 struct fs_operations *fsop = node->fs->fsop;
187 if(node->type != FSNODE_FILE) {
190 return fsop->fsize(node);
193 int fs_seek(struct fs_node *node, int offs, int whence)
195 struct fs_operations *fsop = node->fs->fsop;
197 if(node->type != FSNODE_FILE) {
200 return fsop->seek(node, offs, whence);
203 long fs_tell(struct fs_node *node)
205 struct fs_operations *fsop = node->fs->fsop;
207 if(node->type != FSNODE_FILE) {
210 return fsop->tell(node);
213 int fs_read(struct fs_node *node, void *buf, int sz)
215 struct fs_operations *fsop = node->fs->fsop;
217 if(node->type != FSNODE_FILE) {
220 return fsop->read(node, buf, sz);
223 int fs_write(struct fs_node *node, void *buf, int sz)
225 struct fs_operations *fsop = node->fs->fsop;
227 if(node->type != FSNODE_FILE) {
230 return fsop->write(node, buf, sz);
233 int fs_rewinddir(struct fs_node *node)
235 struct fs_operations *fsop = node->fs->fsop;
237 if(node->type != FSNODE_DIR) {
240 return fsop->rewinddir(node);
243 struct fs_dirent *fs_readdir(struct fs_node *node)
245 struct fs_operations *fsop = node->fs->fsop;
247 if(node->type != FSNODE_DIR) {
250 return fsop->readdir(node);
253 /* fs utility functions */
254 char *fs_path_skipsep(char *s)
256 while(*s == '/') s++;
260 char *fs_path_next(char *s, char *namebuf, int bufsz)
265 ptr = s = fs_path_skipsep(s);
267 while(*ptr && *ptr != '/') ptr++;
271 if(len >= bufsz) len = bufsz - 1;
273 memcpy(namebuf, s, len);
277 return fs_path_skipsep(ptr);