summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornelsonb%netscape.com <devnull@localhost>2001-03-14 00:29:55 +0000
committernelsonb%netscape.com <devnull@localhost>2001-03-14 00:29:55 +0000
commitde79427fadc54130a8b2e8f97fdaecc8c7fb9bdc (patch)
treefd136f0c4ac0b99dd22e0a1be97d1adab690bc2a
parentd6b9fd312f96b0d4b53bd11c118df2d95ac1c5f9 (diff)
downloadnss-hg-de79427fadc54130a8b2e8f97fdaecc8c7fb9bdc.tar.gz
Fix bugzilla bugs 69753 and 39465. Temporary DB files are now created
in $TMP, $TMPDIR or $TEMP, if possible. On windows, temporary DB files are now opened in binary mode and are removed when the progam terminates or the DB is closed. Multiple temp DB files can now be created in the same program. EOF value on disk is now updated when file is extended.
-rw-r--r--dbm/include/hash.h13
-rw-r--r--dbm/src/h_page.c57
-rw-r--r--dbm/src/hash.c98
-rw-r--r--dbm/src/mktemp.c41
4 files changed, 169 insertions, 40 deletions
diff --git a/dbm/include/hash.h b/dbm/include/hash.h
index 70f93e938..30ca297a1 100644
--- a/dbm/include/hash.h
+++ b/dbm/include/hash.h
@@ -51,9 +51,9 @@ struct _bufhead {
BUFHEAD *prev; /* LRU links */
BUFHEAD *next; /* LRU links */
BUFHEAD *ovfl; /* Overflow page buffer header */
- uint32 addr; /* Address of this page */
+ uint32 addr; /* Address of this page */
char *page; /* Actual page data */
- char is_disk;
+ char is_disk;
char flags;
#define BUF_MOD 0x0001
#define BUF_DISK 0x0002
@@ -77,7 +77,7 @@ typedef int DBFILE_PTR;
typedef struct hashhdr { /* Disk resident portion */
int32 magic; /* Magic NO for hash tables */
int32 version; /* Version ID */
- uint32 lorder; /* Byte Order */
+ uint32 lorder; /* Byte Order */
int32 bsize; /* Bucket/Page Size */
int32 bshift; /* Bucket shift */
int32 dsize; /* Directory Size */
@@ -97,7 +97,7 @@ typedef struct hashhdr { /* Disk resident portion */
#define NCACHED 32 /* number of bit maps and spare
* points */
int32 spares[NCACHED];/* spare pages for overflow */
- uint16 bitmaps[NCACHED]; /* address of overflow page
+ uint16 bitmaps[NCACHED]; /* address of overflow page
* bitmaps */
} HASHHDR;
@@ -123,12 +123,15 @@ typedef struct htab { /* Memory resident data structure */
int save_file; /* Indicates whether we need to flush
* file at
* exit */
- uint32 *mapp[NCACHED]; /* Pointers to page maps */
+ uint32 *mapp[NCACHED]; /* Pointers to page maps */
int nmaps; /* Initial number of bitmaps */
int nbufs; /* Number of buffers left to
* allocate */
BUFHEAD bufhead; /* Header of buffer lru list */
SEGMENT *dir; /* Hash Bucket directory */
+ off_t file_size; /* in bytes */
+ char is_temp; /* unlink file on close */
+ char updateEOF; /* close and reopen on flush */
} HTAB;
/*
diff --git a/dbm/src/h_page.c b/dbm/src/h_page.c
index f81298e67..8d8a484fa 100644
--- a/dbm/src/h_page.c
+++ b/dbm/src/h_page.c
@@ -72,6 +72,9 @@ static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#include <errno.h>
#include <fcntl.h>
+#if defined(_WIN32) || defined(_WINDOWS)
+#include <io.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -88,6 +91,8 @@ static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#include "page.h"
/* #include "extern.h" */
+extern int mkstempflags(char *path, int extraFlags);
+
static uint32 *fetch_bitmap __P((HTAB *, uint32));
static uint32 first_free __P((uint32));
static int open_temp __P((HTAB *));
@@ -826,6 +831,7 @@ __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap)
register int fd, page;
size_t size;
int wsize;
+ off_t offset;
size = hashp->BSIZE;
if ((hashp->fp == -1) && open_temp(hashp))
@@ -860,7 +866,8 @@ __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap)
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((MY_LSEEK(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+ offset = (off_t)page << hashp->BSHIFT;
+ if ((MY_LSEEK(fd, offset, SEEK_SET) == -1) ||
((wsize = write(fd, p, size)) == -1))
/* Errno is set */
return (-1);
@@ -868,7 +875,11 @@ __put_page(HTAB *hashp, char *p, uint32 bucket, int is_bucket, int is_bitmap)
errno = EFTYPE;
return (-1);
}
-
+#if defined(_WIN32) || defined(_WINDOWS)
+ if (offset + size > hashp->file_size) {
+ hashp->updateEOF = 1;
+ }
+#endif
/* put the page back the way it was so that it isn't byteswapped
* if it remains in memory - LJM
*/
@@ -1151,7 +1162,11 @@ open_temp(HTAB *hashp)
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2)
sigset_t set, oset;
#endif
- static char namestr[] = "_hashXXXXXX";
+ char * tmpdir;
+ int len;
+ static const char namestr[] = "/_hashXXXXXX";
+ char filename[1024];
+ char last;
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2)
/* Block signals; make sure file goes away at process exit. */
@@ -1159,12 +1174,42 @@ open_temp(HTAB *hashp)
(void)sigprocmask(SIG_BLOCK, &set, &oset);
#endif
- if ((hashp->fp = mkstemp(namestr)) != -1) {
- (void)unlink(namestr);
-#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2)
+ filename[0] = 0;
+#if defined(macintosh)
+ strcat(filename, namestr + 1);
+#else
+ tmpdir = getenv("TMP");
+ if (!tmpdir)
+ tmpdir = getenv("TMPDIR");
+ if (!tmpdir)
+ tmpdir = getenv("TEMP");
+ if (!tmpdir)
+ tmpdir = ".";
+ len = strlen(tmpdir);
+ if (len && len < (sizeof filename - sizeof namestr)) {
+ strcpy(filename, tmpdir);
+ }
+ len = strlen(filename);
+ last = tmpdir[len - 1];
+ strcat(filename, (last == '/' || last == '\\') ? namestr + 1 : namestr);
+#endif
+
+#if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2)
+ if ((hashp->fp = mkstempflags(filename, _O_BINARY|_O_TEMPORARY)) != -1) {
+ if (hashp->filename) {
+ free(hashp->filename);
+ }
+ hashp->filename = strdup(filename);
+ hashp->is_temp = 1;
+ }
+#else
+ if ((hashp->fp = mkstemp(filename)) != -1) {
+ (void)unlink(filename);
+#if !defined(macintosh)
(void)fcntl(hashp->fp, F_SETFD, 1);
#endif
}
+#endif
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2)
(void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
diff --git a/dbm/src/hash.c b/dbm/src/hash.c
index 5aa91424b..8be75721b 100644
--- a/dbm/src/hash.c
+++ b/dbm/src/hash.c
@@ -65,15 +65,16 @@ static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
#if !defined(_WIN32) && !defined(_WINDOWS) && !defined(macintosh) && !defined(XP_OS2_VACPP)
#include <unistd.h>
#endif
+#if defined(_WIN32) || defined(_WINDOWS)
+#include <windows.h>
+#endif
#ifdef XP_OS2_VACPP
#include "types.h"
#define EPERM SOCEPERM
#endif
-#ifdef DEBUG
#include <assert.h>
-#endif
#include "mcom_db.h"
#include "hash.h"
@@ -117,25 +118,21 @@ int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
/* A new Lou (montulli@mozilla.com) routine.
*
- * The database is screwed. Delete it by
- * making it a zero length file
+ * The database is screwed.
*
- * This zero's hashp so that the
- * database can't be accessed any more
+ * This closes the file, flushing buffers as appropriate.
*/
static void
__remove_database(DB *dbp)
{
HTAB *hashp = (HTAB *)dbp->internal;
- if (!hashp)
- return;
- if(hashp->fp != NO_FILE)
- close(hashp->fp);
- if(hashp->filename)
- unlink(hashp->filename);
- dbp->internal = NULL; /* zero the internal stuff */
+ assert(0);
+ if (!hashp)
+ return;
+ hdestroy(hashp);
+ dbp->internal = NULL;
}
/************************** INTERFACE ROUTINES ***************************/
@@ -189,6 +186,7 @@ __hash_open(const char *file, int flags, int mode, const HASHINFO *info, int dfl
*/
new_table = 1;
}
+ hashp->file_size = statbuf.st_size;
if (file) {
@@ -561,8 +559,13 @@ hdestroy(HTAB *hashp)
if (hashp->fp != -1)
(void)close(hashp->fp);
- if(hashp->filename)
+ if(hashp->filename) {
+#if defined(_WIN32) || defined(_WINDOWS) || defined(XP_OS2)
+ if (hashp->is_temp)
+ (void)unlink(hashp->filename);
+#endif
free(hashp->filename);
+ }
free(hashp);
@@ -572,6 +575,65 @@ hdestroy(HTAB *hashp)
}
return (SUCCESS);
}
+
+#if defined(_WIN32) || defined(_WINDOWS)
+/*
+ * Close and reopen file to force file length update on windows.
+ *
+ * Returns:
+ * 0 == OK
+ * -1 DBM_ERROR
+ */
+static int
+update_EOF(HTAB *hashp)
+{
+#if defined(DBM_REOPEN_ON_FLUSH)
+ char * file = hashp->filename;
+ off_t file_size;
+ int flags;
+ int mode = -1;
+ struct stat statbuf;
+
+ memset(&statbuf, 0, sizeof statbuf);
+
+ /* make sure we won't lose the file by closing it. */
+ if (!file || (stat(file, &statbuf) && (errno == ENOENT))) {
+ /* pretend we did it. */
+ return 0;
+ }
+
+ (void)close(hashp->fp);
+
+ flags = hashp->flags & ~(O_TRUNC | O_CREAT | O_EXCL);
+
+ if ((hashp->fp = DBFILE_OPEN(file, flags | O_BINARY, mode)) == -1)
+ return -1;
+ file_size = lseek(hashp->fp, (off_t)0, SEEK_END);
+ if (file_size == -1)
+ return -1;
+ hashp->file_size = file_size;
+ return 0;
+#else
+ int fd = hashp->fp;
+ off_t file_size = lseek(fd, (off_t)0, SEEK_END);
+ HANDLE handle = (HANDLE)_get_osfhandle(fd);
+ BOOL cool = FlushFileBuffers(handle);
+#ifdef DEBUG3
+ if (!cool) {
+ DWORD err = GetLastError();
+ (void)fprintf(stderr,
+ "FlushFileBuffers failed, last error = %d, 0x%08x\n",
+ err, err);
+ }
+#endif
+ if (file_size == -1)
+ return -1;
+ hashp->file_size = file_size;
+ return cool ? 0 : -1;
+#endif
+}
+#endif
+
/*
* Write modified pages to disk
*
@@ -600,6 +662,14 @@ hash_sync(const DB *dbp, uint flags)
return (0);
if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
return (DBM_ERROR);
+#if defined(_WIN32) || defined(_WINDOWS)
+ if (hashp->updateEOF && hashp->filename && !hashp->is_temp) {
+ int status = update_EOF(hashp);
+ hashp->updateEOF = 0;
+ if (status)
+ return status;
+ }
+#endif
hashp->new_file = 0;
return (0);
}
diff --git a/dbm/src/mktemp.c b/dbm/src/mktemp.c
index ab606e30f..4da6c9497 100644
--- a/dbm/src/mktemp.c
+++ b/dbm/src/mktemp.c
@@ -64,28 +64,35 @@ static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
#include "winfile.h"
#endif
-static int _gettemp(char *path, register int *doopen);
+static int _gettemp(char *path, register int *doopen, int extraFlags);
int
-mkstemp(path)
- char *path;
+mkstemp(char *path)
{
int fd;
- return (_gettemp(path, &fd) ? fd : -1);
+ return (_gettemp(path, &fd, 0) ? fd : -1);
+}
+
+int
+mkstempflags(char *path, int extraFlags)
+{
+ int fd;
+
+ return (_gettemp(path, &fd, extraFlags) ? fd : -1);
}
char *
-mktemp(path)
- char *path;
+mktemp(char *path)
{
- return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+ return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL);
}
-static int
-_gettemp(path, doopen)
- char *path;
- register int *doopen;
+/* NB: This routine modifies its input string, and does not always restore it.
+** returns 1 on success, 0 on failure.
+*/
+static int
+_gettemp(char *path, register int *doopen, int extraFlags)
{
#if !defined(_WINDOWS) || defined(_WIN32)
extern int errno;
@@ -106,17 +113,21 @@ _gettemp(path, doopen)
* doesn't exist this runs for a *very* long time.
*/
for (start = trv + 1;; --trv) {
+ char saved;
if (trv <= path)
break;
- if (*trv == '/') {
+ saved = *trv;
+ if (saved == '/' || saved == '\\') {
+ int rv;
*trv = '\0';
- if (stat(path, &sbuf))
+ rv = stat(path, &sbuf);
+ *trv = saved;
+ if (rv)
return(0);
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
return(0);
}
- *trv = '/';
break;
}
}
@@ -124,7 +135,7 @@ _gettemp(path, doopen)
for (;;) {
if (doopen) {
if ((*doopen =
- open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+ open(path, O_CREAT|O_EXCL|O_RDWR|extraFlags, 0600)) >= 0)
return(1);
if (errno != EEXIST)
return(0);