Add FAT32 driver, mount app, fix shell cd/path resolution

- FAT32 VFS driver (fat32.h, fat32.c): reads BPB, FAT table, cluster
  chains, directory entries (8.3 SFN), file read/write, mount via
  fat32_mount_device()
- mount app: writes 'device mountpoint' to /sys/vfs/mount to trigger
  FAT32 mount from userspace
- VFS sysfs mount namespace in kernel.c: handles mount requests via
  sysfs write to /sys/vfs/mount, delegates to FAT32 driver
- Shell cd: validates target directory exists before updating CWD,
  resolves relative paths (., .., components) to absolute paths
- Shell run_command: resolves ARG1 paths relative to CWD so apps
  like cat and ls receive absolute paths automatically
- Fixed FAT32 root directory access: use fs->root_cluster when
  VFS mount root node has inode=0
This commit is contained in:
AI
2026-02-23 14:52:41 +00:00
parent d1bf69ce0d
commit 5229758092
6 changed files with 1198 additions and 8 deletions

95
apps/mount/mount.c Normal file
View File

@@ -0,0 +1,95 @@
/**
* @file mount.c
* @brief Mount a block device as FAT32.
*
* Writes to /sys/vfs/mount to trigger a kernel-level FAT32 mount.
*
* Usage: mount <device> <path>
* e.g.: mount hdd1mbr1 /mnt
*/
#include "syscalls.h"
int main(void) {
char device[64];
char path[128];
if (getenv("ARG1", device, sizeof(device)) < 0 || device[0] == '\0') {
puts("Usage: mount <device> <mountpoint>\n");
puts(" e.g.: mount hdd1mbr1 /mnt\n");
return 1;
}
/* ARG1 contains "device path" — we need to split it.
* Actually, the shell currently only passes the first word as ARG1.
* Let's accept: mount <device> <path> where ARG1 = "device path" */
/* Find the space separating device and path */
int i = 0;
while (device[i] && device[i] != ' ') i++;
if (device[i] == ' ') {
/* ARG1 contains both: "hdd1mbr1 /mnt" */
device[i] = '\0';
/* Copy path part */
int j = i + 1;
while (device[j] == ' ') j++;
int pi = 0;
while (device[j] && pi < 127) {
path[pi++] = device[j++];
}
path[pi] = '\0';
} else {
/* Only device, no path — default to /mnt */
path[0] = '/'; path[1] = 'm'; path[2] = 'n'; path[3] = 't';
path[4] = '\0';
}
if (path[0] == '\0') {
puts("mount: missing mountpoint, using /mnt\n");
path[0] = '/'; path[1] = 'm'; path[2] = 'n'; path[3] = 't';
path[4] = '\0';
}
/* Build the mount command: "device path" */
char cmd[192];
int pos = 0;
for (int k = 0; device[k] && pos < 190; k++) cmd[pos++] = device[k];
cmd[pos++] = ' ';
for (int k = 0; path[k] && pos < 190; k++) cmd[pos++] = path[k];
cmd[pos] = '\0';
/* Open /sys/vfs/mount and write the command */
int32_t fd = open("/sys/vfs/mount", 0);
if (fd < 0) {
puts("mount: cannot open /sys/vfs/mount\n");
return 1;
}
int32_t n = write(fd, cmd, (uint32_t)pos);
close(fd);
if (n < 0) {
/* Read the status to show the error */
fd = open("/sys/vfs/mounts", 0);
if (fd >= 0) {
char status[256];
int32_t sn = read(fd, status, sizeof(status) - 1);
close(fd);
if (sn > 0) {
status[sn] = '\0';
puts(status);
}
} else {
puts("mount: failed\n");
}
return 1;
}
puts("mount: ");
puts(device);
puts(" mounted at ");
puts(path);
puts("\n");
return 0;
}