23
23
#include <sys/wait.h>
36
struct fd_store *next;
36
struct fd_store *next;
54
54
#define MAX_SEND_FDS 2
56
56
static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
61
size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
66
assert(*numfds <= MAX_SEND_FDS);
70
memset(&msg, 0, sizeof(msg));
71
memset(ccmsg, -1, sizeof(ccmsg));
74
msg.msg_control = ccmsg;
75
msg.msg_controllen = sizeof(ccmsg);
77
res = recvmsg(sock, &msg, MSG_WAITALL);
79
/* retry on zero return, see do_recv() in ulockmgr.c */
80
res = recvmsg(sock, &msg, MSG_WAITALL);
85
perror("ulockmgr_server: recvmsg");
88
if ((size_t) res != buflen) {
89
fprintf(stderr, "ulockmgr_server: short message received\n");
93
cmsg = CMSG_FIRSTHDR(&msg);
95
if (!cmsg->cmsg_type == SCM_RIGHTS) {
96
fprintf(stderr, "ulockmgr_server: unknown control message %d\n",
100
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
101
if (msg.msg_flags & MSG_CTRUNC) {
102
fprintf(stderr, "ulockmgr_server: control message truncated\n");
103
for (i = 0; i < *numfds; i++)
108
if (msg.msg_flags & MSG_CTRUNC) {
109
fprintf(stderr, "ulockmgr_server: control message truncated(*)\n");
111
/* There's a bug in the Linux kernel, that if not all file
112
descriptors were allocated, then the cmsg header is not
114
cmsg = (struct cmsghdr *) ccmsg;
115
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
116
for (i = 0; i < *numfds; i++)
61
size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
66
assert(*numfds <= MAX_SEND_FDS);
70
memset(&msg, 0, sizeof(msg));
71
memset(ccmsg, -1, sizeof(ccmsg));
74
msg.msg_control = ccmsg;
75
msg.msg_controllen = sizeof(ccmsg);
77
res = recvmsg(sock, &msg, MSG_WAITALL);
79
/* retry on zero return, see do_recv() in ulockmgr.c */
80
res = recvmsg(sock, &msg, MSG_WAITALL);
85
perror("ulockmgr_server: recvmsg");
88
if ((size_t) res != buflen) {
89
fprintf(stderr, "ulockmgr_server: short message received\n");
93
cmsg = CMSG_FIRSTHDR(&msg);
95
if (!cmsg->cmsg_type == SCM_RIGHTS) {
97
"ulockmgr_server: unknown control message %d\n",
101
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
102
if (msg.msg_flags & MSG_CTRUNC) {
104
"ulockmgr_server: control message truncated\n");
105
for (i = 0; i < *numfds; i++)
110
if (msg.msg_flags & MSG_CTRUNC) {
112
"ulockmgr_server: control message truncated(*)\n");
114
/* There's a bug in the Linux kernel, that if
115
not all file descriptors were allocated,
116
then the cmsg header is not filled in */
117
cmsg = (struct cmsghdr *) ccmsg;
118
memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
119
for (i = 0; i < *numfds; i++)
124
127
static int closefrom(int minfd)
126
DIR *dir = opendir("/proc/self/fd");
128
int dfd = dirfd(dir);
130
while ((ent = readdir(dir))) {
132
int fd = strtol(ent->d_name, &end, 10);
133
if (ent->d_name[0] && !end[0] && fd >= minfd && fd != dfd)
129
DIR *dir = opendir("/proc/self/fd");
131
int dfd = dirfd(dir);
133
while ((ent = readdir(dir))) {
135
int fd = strtol(ent->d_name, &end, 10);
136
if (ent->d_name[0] && !end[0] && fd >= minfd &&
141
145
static void send_reply(int cfd, struct message *msg)
143
int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
145
perror("ulockmgr_server: sending reply");
147
int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
149
perror("ulockmgr_server: sending reply");
147
fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
151
fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
151
155
static void *process_request(void *d_)
153
struct req_data *d = d_;
156
assert(d->msg.cmd == F_SETLKW);
157
res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
158
if (res == -1 && errno == EAGAIN) {
159
d->msg.error = EAGAIN;
160
d->msg.thr = pthread_self();
161
send_reply(d->cfd, &d->msg);
162
res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
164
d->msg.error = (res == -1) ? errno : 0;
165
pthread_mutex_lock(&d->o->lock);
167
pthread_mutex_unlock(&d->o->lock);
168
send_reply(d->cfd, &d->msg);
157
struct req_data *d = d_;
160
assert(d->msg.cmd == F_SETLKW);
161
res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
162
if (res == -1 && errno == EAGAIN) {
163
d->msg.error = EAGAIN;
164
d->msg.thr = pthread_self();
165
send_reply(d->cfd, &d->msg);
166
res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
168
d->msg.error = (res == -1) ? errno : 0;
169
pthread_mutex_lock(&d->o->lock);
171
pthread_mutex_unlock(&d->o->lock);
172
send_reply(d->cfd, &d->msg);
175
179
static void process_message(struct owner *o, struct message *msg, int cfd,
178
struct fd_store *f = NULL;
179
struct fd_store *newf = NULL;
180
struct fd_store **fp;
182
struct fd_store *f = NULL;
183
struct fd_store *newf = NULL;
184
struct fd_store **fp;
186
fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
187
msg->cmd, msg->lock.l_type, msg->lock.l_whence, msg->lock.l_start,
190
fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
191
msg->cmd, msg->lock.l_type, msg->lock.l_whence,
192
msg->lock.l_start, msg->lock.l_len);
191
if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
192
msg->lock.l_start == 0 && msg->lock.l_len == 0) {
193
for (fp = &o->fds; *fp;) {
195
if (f->origfd == msg->fd && !f->inuse) {
206
send_reply(cfd, msg);
212
for (fp = &o->fds; *fp; fp = &(*fp)->next) {
214
if (f->origfd == msg->fd)
218
fprintf(stderr, "ulockmgr_server: fd %i not found\n", msg->fd);
220
send_reply(cfd, msg);
225
newf = f = malloc(sizeof(struct fd_store));
228
send_reply(cfd, msg);
238
if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
239
msg->lock.l_type == F_UNLCK) {
240
res = fcntl(f->fd, msg->cmd, &msg->lock);
241
msg->error = (res == -1) ? errno : 0;
242
send_reply(cfd, msg);
251
d = malloc(sizeof(struct req_data));
254
send_reply(cfd, msg);
265
res = pthread_create(&tid, NULL, process_request, d);
268
send_reply(cfd, msg);
195
if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
196
msg->lock.l_start == 0 && msg->lock.l_len == 0) {
197
for (fp = &o->fds; *fp;) {
199
if (f->origfd == msg->fd && !f->inuse) {
210
send_reply(cfd, msg);
216
for (fp = &o->fds; *fp; fp = &(*fp)->next) {
218
if (f->origfd == msg->fd)
222
fprintf(stderr, "ulockmgr_server: fd %i not found\n",
225
send_reply(cfd, msg);
230
newf = f = malloc(sizeof(struct fd_store));
233
send_reply(cfd, msg);
243
if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
244
msg->lock.l_type == F_UNLCK) {
245
res = fcntl(f->fd, msg->cmd, &msg->lock);
246
msg->error = (res == -1) ? errno : 0;
247
send_reply(cfd, msg);
256
d = malloc(sizeof(struct req_data));
259
send_reply(cfd, msg);
270
res = pthread_create(&tid, NULL, process_request, d);
273
send_reply(cfd, msg);
283
288
static void sigusr1_handler(int sig)
289
294
static void process_owner(int cfd)
294
memset(&sa, 0, sizeof(struct sigaction));
295
sa.sa_handler = sigusr1_handler;
296
sigemptyset(&sa.sa_mask);
298
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
299
perror("ulockmgr_server: cannot set sigusr1 signal handler");
303
memset(&o, 0, sizeof(struct owner));
304
pthread_mutex_init(&o.lock, NULL);
311
res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
319
fprintf(stderr, "ulockmgr_server: too many fds for intr\n");
320
pthread_kill(msg.thr, SIGUSR1);
325
pthread_mutex_lock(&o.lock);
326
process_message(&o, &msg, rfds[0], rfds[1]);
327
pthread_mutex_unlock(&o.lock);
331
fprintf(stderr, "ulockmgr_server: open file descriptors on exit\n");
299
memset(&sa, 0, sizeof(struct sigaction));
300
sa.sa_handler = sigusr1_handler;
301
sigemptyset(&sa.sa_mask);
303
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
304
perror("ulockmgr_server: cannot set sigusr1 signal handler");
308
memset(&o, 0, sizeof(struct owner));
309
pthread_mutex_init(&o.lock, NULL);
316
res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
325
"ulockmgr_server: too many fds for intr\n");
326
pthread_kill(msg.thr, SIGUSR1);
331
pthread_mutex_lock(&o.lock);
332
process_message(&o, &msg, rfds[0], rfds[1]);
333
pthread_mutex_unlock(&o.lock);
338
"ulockmgr_server: open file descriptors on exit\n");
334
341
int main(int argc, char *argv[])
341
if (argc != 2 || !argv[1][0])
344
cfd = strtol(argv[1], &end, 10);
348
if (daemon(0, 1) == -1) {
349
perror("ulockmgr_server: daemon");
354
sigprocmask(SIG_SETMASK, &empty, NULL);
356
if (dup2(cfd, 4) == -1) {
357
perror("ulockmgr_server: dup2");
361
nullfd = open("/dev/null", O_RDWR);
371
int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
380
perror("ulockmgr_server: fork");
388
perror("ulockmgr_server: fork");
395
waitpid(pid, NULL, 0);
401
fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
348
if (argc != 2 || !argv[1][0])
351
cfd = strtol(argv[1], &end, 10);
355
if (daemon(0, 1) == -1) {
356
perror("ulockmgr_server: daemon");
361
sigprocmask(SIG_SETMASK, &empty, NULL);
363
if (dup2(cfd, 4) == -1) {
364
perror("ulockmgr_server: dup2");
368
nullfd = open("/dev/null", O_RDWR);
378
int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
387
perror("ulockmgr_server: fork");
395
perror("ulockmgr_server: fork");
402
waitpid(pid, NULL, 0);
408
fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);