]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/diskd.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / DiskIO / DiskDaemon / diskd.cc
1 /*
2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section -- External DISKD process implementation. */
10
11 #include "squid.h"
12 #include "DiskIO/DiskDaemon/diomsg.h"
13 #include "hash.h"
14
15 #include <cerrno>
16 #include <iostream>
17 #if HAVE_SYS_IPC_H
18 #include <sys/ipc.h>
19 #endif
20 #if HAVE_SYS_MSG_H
21 #include <sys/msg.h>
22 #endif
23 #if HAVE_SYS_SHM_H
24 #include <sys/shm.h>
25 #endif
26
27 void
28 xassert(const char *msg, const char *file, int line)
29 {
30 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
31
32 abort();
33 }
34
35 const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
36 #define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
37
38 typedef struct _file_state file_state;
39
40 struct _file_state {
41 void *key;
42 file_state *next;
43 int id;
44 int fd;
45 off_t offset;
46 };
47
48 static hash_table *hash = NULL;
49 static pid_t mypid;
50 static char *shmbuf;
51 static int DebugLevel = 0;
52
53 static int
54 do_open(diomsg * r, int, const char *buf)
55 {
56 int fd;
57 file_state *fs;
58 /*
59 * note r->offset holds open() flags
60 */
61 fd = open(buf, r->offset, 0600);
62
63 if (fd < 0) {
64 DEBUG(1) {
65 fprintf(stderr, "%d %s: ", (int) mypid, buf);
66 perror("open");
67 }
68
69 return -errno;
70 }
71
72 fs = (file_state *)xcalloc(1, sizeof(*fs));
73 fs->id = r->id;
74 fs->key = &fs->id; /* gack */
75 fs->fd = fd;
76 hash_join(hash, (hash_link *) fs);
77 DEBUG(2) {
78 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
79 (int) mypid,
80 fs->id,
81 fs->fd,
82 fs);
83 }
84 return fd;
85 }
86
87 static int
88 do_close(diomsg * r, int)
89 {
90 int fd;
91 file_state *fs;
92 fs = (file_state *) hash_lookup(hash, &r->id);
93
94 if (NULL == fs) {
95 errno = EBADF;
96 DEBUG(1) {
97 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
98 perror("do_close");
99 }
100
101 return -errno;
102 }
103
104 fd = fs->fd;
105 hash_remove_link(hash, (hash_link *) fs);
106 DEBUG(2) {
107 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
108 (int) mypid,
109 r->id,
110 fs->fd,
111 fs);
112 }
113 xfree(fs);
114 return close(fd);
115 }
116
117 static int
118 do_read(diomsg * r, int, char *buf)
119 {
120 int x;
121 int readlen = r->size;
122 file_state *fs;
123 fs = (file_state *) hash_lookup(hash, &r->id);
124
125 if (NULL == fs) {
126 errno = EBADF;
127 DEBUG(1) {
128 fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id);
129 perror("do_read");
130 }
131
132 return -errno;
133 }
134
135 if (r->offset > -1 && r->offset != fs->offset) {
136 DEBUG(2) {
137 fprintf(stderr, "seeking to %" PRId64 "\n", (int64_t)r->offset);
138 }
139
140 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
141 DEBUG(1) {
142 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
143 perror("lseek");
144 }
145 }
146 }
147
148 x = read(fs->fd, buf, readlen);
149 DEBUG(2) {
150 fprintf(stderr, "%d READ %d,%d,%" PRId64 " ret %d\n", (int) mypid,
151 fs->fd, readlen, (int64_t)r->offset, x);
152 }
153
154 if (x < 0) {
155 DEBUG(1) {
156 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
157 perror("read");
158 }
159
160 return -errno;
161 }
162
163 fs->offset = r->offset + x;
164 return x;
165 }
166
167 static int
168 do_write(diomsg * r, int, const char *buf)
169 {
170 int wrtlen = r->size;
171 int x;
172 file_state *fs;
173 fs = (file_state *) hash_lookup(hash, &r->id);
174
175 if (NULL == fs) {
176 errno = EBADF;
177 DEBUG(1) {
178 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
179 perror("do_write");
180 }
181
182 return -errno;
183 }
184
185 if (r->offset > -1 && r->offset != fs->offset) {
186 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
187 DEBUG(1) {
188 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
189 perror("lseek");
190 }
191 }
192 }
193
194 DEBUG(2) {
195 fprintf(stderr, "%d WRITE %d,%d,%" PRId64 "\n", (int) mypid,
196 fs->fd, wrtlen, (int64_t)r->offset);
197 }
198 x = write(fs->fd, buf, wrtlen);
199
200 if (x < 0) {
201 DEBUG(1) {
202 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
203 perror("write");
204 }
205
206 return -errno;
207 }
208
209 fs->offset = r->offset + x;
210 return x;
211 }
212
213 static int
214 do_unlink(diomsg * r, int, const char *buf)
215 {
216 if (unlink(buf) < 0) {
217 DEBUG(1) {
218 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
219 perror("unlink");
220 }
221
222 return -errno;
223 }
224
225 DEBUG(2) {
226 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
227 }
228 return 0;
229 }
230
231 static void
232 msg_handle(diomsg * r, int rl, diomsg * s)
233 {
234 char *buf = NULL;
235 s->mtype = r->mtype;
236 s->id = r->id;
237 s->seq_no = r->seq_no; /* optional, debugging */
238 s->callback_data = r->callback_data;
239 s->requestor = r->requestor;
240 s->size = 0; /* optional, debugging */
241 s->offset = 0; /* optional, debugging */
242 s->shm_offset = r->shm_offset;
243 s->newstyle = r->newstyle;
244
245 if (s->shm_offset > -1)
246 buf = shmbuf + s->shm_offset;
247 else if (r->mtype != _MQD_CLOSE) {
248 fprintf(stderr, "%d UNLNK id(%u) Error: no filename in shm buffer\n", (int) mypid, s->id);
249 return;
250 }
251
252 switch (r->mtype) {
253
254 case _MQD_OPEN:
255
256 case _MQD_CREATE:
257 s->status = do_open(r, rl, buf);
258 break;
259
260 case _MQD_CLOSE:
261 s->status = do_close(r, rl);
262 break;
263
264 case _MQD_READ:
265 s->status = do_read(r, rl, buf);
266 break;
267
268 case _MQD_WRITE:
269 s->status = do_write(r, rl, buf);
270 break;
271
272 case _MQD_UNLINK:
273 s->status = do_unlink(r, rl, buf);
274 break;
275
276 default:
277 assert(0);
278 break;
279 }
280 }
281
282 static int
283 fsCmp(const void *a, const void *b)
284 {
285 const int *A = (const int *)a;
286 const int *B = (const int *)b;
287 return *A != *B;
288 }
289
290 static unsigned int
291 fsHash(const void *key, unsigned int n)
292 {
293 /* note, n must be a power of 2! */
294 const int *k = (const int *)key;
295 return (*k & (--n));
296 }
297
298 extern "C" {
299 static void alarm_handler(int) {}
300 };
301
302 int
303 main(int argc, char *argv[])
304 {
305 int key;
306 int rmsgid;
307 int smsgid;
308 int shmid;
309 diomsg rmsg;
310 diomsg smsg;
311 int rlen;
312 char rbuf[512];
313
314 struct sigaction sa;
315 setbuf(stdout, NULL);
316 setbuf(stderr, NULL);
317 mypid = getpid();
318 assert(4 == argc);
319 key = atoi(argv[1]);
320 rmsgid = msgget(key, 0600);
321
322 if (rmsgid < 0) {
323 perror("msgget");
324 exit(EXIT_FAILURE);
325 }
326
327 key = atoi(argv[2]);
328 smsgid = msgget(key, 0600);
329
330 if (smsgid < 0) {
331 perror("msgget");
332 exit(EXIT_FAILURE);
333 }
334
335 key = atoi(argv[3]);
336 shmid = shmget(key, 0, 0600);
337
338 if (shmid < 0) {
339 perror("shmget");
340 exit(EXIT_FAILURE);
341 }
342
343 shmbuf = (char *)shmat(shmid, NULL, 0);
344
345 if (shmbuf == (void *) -1) {
346 perror("shmat");
347 exit(EXIT_FAILURE);
348 }
349
350 hash = hash_create(fsCmp, 1 << 4, fsHash);
351 assert(hash);
352 if (fcntl(0, F_SETFL, SQUID_NONBLOCK) < 0) {
353 perror(xstrerr(errno));
354 exit(EXIT_FAILURE);
355 }
356 memset(&sa, '\0', sizeof(sa));
357 sa.sa_handler = alarm_handler;
358 sa.sa_flags = SA_RESTART;
359 sigaction(SIGALRM, &sa, NULL);
360
361 for (;;) {
362 alarm(1);
363 memset(&rmsg, '\0', sizeof(rmsg));
364 DEBUG(2) {
365 std::cerr << "msgrcv: " << rmsgid << ", "
366 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
367 << ", " << 0 << ", " << 0 << std::endl;
368 }
369 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
370
371 if (rlen < 0) {
372 if (EINTR == errno) {
373 if (read(0, rbuf, 512) <= 0) {
374 if (EWOULDBLOCK == errno)
375 (void) 0;
376 else if (EAGAIN == errno)
377 (void) 0;
378 else
379 break;
380 }
381 }
382
383 if (EAGAIN == errno) {
384 continue;
385 }
386
387 perror("msgrcv");
388 break;
389 }
390
391 alarm(0);
392 msg_handle(&rmsg, rlen, &smsg);
393
394 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
395 perror("msgsnd");
396 break;
397 }
398 }
399
400 DEBUG(2) {
401 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
402 }
403
404 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
405 perror("msgctl IPC_RMID");
406
407 if (msgctl(smsgid, IPC_RMID, 0) < 0)
408 perror("msgctl IPC_RMID");
409
410 if (shmdt(shmbuf) < 0)
411 perror("shmdt");
412
413 if (shmctl(shmid, IPC_RMID, 0) < 0)
414 perror("shmctl IPC_RMID");
415
416 return EXIT_SUCCESS;
417 }
418