minifs.cpp



minifs.cpp


#include <stdio.h> // scanf, printf

#include <stdlib.h>//Libreria que contiene la funcion system

#include <string.h>//strcmp

#include "miniFS.h"


const int TEXTO_MAX = 50;


// ¿Por qué tengo estas dos variables globales?: porque sino tengo que pasarle a cada función 2 argumentos más.

// Esto es seguro en este entorno de consola, porque ninguna otra aplicación puede tener acceso a ellas.

NODO_DIR *RAIZ = NULL;

NODO_DIR *DIR_ACTUAL = NULL;


void print_ancestros(NODO_DIR *p) { //recursiva

    /* recursivamente va bajando de nivel hasta encontrar RAIZ,

luego al volver de cada nivel de recursión va imprimiendo los nombres;

así quedan en orden */

    if (p == NULL) return;

    if (p != RAIZ) print_ancestros(p->padre); //si no es la raiz, volver a entrar

    printf(p->Nombre);

    printf("\\");

}

void prompt(const char *Mensaje){

    printf("......%s\n",Mensaje);

    print_ancestros(DIR_ACTUAL);

    printf(">");

}


bool NoExiste_DIR_ACTUAL(void){

    if (DIR_ACTUAL==NULL) DIR_ACTUAL=RAIZ; //no debería ocurrir

    if (DIR_ACTUAL==NULL) {

       prompt("no hay sistema de archivos");

        return true;

    }

     else

        return false;

}

bool MemoriaInsuficiente(void *variable){ //el operador new puede fallar, retona NULL, hay que comprobarlo y no intentar usarlo como puntero válido

    if (variable == NULL){

        prompt("memoria insuficiente");

    return true;

    }

    else

    return false;

}


NODO_DIR *busca_dir(char *comando, NODO_DIR *p){ //recusivo, devuelve un puntero porque lo que necesito es un NODO_DIR para seguir buscando

int c=0;

if (p == NULL) return NULL;//si el nodo no existe, vuelve a la recursion

c = strcmp(p->Nombre, comando);//si no es NULL quiere decir que la estructura existe, que hay un NODO_DIR, entonces comparamos su nombre

if (c==0) return p; //si era ese nombre, ya vuelvo lo encontre, retornarlo

if (c>0)//el comando está más adelante que el nombre? si es así tenemos que ir a la izquierda

return busca_dir(comando, p->izq); //

else //si comando está más a la derecha, nos vamos para la derecha, cuando lo encuentre, vuelve un nivel, despues que vuelve un nivel, sigue volviendo hasta que retorna el que lo llamo originalmente

return busca_dir(comando, p->der);//

}


//comando contiene el nombre del archivo, no se modifica,

//p es puntero al NODO_FILE a partir del cual se empieza a buscar con el nombre de archivo que tiene comando, dentro de

//su arbol binario de archivo.

//Devuelve puntero a Nodo FILE (que es lo que estamos buscando) o NULL si no lo encuentro

// la función no modifica nada y no tiene pre-requisitos

NODO_FILE *busca_file(char *comando, NODO_FILE *p){ //recusivo, idem busca_dir excepto NODO_FILE en vez de NODO_DIR

int c=0;

if (p == NULL) return NULL;

c = strcmp(p->Nombre,comando);

if (c==0) return p;

if (c>0)

return busca_file(comando, p->izq);

else

return busca_file(comando, p->der);

}


// p es un puntero al NODO_FILE que queremos eliminar

// anula todo su sub arbol liberando la memoria, modifica el sistema

// la usa eliminar_dir y elimunar_1_dir

void eliminar_files(NODO_FILE *p) { //recursiva, elimina el árbol completo de archivos de raíz p

    if (p == NULL) return; //si no habia nada vuelve

//si habia algo, elimina el subarbol de la izquierda y luego el subarbol de la derecha

    eliminar_files(p->izq);

    eliminar_files(p->der);

//si llegó hasta aquí es que ya vació los subárboles izq y der, ya puedo eliminar el nodo

    delete p->Texto; //no necesito comprobar si es NULL, a delete no le importa

    delete p; //borra el nodo en cuestion

}


