8 /* The currently mounted filesystem */
9 struct fs_info *this_fs = NULL; /* Root filesystem */
11 /* Actual file structures (we don't have malloc yet...) */
12 struct file files[MAX_OPEN];
14 /* Symlink hard limits */
15 #define MAX_SYMLINK_CNT 20
16 #define MAX_SYMLINK_BUF 4096
19 * Get a new inode structure
21 struct inode *alloc_inode(struct fs_info *fs, uint32_t ino, size_t data)
23 struct inode *inode = zalloc(sizeof(struct inode) + data);
33 * Free a refcounted inode
35 void put_inode(struct inode *inode)
37 while (inode && --inode->refcnt == 0) {
38 struct inode *dead = inode;
39 inode = inode->parent;
45 * Get an empty file structure
47 static struct file *alloc_file(void)
50 struct file *file = files;
52 for (i = 0; i < MAX_OPEN; i++) {
62 * Close and free a file structure
64 static inline void free_file(struct file *file)
66 memset(file, 0, sizeof *file);
69 void _close_file(struct file *file)
72 file->fs->fs_ops->close_file(file);
77 * Convert between a 16-bit file handle and a file structure
80 void load_config(void)
84 err = this_fs->fs_ops->load_config();
87 printf("ERROR: No configuration file found\n");
90 void pm_mangle_name(com32sys_t *regs)
92 const char *src = MK_PTR(regs->ds, regs->esi.w[0]);
93 char *dst = MK_PTR(regs->es, regs->edi.w[0]);
95 mangle_name(dst, src);
98 void mangle_name(char *dst, const char *src)
100 this_fs->fs_ops->mangle_name(dst, src);
103 void getfssec(com32sys_t *regs)
112 sectors = regs->ecx.w[0];
114 handle = regs->esi.w[0];
115 file = handle_to_file(handle);
117 buf = MK_PTR(regs->es, regs->ebx.w[0]);
118 bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
121 * If we reach EOF, the filesystem driver will have already closed
122 * the underlying file... this really should be cleaner.
129 regs->ecx.l = bytes_read;
132 void getfsbytes(com32sys_t *regs)
141 handle = regs->esi.w[0];
142 file = handle_to_file(handle);
144 sectors = regs->ecx.w[0] >> SECTOR_SHIFT(file->fs);
146 buf = MK_PTR(regs->es, regs->ebx.w[0]);
147 bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
150 * If we reach EOF, the filesystem driver will have already closed
151 * the underlying file... this really should be cleaner.
158 regs->ecx.l = bytes_read;
161 size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
167 file = handle_to_file(*handle);
168 bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
171 * If we reach EOF, the filesystem driver will have already closed
172 * the underlying file... this really should be cleaner.
182 void pm_searchdir(com32sys_t *regs)
184 char *name = MK_PTR(regs->ds, regs->edi.w[0]);
187 rv = searchdir(name);
191 regs->eflags.l |= EFLAGS_ZF;
194 regs->eax.l = handle_to_file(rv)->inode->size;
195 regs->eflags.l &= ~EFLAGS_ZF;
199 int searchdir(const char *name)
201 struct inode *inode = NULL;
202 struct inode *parent = NULL;
204 char *pathbuf = NULL;
205 char *part, *p, echar;
206 int symlink_count = MAX_SYMLINK_CNT;
208 if (!(file = alloc_file()))
212 /* if we have ->searchdir method, call it */
213 if (file->fs->fs_ops->searchdir) {
214 file->fs->fs_ops->searchdir(name, file);
217 return file_to_handle(file);
222 /* else, try the generic-path-lookup method */
224 parent = get_inode(this_fs->cwd);
225 p = pathbuf = strdup(name);
233 parent = get_inode(this_fs->root);
237 inode = get_inode(parent);
246 while ((echar = *p) && echar != '/')
250 if (part[0] == '.' && part[1] == '.' && part[2] == '\0') {
253 parent = get_inode(inode->parent);
257 /* Terminal double dots */
259 parent = inode->parent ?
260 get_inode(inode->parent) : NULL;
263 } else if (part[0] != '.' || part[1] != '\0') {
264 inode = this_fs->fs_ops->iget(part, parent);
267 if (inode->mode == DT_LNK) {
269 int name_len = echar ? strlen(p) : 0;
270 int total_len = inode->size + name_len + 2;
273 if (!this_fs->fs_ops->readlink ||
274 --symlink_count == 0 || /* limit check */
275 total_len > MAX_SYMLINK_BUF)
278 linkbuf = malloc(total_len);
282 link_len = this_fs->fs_ops->readlink(inode, linkbuf);
288 q = linkbuf + link_len;
291 if (link_len > 0 && q[-1] != '/')
294 memcpy(q, p, name_len+1);
300 p = pathbuf = linkbuf;
306 inode->parent = parent;
312 if (inode->mode != DT_DIR)
332 return file_to_handle(file);
344 int open_file(const char *name, struct com32_filedata *filedata)
348 char mangled_name[FILENAME_MAX];
350 mangle_name(mangled_name, name);
351 rv = searchdir(mangled_name);
356 file = handle_to_file(rv);
358 if (file->inode->mode != DT_REG) {
363 filedata->size = file->inode->size;
364 filedata->blocklg2 = SECTOR_SHIFT(file->fs);
365 filedata->handle = rv;
370 void pm_open_file(com32sys_t *regs)
374 const char *name = MK_PTR(regs->es, regs->esi.w[0]);
375 char mangled_name[FILENAME_MAX];
377 mangle_name(mangled_name, name);
378 rv = searchdir(mangled_name);
380 regs->eflags.l |= EFLAGS_CF;
382 file = handle_to_file(rv);
383 regs->eflags.l &= ~EFLAGS_CF;
384 regs->eax.l = file->inode->size;
385 regs->ecx.w[0] = SECTOR_SIZE(file->fs);
390 void close_file(uint16_t handle)
395 file = handle_to_file(handle);
400 void pm_close_file(com32sys_t *regs)
402 close_file(regs->esi.w[0]);
407 * initialize the memory management function;
408 * set up the vfs fs structure;
409 * initialize the device structure;
410 * invoke the fs-specific init function;
411 * initialize the cache if we need one;
412 * finally, get the current inode for relative path looking.
414 __bss16 uint16_t SectorSize, SectorShift;
416 void fs_init(com32sys_t *regs)
418 static struct fs_info fs; /* The actual filesystem buffer */
419 uint8_t disk_devno = regs->edx.b[0];
420 uint8_t disk_cdrom = regs->edx.b[1];
421 sector_t disk_offset = regs->ecx.l | ((sector_t)regs->ebx.l << 32);
422 uint16_t disk_heads = regs->esi.w[0];
423 uint16_t disk_sectors = regs->edi.w[0];
424 uint32_t maxtransfer = regs->ebp.l;
426 struct device *dev = NULL;
427 /* ops is a ptr list for several fs_ops */
428 const struct fs_ops **ops = (const struct fs_ops **)regs->eax.l;
430 /* Initialize malloc() */
433 /* Default name for the root directory */
434 fs.cwd_name[0] = '/';
436 while ((blk_shift < 0) && *ops) {
437 /* set up the fs stucture */
441 * This boldly assumes that we don't mix FS_NODEV filesystems
442 * with FS_DEV filesystems...
444 if (fs.fs_ops->fs_flags & FS_NODEV) {
448 dev = device_init(disk_devno, disk_cdrom, disk_offset,
449 disk_heads, disk_sectors, maxtransfer);
452 /* invoke the fs-specific init code */
453 blk_shift = fs.fs_ops->fs_init(&fs);
457 printf("No valid file system found!\n");
463 /* initialize the cache */
464 if (fs.fs_dev && fs.fs_dev->cache_data)
465 cache_init(fs.fs_dev, blk_shift);
467 /* start out in the root directory */
468 if (fs.fs_ops->iget_root) {
469 fs.root = fs.fs_ops->iget_root(&fs);
470 fs.cwd = get_inode(fs.root);
473 SectorShift = fs.sector_shift;
474 SectorSize = fs.sector_size;