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 void close_file(com32sys_t *regs)
298 uint16_t handle = regs->esi.w[0];
302 file = handle_to_file(handle);
309 * initialize the memory management function;
310 * set up the vfs fs structure;
311 * initialize the device structure;
312 * invoke the fs-specific init function;
313 * initialize the cache if we need one;
314 * finally, get the current inode for relative path looking.
317 void fs_init(com32sys_t *regs)
319 static struct fs_info fs; /* The actual filesystem buffer */
320 uint8_t disk_devno = regs->edx.b[0];
321 uint8_t disk_cdrom = regs->edx.b[1];
322 sector_t disk_offset = regs->ecx.l | ((sector_t)regs->ebx.l << 32);
323 uint16_t disk_heads = regs->esi.w[0];
324 uint16_t disk_sectors = regs->edi.w[0];
326 struct device *dev = NULL;
327 /* ops is a ptr list for several fs_ops */
328 const struct fs_ops **ops = (const struct fs_ops **)regs->eax.l;
330 /* Initialize malloc() */
333 /* Default name for the root directory */
334 fs.cwd_name[0] = '/';
336 while ((blk_shift < 0) && *ops) {
337 /* set up the fs stucture */
341 * This boldly assumes that we don't mix FS_NODEV filesystems
342 * with FS_DEV filesystems...
344 if (fs.fs_ops->fs_flags & FS_NODEV) {
348 dev = device_init(disk_devno, disk_cdrom, disk_offset,
349 disk_heads, disk_sectors);
352 /* invoke the fs-specific init code */
353 blk_shift = fs.fs_ops->fs_init(&fs);
357 printf("No valid file system found!\n");
363 /* initialize the cache */
364 if (fs.fs_dev && fs.fs_dev->cache_data)
365 cache_init(fs.fs_dev, blk_shift);
367 /* start out in the root directory */
368 if (fs.fs_ops->iget_root) {
369 fs.root = fs.fs_ops->iget_root(&fs);
370 fs.cwd = get_inode(fs.root);