From 9405e9870dcac253d66d5008260257e2230320c9 Mon Sep 17 00:00:00 2001 From: Galen Sagarin Date: Tue, 6 May 2025 13:30:06 -0400 Subject: tarfs.c, as well as an incomplete ramfs.c: --- kernel/fs/tar.c | 459 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 242 insertions(+), 217 deletions(-) (limited to 'kernel/fs/tar.c') diff --git a/kernel/fs/tar.c b/kernel/fs/tar.c index 8beebc6..b844ed2 100644 --- a/kernel/fs/tar.c +++ b/kernel/fs/tar.c @@ -1,188 +1,222 @@ -#include "lib/kio.h" #include #include - -struct tar_hdr { - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char chksum[8]; - char typeflag; - char linkname[100]; - char magic[6]; - char version[2]; - char uname[32]; - char gname[32]; - char devmajor[8]; - char devminor[8]; - char prefix[155]; - char unused[12]; +#include + +// the placements of these values mimics their placement in standard UStar +struct tar_header { + char name[100]; // 0-99 + char mode[8]; // 100-107 + char ownerUID[8]; // 108-115 + char groupUID[8]; // 116-123 + char fileSize[12]; // 124-135 + char lastMod[12]; // 136-147 + char checksum[8]; // 148-155 + char type_flag; // 156 + char linked_name[100]; // 157-256 + char magic[6]; // 257-262 + char version[2]; // 263-264 + char username[32]; // 265-296 + char groupname[32]; // 297-328 + char majorNum[8]; // 329-336 + char minorNum[8]; // 337-344 + char prefix[155]; // 345-499 + char notUsed[12]; // 500-511 }; - -struct tar_file { - struct file file; - struct file_system *fs; - size_t len; - size_t offset; - size_t sect; -}; - -#define TAR_SECT_SIZE 512 - -#define TMAGIC "ustar" -#define TMAGLEN 6 -#define TVERSION "00" +#define TAR_SIZE 512 +#define TMAGIC "ustar" /* ustar and a null */ +#define TMAGLEN 6 +#define TVERSION "00" /* 00 and no null */ #define TVERSLEN 2 +#define ERROR_TAR 1 +#define NOERROR_TAR 0 -#define REGTYPE '0' -#define DIRTYPE '5' +#define REGTYPE '0' /* regular file */ +#define DIRTYPE '5' /* directory */ -static int read_tar_hdr(struct disk *disk, uint32_t sect, struct tar_hdr *hdr) -{ - if (disk_read(disk, sect * TAR_SECT_SIZE, TAR_SECT_SIZE, hdr) < - TAR_SECT_SIZE) - return 1; - - // check magic - if (memcmp(hdr->magic, TMAGIC, TMAGLEN) != 0) - return 1; - // check version - if (memcmp(hdr->version, TVERSION, TVERSLEN) != 0) - return 1; - - return 0; +struct tar_file { + struct file file; + struct file_system *fs; + size_t len; + size_t offset; + size_t sect; +}; +// read_tar_header reads what is in tar +int read_tar_header(struct disk *disk, uint32_t sect, struct tar_header *hdr) { + + if(disk_read(disk, sect * TAR_SIZE, TAR_SIZE, hdr) < TAR_SIZE) { + return ERROR_TAR; + } + if(memcmp(hdr->magic, TMAGIC, TMAGLEN) != 0 || memcmp(hdr->version, TVERSION, TVERSLEN) != 0) { + return ERROR_TAR; + } + return NOERROR_TAR; + } -static int tar_to_fs_type(char typeflag) -{ - switch (typeflag) { - case REGTYPE: - return F_REG; - case DIRTYPE: - return F_DIR; - default: - return -1; - } +/// @brief +/// @param f +/// @param buffer +/// @param len +/// @return +int tar_read(struct file *f, char *buffer, size_t len) { + struct tar_file *tf = (struct tar_file*) f; + long size = MIN((tf->len - tf->offset), len); + if(tf->file.f_type != F_REG || size < 1) { + return ERROR_TAR; + } + size = disk_read(tf->fs->fs_disk, tf->sect+1 * TAR_SIZE + tf->offset, size, buffer); + tf->offset += size; + return size; } - -static int tar_locate(struct file_system *fs, const char *path, - struct tar_hdr *out_hdr, size_t *out_sect, - size_t *in_sect, bool partial) -{ - struct tar_hdr hdr; - size_t sect = 0; - - if (in_sect != NULL) - sect = *in_sect; - - while (1) { - size_t filesize, sects; - int cmp; - - if (read_tar_hdr(fs->fs_disk, sect, &hdr)) - return 1; - - filesize = strtoull(hdr.size, NULL, 8); - sects = (filesize + TAR_SECT_SIZE - 1) / TAR_SECT_SIZE; - - if (partial) { - size_t len = MIN(strlen(path), strlen(hdr.name)); - cmp = memcmp(hdr.name, path, len); - } else { - cmp = memcmp(hdr.name, path, strlen(path) + 1); - } - - if (cmp) { - // not our file, goto next - sect += sects + 1; - continue; - } - - // we found our file! - *out_hdr = hdr; - *out_sect = sect; - if (in_sect != NULL) - *in_sect = sect + sects + 1; - return 0; - } - - return 1; +//static int read_tar() +// we are assuming that things are formatted correctly. +int find_file(struct file_system *fs, const char *filepath, size_t *sect, size_t *sect_return, struct tar_header *outHeader) { + //char *tempFilePath = filepath; + struct tar_header hdr; + size_t curr_sect; + if(sect == NULL) { + curr_sect = 0; + } else { + curr_sect = *sect; + } + while (1 == 1) { + if(read_tar_header(fs->fs_disk, curr_sect, &hdr) != 0) { + return ERROR_TAR; + } + if(memcmp(hdr.name, filepath, strlen(filepath) + 1) != 0) { + // didn't find it. + + curr_sect += ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1)/TAR_SIZE) + 1; + continue; + } else { + *outHeader = hdr; + *sect_return = curr_sect; + if(sect != NULL) { + sect += curr_sect; + } + return NOERROR_TAR; + } + + } + return ERROR_TAR; } +int find_file_redux(struct file_system *fs, const char *filepath, size_t *sect, size_t *sect_return, struct tar_header *outHeader) { + struct tar_header hdr; + size_t curr_sect; + if(sect == NULL) { + curr_sect = 0; + } else { + curr_sect = *sect; + } + while (1 == 1) { + if(read_tar_header(fs->fs_disk, curr_sect, &hdr) != 0) { + return ERROR_TAR; + } + if(memcmp(hdr.name, filepath, MIN(strlen(filepath), strlen(hdr.name))) != 0) { + // didn't find it. + + curr_sect += ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1)/TAR_SIZE) + 1; + continue; + } else { + *outHeader = hdr; + *sect_return = curr_sect; + if(sect != NULL) { + sect += curr_sect + ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1)/TAR_SIZE) + 1; + } + return NOERROR_TAR; + + } + + } + return ERROR_TAR; // it should never actually reach here. -int tar_read(struct file *in, void *buf, size_t len) -{ - struct tar_file *file = (struct tar_file *)in; - size_t max_bytes = file->len - file->offset; - long bytes = MIN(max_bytes, len); - - if (file->file.f_type != F_REG) - return 1; - - if (bytes < 1) - return 0; +} - bytes = disk_read(file->fs->fs_disk, - (file->sect + 1) * TAR_SECT_SIZE + file->offset, bytes, - buf); - if (bytes < 0) - return bytes; // return err code - file->offset += bytes; - return bytes; +void tar_close(struct file *f) { + kfree(f); } -int tar_write(struct file *in, const void *buf, size_t len) -{ - (void)in; - (void)buf; - (void)len; +int tar_seek(struct file *f, int offsetAdd, int theSeek) { + struct tar_file *tf = (struct tar_file*) f; + if(theSeek == SEEK_SET) { + tf->offset = offsetAdd; + } else if(theSeek == SEEK_CUR) { + tf->offset = tf->offset + offsetAdd; + } else if(theSeek ==SEEK_END) { + tf->offset = tf->len + offsetAdd; + } else { + return ERROR_TAR; + } + return NOERROR_TAR; + - // cannot write to tar balls - return -1; } -int tar_seek(struct file *in, long int off, int whence) -{ - struct tar_file *file = (struct tar_file *)in; - switch (whence) { - case SEEK_SET: - file->offset = off; - return file->offset; - case SEEK_CUR: - file->offset += off; - return file->offset; - case SEEK_END: - file->offset = file->len + off; - return file->offset; - default: - return -1; - } +int tar_write(struct file *f, const char *buffer, size_t len) { + // tar doesn't do write lol. This is just here so there is something to send to write + (void)f; + (void)buffer; + (void)len; + return ERROR_TAR; } -int tar_ents(struct file *in, struct dirent *ent, size_t entry) +/*int tar_ents(struct file *f, struct dirent *d, size_t dIndex) { + struct tar_header hdr; + struct tar_header dir; + struct tar_file *tf = (struct tar_file*) f; + size_t sect = 0; + size_t sect_off = 0; + size_t curr_index = 0; + if(read_tar_header(tf->fs->fs_disk, sect, &hdr) != 0) { + return ERROR_TAR; + } + while(1 == 1) { + if(find_file_redux(tf->fs, dir.name, §_off, §, &dir) != 0) { + return ERROR_TAR; + } + if(curr_index < dIndex) { + curr_index += 1; + } else if(curr_index > dIndex) { + // something went seriously wrong + return ERROR_TAR; + } else { + d->d_namelen = strlen(hdr.name); + dir.type_flag = DIRTYPE; + d->d_offset = dIndex; + memcpy(d->d_name, hdr.name, d->d_namelen + 1); + return NOERROR_TAR; + } + + + } + + +}*/ + + +int tar_ents(struct file *f, struct dirent *ent, size_t entry) { - struct tar_file *file; - struct tar_hdr dir, hdr; + struct tar_file *tf; + struct tar_header dir, hdr; size_t sect; size_t sect_off = 0; size_t idx = 0; - file = (struct tar_file *)in; + tf = (struct tar_file *)f; sect = 0; - if (file->file.f_type != F_DIR) + if (tf->file.f_type != F_DIR) return -1; - if (read_tar_hdr(file->fs->fs_disk, sect, &dir)) - return 1; + if (read_tar_header(tf->fs->fs_disk, sect, &dir)) { + return ERROR_TAR; + } while (1) { - if (tar_locate(file->fs, dir.name, &hdr, §, §_off, true)) - return 1; + if (find_file_redux(tf->fs, dir.name, §_off, §, &hdr)) + return ERROR_TAR; if (idx != entry) { idx++; @@ -192,77 +226,68 @@ int tar_ents(struct file *in, struct dirent *ent, size_t entry) ent->d_offset = entry; ent->d_namelen = strlen(hdr.name); memcpy(ent->d_name, hdr.name, ent->d_namelen + 1); - return 0; + return NOERROR_TAR; } - return 1; + return ERROR_TAR; } -void tar_close(struct file *file) -{ - kfree(file); +// opens up the tar file at fullpath, and puts it in out. +int tar_open(struct file_system *fs, const char *fullpath, struct file **out) { + struct tar_header hdr; + struct tar_file *newFile; + size_t sect_result; + find_file(fs, fullpath, NULL, §_result, &hdr); + newFile = kalloc(sizeof(struct tar_file)); + //newFile->file = idk; + newFile->file.f_type = F_REG; + newFile->fs = fs; + newFile->file.read = tar_read; + newFile->file.close = tar_close; + newFile->file.write = tar_write; // doesn't actually work; + newFile->file.ents = tar_ents; + newFile->file.seek = tar_seek; + newFile->offset = 0; + newFile->len = strtoull(hdr.fileSize, NULL, 8); + newFile->sect = sect_result; + + *out = (struct file *)newFile; + return NOERROR_TAR; + + + + } -int tar_open(struct file_system *fs, const char *path, int flags, - struct file **out) -{ - struct tar_file *file; - struct tar_hdr hdr; - size_t sect; - - // cannot create or write files - if (flags != O_RDONLY) - return 1; - - if (tar_locate(fs, path, &hdr, §, NULL, false)) - return 1; - - file = kalloc(sizeof(struct tar_file)); - if (file == NULL) - return 1; - - file->file.f_type = tar_to_fs_type(hdr.typeflag); - file->file.read = tar_read; - file->file.write = tar_write; - file->file.seek = tar_seek; - file->file.ents = tar_ents; - file->file.close = tar_close; - file->fs = fs; - file->len = strtoull(hdr.size, NULL, 8); - file->offset = 0; - file->sect = sect; - *out = (struct file *)file; - - return 0; +// gets stats at the file at fullpath, putting them in out. +int tar_stat(struct file_system *fs, const char *fullpath, struct stat *out) { + struct tar_header hdr; + size_t sect_result; + find_file(fs, fullpath, NULL, §_result, &hdr); + out->s_length = strtoull(hdr.fileSize, NULL, 8); + if(hdr.type_flag == REGTYPE) { + out->s_type = F_REG; + } else if(hdr.type_flag == DIRTYPE) { + out->s_type = F_DIR; + } else { + // wth + return ERROR_TAR; + } + return NOERROR_TAR; } -int tar_stat(struct file_system *fs, const char *path, struct stat *stat) -{ - struct tar_hdr hdr; - size_t sect; - - if (tar_locate(fs, path, &hdr, §, NULL, false)) - return 1; - - stat->s_length = strtoull(hdr.size, NULL, 8); - stat->s_type = tar_to_fs_type(hdr.typeflag); - - return 0; +// use tar for the filesystem. +int tar_mount(struct file_system *fs) { + struct tar_header hdr; + // reads into hdr + if(read_tar_header(fs->fs_disk, 0, &hdr) == 0) { + fs->fs_name = "tar"; + fs->open = tar_open; + fs->stat = tar_stat; + fs->fs_present = true; + return NOERROR_TAR; + } + return ERROR_TAR; } -int tar_mount(struct file_system *fs) -{ - struct tar_hdr hdr; - - // if first tar hdr is valid, assume valid tarball - if (read_tar_hdr(fs->fs_disk, 0, &hdr)) - return 1; - - fs->fs_present = true; - fs->fs_name = "tar"; - fs->open = tar_open; - fs->stat = tar_stat; - - INFO("loaded tarfs on disk %d", fs->fs_disk->d_id); - return 0; -} +// no need to unmount, since mount just overrides whatever it was using previously. \ No newline at end of file -- cgit v1.2.3-freya