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); }
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; }
/* * 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; }
/* * 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); }