示例#1
0
int g_check_header(GFile *gfile)
/*
 * Checks whether the on-disk copy matches the in-memory copy of the
 * header.
 *
 * The rationale behind this is that users still manually remove the BUSY
 * file because "they know best". They then act all suprised when their
 * database becomes corrupt. Our alternative here is to check the master
 * time-stamp in the Aux header and to simply abort Gap4 (losing all unsaved
 * edits) if it has been changed external to this process.
 *
 * For efficiencies sake, we do not want to call this function too often.
 * Hence it is planned to be called only on the first disk update after a
 * flush. This still leaves room for race conditions (multiple people editing
 * simultaenously), but it covers the more common case of a gap4 session
 * left open for ages and then going back to it later.
 */
{
    AuxHeader diskheader;

    if (gfile == NULL)
	return gerr_set(GERR_INVALID_ARGUMENTS);

    /* Re-read from disk */
    if (-1==lseek(gfile->fdaux,0,0))
	return gerr_set(GERR_SEEK_ERROR);

    g_read_aux_header(gfile, &diskheader);

    if (diskheader.last_time != gfile->header.last_time) {
	fprintf(stderr, "** SERIOUS PROBLEM - file %s\n",
		g_filename(gfile));
	fprintf(stderr, "** Time stamp modified by another process\n");
	fprintf(stderr, "** Hint: DO NOT REMOVE LOCK FILES!\n**\n");
	fprintf(stderr, "** The '%s.log' file contains information on\n",
		g_filename(gfile));
	fprintf(stderr, "** who else has the database open.\n");
	panic_shutdown();
    }

    return 0;
}
示例#2
0
GFile *g_open_file(char *fn, int read_only)
/*
 * Open a file and its associated index
 * On Error:
 *	Returns NULL
 *      Sets xerrno
 */
{
    GFile *gfile;
    char fnaux[1024];
    AuxIndex *idx_arr = NULL;
    int64_t recsize;

    /* g_dump_file(fn); */

    gfile = NULL;

#define ABORT(E)\
    {\
         if (idx_arr) \
             xfree(idx_arr); \
	 g_free_gfile(gfile); \
	 gfile = NULL; \
	 (void)gerr_set(E); \
	 return NULL; \
    }

    /* check file name isn't too long */
    if ( strlen(fn) + strlen(G_AUX_SUFFIX) >= sizeof(fnaux) )
	ABORT(GERR_NAME_TOO_LONG);
    strcpy(fnaux,fn);
    strcat(fnaux,G_AUX_SUFFIX);

    /* allocate new data structure - GFile */
    gfile = g_new_gfile(G_32BIT);
    if (gfile == NULL)
	ABORT(GERR_OUT_OF_MEMORY);

    /* check access privilages */
    /* YUK! - to do */

    /* set file name */
    if ( (gfile->fname = (char *)xmalloc(strlen(fn)+1)) != NULL )
	strcpy(gfile->fname,fn);
    
    /* open file and its aux */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fd = open(fn,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fd = open(fn,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fdaux = open(fnaux,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fdaux = open(fnaux,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);

#if 0
    /*
     * WARNING: See warning in gap4/actf.c for why this is a problem and
     * has been commented out.
     */
    if (lockf(gfile->fd, F_TEST, 0)) {
	fprintf(stderr, "*** File %s is locked (inuse) by another process\n",
		fn);
	if (!read_only) {
	    close(gfile->fdaux);
	    ABORT(GERR_OPENING_FILE);
	}
    }
    if (!read_only) {
	lockf(gfile->fd, F_LOCK, 0);
    }
#endif


#ifdef USE_MMAP
    {
	struct stat sb;

	stat(fn, &sb);
	gfile->fdmap = (char *)mmap(NULL, sb.st_size, PROT_READ,
				    MAP_FILE | /* MAP_FIXED | */ MAP_SHARED,
				    gfile->fd, 0);
    }
#endif

    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,0,0))
	ABORT(GERR_SEEK_ERROR);

    if (g_read_aux_header(gfile, &gfile->header))
	ABORT(GERR_READ_ERROR);

/*
    fprintf(stderr,"** \n");
    fprintf(stderr,"** Opening file %s\n",fn);
    fprintf(stderr,"**    file_size = %d\n",  gfile->header.file_size);
    fprintf(stderr,"**   block_size = %d\n", gfile->header.block_size);
    fprintf(stderr,"**  num_records = %d\n",gfile->header.num_records);
    fprintf(stderr,"**  max_records = %d\n",gfile->header.max_records);
    fprintf(stderr,"**    last_time = %d\n",  gfile->header.last_time);
    fprintf(stderr,"**        flags = %d\n",      gfile->header.flags);
    fprintf(stderr,"**    free_time = %d\n",  gfile->header.free_time);
    fprintf(stderr,"** \n");
*/

    /* allocate index */
    gfile->Nidx = 0;
    gfile->idx = NULL;

    /* LOW LEVEL IO HERE */
    errno = 0;
    recsize = (gfile->header.format == G_32BIT)
	? sizeof(AuxIndex32)
	: sizeof(AuxIndex);
    lseek(gfile->fdaux,
	  sizeof(AuxHeader) + gfile->header.num_records * recsize,
	  SEEK_SET);

    /* Initialise the dheap */
    gfile->dheap = heap_fdload(gfile->fd);

    /* read aux index and initialise */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,sizeof(AuxHeader),0))
	ABORT(GERR_SEEK_ERROR);

