/*Escribe el contenido de un buffer (buf_original dado por parámetro) en un fichero o directorio (inodo pasado por argumento) * offset: posicion inicial de escritura con respeccto al inodo (bytes) * nbytes: nº de bytes a escribir * devuelve la cantidad de bytes escritos (si es que ha escrito bytes) */ int mi_write_f(unsigned int ninodo, const void *buf_original, unsigned int offset, unsigned int nbytes) { struct superbloque sbloq; struct inodo inode; inode = leer_inodo(ninodo); unsigned int bfisico; //Para el uso de la función traducir_bloque_inodo unsigned int bytes_escritos; unsigned char buf_bloque[BLOCKSIZE]; memset(buf_bloque, 0, BLOCKSIZE); if ((inode.permisos & 2) != 2) { //Si no tenemos permisos de escritura devolvemos un error printf("ERROR: ficheros.c => mi_write => No se tienen permisos de escritura\n"); return -1; } else { //en caso contrario, escribimos el buffer en la posición indicada //primer bloque lógico a escribir int primerBlogico = offset / BLOCKSIZE; //último bloque lógico a escribir int ultimoBlogico = (offset + nbytes - 1) / BLOCKSIZE; //desplazamientos int desp1 = offset % BLOCKSIZE; //despl. en el primer bloque int desp2 = (offset + nbytes - 1) % BLOCKSIZE; //despl. en el último bloque //caso 1 if (primerBlogico == ultimoBlogico) { /* Hacemos un bread de este bloque (con ayuda de la función traducir_bloque_inodo) * y almacenamos el resultado en un buffer llamado buf_bloque. */ if (traducir_bloque_inodo(ninodo, primerBlogico, &bfisico, 1) == -1) { printf("ERROR: ficheros.c -> mi_write_f => Error al traducir el bloque lógico %d\n", primerBlogico); return -1; } if (bread(bfisico, buf_bloque) == -1) {//leemos el bloque en el que vamos a escribir printf("ERROR: ficheros.c -> mi_write_f => Error al leer el bloque físico %d\n", bfisico); if (bread(posSB, (char *) &sbloq) == -1) printf("\tficheros.c -> mi_write_f => Error al leer el superbloque \n"); else if (sbloq.totBloques < bfisico) printf("\tficheros.c -> mi_write_f => bfisico fuera de rango\n"); return -1; } //Escribimos el contenido de 'buf_original' en la posición correspondiente del buffer memcpy(buf_bloque + desp1, buf_original, nbytes); /*Hacemos un bwrite del buf_bloque (con los nuevos datos, preservando los que contenía), * en el bloque que nos devuelva la función y guardamos la cantidad de bytes escritos */ if (bwrite(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_write_f => (Caso 1) Error al escribir el bloque %d \n", bfisico); } bytes_escritos = nbytes; //devolvemos la cantidad de bytes escritos } else { //caso 2: primerByteLogico != ultimoByteLogico /////tratamiento del primer bloque lógico /* Hacemos un bread de este bloque (con ayuda de la función traducir_bloque_inodo) * y almacenamos el resultado en un buffer llamado buf_bloque. */ if (traducir_bloque_inodo(ninodo, primerBlogico, &bfisico, 1) == -1) { printf("ERROR: ficheros.c -> mi_write_f => Error al traducir el bloque lógico %d\n", primerBlogico); return -1; } if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_write_f => (Tratamiento PBL) Error al leer el bloque %d\n", bfisico); return -1; } memcpy(buf_bloque + desp1, buf_original, BLOCKSIZE - desp1); /*Hacemos un bwrite del buf_bloque (con los nuevos datos, preservando los que contenía), * en el bloque que nos devuelva la función */ bytes_escritos = BLOCKSIZE - desp1; //primeros bytes escritos if (bwrite(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_write_f => (Tratamiento PBL) Error al escribir el bloque %d \n", bfisico); } //tratamiento de los bloques intermedios int i; for (i = primerBlogico + 1; i < ultimoBlogico; i++) { if (traducir_bloque_inodo(ninodo, i, &bfisico, 1) == -1) { printf("ERROR: ficheros.c -> mi_write_f => Error al traducir el bloque lógico %d\n", i); return -1; } //buf_bloque = buf_original + (BLOCKSIZE - desp1) + (i - primerBlogico - 1) * BLOCKSIZE; int var = bwrite(bfisico, buf_original + (BLOCKSIZE - desp1) + (i - primerBlogico - 1) * BLOCKSIZE); //bytes escritos en el bloque intermedio actual if (var != BLOCKSIZE) {//comprobamos si se ha escrito el bloque al completo printf("ERROR: ficheros.c -> mi_write_f => (Tratamiento bloques intermedios) No se ha escrito el bloque %d al completo\n", bfisico); } bytes_escritos = bytes_escritos + var; //sumamos los bytes escritos en este bloque intermedio } //tratamiento del último bloque if (traducir_bloque_inodo(ninodo, ultimoBlogico, &bfisico, 1) == -1) { printf("ERROR: ficheros.c -> mi_write_f => Error al traducir el bloque lógico %d\n", ultimoBlogico); return -1; } if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_write_f => (Tratamiento UBL) Error al leer el bloque %d \n", bfisico); return -1; } memcpy(buf_bloque, buf_original + (nbytes - desp2 - 1), desp2 + 1); if (bwrite(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_write_f => (Tratamiento UBL) Error al escribir el bloque %d \n", bfisico); } bytes_escritos = bytes_escritos + desp2 + 1; } //Finalmente y en todo caso: //Leemos el inodo inode = leer_inodo(ninodo); //Actualizar el tamaño en bytes lógicos si hemos escrito más allá del final del fichero if (inode.tamEnBytesLog < offset + bytes_escritos) {//En el caso de que tengamos que aumentar el tamaño del fichero inode.tamEnBytesLog = offset + bytes_escritos; //actualizamos el tamaño de bytes lógicos de la metainformación } //actualizar mtime y el ctime inode.ctime = time(NULL); inode.mtime = time(NULL); //Escribir el inodo if (escribir_inodo(inode, ninodo) == -1) { printf("ERROR: ficheros.c -> mi_write_f => Error al escribir inodo %d \n", ninodo); return -1; } } return bytes_escritos; //si todo va bien bytes_escritos=nbytes }
int mi_read_f(unsigned int ninodo, void *buf_original, unsigned int offset, unsigned int nbytes) { struct inodo inode; inode = leer_inodo(ninodo); unsigned int bfisico; //Para el uso de la función traducir_bloque_inodo unsigned int bytes_leidos = 0; unsigned int desp_buffer = 0; //bytes_leidos sin contar los bloques vacíos unsigned char buf_bloque[BLOCKSIZE]; memset(buf_bloque, 0, BLOCKSIZE); if ((inode.permisos & 4) != 4) { //Si no tenemos permisos de lectura devolvemos un error printf("ERROR: ficheros.c => mi_read_f => No se tienen permisos de lectura\n"); return -1; } else { //en caso contrario, leemos el buffer en la posición indicada if (offset + nbytes >= inode.tamEnBytesLog) { nbytes = inode.tamEnBytesLog - offset; // leemos sólo los bytes que podemos desde el offset hasta el final de fichero } if (offset > inode.tamEnBytesLog) { nbytes = 0; return nbytes; //no leemos nada } int primerBlogico = offset / BLOCKSIZE; //primer byte lógico a leer int ultimoBlogico = (offset + nbytes - 1) / BLOCKSIZE; //último byte lógico a leer //desplazamientos int desp1 = offset % BLOCKSIZE; //despl. en el primer bloque int desp2 = (offset + nbytes - 1) % BLOCKSIZE; //despl. en el último bloque //caso 1 if (primerBlogico == ultimoBlogico) { int resultado_traducir = traducir_bloque_inodo(ninodo, primerBlogico, &bfisico, 0); if (resultado_traducir == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al traducir el bloque lógico %d\n", primerBlogico); return -1; } if (resultado_traducir == -2) {//bloque lógico vacío bytes_leidos = nbytes; //lo indicamos como leído pero no pasamos nada al buffer de salida } else {//sino leemos y pasamos el contenido al buffer if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al leer el bloque %d\n", bfisico); return -1; } memcpy(buf_original, buf_bloque + desp1, nbytes); //copiamos el contenido en el buffer de salida bytes_leidos = nbytes; } } else { //caso 2 primerBloqueLogico != ultimoBloqueLogico //tratamiento del primer bloque lógico int resultado_traducir = traducir_bloque_inodo(ninodo, primerBlogico, &bfisico, 0); if (resultado_traducir == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al traducir el bloque lógico %d\n", primerBlogico); return -1; } if (resultado_traducir == -2) {//bloque lógico vacío bytes_leidos = BLOCKSIZE - desp1; //lo indicamos como leído pero no pasamos nada al buffer de salida ni desplazamos el puntero } else {//leemos el primer bloque if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_read_f => (Tratamiento PBL) Error al leer el bloque %d\n", bfisico); return -1; } memcpy(buf_original, buf_bloque + desp1, BLOCKSIZE - desp1); //guardamos los bytes leídos en el buffer de salida bytes_leidos = BLOCKSIZE - desp1; //guardamos la cantidad de bytes leidos desp_buffer = bytes_leidos; //posición del puntero de buf_original } //tratamiento de los bloques intermedios int i; for (i = primerBlogico + 1; i < ultimoBlogico; i++) { int resultado_traducir = traducir_bloque_inodo(ninodo, primerBlogico, &bfisico, 0); if (resultado_traducir == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al traducir el bloque lógico intermedio %d\n", i); return -1; } if (resultado_traducir == -2) {//bloque lógico vacío bytes_leidos = bytes_leidos + BLOCKSIZE; //lo indicamos como leído pero no pasamos nada al buffer de salida ni desplazamos el puntero } else {//leemos el bloque if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_read_f => (Tratamiento bloques intermedios) Error al leer el bloque %d\n", bfisico); return -1; } memcpy(buf_original + desp_buffer, buf_bloque, BLOCKSIZE); //guardamos los bytes leídos en el buffer de salida bytes_leidos = bytes_leidos + BLOCKSIZE; //guardamos la cantidad de bytes leidos desp_buffer = desp_buffer + BLOCKSIZE; //actualizamos la posición del puntero de buf_original } } //tratamiento del último bloque resultado_traducir = traducir_bloque_inodo(ninodo, ultimoBlogico, &bfisico, 0); if (resultado_traducir == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al traducir el bloque lógico %d\n", ultimoBlogico); return -1; } if (resultado_traducir == -2) {//bloque lógico vacío bytes_leidos = desp2 + 1; //lo indicamos como leído pero no pasamos nada al buffer de salida ni desplazamos el puntero } else {//leemos el primer bloque if (bread(bfisico, buf_bloque) == -1) { printf("ERROR: ficheros.c -> mi_read_f => (Tratamiento PBL) Error al leer el bloque %d\n", bfisico); return -1; } memcpy(buf_original, buf_bloque, desp2 + 1); //guardamos los bytes leídos en el buffer de salida bytes_leidos = bytes_leidos + desp2 + 1; //guardamos la cantidad de bytes leidos } } //Finalmente y en todo caso: //Leemos el inodo inode = leer_inodo(ninodo); //actualizar sellos de tiempo inode.ctime = time(NULL); inode.mtime = time(NULL); inode.atime = time(NULL); //Escribir el inodo if (escribir_inodo(inode, ninodo) == -1) { printf("ERROR: ficheros.c -> mi_read_f => Error al escribir inodo %d \n", ninodo); return -1; } } return bytes_leidos; }
int mi_write_f(unsigned int ninodo, const void *buf_original, unsigned int offset, unsigned int nbytes){ struct inodo Inodo = leer_inodo(ninodo); int bytesEscritos = 0; unsigned int primerLogico = offset/BLOCKSIZE; unsigned int ultimoLogico = (offset+nbytes-1)/BLOCKSIZE; if ((Inodo.permisos & 2) != 2) { printf("No tienes permisos de escritura.\n"); return -1; } if(primerLogico == ultimoLogico){ // Un unico bloque modificado unsigned char bufBloque[BLOCKSIZE]; memset(bufBloque, 0, sizeof(bufBloque)); int desp1 = offset%BLOCKSIZE; int bFisico = traducir_bloque_inodo(ninodo, primerLogico, 1); //reserva del bloque fisico if(bread(bFisico, bufBloque) < 0){ return -1; } memcpy(bufBloque+desp1, buf_original, nbytes); int incremento; if((incremento = bwrite(bFisico, &bufBloque)) < 0){ return -1; } bytesEscritos += incremento; }else{ // Primer bloque int desp = 0; unsigned char bufBloque[BLOCKSIZE]; memset(bufBloque, 0, sizeof(bufBloque)); int desp1 = offset%BLOCKSIZE; int bFisico = traducir_bloque_inodo(ninodo, primerLogico, 1); //reserva del bloque fisico if(bFisico < 0) return bytesEscritos; if(bread(bFisico, bufBloque) < 0) return -1; memcpy(bufBloque+desp1, buf_original, BLOCKSIZE-desp1); int incremento; if((incremento = bwrite(bFisico, &bufBloque)) < 0){ return -1; } desp += desp1; bytesEscritos += incremento; // Bloques intermedios int i; for(i = primerLogico + 1; i < ultimoLogico; i++){ bFisico = traducir_bloque_inodo(ninodo, i, 1); if(bFisico < 0) return bytesEscritos; memcpy(bufBloque, buf_original + (BLOCKSIZE - desp1) + (i - primerLogico - 1) * BLOCKSIZE, BLOCKSIZE); int incremento; if((incremento = bwrite(bFisico, &bufBloque)) < 0){ return -1; } bytesEscritos += incremento; } // Último bloque int desp2 = (offset+nbytes-1)%BLOCKSIZE; bFisico = traducir_bloque_inodo(ninodo, ultimoLogico, 1); if(bFisico < 0) return bytesEscritos; if(bread(bFisico, &bufBloque) < 0){ return -1; } memcpy(bufBloque, buf_original + (nbytes - desp2 - 1), desp2 + 1); if((incremento = bwrite(bFisico, &bufBloque)) < 0){ return -1; } bytesEscritos += incremento; } // Actualizar informacion del inodo Inodo = leer_inodo(ninodo); if(offset+nbytes > Inodo.tamEnBytesLog){ Inodo.tamEnBytesLog = offset + nbytes; } Inodo.mtime = time(NULL); Inodo.ctime = time(NULL); if(escribir_inodo(Inodo, ninodo) < 0){ return -1; } return bytesEscritos; }
int mi_read_f(unsigned int ninodo, void *buf, unsigned int offset, unsigned int nbytes){ struct inodo Inodo = leer_inodo(ninodo); if(!(Inodo.permisos & 4)){ printf("Error: no tiene los permisos necesarios\n"); return -1; } if(offset + nbytes > Inodo.tamEnBytesLog){ //si se quiere leer mas de lo que ocupa el fichero nbytes = Inodo.tamEnBytesLog - offset; } if(offset >= Inodo.tamEnBytesLog){ //Se quiere leer mas alla del final de fichero nbytes = 0; return nbytes; } int bFisico = 0; unsigned int primerLogico = offset/BLOCKSIZE; unsigned int ultimoLogico = (offset+nbytes-1)/BLOCKSIZE; unsigned char buffer[BLOCKSIZE]; memset(buffer, 0, sizeof(buffer)); int bytesleidos = 0; if(primerLogico == ultimoLogico){ //se lee un unico bloque bFisico = traducir_bloque_inodo(ninodo, primerLogico, 0); if(bread(bFisico, &buffer) < 0){ return -1; } int desp1 = offset % BLOCKSIZE; memcpy(buf, buffer+desp1, nbytes); bytesleidos += nbytes; }else{ // Hay que leer varios bloques // Primer bloque bFisico = traducir_bloque_inodo(ninodo, primerLogico, 0); if(bread(bFisico, &buffer) < 0){ return -1; } int desp1 = offset % BLOCKSIZE; memcpy(buf, buffer + desp1, BLOCKSIZE - desp1); bytesleidos += BLOCKSIZE - desp1; memset(buffer, 0, sizeof(buffer)); // Bloques intermedios int i; for(i = primerLogico + 1; i < ultimoLogico; i++){ bFisico = traducir_bloque_inodo(ninodo, i, 0); if(bread(bFisico, &buffer) < 0){ return -1; } memcpy(buf + bytesleidos, buffer, BLOCKSIZE); bytesleidos += BLOCKSIZE; memset(buffer, 0, sizeof(buffer)); } // Ultimo bloque int desp2 = (offset + nbytes - 1) % BLOCKSIZE; bFisico = traducir_bloque_inodo(ninodo, ultimoLogico, 0); if(bread(bFisico, &buffer) < 0){ return -1; } memcpy(buf + bytesleidos, buffer, desp2 + 1); bytesleidos += desp2 + 1; } Inodo = leer_inodo(ninodo); Inodo.atime = time(NULL); if(escribir_inodo(Inodo, ninodo) < 0){ return -1; } return bytesleidos; }
int mi_truncar_f(unsigned int ninodo, unsigned int nbytes) { // Creamos una estructura inodo. struct inodo Inodo; // Leemos el inodo indicado por parámetro. Inodo = leer_inodo(ninodo); if (nbytes > Inodo.tamEnBytesLog) { printf("ERROR -> No se ha podido truncar el fichero por sobrepasar su tamaño.\n"); return -1; } // Si el número de bytes es 0, vaciamos el fichero. if (nbytes == 0) { liberar_inodo(ninodo); Inodo.tamEnBytesLog = nbytes; if (escribir_inodo(Inodo, ninodo) == -1) { return -1; } }// Si no... else if (nbytes > 0) { // Calculamos el último bloque a truncar. int ultimoblogico = Inodo.tamEnBytesLog / BLOCKSIZE; // Si el tamaño en bytes lógicos del inodo es múltiplo del tamaño de bloque // decrementamos la variable ultimoblogico. if ((Inodo.tamEnBytesLog % BLOCKSIZE) == 0) { ultimoblogico--; } // Calculamos el último bloque que conservamos. int bloq_queda = nbytes / BLOCKSIZE; // Si el número de bytes es múltiplo de tamaño de bloque, decrementamos // la variable bloq_queda. if (nbytes % BLOCKSIZE == 0) { bloq_queda--; } unsigned int bfisico; int i = 0; char reservar = '0'; // Iteramos para todos los bloques que queremos liberar. for (i = bloq_queda + 1; i <= ultimoblogico; i++) { // Obtenemos el bloque físico. bfisico = traducir_bloque_inodo(ninodo, i, reservar); // Si no es el bloque raíz (SUPERBLOQUE)... if (bfisico > 0) { if (liberar_bloque(bfisico) == -1) { printf("ERROR -> No se ha liberado el bloque.\n"); return -1; } // Decrementamos los bloques ocupados. Inodo.numBloquesOcupados--; } // Si estamos en el último bloque y no ocupa el bloque entero... if ((i == ultimoblogico) && (Inodo.tamEnBytesLog % BLOCKSIZE != 0)) { // Truncamos el trozo del bloque. Inodo.tamEnBytesLog = Inodo.tamEnBytesLog - (Inodo.tamEnBytesLog % BLOCKSIZE); } else { // Truncamos todo el bloque. Inodo.tamEnBytesLog = Inodo.tamEnBytesLog - BLOCKSIZE; } } Inodo.tamEnBytesLog = nbytes; if (escribir_inodo(Inodo, ninodo) == -1) { return -1; } } return 0; }