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 * Get an empty file structure
35 static struct file *alloc_file(void)
38 struct file *file = files;
40 for (i = 0; i < MAX_OPEN; i++) {
50 * Close and free a file structure
52 static inline void free_file(struct file *file)
54 memset(file, 0, sizeof *file);
57 void _close_file(struct file *file)
60 file->fs->fs_ops->close_file(file);
65 * Convert between a 16-bit file handle and a file structure
68 void load_config(void)
72 err = this_fs->fs_ops->load_config();
75 printf("ERROR: No configuration file found\n");
78 void pm_mangle_name(com32sys_t *regs)
80 const char *src = MK_PTR(regs->ds, regs->esi.w[0]);
81 char *dst = MK_PTR(regs->es, regs->edi.w[0]);
83 mangle_name(dst, src);
86 void mangle_name(char *dst, const char *src)
88 this_fs->fs_ops->mangle_name(dst, src);
91 void getfssec(com32sys_t *regs)
100 sectors = regs->ecx.w[0];
102 handle = regs->esi.w[0];
103 file = handle_to_file(handle);
105 buf = MK_PTR(regs->es, regs->ebx.w[0]);
106 bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
109 * If we reach EOF, the filesystem driver will have already closed
110 * the underlying file... this really should be cleaner.
117 regs->ecx.l = bytes_read;
120 size_t pmapi_read_file(uint16_t *handle, void *buf, size_t sectors)
126 file = handle_to_file(*handle);
127 bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);
130 * If we reach EOF, the filesystem driver will have already closed
131 * the underlying file... this really should be cleaner.
141 void pm_searchdir(com32sys_t *regs)
143 char *name = MK_PTR(regs->ds, regs->edi.w[0]);
146 rv = searchdir(name);
150 regs->eflags.l |= EFLAGS_ZF;
153 regs->eax.l = handle_to_file(rv)->file_len;
154 regs->eflags.l &= ~EFLAGS_ZF;
158 int searchdir(const char *name)
160 struct inode *inode = NULL;
161 struct inode *parent = NULL;
163 char *pathbuf = NULL;
164 char *part, *p, echar;
165 int symlink_count = MAX_SYMLINK_CNT;
167 if (!(file = alloc_file()))
171 /* if we have ->searchdir method, call it */
172 if (file->fs->fs_ops->searchdir) {
173 file->fs->fs_ops->searchdir(name, file);
176 return file_to_handle(file);
181 /* else, try the generic-path-lookup method */
183 parent = get_inode(this_fs->cwd);
184 p = pathbuf = strdup(name);
192 parent = get_inode(this_fs->root);
196 inode = get_inode(parent);
205 while ((echar = *p) && echar != '/')
209 if (part[0] != '.' || part[1] != '\0') {
210 inode = this_fs->fs_ops->iget(part, parent);
213 if (inode->mode == I_SYMLINK) {
215 int name_len = echar ? strlen(p) : 0;
216 int total_len = inode->size + name_len + 2;
219 if (!this_fs->fs_ops->readlink ||
220 --symlink_count == 0 || /* limit check */
221 total_len > MAX_SYMLINK_BUF)
224 linkbuf = malloc(total_len);
228 link_len = this_fs->fs_ops->readlink(inode, linkbuf);
234 q = linkbuf + link_len;
237 if (link_len > 0 && q[-1] != '/')
240 memcpy(q, p, name_len+1);
246 p = pathbuf = linkbuf;
258 if (inode->mode != I_DIR)
277 file->file_len = inode->size;
279 dprintf("File %s -> %p (inode %p) len %u\n", name, file,
282 return file_to_handle(file);
296 int open_file(const char *name, struct com32_filedata *filedata)
300 char mangled_name[FILENAME_MAX];
302 mangle_name(mangled_name, name);
303 rv = searchdir(mangled_name);
306 file = handle_to_file(rv);
307 filedata->size = file->file_len;
308 filedata->blocklg2 = SECTOR_SHIFT(file->fs);
309 filedata->handle = rv;
314 void pm_open_file(com32sys_t *regs)
318 const char *name = MK_PTR(regs->es, regs->esi.w[0]);
319 char mangled_name[FILENAME_MAX];
321 mangle_name(mangled_name, name);
322 rv = searchdir(mangled_name);
324 regs->eflags.l |= EFLAGS_CF;
326 file = handle_to_file(rv);
327 regs->eflags.l &= ~EFLAGS_CF;
328 regs->eax.l = file->file_len;
329 regs->ecx.w[0] = SECTOR_SIZE(file->fs);
334 void close_file(uint16_t handle)
339 file = handle_to_file(handle);
344 void pm_close_file(com32sys_t *regs)
346 close_file(regs->esi.w[0]);
351 * initialize the memory management function;
352 * set up the vfs fs structure;
353 * initialize the device structure;
354 * invoke the fs-specific init function;
355 * initialize the cache if we need one;
356 * finally, get the current inode for relative path looking.
359 void fs_init(com32sys_t *regs)
361 static struct fs_info fs; /* The actual filesystem buffer */
362 uint8_t disk_devno = regs->edx.b[0];
363 uint8_t disk_cdrom = regs->edx.b[1];
364 sector_t disk_offset = regs->ecx.l | ((sector_t)regs->ebx.l << 32);
365 uint16_t disk_heads = regs->esi.w[0];
366 uint16_t disk_sectors = regs->edi.w[0];
368 struct device *dev = NULL;
369 /* ops is a ptr list for several fs_ops */
370 const struct fs_ops **ops = (const struct fs_ops **)regs->eax.l;
372 /* Initialize malloc() */
375 /* Default name for the root directory */
376 fs.cwd_name[0] = '/';
378 while ((blk_shift < 0) && *ops) {
379 /* set up the fs stucture */
383 * This boldly assumes that we don't mix FS_NODEV filesystems
384 * with FS_DEV filesystems...
386 if (fs.fs_ops->fs_flags & FS_NODEV) {
390 dev = device_init(disk_devno, disk_cdrom, disk_offset,
391 disk_heads, disk_sectors);
394 /* invoke the fs-specific init code */
395 blk_shift = fs.fs_ops->fs_init(&fs);
399 printf("No valid file system found!\n");
405 /* initialize the cache */
406 if (fs.fs_dev && fs.fs_dev->cache_data)
407 cache_init(fs.fs_dev, blk_shift);
409 /* start out in the root directory */
410 if (fs.fs_ops->iget_root) {
411 fs.root = fs.fs_ops->iget_root(&fs);
412 fs.cwd = get_inode(fs.root);