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