ModStdio.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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 50 Log file handling */
10
11#include "squid.h"
12#include "fatal.h"
13#include "fd.h"
14#include "fde.h"
15#include "fs_io.h"
16#include "globals.h"
17#include "log/File.h"
18#include "log/ModStdio.h"
19#include "SquidConfig.h"
20
21#include <cerrno>
22
23typedef struct {
24 int fd;
25 char *buf;
26 size_t bufsz;
27 int offset;
28} l_stdio_t;
29
30/*
31 * Aborts with fatal message if write() returns something other
32 * than its length argument.
33 */
34static void
35logfileWriteWrapper(Logfile * lf, const void *buf, size_t len)
36{
37 l_stdio_t *ll = (l_stdio_t *) lf->data;
38 size_t s;
39 s = FD_WRITE_METHOD(ll->fd, (char const *) buf, len);
40 int xerrno = errno;
41 fd_bytes(ll->fd, s, FD_WRITE);
42
43 if (s == len)
44 return;
45
46 if (!lf->flags.fatal)
47 return;
48
49 fatalf("logfileWrite: %s: %s\n", lf->path, xstrerr(xerrno));
50}
51
52static void
53logfile_mod_stdio_writeline(Logfile * lf, const char *buf, size_t len)
54{
55 l_stdio_t *ll = (l_stdio_t *) lf->data;
56
57 if (0 == ll->bufsz) {
58 /* buffering disabled */
59 logfileWriteWrapper(lf, buf, len);
60 return;
61 }
62 if (ll->offset > 0 && (ll->offset + len) > ll->bufsz)
63 logfileFlush(lf);
64
65 if (len > ll->bufsz) {
66 /* too big to fit in buffer */
67 logfileWriteWrapper(lf, buf, len);
68 return;
69 }
70 /* buffer it */
71 memcpy(ll->buf + ll->offset, buf, len);
72
73 ll->offset += len;
74
75 assert(ll->offset >= 0);
76
77 assert((size_t) ll->offset <= ll->bufsz);
78}
79
80static void
82{
83}
84
85static void
87{
88 lf->f_flush(lf);
89}
90
91static void
93{
94 l_stdio_t *ll = (l_stdio_t *) lf->data;
95 if (0 == ll->offset)
96 return;
97 logfileWriteWrapper(lf, ll->buf, (size_t) ll->offset);
98 ll->offset = 0;
99}
100
101static void
102logfile_mod_stdio_rotate(Logfile * lf, const int16_t nRotate)
103{
104#ifdef S_ISREG
105
106 struct stat sb;
107#endif
108
109 l_stdio_t *ll = (l_stdio_t *) lf->data;
110 const char *realpath = lf->path+6; // skip 'stdio:' prefix.
111 assert(realpath);
112
113#ifdef S_ISREG
114
115 if (stat(realpath, &sb) == 0)
116 if (S_ISREG(sb.st_mode) == 0)
117 return;
118
119#endif
120
121 debugs(0, DBG_IMPORTANT, "Rotate log file " << lf->path);
122
123 SBuf basePath(realpath);
124
125 /* Rotate numbers 0 through N up one */
126 for (int16_t i = nRotate; i > 1;) {
127 --i;
128 SBuf from(basePath);
129 from.appendf(".%d", i-1);
130 SBuf to(basePath);
131 to.appendf(".%d", i);
132 FileRename(from, to);
133 // TODO handle rename errors
134 }
135
136 /* Rotate the current log to .0 */
137 logfileFlush(lf);
138
139 file_close(ll->fd); /* always close */
140
141 if (nRotate > 0) {
142 SBuf to(basePath);
143 to.appendf(".0");
144 FileRename(basePath, to);
145 // TODO handle rename errors
146 }
147 /* Reopen the log. It may have been renamed "manually" */
148 ll->fd = file_open(realpath, O_WRONLY | O_CREAT | O_TEXT);
149
150 if (DISK_ERROR == ll->fd && lf->flags.fatal) {
151 int xerrno = errno;
152 debugs(50, DBG_CRITICAL, MYNAME << "ERROR: " << lf->path << ": " << xstrerr(xerrno));
153 fatalf("Cannot open %s: %s", lf->path, xstrerr(xerrno));
154 }
155}
156
157static void
159{
160 l_stdio_t *ll = (l_stdio_t *) lf->data;
161 lf->f_flush(lf);
162
163 if (ll->fd >= 0)
164 file_close(ll->fd);
165
166 if (ll->buf)
167 xfree(ll->buf);
168
169 xfree(lf->data);
170 lf->data = nullptr;
171}
172
173/*
174 * This code expects the path to be a writable filename
175 */
176int
177logfile_mod_stdio_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
178{
185
186 l_stdio_t *ll = static_cast<l_stdio_t*>(xcalloc(1, sizeof(*ll)));
187 lf->data = ll;
188
189 ll->fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
190
191 if (DISK_ERROR == ll->fd) {
192 int xerrno = errno;
193 if (ENOENT == xerrno && fatal_flag) {
194 fatalf("Cannot open '%s' because\n"
195 "\tthe parent directory does not exist.\n"
196 "\tPlease create the directory.\n", path);
197 } else if (EACCES == xerrno && fatal_flag) {
198 fatalf("Cannot open '%s' for writing.\n"
199 "\tThe parent directory must be writeable by the\n"
200 "\tuser '%s', which is the cache_effective_user\n"
201 "\tset in squid.conf.", path, Config.effectiveUser);
202 } else if (EISDIR == xerrno && fatal_flag) {
203 fatalf("Cannot open '%s' because it is a directory, not a file.\n", path);
204 } else {
205 debugs(50, DBG_IMPORTANT, MYNAME << "ERROR: " << lf->path << ": " << xstrerr(xerrno));
206 return 0;
207 }
208 }
209 if (bufsz > 0) {
210 ll->buf = static_cast<char*>(xmalloc(bufsz));
211 ll->bufsz = bufsz;
212 }
213 return 1;
214}
215
static void logfile_mod_stdio_writeline(Logfile *lf, const char *buf, size_t len)
Definition: ModStdio.cc:53
static void logfile_mod_stdio_lineend(Logfile *lf)
Definition: ModStdio.cc:86
static void logfile_mod_stdio_flush(Logfile *lf)
Definition: ModStdio.cc:92
int logfile_mod_stdio_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag)
Definition: ModStdio.cc:177
static void logfileWriteWrapper(Logfile *lf, const void *buf, size_t len)
Definition: ModStdio.cc:35
static void logfile_mod_stdio_rotate(Logfile *lf, const int16_t nRotate)
Definition: ModStdio.cc:102
static void logfile_mod_stdio_close(Logfile *lf)
Definition: ModStdio.cc:158
static void logfile_mod_stdio_linestart(Logfile *)
Definition: ModStdio.cc:81
class SquidConfig Config
Definition: SquidConfig.cc:12
#define assert(EX)
Definition: assert.h:17
Definition: File.h:39
LOGLINEEND * f_lineend
Definition: File.h:59
LOGFLUSH * f_flush
Definition: File.h:60
void * data
Definition: File.h:55
LOGCLOSE * f_close
Definition: File.h:62
char path[MAXPATHLEN]
Definition: File.h:46
struct Logfile::@79 flags
LOGLINESTART * f_linestart
Definition: File.h:57
LOGWRITE * f_linewrite
Definition: File.h:58
unsigned int fatal
Definition: File.h:49
LOGROTATE * f_rotate
Definition: File.h:61
Definition: SBuf.h:94
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:229
char * effectiveUser
Definition: SquidConfig.h:196
#define MYNAME
Definition: Stream.h:236
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
#define DBG_CRITICAL
Definition: Stream.h:37
#define O_TEXT
Definition: defines.h:133
#define DISK_ERROR
Definition: defines.h:28
@ FD_WRITE
Definition: enums.h:24
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:226
int FD_WRITE_METHOD(int fd, const char *buf, int len)
Definition: fde.h:200
int file_open(const char *path, int mode)
Definition: fs_io.cc:45
bool FileRename(const SBuf &from, const SBuf &to)
Definition: fs_io.cc:480
void file_close(int fd)
Definition: fs_io.cc:73
void logfileFlush(Logfile *lf)
Definition: File.cc:139
#define xfree
#define xmalloc
static struct stat sb
Definition: squidclient.cc:71
int offset
Definition: ModStdio.cc:27
char * buf
Definition: ModStdio.cc:25
int fd
Definition: ModStdio.cc:24
size_t bufsz
Definition: ModStdio.cc:26
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors