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
|
||||
|
||||
#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;
|
||||
|
@ -202,6 +210,13 @@ 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->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,20 +367,36 @@ 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:
|
||||
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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue