Squid Web Cache master
Loading...
Searching...
No Matches
log_file_daemon.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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#include "squid.h"
10
11#include "compat/unistd.h"
12
13#include <cassert>
14#include <cerrno>
15#include <csignal>
16#include <cstring>
17#if HAVE_FCNTL_H
18#include <fcntl.h>
19#endif
20#if HAVE_SYS_PARAM_H
21#include <sys/param.h>
22#endif
23#if HAVE_SYS_STAT_H
24#include <sys/stat.h>
25#endif
26#if HAVE_PATHS_H
27#include <paths.h>
28#endif
29
31
32/* parse buffer - ie, length of longest expected line */
33#define LOGFILE_BUF_LEN 65536
34
35static void
36rotate(const char *path, int rotate_count)
37{
38#ifdef S_ISREG
39 struct stat sb;
40#endif
41 int i;
42 char from[MAXPATHLEN];
43 char to[MAXPATHLEN];
44 assert(path);
45#ifdef S_ISREG
46 if (stat(path, &sb) == 0)
47 if (S_ISREG(sb.st_mode) == 0)
48 return;
49#endif
50 /* Rotate numbers 0 through N up one */
51 for (i = rotate_count; i > 1;) {
52 --i;
53 snprintf(from, MAXPATHLEN, "%s.%d", path, i - 1);
54 snprintf(to, MAXPATHLEN, "%s.%d", path, i);
55#if _SQUID_OS2_ || _SQUID_WINDOWS_
56 if (remove(to) < 0) {
57 int xerrno = errno;
58 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerr(xerrno));
59 }
60#endif
61 if (rename(from, to) < 0 && errno != ENOENT) {
62 int xerrno = errno;
63 fprintf(stderr, "WARNING: rename '%s' to '%s' failure: %s\n", from, to, xstrerr(xerrno));
64 }
65 }
66 if (rotate_count > 0) {
67 snprintf(to, MAXPATHLEN, "%s.%d", path, 0);
68#if _SQUID_OS2_ || _SQUID_WINDOWS_
69 if (remove(to) < 0) {
70 int xerrno = errno;
71 fprintf(stderr, "WARNING: remove '%s' failure: %s\n", to, xstrerr(xerrno));
72 }
73#endif
74 if (rename(path, to) < 0 && errno != ENOENT) {
75 int xerrno = errno;
76 fprintf(stderr, "WARNING: rename %s to %s failure: %s\n", path, to, xstrerr(xerrno));
77 }
78 }
79}
80
92int
93main(int argc, char *argv[])
94{
95 int t;
96 FILE *fp;
97 char buf[LOGFILE_BUF_LEN];
98 int rotate_count = 10;
99 int do_buffer = 1;
100
101 if (argc < 2) {
102 printf("Error: usage: %s <logfile>\n", argv[0]);
103 exit(EXIT_FAILURE);
104 }
105 fp = fopen(argv[1], "a");
106 if (fp == nullptr) {
107 perror("fopen");
108 exit(EXIT_FAILURE);
109 }
110 setbuf(stdout, nullptr);
111 /* XXX stderr should not be closed, but in order to support squid must be
112 * able to collect and manage modules' stderr first.
113 */
114 xclose(2);
115 t = xopen(_PATH_DEVNULL, O_RDWR);
116 assert(t > -1);
117 dup2(t, 2);
118
119 while (fgets(buf, LOGFILE_BUF_LEN, stdin)) {
120 /* First byte indicates what we're logging! */
121 switch (buf[0]) {
122 case 'L':
123 if (buf[1] != '\0') {
124 fprintf(fp, "%s", buf + 1);
125 /* try to detect the 32-bit file too big write error and rotate */
126 int err = ferror(fp);
127 clearerr(fp);
128 if (err != 0) {
129 /* file too big - recover by rotating the logs and starting a new one.
130 * out of device space - recover by rotating and hoping that rotation count drops a big one.
131 */
132 if (err == EFBIG || err == ENOSPC) {
133 fprintf(stderr, "WARNING: %s writing %s. Attempting to recover via a log rotation.\n",xstrerr(err),argv[1]);
134 fclose(fp);
135 rotate(argv[1], rotate_count);
136 fp = fopen(argv[1], "a");
137 if (fp == nullptr) {
138 perror("fopen");
139 exit(EXIT_FAILURE);
140 }
141 fprintf(fp, "%s", buf + 1);
142 } else {
143 perror("fprintf");
144 exit(EXIT_FAILURE);
145 }
146 }
147 }
148 if (!do_buffer)
149 fflush(fp);
150 break;
151 case 'R':
152 fclose(fp);
153 rotate(argv[1], rotate_count);
154 fp = fopen(argv[1], "a");
155 if (fp == nullptr) {
156 perror("fopen");
157 exit(EXIT_FAILURE);
158 }
159 break;
160 case 'T':
161 break;
162 case 'O':
163 break;
164 case 'r':
165 //fprintf(fp, "SET ROTATE: %s\n", buf + 1);
166 rotate_count = atoi(buf + 1);
167 break;
168 case 'b':
169 //fprintf(fp, "SET BUFFERED: %s\n", buf + 1);
170 do_buffer = (buf[1] == '1');
171 break;
172 case 'F':
173 fflush(fp);
174 break;
175 default:
176 /* Just in case .. */
177 fprintf(fp, "%s", buf);
178 break;
179 }
180 }
181 fclose(fp);
182 fp = nullptr;
183 return EXIT_SUCCESS;
184}
185
#define assert(EX)
Definition assert.h:17
int main()
static void rotate(const char *path, int rotate_count)
#define LOGFILE_BUF_LEN
#define MAXPATHLEN
Definition stdio.h:62
int xclose(int fd)
POSIX close(2) equivalent.
Definition unistd.h:43
int xopen(const char *filename, int oflag, int pmode=0)
POSIX open(2) equivalent.
Definition unistd.h:55
const char * xstrerr(int error)
Definition xstrerror.cc:83