]> git.ipfire.org Git - thirdparty/squid.git/blame - src/DiskIO/DiskDaemon/diskd.cc
Fix some issues revealed by Coverty Scan, improve documentation of parseHttpRequest
[thirdparty/squid.git] / src / DiskIO / DiskDaemon / diskd.cc
CommitLineData
b95b6efb 1/*
b95b6efb 2 * DEBUG: section -- External DISKD process implementation.
3 * AUTHOR: Harvest Derived
4 *
2b6662ba 5 * SQUID Web Proxy Cache http://www.squid-cache.org/
b95b6efb 6 * ----------------------------------------------------------
7 *
2b6662ba 8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
b95b6efb 16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
26ac0430 21 *
b95b6efb 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26ac0430 26 *
b95b6efb 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
cd748f27 32
f7f3304a 33#include "squid.h"
8cab55b3
AJ
34#include "DiskIO/DiskDaemon/diomsg.h"
35#include "hash.h"
cd748f27 36
cec4754f
AJ
37#if HAVE_ERRNO_H
38#include <errno.h>
39#endif
d440d5a4 40#if HAVE_SYS_IPC_H
cd748f27 41#include <sys/ipc.h>
d440d5a4
AJ
42#endif
43#if HAVE_SYS_MSG_H
cd748f27 44#include <sys/msg.h>
d440d5a4
AJ
45#endif
46#if HAVE_SYS_SHM_H
cd748f27 47#include <sys/shm.h>
d440d5a4 48#endif
cec4754f
AJ
49#if HAVE_IOSTREAM
50#include <iostream>
51#endif
cd748f27 52
137a13ea 53void
54xassert(const char *msg, const char *file, int line)
55{
56 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
cd748f27 57
137a13ea 58 abort();
59}
cd748f27 60
b9ae18aa 61const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
62#define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
cd748f27 63
64typedef struct _file_state file_state;
65
26ac0430 66struct _file_state {
cd748f27 67 void *key;
68 file_state *next;
69 int id;
70 int fd;
71 off_t offset;
72};
73
74static hash_table *hash = NULL;
75static pid_t mypid;
76static char *shmbuf;
46069294 77static int DebugLevel = 0;
cd748f27 78
79static int
80do_open(diomsg * r, int len, const char *buf)
81{
82 int fd;
83 file_state *fs;
84 /*
85 * note r->offset holds open() flags
86 */
87 fd = open(buf, r->offset, 0600);
62e76326 88
cd748f27 89 if (fd < 0) {
62e76326 90 DEBUG(1) {
91 fprintf(stderr, "%d %s: ", (int) mypid, buf);
92 perror("open");
93 }
94
95 return -errno;
cd748f27 96 }
62e76326 97
e6ccf245 98 fs = (file_state *)xcalloc(1, sizeof(*fs));
cd748f27 99 fs->id = r->id;
6ca34f6f 100 fs->key = &fs->id; /* gack */
cd748f27 101 fs->fd = fd;
102 hash_join(hash, (hash_link *) fs);
6ca34f6f
HN
103 DEBUG(2) {
104 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
105 (int) mypid,
106 fs->id,
107 fs->fd,
108 fs);
109 }
cd748f27 110 return fd;
111}
112
113static int
114do_close(diomsg * r, int len)
115{
116 int fd;
117 file_state *fs;
118 fs = (file_state *) hash_lookup(hash, &r->id);
62e76326 119
cd748f27 120 if (NULL == fs) {
62e76326 121 errno = EBADF;
122 DEBUG(1) {
123 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
124 perror("do_close");
125 }
126
127 return -errno;
cd748f27 128 }
62e76326 129
cd748f27 130 fd = fs->fd;
131 hash_remove_link(hash, (hash_link *) fs);
6ca34f6f
HN
132 DEBUG(2) {
133 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
134 (int) mypid,
135 r->id,
136 fs->fd,
137 fs);
138 }
cd748f27 139 xfree(fs);
140 return close(fd);
141}
142
143static int
144do_read(diomsg * r, int len, char *buf)
145{
146 int x;
147 int readlen = r->size;
148 file_state *fs;
149 fs = (file_state *) hash_lookup(hash, &r->id);
62e76326 150
cd748f27 151 if (NULL == fs) {
62e76326 152 errno = EBADF;
153 DEBUG(1) {
154 fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id);
155 perror("do_read");
156 }
157
158 return -errno;
cd748f27 159 }
62e76326 160
cd748f27 161 if (r->offset > -1 && r->offset != fs->offset) {
6ca34f6f 162 DEBUG(2) {
c91ca3ce 163 fprintf(stderr, "seeking to %" PRId64 "\n", (int64_t)r->offset);
6ca34f6f 164 }
62e76326 165
166 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
167 DEBUG(1) {
c91ca3ce 168 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
62e76326 169 perror("lseek");
170 }
171 }
cd748f27 172 }
62e76326 173
cd748f27 174 x = read(fs->fd, buf, readlen);
6ca34f6f 175 DEBUG(2) {
c91ca3ce 176 fprintf(stderr, "%d READ %d,%d,%" PRId64 " ret %d\n", (int) mypid,
6ca34f6f
HN
177 fs->fd, readlen, (int64_t)r->offset, x);
178 }
62e76326 179
cd748f27 180 if (x < 0) {
62e76326 181 DEBUG(1) {
182 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
183 perror("read");
184 }
185
186 return -errno;
cd748f27 187 }
62e76326 188
cd748f27 189 fs->offset = r->offset + x;
190 return x;
191}
192
193static int
194do_write(diomsg * r, int len, const char *buf)
195{
196 int wrtlen = r->size;
197 int x;
198 file_state *fs;
199 fs = (file_state *) hash_lookup(hash, &r->id);
62e76326 200
cd748f27 201 if (NULL == fs) {
62e76326 202 errno = EBADF;
203 DEBUG(1) {
204 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
205 perror("do_write");
206 }
207
208 return -errno;
cd748f27 209 }
62e76326 210
cd748f27 211 if (r->offset > -1 && r->offset != fs->offset) {
62e76326 212 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
213 DEBUG(1) {
c91ca3ce 214 fprintf(stderr, "%d FD %d, offset %" PRId64 ": ", (int) mypid, fs->fd, (int64_t)r->offset);
62e76326 215 perror("lseek");
216 }
217 }
cd748f27 218 }
62e76326 219
6ca34f6f 220 DEBUG(2) {
c91ca3ce 221 fprintf(stderr, "%d WRITE %d,%d,%" PRId64 "\n", (int) mypid,
6ca34f6f
HN
222 fs->fd, wrtlen, (int64_t)r->offset);
223 }
cd748f27 224 x = write(fs->fd, buf, wrtlen);
62e76326 225
cd748f27 226 if (x < 0) {
62e76326 227 DEBUG(1) {
228 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
229 perror("write");
230 }
231
232 return -errno;
cd748f27 233 }
62e76326 234
cd748f27 235 fs->offset = r->offset + x;
236 return x;
237}
238
239static int
240do_unlink(diomsg * r, int len, const char *buf)
241{
b3fb9070 242 if (unlink(buf) < 0) {
62e76326 243 DEBUG(1) {
244 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
6af23c85 245 perror("unlink");
62e76326 246 }
247
248 return -errno;
cd748f27 249 }
62e76326 250
6ca34f6f
HN
251 DEBUG(2) {
252 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
253 }
cd748f27 254 return 0;
255}
256
257static void
258msg_handle(diomsg * r, int rl, diomsg * s)
259{
260 char *buf = NULL;
261 s->mtype = r->mtype;
a1ad81aa 262 s->id = r->id;
6ca34f6f 263 s->seq_no = r->seq_no; /* optional, debugging */
cd748f27 264 s->callback_data = r->callback_data;
b9ae18aa 265 s->requestor = r->requestor;
6ca34f6f
HN
266 s->size = 0; /* optional, debugging */
267 s->offset = 0; /* optional, debugging */
cd748f27 268 s->shm_offset = r->shm_offset;
d3b3ab85 269 s->newstyle = r->newstyle;
62e76326 270
cd748f27 271 if (s->shm_offset > -1)
62e76326 272 buf = shmbuf + s->shm_offset;
273
cd748f27 274 switch (r->mtype) {
62e76326 275
cd748f27 276 case _MQD_OPEN:
62e76326 277
d3b3ab85 278 case _MQD_CREATE:
62e76326 279 s->status = do_open(r, rl, buf);
280 break;
281
cd748f27 282 case _MQD_CLOSE:
62e76326 283 s->status = do_close(r, rl);
284 break;
285
cd748f27 286 case _MQD_READ:
62e76326 287 s->status = do_read(r, rl, buf);
288 break;
289
cd748f27 290 case _MQD_WRITE:
62e76326 291 s->status = do_write(r, rl, buf);
292 break;
293
cd748f27 294 case _MQD_UNLINK:
62e76326 295 s->status = do_unlink(r, rl, buf);
296 break;
297
cd748f27 298 default:
62e76326 299 assert(0);
300 break;
cd748f27 301 }
302}
303
2d72d4fd 304static int
cd748f27 305fsCmp(const void *a, const void *b)
306{
e6ccf245 307 const int *A = (const int *)a;
308 const int *B = (const int *)b;
cd748f27 309 return *A != *B;
310}
311
2d72d4fd 312static unsigned int
cd748f27 313fsHash(const void *key, unsigned int n)
314{
315 /* note, n must be a power of 2! */
e6ccf245 316 const int *k = (const int *)key;
cd748f27 317 return (*k & (--n));
318}
319
e4ae841b 320SQUIDCEXTERN {
9853f3b5
A
321 static void
322 alarm_handler(int sig) {
323 (void) 0;
324 }
e4ae841b 325};
cd748f27 326
327int
328main(int argc, char *argv[])
329{
330 int key;
331 int rmsgid;
332 int smsgid;
333 int shmid;
334 diomsg rmsg;
335 diomsg smsg;
336 int rlen;
337 char rbuf[512];
62e76326 338
cd748f27 339 struct sigaction sa;
340 setbuf(stdout, NULL);
341 setbuf(stderr, NULL);
342 mypid = getpid();
343 assert(4 == argc);
344 key = atoi(argv[1]);
345 rmsgid = msgget(key, 0600);
62e76326 346
cd748f27 347 if (rmsgid < 0) {
62e76326 348 perror("msgget");
349 return 1;
cd748f27 350 }
62e76326 351
cd748f27 352 key = atoi(argv[2]);
353 smsgid = msgget(key, 0600);
62e76326 354
cd748f27 355 if (smsgid < 0) {
62e76326 356 perror("msgget");
357 return 1;
cd748f27 358 }
62e76326 359
cd748f27 360 key = atoi(argv[3]);
361 shmid = shmget(key, 0, 0600);
62e76326 362
cd748f27 363 if (shmid < 0) {
62e76326 364 perror("shmget");
365 return 1;
cd748f27 366 }
62e76326 367
e6ccf245 368 shmbuf = (char *)shmat(shmid, NULL, 0);
62e76326 369
cd748f27 370 if (shmbuf == (void *) -1) {
62e76326 371 perror("shmat");
372 return 1;
cd748f27 373 }
62e76326 374
cd748f27 375 hash = hash_create(fsCmp, 1 << 4, fsHash);
376 assert(hash);
377 fcntl(0, F_SETFL, SQUID_NONBLOCK);
378 memset(&sa, '\0', sizeof(sa));
379 sa.sa_handler = alarm_handler;
380 sa.sa_flags = SA_RESTART;
381 sigaction(SIGALRM, &sa, NULL);
62e76326 382
cd748f27 383 for (;;) {
62e76326 384 alarm(1);
385 memset(&rmsg, '\0', sizeof(rmsg));
6ca34f6f
HN
386 DEBUG(2) {
387 std::cerr << "msgrcv: " << rmsgid << ", "
388 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
389 << ", " << 0 << ", " << 0 << std::endl;
390 }
b9ae18aa 391 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
62e76326 392
393 if (rlen < 0) {
394 if (EINTR == errno) {
395 if (read(0, rbuf, 512) <= 0) {
396 if (EWOULDBLOCK == errno)
397 (void) 0;
398 else if (EAGAIN == errno)
399 (void) 0;
400 else
401 break;
402 }
403 }
404
405 if (EAGAIN == errno) {
406 continue;
407 }
408
409 perror("msgrcv");
410 break;
411 }
412
413 alarm(0);
414 msg_handle(&rmsg, rlen, &smsg);
415
b9ae18aa 416 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
62e76326 417 perror("msgsnd");
418 break;
419 }
cd748f27 420 }
62e76326 421
6ca34f6f
HN
422 DEBUG(2) {
423 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
424 }
62e76326 425
cd748f27 426 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
62e76326 427 perror("msgctl IPC_RMID");
428
cd748f27 429 if (msgctl(smsgid, IPC_RMID, 0) < 0)
62e76326 430 perror("msgctl IPC_RMID");
431
cd748f27 432 if (shmdt(shmbuf) < 0)
62e76326 433 perror("shmdt");
434
cd748f27 435 if (shmctl(shmid, IPC_RMID, 0) < 0)
62e76326 436 perror("shmctl IPC_RMID");
437
cd748f27 438 return 0;
439}