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