os/kernel/vfs.c

358 lines
6.9 KiB
C

#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "vfs.h"
typedef struct _vfs_mapping_struct {
char* mntpnt;
uint32_t type;
struct _vfs_mapping_struct* next;
} vfs_mapping;
static const char** drv_names;
static fs_drv* drvs;
static uint32_t max_drvs;
static uint32_t next_drv_indx;
static vfs_mapping* head_mapping;
static vfs_mapping* tail_mapping;
FILE* stdin=NULL;
FILE* stdout=NULL;
FILE* stderr=NULL;
static int vfsstrcmp(const char* s1,const char* s2) {
int i;
for (i = 0; s1[i] == s2[i]; i++) {
if (s1[i] == '\0') return 0;
}
if (s1[i] == '\0') return 0;
return s1[i] - s2[i];
}
void init_vfs() {
drvs=malloc(sizeof(fs_drv)*32);
drv_names=malloc(sizeof(const char**)*32);
max_drvs=32;
next_drv_indx=0;
head_mapping=NULL;
tail_mapping=NULL;
}
uint32_t register_fs(fs_drv drv,const char* type) {
if (next_drv_indx==max_drvs) {
drvs=realloc(drvs,sizeof(fs_drv)*(max_drvs+32));
drv_names=realloc(drv_names,sizeof(char*)*(max_drvs+32));
max_drvs+=32;
}
drvs[next_drv_indx]=drv;
drv_names[next_drv_indx]=type;
next_drv_indx++;
return next_drv_indx-1;
}
char mount(char* mntpnt,char* dev,char* type) {
uint32_t i;
for (i=0;i<next_drv_indx;i++) {
const char* name=drv_names[i];
if (strcmp(name,type)==0) {
break;
}
}
char ok=drvs[i](FSOP_MOUNT,NULL,mntpnt,dev);
if (ok) {
if (head_mapping==NULL) {
vfs_mapping* mapping=malloc(sizeof(vfs_mapping));
mapping->mntpnt=malloc(sizeof(char)*(strlen(mntpnt)+1));
strcpy(mapping->mntpnt,mntpnt);
mapping->type=i;
mapping->next=NULL;
head_mapping=mapping;
tail_mapping=mapping;
} else {
vfs_mapping* mapping=malloc(sizeof(vfs_mapping));
mapping->mntpnt=malloc(sizeof(char)*(strlen(mntpnt)+1));
strcpy(mapping->mntpnt,mntpnt);
mapping->type=i;
mapping->next=NULL;
tail_mapping->next=mapping;
}
return 1;
} else {
return 0;
}
}
FILE* fopen(const char* filename,const char* mode) {
vfs_mapping* mnt=head_mapping;
vfs_mapping* mntpnt=NULL;
const char* path;
uint32_t mntpnt_len=0;
for (;mnt!=NULL;mnt=mnt->next) {
char* root=mnt->mntpnt;
if (strlen(root)>mntpnt_len) {
if (vfsstrcmp(root,filename)==0) {
mntpnt=mnt;
mntpnt_len=strlen(root);
}
}
}
if (mntpnt) {
path=filename+mntpnt_len;
FILE* stream=malloc(sizeof(FILE));
stream->mntpnt=mntpnt->mntpnt;
stream->path=path;
if (strcmp(mode,"w")==0) {
stream->wr=1;
stream->rd=0;
} else if (strcmp(mode,"r+")==0) {
stream->wr=1;
stream->rd=1;
} else {
stream->wr=0;
stream->rd=1;
}
stream->type=mntpnt->type;
stream->pos=0;
stream->eof=0;
stream->error=0;
char ok=drvs[mntpnt->type](FSOP_OPEN,stream,NULL,NULL);
if (ok) {
return stream;
} else {
free(stream);
return NULL;
}
}
return NULL;
}
int fgetc(FILE* stream) {
if (!stream->rd) {
errno=EBADF;
stream->error=1;
return EOF;
}
int c;
drvs[stream->type](FSOP_GETC,stream,&c,NULL);
return c;
}
int getc() {
return fgetc(stdin);
}
char* fgets(char* str,int count,FILE* stream) {
if (!stream->rd) {
errno=EBADF;
stream->error=1;
return NULL;
}
int i;
for (i=0;i<count-1;i++) {
char c=fgetc(stream);
if (c==EOF) {
return NULL;
} else if (c=='\n') {
str[i]=c;
i++;
break;
}
str[i]=c;
}
str[i]='\0';
return str;
}
size_t fread(void* buffer_ptr,size_t size,size_t count,FILE* stream) {
if (!stream->rd) {
errno=EBADF;
stream->error=1;
return 0;
}
char* buffer=(char*)buffer_ptr;
size_t bytes=size*count;
for (size_t i=0;i<bytes;i++) {
int c=fgetc(stream);
if (c==EOF) {
return (size_t)(i/size);
}
buffer[i]=c;
}
return count;
}
int fputc(int c,FILE* stream) {
if (!stream->wr) {
errno=EBADF;
stream->error=1;
return EOF;
}
char ok=drvs[stream->type](FSOP_PUTC,stream,&c,NULL);
if (ok) {
return c;
} else {
return EOF;
}
}
int putc(int c) {
return fputc(c,stdout);
}
int fputs(const char* s,FILE* stream) {
if (!stream->wr) {
errno=EBADF;
stream->error=1;
return EOF;
}
size_t len=strlen(s);
for (size_t i=0;i<len;i++) {
int c=fputc(s[i],stream);
if (c==EOF) {
return EOF;
}
}
return 1;
}
int puts(const char* s) {
return fputs(s,stdout);
}
size_t fwrite(void* buffer_ptr,size_t size,size_t count,FILE* stream) {
if (!stream->wr) {
errno=EBADF;
stream->error=1;
return 0;
}
char* buffer=(char*)buffer_ptr;
size_t bytes=size*count;
for (size_t i=0;i<bytes;i++) {
int c=fputc((uint8_t)buffer[i],stream);
if (c==EOF) {
return (size_t)(i/size);
}
}
return count;
}
int vfprintf(FILE* stream,const char* format,va_list arg) {
int c;
for(;*format!='\0';format++) {
if(*format!='%') {
c=fputc(*format,stream);
if (c==EOF) {
return EOF;
}
continue;
}
format++;
switch(*format) {
case 'c': {
int i=va_arg(arg,int);
c=fputc(i,stream);
if (c==EOF) {
return EOF;
}
break;
}
case 'd': {
int i=va_arg(arg,int); //Fetch Decimal/Integer argument
if(i<0) {
i=-i;
fputc('-',stream);
}
char str[11];
int_to_ascii(i,str);
c=fputs(str,stream);
if (c==EOF) {
return EOF;
}
break;
}
// case 'o': {
// int i=va_arg(arg,unsigned int); //Fetch Octal representation
// puts(convert(i,8));
// break;
// }
case 's': {
char* s=va_arg(arg,char*);
c=fputs(s,stream);
if (c==EOF) {
return EOF;
}
break;
}
case 'x': {
uint32_t i=va_arg(arg,uint32_t);
char str[11];
str[0]='\0';
hex_to_ascii(i,str);
c=fputs(str,stream);
if (c==EOF) {
return EOF;
}
break;
}
}
}
return 1;
}
int fprintf(FILE* stream,const char* format,...) {
va_list arg;
int code;
va_start(arg,format);
code=vfprintf(stream,format,arg);
va_end(arg);
if (code) {
return strlen(format);
} else {
return EOF;
}
}
int printf(const char* format,...) {
va_list arg;
int code;
va_start(arg,format);
code=vfprintf(stdout,format,arg);
va_end(arg);
if (code) {
return strlen(format);
} else {
return EOF;
}
}
int fseek(FILE* stream,long offset,int origin) {
if (origin==SEEK_SET) {
stream->pos=offset;
}
if (origin==SEEK_CUR) {
stream->pos+=offset;
}
return 0;
}
long ftell(FILE* stream) {
return stream->pos;
}
int fclose(FILE* stream) {
drvs[stream->type](FSOP_CLOSE,stream,NULL,NULL);
free(stream);
return 0;
}
int feof(FILE *stream) {
return stream->eof;
}
int ferror(FILE *stream) {
return stream->error;
}