Fixed memory leaks.
[idzebra-moved-to-github.git] / bfile / bfile.c
1 /*
2  * Copyright (C) 1994-1997, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: bfile.c,v $
7  * Revision 1.25  1997-10-27 14:25:38  adam
8  * Fixed memory leaks.
9  *
10  * Revision 1.24  1997/09/18 08:59:16  adam
11  * Extra generic handle for the character mapping routines.
12  *
13  * Revision 1.23  1997/09/17 12:19:06  adam
14  * Zebra version corresponds to YAZ version 1.4.
15  * Changed Zebra server so that it doesn't depend on global common_resource.
16  *
17  * Revision 1.22  1997/09/09 13:37:52  adam
18  * Partial port to WIN95/NT.
19  *
20  * Revision 1.21  1996/10/29 13:56:13  adam
21  * Include of zebrautl.h instead of alexutil.h.
22  *
23  * Revision 1.20  1996/03/26 15:59:04  adam
24  * The directory of the shadow table file can be specified by the new
25  * bf_lockDir call.
26  *
27  * Revision 1.19  1996/02/05  12:28:58  adam
28  * Removed a LOG_LOG message.
29  *
30  * Revision 1.18  1996/01/02  08:59:06  quinn
31  * Changed "commit" setting to "shadow".
32  *
33  * Revision 1.17  1995/12/11  09:03:51  adam
34  * New function: cf_unlink.
35  * New member of commit file head: state (0) deleted, (1) hash file.
36  *
37  * Revision 1.16  1995/12/08  16:21:13  adam
38  * Work on commit/update.
39  *
40  * Revision 1.15  1995/12/01  16:24:28  adam
41  * Commit files use separate meta file area.
42  *
43  * Revision 1.14  1995/12/01  11:37:21  adam
44  * Cached/commit files implemented as meta-files.
45  *
46  * Revision 1.13  1995/11/30  17:00:49  adam
47  * Several bug fixes. Commit system runs now.
48  *
49  * Revision 1.12  1995/11/30  08:33:10  adam
50  * Started work on commit facility.
51  *
52  * Revision 1.11  1995/09/04  12:33:21  adam
53  * Various cleanup. YAZ util used instead.
54  *
55  * Revision 1.10  1994/08/25  10:15:54  quinn
56  * Trivial
57  *
58  * Revision 1.9  1994/08/24  08:45:48  quinn
59  * Using mfile.
60  *
61  * Revision 1.8  1994/08/23  15:03:34  quinn
62  * *** empty log message ***
63  *
64  * Revision 1.7  1994/08/23  14:25:45  quinn
65  * Added O_CREAT because some geek wanted it. Sheesh.
66  *
67  * Revision 1.6  1994/08/23  14:21:38  quinn
68  * Fixed call to log
69  *
70  * Revision 1.5  1994/08/18  08:10:08  quinn
71  * Minimal changes
72  *
73  * Revision 1.4  1994/08/17  14:27:32  quinn
74  * last mods
75  *
76  * Revision 1.2  1994/08/17  14:09:32  quinn
77  * Compiles cleanly (still only dummy).
78  *
79  * Revision 1.1  1994/08/17  13:55:08  quinn
80  * New blocksystem. dummy only
81  *
82  */
83
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <string.h>
87 #include <assert.h>
88 #ifdef WINDOWS
89 #include <io.h>
90 #else
91 #include <unistd.h>
92 #endif
93
94 #include <zebrautl.h>
95 #include <bfile.h>
96 #include "cfile.h"
97
98 struct BFiles_struct {
99     MFile_area commit_area;
100     MFile_area_struct *register_area;
101     char *lockDir;
102 };
103
104 BFiles bfs_create (const char *spec)
105 {
106     BFiles bfs = xmalloc (sizeof(*bfs));
107     bfs->commit_area = NULL;
108     bfs->register_area = mf_init("register", spec);
109     bfs->lockDir = NULL;
110     return bfs;
111 }
112
113 void bfs_destroy (BFiles bfs)
114 {
115     xfree (bfs->lockDir);
116     mf_destroy (bfs->commit_area);
117     mf_destroy (bfs->register_area);
118     xfree (bfs);
119 }
120
121 static FILE *open_cache (BFiles bfs, const char *flags)
122 {
123     char cacheFilename[1024];
124     FILE *file;
125
126     sprintf (cacheFilename, "%scache",
127              bfs->lockDir ? bfs->lockDir : "");
128     file = fopen (cacheFilename, flags);
129     return file;
130 }
131
132 static void unlink_cache (BFiles bfs)
133 {
134     char cacheFilename[1024];
135
136     sprintf (cacheFilename, "%scache",
137              bfs->lockDir ? bfs->lockDir : "");
138     unlink (cacheFilename);
139 }
140
141 void bf_lockDir (BFiles bfs, const char *lockDir)
142 {
143     size_t len;
144     
145     xfree (bfs->lockDir);
146     if (lockDir == NULL)
147         lockDir = "";
148     len = strlen(lockDir);
149     bfs->lockDir = xmalloc (len+2);
150     strcpy (bfs->lockDir, lockDir);
151     
152     if (len > 0 && bfs->lockDir[len-1] != '/')
153         strcpy (bfs->lockDir + len, "/");
154 }
155
156 void bf_cache (BFiles bfs, const char *spec)
157 {
158     if (spec)
159     {
160         if (!bfs->commit_area)
161             bfs->commit_area = mf_init ("shadow", spec);
162     }
163     else
164         bfs->commit_area = NULL;
165 }
166
167 int bf_close (BFile bf)
168 {
169     if (bf->cf)
170         cf_close (bf->cf);
171     mf_close (bf->mf);
172     xfree (bf);
173     return 0;
174 }
175
176 BFile bf_open (BFiles bfs, const char *name, int block_size, int wflag)
177 {
178     BFile tmp = xmalloc(sizeof(BFile_struct));
179
180     if (bfs->commit_area)
181     {
182         int first_time;
183
184         tmp->mf = mf_open (bfs->register_area, name, block_size, 0);
185         tmp->cf = cf_open (tmp->mf, bfs->commit_area, name, block_size,
186                            wflag, &first_time);
187         if (first_time)
188         {
189             FILE *outf;
190
191             outf = open_cache (bfs, "a");
192             if (!outf)
193             {
194                 logf (LOG_FATAL|LOG_ERRNO, "open %scache",
195                       bfs->lockDir ? bfs->lockDir : "");
196                 exit (1);
197             }
198             fprintf (outf, "%s %d\n", name, block_size);
199             fclose (outf);
200         }
201     }
202     else
203     {
204         tmp->mf = mf_open(bfs->register_area, name, block_size, wflag);
205         tmp->cf = NULL;
206     }
207     if (!tmp->mf)
208     {
209         logf (LOG_FATAL, "mf_open failed for %s", name);
210         xfree (tmp);
211         return 0;
212     }
213     return(tmp);
214 }
215
216 int bf_read (BFile bf, int no, int offset, int num, void *buf)
217 {
218     int r;
219
220     if (bf->cf && (r=cf_read (bf->cf, no, offset, num, buf)) != -1)
221         return r;
222     return mf_read (bf->mf, no, offset, num, buf);
223 }
224
225 int bf_write (BFile bf, int no, int offset, int num, const void *buf)
226 {
227     if (bf->cf)
228         return cf_write (bf->cf, no, offset, num, buf);
229     return mf_write (bf->mf, no, offset, num, buf);
230 }
231
232 int bf_commitExists (BFiles bfs)
233 {
234     FILE *inf;
235
236     inf = open_cache (bfs, "r");
237     if (inf)
238     {
239         fclose (inf);
240         return 1;
241     }
242     return 0;
243 }
244
245 void bf_commitExec (BFiles bfs)
246 {
247     FILE *inf;
248     int block_size;
249     char path[256];
250     MFile mf;
251     CFile cf;
252     int first_time;
253
254     assert (bfs->commit_area);
255     if (!(inf = open_cache (bfs, "r")))
256     {
257         logf (LOG_LOG, "No commit file");
258         return ;
259     }
260     while (fscanf (inf, "%s %d", path, &block_size) == 2)
261     {
262         mf = mf_open (bfs->register_area, path, block_size, 1);
263         cf = cf_open (mf, bfs->commit_area, path, block_size, 0, &first_time);
264
265         cf_commit (cf);
266
267         cf_close (cf);
268         mf_close (mf);
269     }
270     fclose (inf);
271 }
272
273 void bf_commitClean (BFiles bfs, const char *spec)
274 {
275     FILE *inf;
276     int block_size;
277     char path[256];
278     MFile mf;
279     CFile cf;
280     int mustDisable = 0;
281     int firstTime;
282
283     if (!bfs->commit_area)
284     {
285         bf_cache (bfs, spec);
286         mustDisable = 1;
287     }
288
289     if (!(inf = open_cache (bfs, "r")))
290         return ;
291     while (fscanf (inf, "%s %d", path, &block_size) == 2)
292     {
293         mf = mf_open (bfs->register_area, path, block_size, 0);
294         cf = cf_open (mf, bfs->commit_area, path, block_size, 1, &firstTime);
295         cf_unlink (cf);
296         cf_close (cf);
297         mf_close (mf);
298     }
299     fclose (inf);
300     unlink_cache (bfs);
301     if (mustDisable)
302         bf_cache (bfs, 0);
303 }