/*

Entrada: NODO_FILE **p

p es la dirección del puntero que apunta a un nodo,

necesito la direccion para poder mofdificarlo

Salida: NODO_FILE **file_minimo

file_minimo es la dirección del puntero que apunta a al nodo de más a la izq

Acción:

recorre recursivamente el ABB de raíz DIR_ACTUAL->primer_hijo_file buscando el nodo

de más a la izq, que correponde al archivo con nombre alfabéticamente menor

*/

NODO_FILE **file_minimo(NODO_FILE **p) { //recursiva

//devuelve la dirección de ->izq o ->der que apunta al nodo de más a la izq para poder modificarla

//por comentarios ver dir_minimo, es idéntica,

    if ((*p)->izq == NULL) //si no tiene nada a la izquierda, era ese el de más a la izquierda

    return p;// lo retorno

    else ////si tiene algo a la izquierda, tenemos que seguir moviendonos un poco más a la izquierda,

        return file_minimo(&((*p)->izq));

}


void eliminar_1_file(NODO_FILE **p) {

//para modificar un nodo necesito modificar la referencia a él en su padre, o sea padre->der o padre->izq

// por eso paso la dirección

NODO_FILE *q; //para evitar tantos * lo hago una sola vez

NODO_FILE **r; //el mínimo de la derecha; es la dirección del puntero en el padre, para poder modificarla después

q=*p; //ya guardé *p en q, ahora puedo modificar *p sin perder su valor original

delete q->Texto;

    if (q->izq == NULL && q->der == NULL) {

    *p=NULL; //esto pone un NULL en padre->der o padre->izq

    delete q;

    return;

    }

//si sólo tengo 1 hijo sólo hay que reemplazarme por mi hijo

    if (q->izq == NULL && q->der != NULL) {

    *p=q->der; //esto pone mi hijo en mi lugar

    delete q;

    return;

    }

    

    if (q->izq != NULL && q->der == NULL) {

    *p=q->izq; //esto pone mi hijo en mi lugar

    delete q;

    return;

    }


//si tengo 2 hijos tengo que copiar el valor del mínimo de la derecha en mí (para mantener el árbol ordenado) y borrarlo

//http://www.algolist.net/Data_structures/Binary_search_tree/Removal

    if (q->izq != NULL && q->der != NULL) {

    r=&((*p)->der);

    r=file_minimo(r);

    strcpy(q->Nombre, (*r)->Nombre);

    q->SoloLectura = (*r)->SoloLectura;

    q->Texto = (*r)->Texto;

    delete *r; //borro el nodo mínimo

    *r=NULL; //esto pone un NULL en padre->der o padre->izq que apunte al mínimo

    return;

    }

}


NODO_DIR **dir_minimo(NODO_DIR **p) { //recursiva; igual a file_minimo pero sobre estructura NODO_DIR

//devuelve la dirección de ->izq o ->der que apunta al nodo de más a la izq

//la usa eliminar_1_dir

if ((*p)->izq == NULL) //si no hay más nodos a la izq éste es el de más a la izq

return p; //devuelvo la dirección del puntero a ese nodo para poder luego modificar ese puntero

else //no era el de más a la izq, bajar un nivel más

return dir_minimo(&((*p)->izq)); //recursivamente me llamo (siempre con la dirección del puntero al nodo) hasta encontrar el de más a la izq; al encontrarlo sube 1 nivel en la pila de llamadas recursivamente hasta terminar la recursión

}

void eliminar_dir(NODO_DIR *p) { //recursiva, elimina el árbol completo de directorios de raíz p

if (p == NULL) return;

eliminar_files(p->primer_hijo_file); //eliminar el arbol de archivos basado en su primer hijo

eliminar_dir(p->primer_hijo_dir); //eliminar el arbol de directorios

eliminar_dir(p->izq);//eliminar la izquierda

eliminar_dir(p->der); //eliminar la derecha

delete p; //eliminar el nodo con el que entre

}

