]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/tipo2.c
* Agrego menues que se van a usar pronto
[z.facultad/75.06/emufs.git] / emufs / tipo2.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:  Fri Apr 10 17:10:00 ART 2004
22  * Autores: Alan Kennedy <kennedya@3dgames.com.ar>
23  *----------------------------------------------------------------------------
24  *
25  * $Id: tipo3.c 85 2004-04-08 23:39:28Z sagar $
26  *
27  */
28
29 /***************************************************************/
30 /* Implementación del Tipo Archivo 2: Registros Variables, Sin */
31 /* Bloques at all.                                             */
32 /***************************************************************/
33
34 #include "tipo2.h"
35 #include "idx.h"
36 #include "fsc.h"
37 #include "did.h"
38
39 /* Asigna los punteros a las funciones apropiadas para el Tipo2 */
40 int emufs_tipo2_inicializar(EMUFS* efs)
41 {
42         efs->grabar_registro = emufs_tipo2_grabar_registro;           
43     efs->borrar_registro = emufs_tipo2_borrar_registro;
44         efs->leer_registro = emufs_tipo2_leer_registro;
45         
46         return 0;
47 }
48
49 /**********************************************************************/
50 /* void *emufs_tipo2_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,   */
51 /*                      EMUFS_REG_SIZE* reg_size, int *err)                        */
52 /* Objetivo: Lee un registro de un archivo del Tipo 2.                */
53 /* Parametros: EMUFS *efs // Struct con handlers + info del openfile. */
54 /*             EMUFS_REG_ID reg_id // Id del registro a cargar        */
55 /*             EMUFS_REG_SIZE *reg_size // Size del reg en cuestion   */
56 /*             int *err // Indicador de errores                       */
57 /**********************************************************************/
58 void *emufs_tipo2_leer_registro(EMUFS* efs, EMUFS_REG_ID reg_id,
59                         EMUFS_REG_SIZE* reg_size, int *err)
60 {
61         FILE* f_data;
62         char *registro; /* registro a leer */
63         char  name_f[255];      
64         EMUFS_OFFSET reg_offset; /* offset donde se encuentra el registro */
65         
66         strcpy(name_f,efs->nombre);
67         strcat(name_f,".dat");
68
69         /* Obtenemos la posicion del registro en el .dat */
70         reg_offset = emufs_idx_buscar_registro(efs, reg_id);
71         if (reg_offset == EMUFS_NOT_FOUND) {
72                 /* TODO Manejo de errores */
73                 PERR("Registro no encontrado");
74                 *err = EMUFS_NOT_FOUND;
75                 return NULL;
76         }
77         
78         /* Levantamos el registro */
79         if ((f_data = fopen(name_f, "rb")) == NULL) {
80                 PERR("No se puede abrir archivo");
81                 *err = 4; /* EMUFS_ERROR_CANT_OPEN_FILE */
82                 return NULL; /* FIXME ERROR */
83         }
84         fseek(f_data,reg_offset+sizeof(EMUFS_REG_ID),0);
85         fread(reg_size,sizeof(EMUFS_REG_SIZE),1,f_data);
86         registro = (char*)malloc(*reg_size);
87         fread(registro,*reg_size,1,f_data);
88         fclose(f_data);
89         
90         return registro;
91 }
92
93 /**********************************************************************/
94 /* EMUFS_REG_ID emufs_tipo2_grabar_registro(EMUFS *efs, void *ptr,    */
95 /*                                 EMUFS_REG_SIZE n_RegSize)          */
96 /* Objetivo: Grabar un registro en un archivo del Tipo 2.             */
97 /* Parametros: EMUFS *efs // Struct con handlers + info del openfile. */
98 /*             void *ptr // Puntero al buffer (registro) a guardar    */
99 /*             EMUFS_REG_SIZE n_RegSize // Size del reg en cuestion   */
100 /**********************************************************************/
101 EMUFS_REG_ID emufs_tipo2_grabar_registro(EMUFS *efs, void *ptr, EMUFS_REG_SIZE reg_size, int* err)
102 {
103         EMUFS_REG_ID id_reg;
104         EMUFS_FREE freespace;
105         EMUFS_OFFSET wrt_offset,reg_offset;
106         unsigned long int fisic_size;
107         FILE *f_data;
108         char name_f[255];
109         
110         /* Armamos el filename del archivo de datos */
111         strcpy(name_f,efs->nombre);
112         strcat(name_f,".dat");
113         
114         if ( (f_data = fopen(name_f,"r+"))==NULL ) return -1; /*ERROR*/
115         
116         /* Obtengo un offset en donde iniciar la escritura de mi registro */
117         /* de manera segura (habra espacio suficiente) */
118         fisic_size = sizeof(EMUFS_REG_ID)+sizeof(EMUFS_REG_SIZE)+reg_size;
119         wrt_offset = emufs_fsc_buscar_lugar(efs,fisic_size,&freespace);
120         /*printf("tipo2.c >> Recording Reg > Searching FSC: Offset = %lu FSpace: %lu\n", n_WrtOffset, n_FreeSpace);*/
121         
122         /* Si no encontre un gap, entonces escribo el registro al final */
123         if (wrt_offset == -1) {                
124                 
125                 /* Obtengo un ID libre para el registro y luego grabo a disco */
126         id_reg = emufs_idx_get_new_id(efs, err);
127                 fseek(f_data, 0, SEEK_END);
128                 reg_offset = ftell(f_data);
129
130                 /* Escribo [RegId]|[RegSize]|[RegData] */
131                 fwrite(&id_reg,sizeof(EMUFS_REG_ID),1,f_data);
132                 fwrite(&reg_size,sizeof(EMUFS_REG_SIZE),1,f_data);
133                 fwrite(ptr,reg_size,1,f_data);
134                                 
135                 /* Bye */
136                 /*printf("Tipo2.c >> RegNr: %lu with FisicSize: %lu inserted at Offset: %lu\n",n_IdReg,n_FisicSize,n_RegOffset);*/
137                 fclose(f_data);
138                 
139         } else {
140                 
141                 /* Obtengo un ID libre para el registro y luego grabo en disco */
142         id_reg = emufs_idx_get_new_id(efs, err);
143                 reg_offset = wrt_offset;
144                 fseek(f_data,reg_offset,0);
145                 
146         /* Escribo [RegId]|[RegSize]|[RegData] */
147                 fwrite(&id_reg,sizeof(EMUFS_REG_ID),1,f_data);
148                 fwrite(&reg_size,sizeof(EMUFS_REG_SIZE),1,f_data);
149                 fwrite(ptr,reg_size,1,f_data);
150                                 
151                 /* Bye */
152                 /*printf("Tipo2.c >> RegNr: %lu with FisicSize: %lu inserted at Offset: %lu\n",n_IdReg,n_FisicSize,n_RegOffset);*/
153                 fclose(f_data);
154                 
155                 /* Actualizo el espacio libre en el GAP donde puse el registro */
156                 if ((freespace-fisic_size) == 0) emufs_fsc_remove_gap(efs,reg_offset);
157                 else emufs_fsc_actualizar_gap(efs,reg_offset,freespace-fisic_size);             
158         }
159                 
160         /* Finalmente, actualizamos el indice de registros (offsets) */
161         emufs_idx_agregar(efs,id_reg,reg_offset);
162                 
163         return id_reg;
164 }
165
166 /**********************************************************************/
167 /* int emufs_tipo2_borrar_registro(EMUFS *efs, EMUFS_REG_ID n_IdReg)  */
168 /* Objetivo: Borra un registro determinado y actualiza los archivos   */
169 /*           de Posicion Relativa (Indice-Offset) y el de Gaps        */
170 /* Parametros: EMUFS *efs // Struct con handlers + info del openfile. */
171 /*             EMUFS_REG_ID n_IdReg // Id del registro a eliminar.    */
172 /**********************************************************************/
173 int emufs_tipo2_borrar_registro(EMUFS *efs, EMUFS_REG_ID id_reg)
174 {       
175         EMUFS_OFFSET reg_offset,reg_size;
176          
177         /* Obtenemos el offset donde arranca el registro */
178         if ((reg_offset = emufs_idx_buscar_registro(efs,id_reg)) == EMUFS_NOT_FOUND) {
179                 /* TODO Manejo de errores */
180                 PERR("Registro no encontrado");
181                 return EMUFS_NOT_FOUND;
182         }
183         
184         /* Obtenemos el Size del Registro en cuestion y hacemos un dummyfill*/
185         emufs_tipo2_get_regsize(efs,reg_offset,&reg_size);      
186         emufs_tipo2_dummyfill(efs,reg_offset,reg_size);
187                 
188         /* Agregamos el GAP en el archivo de FSC, el cual hara un merge con */
189         /* otro GAP por delante y/o por detras en caso de hallarlo. */
190         emufs_fsc_agregar_gap(efs,reg_offset,reg_size+sizeof(EMUFS_REG_ID)+sizeof(EMUFS_REG_SIZE));
191         
192         /* Agrego el ID que se ha liberado al archivo de ID's Libres */
193         emufs_did_agregar(efs,id_reg);  
194         
195         /* Borramos el registro del indice de posiciones relativas */
196         emufs_idx_borrar(efs,id_reg);
197         
198         return(0);
199 }
200
201 /**********************************************************************/
202 /* int emufs_tipo2_get_regsize(EMUFS *efs, EMUFS_OFFSET n_RegPos,     */
203 /*                             EMUFS_REG_SIZE *n_RegSize)             */
204 /* Objetivo: Devuelve el tamanio de un registro, dado su init offset  */
205 /* Parametros: EMUFS *efs // Struct con handlers + info del openfile. */
206 /*             EMUFS_OFFSET n_RegPos // Offset al inicio del registro */
207 /*             EMUFS_REG_SIZE *n_RegSize // Size to lookup and return */
208 /**********************************************************************/
209 int emufs_tipo2_get_regsize(EMUFS *efs, EMUFS_OFFSET reg_pos, EMUFS_REG_SIZE *reg_size)
210 {
211     FILE *f_data;
212         char name_f[255];
213
214     /* Armamos el filename del archivo de datos */
215         strcpy(name_f,efs->nombre);
216         strcat(name_f,".dat");
217
218     if ((f_data = fopen(name_f,"r+")) == NULL) return -1; /* ERROR */
219         fseek(f_data,reg_pos+sizeof(EMUFS_REG_ID),SEEK_SET);
220         fread(reg_size,sizeof(EMUFS_REG_SIZE),1,f_data);                
221         fclose(f_data);
222         
223         return (0);
224 }
225
226 /**********************************************************************/
227 /* int emufs_tipo2_dummyfill(EMUFS *efs, EMUFS_OFFSET n_RegPos,       */
228 /*                           EMUFS_REG_SIZE n_Amount                  */
229 /* Objetivo: Pisa con basura lo que es hasta el momento un reg en     */
230 /*           el disco para indicar su borrado (Debug Purposes Only).  */
231 /* Parametros: EMUFS *efs // Struct con handlers + info del openfile. */
232 /*             EMUFS_OFFSET n_RegPos // Offset al inicio del registro */
233 /*             EMUFS_REG_SIZE *n_Amount // Size to lookup and return  */
234 /**********************************************************************/
235 int emufs_tipo2_dummyfill(EMUFS *efs, EMUFS_OFFSET reg_pos, EMUFS_REG_SIZE amount)
236 {
237     FILE *f_data;
238         char name_f[255];
239     char *dummyfill;
240         char *ptr_cur;
241         unsigned long fill_size,byte_count;
242         
243     /* Armamos el filename del archivo de datos */
244         strcpy(name_f,efs->nombre);
245         strcat(name_f,".dat");
246
247     if ((f_data = fopen(name_f,"r+")) == NULL) return -1; /* ERROR */
248         
249         /* Preparo el garbage y se lo tiro encima */
250         fill_size = amount+sizeof(EMUFS_REG_ID)+sizeof(EMUFS_REG_SIZE);
251         dummyfill = (char*)malloc(fill_size);
252         ptr_cur = dummyfill;
253         for (byte_count = 0; byte_count < fill_size; ++byte_count) memcpy(ptr_cur+byte_count,"#",1);
254         fseek(f_data,reg_pos,SEEK_SET);
255         fwrite(dummyfill,fill_size,1,f_data);
256         fclose(f_data);
257         
258         free(dummyfill);
259         return (0);
260 }