/* 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,
};
|