]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/idx.c
Bugfix. En borrar_registro() se complica poner en cero la basura del final.
[z.facultad/75.06/emufs.git] / emufs / idx.c
1 /* vim: set noexpandtab tabstop=4 shiftwidth=4:
2  *----------------------------------------------------------------------------
3  *                                  emufs
4  *----------------------------------------------------------------------------
5  * This file is part of emufs.
6  *
7  * emufs is free software; you can redistribute it and/or modify it under the
8  * terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version.
11  *
12  * emufs is distributed in the hope that it will be useful, but WITHOUT ANY
13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with emufs; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place, Suite 330, Boston, MA  02111-1307  USA
20  *----------------------------------------------------------------------------
21  * Creado:  jue abr  8 18:10:35 ART 2004
22  * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23  *          Leandro Lucarella <llucare@fi.uba.ar>
24  *----------------------------------------------------------------------------
25  *
26  * $Id$
27  *
28  */
29
30 /** \file
31  *
32  * Manejo de archivos de índice de registros.
33  * 
34  * Implementación del manejo de archivos de índice de registros.
35  *
36  */
37
38 #include "idx.h"
39 #include "did.h"
40 #include "error.h"
41 #include "common.h"
42 #include <stdlib.h>
43 #include <strings.h>
44 #include <unistd.h>
45
46 /* Objetivo: Realiza una apertura de un archivo indice y devuelve el handler. */
47 FILE* emufs_idx_abrir(EMUFS* efs, const char* mode)
48 {
49         FILE* f;
50         char* filename;
51
52         filename = (char*) malloc(sizeof(char) * (strlen(efs->nombre)
53                                 + strlen(EMUFS_IDX_EXT) + 1));
54         if (filename == NULL) {
55                 /* TODO Manejo de errores */
56                 return NULL;
57         }
58         strcpy(filename, efs->nombre);
59         strcat(filename, EMUFS_IDX_EXT);
60         f = fopen(filename, mode);
61         free(filename);
62         return f;
63 }
64
65 /* Crea un archivo indice de registros */
66 int emufs_idx_crear(EMUFS *efs)
67 {
68         return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_IDX_EXT);
69 }
70
71 /* Devuelve el mayor id de registro utilizado so far en el archivo de datos, revisando el indice. */
72 EMUFS_REG_ID emufs_idx_buscar_mayor_id_libre(EMUFS* emu, int* err)
73 {
74         EMUFS_REG_ID max = 0;
75         FILE* f_idx;    
76         EMUFS_IDX reg;
77         char name_f_idx[255]; /* TODO usar malloc para no limitar el tamaño de nombre de archivo */
78         int found = 0;
79
80         strcpy(name_f_idx, emu->nombre);
81         strcat(name_f_idx, EMUFS_IDX_EXT);
82
83         if ((f_idx = fopen(name_f_idx, "rb")) == NULL) {
84                 PERR("No se puede abrir archivo");
85                 *err = EMUFS_ERROR_CANT_OPEN_FILE;
86                 return EMUFS_NOT_FOUND;
87         }
88
89         /* Voy a la ultima entrada */
90         if (fseek(f_idx, -sizeof(EMUFS_IDX), SEEK_END) != 0) {
91                 fclose(f_idx);
92                 return 0;
93         }
94         
95         if (fread(&reg, sizeof(EMUFS_IDX), 1, f_idx) == 1) {
96                 found = 1;
97                 max = reg.id_reg;
98         }
99         fclose(f_idx);
100         
101         if (found) {
102                 return ++max;
103         } else {
104                 return 0;
105         }
106 }
107
108 /* busca el registro ID en el archivo ".idx" y devuelve el nro de bloque en el que se encuentra */
109 EMUFS_BLOCK_ID emufs_idx_buscar_registro(EMUFS *emu, EMUFS_REG_ID reg_id)
110 {
111         FILE* f_idx;
112         EMUFS_IDX reg;
113         char name_f_idx[255];
114         
115         strcpy(name_f_idx,emu->nombre);
116         strcat(name_f_idx, EMUFS_IDX_EXT);
117         
118         if ((f_idx = fopen(name_f_idx, "rb")) == NULL) {
119                 PERR("No se puede abrir archivo");
120                 /* *err = EMUFS_ERROR_CANT_OPEN_FILE; */
121                 return EMUFS_NOT_FOUND;
122         }
123
124         /* Me muevo a la posicion pedida */
125         if (fseek(f_idx, sizeof(EMUFS_IDX)*reg_id, SEEK_SET) == 0) {
126                 if (fread(&reg, sizeof(EMUFS_IDX), 1, f_idx) == 1) {
127                         fclose(f_idx);
128                         return reg.location;
129                 }
130         }
131         fclose(f_idx);
132
133         return EMUFS_NOT_FOUND;
134 }
135
136 int emufs_idx_agregar(EMUFS *emu, EMUFS_REG_ID id_reg, EMUFS_BLOCK_ID location)
137 {
138         FILE *f_idx;
139         EMUFS_IDX reg;
140         char name_f_idx[255];
141         
142         strcpy(name_f_idx,emu->nombre);
143         strcat(name_f_idx, EMUFS_IDX_EXT);
144
145         if ( (f_idx = fopen(name_f_idx,"r+"))==NULL ) return -1;
146
147         fseek(f_idx, sizeof(EMUFS_IDX)*id_reg, SEEK_SET); 
148         reg.id_reg = id_reg;
149         reg.location = location;
150         fwrite(&reg,sizeof(EMUFS_IDX),1,f_idx); 
151         fclose(f_idx);
152
153         return 0;
154 }
155
156 /* Borra un registro del indice dada la eliminacion fisica de un reg */
157 int emufs_idx_borrar(EMUFS *emu, EMUFS_REG_ID idreg)
158 {
159         FILE *f_idx;
160         EMUFS_IDX reg;
161         char name_f_idx[255];
162         
163         strcpy(name_f_idx,emu->nombre);
164         strcat(name_f_idx, EMUFS_IDX_EXT);
165
166         if ( (f_idx = fopen(name_f_idx,"r+"))==NULL ) return 1;
167
168         if (fseek(f_idx, sizeof(EMUFS_IDX)*idreg, SEEK_SET) == 0) {
169                 reg.id_reg = idreg;
170                 reg.location = EMUFS_NOT_FOUND;
171                 fwrite(&reg, sizeof(EMUFS_IDX), 1, f_idx);
172         }
173         fclose(f_idx);
174         
175         return 0;
176 }
177
178 EMUFS_REG_ID emufs_idx_get_new_id(EMUFS* efs, int* err)
179 {
180         EMUFS_REG_ID id;
181
182         id = emufs_did_get_last(efs, err);
183         if (id == EMUFS_NOT_FOUND) {
184                 if (*err) {
185                         PERR("error al obtener ultimo id");
186                         return id;
187                 }
188                 id = emufs_idx_buscar_mayor_id_libre(efs, err);
189                 if (*err) {
190                         PERR("error al obtener id mayor");
191                         return EMUFS_NOT_FOUND;
192                 }
193         }
194
195         return id;      
196 }
197
198 EMUFS_REG_ID *emufs_idx_get(EMUFS *emu, EMUFS_REG_ID *cant)
199 {
200         FILE *f_idx;
201         int count;
202         char name_f_idx[255];
203         EMUFS_REG_ID *tmp;
204         EMUFS_IDX reg;
205         
206         strcpy(name_f_idx,emu->nombre);
207         strcat(name_f_idx, EMUFS_IDX_EXT);
208
209         if ( (f_idx = fopen(name_f_idx, "rb"))==NULL){
210                 PERR("No se pudo abrir el archvo");
211                 (*cant) = EMUFS_NOT_FOUND;
212                 return NULL;
213         }
214
215         tmp = NULL;
216         count = 0;
217         while (!feof(f_idx)) {
218                 if (fread(&reg, sizeof(EMUFS_IDX), 1, f_idx) != 1) continue;
219                 if (reg.location != EMUFS_NOT_FOUND) {
220                         count++;
221                         tmp = realloc(tmp, count*sizeof(EMUFS_REG_ID));
222                         tmp[count-1] = reg.id_reg;
223                 }
224         }
225         fclose(f_idx);
226
227         (*cant) = count;
228         return tmp;
229 }
230
231 /** @todo FIXME borrar cuando se cambie emufs_gui/registros.c que es el unico
232  * que lo usa.
233  * @deprecated Usar emufs_idx_buscar_registro.
234  */
235 int emufs_idx_existe_id(EMUFS *emu, int ID)
236 {
237         FILE *f_idx;
238         char name_f_idx[255];
239         EMUFS_IDX reg;
240         
241         strcpy(name_f_idx,emu->nombre);
242         strcat(name_f_idx, EMUFS_IDX_EXT);
243
244         if ( (f_idx = fopen(name_f_idx, "rb")) == NULL){
245                 PERR("No se pudo abrir el archivo");
246                 return -1;
247         }
248         
249         if (fseek(f_idx, sizeof(EMUFS_IDX)*ID, SEEK_SET) == 0) {
250                 fread(&reg, sizeof(EMUFS_IDX), 1, f_idx);
251                 if (reg.location != EMUFS_NOT_FOUND) {
252                         fclose(f_idx);
253                         return 0;
254                 }
255         }
256         fclose(f_idx);
257         return -1;/*no existe el id*/
258 }
259
260 int emufs_idx_actualizar(EMUFS *emu, int ID, EMUFS_BLOCK_ID bloque)
261 {
262         FILE *f_idx;
263         char name_f_idx[255];
264         EMUFS_IDX reg;
265         
266         strcpy(name_f_idx,emu->nombre);
267         strcat(name_f_idx, EMUFS_IDX_EXT);
268
269         if ( (f_idx = fopen(name_f_idx, "r+")) == NULL){
270                 PERR("No se pudo abrir el archivo");
271                 return -1;
272         }
273         fseek(f_idx,0,SEEK_SET);
274         fseek(f_idx,ID*sizeof(EMUFS_IDX),SEEK_SET);
275         fread(&reg,sizeof(EMUFS_IDX),1,f_idx);
276         reg.location = bloque;
277         fseek(f_idx,-sizeof(EMUFS_IDX),SEEK_CUR);
278         fwrite(&reg,sizeof(EMUFS_IDX),1,f_idx);
279         fclose(f_idx);
280         return 0;
281 }
282
283 long emufs_idx_get_file_size(EMUFS* efs, int* err)
284 {
285         char name[255];
286         strcpy(name, efs->nombre);
287         strcat(name, EMUFS_IDX_EXT);
288         return emufs_common_get_file_size(name, err);
289 }
290