1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include "../common/tdb_private.h"
#include "../common/io.c"
#include "../common/tdb.c"
#include "../common/lock.c"
#include "../common/freelist.c"
#include "../common/traverse.c"
#include "../common/transaction.c"
#include "../common/error.c"
#include "../common/open.c"
#include "../common/check.c"
#include "../common/hash.c"
#include "../common/mutex.c"
#include "tap-interface.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <poll.h>
#include <stdarg.h>
static TDB_DATA key, data;
static void log_void(struct tdb_context *tdb, enum tdb_debug_level level,
const char *fmt, ...)
{
}
static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
static int do_child(int fd)
{
struct tdb_context *tdb;
unsigned int log_count;
struct tdb_logging_context log_ctx = { log_fn, &log_count };
struct tdb_logging_context nolog_ctx = { log_void, NULL };
char c;
read(fd, &c, 1);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_DEFAULT,
O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
ok((tdb == NULL) && (errno == EINVAL), "TDB_DEFAULT without "
"TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST,
O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
ok((tdb == NULL) && (errno == EINVAL), "TDB_CLEAR_IF_FIRST without "
"TDB_MUTEX_LOCKING should fail with EINVAL - %d", errno);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST |
TDB_MUTEX_LOCKING |
TDB_INTERNAL,
O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with "
"TDB_INTERNAL should fail with EINVAL - %d", errno);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST |
TDB_MUTEX_LOCKING |
TDB_NOMMAP,
O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
ok((tdb == NULL) && (errno == EINVAL), "TDB_MUTEX_LOCKING with "
"TDB_NOMMAP should fail with EINVAL - %d", errno);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST |
TDB_MUTEX_LOCKING,
O_RDONLY, 0755, &nolog_ctx, NULL);
ok((tdb != NULL), "TDB_MUTEX_LOCKING with "
"O_RDONLY should work - %d", errno);
tdb_close(tdb);
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST |
TDB_MUTEX_LOCKING,
O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
ok((tdb != NULL), "TDB_MUTEX_LOCKING with TDB_CLEAR_IF_FIRST"
"TDB_NOMMAP should work - %d", errno);
return 0;
}
/* The code should barf on TDBs created with rwlocks. */
int main(int argc, char *argv[])
{
struct tdb_context *tdb;
unsigned int log_count;
struct tdb_logging_context log_ctx = { log_fn, &log_count };
struct tdb_logging_context nolog_ctx = { log_void, NULL };
int ret, status;
pid_t child, wait_ret;
int pipefd[2];
char c = 0;
bool runtime_support;
runtime_support = tdb_runtime_check_for_robust_mutexes();
ret = pipe(pipefd);
ok1(ret == 0);
key.dsize = strlen("hi");
key.dptr = discard_const_p(uint8_t, "hi");
data.dsize = strlen("world");
data.dptr = discard_const_p(uint8_t, "world");
if (!runtime_support) {
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST|
TDB_MUTEX_LOCKING,
O_RDWR|O_CREAT, 0755, &nolog_ctx, NULL);
ok((tdb == NULL) && (errno == ENOSYS), "TDB_MUTEX_LOCKING without "
"runtime support should fail with ENOSYS - %d", errno);
skip(1, "No robust mutex support");
return exit_status();
}
child = fork();
if (child == 0) {
return do_child(pipefd[0]);
}
tdb = tdb_open_ex("mutex-openflags2.tdb", 0,
TDB_CLEAR_IF_FIRST|
TDB_MUTEX_LOCKING,
O_RDWR|O_CREAT, 0755, &log_ctx, NULL);
ok((tdb != NULL), "tdb_open_ex with mutexes should succeed");
write(pipefd[1], &c, 1);
wait_ret = wait(&status);
ok((wait_ret == child) && (status == 0),
"child should have exited correctly");
diag("done");
return exit_status();
}
|