/* Dispositivo para el sistema de ficheros malvado * creado por Eduardo Orive * para la asignatura de DSO * se declina cualquier responsabilidad * -------------------------------- * Utilizare la letra V porque esta libre y porque * es una de las letras de malVado, como el mismo. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" enum{ Qtop = 0, Qdir = 0, Qctl = 1, Qfirst = 2, Qdisp=2, // a partir de aqui van los Qid de los descriptores r0, // Raid0 (mirroring) r1, // Raid1 (Striping) r3, // Raid5 (interleaving) dv, // disco virtual particionable // numero de FSes especiales, yo los llamare principales N = 8, // numero de posiciones posibles en la matriz de punteros a nodos. NNod = 9, bloque = 8 * 1024, Qdata=1, }; Dirtab evilfstab[N+2]={ ".", {Qdir, 0, QTDIR}, 0, 0555, "evilfs", {Qctl, 0}, 0, 0660, // Las posiciones restantes se emplearan para los dispositivos }; int NDisp=0 ; static Qid dispid = { Qdisp , 0 } ; #define NKBFILE sizeof(evilfstab)/sizeof(evilfstab[0]) #define KBLINELEN (3*NUMSIZE+1) /* t code val\n */ typedef struct principal principal; typedef struct nodo nodo; struct principal { int tipo; char *nombre; long ini; long t; int n_nodos; nodo *nodos[NNod]; //dedicado a aquellos que no quieren ptr en kernel nodo *sig; // para la rotacion del rd3 }; typedef nodo nodo; struct nodo { char *n; Chan *c; long t; nodo *sig; // para el interleaving }; static principal *dispositivos[N] = nil; int libre(int inicio) { int i; for (i = inicio; i < N; i++) { if (dispositivos[i] == nil) return (i); }; return -1; }; void alta_disp(char *nombre) { Dirtab nuevo ; // char *n; // n = malloc (strlen(nombre) ) ; Qid qid = {Qfirst+NDisp,0} ; strcpy (nuevo.name, nombre); nuevo.qid= qid ; nuevo.length = 0 ; nuevo.perm= 0660; evilfstab[Qfirst+NDisp] = nuevo ; NDisp++ ; } static int config_linea(char *cadena) { int i; int tipo; int ifich; int ffich; int npos; char *tokens[10] = nil; int args=0; long a1; long a2; principal *nuevo; nodo *anterior = nil; char *nombre; print("%s \n", cadena) ; args = getfields(cadena, tokens, 8, 1, " "); print("se han recibido %i parametros\n",args); if (args < 4) { print("no hay parametros para hacer nada \n"); return -1; } if (strcmp(tokens[0], "r0") == 0) { tipo = r0; } else if (strcmp(tokens[0], "r1") == 0) { tipo = r1; } else if (strcmp(tokens[0], "r3") == 0) { tipo = r3; } else if (strcmp(tokens[0], "dv") == 0) { tipo = dv; } else { error ("el tipo de dispostivo no esta reconocido"); return -1; }; /* for (i = 0; i < 9; i++) { if (tokens[i] == nil) break; // ya no quedan tokens if (tokens[i][0] == 0) continue; // eran 2 espacios seguidos args++; // printf("%s:%i\n",tokens[i],atol(tokens[i])); };*/ // error(tokens[1]); switch (tipo) { case dv: if (args < 4) { error("se requieren 4 parametros para un disco virtual: nombre fichero inicio y fina\n"); return -1; } a1 = strtol(tokens[3],nil,0); a2 = strtol(tokens[4],nil,0); if (!strcmp(tokens[3], "0") && (a1 == 0)) { error("inicio y final deben ser variables numericas\n"); return -1; }; if (a1 >= a2) { error ("la posicion de inicio debe ser menor que la de final y ambas deben ser numericas\n"); return -1; }; ifich = 2; ffich = 2; break; default: print("default\n"); ifich = 2; ffich = args - 1; print("%i nodos a instanciar.\n", ffich - ifich); }; // esta es la parte donde se acometen los cambios // abrimos los ficheros print("aqui va el malloc de principal\n"); nuevo = malloc(sizeof(principal)); print("aqui va el malloc de nombre\n"); nuevo->nombre = malloc(strlen(tokens[1])) ; //print(tokens[1]) ; strcpy(nuevo->nombre, tokens[1]) ; //print( nuevo->nombre ) ; print("buscamos una posicion libre para el dispositivo\n"); npos = libre(0); if (npos == -1) { error("no quedan posiciones libres en el array de dispositivos"); return -1; } print("iniciamos a apertura de ficheros:"); print(" %i a %i\n" , ifich, ffich) ; for (i = 0; ifich + i <= ffich; i++) { print("abriendo %s, %i de %i\n", tokens[i + ifich], i + 1,ffich - ifich + 1); nuevo->nodos[i] = malloc(sizeof(nodo)); if (i == 0) { nuevo->sig = nuevo->nodos[0]; nuevo->nodos[0]->sig = nuevo->nodos[0]; } else { anterior->sig = nuevo->nodos[i]; nuevo->nodos[i]->sig = nuevo->sig; }; nuevo->nodos[i]->n = tokens[i + ifich]; anterior = nuevo->nodos[i]; print("fin commit para %s\n", nuevo->nodos[i]->n); nuevo->n_nodos = args + 1; }; //calc_size(nuevo); npos = Qfirst + NDisp; dispositivos[npos] = nuevo; print(" alta dispositivos ") ; alta_disp(tokens[1]); if (i + ifich < ffich) { // printf("instanciacion abortada\n"); // tocaria deshacer pero no es prioritario return -1; } else print("fin commit para el dispositivo: %s\n", tokens[1]); return 0; }; static int evilconfig(char *cadena, long n) { char *cadenas[2]=nil; char *sig_cadena=nil; long i = n ; while (sig_cadena != cadena) { getfields(cadena, cadenas, 2, 1, "\n"); cadena = cadenas[0]; sig_cadena = cadenas[1]; if (cadena == nil) { break ; }; print("recibido; %s\n", cadena); // i -= strlen(cadena) ; print("siguientes: %s %p\n",sig_cadena, sig_cadena); print("punteros: %p %p \n",cadenas[0], cadenas[1]); if (config_linea(cadena) == -1) { error("error creando el dispositivo");break;}; if (strlen(sig_cadena) == 0 ) break; cadena = sig_cadena; }; return 0; }; static Chan * evilfsattach(char *spec) { // alta_disp("uno") ; alta_disp("dos"); return devattach(L'V', spec); } static Walkqid* evilfswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, evilfstab, Qfirst+NDisp, devgen); } static int evilfsstat(Chan *c, uchar *dp, int n) { return devstat(c, dp, n, evilfstab, Qfirst+NDisp, devgen); } static Chan* evilfsopen(Chan *c, int omode) { if(!iseve()) error(Eperm); return devopen(c, omode, evilfstab, Qfirst+NDisp, devgen); } static void evilfsclose(Chan *c) { if(c->aux){ free(c->aux); c->aux = nil; } } static long evilfsread(Chan *c, void *a, long n, vlong offset) { char *bp; char tmp[KBLINELEN+1]; int t, sc; Rune r; if(c->qid.type == QTDIR) return devdirread(c, a, n, evilfstab, Qfirst+NDisp, devgen); switch((int)(c->qid.path)){ case Qctl: if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) { bp = tmp; bp += readnum(0, bp, NUMSIZE, t, NUMSIZE); bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE); bp += readnum(0, bp, NUMSIZE, r, NUMSIZE); *bp++ = '\n'; *bp = 0; n = readstr(offset%KBLINELEN, a, n, tmp); } else n = 0; break; default: n=0; break; } return n; } static long evilfswrite(Chan *c, void *a, long n, vlong) { char line[100], *lp, *b; int key, m, l; Rune r; if(c->qid.type == QTDIR) error(Eperm); switch((int)(c->qid.path)){ case Qctl: evilconfig(a,n); } return n; } Dev evilfsdevtab = { L'V', "evilfs", devreset, devinit, devshutdown, evilfsattach, evilfswalk, evilfsstat, evilfsopen, devcreate, evilfsclose, evilfsread, devbread, evilfswrite, devbwrite, devremove, devwstat, };