void eliminar_1_dir(NODO_DIR **p) {

//para modificar un nodo necesito modificar la referencia a él en su padre, o sea padre->der o padre->izq

// por eso paso la dirección. //para borrar un nodo que no tiene hijos simplemente se borra el nodo y se pone un NULL en el padre que apuntaba a el

NODO_DIR *q; //para evitar tantos * lo hago una sola vez

NODO_DIR **r; //el mínimo de la derecha; es la dirección del puntero en el padre, para poder modificarla después

q=*p; //ya guardé *p en q, ahora puedo modificar *p sin perder su valor original

eliminar_dir(q->primer_hijo_dir);

eliminar_files(q->primer_hijo_file);

if (q->izq == NULL && q->der == NULL) {

*p=NULL; //esto pone un NULL en padre->der o padre->izq

delete q;

return;

}

//si sólo tengo 1 hijo sólo hay que reemplazarme por mi hijo, o sea ponemos el hijo en el lugar del nodo que borramos

if (q->izq == NULL && q->der != NULL) {

*p=q->der; //esto pone mi hijo en mi lugar

delete q;

return;

}

if (q->izq != NULL && q->der == NULL) {

*p=q->izq; //esto pone mi hijo en mi lugar

delete q;

return;

}

//si tengo 2 hijos tengo que copiar el valor del mínimo de la derecha en mí (para mantener el árbol ordenado) y borrarlo.

/* Al nodo que vamos a borrar le vamos a poner un valor que vamos a elejir para que no se desordene el arbol.

¿Qué valor podemos mover al nodo vacante para que mantenga el arbol ordenado? Si elegimos un valor X entonces,

1)todo en el sub arbol izq del nodo que vamos a borrar que es donde vamos a poner la X, tiene que ser menor que X

2)todo en el sub arbol derecho del nodo que vamos a borrar tiene que ser mayor que X.

Supongamos que vamos a elegir X del sub arbol izquierdo del nodo que vamos a borrar,

la condicion 2 esta garantizada porque todo en el sub arbol izq del nodo que

vamos a borrar es menor que todo en el sub arbol derecho. Si X viene del subarbol izq la

condicion 1 dice que todo en el sub arbol izq tiene que ser menor que x entonces hay una unica opcion para X,

debemos elegir X que sea el mayor valor del sub arbol izq, asi si lo ponemos en el nodo vacante

y borramos el nodo que tiene el valo X de su posicion actual tendremos un arbol ordenado con el nodo que ibamos a borrar

eliminado.

Podriamos hacer lo mismo usando el menor valor del sub arbol derecho que es como lo hacemos nosotros.

*/

//http://www.algolist.net/Data_structures/Binary_search_tree/Removal

if (q->izq != NULL && q->der != NULL) {

r=&((*p)->der);

r=dir_minimo(r);

strcpy(q->Nombre, (*r)->Nombre);

q->padre=(*r)->padre;//no sería necesario porque de todas formas todos tienen el mismo padre

q->primer_hijo_dir=(*r)->primer_hijo_dir;

q->primer_hijo_file=(*r)->primer_hijo_file;

delete *r; //borro el nodo mínimo

*r=NULL; //esto pone un NULL en padre->der o padre->izq que apunte al mínimo

return;

}

}

void insertar_hijo_file (NODO_FILE **p, NODO_FILE *h){

// h apunta a un NODO previamente creado a añadir al arbol, su padre será *p

int c = 0;

if (*p == NULL) //pasé p por referencia para poder modificarlo; puntero al puntero al nodo

*p=h;

else {

c=strcmp((*p)->Nombre,h->Nombre); //ya comprobé que no existe ese nombre así que c!=0

if (c>0)

insertar_hijo_file(&((*p)->izq), h);

else

insertar_hijo_file(&((*p)->der), h);

}

}

void insertar_hijo_dir (NODO_DIR **p, NODO_DIR *h){

// h apunta a un NODO previamente creado a añadir al arbol, su padre será *p

int c = 0;

if (*p == NULL) //pasé p por referencia para poder modificarlo; puntero al puntero al nodo

*p=h;

else {

c=strcmp((*p)->Nombre,h->Nombre); //ya comprobé que no existe ese nombre así que c!=0

if (c>0)

insertar_hijo_dir(&((*p)->izq), h);

else

insertar_hijo_dir(&((*p)->der), h);

}

}

// comando originalmente tenia la accion, un espacio y argumentos, pero evalua lo manda

//ya sin la accion. hay funciones como crearsistema que no admiten argumentos.

bool SobraElArgumento(char *comando){

if (*comando == 0) //string vacío

return false;

else {//resulta que hay caracteres despues de la acción

prompt("no se reconoce el comando");

return true;

}

}

