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
;