mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
Disk improvements
This commit is contained in:
parent
8bd70faa89
commit
5cf552fd14
12 changed files with 558 additions and 126 deletions
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
BIN
build/fat32.o
BIN
build/fat32.o
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
BIN
disk.img
BIN
disk.img
Binary file not shown.
|
|
@ -309,7 +309,7 @@ static int ramfs_read(FAT32_FileHandle *handle, void *buffer, int size) {
|
|||
int to_read = size - bytes_read;
|
||||
int available = handle->size - handle->position;
|
||||
if (to_read > available) to_read = available;
|
||||
if (to_read > FAT32_CLUSTER_SIZE - offset_in_cluster) to_read = FAT32_CLUSTER_SIZE - offset_in_cluster;
|
||||
if (to_read > (int)(FAT32_CLUSTER_SIZE - offset_in_cluster)) to_read = FAT32_CLUSTER_SIZE - offset_in_cluster;
|
||||
|
||||
if (handle->cluster >= MAX_CLUSTERS) break;
|
||||
|
||||
|
|
@ -342,7 +342,7 @@ static int ramfs_write(FAT32_FileHandle *handle, const void *buffer, int size) {
|
|||
while (bytes_written < size) {
|
||||
uint32_t offset_in_cluster = handle->position % FAT32_CLUSTER_SIZE;
|
||||
int to_write = size - bytes_written;
|
||||
if (to_write > FAT32_CLUSTER_SIZE - offset_in_cluster) to_write = FAT32_CLUSTER_SIZE - offset_in_cluster;
|
||||
if (to_write > (int)(FAT32_CLUSTER_SIZE - offset_in_cluster)) to_write = FAT32_CLUSTER_SIZE - offset_in_cluster;
|
||||
|
||||
if (handle->cluster >= MAX_CLUSTERS) break;
|
||||
|
||||
|
|
@ -514,13 +514,7 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
|
|||
const char *p = path;
|
||||
if (*p == '/') p++;
|
||||
|
||||
fs_serial_str("[FAT32] realfs_open drive=");
|
||||
fs_serial_char(drive);
|
||||
fs_serial_str(" path='");
|
||||
fs_serial_str(path);
|
||||
fs_serial_str("' mode=");
|
||||
fs_serial_char(mode[0]);
|
||||
fs_serial_str("\n");
|
||||
|
||||
|
||||
if (*p == 0) {
|
||||
// Root dir
|
||||
|
|
@ -559,6 +553,7 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
|
|||
found = false;
|
||||
uint32_t search_cluster = current_cluster;
|
||||
uint8_t *cluster_buf = (uint8_t*)kmalloc(vol->sectors_per_cluster * 512);
|
||||
if (!cluster_buf) return NULL;
|
||||
|
||||
while (search_cluster < 0x0FFFFFF8) {
|
||||
if (realfs_read_cluster(vol, search_cluster, cluster_buf) != 0) break;
|
||||
|
|
@ -594,13 +589,6 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
|
|||
|
||||
if (match) {
|
||||
uint32_t cluster = (entry[e].start_cluster_high << 16) | entry[e].start_cluster_low;
|
||||
fs_serial_str("[FAT32] MATCH '");
|
||||
fs_serial_str(name);
|
||||
fs_serial_str("' cluster=");
|
||||
fs_serial_num(cluster);
|
||||
fs_serial_str(" size=");
|
||||
fs_serial_num(entry[e].file_size);
|
||||
fs_serial_str("\n");
|
||||
|
||||
uint32_t lba = vol->cluster_begin_lba + (search_cluster - 2) * vol->sectors_per_cluster;
|
||||
int sect_in_cluster = (e * 32) / 512;
|
||||
|
|
@ -644,52 +632,53 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
|
|||
int count = (vol->sectors_per_cluster * 512) / 32;
|
||||
|
||||
for (int e = 0; e < count; e++) {
|
||||
if (entries[e].filename[0] == 0 || entries[e].filename[0] == 0xE5) {
|
||||
uint32_t lba = vol->cluster_begin_lba + (search_cluster - 2) * vol->sectors_per_cluster;
|
||||
int sect_in_cluster = (e * 32) / 512;
|
||||
free_sector = lba + sect_in_cluster;
|
||||
free_offset = (e * 32) % 512;
|
||||
found_free = true;
|
||||
break;
|
||||
}
|
||||
if (entries[e].filename[0] == 0 || entries[e].filename[0] == 0xE5) {
|
||||
uint32_t lba = vol->cluster_begin_lba + (search_cluster - 2) * vol->sectors_per_cluster;
|
||||
int sect_in_cluster = (e * 32) / 512;
|
||||
free_sector = lba + sect_in_cluster;
|
||||
free_offset = (e * 32) % 512;
|
||||
found_free = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_free) search_cluster = realfs_next_cluster(vol, search_cluster);
|
||||
}
|
||||
|
||||
if (found_free) {
|
||||
uint8_t *sect_buf = (uint8_t*)kmalloc(512);
|
||||
vol->disk->read_sector(vol->disk, free_sector, sect_buf);
|
||||
FAT32_DirEntry *d = (FAT32_DirEntry*)(sect_buf + free_offset);
|
||||
|
||||
for(int k=0; k<8; k++) d->filename[k] = dos_name[k];
|
||||
for(int k=0; k<3; k++) d->extension[k] = dos_name[8+k];
|
||||
d->attributes = ATTR_ARCHIVE;
|
||||
d->start_cluster_high = 0;
|
||||
d->start_cluster_low = 0;
|
||||
d->file_size = 0;
|
||||
|
||||
// Write to disk
|
||||
if (vol->disk->write_sector(vol->disk, free_sector, sect_buf) != 0) {
|
||||
// Write failed, free the buffer and return NULL
|
||||
if (sect_buf) {
|
||||
vol->disk->read_sector(vol->disk, free_sector, sect_buf);
|
||||
FAT32_DirEntry *d = (FAT32_DirEntry*)(sect_buf + free_offset);
|
||||
|
||||
for(int k=0; k<8; k++) d->filename[k] = dos_name[k];
|
||||
for(int k=0; k<3; k++) d->extension[k] = dos_name[8+k];
|
||||
d->attributes = ATTR_ARCHIVE;
|
||||
d->start_cluster_high = 0;
|
||||
d->start_cluster_low = 0;
|
||||
d->file_size = 0;
|
||||
|
||||
// Write to disk
|
||||
if (vol->disk->write_sector(vol->disk, free_sector, sect_buf) != 0) {
|
||||
kfree(sect_buf);
|
||||
kfree(cluster_buf);
|
||||
return NULL;
|
||||
}
|
||||
kfree(sect_buf);
|
||||
kfree(cluster_buf);
|
||||
return NULL;
|
||||
}
|
||||
kfree(sect_buf);
|
||||
|
||||
FAT32_FileHandle *fh = ramfs_find_free_handle();
|
||||
if (fh) {
|
||||
fh->valid = true;
|
||||
fh->drive = drive;
|
||||
fh->start_cluster = 0;
|
||||
fh->cluster = 0;
|
||||
fh->position = 0;
|
||||
fh->size = 0;
|
||||
fh->mode = 1; // Write
|
||||
fh->dir_sector = free_sector;
|
||||
fh->dir_offset = free_offset;
|
||||
kfree(cluster_buf);
|
||||
return fh;
|
||||
|
||||
FAT32_FileHandle *fh = ramfs_find_free_handle();
|
||||
if (fh) {
|
||||
fh->valid = true;
|
||||
fh->drive = drive;
|
||||
fh->start_cluster = 0;
|
||||
fh->cluster = 0;
|
||||
fh->position = 0;
|
||||
fh->size = 0;
|
||||
fh->mode = (mode[0] == 'a' ? 2 : 1);
|
||||
fh->dir_sector = free_sector;
|
||||
fh->dir_offset = free_offset;
|
||||
kfree(cluster_buf);
|
||||
return fh;
|
||||
}
|
||||
}
|
||||
}
|
||||
kfree(cluster_buf);
|
||||
|
|
@ -710,9 +699,22 @@ static FAT32_FileHandle* realfs_open(char drive, const char *path, const char *m
|
|||
fh->cluster = current_cluster;
|
||||
fh->position = 0;
|
||||
fh->size = file_size;
|
||||
fh->mode = (mode[0] == 'w' ? 1 : 0); // Only R/W supported
|
||||
fh->mode = (mode[0] == 'w' ? 1 : (mode[0] == 'a' ? 2 : 0));
|
||||
fh->dir_sector = entry_sector;
|
||||
fh->dir_offset = entry_offset;
|
||||
|
||||
if (mode[0] == 'a') {
|
||||
fh->position = fh->size;
|
||||
// Seek to EOF cluster
|
||||
uint32_t cluster_size = vol->sectors_per_cluster * 512;
|
||||
uint32_t pos = 0;
|
||||
while (pos + cluster_size <= fh->position) {
|
||||
uint32_t next = realfs_next_cluster(vol, fh->cluster);
|
||||
if (next >= 0x0FFFFFF8) break;
|
||||
fh->cluster = next;
|
||||
pos += cluster_size;
|
||||
}
|
||||
}
|
||||
return fh;
|
||||
}
|
||||
|
||||
|
|
@ -736,7 +738,7 @@ static int realfs_read(FAT32_FileHandle *handle, void *buffer, int size) {
|
|||
uint32_t offset = handle->position % cluster_size;
|
||||
int to_copy = size - bytes_read;
|
||||
int available = cluster_size - offset;
|
||||
if (handle->size - handle->position < available) available = handle->size - handle->position;
|
||||
if ((int)(handle->size - handle->position) < available) available = handle->size - handle->position;
|
||||
if (to_copy > available) to_copy = available;
|
||||
|
||||
for (int i = 0; i < to_copy; i++) {
|
||||
|
|
@ -808,22 +810,25 @@ static int realfs_write(FAT32_FileHandle *handle, const void *buffer, int size)
|
|||
handle->start_cluster = new_cluster;
|
||||
handle->cluster = new_cluster;
|
||||
|
||||
// Mark new cluster as EOF in FAT
|
||||
// Mark new cluster as EOF in FAT, preserve high bits
|
||||
uint32_t fat_sector = vol->fat_begin_lba + (new_cluster * 4) / 512;
|
||||
uint32_t fat_offset = (new_cluster * 4) % 512;
|
||||
uint8_t *fat_buf = (uint8_t*)kmalloc(512);
|
||||
if (vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
*(uint32_t*)&fat_buf[fat_offset] = 0x0FFFFFF8; // EOF marker
|
||||
if (fat_buf && vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
uint32_t old_val = *(uint32_t*)&fat_buf[fat_offset];
|
||||
*(uint32_t*)&fat_buf[fat_offset] = (old_val & 0xF0000000) | 0x0FFFFFF8; // EOF
|
||||
vol->disk->write_sector(vol->disk, fat_sector, fat_buf);
|
||||
}
|
||||
kfree(fat_buf);
|
||||
if (fat_buf) kfree(fat_buf);
|
||||
|
||||
// Initialize the new cluster with zeros to avoid garbage
|
||||
uint32_t cluster_size_bytes = vol->sectors_per_cluster * 512;
|
||||
uint8_t *cbuf = (uint8_t*)kmalloc(cluster_size_bytes);
|
||||
for(uint32_t i=0; i<cluster_size_bytes; i++) cbuf[i] = 0;
|
||||
realfs_write_cluster(vol, new_cluster, cbuf);
|
||||
kfree(cbuf);
|
||||
if (cbuf) {
|
||||
for(uint32_t i=0; i<cluster_size_bytes; i++) cbuf[i] = 0;
|
||||
realfs_write_cluster(vol, new_cluster, cbuf);
|
||||
kfree(cbuf);
|
||||
}
|
||||
|
||||
// Update directory entry immediately with the allocated cluster and initial size
|
||||
if (handle->dir_sector != 0 && handle->dir_offset != 0xFFFFFFFF && handle->dir_offset < 512) {
|
||||
|
|
@ -875,36 +880,41 @@ static int realfs_write(FAT32_FileHandle *handle, const void *buffer, int size)
|
|||
|
||||
if (handle->position % cluster_size == 0 && bytes_written < size) {
|
||||
uint32_t next = realfs_next_cluster(vol, handle->cluster);
|
||||
if (next >= 0x0FFFFFF8) {
|
||||
// If next is 0 (unallocated) or EOC, we must allocate a new cluster
|
||||
if (next < 2 || next >= 0x0FFFFFF8) {
|
||||
uint32_t new_cluster = realfs_allocate_cluster(vol);
|
||||
if (new_cluster == 0) break;
|
||||
|
||||
// Link current cluster to new cluster in FAT
|
||||
// Link current cluster to new cluster in FAT, preserve high bits
|
||||
uint32_t fat_sector = vol->fat_begin_lba + (handle->cluster * 4) / 512;
|
||||
uint32_t fat_offset = (handle->cluster * 4) % 512;
|
||||
|
||||
uint8_t *fat_buf = (uint8_t*)kmalloc(512);
|
||||
if (vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
*(uint32_t*)&fat_buf[fat_offset] = new_cluster;
|
||||
if (fat_buf && vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
uint32_t old_val = *(uint32_t*)&fat_buf[fat_offset];
|
||||
*(uint32_t*)&fat_buf[fat_offset] = (old_val & 0xF0000000) | (new_cluster & 0x0FFFFFFF);
|
||||
vol->disk->write_sector(vol->disk, fat_sector, fat_buf);
|
||||
}
|
||||
kfree(fat_buf);
|
||||
if (fat_buf) kfree(fat_buf);
|
||||
|
||||
// Mark new cluster as EOF in FAT
|
||||
// Mark new cluster as EOF in FAT, preserve high bits
|
||||
fat_sector = vol->fat_begin_lba + (new_cluster * 4) / 512;
|
||||
fat_offset = (new_cluster * 4) % 512;
|
||||
fat_buf = (uint8_t*)kmalloc(512);
|
||||
if (vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
*(uint32_t*)&fat_buf[fat_offset] = 0x0FFFFFF8; // EOF marker
|
||||
if (fat_buf && vol->disk->read_sector(vol->disk, fat_sector, fat_buf) == 0) {
|
||||
uint32_t old_val = *(uint32_t*)&fat_buf[fat_offset];
|
||||
*(uint32_t*)&fat_buf[fat_offset] = (old_val & 0xF0000000) | 0x0FFFFFF8; // EOF
|
||||
vol->disk->write_sector(vol->disk, fat_sector, fat_buf);
|
||||
}
|
||||
kfree(fat_buf);
|
||||
if (fat_buf) kfree(fat_buf);
|
||||
|
||||
// Init new cluster
|
||||
uint8_t *cbuf = (uint8_t*)kmalloc(cluster_size);
|
||||
for(uint32_t i=0; i<cluster_size; i++) cbuf[i] = 0;
|
||||
realfs_write_cluster(vol, new_cluster, cbuf);
|
||||
kfree(cbuf);
|
||||
if (cbuf) {
|
||||
for(uint32_t k=0; k<cluster_size; k++) cbuf[k] = 0;
|
||||
realfs_write_cluster(vol, new_cluster, cbuf);
|
||||
kfree(cbuf);
|
||||
}
|
||||
|
||||
next = new_cluster;
|
||||
}
|
||||
|
|
@ -1339,13 +1349,151 @@ int fat32_seek(FAT32_FileHandle *handle, int offset, int whence) {
|
|||
return new_position;
|
||||
}
|
||||
|
||||
static bool realfs_mkdir(char drive, const char *path) {
|
||||
int vol_idx = drive - 'A';
|
||||
if (!volumes[vol_idx].mounted) {
|
||||
if (!realfs_mount(drive)) return false;
|
||||
}
|
||||
FAT32_Volume *vol = &volumes[vol_idx];
|
||||
|
||||
// Find parent directory and name of new directory
|
||||
char parent_path[FAT32_MAX_PATH];
|
||||
char dirname[FAT32_MAX_FILENAME];
|
||||
extract_parent_path(path, parent_path);
|
||||
extract_filename(path, dirname);
|
||||
|
||||
// Open parent directory
|
||||
FAT32_FileHandle *parent_fh = realfs_open(drive, parent_path, "r");
|
||||
if (!parent_fh) return false;
|
||||
uint32_t parent_cluster = parent_fh->start_cluster;
|
||||
fat32_close(parent_fh);
|
||||
|
||||
// Check if it already exists
|
||||
FAT32_FileHandle *check_fh = realfs_open(drive, path, "r");
|
||||
if (check_fh) {
|
||||
fat32_close(check_fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate cluster for new directory
|
||||
uint32_t new_cluster = realfs_allocate_cluster(vol);
|
||||
if (new_cluster == 0) return false;
|
||||
|
||||
// Initialize new directory cluster with . and .. entries
|
||||
uint32_t cluster_size = vol->sectors_per_cluster * 512;
|
||||
uint8_t *cluster_buf = (uint8_t*)kmalloc(cluster_size);
|
||||
if (!cluster_buf) return false;
|
||||
for (uint32_t i = 0; i < cluster_size; i++) cluster_buf[i] = 0;
|
||||
|
||||
FAT32_DirEntry *dot = (FAT32_DirEntry*)cluster_buf;
|
||||
FAT32_DirEntry *dotdot = (FAT32_DirEntry*)(cluster_buf + 32);
|
||||
|
||||
// . entry
|
||||
for (int i = 0; i < 8; i++) dot->filename[i] = ' ';
|
||||
for (int i = 0; i < 3; i++) dot->extension[i] = ' ';
|
||||
dot->filename[0] = '.';
|
||||
dot->attributes = ATTR_DIRECTORY;
|
||||
dot->start_cluster_high = (new_cluster >> 16);
|
||||
dot->start_cluster_low = (new_cluster & 0xFFFF);
|
||||
|
||||
// .. entry
|
||||
for (int i = 0; i < 8; i++) dotdot->filename[i] = ' ';
|
||||
for (int i = 0; i < 3; i++) dotdot->extension[i] = ' ';
|
||||
dotdot->filename[0] = '.'; dotdot->filename[1] = '.';
|
||||
dotdot->attributes = ATTR_DIRECTORY;
|
||||
dotdot->start_cluster_high = (parent_cluster >> 16);
|
||||
dotdot->start_cluster_low = (parent_cluster & 0xFFFF);
|
||||
|
||||
if (realfs_write_cluster(vol, new_cluster, cluster_buf) != 0) {
|
||||
kfree(cluster_buf);
|
||||
return false;
|
||||
}
|
||||
kfree(cluster_buf);
|
||||
|
||||
// Find free entry in parent directory
|
||||
uint32_t search_cluster = parent_cluster;
|
||||
uint8_t *sect_buf = (uint8_t*)kmalloc(512);
|
||||
bool found_free = false;
|
||||
uint32_t free_sector = 0;
|
||||
uint32_t free_offset = 0;
|
||||
|
||||
uint8_t *dir_cluster_buf = (uint8_t*)kmalloc(cluster_size);
|
||||
if (!dir_cluster_buf) {
|
||||
kfree(sect_buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (search_cluster < 0x0FFFFFF8 && !found_free) {
|
||||
if (realfs_read_cluster(vol, search_cluster, dir_cluster_buf) != 0) break;
|
||||
FAT32_DirEntry *entries = (FAT32_DirEntry*)dir_cluster_buf;
|
||||
int count = cluster_size / 32;
|
||||
for (int e = 0; e < count; e++) {
|
||||
if (entries[e].filename[0] == 0 || entries[e].filename[0] == 0xE5) {
|
||||
uint32_t lba = vol->cluster_begin_lba + (search_cluster - 2) * vol->sectors_per_cluster;
|
||||
free_sector = lba + (e * 32) / 512;
|
||||
free_offset = (e * 32) % 512;
|
||||
found_free = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_free) {
|
||||
uint32_t next = realfs_next_cluster(vol, search_cluster);
|
||||
if (next >= 0x0FFFFFF8) {
|
||||
// Need to expand directory?
|
||||
uint32_t expanded = realfs_allocate_cluster(vol);
|
||||
if (expanded == 0) break;
|
||||
// Link, preserve high bits
|
||||
uint32_t fat_sector = vol->fat_begin_lba + (search_cluster * 4) / 512;
|
||||
uint32_t fat_offset = (search_cluster * 4) % 512;
|
||||
if (vol->disk->read_sector(vol->disk, fat_sector, sect_buf) == 0) {
|
||||
uint32_t old_val = *(uint32_t*)§_buf[fat_offset];
|
||||
*(uint32_t*)§_buf[fat_offset] = (old_val & 0xF0000000) | (expanded & 0x0FFFFFFF);
|
||||
vol->disk->write_sector(vol->disk, fat_sector, sect_buf);
|
||||
}
|
||||
// Zero out new cluster
|
||||
for(uint32_t k=0; k<cluster_size; k++) dir_cluster_buf[k] = 0;
|
||||
realfs_write_cluster(vol, expanded, dir_cluster_buf);
|
||||
next = expanded;
|
||||
}
|
||||
search_cluster = next;
|
||||
}
|
||||
}
|
||||
kfree(dir_cluster_buf);
|
||||
|
||||
if (found_free) {
|
||||
vol->disk->read_sector(vol->disk, free_sector, sect_buf);
|
||||
FAT32_DirEntry *d = (FAT32_DirEntry*)(sect_buf + free_offset);
|
||||
char dos_name[11];
|
||||
to_dos_filename(dirname, dos_name);
|
||||
for (int k = 0; k < 8; k++) d->filename[k] = dos_name[k];
|
||||
for (int k = 0; k < 3; k++) d->extension[k] = dos_name[8+k];
|
||||
d->attributes = ATTR_DIRECTORY;
|
||||
d->start_cluster_high = (new_cluster >> 16);
|
||||
d->start_cluster_low = (new_cluster & 0xFFFF);
|
||||
d->file_size = 0;
|
||||
vol->disk->write_sector(vol->disk, free_sector, sect_buf);
|
||||
}
|
||||
|
||||
kfree(sect_buf);
|
||||
return found_free;
|
||||
}
|
||||
|
||||
bool fat32_mkdir(const char *path) {
|
||||
if (parse_drive_from_path(&path) != 'A') return false; // RAMFS only for now
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
|
||||
if (drive != 'A') {
|
||||
bool res = realfs_mkdir(drive, p);
|
||||
wm_notify_fs_change();
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
return res;
|
||||
}
|
||||
|
||||
char normalized[FAT32_MAX_PATH];
|
||||
fat32_normalize_path(path, normalized);
|
||||
fat32_normalize_path(p, normalized);
|
||||
|
||||
if (ramfs_find_file(normalized)) {
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
|
|
@ -1428,6 +1576,48 @@ bool fat32_delete(const char *path) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int fat32_get_info(const char *path, FAT32_FileInfo *info) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
|
||||
const char *p = path;
|
||||
char drive = parse_drive_from_path(&p);
|
||||
|
||||
int result = -1;
|
||||
if (drive == 'A') {
|
||||
char normalized[FAT32_MAX_PATH];
|
||||
fat32_normalize_path(p, normalized);
|
||||
FileEntry *entry = ramfs_find_file(normalized);
|
||||
if (entry) {
|
||||
fs_strcpy(info->name, entry->filename);
|
||||
info->size = entry->size;
|
||||
info->is_directory = (entry->attributes & ATTR_DIRECTORY) != 0;
|
||||
info->start_cluster = entry->start_cluster;
|
||||
result = 0;
|
||||
}
|
||||
} else {
|
||||
FAT32_FileHandle *fh = realfs_open(drive, p, "r");
|
||||
if (fh) {
|
||||
|
||||
extract_filename(p, info->name);
|
||||
info->size = fh->size;
|
||||
info->start_cluster = fh->start_cluster;
|
||||
|
||||
if (fs_strcmp(p, "/") == 0 || fs_strcmp(p, "") == 0) {
|
||||
info->is_directory = 1;
|
||||
} else {
|
||||
|
||||
info->is_directory = fat32_is_directory(path);
|
||||
}
|
||||
fat32_close(fh);
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool fat32_exists(const char *path) {
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
|
|
@ -1539,10 +1729,7 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
|
|||
char normalized[FAT32_MAX_PATH];
|
||||
fat32_normalize_path(p, normalized);
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
serial_write("[DEBUG] fat32_list_directory (RAMFS) path: ");
|
||||
serial_write(normalized);
|
||||
serial_write("\n");
|
||||
|
||||
|
||||
for (int i = 0; i < MAX_FILES && count < max_entries; i++) {
|
||||
if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) {
|
||||
|
|
@ -1553,10 +1740,6 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
|
|||
count++;
|
||||
}
|
||||
}
|
||||
serial_write("[DEBUG] fat32_list_directory (RAMFS) found count: ");
|
||||
extern void serial_write_num(uint32_t n);
|
||||
serial_write_num(count);
|
||||
serial_write("\n");
|
||||
} else {
|
||||
count = realfs_list_directory(drive, p, entries, max_entries);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,6 +468,12 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6
|
|||
const char *path = (const char *)arg2;
|
||||
if (!path) return -1;
|
||||
return fat32_delete(path) ? 0 : -1;
|
||||
} else if (cmd == FS_CMD_GET_INFO) {
|
||||
const char *path = (const char *)arg2;
|
||||
FAT32_FileInfo *info = (FAT32_FileInfo *)arg3;
|
||||
if (!path || !info) return -1;
|
||||
extern int fat32_get_info(const char *path, FAT32_FileInfo *info);
|
||||
return (uint64_t)fat32_get_info(path, info);
|
||||
} else if (cmd == FS_CMD_MKDIR) {
|
||||
const char *path = (const char *)arg2;
|
||||
if (!path) return -1;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ typedef struct registers_t registers_t;
|
|||
#define FS_CMD_EXISTS 11
|
||||
#define FS_CMD_GETCWD 12
|
||||
#define FS_CMD_CHDIR 13
|
||||
#define FS_CMD_GET_INFO 14
|
||||
|
||||
void syscall_init(void);
|
||||
uint64_t syscall_handler_c(registers_t *regs);
|
||||
|
|
|
|||
|
|
@ -4,33 +4,163 @@
|
|||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: cp <source> <dest>\n");
|
||||
return 1;
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
void combine_path(char *dest, const char *path1, const char *path2) {
|
||||
int i = 0;
|
||||
while (path1[i]) {
|
||||
dest[i] = path1[i];
|
||||
i++;
|
||||
}
|
||||
if (i > 0 && dest[i-1] != '/') {
|
||||
dest[i++] = '/';
|
||||
}
|
||||
int j = 0;
|
||||
while (path2[j]) {
|
||||
dest[i++] = path2[j++];
|
||||
}
|
||||
dest[i] = 0;
|
||||
}
|
||||
|
||||
const char* get_basename(const char *path) {
|
||||
const char *last_slash = NULL;
|
||||
int len = 0;
|
||||
while (path[len]) {
|
||||
if (path[len] == '/') last_slash = path + len;
|
||||
len++;
|
||||
}
|
||||
|
||||
int fd_in = sys_open(argv[1], "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", argv[1]);
|
||||
return 1;
|
||||
if (!last_slash) return path;
|
||||
|
||||
// If it ends with a slash, skip it and find the previous one
|
||||
if (last_slash[1] == '\0') {
|
||||
if (len <= 1) return path; // root "/"
|
||||
int i = len - 2;
|
||||
while (i >= 0 && path[i] != '/') i--;
|
||||
if (i < 0) return path;
|
||||
return path + i + 1;
|
||||
}
|
||||
|
||||
int fd_out = sys_open(argv[2], "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", argv[2]);
|
||||
return last_slash + 1;
|
||||
}
|
||||
|
||||
void copy_recursive(const char *src, const char *dst) {
|
||||
FAT32_FileInfo info;
|
||||
if (sys_get_file_info(src, &info) < 0) {
|
||||
printf("Error: Cannot get info for %s\n", src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.is_directory) {
|
||||
if (sys_mkdir(dst) < 0) {
|
||||
// Might already exist
|
||||
}
|
||||
|
||||
FAT32_FileInfo entries[64];
|
||||
int count = sys_list(src, entries, 64);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (strcmp(entries[i].name, ".") == 0 || strcmp(entries[i].name, "..") == 0) continue;
|
||||
|
||||
char sub_src[512], sub_dst[512];
|
||||
combine_path(sub_src, src, entries[i].name);
|
||||
combine_path(sub_dst, dst, entries[i].name);
|
||||
copy_recursive(sub_src, sub_dst);
|
||||
}
|
||||
} else {
|
||||
int fd_in = sys_open(src, "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", src);
|
||||
return;
|
||||
}
|
||||
int fd_out = sys_open(dst, "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", dst);
|
||||
sys_close(fd_in);
|
||||
return;
|
||||
}
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
bool recursive = false;
|
||||
char *src_path = NULL;
|
||||
char *dst_path = NULL;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-r") == 0) {
|
||||
recursive = true;
|
||||
} else if (!src_path) {
|
||||
src_path = argv[i];
|
||||
} else if (!dst_path) {
|
||||
dst_path = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!src_path || !dst_path) {
|
||||
printf("Usage: cp [-r] <source> <dest>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
FAT32_FileInfo info_src;
|
||||
if (sys_get_file_info(src_path, &info_src) < 0) {
|
||||
printf("Error: Source %s does not exist\n", src_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info_src.is_directory && !recursive) {
|
||||
printf("Error: %s is a directory (use -r to copy recursively)\n", src_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char actual_dst[512];
|
||||
FAT32_FileInfo info_dst;
|
||||
if (sys_get_file_info(dst_path, &info_dst) == 0 && info_dst.is_directory) {
|
||||
// If destination is a directory, copy INTO it
|
||||
const char *base = get_basename(src_path);
|
||||
// Clean up trailing slash from basename if any (get_basename handles it mostly)
|
||||
char clean_base[256];
|
||||
int k = 0;
|
||||
while (base[k] && base[k] != '/') {
|
||||
clean_base[k] = base[k];
|
||||
k++;
|
||||
}
|
||||
clean_base[k] = 0;
|
||||
combine_path(actual_dst, dst_path, clean_base);
|
||||
} else {
|
||||
strcpy(actual_dst, dst_path);
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
copy_recursive(src_path, actual_dst);
|
||||
} else {
|
||||
int fd_in = sys_open(src_path, "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", src_path);
|
||||
return 1;
|
||||
}
|
||||
int fd_out = sys_open(actual_dst, "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", actual_dst);
|
||||
sys_close(fd_in);
|
||||
return 1;
|
||||
}
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
}
|
||||
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,10 @@ int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries) {
|
|||
return (int)syscall4(SYS_FS, FS_CMD_LIST, (uint64_t)path, (uint64_t)entries, (uint64_t)max_entries);
|
||||
}
|
||||
|
||||
int sys_get_file_info(const char *path, FAT32_FileInfo *info) {
|
||||
return (int)syscall3(SYS_FS, FS_CMD_GET_INFO, (uint64_t)path, (uint64_t)info);
|
||||
}
|
||||
|
||||
int sys_delete(const char *path) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_DELETE, (uint64_t)path);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#define FS_CMD_EXISTS 11
|
||||
#define FS_CMD_GETCWD 12
|
||||
#define FS_CMD_CHDIR 13
|
||||
#define FS_CMD_GET_INFO 14
|
||||
|
||||
// System Commands (via SYS_SYSTEM)
|
||||
#define SYSTEM_CMD_SET_BG_COLOR 1
|
||||
|
|
@ -100,6 +101,7 @@ typedef struct {
|
|||
} FAT32_FileInfo;
|
||||
|
||||
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries);
|
||||
int sys_get_file_info(const char *path, FAT32_FileInfo *info);
|
||||
|
||||
// Network API
|
||||
typedef struct { uint8_t bytes[6]; } net_mac_address_t;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,24 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
FAT32_FileInfo info;
|
||||
if (sys_get_file_info(path, &info) < 0) {
|
||||
sys_set_text_color(error_color);
|
||||
printf("Error: Path '%s' does not exist\n", path);
|
||||
sys_set_text_color(default_color);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!info.is_directory) {
|
||||
sys_set_text_color(file_color);
|
||||
printf("[FILE] %s", info.name);
|
||||
sys_set_text_color(size_color);
|
||||
printf(" (%d bytes)\n", info.size);
|
||||
sys_set_text_color(default_color);
|
||||
printf("\nTotal: 1 items\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
FAT32_FileInfo entries[128];
|
||||
int count = sys_list(path, entries, 128);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,37 +4,125 @@
|
|||
#include <stdlib.h>
|
||||
#include <syscall.h>
|
||||
|
||||
void combine_path(char *dest, const char *path1, const char *path2) {
|
||||
int i = 0;
|
||||
while (path1[i]) {
|
||||
dest[i] = path1[i];
|
||||
i++;
|
||||
}
|
||||
if (i > 0 && dest[i-1] != '/') {
|
||||
dest[i++] = '/';
|
||||
}
|
||||
int j = 0;
|
||||
while (path2[j]) {
|
||||
dest[i++] = path2[j++];
|
||||
}
|
||||
dest[i] = 0;
|
||||
}
|
||||
|
||||
const char* get_basename(const char *path) {
|
||||
const char *last_slash = NULL;
|
||||
int len = 0;
|
||||
while (path[len]) {
|
||||
if (path[len] == '/') last_slash = path + len;
|
||||
len++;
|
||||
}
|
||||
|
||||
if (!last_slash) return path;
|
||||
|
||||
if (last_slash[1] == '\0') {
|
||||
if (len <= 1) return path;
|
||||
int i = len - 2;
|
||||
while (i >= 0 && path[i] != '/') i--;
|
||||
if (i < 0) return path;
|
||||
return path + i + 1;
|
||||
}
|
||||
|
||||
return last_slash + 1;
|
||||
}
|
||||
|
||||
void copy_recursive(const char *src, const char *dst) {
|
||||
FAT32_FileInfo info;
|
||||
if (sys_get_file_info(src, &info) < 0) return;
|
||||
|
||||
if (info.is_directory) {
|
||||
sys_mkdir(dst);
|
||||
FAT32_FileInfo entries[64];
|
||||
int count = sys_list(src, entries, 64);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (strcmp(entries[i].name, ".") == 0 || strcmp(entries[i].name, "..") == 0) continue;
|
||||
char sub_src[512], sub_dst[512];
|
||||
combine_path(sub_src, src, entries[i].name);
|
||||
combine_path(sub_dst, dst, entries[i].name);
|
||||
copy_recursive(sub_src, sub_dst);
|
||||
}
|
||||
} else {
|
||||
int fd_in = sys_open(src, "r");
|
||||
if (fd_in < 0) return;
|
||||
int fd_out = sys_open(dst, "w");
|
||||
if (fd_out < 0) { sys_close(fd_in); return; }
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
}
|
||||
}
|
||||
|
||||
void delete_recursive(const char *path) {
|
||||
FAT32_FileInfo info;
|
||||
if (sys_get_file_info(path, &info) < 0) return;
|
||||
|
||||
if (info.is_directory) {
|
||||
FAT32_FileInfo entries[64];
|
||||
int count = sys_list(path, entries, 64);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (strcmp(entries[i].name, ".") == 0 || strcmp(entries[i].name, "..") == 0) continue;
|
||||
char sub_path[512];
|
||||
combine_path(sub_path, path, entries[i].name);
|
||||
delete_recursive(sub_path);
|
||||
}
|
||||
sys_delete(path);
|
||||
} else {
|
||||
sys_delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: mv <source> <dest>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_in = sys_open(argv[1], "r");
|
||||
if (fd_in < 0) {
|
||||
printf("Error: Cannot open source %s\n", argv[1]);
|
||||
char *src_path = argv[1];
|
||||
char *dst_path = argv[2];
|
||||
|
||||
FAT32_FileInfo info_src;
|
||||
if (sys_get_file_info(src_path, &info_src) < 0) {
|
||||
printf("Error: Cannot open source %s\n", src_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_out = sys_open(argv[2], "w");
|
||||
if (fd_out < 0) {
|
||||
printf("Error: Cannot create destination %s\n", argv[2]);
|
||||
sys_close(fd_in);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
int bytes;
|
||||
while ((bytes = sys_read(fd_in, buffer, sizeof(buffer))) > 0) {
|
||||
sys_write_fs(fd_out, buffer, bytes);
|
||||
}
|
||||
|
||||
sys_close(fd_in);
|
||||
sys_close(fd_out);
|
||||
|
||||
if (sys_delete(argv[1]) != 0) {
|
||||
printf("Warning: Failed to delete source %s after copy\n", argv[1]);
|
||||
|
||||
char actual_dst[512];
|
||||
FAT32_FileInfo info_dst;
|
||||
if (sys_get_file_info(dst_path, &info_dst) == 0 && info_dst.is_directory) {
|
||||
const char *base = get_basename(src_path);
|
||||
char clean_base[256];
|
||||
int k = 0;
|
||||
while (base[k] && base[k] != '/') {
|
||||
clean_base[k] = base[k];
|
||||
k++;
|
||||
}
|
||||
clean_base[k] = 0;
|
||||
combine_path(actual_dst, dst_path, clean_base);
|
||||
} else {
|
||||
strcpy(actual_dst, dst_path);
|
||||
}
|
||||
|
||||
copy_recursive(src_path, actual_dst);
|
||||
delete_recursive(src_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue