/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/DB/RCS/hashdir.c,v 1.2 91/08/07 00:48:20 mjr Exp $"; #endif /* configure all options BEFORE including system stuff. */ #include "config.h" #ifdef DB_DIRHASH #include <stdio.h> #include <sys/types.h> #include <sys/file.h> #include <sys/param.h> #ifdef FCNTL_H #include <fcntl.h> #endif #ifdef DIRENT #include <dirent.h> #else #include <sys/dir.h> #endif #include "mud.h" /* default (runtime-resettable) directory hash size for permanent storage */ #ifndef DEFAULT_HASH_SIZE #define DEFAULT_HASH_SIZE 11 #endif /* noisy complaints in the log if we can't find something. useful for tracking "lost" objects */ #define HASHDIR_DEBUG /* default object storage routines. these store objects one per file in a hashed directory structure. this is faster than it might seem at first, and has the benefit of making it easy to online edit objects. */ /* initial hash directory pointer and hash size */ static char *hashpath = DEFAULT_HASHDIR; static int hashsiz = DEFAULT_HASH_SIZE; static DIR *dirp = (DIR *)0; static int currdir = -1; static int db_initted = 0; /* initialize the database. this is pretty trivial in this version. :) */ int dhdb_init() { db_initted = 1; return(0); } int dhdb_close() { db_initted = 0; return(0); } /* is it initialized ? */ int dhdb_initted() { return(db_initted); } /* set hash table size */ int dhdb_sethsiz(newsiz) int newsiz; { return(hashsiz = newsiz); } /* configure hash path */ int dhdb_sethpath(newpath) char *newpath; { char *xp; if(db_initted) return(1); xp = (char *)malloc((unsigned)(strlen(newpath) + 1)); if(xp == (char *)0) return(1); (void)strcpy(xp,newpath); hashpath = xp; return(0); } /* thaw an object from disk (or whatever) and return it, or NULL in the event of an error. all you get is the name of the object to thaw, and nothing more. */ Obj * dhdb_get(nam) char *nam; { FILE *inf; Obj *ret; int hv = 0; char fn[MAXPATHLEN]; #ifdef NO_AT_IN_PATHS char *p; #endif if(!db_initted) return((Obj *)0); /* hash to directory slot on object # */ hv = objid_hash(nam,hashsiz); (void)sprintf(fn,"%s/%d/%s",hashpath,hv,nam); #ifdef NO_AT_IN_PATHS /* VMS hates @ in file names. Bash it into a _ */ for(p = fn; *p != '\0' && *p; p++) { if(*p == '@') { *p = '_'; break; } } #endif if((inf = fopen(fn,"r")) == (FILE *)0) { #ifdef HASHDIR_DEBUG logf("db_get: cannot open ",fn," ",(char *)-1,"\n",(char *)0); #endif return((Obj *)0); } /* if the file is badly formatted, ret == Obj * 0 */ if((ret = oiffromFILE(inf,(char *)0)) == (Obj *)0) logf("db_get: cannot decode ",fn," ",(char *)-1,"\n",(char *)0); (void)fclose(inf); return(ret); } /* freeze an object to disk (or whatever) and return 0, or -1. */ int dhdb_put(obj,nam) Obj *obj; char *nam; { FILE *ofi; int hv = 0; char fn[MAXPATHLEN]; #ifdef NO_AT_IN_PATHS char *p; #endif if(!db_initted) return(1); hv = objid_hash(nam,hashsiz); (void)sprintf(fn,"%s/%d/%s",hashpath,hv,nam); #ifdef NO_AT_IN_PATHS /* VMS hates @ in file names. Bash it into a _ */ for(p = fn; *p != '\0' && *p; p++) { if(*p == '@') { *p = '_'; break; } } #endif if((ofi = fopen(fn,"w")) == (FILE *)0) { #ifdef HASHDIR_DEBUG logf("db_put: can't open ",fn," ",(char *)-1,"\n",(char *)0); #endif return(-1); } if((hv = oiftoFILE(obj,ofi,nam)) != 0) logf("db_put: can't save ",fn," ",(char *)-1,"\n",(char *)0); (void)fclose(ofi); return(hv); } /* probe for existence of the object in the database. this could use access(2), but it's a stupid system call and I don't like it. plus, no two systems seem to do it the same way (other than stupid). */ int dhdb_check(nam) char *nam; { #ifdef NO_AT_IN_PATHS char *p; #endif int fd = 0; char fn[MAXPATHLEN]; if(!db_initted) return(0); /* hash to directory slot on object # */ fd = objid_hash(nam,hashsiz); (void)sprintf(fn,"%s/%d/%s",hashpath,fd,nam); #ifdef NO_AT_IN_PATHS for(p = fn; *p != '\0' && *p; p++) { if(*p == '@') { *p = '_'; break; } } #endif if((fd = open(fn,O_RDONLY,0600)) < 0) return(0); (void)close(fd); return(1); } /* clobber something out of the database */ int dhdb_del(nam,flg) char *nam; int flg; { #ifdef NO_AT_IN_PATHS char *p; #endif char fn[MAXPATHLEN]; if(!db_initted) return(1); (void)sprintf(fn,"%s/%d/%s",hashpath,objid_hash(nam,hashsiz),nam); #ifdef NO_AT_IN_PATHS /* VMS hates @ in file names. Bash it into a _ */ for(p = fn; *p != '\0' && *p; p++) { if(*p == '@') { *p = '_'; break; } } #endif unlink(fn); return(0); } int dhdb_travstart() { char fn[MAXPATHLEN]; /* already open */ if(!db_initted || currdir != -1 || dirp != (DIR *)0) return(1); currdir = 0; (void)sprintf(fn,"%s/%d",hashpath,currdir); if((dirp = opendir(fn)) == (DIR *)0) return(1); return(0); } int dhdb_traverse(ob) char *ob; { #ifdef DIRENT struct dirent *drp; #else struct direct *drp; #endif char fn[MAXPATHLEN]; if(!db_initted) return(0); while(1) { #ifdef DIRENT if((drp = readdir(dirp)) == (struct dirent *)0) { #else if((drp = readdir(dirp)) == (struct direct *)0) { #endif if(++currdir >= hashsiz) return(0); closedir(dirp); (void)sprintf(fn,"%s/%d",hashpath,currdir); if((dirp = opendir(fn)) == (DIR *)0) break; continue; } if(drp->d_name[0] == '.') continue; strncpy(ob,drp->d_name,MAXOID); return(1); } return(0); } int dhdb_travend() { if(!db_initted) return(0); if(dirp != (DIR *)0) { closedir(dirp); dirp = (DIR *)0; currdir = -1; } return(0); } dhdb_backup(out) char *out; { #ifdef DIRENT struct dirent *drp; #else struct direct *drp; #endif int red; char buf[BUFSIZ]; char fn[MAXPATHLEN]; int ifd; int ofd; currdir = 0; (void)sprintf(fn,"%s/%d",hashpath,currdir); if((dirp = opendir(fn)) == (DIR *)0) return(1); if((ofd = open(out,O_WRONLY|O_CREAT,0600)) < 0) { closedir(dirp); dirp = (DIR *)0; return(1); } while(1) { #ifdef DIRENT if((drp = readdir(dirp)) == (struct dirent *)0) { #else if((drp = readdir(dirp)) == (struct direct *)0) { #endif if(++currdir >= hashsiz) break; closedir(dirp); (void)sprintf(fn,"%s/%d",hashpath,currdir); if((dirp = opendir(fn)) == (DIR *)0) break; continue; } if(drp->d_name[0] == '.') continue; /* copy file out */ (void)sprintf(fn,"%s/%d/%s",hashpath,currdir,drp->d_name); if((ifd = open(fn,O_RDONLY,0600)) < 0) { logf("db_backup: can't open ",fn," ",(char *)-1,"\n",(char *)0); continue; } while((red = read(ifd,buf,sizeof(buf))) > 0) { if(write(ofd,buf,red) != red) { logf("db_backup: can't write ",(char *)-1,"\n",(char *)0); close(ifd); break; } } close(ifd); } closedir(dirp); dirp = (DIR *)0; close(ofd); return(0); } #endif DB_DIRHASH