tt/mini_isam: remove all ancient sccsid blocks
[oweals/cde.git] / cde / lib / tt / mini_isam / isamopen.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $TOG: isamopen.c /main/5 1998/04/10 08:03:57 mgreess $                                                     */
28 /*
29  * Copyright (c) 1988 by Sun Microsystems, Inc.
30  */
31
32 /*
33  * isamopen.c
34  *
35  * Description: _amopen()
36  *      Open an ISAM file.
37  *      
38  *
39  */
40
41 #include <stdlib.h>
42 #include "isam_impl.h"
43
44 /*
45  * _amopen(isfname, varflag, minlen, maxlen, primkey, 
46  *          isfhandle, curpos, errcode)
47  *
48  * _amopen() opens an ISAM file.
49  *
50  * Input params:
51  * isfname ISAM file name
52  * 
53  * Output params:
54  * isfhandle a file handle to be used in subsequent operations on the file
55  * varflag TRUE if file is for variable length records
56  * minlen, maxlen minimum and maximum record length
57  * curpos  initial current record position
58  * errcode {iserrno, isstat1-4} 
59  *
60  * _amopen() returns 0 if successful, or -1 to indicate an error.
61  */
62
63 /* ARGSUSED */
64 int
65 _amopen(char *isfname, enum openmode openmode, Bool *varflag,
66         int *minlen, int *maxlen, Bytearray *isfhandle,
67         Bytearray *curpos, struct errcode *errcode)
68 {
69     Fcb                 *fcb;
70     Bytearray           isfhandle0;
71     Crp                 *crp;
72     int                 err;
73
74
75     _isam_entryhook();
76
77     /*
78      * Make isfhandle0. 
79      */
80
81     isfhandle0 = _makeisfhandle(isfname);
82
83     /*
84      * Invalidate the FCB cache entry to avoid a problem found when using 
85      * multiple servers.
86      */
87     if ((fcb = _mngfcb_find(&isfhandle0)) != NULL) {
88         (void) _watchfd_decr(_isfcb_nfds(fcb));
89         _isfcb_close(fcb);
90         _mngfcb_delete(&isfhandle0);
91     }
92
93     /*
94      * Get the FCB that corresponds to the isfhandle handle.
95      */
96     if ((fcb = _openfcb(&isfhandle0, errcode)) == NULL) {
97         goto ERROR;
98     }
99
100     /* 
101      * Check if the FCB allows writes if INOUT or OUTPUT is needed.
102      */
103     if (fcb->rdonly==TRUE && (openmode==OM_INOUT || openmode==OM_OUTPUT)) {
104         _amseterrcode(errcode, EACCES);
105         goto ERROR;
106     }
107     
108     /*
109      * Fill output parameters. 
110      */
111     *minlen = fcb->minreclen;
112     *maxlen = fcb->maxreclen;
113     *varflag = fcb->varflag;
114     *isfhandle = isfhandle0;
115
116     /*
117      * Initial current record position.
118      */
119     if (FCB_NOPRIMARY_KEY(fcb)) {
120         /* Use physical order. */
121         crp = (Crp *) _ismalloc(sizeof(*crp));
122         memset ((char *) crp, 0, sizeof(*crp));
123
124         crp->keyid = PHYS_ORDER;
125         crp->flag = CRP_BEFOREANY;
126
127         curpos->length = sizeof(*crp);
128         curpos->data = (char *) crp;
129     }
130     else {
131         /* 
132          * Use primary key order. 
133          */
134
135         crp = (Crp *) _ismalloc((unsigned)(sizeof(*crp) + fcb->keys[0].k2_len));
136         memset((char *) crp, 0, (sizeof(*crp) + fcb->keys[0].k2_len)); 
137
138         crp->keyid = fcb->keys[0].k2_keyid;
139         crp->flag = CRP_BEFOREANY;
140
141         _iskey_fillmin(&fcb->keys[0], crp->key);
142
143         curpos->length = sizeof(*crp) + fcb->keys[0].k2_len;
144         curpos->data = (char *) crp;
145         
146         /*
147          * Set full key length as the number of bytes to match in key comparison
148          */
149         crp->matchkeylen = fcb->keys[0].k2_len - RECNOSIZE;
150         
151         if (ALLOWS_DUPS2(&fcb->keys[0]))
152             crp->matchkeylen -= DUPIDSIZE;
153     }
154
155     _isam_exithook();
156     return (ISOK);
157
158  ERROR:
159     _bytearr_free(&isfhandle0);
160     _isam_exithook();
161     return (ISERROR);
162 }
163
164
165 /*
166  * fcb = _openfcb(isfhandle, errcode)
167  *
168  * Try to locate FCB in the FCB cache. If not found, open the FCB and
169  * insert it into the cache. 
170  *
171  * Return a pointer to the FCB, or NULL in the case of any error.
172  */
173
174 #define FDNEEDED        3                    /* Needs 3 UNIX fd to open a file*/
175 Fcb *
176 _openfcb(Bytearray *isfhandle, struct errcode *errcode)
177 {
178     Fcb                 *fcb;
179     Bytearray           *isfhandle2;
180     char                errbuf[BUFSIZ];
181     char                *errmsg0;
182
183     if ((fcb = _mngfcb_find(isfhandle)) != NULL)
184         goto out;
185
186     /*
187      * Check that there are UNIX file descriptors available.    
188      */
189     while (_watchfd_check() < FDNEEDED) {
190         /*
191          * Find victim (LRU FCB) and close it.
192          */
193         if((isfhandle2 = _mngfcb_victim()) == NULL) 
194             _isfatal_error ("_openfcb() cannot find LRU victim");
195
196         fcb = _mngfcb_find(isfhandle2);
197         (void) _watchfd_decr(_isfcb_nfds(fcb));
198         _isfcb_close(fcb);
199         _mngfcb_delete(isfhandle2);
200     }
201
202     /*
203      * Open files, create FCB block.
204      */
205     if ((fcb = _isfcb_open(_getisfname(isfhandle), errcode)) == NULL) {
206         return (NULL);
207     }
208
209     /*
210      * Check that ISAM file is not corrupted (only check magic number).
211      */
212     if (_check_isam_magic(fcb) != ISOK) {
213         _amseterrcode(errcode, EBADFILE);
214         _isfcb_close(fcb);
215         return (NULL);
216     }
217
218     /*
219      * Read information from CNTL PAGE and store it in the FCB.
220      */
221     if (_isfcb_cntlpg_r(fcb) == ISERROR)
222         _isfatal_error("_openfcb() cannot read CNTL PAGE");
223
224     /*
225      * Register UNIX file descriptors consumed.
226      */
227     (void) _watchfd_incr(_isfcb_nfds(fcb));
228
229     /*
230      * Insert new entry into the FCB cache.
231      */
232     _mngfcb_insert(fcb, isfhandle); 
233
234  out:
235
236     /*
237      * Check that all file descriptors are open. This is needed to handle
238      * user errors such as removing .ind or .var files.
239      */
240     if (fcb->varflag==TRUE && fcb->varfd == -1) {
241         char *fmt = "%s.var has been removed";
242         if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
243           errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
244         else
245           errmsg0 = errbuf;
246
247         (void)sprintf(errmsg0, fmt, fcb->isfname);
248         _isam_warning(errmsg0);
249         _amseterrcode(errcode, EBADFILE);
250         if (errmsg0 != errbuf) free(errmsg0);
251         goto err;
252     }
253
254     if ((fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) && fcb->indfd == -1) {
255         char *fmt = "%s.ind has been removed";
256         if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
257           errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
258         else
259           errmsg0 = errbuf;
260
261         (void)sprintf(errmsg0, fmt, fcb->isfname);
262         _isam_warning(errmsg0);
263         _amseterrcode(errcode, EBADFILE);
264         if (errmsg0 != errbuf) free(errmsg0);
265         goto err;
266     }
267
268     return (fcb);
269
270  err:
271     /*
272      * Delete FCB and remove it from FCB cache. Close UNIX fds.
273      *
274      * This is needed to recover netisamd server if users remove .ind or
275      * or .var files.
276      */
277     (void) _watchfd_decr(_isfcb_nfds(fcb));
278     _isfcb_close(fcb);
279     _mngfcb_delete(isfhandle);
280
281     return (NULL);
282
283 }
284
285 /*
286  * isfname = _getisfname(isfhandle)
287  *
288  * Get ISAM file name from ISAM file handle.
289  */
290
291 char *
292 _getisfname(Bytearray *isfhandle)
293 {
294     return (isfhandle->data);
295 }
296
297
298 /*
299  * isfhandle = _makeisfhandle(isfname)
300  *
301  * Make ISAM file handle.
302  */
303
304 Bytearray 
305 _makeisfhandle(char *isfname)
306 {
307     return (_bytearr_new((u_short)(strlen(isfname) + 1), isfname));
308 }
309