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