mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
-lock support moved from dba_flatfile.c to dba.c
-flatfile, cdb, cdb_make use locking now #locking is blocking per default use 'rt', 'wt', ct' or 'nt' for non blocking alias #test access to a database file. #locking uses flock() which will be emulated or warned if that is not eally #possible in ext/standard/flock_compat.c
This commit is contained in:
parent
28c2fb6681
commit
95018fc5c0
3 changed files with 89 additions and 103 deletions
|
@ -26,6 +26,13 @@
|
||||||
|
|
||||||
#if HAVE_DBA
|
#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 "php_dba.h"
|
||||||
#include "ext/standard/info.h"
|
#include "ext/standard/info.h"
|
||||||
|
|
||||||
|
@ -79,7 +86,8 @@ ZEND_GET_MODULE(dba)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct dba_handler {
|
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);
|
int (*open)(dba_info *, char **error TSRMLS_DC);
|
||||||
void (*close)(dba_info * TSRMLS_DC);
|
void (*close)(dba_info * TSRMLS_DC);
|
||||||
char* (*fetch)(dba_info *, char *, int, int, int * 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 */
|
/* 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_exists_##x, dba_delete_##x, dba_firstkey_##x, dba_nextkey_##x, \
|
||||||
dba_optimize_##x, dba_sync_##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 */
|
/* check whether the user has write access */
|
||||||
#define DBA_WRITE_CHECK \
|
#define DBA_WRITE_CHECK \
|
||||||
|
@ -166,30 +174,30 @@ typedef struct dba_handler {
|
||||||
|
|
||||||
static dba_handler handler[] = {
|
static dba_handler handler[] = {
|
||||||
#if DBA_GDBM
|
#if DBA_GDBM
|
||||||
DBA_HND(gdbm)
|
DBA_HND(gdbm, DBA_LOCK_EXT)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_DBM
|
#if DBA_DBM
|
||||||
DBA_HND(dbm)
|
DBA_HND(dbm, DBA_LOCK_EXT)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_NDBM
|
#if DBA_NDBM
|
||||||
DBA_HND(ndbm)
|
DBA_HND(ndbm, DBA_LOCK_EXT)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_CDB
|
#if DBA_CDB
|
||||||
DBA_HND(cdb)
|
DBA_HND(cdb, DBA_LOCK_ALL)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_CDB_BUILTIN
|
#if DBA_CDB_BUILTIN
|
||||||
DBA_NAMED_HND(cdb_make, cdb)
|
DBA_NAMED_HND(cdb_make, cdb, DBA_LOCK_ALL)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_DB2
|
#if DBA_DB2
|
||||||
DBA_HND(db2)
|
DBA_HND(db2, DBA_LOCK_EXT)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_DB3
|
#if DBA_DB3
|
||||||
DBA_HND(db3)
|
DBA_HND(db3, DBA_LOCK_EXT)
|
||||||
#endif
|
#endif
|
||||||
#if DBA_FLATFILE
|
#if DBA_FLATFILE
|
||||||
DBA_HND(flatfile)
|
DBA_HND(flatfile, DBA_LOCK_ALL)
|
||||||
#endif
|
#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;
|
static int le_db;
|
||||||
|
@ -200,8 +208,15 @@ static int le_pdb;
|
||||||
*/
|
*/
|
||||||
static void dba_close(dba_info *info TSRMLS_DC)
|
static void dba_close(dba_info *info TSRMLS_DC)
|
||||||
{
|
{
|
||||||
if(info->hnd) info->hnd->close(info TSRMLS_CC);
|
if (info->hnd) info->hnd->close(info TSRMLS_CC);
|
||||||
if(info->path) efree(info->path);
|
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);
|
efree(info);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -297,6 +312,8 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
||||||
char *key = NULL, *error = NULL;
|
char *key = NULL, *error = NULL;
|
||||||
int keylen = 0;
|
int keylen = 0;
|
||||||
int i;
|
int i;
|
||||||
|
int lock;
|
||||||
|
char mode[4], *pmode;
|
||||||
|
|
||||||
if(ac < 3) {
|
if(ac < 3) {
|
||||||
WRONG_PARAM_COUNT;
|
WRONG_PARAM_COUNT;
|
||||||
|
@ -350,23 +367,39 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Z_STRVAL_PP(args[1])[0]) {
|
strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
|
||||||
case 'c':
|
pmode = &mode[0];
|
||||||
modenr = DBA_CREAT;
|
switch (*pmode++) {
|
||||||
|
case 'r':
|
||||||
|
modenr = DBA_READER;
|
||||||
|
lock = (hptr->lock & DBA_LOCK_READER) ? LOCK_SH : 0;
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
modenr = DBA_WRITER;
|
modenr = DBA_WRITER;
|
||||||
break;
|
lock = (hptr->lock & DBA_LOCK_WRITER) ? LOCK_EX : 0;
|
||||||
case 'r':
|
|
||||||
modenr = DBA_READER;
|
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
modenr = DBA_TRUNC;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
|
lock = 0;
|
||||||
FREENOW;
|
modenr = 0;
|
||||||
RETURN_FALSE;
|
}
|
||||||
|
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));
|
info = emalloc(sizeof(dba_info));
|
||||||
|
@ -376,7 +409,21 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
|
||||||
info->argc = ac - 3;
|
info->argc = ac - 3;
|
||||||
info->argv = args + 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);
|
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:"");
|
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;
|
FREENOW;
|
||||||
|
|
|
@ -34,16 +34,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.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_DATA flatfile *dba = info->dbf
|
||||||
#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
|
#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
|
||||||
|
|
||||||
|
@ -51,14 +41,6 @@ DBA_OPEN_FUNC(flatfile)
|
||||||
{
|
{
|
||||||
char *fmode;
|
char *fmode;
|
||||||
php_stream *fp;
|
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));
|
info->dbf = emalloc(sizeof(flatfile));
|
||||||
memset(info->dbf, 0, sizeof(flatfile));
|
memset(info->dbf, 0, sizeof(flatfile));
|
||||||
|
@ -66,78 +48,29 @@ DBA_OPEN_FUNC(flatfile)
|
||||||
switch(info->mode) {
|
switch(info->mode) {
|
||||||
case DBA_READER:
|
case DBA_READER:
|
||||||
fmode = "r";
|
fmode = "r";
|
||||||
lock = 0;
|
|
||||||
break;
|
break;
|
||||||
case DBA_WRITER:
|
case DBA_WRITER:
|
||||||
fmode = "r+b";
|
fmode = "r+b";
|
||||||
lock = 1;
|
|
||||||
break;
|
break;
|
||||||
case DBA_CREAT:
|
case DBA_CREAT:
|
||||||
fmode = "a+b";
|
fmode = "a+b";
|
||||||
lock = 1;
|
|
||||||
break;
|
break;
|
||||||
case DBA_TRUNC:
|
case DBA_TRUNC:
|
||||||
fmode = "w+b";
|
fmode = "w+b";
|
||||||
lock = 1;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
efree(info->dbf);
|
efree(info->dbf);
|
||||||
return FAILURE; /* not possible */
|
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);
|
fp = php_stream_open_wrapper(info->path, fmode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE, NULL);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
*error = "Unable to open file";
|
*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);
|
efree(info->dbf);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
((flatfile*)info->dbf)->fp = fp;
|
((flatfile*)info->dbf)->fp = fp;
|
||||||
((flatfile*)info->dbf)->lockfn = lockfn;
|
|
||||||
((flatfile*)info->dbf)->lockfd = lockfd;
|
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -146,17 +79,6 @@ DBA_CLOSE_FUNC(flatfile)
|
||||||
{
|
{
|
||||||
FLATFILE_DATA;
|
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);
|
php_stream_close(dba->fp);
|
||||||
if (dba->nextkey.dptr)
|
if (dba->nextkey.dptr)
|
||||||
efree(dba->nextkey.dptr);
|
efree(dba->nextkey.dptr);
|
||||||
|
|
|
@ -24,12 +24,19 @@
|
||||||
#if HAVE_DBA
|
#if HAVE_DBA
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
/* do not allow 0 here */
|
||||||
DBA_READER = 1,
|
DBA_READER = 1,
|
||||||
DBA_WRITER,
|
DBA_WRITER,
|
||||||
DBA_TRUNC,
|
DBA_TRUNC,
|
||||||
DBA_CREAT
|
DBA_CREAT
|
||||||
} dba_mode_t;
|
} dba_mode_t;
|
||||||
|
|
||||||
|
typedef struct dba_lock {
|
||||||
|
php_stream *fp;
|
||||||
|
int fd;
|
||||||
|
char *name;
|
||||||
|
} dba_lock;
|
||||||
|
|
||||||
typedef struct dba_info {
|
typedef struct dba_info {
|
||||||
/* public */
|
/* public */
|
||||||
void *dbf; /* ptr to private data or whatever */
|
void *dbf; /* ptr to private data or whatever */
|
||||||
|
@ -40,8 +47,18 @@ typedef struct dba_info {
|
||||||
zval ***argv;
|
zval ***argv;
|
||||||
/* private */
|
/* private */
|
||||||
struct dba_handler *hnd;
|
struct dba_handler *hnd;
|
||||||
|
dba_lock lock;
|
||||||
} dba_info;
|
} 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;
|
extern zend_module_entry dba_module_entry;
|
||||||
#define dba_module_ptr &dba_module_entry
|
#define dba_module_ptr &dba_module_entry
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue