blob: 03cd8d106b80aae85b8b935843d8bd7a31edea81 [file] [log] [blame]
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <stdlib.h>
#include <stdio.h>
#include <parlib/parlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <iplib/iplib.h>
#include <ndblib/ndb.h>
#include <ndblib/ndbhf.h>
static struct ndb* doopen(char*);
static void hffree(struct ndb*);
static char *deffile = "/lib/ndb/local";
/*
* the database entry in 'file' indicates the list of files
* that makeup the database. Open each one and search in
* the same order.
*/
struct ndb*
ndbopen(char *file)
{
struct ndb *db, *first, *last;
struct ndbs s;
struct ndbtuple *t, *nt;
if(file == 0)
file = deffile;
db = doopen(file);
if(db == 0) {
return 0;
}
first = last = db;
t = ndbsearch(db, &s, "database", "");
fseek(db->b, 0, 0);
if(t == 0) {
return db;
}
for(nt = t; nt; nt = nt->entry){
if(strcmp(nt->attr, "file") != 0)
continue;
if(strcmp(nt->val, file) == 0){
/* default file can be reordered in the list */
if(first->next == 0)
continue;
if(strcmp(first->file, file) == 0){
db = first;
first = first->next;
last->next = db;
db->next = 0;
last = db;
}
continue;
}
db = doopen(nt->val);
if(db == 0)
continue;
last->next = db;
last = db;
}
ndbfree(t);
return first;
}
/*
* open a single file
*/
static struct ndb*
doopen(char *file)
{
struct ndb *db;
db = (struct ndb*)calloc(sizeof(struct ndb), 1);
if(db == 0) {
return 0;
}
memset(db, 0, sizeof(struct ndb));
strncpy(db->file, file, sizeof(db->file)-1);
if(ndbreopen(db) < 0){
free(db);
return 0;
}
return db;
}
/*
* dump any cached information, forget the hash tables, and reopen a single file
*/
int
ndbreopen(struct ndb *db)
{
int fd;
struct dir *d;
/* forget what we know about the open files */
if(db->isopen){
_ndbcacheflush(db);
hffree(db);
fclose(db->b);
db->mtime = 0;
db->isopen = 0;
}
/* try the open again */
db->b = fopen(db->file, "r");
if(! db->b) {
return -1;
}
#if 0
d = dirfstat(fd);
if(d == NULL){
close(fd);
return -1;
}
db->qid.path = d->qid.path;
db->mtime = d->mtime;
db->length = d->length;
free(d);
#else
struct stat s;
/* we opened it, this WILL work */
stat(db->file, &s);
db->qid.path = s.st_ino;
db->mtime = s.st_mtime + 1;
db->length = s.st_size;
#endif
db->isopen = 1;
return 0;
}
/*
* close the database files
*/
void
ndbclose(struct ndb *db)
{
struct ndb *nextdb;
for(; db; db = nextdb){
nextdb = db->next;
_ndbcacheflush(db);
hffree(db);
fclose(db->b);
free(db);
}
}
/*
* free the hash files belonging to a db
*/
static void
hffree(struct ndb *db)
{
struct ndbhf *hf, *next;
for(hf = db->hf; hf; hf = next){
next = hf->next;
close(hf->fd);
free(hf);
}
db->hf = 0;
}
/*
* return true if any part of the database has changed
*/
int
ndbchanged(struct ndb *db)
{
/* TODO: implement me (no one calls this yet) */
assert(0);
return 0;
#if 0
struct ndb *ndb;
struct dir *d;
/* FIX ME */
for(ndb = db; ndb != NULL; ndb = ndb->next){
d = dirfstat(Bfildes(&ndb->b));
if(d == NULL)
continue;
if(ndb->qid.path != d->qid.path
|| ndb->qid.vers != d->qid.vers){
free(d);
return 1;
}
free(d);
}
return 0;
#endif
}