2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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 $ */
29 * Copyright (c) 1988 by Sun Microsystems, Inc.
35 * Description: _amopen()
42 #include "isam_impl.h"
45 * _amopen(isfname, varflag, minlen, maxlen, primkey,
46 * isfhandle, curpos, errcode)
48 * _amopen() opens an ISAM file.
51 * isfname ISAM file name
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}
60 * _amopen() returns 0 if successful, or -1 to indicate an error.
65 _amopen(char *isfname, enum openmode openmode, Bool *varflag,
66 int *minlen, int *maxlen, Bytearray *isfhandle,
67 Bytearray *curpos, struct errcode *errcode)
80 isfhandle0 = _makeisfhandle(isfname);
83 * Invalidate the FCB cache entry to avoid a problem found when using
86 if ((fcb = _mngfcb_find(&isfhandle0)) != NULL) {
87 (void) _watchfd_decr(_isfcb_nfds(fcb));
89 _mngfcb_delete(&isfhandle0);
93 * Get the FCB that corresponds to the isfhandle handle.
95 if ((fcb = _openfcb(&isfhandle0, errcode)) == NULL) {
100 * Check if the FCB allows writes if INOUT or OUTPUT is needed.
102 if (fcb->rdonly==TRUE && (openmode==OM_INOUT || openmode==OM_OUTPUT)) {
103 _amseterrcode(errcode, EACCES);
108 * Fill output parameters.
110 *minlen = fcb->minreclen;
111 *maxlen = fcb->maxreclen;
112 *varflag = fcb->varflag;
113 *isfhandle = isfhandle0;
116 * Initial current record position.
118 if (FCB_NOPRIMARY_KEY(fcb)) {
119 /* Use physical order. */
120 crp = (Crp *) _ismalloc(sizeof(*crp));
121 memset ((char *) crp, 0, sizeof(*crp));
123 crp->keyid = PHYS_ORDER;
124 crp->flag = CRP_BEFOREANY;
126 curpos->length = sizeof(*crp);
127 curpos->data = (char *) crp;
131 * Use primary key order.
134 crp = (Crp *) _ismalloc((unsigned)(sizeof(*crp) + fcb->keys[0].k2_len));
135 memset((char *) crp, 0, (sizeof(*crp) + fcb->keys[0].k2_len));
137 crp->keyid = fcb->keys[0].k2_keyid;
138 crp->flag = CRP_BEFOREANY;
140 _iskey_fillmin(&fcb->keys[0], crp->key);
142 curpos->length = sizeof(*crp) + fcb->keys[0].k2_len;
143 curpos->data = (char *) crp;
146 * Set full key length as the number of bytes to match in key comparison
148 crp->matchkeylen = fcb->keys[0].k2_len - RECNOSIZE;
150 if (ALLOWS_DUPS2(&fcb->keys[0]))
151 crp->matchkeylen -= DUPIDSIZE;
158 _bytearr_free(&isfhandle0);
165 * fcb = _openfcb(isfhandle, errcode)
167 * Try to locate FCB in the FCB cache. If not found, open the FCB and
168 * insert it into the cache.
170 * Return a pointer to the FCB, or NULL in the case of any error.
173 #define FDNEEDED 3 /* Needs 3 UNIX fd to open a file*/
175 _openfcb(Bytearray *isfhandle, struct errcode *errcode)
178 Bytearray *isfhandle2;
182 if ((fcb = _mngfcb_find(isfhandle)) != NULL)
186 * Check that there are UNIX file descriptors available.
188 while (_watchfd_check() < FDNEEDED) {
190 * Find victim (LRU FCB) and close it.
192 if((isfhandle2 = _mngfcb_victim()) == NULL)
193 _isfatal_error ("_openfcb() cannot find LRU victim");
195 fcb = _mngfcb_find(isfhandle2);
196 (void) _watchfd_decr(_isfcb_nfds(fcb));
198 _mngfcb_delete(isfhandle2);
202 * Open files, create FCB block.
204 if ((fcb = _isfcb_open(_getisfname(isfhandle), errcode)) == NULL) {
209 * Check that ISAM file is not corrupted (only check magic number).
211 if (_check_isam_magic(fcb) != ISOK) {
212 _amseterrcode(errcode, EBADFILE);
218 * Read information from CNTL PAGE and store it in the FCB.
220 if (_isfcb_cntlpg_r(fcb) == ISERROR)
221 _isfatal_error("_openfcb() cannot read CNTL PAGE");
224 * Register UNIX file descriptors consumed.
226 (void) _watchfd_incr(_isfcb_nfds(fcb));
229 * Insert new entry into the FCB cache.
231 _mngfcb_insert(fcb, isfhandle);
236 * Check that all file descriptors are open. This is needed to handle
237 * user errors such as removing .ind or .var files.
239 if (fcb->varflag==TRUE && fcb->varfd == -1) {
240 char *fmt = "%s.var has been removed";
241 if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
242 errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
246 (void)sprintf(errmsg0, fmt, fcb->isfname);
247 _isam_warning(errmsg0);
248 _amseterrcode(errcode, EBADFILE);
249 if (errmsg0 != errbuf) free(errmsg0);
253 if ((fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) && fcb->indfd == -1) {
254 char *fmt = "%s.ind has been removed";
255 if (strlen(fmt) + strlen(fcb->isfname) + 1 >= BUFSIZ)
256 errmsg0 = (char*) malloc(strlen(fmt) + strlen(fcb->isfname) + 1);
260 (void)sprintf(errmsg0, fmt, fcb->isfname);
261 _isam_warning(errmsg0);
262 _amseterrcode(errcode, EBADFILE);
263 if (errmsg0 != errbuf) free(errmsg0);
271 * Delete FCB and remove it from FCB cache. Close UNIX fds.
273 * This is needed to recover netisamd server if users remove .ind or
276 (void) _watchfd_decr(_isfcb_nfds(fcb));
278 _mngfcb_delete(isfhandle);
285 * isfname = _getisfname(isfhandle)
287 * Get ISAM file name from ISAM file handle.
291 _getisfname(Bytearray *isfhandle)
293 return (isfhandle->data);
298 * isfhandle = _makeisfhandle(isfname)
300 * Make ISAM file handle.
304 _makeisfhandle(char *isfname)
306 return (_bytearr_new((u_short)(strlen(isfname) + 1), isfname));