Files
cdesktop/cde/lib/tt/mini_isam/isfcb.c
Jon Trulson c0388656dc tt/mini_isam: add new isam_prototypes.h include file and fix up problems
There were a variety of potential 64b problems due to the complete
lack of prototype declarations.  So, we add a file, isam_prototypes.h,
generated mostly by the 'cproto' tool.

We also fixed up some errors that having proper prototypes pointed
out, mainly in passing ints where pointers were expected and vice
versa.  The iserase() function was supposed to accept a char *, but
was defined as only accepting a char.  Fun stuff like that.
2018-06-30 20:13:39 -06:00

903 lines
20 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*%% (c) Copyright 1993, 1994 Hewlett-Packard Company */
/*%% (c) Copyright 1993, 1994 International Business Machines Corp. */
/*%% (c) Copyright 1993, 1994 Sun Microsystems, Inc. */
/*%% (c) Copyright 1993, 1994 Novell, Inc. */
/*%% $XConsortium: isfcb.c /main/3 1995/10/23 11:38:34 rswiston $ */
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* isfcb.c
*
* Description: _ambuild()
* File Control Block functions
*
*
*/
#include <unistd.h>
#include <stdlib.h>
#include "isam_impl.h"
#include <sys/stat.h>
static int _create_datfile(), _create_indfile(), _create_varfile();
static void _remove_datfile(), _remove_indfile(), _remove_varfile();
Static int _open_datfile(), _open_indfile(), _open_varfile();
/*
* _isfcb_create(isfname, crdat, crind, crvar, owner, group, u_mask, errcode)
*
* Create ISAM file: create UNIX files (dat/ind/var),
* and initialize File Control Block.
*
* Return 0 if create is successful, or -1 if any error. In the case of
*an error, the errcode block is set.
*
* crdat, 0/1 flag
* crind, 0/1 flag
* crvar, 0/1 flag
*/
Fcb *
_isfcb_create(char *isfname, int crdat, int crind, int crvar,
int owner, int group, int u_mask, struct errcode *errcode)
{
Fcb *fcb;
int dat_fd = -1;
int ind_fd = -1;
int var_fd = -1;
int oldumask = umask (u_mask); /* Change umask to client's */
/*
* Create the UNIX file for .rec file.
*/
if (crdat && (dat_fd = _create_datfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* If a primary is specified, create .ind file.
*/
if (crind && (ind_fd = _create_indfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* If the ISAM file is for variable length records, create .var file.
*/
if (crvar && (var_fd = _create_varfile (isfname)) == -1) {
_amseterrcode(errcode, errno);
goto ERROR;
}
/*
* Change user and group onwer ship of the file.
* This has affect only when executed by the netisamd daemon.
*/
if (dat_fd != -1)
(void) fchown(dat_fd, owner, group);
if (ind_fd != -1)
(void) fchown(ind_fd, owner, group);
if (var_fd != -1)
(void) fchown(var_fd, owner, group);
/*
* Allocate File Control Block.
*/
fcb = (Fcb *) _ismalloc(sizeof(*fcb));
memset ((char *) fcb, 0, sizeof(*fcb));
fcb->isfname = _isallocstring(isfname);
fcb->rdonly = FALSE;
fcb->datfd = dat_fd;
fcb->indfd = ind_fd;
fcb->varfd = var_fd;
fcb->datsize = N_CNTL_PAGES; /* Control Pages */
fcb->indfreelist = FREELIST_NOPAGE;
/* Key descriptor */
fcb->nkeys = 1;
fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
return (fcb);
ERROR:
/* Undo whatever was done. */
if (dat_fd != -1) {
(void) close(dat_fd);
_remove_datfile(isfname);
}
if (ind_fd != -1) {
(void) close(ind_fd);
_remove_indfile(isfname);
}
if (var_fd != -1) {
(void) close(var_fd);
_remove_varfile(isfname);
}
(void) umask(oldumask);
return (NULL);
}
/*
* _isfcb_setlength(fcb, varflag, minreclen, maxreclen)
*
* Set FCB attributes pertaining to record length.
*/
void
_isfcb_setreclength(Fcb *fcb, Bool varflag, int minreclen, int maxreclen)
{
fcb->varflag = varflag;
fcb->minreclen = minreclen;
fcb->maxreclen = maxreclen;
}
/*
* _isfcb_open(isfname, errcode)
*
* Open ISAM file: open UNIX files and create File Control Block.
*
* Return 0 if open is successful, or -1 if any error. In the case of an error,
* the errcode block is set.
*
* Note that rdonly is not fuly implemented. Now, all ISAM files are assumed
* to have permissions set to 0666 and may be opened in RW mode.
* If read-only media are used then the _open_datfile() function would have to
* try first to open the file in RW mode, and of that failed, try to
* open it in RO mode. The rdonly flag is used to reject any isamopen() with
* INOUT or OUTPUT mode on such files.
*/
Fcb *
_isfcb_open(char *isfname, struct errcode *errcode)
{
Fcb *fcb;
int dat_fd = -1;
int ind_fd = -1;
int var_fd = -1;
Bool rdonly; /* set to 1 if file is Read-Only */
/*
* Open the UNIX file for .rec file.
*/
if ((dat_fd = _open_datfile (isfname, &rdonly)) == -1 || errno == EMFILE) {
_amseterrcode(errcode, errno);
if(dat_fd != -1) {
close(dat_fd);
}
return (NULL);
}
/*
* Open .ind file.
*/
ind_fd = _open_indfile (isfname, rdonly);
/*
* Open .var file.
*/
var_fd = _open_varfile (isfname, rdonly);
/*
* Allocate File Control Block.
*/
fcb = (Fcb *) _ismalloc(sizeof(*fcb));
memset ((char *) fcb, 0, sizeof(*fcb));
fcb->isfname = _isallocstring(isfname);
fcb->rdonly = rdonly;
fcb->datfd = dat_fd;
fcb->indfd = ind_fd;
fcb->varfd = var_fd;
/* Key descriptor */
fcb->nkeys = 1;
fcb->keys = (Keydesc2 *) _ismalloc(sizeof(fcb->keys[0]));
memset((char *)fcb->keys, 0, sizeof(fcb->keys[0]));
return (fcb);
}
/*
* _isfcb_nfds(fcb)
*
* Return the number of UNIX fd consumed by the fcb block.
*/
int
_isfcb_nfds(Fcb *fcb)
{
int count = 0;
if (fcb->datfd != -1)
count++;
if (fcb->indfd != -1)
count++;
if (fcb->varfd != -1)
count++;
return (count);
}
/*
* _isfcb_remove(fcb)
*
* Remove UNIX files associated with an FCB.
*/
void
_isfcb_remove(Fcb *fcb)
{
if (fcb->datfd)
_remove_datfile(fcb->isfname);
if (fcb->indfd)
_remove_indfile(fcb->isfname);
if (fcb->varfd)
_remove_varfile(fcb->isfname);
}
/*
* _isfcb_close(fcb)
*
* Close UNIX files associated with an FCB, deallocate the FCB block.
*/
void
_isfcb_close(Fcb *fcb)
{
assert (fcb != NULL);
assert (fcb->isfname != NULL);
(void) close(fcb->datfd);
(void) close(fcb->indfd);
(void) close(fcb->varfd);
_isfreestring(fcb->isfname);
free((char *)fcb->keys);
free((char *)fcb);
}
/*
* _isfcb_cntlpg_w(fcb)
*
* Write information from the control block to the disk.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_w(Fcb *fcb)
{
char cntl_page[ISCNTLSIZE];
int dat_fd = fcb->datfd;
int i;
/* Clear the page. */
memset (cntl_page, 0, sizeof(cntl_page));
/* Set Magic number. */
(void)strcpy(cntl_page + CP_MAGIC_OFF, ISMAGIC);
/* Set Block size */
stshort(ISPAGESIZE, cntl_page + CP_BLOCKSIZE_OFF);
/* Set NetISAM version stamp. */
(void)strcpy(cntl_page + CP_VERSION_OFF, ISVERSION);
/* .rec file size in blocks. */
stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
/* Variable length 0/1 flag. */
stshort((short)fcb->varflag, cntl_page + CP_VARFLAG_OFF);
/* Number of records. */
stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
/* Minimum and maximum record length. */
stshort((short)fcb->minreclen, cntl_page + CP_MINRECLEN_OFF);
stshort((short)fcb->maxreclen, cntl_page + CP_MAXRECLEN_OFF);
/* Last record number. */
strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
/* Number of keys */
stshort((short)fcb->nkeys, cntl_page + CP_NKEYS_OFF);
/* Last key id */
stlong((long)fcb->lastkeyid, cntl_page + CP_LASTKEYID_OFF);
/* ind. free list head */
stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
/* offset of the end of .var file */
stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
/* Key descriptors. */
for (i = 0; i < fcb->nkeys; i++) {
stkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
}
/* Increment stamp1 and stamp2 to indicate change in the Control Page. */
fcb->changestamp1++;
fcb->changestamp2++;
stlong((long)fcb->changestamp1, cntl_page + CP_CHANGESTAMP1_OFF);
stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Write the buffer to the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
_iswritepg(dat_fd, cntl_page);
_iswritepg(dat_fd, cntl_page + ISPAGESIZE);
return (ISOK);
}
/*
* _isfcb_cntlpg_w2(fcb)
*
* Write information from the control block to the disk.
* Write only selected fields of the control block to avoid the overhead
* of coding and decoding.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_w2(Fcb *fcb)
{
char cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
int dat_fd = fcb->datfd;
/*
* Read the page from disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)read(dat_fd, cntl_page, sizeof(cntl_page));
/* .rec file size in blocks. */
stlong((long)fcb->datsize, cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
stlong((long)fcb->indsize, cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
stlong((long)fcb->varsize, cntl_page + CP_VARSIZE_OFF);
/* Number of records. */
stlong((long)fcb->nrecords, cntl_page + CP_NRECORDS_OFF);
/* Last record number. */
strecno(fcb->lastrecno, cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
strecno(fcb->freerecno, cntl_page + CP_FREERECNO_OFF);
/* ind. free list head */
stlong((long)fcb->indfreelist, cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
stlong((long)fcb->varend, cntl_page + CP_VAREND_OFF);
/* Increment stamp2 to indicate change in the Control Page. */
fcb->changestamp2++;
stlong((long)fcb->changestamp2, cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Write the buffer to the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)write(dat_fd, cntl_page, sizeof(cntl_page));
return (ISOK);
}
/*
* _isfcb_cntlpg_r(fcb)
*
* Read information from control page and store it in the FCB.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if read was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_r(Fcb *fcb)
{
char cntl_page[ISCNTLSIZE];
int dat_fd = fcb->datfd;
int i;
/*
* Read the page from the disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
_isreadpg(dat_fd, cntl_page);
_isreadpg(dat_fd, cntl_page + ISPAGESIZE);
/* block size */
fcb->blocksize = ldshort(cntl_page + CP_BLOCKSIZE_OFF);
/* .rec file size in blocks. */
fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
/* Variable length 0/1 flag. */
fcb->varflag = (Bool)ldshort(cntl_page + CP_VARFLAG_OFF);
/* Number of records. */
fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
/* Minimum and maximum record length. */
fcb->minreclen = ldunshort(cntl_page + CP_MINRECLEN_OFF);
fcb->maxreclen = ldunshort(cntl_page + CP_MAXRECLEN_OFF);
/* Last record number. */
fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
/* Last key id */
fcb->lastkeyid = ldlong(cntl_page + CP_LASTKEYID_OFF);
/* .ind free list head. */
fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
/* Number of keys */
fcb->nkeys = ldshort(cntl_page + CP_NKEYS_OFF);
/*
* Read key descriptors.
*/
fcb->keys = (Keydesc2 *)
_isrealloc((char *)fcb->keys,
(unsigned) (sizeof(Keydesc2) * fcb->nkeys));
memset((char *)fcb->keys, 0, sizeof(Keydesc2) * fcb->nkeys);
for (i = 0; i < fcb->nkeys; i++) {
ldkey(fcb->keys + i, cntl_page + CP_KEYS_OFF + i * K2_LEN);
}
/* Changestamp1 */
fcb->changestamp1 = ldlong(cntl_page + CP_CHANGESTAMP1_OFF);
/* Changestamp2 */
fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
/*
* Open .ind file in situations when some other process has created
* keys and this process has just learned it now.
*/
if (fcb->nkeys > 1 || !FCB_NOPRIMARY_KEY(fcb)) {
/*
if (_open2_indfile(fcb) != ISOK)
_isfatal_error("_open2_indfile()");
*/
(void)_open2_indfile(fcb);
}
return (ISOK);
}
/*
* _isfcb_cntlpg_r2(fcb)
*
* Read information from the control block on the disk.
* Read only selected fields of the control block to avoid the overhead
* of coding and decoding.
* Note that the Control Page transfer bypasses the disk buffer manager.
*
* Return 0 if write was successful, return -1 if any error.
*/
int
_isfcb_cntlpg_r2(Fcb *fcb)
{
char cntl_page[CP_VAREND_OFF+CP_VAREND_LEN];
int dat_fd = fcb->datfd;
/*
* Read the page from disk.
*/
_isseekpg(dat_fd, ISCNTLPGOFF);
(void)read(dat_fd, cntl_page, sizeof(cntl_page));
/*
* Check changestamp1. If the stamp has changed, we must read the entire
* page and update the FCB.
*/
if (ldlong(cntl_page + CP_CHANGESTAMP1_OFF) != fcb->changestamp1) {
(void)_isfcb_cntlpg_r(fcb);
}
/*
*_isfcb_cntlpg_r2() is called if transaction is rolled back.
* We cannot test changestamp2; we must read the info into the FCB
* always.
*/
#if 0
/*
* Check changestamp2. If the stamp has not changed, the FCB contains
* up-to-date information.
*/
if (ldlong(cntl_page + CP_CHANGESTAMP2_OFF) == fcb->changestamp2) {
return (ISOK);
}
#endif
/* .rec file size in blocks. */
fcb->datsize = ldlong(cntl_page + CP_DATSIZE_OFF);
/* .ind file size in blocks. */
fcb->indsize = ldlong(cntl_page + CP_INDSIZE_OFF);
/* .var file size in blocks. */
fcb->varsize = ldlong(cntl_page + CP_VARSIZE_OFF);
/* Number of records. */
fcb->nrecords = ldlong(cntl_page + CP_NRECORDS_OFF);
/* Last record number. */
fcb->lastrecno = ldrecno(cntl_page + CP_LASTRECNO_OFF);
/* Free record number. */
fcb->freerecno = ldrecno(cntl_page + CP_FREERECNO_OFF);
/* .ind free list head. */
fcb->indfreelist = ldlong(cntl_page + CP_INDFREELIST_OFF);
/* end of .var file */
fcb->varend = ldlong(cntl_page + CP_VAREND_OFF);
/* Changestamp2 */
fcb->changestamp2 = ldlong(cntl_page + CP_CHANGESTAMP2_OFF);
return (ISOK);
}
/*
* _create_datfile(isfname)
*
* Create .rec file for ISAM file isfname.
*/
Static int
_create_datfile(char *isfname)
{
int fd;
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makedat_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
/* Close on exec */
if(fcntl(fd, F_SETFD, 1) == -1) {
close(fd);
return(-1);
}
}
return (fd);
}
/*
* _create_indfile(isfname)
*
* Create .ind file for ISAM file isfname.
*/
Static int
_create_indfile(char *isfname)
{
int fd;
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makeind_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
/* Close on exec */
if(fcntl(fd, F_SETFD, 1) == -1) {
close(fd);
return(-1);
}
}
return (fd);
}
/*
* _create_varfile(isfname)
*
* Create .var file for ISAM file isfname.
*/
Static int
_create_varfile(char *isfname)
{
int fd;
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makevar_isfname(namebuf);
fd = open (namebuf, O_CREAT | O_EXCL | O_RDWR, 0666);
if (fd > -1) {
/* Close on exec */
if(fcntl(fd, F_SETFD, 1) == -1) {
close(fd);
return(-1);
}
}
return (fd);
}
/*
* _remove_datfile(isfname)
*
* Remove .rec file for ISAM file isfname.
*/
Static void
_remove_datfile(char *isfname)
{
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makedat_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _remove_indfile(isfname)
*
* Remove .ind file for ISAM file isfname.
*/
Static void
_remove_indfile(char *isfname)
{
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makeind_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _remove_varfile(isfname)
*
* Remove .var file for ISAM file isfname.
*/
Static void
_remove_varfile(char *isfname)
{
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makevar_isfname(namebuf);
(void) unlink(namebuf);
}
/*
* _open_datfile(isfname)
*
* Open .rec file for ISAM file isfname.
*/
Static int
_open_datfile(char *isfname, Bool *rdonly)
{
char namebuf[MAXPATHLEN];
int ret;
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makedat_isfname(namebuf);
if ((ret = open (namebuf, O_RDWR)) != -1) {
*rdonly = FALSE;
/* Close on exec */
if(fcntl(ret, F_SETFD, 1) == -1) {
close(ret);
ret = -1;
}
return (ret);
}
*rdonly = TRUE;
ret = open (namebuf, O_RDONLY);
if (ret > -1) {
/* Close on exec */
if(fcntl(ret, F_SETFD, 1) == -1) {
close(ret);
return(-1);
}
}
return (ret);
}
/*
* _open_indfile(isfname)
*
* Open .ind file for ISAM file isfname.
*/
Static int
_open_indfile(char *isfname, Bool rdonly)
{
int fd;
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makeind_isfname(namebuf);
fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
if (fd > -1) {
/* Close on exec */
if(fcntl(fd, F_SETFD, 1) == -1) {
close(fd);
return(-1);
}
}
return (fd);
}
/*
* _open_varfile(isfname)
*
* Open .var file for ISAM file isfname.
*/
Static int
_open_varfile(char *isfname, Bool rdonly)
{
int fd;
char namebuf[MAXPATHLEN];
snprintf(namebuf, sizeof(namebuf), "%s", isfname);
_makevar_isfname(namebuf);
fd = open (namebuf, (rdonly==TRUE)?O_RDONLY:O_RDWR);
if (fd > -1) {
/* Close on exec */
if(fcntl(fd, F_SETFD, 1) == -1) {
close(fd);
return(-1);
}
}
return (fd);
}
int
_check_isam_magic(Fcb *fcb)
{
char magicbuffer[CP_MAGIC_LEN];
(void)lseek(fcb->datfd, 0L, 0);
if ((read(fcb->datfd, magicbuffer, CP_MAGIC_LEN) < CP_MAGIC_LEN) ||
/* The following test for compatibilty with `SunISAM 1.0 Beta files. */
((strncmp(magicbuffer, "SunISAM", strlen(ISMAGIC)) != 0) &&
(strncmp(magicbuffer, ISMAGIC, strlen(ISMAGIC))) != 0)) {
return ISERROR;
}
else
return ISOK;
}
/*
* _open2_indfile(fcb)
*
* Open (or create) .ind file for ISAM file if the .ind file
* is not open already (or does not exist).
*/
int
_open2_indfile(Fcb *fcb)
{
char namebuf[MAXPATHLEN];
struct stat buf;
int openmode;
if (fcb->indfd != -1)
return (ISOK);
snprintf(namebuf, sizeof(namebuf), "%s", fcb->isfname);
_makeind_isfname(namebuf);
(void)fstat(fcb->datfd, &buf);
openmode = (fcb->rdonly) ? O_RDONLY : O_RDWR;
if (fcb->indsize == 0)
openmode |= O_CREAT;
fcb->indfd = open(namebuf, openmode, buf.st_mode);
if (fcb->indfd > -1) {
/* Close on exec */
if(fcntl(fcb->indfd, F_SETFD, 1) == -1) {
close(fcb->indfd);
fcb->indfd = -1;
}
}
if(fcb->indfd == -1 && (openmode & O_CREAT)) {
_isfatal_error("Cannot create .ind file");
}
if (fcb->indfd != -1) {
(void) _watchfd_incr(1);
(void)fchown(fcb->indfd, buf.st_uid, buf.st_gid);
}
return ((fcb->indfd == -1) ? ISERROR : ISOK);
}