ModStdio.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 
23 typedef 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  */
34 static void
35 logfileWriteWrapper(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 
52 static void
53 logfile_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 
80 static void
82 {
83 }
84 
85 static void
87 {
88  lf->f_flush(lf);
89 }
90 
91 static 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 
101 static void
102 logfile_mod_stdio_rotate(Logfile * lf, const int16_t nRotate)
103 {
104 #ifdef S_ISREG
105 
106  struct stat sb;
107 #endif
108 
109  char from[MAXPATHLEN];
110  char to[MAXPATHLEN];
111  l_stdio_t *ll = (l_stdio_t *) lf->data;
112  const char *realpath = lf->path+6; // skip 'stdio:' prefix.
113  assert(realpath);
114 
115 #ifdef S_ISREG
116 
117  if (stat(realpath, &sb) == 0)
118  if (S_ISREG(sb.st_mode) == 0)
119  return;
120 
121 #endif
122 
123  debugs(0, DBG_IMPORTANT, "Rotate log file " << lf->path);
124 
125  /* Rotate numbers 0 through N up one */
126  for (int16_t i = nRotate; i > 1;) {
127  --i;
128  snprintf(from, MAXPATHLEN, "%s.%d", realpath, i - 1);
129  snprintf(to, MAXPATHLEN, "%s.%d", realpath, i);
130  xrename(from, to);
131  }
132 
133  /* Rotate the current log to .0 */
134  logfileFlush(lf);
135 
136  file_close(ll->fd); /* always close */
137 
138  if (nRotate > 0) {
139  snprintf(to, MAXPATHLEN, "%s.%d", realpath, 0);
140  xrename(realpath, to);
141  }
142  /* Reopen the log. It may have been renamed "manually" */
143  ll->fd = file_open(realpath, O_WRONLY | O_CREAT | O_TEXT);
144 
145  if (DISK_ERROR == ll->fd && lf->flags.fatal) {
146  int xerrno = errno;
147  debugs(50, DBG_CRITICAL, MYNAME << "ERROR: " << lf->path << ": " << xstrerr(xerrno));
148  fatalf("Cannot open %s: %s", lf->path, xstrerr(xerrno));
149  }
150 }
151 
152 static void
154 {
155  l_stdio_t *ll = (l_stdio_t *) lf->data;
156  lf->f_flush(lf);
157 
158  if (ll->fd >= 0)
159  file_close(ll->fd);
160 
161  if (ll->buf)
162  xfree(ll->buf);
163 
164  xfree(lf->data);
165  lf->data = NULL;
166 }
167 
168 /*
169  * This code expects the path to be a writable filename
170  */
171 int
172 logfile_mod_stdio_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
173 {
180 
181  l_stdio_t *ll = static_cast<l_stdio_t*>(xcalloc(1, sizeof(*ll)));
182  lf->data = ll;
183 
184  ll->fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
185 
186  if (DISK_ERROR == ll->fd) {
187  int xerrno = errno;
188  if (ENOENT == xerrno && fatal_flag) {
189  fatalf("Cannot open '%s' because\n"
190  "\tthe parent directory does not exist.\n"
191  "\tPlease create the directory.\n", path);
192  } else if (EACCES == xerrno && fatal_flag) {
193  fatalf("Cannot open '%s' for writing.\n"
194  "\tThe parent directory must be writeable by the\n"
195  "\tuser '%s', which is the cache_effective_user\n"
196  "\tset in squid.conf.", path, Config.effectiveUser);
197  } else if (EISDIR == xerrno && fatal_flag) {
198  fatalf("Cannot open '%s' because it is a directory, not a file.\n", path);
199  } else {
200  debugs(50, DBG_IMPORTANT, MYNAME << "ERROR: " << lf->path << ": " << xstrerr(xerrno));
201  return 0;
202  }
203  }
204  if (bufsz > 0) {
205  ll->buf = static_cast<char*>(xmalloc(bufsz));
206  ll->bufsz = bufsz;
207  }
208  return 1;
209 }
210 
static void logfile_mod_stdio_close(Logfile *lf)
Definition: ModStdio.cc:153
LOGFLUSH * f_flush
Definition: File.h:60
#define assert(EX)
Definition: assert.h:17
int logfile_mod_stdio_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag)
Definition: ModStdio.cc:172
LOGWRITE * f_linewrite
Definition: File.h:58
Definition: File.h:38
unsigned int fatal
Definition: File.h:49
size_t bufsz
Definition: ModStdio.cc:26
char * buf
Definition: ModStdio.cc:25
#define xcalloc
Definition: membanger.c:57
char * effectiveUser
Definition: SquidConfig.h:185
int i
Definition: membanger.c:49
#define MAXPATHLEN
Definition: stdio.h:62
int file_open(const char *path, int mode)
Definition: fs_io.cc:46
void logfileFlush(Logfile *lf)
Definition: File.cc:147
Definition: enums.h:24
#define DBG_CRITICAL
Definition: Debug.h:44
int xrename(const char *from, const char *to)
Definition: fs_io.cc:513
#define DISK_ERROR
Definition: defines.h:40
LOGLINEEND * f_lineend
Definition: File.h:59
void fatalf(const char *fmt,...)
Definition: fatal.cc:79
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:261
void * data
Definition: File.h:55
char path[MAXPATHLEN]
Definition: File.h:46
const char * xstrerr(int error)
Definition: xstrerror.cc:83
static void logfile_mod_stdio_writeline(Logfile *lf, const char *buf, size_t len)
Definition: ModStdio.cc:53
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
static void logfileWriteWrapper(Logfile *lf, const void *buf, size_t len)
Definition: ModStdio.cc:35
#define DBG_IMPORTANT
Definition: Debug.h:45
int offset
Definition: ModStdio.cc:27
static void logfile_mod_stdio_rotate(Logfile *lf, const int16_t nRotate)
Definition: ModStdio.cc:102
static void logfile_mod_stdio_flush(Logfile *lf)
Definition: ModStdio.cc:92
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void const char * buf
Definition: stub_helper.cc:16
#define O_TEXT
Definition: defines.h:201
#define MYNAME
Definition: Debug.h:160
int fd
Definition: ModStdio.cc:24
#define xmalloc
static void logfile_mod_stdio_linestart(Logfile *)
Definition: ModStdio.cc:81
LOGLINESTART * f_linestart
Definition: File.h:57
struct Logfile::@85 flags
LOGROTATE * f_rotate
Definition: File.h:61
#define FD_WRITE_METHOD(fd, buf, len)
Definition: fde.h:162
static void logfile_mod_stdio_lineend(Logfile *lf)
Definition: ModStdio.cc:86
#define xfree
void file_close(int fd)
Definition: fs_io.cc:76
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
LOGCLOSE * f_close
Definition: File.h:62

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors