static char * errorTryLoadText(const char *page_name, const char *dir) { int fd; char path[MAXPATHLEN]; struct stat sb; char *text; snprintf(path, sizeof(path), "%s/%s", dir, page_name); #ifdef _SQUID_MSWIN_ fd = file_open(path, O_RDONLY | O_BINARY); #else fd = file_open(path, O_RDONLY | O_TEXT); #endif if (fd < 0 || fstat(fd, &sb) < 0) { debug(4, 0) ("errorTryLoadText: '%s': %s\n", path, xstrerror()); if (fd >= 0) file_close(fd); return NULL; } text = xcalloc((size_t) sb.st_size + 2 + 1, 1); /* 2 == space for %S */ if (FD_READ_METHOD(fd, text, (int) sb.st_size) != sb.st_size) { debug(4, 0) ("errorTryLoadText: failed to fully read: '%s': %s\n", path, xstrerror()); safe_free(text); } file_close(fd); if (text && strstr(text, "%s") == NULL) strcat(text, "%S"); /* add signature */ return text; }
static void squidaio_fdhandler(int fd, void *data) { char junk[256]; FD_READ_METHOD(done_fd_read, junk, sizeof(junk)); commSetSelect(fd, COMM_SELECT_READ, squidaio_fdhandler, NULL, 0); }
static void identReadReply(int fd, void *data) { IdentStateData *state = data; LOCAL_ARRAY(char, buf, BUFSIZ); char *ident = NULL; char *t = NULL; int len = -1; buf[0] = '\0'; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, BUFSIZ - 1); fd_bytes(fd, len, FD_READ); if (len <= 0) { comm_close(fd); return; } /* * XXX This isn't really very tolerant. It should read until EOL * or EOF and then decode the answer... If the reply is fragmented * then this will fail */ buf[len] = '\0'; if ((t = strchr(buf, '\r'))) *t = '\0'; if ((t = strchr(buf, '\n'))) *t = '\0'; debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf); if (strstr(buf, "USERID")) { if ((ident = strrchr(buf, ':'))) { while (xisspace(*++ident)); identCallback(state, ident); } } comm_close(fd); }
static void idnsReadTcp(int fd, void *data) { ssize_t n; idns_query *q = data; int ns = (q->nsends - 1) % nns; if (!q->tcp_buffer) q->tcp_buffer = memAllocBuf(1024, &q->tcp_buffer_size); statCounter.syscalls.sock.reads++; n = FD_READ_METHOD(q->tcp_socket, q->tcp_buffer + q->tcp_buffer_offset, q->tcp_buffer_size - q->tcp_buffer_offset); if (n < 0 && ignoreErrno(errno)) { commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0); return; } if (n <= 0) { debug(78, 1) ("idnsReadTcp: Short response from nameserver %d for %s.\n", ns + 1, q->name); idnsTcpCleanup(q); return; } fd_bytes(fd, n, FD_READ); q->tcp_buffer_offset += n; if (q->tcp_buffer_offset > 2) { unsigned short response_size = ntohs(*(short *) q->tcp_buffer); if (q->tcp_buffer_offset >= response_size + 2) { nameservers[ns].nreplies++; idnsGrokReply(q->tcp_buffer + 2, response_size); return; } if (q->tcp_buffer_size < response_size + 2) q->tcp_buffer = memReallocBuf(q->tcp_buffer, response_size + 2, &q->tcp_buffer_size); } commSetSelect(q->tcp_socket, COMM_SELECT_READ, idnsReadTcp, q, 0); }
static void whoisReadReply(int fd, void *data) { WhoisState *p = data; StoreEntry *entry = p->entry; char *buf = memAllocate(MEM_4K_BUF); MemObject *mem = entry->mem_obj; int len; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, 4095); buf[len] = '\0'; debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len); debug(75, 5) ("{%s}\n", buf); if (len > 0) { if (0 == mem->inmem_hi) { http_reply *reply = mem->reply; http_version_t version; storeBuffer(entry); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2); httpReplySwapOut(reply, entry); } fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.http.kbytes_in, len); storeAppend(entry, buf, len); storeBufferFlush(entry); commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (len < 0) { debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else { ErrorState *err; err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, p->fwd->request); err->xerrno = errno; fwdFail(p->fwd, err); comm_close(fd); } } else { storeTimestampsSet(entry); storeBufferFlush(entry); if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) storeSetPublicKey(entry); fwdComplete(p->fwd); debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); comm_close(fd); } memFree(buf, MEM_4K_BUF); }
static void helperStatefulHandleRead(int fd, void *data) { int len; char *t = NULL; helper_stateful_server *srv = data; helper_stateful_request *r; statefulhelper *hlp = srv->parent; assert(fd == srv->rfd); assert(cbdataValid(data)); statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, srv->buf + srv->offset, srv->buf_sz - srv->offset); fd_bytes(fd, len, FD_READ); debug(84, 5) ("helperStatefulHandleRead: %d bytes from %s #%d.\n", len, hlp->id_name, srv->index + 1); if (len <= 0) { if (len < 0) debug(84, 1) ("helperStatefulHandleRead: FD %d read: %s\n", fd, xstrerror()); comm_close(fd); return; } srv->offset += len; srv->buf[srv->offset] = '\0'; r = srv->request; if (r == NULL) { /* someone spoke without being spoken to */ debug(84, 1) ("helperStatefulHandleRead: unexpected read from %s #%d, %d bytes\n", hlp->id_name, srv->index + 1, len); srv->offset = 0; } else if ((t = strchr(srv->buf, '\n'))) { /* end of reply found */ debug(84, 3) ("helperStatefulHandleRead: end of reply found\n"); *t = '\0'; srv->flags.busy = 0; srv->offset = 0; srv->request = NULL; hlp->stats.replies++; hlp->stats.avg_svc_time = intAverage(hlp->stats.avg_svc_time, tvSubMsec(srv->dispatch_time, current_time), hlp->stats.replies, REDIRECT_AV_FACTOR); if (cbdataValid(r->data)) { r->callback(r->data, srv, srv->buf); } else { debug(84, 1) ("StatefulHandleRead: no callback data registered\n"); } helperStatefulRequestFree(r); } else { commSetSelect(srv->rfd, COMM_SELECT_READ, helperStatefulHandleRead, srv, 0); } }
/* Read from FD */ static void diskHandleRead(int fd, void *data) { dread_ctrl *ctrl_dat = data; fde *F = &fd_table[fd]; int len; int rc = DISK_OK; /* * FD < 0 indicates premature close; we just have to free * the state data. */ if (fd < 0) { memFree(ctrl_dat, MEM_DREAD_CTRL); return; } if (F->disk.offset != ctrl_dat->file_offset) { debug(6, 3) ("diskHandleRead: FD %d seeking to offset %d\n", fd, (int) ctrl_dat->file_offset); lseek(fd, ctrl_dat->file_offset, SEEK_SET); /* XXX ignore return? */ statCounter.syscalls.disk.seeks++; F->disk.offset = ctrl_dat->file_offset; } errno = 0; len = FD_READ_METHOD(fd, ctrl_dat->buf, ctrl_dat->req_len); if (len > 0) F->disk.offset += len; statCounter.syscalls.disk.reads++; fd_bytes(fd, len, FD_READ); if (len < 0) { if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, diskHandleRead, ctrl_dat, 0); return; } debug(50, 1) ("diskHandleRead: FD %d: %s\n", fd, xstrerror()); len = 0; rc = DISK_ERROR; } else if (len == 0) { rc = DISK_EOF; } if (cbdataValid(ctrl_dat->client_data)) ctrl_dat->handler(fd, ctrl_dat->buf, len, rc, ctrl_dat->client_data); cbdataUnlock(ctrl_dat->client_data); memFree(ctrl_dat, MEM_DREAD_CTRL); }
static void pconnRead(int fd, void *data) { LOCAL_ARRAY(char, buf, 256); struct _pconn *p = data; int n; assert(table != NULL); statCounter.syscalls.sock.reads++; n = FD_READ_METHOD(fd, buf, 256); debug(48, 3) ("pconnRead: %d bytes from FD %d, %s\n", n, fd, hashKeyStr(&p->hash)); pconnRemoveFD(p, fd); comm_close(fd); }
/* This will be called when data is ready to be read from fd. Read until * error or connection closed. */ static void gopherReadReply(int fd, void *data) { GopherStateData *gopherState = data; StoreEntry *entry = gopherState->entry; char *buf = NULL; int len; int clen; int bin; size_t read_sz; #if DELAY_POOLS delay_id delay_id; #endif if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; buf = memAllocate(MEM_4K_BUF); read_sz = 4096 - 1; /* leave room for termination */ #if DELAY_POOLS delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif /* leave one space for \0 in gopherToHTML */ statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, read_sz); if (len > 0) { fd_bytes(fd, len, FD_READ); #if DELAY_POOLS delayBytesIn(delay_id, len); #endif kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.other.kbytes_in, len); } debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, len); if (len > 0) { commSetTimeout(fd, Config.Timeout.read, NULL, NULL); IOStats.Gopher.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Gopher.read_hist[bin]++; }
static void whoisReadReply(int fd, void *data) { WhoisState *p = data; StoreEntry *entry = p->entry; char *buf = memAllocate(MEM_4K_BUF); MemObject *mem = entry->mem_obj; int len; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, 4095); buf[len] = '\0'; debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len); debug(75, 5) ("{%s}\n", buf); if (len > 0) { if (0 == mem->inmem_hi) mem->reply->sline.status = HTTP_OK; fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.http.kbytes_in, len); storeAppend(entry, buf, len); commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (len < 0) { debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (mem->inmem_hi == 0) { ErrorState *err; err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; fwdFail(p->fwd, err); comm_close(fd); } else { comm_close(fd); } } else { fwdComplete(p->fwd); debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); comm_close(fd); } memFree(buf, MEM_4K_BUF); }
/* * Gobble up (read) some bytes until we get to the start of the body */ static void icapRespModGobble(int fd, void *data) { IcapStateData *icap = data; int len; LOCAL_ARRAY(char, junk, SQUID_TCP_SO_RCVBUF); debug(81, 3) ("icapRespModGobble: FD %d gobbling %d bytes\n", fd, icap->bytes_to_gobble); len = FD_READ_METHOD(fd, junk, icap->bytes_to_gobble); debug(81, 3) ("icapRespModGobble: gobbled %d bytes\n", len); if (len < 0) { /* XXX error */ abort(); } icap->bytes_to_gobble -= len; if (icap->bytes_to_gobble) commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0); else icapReadReply(fd, icap); }
/* This will be called when data is ready to be read from fd. Read until * error or connection closed. */ static void waisReadReply(int fd, void *data) { WaisStateData *waisState = data; LOCAL_ARRAY(char, buf, 4096); StoreEntry *entry = waisState->entry; int len; int clen; int bin; size_t read_sz; #if DELAY_POOLS delay_id delay_id; #endif if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; read_sz = 4096; #if DELAY_POOLS delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz); #endif statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, read_sz); if (len > 0) { fd_bytes(fd, len, FD_READ); #if DELAY_POOLS delayBytesIn(delay_id, len); #endif kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.other.kbytes_in, len); } debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, len); if (len > 0) { commSetTimeout(fd, Config.Timeout.read, NULL, NULL); IOStats.Wais.reads++; for (clen = len - 1, bin = 0; clen; bin++) clen >>= 1; IOStats.Wais.read_hist[bin]++; }
squidaio_result_t * squidaio_poll_done(void) { squidaio_request_t *request; squidaio_result_t *resultp; int cancelled; int polled = 0; AIO_REPOLL: request = done_requests.head; if (request == NULL && !polled) { if (done_signalled) { char junk[256]; FD_READ_METHOD(done_fd_read, junk, sizeof(junk)); done_signalled = 0; } squidaio_poll_queues(); polled = 1; request = done_requests.head; } if (!request) { return NULL; } debug(43, 9) ("squidaio_poll_done: %p type=%d result=%p\n", request, request->request_type, request->resultp); done_requests.head = request->next; if (!done_requests.head) done_requests.tailp = &done_requests.head; resultp = request->resultp; cancelled = request->cancelled; squidaio_debug(request); debug(43, 5) ("DONE: %d -> %d\n", request->ret, request->err); squidaio_cleanup_request(request); if (cancelled) goto AIO_REPOLL; return resultp; } /* squidaio_poll_done */
static void mimeLoadIconFile(const char *icon) { int fd; int n; request_flags flags; struct stat sb; StoreEntry *e; LOCAL_ARRAY(char, path, MAXPATHLEN); LOCAL_ARRAY(char, url, MAX_URL); char *buf; const char *type = mimeGetContentType(icon); HttpReply *reply; http_version_t version; request_t *r; if (type == NULL) fatal("Unknown icon format while reading mime.conf\n"); buf = internalLocalUri("/squid-internal-static/icons/", icon); xstrncpy(url, buf, MAX_URL); if (storeGetPublic(url, METHOD_GET)) return; snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon); fd = file_open(path, O_RDONLY | O_BINARY); if (fd < 0) { debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror()); return; } if (fstat(fd, &sb) < 0) { debug(25, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror()); file_close(fd); return; } flags = null_request_flags; flags.cachable = 1; e = storeCreateEntry(url, url, flags, METHOD_GET); assert(e != NULL); EBIT_SET(e->flags, ENTRY_SPECIAL); storeSetPublicKey(e); storeBuffer(e); r = urlParse(METHOD_GET, url); if (NULL == r) fatal("mimeLoadIcon: cannot parse internal URL"); e->mem_obj->request = requestLink(r); httpReplyReset(reply = e->mem_obj->reply); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(reply, version, HTTP_OK, NULL, type, (int) sb.st_size, sb.st_mtime, -1); reply->cache_control = httpHdrCcCreate(); httpHdrCcSetMaxAge(reply->cache_control, 86400); httpHeaderPutCc(&reply->header, reply->cache_control); httpReplySwapOut(reply, e); reply->hdr_sz = e->mem_obj->inmem_hi; /* yuk */ /* read the file into the buffer and append it to store */ buf = memAllocate(MEM_4K_BUF); while ((n = FD_READ_METHOD(fd, buf, 4096)) > 0) storeAppend(e, buf, n); file_close(fd); storeBufferFlush(e); storeComplete(e); storeTimestampsSet(e); debug(25, 3) ("Loaded icon %s\n", url); storeUnlockObject(e); memFree(buf, MEM_4K_BUF); }
static void netdbReloadState(void) { char *buf; char *t; char *s; int fd; int l; struct stat sb; netdbEntry *n; netdbEntry N; struct in_addr addr; int count = 0; struct timeval start = current_time; if (strcmp(Config.netdbFilename, "none") == 0) return; /* * This was nicer when we were using stdio, but thanks to * Solaris bugs, its a bad idea. fopen can fail if more than * 256 FDs are open. */ fd = file_open(Config.netdbFilename, O_RDONLY | O_BINARY); if (fd < 0) return; if (fstat(fd, &sb) < 0) { file_close(fd); return; } t = buf = xcalloc(1, (size_t) sb.st_size + 1); l = FD_READ_METHOD(fd, buf, (int) sb.st_size); file_close(fd); if (l <= 0) return; while ((s = strchr(t, '\n'))) { char *q; assert(s - buf < l); *s = '\0'; memset(&N, '\0', sizeof(netdbEntry)); q = strtok(t, w_space); t = s + 1; if (NULL == q) continue; if (!safe_inet_addr(q, &addr)) continue; if (netdbLookupAddr(addr) != NULL) /* no dups! */ continue; if ((q = strtok(NULL, w_space)) == NULL) continue; N.pings_sent = atoi(q); if ((q = strtok(NULL, w_space)) == NULL) continue; N.pings_recv = atoi(q); if (N.pings_recv == 0) continue; /* give this measurement low weight */ N.pings_sent = 1; N.pings_recv = 1; if ((q = strtok(NULL, w_space)) == NULL) continue; N.hops = atof(q); if ((q = strtok(NULL, w_space)) == NULL) continue; N.rtt = atof(q); if ((q = strtok(NULL, w_space)) == NULL) continue; N.next_ping_time = (time_t) atoi(q); if ((q = strtok(NULL, w_space)) == NULL) continue; N.last_use_time = (time_t) atoi(q); n = memAllocate(MEM_NETDBENTRY); xmemcpy(n, &N, sizeof(netdbEntry)); netdbHashInsert(n, addr); while ((q = strtok(NULL, w_space)) != NULL) { if (netdbLookupHost(q) != NULL) /* no dups! */ continue; netdbHostInsert(n, q); } count++; } xfree(buf); getCurrentTime(); debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n", count, tvSubMsec(start, current_time)); }