void destruirsistema(void){

if (NoExiste_DIR_ACTUAL()) return;

eliminar_1_dir(&RAIZ); //ésto también se puede hacer así: eliminar_dir(RAIZ); RAIZ=NULL;

DIR_ACTUAL = NULL;

prompt("OK");

}

// comando no la usamos, evalua llama a funciones con un argumento

void crearsistema(char *comando){

if (SobraElArgumento(comando)) return;

if (RAIZ != NULL) {

prompt("ya existe el sistema, para crearlo nuevamente antes debe destruir el actual");

return;

}

//eliminar_dir(RAIZ);

RAIZ = new NODO_DIR; //otra opción: RAIZ = (NODO_DIR *)malloc(sizeof(NODO_DIR)); .... free(RAIZ);

if (MemoriaInsuficiente(RAIZ)) return;

strcpy(RAIZ->Nombre,"RAIZ");

RAIZ->padre = RAIZ; //para cd .. "Si el directorio actual es el raiz y hacemos cd .. no se cambia de directorio."

RAIZ->izq = NULL;

RAIZ->der = NULL;

RAIZ->primer_hijo_dir = NULL;

RAIZ->primer_hijo_file = NULL;

DIR_ACTUAL = RAIZ;

prompt("OK");

}

//comando es el nombre del archivo o de directorio, y no se modifica

bool valida_nombre(char *comando, bool BuscaDir){

int nombre=0; //contador de cantidad de caracteres del nombre

int extension=0; //contador de cantidad de caracteres de la extensión

int punto=0; //contador de cantidad de puntos

int i=0;

for (i=0;comando[i]!=0;i++){ //recorrer la string hasta el final

if (comando[i]=='.'){

punto++;

if (punto>1) return false; //si hay más de 1 punto el nombre no es válido

}

else

if ((comando[i]>='a' && comando[i]<='z') || (comando[i]>='0' && comando[i]<='9')){

if (punto==0) //antes del punto es el nombre

nombre++;

else //después del punto es la extensión

extension++;

}

else

return false; //otros caracteres no son admitidos

}

if (nombre>15 || extension>3) return false; //si el nombre tiene más de 15 caracteres o la extension es mayor a 3 caracteres falló

if (nombre<1) return false; //si el nombre es menor a 1 caracter, falló

if (BuscaDir && punto>0) return false; //los directorios no admiten extensión

if (BuscaDir && strcmp(comando,"RAIZ")==0) return false; //no permitir crear un directorio llamado RAIZ

if (punto>0 && extension<1) return false;

return true;

}

//comando es el nombre del directorio que vamos a crear. No se modifica

void mkdir(char *comando){

NODO_DIR *h;

if (NoExiste_DIR_ACTUAL()) return;

if (busca_dir(comando, DIR_ACTUAL->primer_hijo_dir) != NULL){

prompt("ya existe ese nombre de directorio");

return;

}

if (!valida_nombre(comando,true)){

prompt("nombre invalido: hasta 15 caracteres a-z, 0-9");

return;

}

h = new NODO_DIR;

if (MemoriaInsuficiente(h)) return;

strncpy(h->Nombre,comando,15); //el 15 es importante, si no strncpy escribe 0s más alla del tamaño de Nombre

h->Nombre[15] = 0; //no sé si es necesario pero me aseguro

h->padre = DIR_ACTUAL;

h->izq = NULL;

h->der = NULL;

h->primer_hijo_dir = NULL;

h->primer_hijo_file = NULL;

insertar_hijo_dir(&(DIR_ACTUAL->primer_hijo_dir),h);

prompt("OK");

}

//comando contiene el nombre del directorio, no se modifica

NODO_DIR **busca_dir_puntero(char *comando, NODO_DIR **p){ //recusivo, idem excepto NODO_DIR en vez de NODO_FILE; toma dirección y devuelve dirección para poder modificar el padre

int c=0;

if ((*p) == NULL) return NULL;

c = strcmp((*p)->Nombre,comando);

if (c==0) return p;

if (c>0)

return busca_dir_puntero(comando, &((*p)->izq));

else

return busca_dir_puntero(comando, &((*p)->der));

}

