13 /* The currently mounted filesystem */
14 __export
struct fs_info
*this_fs
= NULL
; /* Root filesystem */
16 /* Actual file structures (we don't have malloc yet...) */
17 __export
struct file files
[MAX_OPEN
];
19 /* Symlink hard limits */
20 #define MAX_SYMLINK_CNT 20
21 #define MAX_SYMLINK_BUF 4096
24 * Get a new inode structure
26 struct inode
*alloc_inode(struct fs_info
*fs
, uint32_t ino
, size_t data
)
28 struct inode
*inode
= zalloc(sizeof(struct inode
) + data
);
38 * Free a refcounted inode
40 void put_inode(struct inode
*inode
)
43 struct inode
*dead
= inode
;
44 int refcnt
= --(dead
->refcnt
);
45 dprintf("put_inode %p name %s refcnt %u\n", dead
, dead
->name
, refcnt
);
47 break; /* We still have references */
50 free((char *)dead
->name
);
56 * Get an empty file structure
58 static struct file
*alloc_file(void)
61 struct file
*file
= files
;
63 for (i
= 0; i
< MAX_OPEN
; i
++) {
73 * Close and free a file structure
75 static inline void free_file(struct file
*file
)
77 memset(file
, 0, sizeof *file
);
80 __export
void _close_file(struct file
*file
)
83 file
->fs
->fs_ops
->close_file(file
);
88 * Find and open the configuration file
90 __export
int open_config(void)
95 fd
= opendev(&__file_dev
, NULL
, O_RDONLY
);
99 fp
= &__file_info
[fd
];
101 handle
= this_fs
->fs_ops
->open_config(&fp
->i
.fd
);
114 __export
void mangle_name(char *dst
, const char *src
)
116 this_fs
->fs_ops
->mangle_name(dst
, src
);
119 size_t pmapi_read_file(uint16_t *handle
, void *buf
, size_t sectors
)
125 file
= handle_to_file(*handle
);
126 bytes_read
= file
->fs
->fs_ops
->getfssec(file
, buf
, sectors
, &have_more
);
129 * If we reach EOF, the filesystem driver will have already closed
130 * the underlying file... this really should be cleaner.
140 int searchdir(const char *name
, int flags
)
142 static char root_name
[] = "/";
144 char *path
, *inode_name
, *next_inode_name
;
145 struct inode
*tmp
, *inode
= NULL
;
146 int symlink_count
= MAX_SYMLINK_CNT
;
148 dprintf("searchdir: %s root: %p cwd: %p\n",
149 name
, this_fs
->root
, this_fs
->cwd
);
151 if (!(file
= alloc_file()))
155 /* if we have ->searchdir method, call it */
156 if (file
->fs
->fs_ops
->searchdir
) {
157 file
->fs
->fs_ops
->searchdir(name
, flags
, file
);
160 return file_to_handle(file
);
165 /* else, try the generic-path-lookup method */
170 dprintf("searchdir: Couldn't copy path\n");
174 /* Work with the current directory, by default */
175 inode
= get_inode(this_fs
->cwd
);
177 dprintf("searchdir: Couldn't use current directory\n");
181 for (inode_name
= path
; inode_name
; inode_name
= next_inode_name
) {
182 /* Root directory? */
183 if (inode_name
[0] == '/') {
184 next_inode_name
= inode_name
+ 1;
185 inode_name
= root_name
;
187 /* Find the next inode name */
188 next_inode_name
= strchr(inode_name
+ 1, '/');
189 if (next_inode_name
) {
190 /* Terminate the current inode name and point to next */
191 *next_inode_name
++ = '\0';
194 if (next_inode_name
) {
195 /* Advance beyond redundant slashes */
196 while (*next_inode_name
== '/')
199 /* Check if we're at the end */
200 if (*next_inode_name
== '\0')
201 next_inode_name
= NULL
;
203 dprintf("searchdir: inode_name: %s\n", inode_name
);
205 dprintf("searchdir: Remaining: %s\n", next_inode_name
);
207 /* Root directory? */
208 if (inode_name
[0] == '/') {
209 /* Release any chain that's already been established */
211 inode
= get_inode(this_fs
->root
);
215 /* Current directory? */
216 if (!strncmp(inode_name
, ".", sizeof "."))
219 /* Parent directory? */
220 if (!strncmp(inode_name
, "..", sizeof "..")) {
221 /* If there is no parent, just ignore it */
225 /* Add a reference to the parent so we can release the child */
226 tmp
= get_inode(inode
->parent
);
228 /* Releasing the child will drop the parent back down to 1 */
237 inode
= this_fs
->fs_ops
->iget(inode_name
, inode
);
239 /* Failure. Release the chain */
245 if (inode
->parent
&& inode
->parent
!= tmp
) {
246 dprintf("searchdir: iget returned a different parent\n");
253 inode
->name
= strdup(inode_name
);
254 dprintf("searchdir: path component: %s\n", inode
->name
);
256 /* Symlink handling */
257 if (inode
->mode
== DT_LNK
) {
261 /* target path + NUL */
262 new_len
= inode
->size
+ 1;
264 if (next_inode_name
) {
265 /* target path + slash + remaining + NUL */
266 new_len
+= strlen(next_inode_name
) + 1;
269 if (!this_fs
->fs_ops
->readlink
||
271 --symlink_count
== 0 ||
272 new_len
> MAX_SYMLINK_BUF
)
275 new_path
= malloc(new_len
);
279 copied
= this_fs
->fs_ops
->readlink(inode
, new_path
);
282 new_path
[copied
] = '\0';
283 dprintf("searchdir: Symlink: %s\n", new_path
);
285 if (next_inode_name
) {
286 new_path
[copied
] = '/';
287 strcpy(new_path
+ copied
+ 1, next_inode_name
);
288 dprintf("searchdir: New path: %s\n", new_path
);
292 path
= next_inode_name
= new_path
;
294 /* Add a reference to the parent so we can release the child */
295 tmp
= get_inode(inode
->parent
);
297 /* Releasing the child will drop the parent back down to 1 */
311 /* If there's more to process, this should be a directory */
312 if (next_inode_name
&& inode
->mode
!= DT_DIR
) {
313 dprintf("searchdir: Expected a directory\n");
323 dprintf("searchdir: Not found\n");
330 return file_to_handle(file
);
333 dprintf("serachdir: error seraching file %s\n", name
);
339 __export
int open_file(const char *name
, int flags
, struct com32_filedata
*filedata
)
343 char mangled_name
[FILENAME_MAX
];
345 dprintf("open_file %s\n", name
);
347 mangle_name(mangled_name
, name
);
348 rv
= searchdir(mangled_name
, flags
);
353 file
= handle_to_file(rv
);
355 if (file
->inode
->mode
!= DT_REG
) {
360 filedata
->size
= file
->inode
->size
;
361 filedata
->blocklg2
= SECTOR_SHIFT(file
->fs
);
362 filedata
->handle
= rv
;
367 __export
void close_file(uint16_t handle
)
372 file
= handle_to_file(handle
);
379 * initialize the memory management function;
380 * set up the vfs fs structure;
381 * initialize the device structure;
382 * invoke the fs-specific init function;
383 * initialize the cache if we need one;
384 * finally, get the current inode for relative path looking.
386 * ops is a ptr list for several fs_ops
388 __bss16
uint16_t SectorSize
, SectorShift
;
390 void fs_init(const struct fs_ops
**ops
, void *priv
)
392 static struct fs_info fs
; /* The actual filesystem buffer */
394 struct device
*dev
= NULL
;
396 /* Default name for the root directory */
397 fs
.cwd_name
[0] = '/';
399 while ((blk_shift
< 0) && *ops
) {
400 /* set up the fs stucture */
404 * This boldly assumes that we don't mix FS_NODEV filesystems
405 * with FS_DEV filesystems...
407 if (fs
.fs_ops
->fs_flags
& FS_NODEV
) {
411 dev
= device_init(priv
);
414 /* invoke the fs-specific init code */
415 blk_shift
= fs
.fs_ops
->fs_init(&fs
);
419 printf("No valid file system found!\n");
425 /* initialize the cache */
426 if (fs
.fs_dev
&& fs
.fs_dev
->cache_data
)
427 cache_init(fs
.fs_dev
, blk_shift
);
429 /* start out in the root directory */
430 if (fs
.fs_ops
->iget_root
) {
431 fs
.root
= fs
.fs_ops
->iget_root(&fs
);
432 fs
.cwd
= get_inode(fs
.root
);
433 dprintf("init: root inode %p, cwd inode %p\n", fs
.root
, fs
.cwd
);
436 if (fs
.fs_ops
->chdir_start
) {
437 if (fs
.fs_ops
->chdir_start() < 0)
438 printf("Failed to chdir to start directory\n");
441 SectorShift
= fs
.sector_shift
;
442 SectorSize
= fs
.sector_size
;