diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..135458b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,17 @@
+# Set default behavior to automatically normalize line endings
+* text=auto
+
+# Force LF for source files (Unix-style, common for C projects)
+*.c text eol=lf
+*.h text eol=lf
+*.ld text eol=lf
+*.sh text eol=lf
+
+# Binary files
+*.bin binary
+*.elf binary
+*.tar binary
+*.png binary
+*.ico binary
+*.svg binary
+
diff --git a/README.md b/README.md
index 4c681df..aa62f03 100644
--- a/README.md
+++ b/README.md
@@ -14,4 +14,27 @@ The book only covers the basics of an operating system. You can do more with the
| --- | --- |
| [Shutdown command](https://github.com/nuta/operating-system-in-1000-lines/pull/59/files) | [@calvera](https://github.com/calvera) |
-Let me know if you have implemented something interesting!
+
+
+I added
+
+ls
+
+
+
+addf
+
+
+readf
+
+
+writef
+
+
+
+
+
+
+
+
+commands and syscalls needed
diff --git a/common.c b/common.c
index 9cd9e25..66eafa4 100644
--- a/common.c
+++ b/common.c
@@ -22,6 +22,19 @@ char *strcpy(char *dst, const char *src) {
*d = '\0';
return dst;
}
+int strncmp(const char *s1, const char *s2, int n) {
+ for (int i = 0; i < n; i++) {
+ unsigned char c1 = (unsigned char)s1[i];
+ unsigned char c2 = (unsigned char)s2[i];
+
+ if (c1 != c2)
+ return c1 - c2;
+ if (c1 == '\0') // Eğer birisi '\0' ise karşılaştırmayı bitir
+ return 0;
+ }
+ return 0;
+}
+
int strcmp(const char *s1, const char *s2) {
while (*s1 && *s2) {
diff --git a/common.h b/common.h
index 286df8a..6abd316 100644
--- a/common.h
+++ b/common.h
@@ -25,9 +25,14 @@ typedef uint32_t vaddr_t;
#define SYS_EXIT 3
#define SYS_READFILE 4
#define SYS_WRITEFILE 5
-
+#define SYS_ADDFILE 6
+#define SYS_READF 7
+#define SYS_ADDF 8
+#define SYS_WRITEF 9
+#define SYS_LS 10
void *memset(void *buf, char c, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
char *strcpy(char *dst, const char *src);
int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, int n);
void printf(const char *fmt, ...);
diff --git a/kernel.c b/kernel.c
index ec7b666..97a8472 100644
--- a/kernel.c
+++ b/kernel.c
@@ -497,13 +497,100 @@ void handle_syscall(struct trap_frame *f) {
yield();
}
break;
+ case SYS_READF: {
+ const char *filename = (const char *) f->a0;
+ struct file *file = fs_lookup(filename);
+ if (!file) {
+ f->a0 = -1; // dosya yok
+ break;
+ }
+
+ // Dosya içeriğini console’a yaz
+ for (int i = 0; i < file->size; i++)
+ putchar(file->data[i]);
+
+ f->a0 = file->size;
+ break;
+
+}
+case SYS_LS: {
+ printf("Files:\n");
+ for (int i = 0; i < FILES_MAX; i++) {
+ if (files[i].in_use) {
+ printf(" %s (size: %d)\n", files[i].name, files[i].size);
+ }
+ }
+ f->a0 = 0;
+ break;
+}
+
+case SYS_ADDF: {
+ const char *filename = (const char *) f->a0;
+ struct file *file = NULL;
+ for (int i = 0; i < FILES_MAX; i++) {
+ if (!files[i].in_use) {
+ file = &files[i];
+ break;
+ }
+ }
+ if (!file) { f->a0 = -1; break; }
+ file->in_use = true;
+ strcpy(file->name, filename);
+ file->size = 0;
+ fs_flush();
+ f->a0 = 0;
+ break;
+}
+
+case SYS_WRITEF: {
+ const char *filename = (const char *) f->a0;
+ struct file *file = fs_lookup(filename);
+ if (!file) { f->a0 = -1; break; }
+
+ char *buf = (char *) f->a1;
+ int len = f->a2;
+ if (len > (int) sizeof(file->data))
+ len = sizeof(file->data);
+ memcpy(file->data, buf, len);
+ file->size = len;
+ fs_flush();
+ f->a0 = len;
+ break;
+}
+
+
+ case SYS_ADDFILE: {
+ const char *filename = (const char *) f->a0;
+
+ // find free slot
+ struct file *file = NULL;
+ for (int i = 0; i < FILES_MAX; i++) {
+ if (!files[i].in_use) {
+ file = &files[i];
+ break;
+ }
+ }
+
+ if (!file) {
+ f->a0 = -1; // fail
+ break;
+ }
+
+ file->in_use = true;
+ strcpy(file->name, filename);
+ file->size = 0; // boş dosya
+ fs_flush(); // diske yaz
+ f->a0 = 0; // success
+ break;
+ }
+
case SYS_EXIT:
printf("process %d exited\n", current_proc->pid);
current_proc->state = PROC_EXITED;
yield();
PANIC("unreachable");
case SYS_READFILE:
- case SYS_WRITEFILE: {
+ case SYS_WRITEFILE: {
const char *filename = (const char *) f->a0;
char *buf = (char *) f->a1;
int len = f->a2;
diff --git a/kernel.h b/kernel.h
index 6969d99..95f32fb 100644
--- a/kernel.h
+++ b/kernel.h
@@ -15,7 +15,7 @@
#define PAGE_X (1 << 3)
#define PAGE_U (1 << 4)
#define USER_BASE 0x1000000
-#define FILES_MAX 2
+#define FILES_MAX 3
#define DISK_MAX_SIZE align_up(sizeof(struct file) * FILES_MAX, SECTOR_SIZE)
#define SECTOR_SIZE 512
#define VIRTQ_ENTRY_NUM 16
diff --git a/run_on_ubuntu.sh b/run_on_ubuntu.sh
new file mode 100644
index 0000000..31e3ce1
--- /dev/null
+++ b/run_on_ubuntu.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+set -xue
+
+QEMU=qemu-system-riscv32
+CC=/usr/bin/clang
+OBJCOPY=/usr/bin/llvm-objcopy-18
+
+CFLAGS="-std=c11 -O2 -g3 -Wall -Wextra --target=riscv32-unknown-elf -fuse-ld=lld -fno-stack-protector -ffreestanding -nostdlib"
+
+# Build the shell.
+$CC $CFLAGS -Wl,-Tuser.ld -Wl,-Map=shell.map -o shell.elf shell.c user.c common.c
+$OBJCOPY --set-section-flags .bss=alloc,contents -O binary shell.elf shell.bin
+$OBJCOPY -Ibinary -Oelf32-littleriscv shell.bin shell.bin.o
+
+# Build the kernel.
+$CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \
+ kernel.c common.c shell.bin.o
+
+(cd disk && tar cf ../disk.tar --format=ustar *.txt)
+
+$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \
+ -d unimp,guest_errors,int,cpu_reset -D qemu.log \
+ -drive id=drive0,file=disk.tar,format=raw,if=none \
+ -device virtio-blk-device,drive=drive0,bus=virtio-mmio-bus.0 \
+ -kernel kernel.elf
diff --git a/shell.c b/shell.c
index 0bff8e2..d13c8e9 100644
--- a/shell.c
+++ b/shell.c
@@ -2,7 +2,7 @@
void main(void) {
while (1) {
-prompt:
+ prompt:
printf("> ");
char cmdline[128];
for (int i = 0;; i++) {
@@ -11,7 +11,7 @@ void main(void) {
if (i == sizeof(cmdline) - 1) {
printf("command line too long\n");
goto prompt;
- } else if (ch == '\r') {
+ } else if (ch == '\r' || ch == '\n') { // ENTER tuşunu hem \r hem \n olarak kontrol et
printf("\n");
cmdline[i] = '\0';
break;
@@ -20,19 +20,48 @@ void main(void) {
}
}
- if (strcmp(cmdline, "hello") == 0)
+ if (strcmp(cmdline, "hello") == 0) {
printf("Hello world from shell!\n");
- else if (strcmp(cmdline, "exit") == 0)
+ } else if (strcmp(cmdline, "exit") == 0) {
exit();
- else if (strcmp(cmdline, "readfile") == 0) {
- char buf[128];
- int len = readfile("hello.txt", buf, sizeof(buf));
- buf[len] = '\0';
- printf("%s\n", buf);
}
- else if (strcmp(cmdline, "writefile") == 0)
- writefile("hello.txt", "Hello from shell!\n", 19);
- else
+ else if (strcmp(cmdline, "ls") == 0) {
+ ls();
+ }
+ else if (strncmp(cmdline, "readf ", 6) == 0) {
+ char *filename = cmdline + 6;
+ int ret = readf(filename);
+ if (ret < 0)
+ printf("file not found: %s\n", filename);
+ } else if (strncmp(cmdline, "addf ", 5) == 0) {
+ char *filename = cmdline + 5;
+ int ret = addf(filename);
+ if (ret == 0)
+ printf("file \"%s\" added successfully!\n", filename);
+ else
+ printf("failed to add file \"%s\"\n", filename);
+ } else if (strncmp(cmdline, "writef ", 7) == 0) {
+ char *filename = cmdline + 7;
+ char buf[128];
+ printf("Enter content (end with ENTER): ");
+ int i = 0;
+ for (;;) {
+ char ch = getchar();
+ if (ch == '\r' || ch == '\n' || i == sizeof(buf) - 1) {
+ buf[i] = '\0';
+ break;
+ }
+ putchar(ch);
+ buf[i++] = ch;
+ }
+ int ret = writef(filename, buf, i);
+ if (ret >= 0)
+ printf("written %d bytes to %s\n", ret, filename);
+ else
+ printf("failed to write to %s\n", filename);
+ } else {
printf("unknown command: %s\n", cmdline);
+ }
}
}
+
diff --git a/user.c b/user.c
index c0854fa..cff4192 100644
--- a/user.c
+++ b/user.c
@@ -15,6 +15,9 @@ int syscall(int sysno, int arg0, int arg1, int arg2) {
return a0;
}
+int ls(void) {
+ return syscall(SYS_LS, 0, 0, 0);
+}
void putchar(char ch) {
syscall(SYS_PUTCHAR, ch, 0, 0);
@@ -32,11 +35,27 @@ int writefile(const char *filename, const char *buf, int len) {
return syscall(SYS_WRITEFILE, (int) filename, (int) buf, len);
}
+int addfile(const char *filename) {
+ return syscall(SYS_ADDFILE, (int) filename, 0, 0);
+}
+int readf(const char *filename) {
+ return syscall(SYS_READF, (int)filename, 0, 0);
+}
+
+int addf(const char *filename) {
+ return syscall(SYS_ADDF, (int)filename, 0, 0);
+}
+
+int writef(const char *filename, const char *buf, int len) {
+ return syscall(SYS_WRITEF, (int)filename, (int)buf, len);
+}
+
+
__attribute__((noreturn)) void exit(void) {
syscall(SYS_EXIT, 0, 0, 0);
for (;;);
}
-
+
__attribute__((section(".text.start")))
__attribute__((naked))
void start(void) {
diff --git a/user.h b/user.h
index 8c0c859..a0728be 100644
--- a/user.h
+++ b/user.h
@@ -11,4 +11,10 @@ void putchar(char ch);
int getchar(void);
int readfile(const char *filename, char *buf, int len);
int writefile(const char *filename, const char *buf, int len);
+int addfile(const char *filename);
+int readf(const char *filename);
+int addf(const char *filename);
+int writef(const char *filename, const char *buf, int len);
+int ls(void);
+
__attribute__((noreturn)) void exit(void);