//comando contiene el nombre del directorio, no se modifica

void rmdir(char *comando){

NODO_DIR **p = NULL;

if (NoExiste_DIR_ACTUAL()) return;

//no hay peligro de eliminar RAIZ porque busco sólo entre los hijos y RAIZ no es hijo

//para modificar un nodo necesito modificar la referencia a él en su padre, o sea padre->der o padre->izq

// por eso paso la dirección

p=busca_dir_puntero(comando, &(DIR_ACTUAL->primer_hijo_dir));

if (p == NULL)

prompt("no existe el directorio");

else

{

eliminar_1_dir(p);

prompt("OK");

}

}

//comando puede contener sub comandos como ser RAIZ o .. o un nombre de directorio

//Esta función modifica el sistema

void cd(char *comando){

NODO_DIR *p = NULL;

if (NoExiste_DIR_ACTUAL()) return;

if (strcmp(comando,"..")==0 || strcmp(comando," ..")==0) {

DIR_ACTUAL = DIR_ACTUAL->padre;

prompt("OK");

return; //retornamos el directorio padre

}

if (*comando == ' ') // en todos los otros casos el espacio es necesario

comando++; //saltear el espacio

else { //sino hay espacio no se reconoce el comando, por ejemplo cda

prompt("no se reconoce el comando");

return;

}

if (strcmp(comando,"RAIZ")==0) {

DIR_ACTUAL = RAIZ;

prompt("OK");

}

else {

p = busca_dir(comando, DIR_ACTUAL->primer_hijo_dir);

if (p != NULL) {

DIR_ACTUAL = p;

prompt("OK");

}

else

prompt("no existe el directorio");

}

}

void inorder_dir(NODO_DIR *p){ //usada por dir, es para listar

if (p != NULL){ //si no era null entonces vemos si hay uno mas a la izquierda, va todo a la izquierda que pueda

inorder_dir(p->izq);

//mostrar el directorio cuyo ->izq==NULL o cuya ruta ya fue recorrida

printf("%s\n", p->Nombre);

inorder_dir(p->der); // va a buscar a la derecha

}

}

void inorder_file(NODO_FILE *p){ //usada por dir, idem a inorder_dir

if (p != NULL){

inorder_file(p->izq);

//mostrar el archivo cuyo ->izq==NULL o cuya ruta ya fue recorrida

printf("%s",p->Nombre);

if (p->SoloLectura)

printf("\t lectura\n");

else

printf("\t lectura/escritura \n");

inorder_file(p->der);

}

}

//comando 3 posibilidades: argumento nulo, .. o el nombre del directorio

//La función no modifica el sistema

void dir(char *comando){

NODO_DIR *p = NULL;

if (NoExiste_DIR_ACTUAL()) return;

if (*comando == 0) //dir solo, sin argumentos, muestra lo que hay en el directorio actual

p = DIR_ACTUAL;

else {

if (strcmp(comando,"..")==0 || strcmp(comando," ..")==0) { //listamos lo que hay en el directorio padre

if (DIR_ACTUAL == RAIZ) {

prompt("no existe el directorio padre");

return;

}

p = DIR_ACTUAL->padre;

}

else {

if (*comando == ' ') // en todos los otros casos el espacio es necesario

comando++; //saltear el espacio

else {

prompt("no se reconoce el comando");

return;

}

p = busca_dir(comando, DIR_ACTUAL->primer_hijo_dir);

}

}

if (p == NULL){//si no encuentra el directorio

prompt("no existe el directorio");

return;

}

//si llega hasta aca es que encontro el directorio a listar y lo lista

inorder_file(p->primer_hijo_file);

inorder_dir(p->primer_hijo_dir);

prompt("OK");

}

//comando contiene el nombre de archivo

