Add sysfs VFS driver, SYS_OPEN/CLOSE syscalls, cat app
Sysfs: - New VFS driver mounted at /sys that lets kernel drivers expose virtual text files via namespace registration - Drivers call sysfs_register(name, ops, ctx) with list/read/write callbacks for their namespace - IDE driver registers 'ide' namespace exposing per-device attributes: model, type, channel, drive, sectors, sector_size - Tested: ls /sys -> ide, ls /sys/ide -> hdd1 cd1, cat /sys/ide/hdd1/model -> QEMU HARDDISK Syscalls: - Added SYS_OPEN (11) and SYS_CLOSE (12) for file I/O from userspace - Extended SYS_READ/SYS_WRITE to handle VFS file descriptors (fd >= 3) - Updated userspace syscalls.h with open()/close() wrappers Apps: - New 'cat' app: reads and displays file contents via open/read/close - Updated 'ls' to accept path argument via ARG1 env var - Updated shell to pass ARG1 env var to external commands
This commit is contained in:
41
apps/cat/cat.c
Normal file
41
apps/cat/cat.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file cat.c
|
||||
* @brief Display file contents.
|
||||
*
|
||||
* Reads a file specified as the first argument (from shell)
|
||||
* and prints its contents to stdout. If no argument is given,
|
||||
* prints usage.
|
||||
*
|
||||
* Usage: cat <filepath>
|
||||
*/
|
||||
|
||||
#include "syscalls.h"
|
||||
|
||||
int main(void) {
|
||||
/* Get the file path from the ARGS environment variable.
|
||||
* The shell sets ARGS to the arguments after the command name. */
|
||||
char path[128];
|
||||
if (getenv("ARG1", path, sizeof(path)) < 0) {
|
||||
puts("Usage: cat <file>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
int32_t fd = open(path, 0);
|
||||
if (fd < 0) {
|
||||
puts("cat: ");
|
||||
puts(path);
|
||||
puts(": open failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read and print in chunks */
|
||||
char buf[256];
|
||||
int32_t n;
|
||||
while ((n = read(fd, buf, sizeof(buf))) > 0) {
|
||||
write(1, buf, (uint32_t)n);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -24,6 +24,8 @@ typedef int int32_t;
|
||||
#define SYS_GETENV 8
|
||||
#define SYS_SETENV 9
|
||||
#define SYS_READDIR 10
|
||||
#define SYS_OPEN 11
|
||||
#define SYS_CLOSE 12
|
||||
|
||||
static inline int32_t syscall0(int num) {
|
||||
int32_t ret;
|
||||
@@ -103,6 +105,25 @@ static inline int32_t readdir(const char *path, uint32_t idx, char *name) {
|
||||
return syscall3(SYS_READDIR, (uint32_t)path, idx, (uint32_t)name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file by path.
|
||||
* @param path File path.
|
||||
* @param flags Open flags (currently unused, pass 0).
|
||||
* @return File descriptor (>= 3) on success, -1 on failure.
|
||||
*/
|
||||
static inline int32_t open(const char *path, uint32_t flags) {
|
||||
return syscall2(SYS_OPEN, (uint32_t)path, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a file descriptor.
|
||||
* @param fd File descriptor.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static inline int32_t close(int32_t fd) {
|
||||
return syscall1(SYS_CLOSE, (uint32_t)fd);
|
||||
}
|
||||
|
||||
/* Basic string operations for user-space */
|
||||
static inline uint32_t strlen(const char *s) {
|
||||
uint32_t len = 0;
|
||||
|
||||
12
apps/ls/ls.c
12
apps/ls/ls.c
@@ -10,12 +10,14 @@
|
||||
#include "syscalls.h"
|
||||
|
||||
int main(void) {
|
||||
/* Get the current working directory */
|
||||
/* Check for an explicit path argument first */
|
||||
char cwd[128];
|
||||
if (getenv("CWD", cwd, sizeof(cwd)) < 0) {
|
||||
/* Default to root if CWD not set */
|
||||
cwd[0] = '/';
|
||||
cwd[1] = '\0';
|
||||
if (getenv("ARG1", cwd, sizeof(cwd)) < 0 || cwd[0] == '\0') {
|
||||
/* No argument; use the current working directory */
|
||||
if (getenv("CWD", cwd, sizeof(cwd)) < 0) {
|
||||
cwd[0] = '/';
|
||||
cwd[1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
char name[128];
|
||||
|
||||
13
apps/sh/sh.c
13
apps/sh/sh.c
@@ -105,7 +105,7 @@ static void builtin_help(void) {
|
||||
}
|
||||
|
||||
/** Execute an external command via fork+exec. */
|
||||
static void run_command(const char *cmd) {
|
||||
static void run_command(const char *cmd, const char *arg) {
|
||||
int32_t pid = fork();
|
||||
if (pid < 0) {
|
||||
puts("sh: fork failed\n");
|
||||
@@ -113,7 +113,14 @@ static void run_command(const char *cmd) {
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child: exec the command */
|
||||
/* Child: set ARG1 if there's an argument */
|
||||
if (arg && *arg) {
|
||||
setenv("ARG1", arg);
|
||||
} else {
|
||||
setenv("ARG1", "");
|
||||
}
|
||||
|
||||
/* exec the command */
|
||||
int32_t ret = exec(cmd);
|
||||
if (ret < 0) {
|
||||
puts("sh: ");
|
||||
@@ -172,7 +179,7 @@ int main(void) {
|
||||
builtin_help();
|
||||
} else {
|
||||
/* External command */
|
||||
run_command(line);
|
||||
run_command(line, arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user