summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);