311406b846c4c0dbe5b797039765d7a977d890ab
[oweals/cde.git] / cde / lib / tt / mini_isam / isfcb.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 /*%%  $XConsortium: isfcb.c /main/3 1995/10/23 11:38:34 rswiston $                                                       */
28 #ifndef lint
29 static char sccsid[] = "@(#)isfcb.c 1.9 89/07/17 Copyr 1988 Sun Micro";
30 #endif
31 /*
32  * Copyright (c) 1988 by Sun Microsystems, Inc.
33  */
34
35 /*
36  * isfcb.c
37  *
38  * Description: _ambuild()
39  *      File Control Block functions
40  *      
41  *
42  */
43 #include <stdlib.h>
44 #include "isam_impl.h"
45 #include <sys/stat.h>
46
47 static int _create_datfile(), _create_indfile(), _create_varfile();
48 static void _remove_datfile(), _remove_indfile(), _remove_varfile();
49 Static int _open_datfile(), _open_indfile(), _open_varfile();
50
51 /*
52  * _isfcb_create(isfname, crdat, crind, crvar, owner, group, u_mask, errcode)
53  *
54  * Create ISAM file: create UNIX files (dat/ind/var), 
55  * and initialize File Control Block.
56  *
57  * Return 0 if create is successful, or -1 if any error. In the case of 
58   *an error, the errcode block is set.
59  *
60  * crdat, 0/1 flag
61  * crind, 0/1 flag
62  * crvar, 0/1 flag
63  */
64
65 Fcb *
66 _isfcb_create(char *isfname, int crdat, int crind, int crvar,
67               int owner, int group, int u_mask, struct errcode *errcode)
68 {
69     Fcb *fcb;
70     int                 dat_fd = -1;
71     int                 ind_fd = -1;
72     int                 var_fd = -1;
73     int                 oldumask = umask (u_mask); /* Change umask to client's */
74
75     /*
76      * Create the UNIX file for .rec file.
77      */
78     if (crdat && (dat_fd = _create_datfile (isfname)) == -1) {
79         _amseterrcode(errcode, errno);
80         goto ERROR;
81     }
82
83     /*
84      * If a primary is specified, create .ind file.
85      */
86     if (crind && (ind_fd = _create_indfile (isfname)) == -1) {
87         _amseterrcode(errcode, errno);
88         goto ERROR;
89     }
90  
91     /*
92      * If the ISAM file is for variable length records, create .var file.
93      */
94     if (crvar && (var_fd = _create_varfile (isfname)) == -1) {
95         _amseterrcode(errcode, errno);
96         goto ERROR;
97     }
98
99     /*
100      * Change user and group onwer ship of the file.
101      * This has affect only when executed by the netisamd daemon.
102      */
103     if (dat_fd != -1)
104         (void) fchown(dat_fd, owner, group);
105     if (ind_fd != -1)
106         (void) fchown(ind_fd, owner, group);
107     if (var_fd != -1)
108         (void) fchown(var_fd, owner, group);
109
110     /*
111      * Allocate File Control Block.
112      */
113     fcb = (Fcb *) _ismalloc(sizeof(*fcb));
114     memset ((char *) fcb, 0, sizeof(*fcb));
115
116     fcb->isfname = _isallocstring(isfname);
117     fcb->rdonly = FALSE;
118     fcb->datfd = dat_fd;        
119     fcb->indfd = ind_fd;
120     fcb->varfd = var_fd;
121
122     fcb->datsize = N_CNTL_PAGES;             /* Control Pages */
123     fcb->indfreelist = FREELIST_NOPAGE;
124
125     /* Key descriptor */
126     fcb->nkeys = 1;
127     fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
128     memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
129     
130     return (fcb);
131
132  ERROR:
133     /* Undo whatever was done. */
134     if (dat_fd != -1) { 
135         (void) close(dat_fd);
136         _remove_datfile(isfname);
137     }
138     if (ind_fd != -1) {
139         (void) close(ind_fd);
140         _remove_indfile(isfname);
141     }   
142     if (var_fd != -1) {
143         (void) close(var_fd);
144         _remove_varfile(isfname);
145     }
146
147     (void) umask(oldumask);
148
149     return (NULL);
150 }
151
152 /*
153  * _isfcb_setlength(fcb, varflag, minreclen, maxreclen)
154  *
155  * Set FCB attributes pertaining to record length.
156  */
157
158 void
159 _isfcb_setreclength(Fcb *fcb, Bool varflag, int minreclen, int maxreclen)
160 {
161     fcb->varflag = varflag;
162     fcb->minreclen = minreclen;
163     fcb->maxreclen = maxreclen;
164 }
165
166 /*
167  * _isfcb_open(isfname, errcode)
168  *
169  * Open ISAM file: open UNIX files and create File Control Block.
170  *
171  * Return 0 if open is successful, or -1 if any error. In the case of an error,
172  * the errcode block is set.
173  *
174  * Note that rdonly is not fuly implemented. Now, all ISAM files are assumed
175  * to have permissions set to 0666 and may be opened in RW mode.
176  * If read-only media are used then the _open_datfile() function would have to
177  * try first to open the file in RW mode, and of that failed, try to 
178  * open it in RO mode. The rdonly flag is used to reject any isamopen() with
179  * INOUT or OUTPUT mode on such files.
180  */
181
182 Fcb *
183 _isfcb_open(char *isfname, struct errcode *errcode)
184 {
185     Fcb *fcb;
186     int                 dat_fd = -1;
187     int                 ind_fd = -1;
188     int                 var_fd = -1;
189     Bool                rdonly;              /* set to 1 if file is Read-Only */
190
191     /*
192      *  Open the UNIX file for .rec file.
193      */
194     if ((dat_fd = _open_datfile (isfname, &rdonly)) == -1 || errno == EMFILE) {
195         _amseterrcode(errcode, errno);
196         if(dat_fd != -1) {
197             close(dat_fd);
198         }
199         return (NULL);
200     }
201
202     /*
203      * Open .ind file.
204      */
205     ind_fd = _open_indfile (isfname, rdonly);
206  
207     /*
208      * Open .var file.
209      */
210     var_fd = _open_varfile (isfname, rdonly);
211
212
213     /*
214      * Allocate File Control Block.
215      */
216     fcb = (Fcb *) _ismalloc(sizeof(*fcb));
217     memset ((char *) fcb, 0, sizeof(*fcb));
218
219     fcb->isfname = _isallocstring(isfname);
220     fcb->rdonly = rdonly;
221     fcb->datfd = dat_fd;        
222     fcb->indfd = ind_fd;
223     fcb->varfd = var_fd;
224
225     /* Key descriptor */
226     fcb->nkeys = 1;
227     fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
228     memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
229
230     return (fcb);
231 }
232
233 /*
234  * _isfcb_nfds(fcb)
235  *
236  * Return the number of UNIX fd consumed by the fcb block.
237  */
238
239 int
240 _isfcb_nfds(Fcb *fcb)
241 {
242     int count = 0;
243
244     if (fcb->datfd != -1)
245         count++;
246
247     if (fcb->indfd != -1)
248         count++;
249
250     if (fcb->varfd != -1)
251         count++;
252     
253     return (count);
254 }
255
256
257 /*
258  * _isfcb_remove(fcb)
259  *
260  * Remove UNIX files associated with an FCB.
261  */
262
263 void
264 _isfcb_remove(Fcb *fcb)
265 {
266     if (fcb->datfd)
267         _remove_datfile(fcb->isfname);
268     
269     if (fcb->indfd)
270         _remove_indfile(fcb->isfname);
271
272     if (fcb->varfd)
273         _remove_varfile(fcb->isfname);
274 }
275
276 /*
277  * _isfcb_close(fcb)
278  *
279  * Close UNIX files associated with an FCB, deallocate the FCB block.
280  */
281
282 void
283 _isfcb_close(Fcb *fcb)
284 {
285     assert (fcb != NULL);
286     assert (fcb->isfname != NULL);
287
288     (void) close(fcb->datfd);
289     (void) close(fcb->indfd);
290     (void) close(fcb->varfd);
291
292     _isfreestring(fcb->isfname);
293     free((char *)fcb->keys);
294     free((char *)fcb);
295 }
296
297 /*
298  * _isfcb_cntlpg_w(fcb)
299  *
300  * Write information from the control block to the disk.
301  * Note that the Control Page transfer bypasses the disk buffer manager.
302  *
303  * Return 0 if write was successful, return -1 if any error.
304  */
305
306 int
307 _isfcb_cntlpg_w(Fcb *fcb)
308 {
309     char                cntl_page[ISCNTLSIZE];
310     int                 dat_fd = fcb->datfd;
311     int                 i;
312
313     /* Clear the page. */
314     memset (cntl_page, 0, sizeof(cntl_page));
315
316     /* Set Magic number. */
317     (void)strcpy(cntl_page + CP_MAGIC_OFF, ISMAGIC);
318
319     /* Set Block size */
320     stshort(ISPAGESIZE, cntl_page + CP_BLOCKSIZE_OFF);
321
322     /* Set NetISAM version stamp. */
323     (void)strcpy(cntl_page + CP_VERSION_OFF, ISVERSION);
324
325     /* .rec file size in blocks. */
326     stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
327
328     /* .ind file size in blocks. */
329     stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
330
331     /* .var file size in blocks. */
332     stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
333
334     /* Variable length 0/1 flag. */
335     stshort((short)fcb->varflag, cntl_page + CP_VARFLAG_OFF);
336
337     /* Number of records. */
338     stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
339
340     /* Minimum and maximum record length. */
341     stshort((short)fcb->minreclen, cntl_page + CP_MINRECLEN_OFF);
342     stshort((short)fcb->maxreclen, cntl_page + CP_MAXRECLEN_OFF);
343
344     /* Last record number. */
345     strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
346
347     /* Free record number. */
348     strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
349  
350     /* Number of keys */
351     stshort((short)fcb->nkeys, cntl_page + CP_NKEYS_OFF);
352
353     /* Last key id */
354     stlong((long)fcb->lastkeyid, cntl_page + CP_LASTKEYID_OFF);
355
356     /* ind. free list head */
357     stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
358
359     /* offset of the end of .var file */
360     stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
361
362     /* Key descriptors. */
363     for (i = 0; i < fcb->nkeys; i++) {
364         stkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
365     }
366
367     /* Increment stamp1 and stamp2 to indicate change in the Control Page. */
368     fcb->changestamp1++;
369     fcb->changestamp2++;
370
371     stlong((long)fcb->changestamp1, cntl_page + CP_CHANGESTAMP1_OFF);
372     stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
373     
374     /* 
375      * Write the buffer to the disk.
376      */
377     _isseekpg(dat_fd, ISCNTLPGOFF);
378     _iswritepg(dat_fd, cntl_page);
379     _iswritepg(dat_fd, cntl_page + ISPAGESIZE);
380
381     return (ISOK);
382 }
383
384 /*
385  * _isfcb_cntlpg_w2(fcb)
386  *
387  * Write information from the control block to the disk.
388  * Write only selected fields of the control block to avoid the overhead
389  * of coding and decoding.
390  * Note that the Control Page transfer bypasses the disk buffer manager.
391  *
392  * Return 0 if write was successful, return -1 if any error.
393  */
394
395 int
396 _isfcb_cntlpg_w2(Fcb *fcb)
397 {
398     char                cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
399     int                 dat_fd = fcb->datfd;
400
401     /* 
402      * Read the page from disk.
403      */
404     _isseekpg(dat_fd, ISCNTLPGOFF);
405     (void)read(dat_fd, cntl_page, sizeof(cntl_page));
406
407     /* .rec file size in blocks. */
408     stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
409
410     /* .ind file size in blocks. */
411     stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
412
413     /* .var file size in blocks. */
414     stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
415
416     /* Number of records. */
417     stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
418
419     /* Last record number. */
420     strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
421
422     /* Free record number. */
423     strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
424
425     /* ind. free list head */
426     stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
427
428     /* end of .var file */
429     stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
430
431     /* Increment stamp2 to indicate change in the Control Page. */
432     fcb->changestamp2++;
433     stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
434     
435
436     /* 
437      * Write the buffer to the disk.
438      */
439     _isseekpg(dat_fd, ISCNTLPGOFF);
440     (void)write(dat_fd, cntl_page, sizeof(cntl_page));
441
442     return (ISOK);
443 }
444
445 /*
446  * _isfcb_cntlpg_r(fcb)
447  *
448  * Read information from control page and store it in the FCB.
449  * Note that the Control Page transfer bypasses the disk buffer manager.
450  *
451  * Return 0 if read was successful, return -1 if any error.
452  */
453
454 int
455 _isfcb_cntlpg_r(Fcb *fcb)
456 {
457     char                cntl_page[ISCNTLSIZE];
458     int                 dat_fd = fcb->datfd;
459     int                 i;
460     
461     /* 
462      * Read the page from the disk.
463      */
464     _isseekpg(dat_fd, ISCNTLPGOFF);
465     _isreadpg(dat_fd, cntl_page);
466     _isreadpg(dat_fd, cntl_page + ISPAGESIZE);
467
468     /* block size */
469     fcb->blocksize = ldshort(cntl_page + CP_BLOCKSIZE_OFF);
470
471     /* .rec file size in blocks. */
472     fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
473
474     /* .ind file size in blocks. */
475     fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
476
477     /* .var file size in blocks. */
478     fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
479
480     /* Variable length 0/1 flag. */
481     fcb->varflag = (Bool)ldshort(cntl_page + CP_VARFLAG_OFF);
482
483     /* Number of records. */
484     fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
485
486     /* Minimum and maximum record length. */
487     fcb->minreclen = ldunshort(cntl_page + CP_MINRECLEN_OFF);
488     fcb->maxreclen = ldunshort(cntl_page + CP_MAXRECLEN_OFF);
489
490     /* Last record number. */
491     fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
492
493     /* Free record number. */
494     fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
495
496     /* Last key id */
497     fcb->lastkeyid = ldlong(cntl_page + CP_LASTKEYID_OFF);
498
499     /* .ind free list head. */
500     fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
501
502     /* end of .var file */
503     fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
504
505     /* Number of keys */
506     fcb->nkeys = ldshort(cntl_page + CP_NKEYS_OFF);
507
508     /*
509      * Read key descriptors.
510      */
511     fcb->keys = (Keydesc2 *) 
512         _isrealloc((char *)fcb->keys,
513                    (unsigned) (sizeof(Keydesc2) * fcb->nkeys));
514     memset((char *)fcb->keys, 0, sizeof(Keydesc2) * fcb->nkeys);
515
516     for (i = 0; i < fcb->nkeys; i++) {
517         ldkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
518     }
519
520     /* Changestamp1 */
521     fcb->changestamp1 = ldlong(cntl_page + CP_CHANGESTAMP1_OFF);
522
523     /* Changestamp2 */
524     fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
525
526     /*
527      * Open .ind file in situations when some other process has created
528      * keys and this process has just learned it now.
529      */
530     if (fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) {
531 /*
532         if (_open2_indfile(fcb) != ISOK)
533             _isfatal_error("_open2_indfile()");
534 */
535         (void)_open2_indfile(fcb);
536     }
537
538     
539     return (ISOK);
540 }
541
542
543 /*
544  * _isfcb_cntlpg_r2(fcb)
545  *
546  * Read information from the control block on the disk.
547  * Read only selected fields of the control block to avoid the overhead
548  * of coding and decoding.
549  * Note that the Control Page transfer bypasses the disk buffer manager.
550  *
551  * Return 0 if write was successful, return -1 if any error.
552  */
553
554 int
555 _isfcb_cntlpg_r2(Fcb *fcb)
556 {
557     char                cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
558     int                 dat_fd = fcb->datfd;
559
560     /* 
561      * Read the page from disk.
562      */
563     _isseekpg(dat_fd, ISCNTLPGOFF);
564     (void)read(dat_fd, cntl_page, sizeof(cntl_page));
565
566     /*
567      * Check changestamp1. If the stamp has changed, we must read the entire
568      * page and update the FCB.
569      */
570     if (ldlong(cntl_page + CP_CHANGESTAMP1_OFF) != fcb->changestamp1) {
571         (void)_isfcb_cntlpg_r(fcb);
572     }
573
574     /* 
575      *_isfcb_cntlpg_r2() is called if transaction is rolled back.
576      * We cannot test changestamp2; we must read the info into the FCB
577      * always.
578      */
579        
580 #if 0
581     /*
582      * Check changestamp2. If the stamp has not changed, the FCB contains
583      * up-to-date information.
584      */
585     if (ldlong(cntl_page + CP_CHANGESTAMP2_OFF) == fcb->changestamp2) {
586         return (ISOK);
587     }
588 #endif
589
590     /* .rec file size in blocks. */
591     fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
592
593     /* .ind file size in blocks. */
594     fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
595
596     /* .var file size in blocks. */
597     fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
598
599     /* Number of records. */
600     fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
601
602     /* Last record number. */
603     fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
604
605     /* Free record number. */
606     fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
607
608     /* .ind free list head. */
609     fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
610
611     /* end of .var file */
612     fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
613
614     /* Changestamp2 */
615     fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
616     
617     return (ISOK);
618 }
619
620
621 /*
622  * _create_datfile(isfname)
623  *
624  * Create .rec file for ISAM file isfname.
625  */
626
627 Static int
628 _create_datfile(char *isfname)
629 {
630         int     fd;
631         char    namebuf[MAXPATHLEN];
632
633         snprintf(namebuf, sizeof(namebuf), "%s", isfname);
634         _makedat_isfname(namebuf);
635         
636         fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
637         if (fd > -1) {
638                 /* Close on exec */
639                 if(fcntl(fd, F_SETFD, 1) == -1) {
640                         close(fd);
641                         return(-1);
642                 }
643         }
644         return (fd);
645 }
646
647 /*
648  * _create_indfile(isfname)
649  *
650  * Create .ind file for ISAM file isfname.
651  */
652
653 Static int
654 _create_indfile(char *isfname)
655 {
656         int     fd;
657         char    namebuf[MAXPATHLEN];
658
659         snprintf(namebuf, sizeof(namebuf), "%s", isfname);
660         _makeind_isfname(namebuf);
661
662         fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
663         if (fd > -1) {
664                 /* Close on exec */
665                 if(fcntl(fd, F_SETFD, 1) == -1) {
666                         close(fd);
667                         return(-1);
668                 }
669         }
670         return (fd);
671 }
672
673 /*
674  * _create_varfile(isfname)
675  *
676  * Create .var file for ISAM file isfname.
677  */
678
679 Static int
680 _create_varfile(char *isfname)
681 {
682         int     fd;
683         char    namebuf[MAXPATHLEN];
684
685         snprintf(namebuf, sizeof(namebuf), "%s", isfname);
686         _makevar_isfname(namebuf);
687
688         fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
689         if (fd > -1) {
690                 /* Close on exec */
691                 if(fcntl(fd, F_SETFD, 1) == -1) {
692                         close(fd);
693                         return(-1);
694                 }
695         }
696         return (fd);
697 }
698
699
700 /*
701  * _remove_datfile(isfname)
702  *
703  * Remove .rec file for ISAM file isfname.
704  */
705
706 Static void
707 _remove_datfile(char *isfname)
708 {
709     char        namebuf[MAXPATHLEN];
710
711     snprintf(namebuf, sizeof(namebuf), "%s", isfname);
712     _makedat_isfname(namebuf);
713
714     (void) unlink(namebuf);
715 }
716
717 /*
718  * _remove_indfile(isfname)
719  *
720  * Remove .ind file for ISAM file isfname.
721  */
722
723 Static void
724 _remove_indfile(char *isfname)
725 {
726     char        namebuf[MAXPATHLEN];
727
728     snprintf(namebuf, sizeof(namebuf), "%s", isfname);
729     _makeind_isfname(namebuf);
730
731     (void) unlink(namebuf);
732 }
733
734 /*
735  * _remove_varfile(isfname)
736  *
737  * Remove .var file for ISAM file isfname.
738  */
739
740 Static void
741 _remove_varfile(char *isfname)
742 {
743     char        namebuf[MAXPATHLEN];
744
745     snprintf(namebuf, sizeof(namebuf), "%s", isfname);
746     _makevar_isfname(namebuf);
747
748     (void) unlink(namebuf);
749 }
750
751
752 /*
753  * _open_datfile(isfname)
754  *
755  * Open .rec file for ISAM file isfname.
756  */
757
758 Static int
759 _open_datfile(char *isfname, Bool *rdonly)
760 {
761     char        namebuf[MAXPATHLEN];
762     int         ret;
763
764     snprintf(namebuf, sizeof(namebuf), "%s", isfname);
765     _makedat_isfname(namebuf);
766
767     if ((ret = open (namebuf, O_RDWR)) != -1) {
768         *rdonly = FALSE;
769         /* Close on exec */
770         if(fcntl(ret, F_SETFD, 1) == -1) {
771             close(ret);
772             ret = -1;
773         }
774         return (ret);
775     }
776
777     *rdonly = TRUE;
778     ret = open (namebuf, O_RDONLY);
779     if (ret > -1) {
780         /* Close on exec */
781         if(fcntl(ret, F_SETFD, 1) == -1) {
782             close(ret);
783             return(-1);
784         }
785     }
786     return (ret);
787 }
788
789 /*
790  * _open_indfile(isfname)
791  *
792  * Open .ind file for ISAM file isfname.
793  */
794
795 Static int
796 _open_indfile(char *isfname, Bool rdonly)
797 {
798         int     fd;
799         char    namebuf[MAXPATHLEN];
800
801         snprintf(namebuf, sizeof(namebuf), "%s", isfname);
802         _makeind_isfname(namebuf);
803
804         fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
805         if (fd > -1) {
806                 /* Close on exec */
807                 if(fcntl(fd, F_SETFD, 1) == -1) {
808                         close(fd);
809                         return(-1);
810                 }
811         }
812         return (fd);
813 }
814
815 /*
816  * _open_varfile(isfname)
817  *
818  * Open .var file for ISAM file isfname.
819  */
820
821 Static int
822 _open_varfile(char *isfname, Bool rdonly)
823 {
824         int     fd;
825         char    namebuf[MAXPATHLEN];
826
827         snprintf(namebuf, sizeof(namebuf), "%s", isfname);
828         _makevar_isfname(namebuf);
829
830         fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
831         if (fd > -1) {
832                 /* Close on exec */
833                 if(fcntl(fd, F_SETFD, 1) == -1) {
834                         close(fd);
835                         return(-1);
836                 }
837         }
838         return (fd);
839 }
840
841 int
842 _check_isam_magic(Fcb *fcb)
843 {
844     char                magicbuffer[CP_MAGIC_LEN];
845
846     (void)lseek(fcb->datfd, 0L, 0);
847     if (read(fcb->datfd, magicbuffer, CP_MAGIC_LEN) < CP_MAGIC_LEN ||
848         /* The following test for compatibilty with `SunISAM 1.0 Beta files. */
849         strncmp(magicbuffer, "SunISAM", strlen(ISMAGIC)) != 0 &&
850         strncmp(magicbuffer, ISMAGIC, strlen(ISMAGIC)) != 0) {
851         return ISERROR;
852     }
853     else
854         return ISOK;
855 }
856
857
858 /*
859  * _open2_indfile(fcb)
860  *
861  * Open (or create) .ind file for ISAM file if the .ind file
862  * is not open already (or does not exist).
863  */
864
865 int
866 _open2_indfile(Fcb *fcb)
867 {
868     char        namebuf[MAXPATHLEN];
869     struct stat buf;
870     int         openmode;
871
872     if (fcb->indfd != -1)
873         return (ISOK);
874
875     snprintf(namebuf, sizeof(namebuf), "%s", fcb->isfname);
876     _makeind_isfname(namebuf);
877
878     (void)fstat(fcb->datfd, &buf);
879
880     openmode = (fcb->rdonly) ? O_RDONLY : O_RDWR;
881
882     if (fcb->indsize == 0)
883         openmode |= O_CREAT;
884
885     fcb->indfd =  open(namebuf, openmode, buf.st_mode);
886     if (fcb->indfd > -1) {
887         /* Close on exec */
888         if(fcntl(fcb->indfd, F_SETFD, 1) == -1) {
889             close(fcb->indfd);
890             fcb->indfd = -1;
891         }
892     }
893
894     if(fcb->indfd == -1 && (openmode & O_CREAT)) {
895         _isfatal_error("Cannot create .ind file");
896     }
897
898     if (fcb->indfd != -1) {
899         (void) _watchfd_incr(1);
900         (void)fchown(fcb->indfd, buf.st_uid, buf.st_gid);
901     }
902
903     return ((fcb->indfd == -1) ? ISERROR : ISOK);
904 }