#undef ABORT

    return gfile;
}
示例#3
0
GFile *g_open_file(char *fn, int read_only)
/*
 * Open a file and its associated index
 * On Error:
 *	Returns NULL
 *      Sets xerrno
 */
{
    GFile *gfile;
    char fnaux[1024], fndb[1024], fnorig[1024];
    AuxIndex *idx_arr = NULL;
    int64_t recsize;
    int try;

    /* g_dump_file(fn); */

    gfile = NULL;

#define ABORT(E)\
    {\
         if (idx_arr) \
             xfree(idx_arr); \
	 g_free_gfile(gfile); \
	 gfile = NULL; \
	 (void)gerr_set(E); \
	 return NULL; \
    }

    /* check file name isn't too long */
    if ( strlen(fn) + strlen(G_AUX_SUFFIX) >= sizeof(fnaux) )
	ABORT(GERR_NAME_TOO_LONG);
    strncpy(fnorig, fn, 1024);

    /*
     * Attempt to work alternative file names. We support
     * foo.0 + foo.0.aux as before, but also now handle
     * foo.0.g5d and foo.0.g5x.
     * Sorry this is so convoluted! It got shuffled around a lot and
     * could probably be rewritten to be a simpler structure.
     */
    for (try = 0; try < 2; try++) {
	char *cp;

	/* Try new format first */
	strcpy(fndb ,fn);
	strcat(fndb ,G5_DB_SUFFIX);
	strcpy(fnaux,fn);
	strcat(fnaux,G5_AUX_SUFFIX);

	if (file_exists(fndb) && file_exists(fnaux))
	    break;

	/* Not new. Maybe we specified suffix too though? Strip and repeat */
	if (try == 1) {
	    /* Second pass of trying new format (with/without suffix */
	    /* Fail back to old format instead then */
	    strcpy(fndb ,fnorig);
	    strcpy(fnaux,fnorig);
	    strcat(fnaux,G_AUX_SUFFIX);
    
	    if (file_exists(fndb) && file_exists(fnaux))
		break;

	    gerr_set(GERR_OPENING_FILE);
	    return NULL;
	}

	/* Not root of new, but maybe we specified a full name */
	if (!(cp = strrchr(fn, '.'))) {
	    if (try == 0)
		continue;
	    gerr_set(GERR_OPENING_FILE);
	    return NULL;
	}

	if (strcmp(cp, G_AUX_SUFFIX)     != 0 &&
	    strcmp(cp, G5_AUX_SUFFIX)    != 0 &&
	    strcmp(cp, G5_DB_SUFFIX)     != 0 &&
	    strcmp(cp, G5_COMMON_SUFFIX) != 0) {
	    if (try == 0)
		continue;

	    gerr_set(GERR_OPENING_FILE);
	    return NULL;
	}
	
	*cp = 0;
    }

    /*
     * After this, fn is the root "foo.0" while
     * fndb and fnaux are the db and aux extensions of the root.
     * (Either foo.0/foo.0.aux or foo.0.g5d/foo.0.g5x).
     */


    /* allocate new data structure - GFile */
    gfile = g_new_gfile(G_32BIT);
    if (gfile == NULL)
	ABORT(GERR_OUT_OF_MEMORY);

    /* check access privilages */
    /* YUK! - to do */

    /* set file name */
    if ( (gfile->fname = (char *)xmalloc(strlen(fn)+1)) != NULL )
	strcpy(gfile->fname,fn);
    
    /* open file and its aux */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fd = open(fndb,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fd = open(fndb,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fdaux = open(fnaux,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fdaux = open(fnaux,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);

#if 0
    /*
     * WARNING: See warning in gap4/actf.c for why this is a problem and
     * has been commented out.
     */
    if (lockf(gfile->fd, F_TEST, 0)) {
	fprintf(stderr, "*** File %s is locked (inuse) by another process\n",
		fn);
	if (!read_only) {
	    close(gfile->fdaux);
	    ABORT(GERR_OPENING_FILE);
	}
    }
    if (!read_only) {
	lockf(gfile->fd, F_LOCK, 0);
    }
#endif


#ifdef USE_MMAP
    {
	struct stat sb;

	stat(fndb, &sb);
	gfile->fdmap = (char *)mmap(NULL, sb.st_size, PROT_READ,
				    MAP_FILE | /* MAP_FIXED | */ MAP_SHARED,
				    gfile->fd, 0);
    }
#endif

    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,0,0))
	ABORT(GERR_SEEK_ERROR);

    if (g_read_aux_header(gfile, &gfile->header))
	ABORT(GERR_READ_ERROR);

/*
    fprintf(stderr,"** \n");
    fprintf(stderr,"** Opening file %s\n",fn);
    fprintf(stderr,"**    file_size = %d\n",  gfile->header.file_size);
    fprintf(stderr,"**   block_size = %d\n", gfile->header.block_size);
    fprintf(stderr,"**  num_records = %d\n",gfile->header.num_records);
    fprintf(stderr,"**  max_records = %d\n",gfile->header.max_records);
    fprintf(stderr,"**    last_time = %d\n",  gfile->header.last_time);
    fprintf(stderr,"**        flags = %d\n",      gfile->header.flags);
    fprintf(stderr,"**    free_time = %d\n",  gfile->header.free_time);
    fprintf(stderr,"** \n");
*/

    /* allocate index */
    gfile->Nidx = 0;
    gfile->idx = NULL;

    /* LOW LEVEL IO HERE */
    errno = 0;
    recsize = (gfile->header.format == G_32BIT)
	? sizeof(AuxIndex32)
	: sizeof(AuxIndex);
    lseek(gfile->fdaux,
	  sizeof(AuxHeader) + gfile->header.num_records * recsize,
	  SEEK_SET);

    /* Initialise the dheap */
    gfile->dheap = heap_fdload(gfile->fd);

    /* read aux index and initialise */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,sizeof(AuxHeader),0))
	ABORT(GERR_SEEK_ERROR);

#undef ABORT

    return gfile;
}


void g_close_file(GFile *g)
/*
 * Close a file and its associated index
 */
{
    /* tidy up files if necessary */

    /* free data structures */
    g_free_gfile(g);
}

/* 6/1/99 johnt - Don't have fcntl with Visual C++ */
#if !defined(_MSC_VER) && !defined(__APPLE__) && !defined(__MINGW32__)
int g_sync_aux_on(GFile *gfile)
/*
 * Force a flush of all prior data and then all subsequent data is to be
 * written in SYNC mode.
 */
{
    int fdaux = gfile->fdaux;
#if 0
    char c;
#endif

    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1 == fcntl(fdaux, F_SETFL, O_RDWR | O_SYNC))
	return gerr_set(GERR_SYNC);

#if 0
    /* Force a SYNC write to flush all prior data. */
    if (-1 == lseek(fdaux, 0, 0)) return gerr_set(GERR_SEEK_ERROR);
    if (-1 == read(fdaux, &c, 1)) return gerr_set(GERR_READ_ERROR);
    lseek(fdaux, 0, 0);
    if (-1 == write(fdaux, &c, 1)) return gerr_set(GERR_WRITE_ERROR);
#endif
    if (-1 == fsync(fdaux)) return gerr_set(GERR_SYNC);

    return 0;
}
示例#4
0
/*
 * Dumps a G database in an ASCII readable form. Modelled around the start
 * of the g_open_file() routine.
 */
