/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ /* configure all options BEFORE including system stuff. */ #include "config.h" #ifdef DB_DIRHASH #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 (int newsiz) { return (hashsiz = newsiz); } /* configure hash path */ int dhdb_sethpath (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 (char *nam) { FILE *inf; Obj *ret; int hv = 0; char fn[MAXPATHLEN]; 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); if ((inf = fopen (fn, "rb")) == (FILE *) 0) { #ifdef HASHDIR_DEBUG log_printf ("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) log_printf ("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 * obj, char *nam) { FILE *ofi; int hv = 0; char fn[MAXPATHLEN]; if (!db_initted) return (1); hv = objid_hash (nam, hashsiz); (void) sprintf (fn, "%s/%d/%s", hashpath, hv, nam); if ((ofi = fopen (fn, "wb")) == (FILE *) 0) { #ifdef HASHDIR_DEBUG log_printf ("db_put: can't open ", fn, " ", (char *) -1, "\n", (char *) 0); #endif return (-1); } if ((hv = oiftoFILE (obj, ofi, nam)) != 0) log_printf ("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 (char *nam) { 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); if ((fd = open (fn, O_RDONLY, 0600)) < 0) return (0); (void) close (fd); return (1); } /* clobber something out of the database */ int dhdb_del (char *nam, int flg) { char fn[MAXPATHLEN]; if (!db_initted) return (1); (void) sprintf (fn, "%s/%d/%s", hashpath, objid_hash (nam, hashsiz), nam); 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 (char *ob) { struct dirent *drp; char fn[MAXPATHLEN]; if (!db_initted) return (0); while (1) { if ((drp = readdir (dirp)) == (struct dirent *) 0) { 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); } int dhdb_backup (char *out) { struct dirent *drp; 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, S_IREAD | S_IWRITE)) < 0) { closedir (dirp); dirp = (DIR *) 0; return (1); } while (1) { if ((drp = readdir (dirp)) == (struct dirent *) 0) { 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, S_IREAD | S_IWRITE)) < 0) { log_printf ("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) { log_printf ("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