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 pm_load_config(com32sys_t
*regs
)
84 err
= this_fs
->fs_ops
->load_config();
87 printf("ERROR: No configuration file found\n");
89 set_flags(regs
, err
? EFLAGS_ZF
: 0);
92 void pm_mangle_name(com32sys_t
*regs
)
94 const char *src
= MK_PTR(regs
->ds
, regs
->esi
.w
[0]);
95 char *dst
= MK_PTR(regs
->es
, regs
->edi
.w
[0]);
97 mangle_name(dst
, src
);
100 void mangle_name(char *dst
, const char *src
)
102 this_fs
->fs_ops
->mangle_name(dst
, src
);
105 void getfssec(com32sys_t
*regs
)
114 sectors
= regs
->ecx
.w
[0];
116 handle
= regs
->esi
.w
[0];
117 file
= handle_to_file(handle
);
119 buf
= MK_PTR(regs
->es
, regs
->ebx
.w
[0]);
120 bytes_read
= file
->fs
->fs_ops
->getfssec(file
, buf
, sectors
, &have_more
);
123 * If we reach EOF, the filesystem driver will have already closed
124 * the underlying file... this really should be cleaner.
131 regs
->ecx
.l
= bytes_read
;
134 void getfsbytes(com32sys_t
*regs
)
143 handle
= regs
->esi
.w
[0];
144 file
= handle_to_file(handle
);
146 sectors
= regs
->ecx
.w
[0] >> SECTOR_SHIFT(file
->fs
);
148 buf
= MK_PTR(regs
->es
, regs
->ebx
.w
[0]);
149 bytes_read
= file
->fs
->fs_ops
->getfssec(file
, buf
, sectors
, &have_more
);
152 * If we reach EOF, the filesystem driver will have already closed
153 * the underlying file... this really should be cleaner.
160 regs
->ecx
.l
= bytes_read
;
163 size_t pmapi_read_file(uint16_t *handle
, void *buf
, size_t sectors
)
169 file
= handle_to_file(*handle
);
170 bytes_read
= file
->fs
->fs_ops
->getfssec(file
, buf
, sectors
, &have_more
);
173 * If we reach EOF, the filesystem driver will have already closed
174 * the underlying file... this really should be cleaner.
184 void pm_searchdir(com32sys_t
*regs
)
186 char *name
= MK_PTR(regs
->ds
, regs
->edi
.w
[0]);
189 rv
= searchdir(name
);
193 regs
->eflags
.l
|= EFLAGS_ZF
;
196 regs
->eax
.l
= handle_to_file(rv
)->inode
->size
;
197 regs
->eflags
.l
&= ~EFLAGS_ZF
;
201 int searchdir(const char *name
)
203 struct inode
*inode
= NULL
;
204 struct inode
*parent
= NULL
;
206 char *pathbuf
= NULL
;
207 char *part
, *p
, echar
;
208 int symlink_count
= MAX_SYMLINK_CNT
;
210 if (!(file
= alloc_file()))
214 /* if we have ->searchdir method, call it */
215 if (file
->fs
->fs_ops
->searchdir
) {
216 file
->fs
->fs_ops
->searchdir(name
, file
);
219 return file_to_handle(file
);
224 /* else, try the generic-path-lookup method */
226 parent
= get_inode(this_fs
->cwd
);
227 p
= pathbuf
= strdup(name
);
235 parent
= get_inode(this_fs
->root
);
239 inode
= get_inode(parent
);
248 while ((echar
= *p
) && echar
!= '/')
252 if (part
[0] == '.' && part
[1] == '.' && part
[2] == '\0') {
255 parent
= get_inode(inode
->parent
);
259 /* Terminal double dots */
261 parent
= inode
->parent
?
262 get_inode(inode
->parent
) : NULL
;
265 } else if (part
[0] != '.' || part
[1] != '\0') {
266 inode
= this_fs
->fs_ops
->iget(part
, parent
);
269 if (inode
->mode
== DT_LNK
) {
271 int name_len
= echar
? strlen(p
) : 0;
272 int total_len
= inode
->size
+ name_len
+ 2;
275 if (!this_fs
->fs_ops
->readlink
||
276 --symlink_count
== 0 || /* limit check */
277 total_len
> MAX_SYMLINK_BUF
)
280 linkbuf
= malloc(total_len
);
284 link_len
= this_fs
->fs_ops
->readlink(inode
, linkbuf
);
290 q
= linkbuf
+ link_len
;
293 if (link_len
> 0 && q
[-1] != '/')
296 memcpy(q
, p
, name_len
+1);
302 p
= pathbuf
= linkbuf
;
308 inode
->parent
= parent
;
314 if (inode
->mode
!= DT_DIR
)
334 return file_to_handle(file
);
346 int open_file(const char *name
, struct com32_filedata
*filedata
)
350 char mangled_name
[FILENAME_MAX
];
352 mangle_name(mangled_name
, name
);
353 rv
= searchdir(mangled_name
);
358 file
= handle_to_file(rv
);
360 if (file
->inode
->mode
!= DT_REG
) {
365 filedata
->size
= file
->inode
->size
;
366 filedata
->blocklg2
= SECTOR_SHIFT(file
->fs
);
367 filedata
->handle
= rv
;
372 void pm_open_file(com32sys_t
*regs
)
376 const char *name
= MK_PTR(regs
->es
, regs
->esi
.w
[0]);
377 char mangled_name
[FILENAME_MAX
];
379 mangle_name(mangled_name
, name
);
380 rv
= searchdir(mangled_name
);
382 regs
->eflags
.l
|= EFLAGS_CF
;
384 file
= handle_to_file(rv
);
385 regs
->eflags
.l
&= ~EFLAGS_CF
;
386 regs
->eax
.l
= file
->inode
->size
;
387 regs
->ecx
.w
[0] = SECTOR_SIZE(file
->fs
);
392 void close_file(uint16_t handle
)
397 file
= handle_to_file(handle
);
402 void pm_close_file(com32sys_t
*regs
)
404 close_file(regs
->esi
.w
[0]);
409 * initialize the memory management function;
410 * set up the vfs fs structure;
411 * initialize the device structure;
412 * invoke the fs-specific init function;
413 * initialize the cache if we need one;
414 * finally, get the current inode for relative path looking.
416 __bss16
uint16_t SectorSize
, SectorShift
;
418 void fs_init(com32sys_t
*regs
)
420 static struct fs_info fs
; /* The actual filesystem buffer */
421 uint8_t disk_devno
= regs
->edx
.b
[0];
422 uint8_t disk_cdrom
= regs
->edx
.b
[1];
423 sector_t disk_offset
= regs
->ecx
.l
| ((sector_t
)regs
->ebx
.l
<< 32);
424 uint16_t disk_heads
= regs
->esi
.w
[0];
425 uint16_t disk_sectors
= regs
->edi
.w
[0];
426 uint32_t maxtransfer
= regs
->ebp
.l
;
428 struct device
*dev
= NULL
;
429 /* ops is a ptr list for several fs_ops */
430 const struct fs_ops
**ops
= (const struct fs_ops
**)regs
->eax
.l
;
432 /* Initialize malloc() */
435 /* Default name for the root directory */
436 fs
.cwd_name
[0] = '/';
438 while ((blk_shift
< 0) && *ops
) {
439 /* set up the fs stucture */
443 * This boldly assumes that we don't mix FS_NODEV filesystems
444 * with FS_DEV filesystems...
446 if (fs
.fs_ops
->fs_flags
& FS_NODEV
) {
450 dev
= device_init(disk_devno
, disk_cdrom
, disk_offset
,
451 disk_heads
, disk_sectors
, maxtransfer
);
454 /* invoke the fs-specific init code */
455 blk_shift
= fs
.fs_ops
->fs_init(&fs
);
459 printf("No valid file system found!\n");
465 /* initialize the cache */
466 if (fs
.fs_dev
&& fs
.fs_dev
->cache_data
)
467 cache_init(fs
.fs_dev
, blk_shift
);
469 /* start out in the root directory */
470 if (fs
.fs_ops
->iget_root
) {
471 fs
.root
= fs
.fs_ops
->iget_root(&fs
);
472 fs
.cwd
= get_inode(fs
.root
);
475 SectorShift
= fs
.sector_shift
;
476 SectorSize
= fs
.sector_size
;