summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/dba/dba.c97
-rw-r--r--ext/dba/dba_flatfile.c78
-rw-r--r--ext/dba/php_dba.h17
3 files changed, 89 insertions, 103 deletions
diff --git a/ext/dba/dba.c b/ext/dba/dba.c
index 8213166afd..f01c34bd70 100644
--- a/ext/dba/dba.c
+++ b/ext/dba/dba.c
@@ -26,6 +26,13 @@
#if HAVE_DBA
+#include "ext/standard/flock_compat.h"
+#include <stdio.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
#include "php_dba.h"
#include "ext/standard/info.h"
@@ -79,7 +86,8 @@ ZEND_GET_MODULE(dba)
#endif
typedef struct dba_handler {
- char *name;
+ char *name; /* handler name */
+ int lock; /* whether and how dba does locking */
int (*open)(dba_info *, char **error TSRMLS_DC);
void (*close)(dba_info * TSRMLS_DC);
char* (*fetch)(dba_info *, char *, int, int, int * TSRMLS_DC);
@@ -144,14 +152,14 @@ typedef struct dba_handler {
/* a DBA handler must have specific routines */
-#define DBA_NAMED_HND(name, x) \
+#define DBA_NAMED_HND(name, x, lock) \
{\
- #name, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \
+ #name, lock, dba_open_##x, dba_close_##x, dba_fetch_##x, dba_update_##x, \
dba_exists_##x, dba_delete_##x, dba_firstkey_##x, dba_nextkey_##x, \
dba_optimize_##x, dba_sync_##x \
},
-#define DBA_HND(x) DBA_NAMED_HND(x, x)
+#define DBA_HND(x, lock) DBA_NAMED_HND(x, x, lock)
/* check whether the user has write access */
#define DBA_WRITE_CHECK \
@@ -166,30 +174,30 @@ typedef struct dba_handler {
static dba_handler handler[] = {
#if DBA_GDBM
- DBA_HND(gdbm)
+ DBA_HND(gdbm, DBA_LOCK_EXT)
#endif
#if DBA_DBM
- DBA_HND(dbm)
+ DBA_HND(dbm, DBA_LOCK_EXT)
#endif
#if DBA_NDBM
- DBA_HND(ndbm)
+ DBA_HND(ndbm, DBA_LOCK_EXT)
#endif
#if DBA_CDB
- DBA_HND(cdb)
+ DBA_HND(cdb, DBA_LOCK_ALL)
#endif
#if DBA_CDB_BUILTIN
- DBA_NAMED_HND(cdb_make, cdb)
+ DBA_NAMED_HND(cdb_make, cdb, DBA_LOCK_ALL)
#endif
#if DBA_DB2
- DBA_HND(db2)
+ DBA_HND(db2, DBA_LOCK_EXT)
#endif
#if DBA_DB3
- DBA_HND(db3)
+ DBA_HND(db3, DBA_LOCK_EXT)
#endif
#if DBA_FLATFILE
- DBA_HND(flatfile)
+ DBA_HND(flatfile, DBA_LOCK_ALL)
#endif
- { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
static int le_db;
@@ -200,8 +208,15 @@ static int le_pdb;
*/
static void dba_close(dba_info *info TSRMLS_DC)
{
- if(info->hnd) info->hnd->close(info TSRMLS_CC);
- if(info->path) efree(info->path);
+ if (info->hnd) info->hnd->close(info TSRMLS_CC);
+ if (info->path) efree(info->path);
+ if (info->lock.fd) {
+ flock(info->lock.fd, LOCK_UN);
+ close(info->lock.fd);
+ info->lock.fd = 0;
+ }
+ if (info->lock.fp) php_stream_close(info->lock.fp);
+ if (info->lock.name) efree(info->lock.name);
efree(info);
}
/* }}} */
@@ -297,6 +312,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
char *key = NULL, *error = NULL;
int keylen = 0;
int i;
+ int lock;
+ char mode[4], *pmode;
if(ac < 3) {
WRONG_PARAM_COUNT;
@@ -350,23 +367,39 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
RETURN_FALSE;
}
- switch (Z_STRVAL_PP(args[1])[0]) {
- case 'c':
- modenr = DBA_CREAT;
+ strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
+ pmode = &mode[0];
+ switch (*pmode++) {
+ case 'r':
+ modenr = DBA_READER;
+ lock = (hptr->lock & DBA_LOCK_READER) ? LOCK_SH : 0;
break;
case 'w':
modenr = DBA_WRITER;
- break;
- case 'r':
- modenr = DBA_READER;
+ lock = (hptr->lock & DBA_LOCK_WRITER) ? LOCK_EX : 0;
break;
case 'n':
modenr = DBA_TRUNC;
+ lock = (hptr->lock & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
+ break;
+ case 'c':
+ modenr = DBA_CREAT;
+ lock = (hptr->lock & DBA_LOCK_CREAT) ? LOCK_EX : 0;
break;
default:
- php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
- FREENOW;
- RETURN_FALSE;
+ lock = 0;
+ modenr = 0;
+ }
+ if (*pmode=='t') {
+ pmode++;
+ lock |= LOCK_NB; /* test =: non blocking */
+ } else if (*pmode=='b') {
+ pmode++; /* default is blocking */
+ }
+ if (*pmode || !modenr) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
+ FREENOW;
+ RETURN_FALSE;
}
info = emalloc(sizeof(dba_info));
@@ -376,7 +409,21 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
info->argc = ac - 3;
info->argv = args + 3;
- if (hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
+ if (lock) {
+ spprintf(&info->lock.name, 0, "%s.lck", info->path);
+ info->lock.fp = php_stream_open_wrapper(info->lock.name, "a+b", STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
+ if (info->lock.fp && php_stream_cast(info->lock.fp, PHP_STREAM_AS_FD, (void*)&info->lock.fd, 1) == FAILURE) {
+ dba_close(info TSRMLS_CC);
+ /* stream operation already wrote an error message */
+ FREENOW;
+ RETURN_FALSE;
+ }
+ if (!info->lock.fp || flock(info->lock.fd, lock)) {
+ error = "Unable to establish lock"; /* force failure exit */
+ }
+ }
+
+ if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
dba_close(info TSRMLS_CC);
php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", Z_STRVAL_PP(args[2]), error?": ":"", error?error:"");
FREENOW;
diff --git a/ext/dba/dba_flatfile.c b/ext/dba/dba_flatfile.c
index 54e625bd26..0a90ecb971 100644
--- a/ext/dba/dba_flatfile.c
+++ b/ext/dba/dba_flatfile.c
@@ -34,16 +34,6 @@
#include <sys/stat.h>
#include <fcntl.h>
-#ifdef PHP_31
-#include "os/nt/flock.h"
-#else
-#ifdef PHP_WIN32
-#include "win32/flock.h"
-#else
-#include <sys/file.h>
-#endif
-#endif
-
#define FLATFILE_DATA flatfile *dba = info->dbf
#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
@@ -51,14 +41,6 @@ DBA_OPEN_FUNC(flatfile)
{
char *fmode;
php_stream *fp;
- int lock;
- char *lockfn = NULL;
- int lockfd = 0;
-#if NFS_HACK
- int last_try = 0;
- struct stat sb;
- int retries = 0;
-#endif
info->dbf = emalloc(sizeof(flatfile));
memset(info->dbf, 0, sizeof(flatfile));
@@ -66,78 +48,29 @@ DBA_OPEN_FUNC(flatfile)
switch(info->mode) {
case DBA_READER:
fmode = "r";
- lock = 0;
break;
case DBA_WRITER:
fmode = "r+b";
- lock = 1;
break;
case DBA_CREAT:
fmode = "a+b";
- lock = 1;
break;
case DBA_TRUNC:
fmode = "w+b";
- lock = 1;
break;
default:
efree(info->dbf);
return FAILURE; /* not possible */
}
- if (lock) {
- spprintf(&lockfn, 0, "%s.lck", info->path);
-
-#if NFS_HACK
- while((last_try = VCWD_STAT(lockfn, &sb))==0) {
- retries++;
- php_sleep(1);
- if (retries>30)
- break;
- }
- if (last_try!=0) {
- lockfd = open(lockfn, O_RDWR|O_CREAT, 0644);
- close(lockfd);
- } else {
- *error = "File appears to be locked";
- efree(lockfn);
- efree(info->dbf);
- return FAILURE;
- }
-#else /* NFS_HACK */
- lockfd = VCWD_OPEN_MODE(lockfn, O_RDWR|O_CREAT, 0644);
-
- if (!lockfd || flock(lockfd, LOCK_EX)) {
- if (lockfd)
- close(lockfd);
- efree(lockfn);
- efree(info->dbf);
- *error = "Unable to establish lock";
- return FAILURE;
- }
-#endif /* else NFS_HACK */
- }
-
fp = php_stream_open_wrapper(info->path, fmode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
if (!fp) {
*error = "Unable to open file";
-#if NFS_HACK
- VCWD_UNLINK(lockfn);
-#else
- if (lockfn) {
- lockfd = VCWD_OPEN_MODE(lockfn, O_RDWR, 0644);
- flock(lockfd, LOCK_UN);
- close(lockfd);
- }
-#endif
- efree(lockfn);
efree(info->dbf);
return FAILURE;
}
((flatfile*)info->dbf)->fp = fp;
- ((flatfile*)info->dbf)->lockfn = lockfn;
- ((flatfile*)info->dbf)->lockfd = lockfd;
return SUCCESS;
}
@@ -146,17 +79,6 @@ DBA_CLOSE_FUNC(flatfile)
{
FLATFILE_DATA;
- if (dba->lockfn) {
-#if NFS_HACK
- VCWD_UNLINK(dba->lockfn);
-#else
- /*dba->lockfd = VCWD_OPEN_MODE(dba->lockfn, O_RDWR, 0644);*/
- flock(dba->lockfd, LOCK_UN);
- close(dba->lockfd);
-#endif
- efree(dba->lockfn);
- }
-
php_stream_close(dba->fp);
if (dba->nextkey.dptr)
efree(dba->nextkey.dptr);
diff --git a/ext/dba/php_dba.h b/ext/dba/php_dba.h
index c0c1bfc672..661f6af97b 100644
--- a/ext/dba/php_dba.h
+++ b/ext/dba/php_dba.h
@@ -24,12 +24,19 @@
#if HAVE_DBA
typedef enum {
+ /* do not allow 0 here */
DBA_READER = 1,
DBA_WRITER,
DBA_TRUNC,
DBA_CREAT
} dba_mode_t;
+typedef struct dba_lock {
+ php_stream *fp;
+ int fd;
+ char *name;
+} dba_lock;
+
typedef struct dba_info {
/* public */
void *dbf; /* ptr to private data or whatever */
@@ -40,8 +47,18 @@ typedef struct dba_info {
zval ***argv;
/* private */
struct dba_handler *hnd;
+ dba_lock lock;
} dba_info;
+#define DBA_LOCK_READER (1)
+#define DBA_LOCK_WRITER (2)
+#define DBA_LOCK_CREAT (4)
+#define DBA_LOCK_TRUNC (8)
+
+#define DBA_LOCK_EXT (0)
+#define DBA_LOCK_ALL (DBA_LOCK_READER|DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
+#define DBA_LOCK_WCT (DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
+
extern zend_module_entry dba_module_entry;
#define dba_module_ptr &dba_module_entry