void _createfile(char *comando){

NODO_FILE *h;

if (NoExiste_DIR_ACTUAL()) return; //comprobamos que exista el sistema

if (busca_file(comando, DIR_ACTUAL->primer_hijo_file) != NULL){ //false porque no estoy buscando directorios

prompt("ya existe ese nombre de archivo");

return;

}

if (!valida_nombre(comando,false)){ //validamos que el nombre de archivo sea valido

prompt("nombre invalido: hasta 15 caracteres a-z, 0-9, y opcionalmente un punto + una extensión de hasta 3 caracteres a-z, 0-9");

return;

}

h = new NODO_FILE;

if (MemoriaInsuficiente(h)) return;

strncpy(h->Nombre,comando,19); //Nombre[0] a Nombre[19] = 20 caracteres: 15 + el punto + 3 + \0

h->Nombre[19]=0; //le ponemos un cero al final, strncpy dice que si el nombre es mas chico que 19 le agrega ceros hasta llegar al 19, por eso no sé si es necesario pero me aseguro

h->izq=NULL;

h->der=NULL;

h->SoloLectura=false;

h->Texto=NULL;

insertar_hijo_file(&(DIR_ACTUAL->primer_hijo_file), h);

prompt("OK");

}

//comando contiene el nombre del archivo, no se modifica,

NODO_FILE **busca_file_puntero(char *comando, NODO_FILE **p){ //recusivo, idem busca_dir excepto NODO_FILE en vez de NODO_DIR; toma dirección y devuelve dirección para poder modificar el padre. Esta funcion la usa delete

int c=0;

if ((*p) == NULL) return NULL;

c = strcmp((*p)->Nombre,comando);

if (c==0) return p;

if (c>0)

return busca_file_puntero(comando, &((*p)->izq));

else

return busca_file_puntero(comando, &((*p)->der));

}

//comando contiene el nombre de archivo a borrar

//la funcion modifica el sistema

void _delete(char *comando){

//para modificar un nodo necesito modificar la referencia a él en su padre, o sea padre->der o padre->izq

// por eso paso la dirección

NODO_FILE **p = NULL;

if (NoExiste_DIR_ACTUAL()) return;

p=busca_file_puntero(comando, &(DIR_ACTUAL->primer_hijo_file));

if (p == NULL)

prompt("no existe el archivo");

else if ((*p)->SoloLectura)

prompt("el archivo es de solo lectura");

else

{

eliminar_1_file(p);

prompt("OK");

}

}

//comando contiene 2 tokens. que son el nombre del archivo y el modificador

// la función modifica comando para separar esos tokens

void attrib(char *comando){

NODO_FILE *p = NULL;

char *l = NULL; //espacio que separa archivo de atributo

bool QueSeaSoloLectura = false;

if (NoExiste_DIR_ACTUAL()) return;

//hay que dividir comando en tokens

l=strchr(comando,' '); //archivo

if (l == NULL) {

prompt("error de sintaxis, faltan argumentos");

return;

}

if (strcmp(l," +w")==0) //l apunta al espacio

QueSeaSoloLectura = false;

else if (strcmp(l," -w")==0)

QueSeaSoloLectura = true;

else {

prompt("error de sintaxis, +w o -w");

return;

}

*l=0; //dejo solo el nombre de archivo, strcpy va a parar en el 0

p=busca_file(comando, DIR_ACTUAL->primer_hijo_file);

if (p == NULL)

prompt("no existe");

else {

p->SoloLectura = QueSeaSoloLectura;

prompt("OK");

}

return;

}

//comando contiene 2 tokens. que son el nombre del archivo y el modificador

// la funcion modifica comando para separar esos tokens, por eso no podemos llamarla con una cadena literal

void it(char *comando){

NODO_FILE *p = NULL;

char *l = NULL;

char *m = NULL;

if (NoExiste_DIR_ACTUAL()) return;

//hay que dividir comando en tokens

l=strchr(comando,' '); //archivo

if (l != NULL) {

*l = 0; //en comando dejo solo el nombre de archivo, strcmp se detiene en el 0

l++; //el texto comienza luego del espacio

if (strlen(l) > TEXTO_MAX) //l apunta al texto

*(l + TEXTO_MAX + 1) = 0; //strdup se detiene en el 0; no hay peligro de escribir el 0 más allá del espacio asignado a comando porque strlen(l + 1) se detiene en el 0 escrito por scanf

m = strdup(l); //saltear el espacio.

}

p = busca_file(comando, DIR_ACTUAL->primer_hijo_file);

if (p == NULL) {

prompt("no existe el archivo");

delete m;

}

else if (p->SoloLectura) {

prompt("el archivo es de solo lectura");

delete m;

}

else {

delete p->Texto; //reemplaza por el nuevo o NULL

if (m == NULL && p->Texto!=NULL)

prompt("OK, se borro el texto");

else

prompt("OK");

p->Texto = m;

}

}

