summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h7
-rw-r--r--source3/libsmb/clientgen.c10
-rw-r--r--source3/utils/torture.c150
3 files changed, 140 insertions, 27 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0388ef6911..2db1f3ed02 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -587,8 +587,10 @@ BOOL cli_rmdir(struct cli_state *cli, char *dname);
int cli_nt_create(struct cli_state *cli, char *fname);
int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode);
BOOL cli_close(struct cli_state *cli, int fnum);
-BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
-BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
+BOOL cli_lock(struct cli_state *cli, int fnum,
+ uint32 offset, uint32 len, int timeout, int locktype);
+BOOL cli_unlock(struct cli_state *cli, int fnum,
+ uint32 offset, uint32 len, int timeout, int locktype);
size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size);
ssize_t cli_write(struct cli_state *cli,
int fnum, uint16 write_mode,
@@ -2972,6 +2974,7 @@ int smbw_stat(const char *fname, struct stat *st);
/*The following definitions come from tdb/tdb.c */
+char *tdb_error(TDB_CONTEXT *tdb);
int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 3b6403fe73..bf610a7ff7 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -1344,7 +1344,8 @@ BOOL cli_close(struct cli_state *cli, int fnum)
/****************************************************************************
lock a file
****************************************************************************/
-BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
+BOOL cli_lock(struct cli_state *cli, int fnum,
+ uint32 offset, uint32 len, int timeout, int locktype)
{
char *p;
int saved_timeout = cli->timeout;
@@ -1360,7 +1361,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
- CVAL(cli->outbuf,smb_vwv3) = 0;
+ CVAL(cli->outbuf,smb_vwv3) = (locktype == F_RDLCK? 1 : 0);
SIVALS(cli->outbuf, smb_vwv4, timeout);
SSVAL(cli->outbuf,smb_vwv6,0);
SSVAL(cli->outbuf,smb_vwv7,1);
@@ -1390,7 +1391,8 @@ BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int ti
/****************************************************************************
unlock a file
****************************************************************************/
-BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
+BOOL cli_unlock(struct cli_state *cli, int fnum,
+ uint32 offset, uint32 len, int timeout, int locktype)
{
char *p;
@@ -1405,7 +1407,7 @@ BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,fnum);
- CVAL(cli->outbuf,smb_vwv3) = 0;
+ CVAL(cli->outbuf,smb_vwv3) = (locktype == F_RDLCK? 1 : 0);
SIVALS(cli->outbuf, smb_vwv4, timeout);
SSVAL(cli->outbuf,smb_vwv6,1);
SSVAL(cli->outbuf,smb_vwv7,0);
diff --git a/source3/utils/torture.c b/source3/utils/torture.c
index 4375cbe231..b9f0d76581 100644
--- a/source3/utils/torture.c
+++ b/source3/utils/torture.c
@@ -168,7 +168,7 @@ static BOOL check_error(struct cli_state *c,
static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
{
- while (!cli_lock(c, fnum, offset, len, -1)) {
+ while (!cli_lock(c, fnum, offset, len, -1, F_WRLCK)) {
if (!check_error(c, ERRDOS, ERRlock, 0)) return False;
}
return True;
@@ -242,7 +242,7 @@ static BOOL rw_torture(struct cli_state *c)
printf("unlink failed (%s)\n", cli_errstr(c));
}
- if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
+ if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1, F_WRLCK)) {
printf("unlock failed (%s)\n", cli_errstr(c));
}
}
@@ -436,13 +436,13 @@ static void run_locktest1(int dummy)
return;
}
- if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
+ if (!cli_lock(&cli1, fnum1, 0, 4, 0, F_WRLCK)) {
printf("lock1 failed (%s)\n", cli_errstr(&cli1));
return;
}
- if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
+ if (cli_lock(&cli2, fnum3, 0, 4, 0, F_WRLCK)) {
printf("lock2 succeeded! This is a locking bug\n");
return;
} else {
@@ -452,7 +452,7 @@ static void run_locktest1(int dummy)
printf("Testing lock timeouts\n");
t1 = time(NULL);
- if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
+ if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, F_WRLCK)) {
printf("lock3 succeeded! This is a locking bug\n");
return;
} else {
@@ -469,7 +469,7 @@ static void run_locktest1(int dummy)
return;
}
- if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
+ if (cli_lock(&cli2, fnum3, 0, 4, 0, F_WRLCK)) {
printf("lock4 succeeded! This is a locking bug\n");
return;
} else {
@@ -550,12 +550,12 @@ static void run_locktest2(int dummy)
cli_setpid(&cli, 1);
- if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
+ if (!cli_lock(&cli, fnum1, 0, 4, 0, F_WRLCK)) {
printf("lock1 failed (%s)\n", cli_errstr(&cli));
return;
}
- if (cli_lock(&cli, fnum2, 0, 4, 0)) {
+ if (cli_lock(&cli, fnum2, 0, 4, 0, F_WRLCK)) {
printf("lock2 succeeded! This is a locking bug\n");
} else {
if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
@@ -563,11 +563,11 @@ static void run_locktest2(int dummy)
cli_setpid(&cli, 2);
- if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
+ if (cli_unlock(&cli, fnum1, 0, 4, 0, F_WRLCK)) {
printf("unlock1 succeeded! This is a locking bug\n");
}
- if (cli_lock(&cli, fnum3, 0, 4, 0)) {
+ if (cli_lock(&cli, fnum3, 0, 4, 0, F_WRLCK)) {
printf("lock3 succeeded! This is a locking bug\n");
} else {
if (!check_error(&cli, ERRDOS, ERRlock, 0)) return;
@@ -633,14 +633,14 @@ static void run_locktest3(int dummy)
for (offset=i=0;i<numops;i++) {
NEXT_OFFSET;
- if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
+ if (!cli_lock(&cli1, fnum1, offset-1, 1, 0, F_WRLCK)) {
printf("lock1 %d failed (%s)\n",
i,
cli_errstr(&cli1));
return;
}
- if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
+ if (!cli_lock(&cli2, fnum2, offset-2, 1, 0, F_WRLCK)) {
printf("lock2 %d failed (%s)\n",
i,
cli_errstr(&cli1));
@@ -651,22 +651,22 @@ static void run_locktest3(int dummy)
for (offset=i=0;i<numops;i++) {
NEXT_OFFSET;
- if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
+ if (cli_lock(&cli1, fnum1, offset-2, 1, 0, F_WRLCK)) {
printf("error: lock1 %d succeeded!\n", i);
return;
}
- if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
+ if (cli_lock(&cli2, fnum2, offset-1, 1, 0, F_WRLCK)) {
printf("error: lock2 %d succeeded!\n", i);
return;
}
- if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
+ if (cli_lock(&cli1, fnum1, offset-1, 1, 0, F_WRLCK)) {
printf("error: lock3 %d succeeded!\n", i);
return;
}
- if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
+ if (cli_lock(&cli2, fnum2, offset-2, 1, 0, F_WRLCK)) {
printf("error: lock4 %d succeeded!\n", i);
return;
}
@@ -675,14 +675,14 @@ static void run_locktest3(int dummy)
for (offset=i=0;i<numops;i++) {
NEXT_OFFSET;
- if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
+ if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0, F_WRLCK)) {
printf("unlock1 %d failed (%s)\n",
i,
cli_errstr(&cli1));
return;
}
- if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
+ if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0, F_WRLCK)) {
printf("unlock2 %d failed (%s)\n",
i,
cli_errstr(&cli1));
@@ -711,6 +711,114 @@ static void run_locktest3(int dummy)
/*
+ looks at overlapping locks
+*/
+static void run_locktest4(int dummy)
+{
+ static struct cli_state cli1, cli2;
+ char *fname = "\\lockt4.lck";
+ int fnum1, fnum2;
+ BOOL ret;
+ char buf[1000];
+
+ if (!open_connection(&cli1) || !open_connection(&cli2)) {
+ return;
+ }
+ cli_sockopt(&cli1, sockops);
+ cli_sockopt(&cli2, sockops);
+
+ printf("starting locktest4\n");
+
+ cli_unlink(&cli1, fname);
+
+ fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
+ fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
+
+ memset(buf, 0, sizeof(buf));
+
+ if (cli_write(&cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
+ printf("Failed to create file\n");
+ goto fail;
+ }
+
+ cli_lock(&cli1, fnum1, 0, 4, 0, F_WRLCK);
+ ret = cli_lock(&cli1, fnum1, 2, 4, 0, F_WRLCK);
+ printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 10, 4, 0, F_RDLCK);
+ ret = cli_lock(&cli1, fnum1, 12, 4, 0, F_RDLCK);
+ printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 20, 4, 0, F_WRLCK);
+ ret = cli_lock(&cli2, fnum2, 22, 4, 0, F_WRLCK);
+ printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 30, 4, 0, F_RDLCK);
+ ret = cli_lock(&cli2, fnum2, 32, 4, 0, F_RDLCK);
+ printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
+
+ cli_setpid(&cli1, 1);
+ cli_lock(&cli1, fnum1, 40, 4, 0, F_WRLCK);
+ cli_setpid(&cli1, 2);
+ ret = cli_lock(&cli1, fnum1, 42, 4, 0, F_WRLCK);
+ printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
+
+ cli_setpid(&cli1, 1);
+ cli_lock(&cli1, fnum1, 50, 4, 0, F_RDLCK);
+ cli_setpid(&cli1, 2);
+ ret = cli_lock(&cli1, fnum1, 52, 4, 0, F_RDLCK);
+ printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 60, 4, 0, F_RDLCK);
+ ret = cli_lock(&cli1, fnum1, 60, 4, 0, F_RDLCK);
+ printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 70, 4, 0, F_WRLCK);
+ ret = cli_lock(&cli1, fnum1, 70, 4, 0, F_WRLCK);
+ printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 80, 4, 0, F_RDLCK);
+ ret = cli_lock(&cli1, fnum1, 80, 4, 0, F_WRLCK);
+ printf("the same process %s override a read lock with a write lock\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 90, 4, 0, F_WRLCK);
+ ret = cli_lock(&cli1, fnum1, 90, 4, 0, F_RDLCK);
+ printf("the same process %s override a write lock with a read lock\n", ret?"can":"cannot");
+
+ cli_setpid(&cli1, 1);
+ cli_lock(&cli1, fnum1, 100, 4, 0, F_WRLCK);
+ cli_setpid(&cli1, 2);
+ ret = cli_lock(&cli1, fnum1, 100, 4, 0, F_RDLCK);
+ printf("a different pid %s override a write lock with a read lock\n", ret?"can":"cannot");
+
+ cli_lock(&cli1, fnum1, 110, 4, 0, F_RDLCK);
+ cli_lock(&cli1, fnum1, 112, 4, 0, F_RDLCK);
+ ret = cli_unlock(&cli1, fnum1, 110, 6, 0, F_RDLCK);
+ printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
+
+
+ cli_lock(&cli1, fnum1, 120, 4, 0, F_WRLCK);
+ ret = (cli_read(&cli2, fnum2, buf, 120, 4) == 4);
+ printf("this server %s strict write locking\n", ret?"doesn't do":"does");
+
+ cli_lock(&cli1, fnum1, 130, 4, 0, F_RDLCK);
+ ret = (cli_write(&cli2, fnum2, 0, buf, 130, 4) == 4);
+ printf("this server %s strict read locking\n", ret?"doesn't do":"does");
+
+
+
+ fail:
+ cli_close(&cli1, fnum1);
+ cli_close(&cli1, fnum2);
+ cli_unlink(&cli1, fname);
+ close_connection(&cli1);
+ close_connection(&cli2);
+
+ printf("finished locktest4\n");
+}
+
+
+/*
this produces a matrix of deny mode behaviour
*/
static void run_denytest(int dummy)
@@ -1190,10 +1298,9 @@ static void run_trans2test(int dummy)
*/
static void run_oplock(int dummy)
{
- static struct cli_state cli1, cli2;
+ static struct cli_state cli1;
char *fname = "\\lockt1.lck";
- char *fname2 = "\\lockt2.lck";
- int fnum1, fnum2;
+ int fnum1;
printf("starting oplock test\n");
@@ -1380,6 +1487,7 @@ static struct {
{"LOCK1", run_locktest1, 0},
{"LOCK2", run_locktest2, 0},
{"LOCK3", run_locktest3, 0},
+ {"LOCK4", run_locktest4, 0},
{"UNLINK", run_unlinktest, 0},
{"BROWSE", run_browsetest, 0},
{"ATTR", run_attrtest, 0},