void g_dump_file(char *fn) {
    GFile *gfile = NULL;
    char fnaux[1024];
    AuxIndex aux_ind;
    int i;

#define ABORT(E)\
    {\
	 g_free_gfile(gfile); \
	 gfile = NULL; \
	 (void)gerr_set(E); \
	 perror("ABORT"); \
	 return; \
    }

    /* check file name isn't too long */
    if (strlen(fn) + strlen(G_AUX_SUFFIX) >= sizeof(fnaux))
        ABORT(GERR_NAME_TOO_LONG);
    strcpy(fnaux, fn);
    strcat(fnaux, G_AUX_SUFFIX);

    /* allocate new data structure - GFile */
    gfile = g_new_gfile();
    if (gfile == NULL)
        ABORT(GERR_OUT_OF_MEMORY);

    /* set file name */
    if ((gfile->fname = (char *)xmalloc(strlen(fn)+1)) != NULL)
        strcpy(gfile->fname, fn);

    /* open file and its aux */
    /* LOW LEVEL IO HERE */
    if ((gfile->fd = open(fn, O_RDONLY)) == -1)
        ABORT(GERR_OPENING_FILE);
    /* LOW LEVEL IO HERE */
    if ((gfile->fdaux = open(fnaux, O_RDONLY)) == -1)
        ABORT(GERR_OPENING_FILE);

    /* LOW LEVEL IO HERE */
    if (-1 == lseek(gfile->fdaux, 0, 0))
        ABORT(GERR_SEEK_ERROR);
    if (g_read_aux_header(gfile->fdaux, &gfile->header))
        ABORT(GERR_READ_ERROR);

    printf("** \n");
    printf("** Opening file %s\n",fn);
    printf("**    file_size = %"PRIGImage"\n", gfile->header.file_size);
    printf("**   block_size = %"PRIGCardinal"\n", gfile->header.block_size);
    printf("**  num_records = %"PRIGCardinal"\n", gfile->header.num_records);
    printf("**  max_records = %"PRIGCardinal"\n", gfile->header.max_records);
    printf("**    last_time = %"PRIGCardinal"\n", gfile->header.last_time);
    printf("**        flags = %"PRIGHFlags"\n", gfile->header.flags);
    printf("** \n");

    /* allocate index */
    gfile->Nidx = gfile->header.num_records;
    if ((gfile->idx = ArrayCreate(sizeof(Index), gfile->Nidx)) == NULL )
        ABORT(GERR_OUT_OF_MEMORY);

    (void) ArrayRef(gfile->idx, gfile->Nidx-1);
    for(i = 0; i < gfile->Nidx; i++)
        arr(Index, gfile->idx, i).flags = G_INDEX_NEW;

    /* read aux index and initialise */
    /* LOW LEVEL IO HERE */
    if (-1 == lseek(gfile->fdaux, sizeof(AuxHeader), 0))
        ABORT(GERR_SEEK_ERROR);

    /* force Array.max field to be updated */
    (void)ArrayRef(gfile->idx, gfile->header.num_records-1);

    printf("global_time %08x\n", gfile->header.last_time);

    for (i = 0; i < gfile->header.num_records; i++) {
        char buf[MAX_BUF];
        int toggle, len, len_r;

        /* Load index for this record */
        if (g_read_aux_index(gfile->fdaux, &aux_ind))
            ABORT(GERR_READ_ERROR);

        /* Compute toggle */
        toggle = g_toggle_state(gfile->header.last_time, &aux_ind);

        /* LOW LEVEL IO HERE */
        if (-1 == lseek(gfile->fd, aux_ind.image[toggle], 0))
            ABORT(GERR_SEEK_ERROR);

        len = MIN(aux_ind.used[toggle], MAX_BUF);
        /* LOW LEVEL IO HERE */
        if (-1 == (len_r = read(gfile->fd, buf, len)))
            ABORT(GERR_READ_ERROR);
        if (len_r != len) {
            fprintf(stderr, "WARNING: Read too short. Requested %d, got %d\n",
                    len, len_r);
        }

        printf("record %05d pos %020"PRIGImage" len %08d : %08x",
               i, aux_ind.image[toggle], aux_ind.used[toggle],
               (((((buf[0] << 8) + buf[1]) << 8) + buf[2]) << 8) + buf[3]);
        if (len > 4)
            printf(" %c%c%c%c%c%c%c%c\n",
                   isprint(buf[4])?buf[4]:'.',
                   isprint(buf[5])?buf[5]:'.',
                   isprint(buf[6])?buf[6]:'.',
                   isprint(buf[7])?buf[7]:'.',
                   isprint(buf[8])?buf[8]:'.',
                   isprint(buf[9])?buf[9]:'.',
                   isprint(buf[10])?buf[10]:'.',
                   isprint(buf[11])?buf[11]:'.');
        else
            putchar('\n');
    }

#undef ABORT

    g_free_gfile(gfile);
    return;
}
示例#5
0
/*
 * Given an input filename 'fn' output to *fndb and *fnaux.
 * We also trim fn to be the root, removing any suffix.
 * N.B.: This now allocates *fndb and *fnaux.  The caller should free them.
 *
 * We support foo.0 + foo.0.aux as before, but also now handle
 * foo.0.g5d and foo.0.g5x.
 * Sorry this is so convoluted! It got shuffled around a lot and
 * could probably be rewritten to be a simpler structure.
 *
 * Returns 0 on success
 *        -1 on failure (no obvious derivations of fn found).
 */
int find_db_files(char *fn, char *dir, char **fndb_out, char **fnaux_out) {
    size_t fn2l = (NULL != dir ? strlen(dir) : 0) + strlen(fn);
    char *fn2 = malloc(fn2l + 1);
    char *cp = NULL;
    char *fndb = NULL;
    char *fnaux = NULL;
    int try;
    
    if (NULL == fn2) return -1;
    fndb = malloc(fn2l + strlen(G5_DB_SUFFIX) + 1);
    if (NULL == fndb)  goto fail;
    fnaux = malloc(fn2l + strlen(G5_AUX_SUFFIX) + 1);
    if (NULL == fnaux) goto fail;

    if (dir) {
	sprintf(fn2, "%s%s", dir, fn);
    } else {
	strcpy(fn2, fn);
    }

    for (try = 0; try < 2; try++) {
	/* Try new format first */
	strcpy(fndb,  fn2);
	strcat((fndb) + fn2l,  G5_DB_SUFFIX);
	strcpy(fnaux, fn2);
	strcat((fnaux) + fn2l, G5_AUX_SUFFIX);
	
	if (file_exists(fndb) && file_exists(fnaux))
	    break;

	/* Not new. Maybe we specified suffix too though? Strip and repeat */
	if (try == 1) {
	    /* Second pass of trying new format (with/without suffix */
	    /* Fail back to old format instead then */
	    strcpy(fndb , fn2);
	    strcpy(fnaux, fn2);
	    strcat((fnaux) + fn2l, G_AUX_SUFFIX);
    
	    if (file_exists(fndb) && file_exists(fnaux))
		break;

	    goto fail;
	}

	/* Not root of new, but maybe we specified a full name */
	if (!(cp = strrchr(fn, '.'))) {
	    if (try == 0)
		continue;
	    goto fail;
	}

	if (strcmp(cp, G_AUX_SUFFIX)     != 0 &&
	    strcmp(cp, G5_AUX_SUFFIX)    != 0 &&
	    strcmp(cp, G5_DB_SUFFIX)     != 0 &&
	    strcmp(cp, G5_COMMON_SUFFIX) != 0) {
	    if (try == 0)
		continue;

	    goto fail;
	}
	
	/* Strip suffix and have another go */
	fn2l -= strlen(cp);
	fn2[fn2l] = '\0';
    }

     /*
      * Strip suffix in *fn if we found one.  Done here so that we only modify
      * the value if we succeed.
      */
    if (NULL != cp)
	*cp = 0;

    *fndb_out  = fndb;
    *fnaux_out = fnaux;

    free(fn2);
    return 0;

 fail:
    if (NULL != fndb)  free(fndb);
    if (NULL != fnaux) free(fnaux);
    free(fn2);
    return -1;
}


GFile *g_open_file(char *fn, int read_only)
/*
 * Open a file and its associated index
 * On Error:
 *	Returns NULL
 *      Sets xerrno
 */
{
    GFile *gfile;
    char *fnaux = NULL, *fndb = NULL;
    AuxIndex *idx_arr = NULL;
    int64_t recsize;

    /* g_dump_file(fn); */

    gfile = NULL;

#define ABORT(E)\
    {\
         if (idx_arr) \
             xfree(idx_arr); \
	 g_free_gfile(gfile); \
	 gfile = NULL; \
	 (void)gerr_set(E); \
	 return NULL; \
    }

    /* Attempt to work alternative file names. */
    if (find_db_files(fn, 0, &fndb, &fnaux) == -1) {
	gerr_set(GERR_OPENING_FILE);
	return NULL;
    }

    /*
     * After this, fn is the root "foo.0" while
     * fndb and fnaux are the db and aux extensions of the root.
     * (Either foo.0/foo.0.aux or foo.0.g5d/foo.0.g5x).
     */


    /* allocate new data structure - GFile */
    gfile = g_new_gfile(G_32BIT);
    if (gfile == NULL)
	ABORT(GERR_OUT_OF_MEMORY);

    /* check access privilages */
    /* YUK! - to do */

    /* set file names */
    if ( (gfile->fname = (char *)xmalloc(strlen(fn)+1)) != NULL )
	strcpy(gfile->fname,fn);
    gfile->fndb  = fndb;
    gfile->fnaux = fnaux;
    
    /* open file and its aux */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fd = open(fndb,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fd = open(fndb,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (read_only || (gfile->fdaux = open(fnaux,O_RDWR|O_BINARY)) == -1 )
	if ( !read_only || (gfile->fdaux = open(fnaux,O_RDONLY|O_BINARY)) == -1 )
	    ABORT(GERR_OPENING_FILE);

#if 0
    /*
     * WARNING: See warning in gap4/actf.c for why this is a problem and
     * has been commented out.
     */
    if (lockf(gfile->fd, F_TEST, 0)) {
	fprintf(stderr, "*** File %s is locked (inuse) by another process\n",
		fn);
	if (!read_only) {
	    close(gfile->fdaux);
	    ABORT(GERR_OPENING_FILE);
	}
    }
    if (!read_only) {
	lockf(gfile->fd, F_LOCK, 0);
    }
#endif


#ifdef USE_MMAP
    {
	struct stat sb;

	stat(fndb, &sb);
	gfile->fdmap = (char *)mmap(NULL, sb.st_size, PROT_READ,
				    MAP_FILE | /* MAP_FIXED | */ MAP_SHARED,
				    gfile->fd, 0);
    }
#endif

    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,0,0))
	ABORT(GERR_SEEK_ERROR);

    if (g_read_aux_header(gfile, &gfile->header))
	ABORT(GERR_READ_ERROR);

/*
    fprintf(stderr,"** \n");
    fprintf(stderr,"** Opening file %s\n",fn);
    fprintf(stderr,"**    file_size = %d\n",  gfile->header.file_size);
    fprintf(stderr,"**   block_size = %d\n", gfile->header.block_size);
    fprintf(stderr,"**  num_records = %d\n",gfile->header.num_records);
    fprintf(stderr,"**  max_records = %d\n",gfile->header.max_records);
    fprintf(stderr,"**    last_time = %d\n",  gfile->header.last_time);
    fprintf(stderr,"**        flags = %d\n",      gfile->header.flags);
    fprintf(stderr,"**    free_time = %d\n",  gfile->header.free_time);
    fprintf(stderr,"** \n");
*/

    /* allocate index */
    gfile->Nidx = 0;
    gfile->idx = NULL;

    /* LOW LEVEL IO HERE */
    errno = 0;
    recsize = (gfile->header.format == G_32BIT)
	? sizeof(AuxIndex32)
	: sizeof(AuxIndex);
    lseek(gfile->fdaux,
	  sizeof(AuxHeader) + gfile->header.num_records * recsize,
	  SEEK_SET);

    /* Initialise the dheap */
    gfile->dheap = heap_fdload(gfile->fd);

    /* read aux index and initialise */
    /* LOW LEVEL IO HERE */
    errno = 0;
    if (-1==lseek(gfile->fdaux,sizeof(AuxHeader),0))
	ABORT(GERR_SEEK_ERROR);

#undef ABORT

    return gfile;
}


void g_close_file(GFile *g)
/*
 * Close a file and its associated index
 */
{
    /* tidy up files if necessary */

    /* free data structures */
    g_free_gfile(g);
}