// comando contiene el nombre del archivo

void type(char *comando){

NODO_FILE *p = NULL;

if (NoExiste_DIR_ACTUAL()) return;

p=busca_file(comando, DIR_ACTUAL->primer_hijo_file);

if (p == NULL)

prompt("no existe el archivo");

else {

if (p->Texto == NULL)

prompt("no hay texto");

else

prompt(p->Texto);

}

}

//comando no usa el argumento, la pasamos como argumento porque evalua llama a funciones con un argumento

void ayuda(char *comando){

system("cls");

printf("\n\n\t\t\tComandos:\

\n\t fin\

\n\t crearsistema\

\n\t destruirsistema\

\n\t mkdir directorio\

\n\t rmdir directorio\

\n\t cd directorio | cd .. | cd.. | cd RAIZ\

\n\t dir | dir directorio | dir .. | dir..\

\n\t createfile archivo\

\n\t delete archivo\

\n\t attrib archivo +w | attrib archivo -w\

\n\t it archivo texto\

\n\t type archivo\

\n\n\t ayuda\

\n\t prueba \n\n");

print_ancestros(DIR_ACTUAL);

printf(">");

}

//intérprete de comandos

bool evalua(char *comando, const char *accion, void (*proc)(char *))

// proc es un puntero a función, según la acción a realizar pasar como argumento la función que la realiza

//const char *accion --uso const porque los string literals no deben ser modificados, esta "const" impide que la función modofique esa parte de la memoria

{

if (strncmp(comando, accion, strlen(accion))==0){ //comparar sólo los primeros caracteres (que determinan la acción), el resto del string comando son argumentos, strncmp permite fijar cuantos caracteres tiene que comparar

proc(comando + strlen(accion)); //el string argumento comienza luego del string accion, avanzar el puntero a ese punto, lo que le mandamos a las funciones no es un puntero al comienzo de la cadena, que creamos en el main, tiene el mismo nombre pero es otra cadena que esta dentro de la cadena original pero es solo una parte, esa parte son los argumentos que le pasamos a las funciones que realizan las acciones

return true;

}

else

return false;

}

//comando no se usa(evalua llama a funciones con un argumento)

void prueba(char *comando){

char nada[] = "";

char archivo1[] = "archivo1";

char directorio1[] = "directorio1";

char attrib1[] = "archivo1 -w";

char attrib23[] = "archivo23 -w";

char archivo2[] = "archivo2.txt";

char it2[] = "archivo1 este texto no lo tendría que dejar ingresar porque el archivo es de solo lectura";

char it1[] = "archivo2.txt este texto es para probar que no se pase mucho de los 50... y listo";

char type_archivo2[] = "archivo2.txt";

char attrib_archivo12[] = "archivo12 -w";

char cd_directorio1[] = "directorio1";

char archivo11[] = "archivo11.txt";

char archivo12[] = "archivo12";

char archivo13[] = "archivo13";

char directorio11[] = "directorio11";

char directorio12[] = "directorio12";

char cd_directorio12[] = " directorio12";

char archivo121[] = "archivo121";

char archivo122[] = "archivo122";

char cd_RAIZ[] = " RAIZ";

char cd_puntopunto[] = " ..";

char dir_puntopunto[] = " ..";

char cd_directorio13[] = " directorio13";

char cd_directorio14[] = " este es un directorio que no existe";

char delete_archivo12[]="archivo12";

printf("destruirsistema\n");

destruirsistema();

printf("crearsistema\n");

crearsistema(nada);

printf("createfile archivo2.txt\n");

_createfile(archivo2);

printf("createfile archivo1\n");

_createfile(archivo1);

printf("mkdir directorio1\n");

mkdir(directorio1);

printf("attrib archivo1 -w\n");

attrib(attrib1);

printf("attrib archivo123 -w\n");

attrib(attrib23);

printf("it archivo2.txt este texto es para probar que no se pase mucho de los 50... y listo\n");

it(it1);

printf("type archivo2.txt\n");

type(type_archivo2);

printf("cd directorio1\n");

cd(cd_directorio1);

printf("createfile archivo11\n");

_createfile(archivo11);

printf("createfile archivo12\n");

_createfile(archivo12);

printf("mkdir directorio12\n");

mkdir(directorio12);

printf("cd directorio12\n");

cd(cd_directorio12);

printf("mkdir directorio11\n");

mkdir(directorio11);

printf("createfile archivo13\n");

_createfile(archivo13);

printf("cd directorio13\n");

cd(cd_directorio13);

printf("createfile archivo122\n");

_createfile(archivo122);

printf("createfile archivo121\n");

_createfile(archivo121);

printf("dir..\n");

dir(dir_puntopunto);

printf("cd RAIZ\n");

cd(cd_RAIZ);

printf("cd este es un directorio que no existe\n");

cd(cd_directorio14);

printf("cd..\n");

cd(cd_puntopunto);

printf("dir..\n");

dir(dir_puntopunto);

printf("it archivo1 este texto no lo tendría que dejar ingresar porque el archivo es de solo lectura\n");

it(it2);

printf("attrib archivo12 -w\n");

attrib(attrib_archivo12);

printf("delete archivo12\n");

_delete(delete_archivo12);

}

//Desde acá empiezan nuevas funcionalidades agregadas al programa que no son parte de la letra del proyecto

//Esta función busca en el directorio actual, un directorio que empiece con una letra que ingresa el usuario

void letra(char *comando){

NODO_DIR *p = NULL;// se crea una variable puntero de tipo NODO_DIR y se la iguala a NULL

if (NoExiste_DIR_ACTUAL()) return;// primero comprobamos si existe el directorio actual

comando ++; // esto lo que hace es saltear el espacio xq cuando ingresamos el comando ponemos por ejemplo: si queremos buscar los directorios q comienzan con la letra e, ingresamos en la consola letra e, como se ve hay un espacio entonces con el ++ salteamos ese espacio..

p = busca_letra(comando, DIR_ACTUAL->primer_hijo_dir);// a la variable p le asignamos lo que devuelva la función busca, se le pasa como argumento el comando o sea la letra q queremos buscar, y el primer hijo del directorio actual..

if (p == NULL){// esto es solo para q e programa deje de buscar, cuando la función busca encuentra el null q es q se terminaron todos nodos del árbol, devuelve null y por lo tanto se le asigna null a la variable p. por lo tanto entra al if imprime Fin del programa y sale..

prompt("\nFin de la busqueda");

return;

}

}

NODO_DIR *busca_letra(char *comando, NODO_DIR *p){ // función buscar que apunta a nodo Dir.

int c=0;

if (p == NULL) return NULL; // nos indica que es el fin de la búsqueda ya no quedan más nodos en el árbol

c = strncmp(p->Nombre,comando,1); // strncmp comprara dos cadenas hasta cierto número en este caso solo queremos que nos compare la primera letra por eso ponemos un 1,

//Si existe la coincidencia se le asigna cero a la variable c, de lo contrario se le asigna un numero positivo si nodo q se busco fue el de la izquierda y un numero negativo si el nodo que busco fue el de la derecha

if (c==0)

printf(" %s\n",p->Nombre);// si existe coincidencia se le asigna cero a la variable c por lo tanto ingresa en este if y se imprime el nombre del directorio. Luego continúa...

if (c>0)// si no hubo coincidencia y el nodo buscado fue el izquierdo se le asigno un numero positivo a c, por lo cual va a seguir buscando hasta terminar con la rama izquierda, se vuelve a llamar a la función busca se le pasa el comando, letra a buscar y se le pasa ahora el hijo izquierdo.

return busca_letra(comando, p->izq);

else //si no hubo coincidencia y el nodo buscado fue el derecho se le asigno un numero negativo a c, por lo cual va a seguir buscando hasta terminar con la rama derecha, se vuelve a llamar a la función busca se le pasa el comando, letra a buscar y se le pasa ahora el hijo derecho

return busca_letra(comando, p->der);

}


ċ
main.cpp
(2k)
Andrés Franchi,
23 nov. 2015 4:47
ċ
miniFS.cpp
(29k)
Andrés Franchi,
23 nov. 2015 4:47
ċ
miniFS.h
(2k)
Andrés Franchi,
23 nov. 2015 4:48
Comments