Bug Summary

File:http/modules/ngx_http_log_module.c
Location:line 356, column 16
Description:Dereference of null pointer

Annotated Source Code

1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12#if (NGX_ZLIB1)
13#include <zlib.h>
14#endif
15
16
17typedef struct ngx_http_log_op_s ngx_http_log_op_t;
18
19typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
20 ngx_http_log_op_t *op);
21
22typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
23 uintptr_t data);
24
25
26struct ngx_http_log_op_s {
27 size_t len;
28 ngx_http_log_op_getlen_pt getlen;
29 ngx_http_log_op_run_pt run;
30 uintptr_t data;
31};
32
33
34typedef struct {
35 ngx_str_t name;
36 ngx_array_t *flushes;
37 ngx_array_t *ops; /* array of ngx_http_log_op_t */
38} ngx_http_log_fmt_t;
39
40
41typedef struct {
42 ngx_array_t formats; /* array of ngx_http_log_fmt_t */
43 ngx_uint_t combined_used; /* unsigned combined_used:1 */
44} ngx_http_log_main_conf_t;
45
46
47typedef struct {
48 u_char *start;
49 u_char *pos;
50 u_char *last;
51
52 ngx_event_t *event;
53 ngx_msec_t flush;
54 ngx_int_t gzip;
55} ngx_http_log_buf_t;
56
57
58typedef struct {
59 ngx_array_t *lengths;
60 ngx_array_t *values;
61} ngx_http_log_script_t;
62
63
64typedef struct {
65 ngx_open_file_t *file;
66 ngx_http_log_script_t *script;
67 time_t disk_full_time;
68 time_t error_log_time;
69 ngx_http_log_fmt_t *format;
70} ngx_http_log_t;
71
72
73typedef struct {
74 ngx_array_t *logs; /* array of ngx_http_log_t */
75
76 ngx_open_file_cache_t *open_file_cache;
77 time_t open_file_cache_valid;
78 ngx_uint_t open_file_cache_min_uses;
79
80 ngx_uint_t off; /* unsigned off:1 */
81} ngx_http_log_loc_conf_t;
82
83
84typedef struct {
85 ngx_str_t name;
86 size_t len;
87 ngx_http_log_op_run_pt run;
88} ngx_http_log_var_t;
89
90
91static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
92 u_char *buf, size_t len);
93static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
94 ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
95
96#if (NGX_ZLIB1)
97static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
98 ngx_int_t level, ngx_log_t *log);
99
100static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
101static void ngx_http_log_gzip_free(void *opaque, void *address);
102#endif
103
104static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
105static void ngx_http_log_flush_handler(ngx_event_t *ev);
106
107static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
108 ngx_http_log_op_t *op);
109static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
110 ngx_http_log_op_t *op);
111static u_char *ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf,
112 ngx_http_log_op_t *op);
113static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
114 ngx_http_log_op_t *op);
115static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
116 ngx_http_log_op_t *op);
117static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
118 ngx_http_log_op_t *op);
119static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
120 ngx_http_log_op_t *op);
121static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r,
122 u_char *buf, ngx_http_log_op_t *op);
123static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
124 ngx_http_log_op_t *op);
125
126static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
127 ngx_http_log_op_t *op, ngx_str_t *value);
128static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
129 uintptr_t data);
130static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
131 ngx_http_log_op_t *op);
132static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
133
134
135static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
136static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
137static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
138 void *child);
139static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
140 void *conf);
141static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
142 void *conf);
143static char *ngx_http_log_compile_format(ngx_conf_t *cf,
144 ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
145static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
146 void *conf);
147static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
148
149
150static ngx_command_t ngx_http_log_commands[] = {
151
152 { ngx_string("log_format"){ sizeof("log_format") - 1, (u_char *) "log_format" },
153 NGX_HTTP_MAIN_CONF0x02000000|NGX_HTTP_SRV_CONF0x04000000|NGX_HTTP_LOC_CONF0x08000000|NGX_CONF_2MORE0x00001000,
154 ngx_http_log_set_format,
155 NGX_HTTP_MAIN_CONF_OFFSET__builtin_offsetof(ngx_http_conf_ctx_t, main_conf),
156 0,
157 NULL((void*)0) },
158
159 { ngx_string("access_log"){ sizeof("access_log") - 1, (u_char *) "access_log" },
160 NGX_HTTP_MAIN_CONF0x02000000|NGX_HTTP_SRV_CONF0x04000000|NGX_HTTP_LOC_CONF0x08000000|NGX_HTTP_LIF_CONF0x40000000
161 |NGX_HTTP_LMT_CONF0x80000000|NGX_CONF_1MORE0x00000800,
162 ngx_http_log_set_log,
163 NGX_HTTP_LOC_CONF_OFFSET__builtin_offsetof(ngx_http_conf_ctx_t, loc_conf),
164 0,
165 NULL((void*)0) },
166
167 { ngx_string("open_log_file_cache"){ sizeof("open_log_file_cache") - 1, (u_char *) "open_log_file_cache"
}
,
168 NGX_HTTP_MAIN_CONF0x02000000|NGX_HTTP_SRV_CONF0x04000000|NGX_HTTP_LOC_CONF0x08000000|NGX_CONF_TAKE1234(0x00000002|0x00000004|0x00000008 |0x00000010),
169 ngx_http_log_open_file_cache,
170 NGX_HTTP_LOC_CONF_OFFSET__builtin_offsetof(ngx_http_conf_ctx_t, loc_conf),
171 0,
172 NULL((void*)0) },
173
174 ngx_null_command{ { 0, ((void*)0) }, 0, ((void*)0), 0, 0, ((void*)0) }
175};
176
177
178static ngx_http_module_t ngx_http_log_module_ctx = {
179 NULL((void*)0), /* preconfiguration */
180 ngx_http_log_init, /* postconfiguration */
181
182 ngx_http_log_create_main_conf, /* create main configuration */
183 NULL((void*)0), /* init main configuration */
184
185 NULL((void*)0), /* create server configuration */
186 NULL((void*)0), /* merge server configuration */
187
188 ngx_http_log_create_loc_conf, /* create location configuration */
189 ngx_http_log_merge_loc_conf /* merge location configuration */
190};
191
192
193ngx_module_t ngx_http_log_module = {
194 NGX_MODULE_V10, 0, 0, 0, 0, 0, 1,
195 &ngx_http_log_module_ctx, /* module context */
196 ngx_http_log_commands, /* module directives */
197 NGX_HTTP_MODULE0x50545448, /* module type */
198 NULL((void*)0), /* init master */
199 NULL((void*)0), /* init module */
200 NULL((void*)0), /* init process */
201 NULL((void*)0), /* init thread */
202 NULL((void*)0), /* exit thread */
203 NULL((void*)0), /* exit process */
204 NULL((void*)0), /* exit master */
205 NGX_MODULE_V1_PADDING0, 0, 0, 0, 0, 0, 0, 0
206};
207
208
209static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH){ sizeof("logs/access.log") - 1, (u_char *) "logs/access.log"
}
;
210
211
212static ngx_str_t ngx_http_combined_fmt =
213 ngx_string("$remote_addr - $remote_user [$time_local] "{ sizeof("$remote_addr - $remote_user [$time_local] " "\"$request\" $status $body_bytes_sent "
"\"$http_referer\" \"$http_user_agent\"") - 1, (u_char *) "$remote_addr - $remote_user [$time_local] "
"\"$request\" $status $body_bytes_sent " "\"$http_referer\" \"$http_user_agent\""
}
214 "\"$request\" $status $body_bytes_sent "{ sizeof("$remote_addr - $remote_user [$time_local] " "\"$request\" $status $body_bytes_sent "
"\"$http_referer\" \"$http_user_agent\"") - 1, (u_char *) "$remote_addr - $remote_user [$time_local] "
"\"$request\" $status $body_bytes_sent " "\"$http_referer\" \"$http_user_agent\""
}
215 "\"$http_referer\" \"$http_user_agent\""){ sizeof("$remote_addr - $remote_user [$time_local] " "\"$request\" $status $body_bytes_sent "
"\"$http_referer\" \"$http_user_agent\"") - 1, (u_char *) "$remote_addr - $remote_user [$time_local] "
"\"$request\" $status $body_bytes_sent " "\"$http_referer\" \"$http_user_agent\""
}
;
216
217
218static ngx_http_log_var_t ngx_http_log_vars[] = {
219 { ngx_string("pipe"){ sizeof("pipe") - 1, (u_char *) "pipe" }, 1, ngx_http_log_pipe },
220 { ngx_string("time_local"){ sizeof("time_local") - 1, (u_char *) "time_local" }, sizeof("28/Sep/1970:12:00:00 +0600") - 1,
221 ngx_http_log_time },
222 { ngx_string("time_iso8601"){ sizeof("time_iso8601") - 1, (u_char *) "time_iso8601" }, sizeof("1970-09-28T12:00:00+06:00") - 1,
223 ngx_http_log_iso8601 },
224 { ngx_string("msec"){ sizeof("msec") - 1, (u_char *) "msec" }, NGX_TIME_T_LEN(sizeof("-9223372036854775808") - 1) + 4, ngx_http_log_msec },
225 { ngx_string("request_time"){ sizeof("request_time") - 1, (u_char *) "request_time" }, NGX_TIME_T_LEN(sizeof("-9223372036854775808") - 1) + 4,
226 ngx_http_log_request_time },
227 { ngx_string("status"){ sizeof("status") - 1, (u_char *) "status" }, NGX_INT_T_LENsizeof("-9223372036854775808") - 1, ngx_http_log_status },
228 { ngx_string("bytes_sent"){ sizeof("bytes_sent") - 1, (u_char *) "bytes_sent" }, NGX_OFF_T_LEN(sizeof("-9223372036854775808") - 1), ngx_http_log_bytes_sent },
229 { ngx_string("body_bytes_sent"){ sizeof("body_bytes_sent") - 1, (u_char *) "body_bytes_sent"
}
, NGX_OFF_T_LEN(sizeof("-9223372036854775808") - 1),
230 ngx_http_log_body_bytes_sent },
231 { ngx_string("request_length"){ sizeof("request_length") - 1, (u_char *) "request_length" }, NGX_SIZE_T_LEN(sizeof("-9223372036854775808") - 1),
232 ngx_http_log_request_length },
233
234 { ngx_null_string{ 0, ((void*)0) }, 0, NULL((void*)0) }
235};
236
237
238static ngx_int_t
239ngx_http_log_handler(ngx_http_request_t *r)
240{
241 u_char *line, *p;
242 size_t len;
243 ngx_uint_t i, l;
244 ngx_http_log_t *log;
245 ngx_http_log_op_t *op;
246 ngx_http_log_buf_t *buffer;
247 ngx_http_log_loc_conf_t *lcf;
248
249 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
250 "http log handler");
251
252 lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module)(r)->loc_conf[ngx_http_log_module.ctx_index];
253
254 if (lcf->off) {
1
Taking false branch
255 return NGX_OK0;
256 }
257
258 log = lcf->logs->elts;
259 for (l = 0; l < lcf->logs->nelts; l++) {
2
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
260
261 if (ngx_time()ngx_cached_time->sec == log[l].disk_full_time) {
3
Taking false branch
11
Taking false branch
19
Taking false branch
262
263 /*
264 * on FreeBSD writing to a full filesystem with enabled softupdates
265 * may block process for much longer time than writing to non-full
266 * filesystem, so we skip writing to a log for one second
267 */
268
269 continue;
270 }
271
272 ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
273
274 len = 0;
275 op = log[l].format->ops->elts;
276 for (i = 0; i < log[l].format->ops->nelts; i++) {
4
Loop condition is false. Execution continues on line 285
12
Loop condition is false. Execution continues on line 285
20
Loop condition is false. Execution continues on line 285
277 if (op[i].len == 0) {
278 len += op[i].getlen(r, op[i].data);
279
280 } else {
281 len += op[i].len;
282 }
283 }
284
285 len += NGX_LINEFEED_SIZE1;
286
287 buffer = log[l].file ? log[l].file->data : NULL((void*)0);
5
'?' condition is false
13
'?' condition is false
21
Assuming pointer value is null
22
'?' condition is false
288
289 if (buffer) {
6
Taking false branch
14
Taking false branch
23
Taking false branch
290
291 if (len > (size_t) (buffer->last - buffer->pos)) {
292
293 ngx_http_log_write(r, &log[l], buffer->start,
294 buffer->pos - buffer->start);
295
296 buffer->pos = buffer->start;
297 }
298
299 if (len <= (size_t) (buffer->last - buffer->pos)) {
300
301 p = buffer->pos;
302
303 if (buffer->event && p == buffer->start) {
304 ngx_add_timerngx_event_add_timer(buffer->event, buffer->flush);
305 }
306
307 for (i = 0; i < log[l].format->ops->nelts; i++) {
308 p = op[i].run(r, p, &op[i]);
309 }
310
311 ngx_linefeed(p)*p++ = (u_char) 10;;
312
313 buffer->pos = p;
314
315 continue;
316 }
317
318 if (buffer->event && buffer->event->timer_set) {
319 ngx_del_timerngx_event_del_timer(buffer->event);
320 }
321 }
322
323 line = ngx_pnalloc(r->pool, len);
324 if (line == NULL((void*)0)) {
7
Assuming 'line' is not equal to null
8
Taking false branch
15
Assuming 'line' is not equal to null
16
Taking false branch
24
Assuming 'line' is not equal to null
25
Taking false branch
325 return NGX_ERROR-1;
326 }
327
328 p = line;
329
330 for (i = 0; i < log[l].format->ops->nelts; i++) {
9
Loop condition is false. Execution continues on line 334
17
Loop condition is false. Execution continues on line 334
26
Loop condition is false. Execution continues on line 334
331 p = op[i].run(r, p, &op[i]);
332 }
333
334 ngx_linefeed(p)*p++ = (u_char) 10;;
335
336 ngx_http_log_write(r, &log[l], line, p - line);
27
Calling 'ngx_http_log_write'
337 }
338
339 return NGX_OK0;
340}
341
342
343static void
344ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
345 size_t len)
346{
347 u_char *name;
348 time_t now;
349 ssize_t n;
350 ngx_err_t err;
351#if (NGX_ZLIB1)
352 ngx_http_log_buf_t *buffer;
353#endif
354
355 if (log->script == NULL((void*)0)) {
28
Taking true branch
356 name = log->file->name.data;
29
Dereference of null pointer
357
358#if (NGX_ZLIB1)
359 buffer = log->file->data;
360
361 if (buffer && buffer->gzip) {
362 n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
363 r->connection->log);
364 } else {
365 n = ngx_write_fd(log->file->fd, buf, len);
366 }
367#else
368 n = ngx_write_fd(log->file->fd, buf, len);
369#endif
370
371 } else {
372 name = NULL((void*)0);
373 n = ngx_http_log_script_write(r, log->script, &name, buf, len);
374 }
375
376 if (n == (ssize_t) len) {
377 return;
378 }
379
380 now = ngx_time()ngx_cached_time->sec;
381
382 if (n == -1) {
383 err = ngx_errno(*__error());
384
385 if (err == NGX_ENOSPC28) {
386 log->disk_full_time = now;
387 }
388
389 if (now - log->error_log_time > 59) {
390 ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, err, "write()" " to \"%s\" failed"
, name)
391 ngx_write_fd_n " to \"%s\" failed", name)if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, err, "write()" " to \"%s\" failed"
, name)
;
392
393 log->error_log_time = now;
394 }
395
396 return;
397 }
398
399 if (now - log->error_log_time > 59) {
400 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "write()" " to \"%s\" was incomplete: %z of %uz"
, name, n, len)
401 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "write()" " to \"%s\" was incomplete: %z of %uz"
, name, n, len)
402 name, n, len)if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "write()" " to \"%s\" was incomplete: %z of %uz"
, name, n, len)
;
403
404 log->error_log_time = now;
405 }
406}
407
408
409static ssize_t
410ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
411 u_char **name, u_char *buf, size_t len)
412{
413 size_t root;
414 ssize_t n;
415 ngx_str_t log, path;
416 ngx_open_file_info_t of;
417 ngx_http_log_loc_conf_t *llcf;
418 ngx_http_core_loc_conf_t *clcf;
419
420 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
421
422 if (!r->root_tested) {
423
424 /* test root directory existence */
425
426 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL((void*)0)) {
427 /* simulate successful logging */
428 return len;
429 }
430
431 path.data[root] = '\0';
432
433 ngx_memzero(&of, sizeof(ngx_open_file_info_t))(void) ((__builtin_object_size (&of, 0) != (size_t) -1) ?
__builtin___memset_chk (&of, 0, sizeof(ngx_open_file_info_t
), __builtin_object_size (&of, 0)) : __inline_memset_chk (
&of, 0, sizeof(ngx_open_file_info_t)))
;
434
435 of.valid = clcf->open_file_cache_valid;
436 of.min_uses = clcf->open_file_cache_min_uses;
437 of.test_dir = 1;
438 of.test_only = 1;
439 of.errors = clcf->open_file_cache_errors;
440 of.events = clcf->open_file_cache_events;
441
442 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK0) {
443 /* simulate successful logging */
444 return len;
445 }
446
447 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
448 != NGX_OK0)
449 {
450 if (of.err == 0) {
451 /* simulate successful logging */
452 return len;
453 }
454
455 ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, of.err, "testing \"%s\" existence failed"
, path.data)
456 "testing \"%s\" existence failed", path.data)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, of.err, "testing \"%s\" existence failed"
, path.data)
;
457
458 /* simulate successful logging */
459 return len;
460 }
461
462 if (!of.is_dir) {
463 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 20, "testing \"%s\" existence failed"
, path.data)
464 "testing \"%s\" existence failed", path.data)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 20, "testing \"%s\" existence failed"
, path.data)
;
465
466 /* simulate successful logging */
467 return len;
468 }
469 }
470
471 if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
472 script->values->elts)
473 == NULL((void*)0))
474 {
475 /* simulate successful logging */
476 return len;
477 }
478
479 log.data[log.len - 1] = '\0';
480 *name = log.data;
481
482 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
483 "http log \"%s\"", log.data);
484
485 llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module)(r)->loc_conf[ngx_http_log_module.ctx_index];
486
487 ngx_memzero(&of, sizeof(ngx_open_file_info_t))(void) ((__builtin_object_size (&of, 0) != (size_t) -1) ?
__builtin___memset_chk (&of, 0, sizeof(ngx_open_file_info_t
), __builtin_object_size (&of, 0)) : __inline_memset_chk (
&of, 0, sizeof(ngx_open_file_info_t)))
;
488
489 of.log = 1;
490 of.valid = llcf->open_file_cache_valid;
491 of.min_uses = llcf->open_file_cache_min_uses;
492 of.directio = NGX_OPEN_FILE_DIRECTIO_OFF9223372036854775807LL;
493
494 if (ngx_http_set_disable_symlinks(r, clcf, &log, &of) != NGX_OK0) {
495 /* simulate successful logging */
496 return len;
497 }
498
499 if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
500 != NGX_OK0)
501 {
502 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__error()), "%s \"%s\" failed"
, of.failed, log.data)
503 "%s \"%s\" failed", of.failed, log.data)if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__error()), "%s \"%s\" failed"
, of.failed, log.data)
;
504 /* simulate successful logging */
505 return len;
506 }
507
508 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
509 "http log #%d", of.fd);
510
511 n = ngx_write_fd(of.fd, buf, len);
512
513 return n;
514}
515
516
517#if (NGX_ZLIB1)
518
519static ssize_t
520ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
521 ngx_log_t *log)
522{
523 int rc, wbits, memlevel;
524 u_char *out;
525 size_t size;
526 ssize_t n;
527 z_stream zstream;
528 ngx_err_t err;
529 ngx_pool_t *pool;
530
531 wbits = MAX_WBITS15;
532 memlevel = MAX_MEM_LEVEL9 - 1;
533
534 while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
535 wbits--;
536 memlevel--;
537 }
538
539 /*
540 * This is a formula from deflateBound() for conservative upper bound of
541 * compressed data plus 18 bytes of gzip wrapper.
542 */
543
544 size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
545
546 ngx_memzero(&zstream, sizeof(z_stream))(void) ((__builtin_object_size (&zstream, 0) != (size_t) -
1) ? __builtin___memset_chk (&zstream, 0, sizeof(z_stream
), __builtin_object_size (&zstream, 0)) : __inline_memset_chk
(&zstream, 0, sizeof(z_stream)))
;
547
548 pool = ngx_create_pool(256, log);
549 if (pool == NULL((void*)0)) {
550 /* simulate successful logging */
551 return len;
552 }
553
554 pool->log = log;
555
556 zstream.zalloc = ngx_http_log_gzip_alloc;
557 zstream.zfree = ngx_http_log_gzip_free;
558 zstream.opaque = pool;
559
560 out = ngx_pnalloc(pool, size);
561 if (out == NULL((void*)0)) {
562 goto done;
563 }
564
565 zstream.next_in = buf;
566 zstream.avail_in = len;
567 zstream.next_out = out;
568 zstream.avail_out = size;
569
570 rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,deflateInit2_((&zstream),((int) level),(8),(wbits + 16),(
memlevel), (0), "1.2.8", (int)sizeof(z_stream))
571 Z_DEFAULT_STRATEGY)deflateInit2_((&zstream),((int) level),(8),(wbits + 16),(
memlevel), (0), "1.2.8", (int)sizeof(z_stream))
;
572
573 if (rc != Z_OK0) {
574 ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc)if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "deflateInit2() failed: %d", rc)
;
575 goto done;
576 }
577
578 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
579 "deflate in: ni:%p no:%p ai:%ud ao:%ud",
580 zstream.next_in, zstream.next_out,
581 zstream.avail_in, zstream.avail_out);
582
583 rc = deflate(&zstream, Z_FINISH4);
584
585 if (rc != Z_STREAM_END1) {
586 ngx_log_error(NGX_LOG_ALERT, log, 0,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "deflate(Z_FINISH) failed: %d", rc)
587 "deflate(Z_FINISH) failed: %d", rc)if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "deflate(Z_FINISH) failed: %d", rc)
;
588 goto done;
589 }
590
591 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
592 "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
593 zstream.next_in, zstream.next_out,
594 zstream.avail_in, zstream.avail_out,
595 rc);
596
597 size -= zstream.avail_out;
598
599 rc = deflateEnd(&zstream);
600
601 if (rc != Z_OK0) {
602 ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc)if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "deflateEnd() failed: %d", rc)
;
603 goto done;
604 }
605
606 n = ngx_write_fd(fd, out, size);
607
608 if (n != (ssize_t) size) {
609 err = (n == -1) ? ngx_errno(*__error()) : 0;
610
611 ngx_destroy_pool(pool);
612
613 ngx_set_errno(err)(*__error()) = err;
614 return -1;
615 }
616
617done:
618
619 ngx_destroy_pool(pool);
620
621 /* simulate successful logging */
622 return len;
623}
624
625
626static void *
627ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
628{
629 ngx_pool_t *pool = opaque;
630
631 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
632 "gzip alloc: n:%ud s:%ud", items, size);
633
634 return ngx_palloc(pool, items * size);
635}
636
637
638static void
639ngx_http_log_gzip_free(void *opaque, void *address)
640{
641#if 0
642 ngx_pool_t *pool = opaque;
643
644 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
645#endif
646}
647
648#endif
649
650
651static void
652ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
653{
654 size_t len;
655 ssize_t n;
656 ngx_http_log_buf_t *buffer;
657
658 buffer = file->data;
659
660 len = buffer->pos - buffer->start;
661
662 if (len == 0) {
663 return;
664 }
665
666#if (NGX_ZLIB1)
667 if (buffer->gzip) {
668 n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
669 } else {
670 n = ngx_write_fd(file->fd, buffer->start, len);
671 }
672#else
673 n = ngx_write_fd(file->fd, buffer->start, len);
674#endif
675
676 if (n == -1) {
677 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,if ((log)->log_level >= 2) ngx_log_error_core(2, log, (
*__error()), "write()" " to \"%s\" failed", file->name.data
)
678 ngx_write_fd_n " to \"%s\" failed",if ((log)->log_level >= 2) ngx_log_error_core(2, log, (
*__error()), "write()" " to \"%s\" failed", file->name.data
)
679 file->name.data)if ((log)->log_level >= 2) ngx_log_error_core(2, log, (
*__error()), "write()" " to \"%s\" failed", file->name.data
)
;
680
681 } else if ((size_t) n != len) {
682 ngx_log_error(NGX_LOG_ALERT, log, 0,if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "write()" " to \"%s\" was incomplete: %z of %uz", file->
name.data, n, len)
683 ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "write()" " to \"%s\" was incomplete: %z of %uz", file->
name.data, n, len)
684 file->name.data, n, len)if ((log)->log_level >= 2) ngx_log_error_core(2, log, 0
, "write()" " to \"%s\" was incomplete: %z of %uz", file->
name.data, n, len)
;
685 }
686
687 buffer->pos = buffer->start;
688
689 if (buffer->event && buffer->event->timer_set) {
690 ngx_del_timerngx_event_del_timer(buffer->event);
691 }
692}
693
694
695static void
696ngx_http_log_flush_handler(ngx_event_t *ev)
697{
698 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
699 "http log buffer flush handler");
700
701 ngx_http_log_flush(ev->data, ev->log);
702}
703
704
705static u_char *
706ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
707 ngx_http_log_op_t *op)
708{
709 size_t len;
710 uintptr_t data;
711
712 len = op->len;
713 data = op->data;
714
715 while (len--) {
716 *buf++ = (u_char) (data & 0xff);
717 data >>= 8;
718 }
719
720 return buf;
721}
722
723
724static u_char *
725ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
726 ngx_http_log_op_t *op)
727{
728 return ngx_cpymem(buf, (u_char *) op->data, op->len)(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, (u_char *) op->data, op->
len, __builtin_object_size (buf, 0)) : __inline_memcpy_chk (buf
, (u_char *) op->data, op->len))) + (op->len))
;
729}
730
731
732static u_char *
733ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
734{
735 if (r->pipeline) {
736 *buf = 'p';
737 } else {
738 *buf = '.';
739 }
740
741 return buf + 1;
742}
743
744
745static u_char *
746ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
747{
748 return ngx_cpymem(buf, ngx_cached_http_log_time.data,(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, ngx_cached_http_log_time.data
, ngx_cached_http_log_time.len, __builtin_object_size (buf, 0
)) : __inline_memcpy_chk (buf, ngx_cached_http_log_time.data,
ngx_cached_http_log_time.len))) + (ngx_cached_http_log_time.
len))
749 ngx_cached_http_log_time.len)(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, ngx_cached_http_log_time.data
, ngx_cached_http_log_time.len, __builtin_object_size (buf, 0
)) : __inline_memcpy_chk (buf, ngx_cached_http_log_time.data,
ngx_cached_http_log_time.len))) + (ngx_cached_http_log_time.
len))
;
750}
751
752static u_char *
753ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
754{
755 return ngx_cpymem(buf, ngx_cached_http_log_iso8601.data,(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, ngx_cached_http_log_iso8601.data
, ngx_cached_http_log_iso8601.len, __builtin_object_size (buf
, 0)) : __inline_memcpy_chk (buf, ngx_cached_http_log_iso8601
.data, ngx_cached_http_log_iso8601.len))) + (ngx_cached_http_log_iso8601
.len))
756 ngx_cached_http_log_iso8601.len)(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, ngx_cached_http_log_iso8601.data
, ngx_cached_http_log_iso8601.len, __builtin_object_size (buf
, 0)) : __inline_memcpy_chk (buf, ngx_cached_http_log_iso8601
.data, ngx_cached_http_log_iso8601.len))) + (ngx_cached_http_log_iso8601
.len))
;
757}
758
759static u_char *
760ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
761{
762 ngx_time_t *tp;
763
764 tp = ngx_timeofday()(ngx_time_t *) ngx_cached_time;
765
766 return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);
767}
768
769
770static u_char *
771ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
772 ngx_http_log_op_t *op)
773{
774 ngx_time_t *tp;
775 ngx_msec_int_t ms;
776
777 tp = ngx_timeofday()(ngx_time_t *) ngx_cached_time;
778
779 ms = (ngx_msec_int_t)
780 ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
781 ms = ngx_max(ms, 0)((ms < 0) ? (0) : (ms));
782
783 return ngx_sprintf(buf, "%T.%03M", (time_t) ms / 1000, ms % 1000);
784}
785
786
787static u_char *
788ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
789{
790 ngx_uint_t status;
791
792 if (r->err_status) {
793 status = r->err_status;
794
795 } else if (r->headers_out.status) {
796 status = r->headers_out.status;
797
798 } else if (r->http_version == NGX_HTTP_VERSION_99) {
799 status = 9;
800
801 } else {
802 status = 0;
803 }
804
805 return ngx_sprintf(buf, "%03ui", status);
806}
807
808
809static u_char *
810ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
811 ngx_http_log_op_t *op)
812{
813 return ngx_sprintf(buf, "%O", r->connection->sent);
814}
815
816
817/*
818 * although there is a real $body_bytes_sent variable,
819 * this log operation code function is more optimized for logging
820 */
821
822static u_char *
823ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf,
824 ngx_http_log_op_t *op)
825{
826 off_t length;
827
828 length = r->connection->sent - r->header_size;
829
830 if (length > 0) {
831 return ngx_sprintf(buf, "%O", length);
832 }
833
834 *buf = '0';
835
836 return buf + 1;
837}
838
839
840static u_char *
841ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
842 ngx_http_log_op_t *op)
843{
844 return ngx_sprintf(buf, "%O", r->request_length);
845}
846
847
848static ngx_int_t
849ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
850 ngx_str_t *value)
851{
852 ngx_int_t index;
853
854 index = ngx_http_get_variable_index(cf, value);
855 if (index == NGX_ERROR-1) {
856 return NGX_ERROR-1;
857 }
858
859 op->len = 0;
860 op->getlen = ngx_http_log_variable_getlen;
861 op->run = ngx_http_log_variable;
862 op->data = index;
863
864 return NGX_OK0;
865}
866
867
868static size_t
869ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
870{
871 uintptr_t len;
872 ngx_http_variable_value_t *value;
873
874 value = ngx_http_get_indexed_variable(r, data);
875
876 if (value == NULL((void*)0) || value->not_found) {
877 return 1;
878 }
879
880 len = ngx_http_log_escape(NULL((void*)0), value->data, value->len);
881
882 value->escape = len ? 1 : 0;
883
884 return value->len + len * 3;
885}
886
887
888static u_char *
889ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
890{
891 ngx_http_variable_value_t *value;
892
893 value = ngx_http_get_indexed_variable(r, op->data);
894
895 if (value == NULL((void*)0) || value->not_found) {
896 *buf = '-';
897 return buf + 1;
898 }
899
900 if (value->escape == 0) {
901 return ngx_cpymem(buf, value->data, value->len)(((u_char *) ((__builtin_object_size (buf, 0) != (size_t) -1)
? __builtin___memcpy_chk (buf, value->data, value->len
, __builtin_object_size (buf, 0)) : __inline_memcpy_chk (buf,
value->data, value->len))) + (value->len))
;
902
903 } else {
904 return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
905 }
906}
907
908
909static uintptr_t
910ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
911{
912 ngx_uint_t n;
913 static u_char hex[] = "0123456789ABCDEF";
914
915 static uint32_t escape[] = {
916 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
917
918 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
919 0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
920
921 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
922 0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
923
924 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
925 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
926
927 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
928 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
929 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
930 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
931 };
932
933
934 if (dst == NULL((void*)0)) {
935
936 /* find the number of the characters to be escaped */
937
938 n = 0;
939
940 while (size) {
941 if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
942 n++;
943 }
944 src++;
945 size--;
946 }
947
948 return (uintptr_t) n;
949 }
950
951 while (size) {
952 if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
953 *dst++ = '\\';
954 *dst++ = 'x';
955 *dst++ = hex[*src >> 4];
956 *dst++ = hex[*src & 0xf];
957 src++;
958
959 } else {
960 *dst++ = *src++;
961 }
962 size--;
963 }
964
965 return (uintptr_t) dst;
966}
967
968
969static void *
970ngx_http_log_create_main_conf(ngx_conf_t *cf)
971{
972 ngx_http_log_main_conf_t *conf;
973
974 ngx_http_log_fmt_t *fmt;
975
976 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
977 if (conf == NULL((void*)0)) {
978 return NULL((void*)0);
979 }
980
981 if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
982 != NGX_OK0)
983 {
984 return NULL((void*)0);
985 }
986
987 fmt = ngx_array_push(&conf->formats);
988 if (fmt == NULL((void*)0)) {
989 return NULL((void*)0);
990 }
991
992 ngx_str_set(&fmt->name, "combined")(&fmt->name)->len = sizeof("combined") - 1; (&fmt
->name)->data = (u_char *) "combined"
;
993
994 fmt->flushes = NULL((void*)0);
995
996 fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
997 if (fmt->ops == NULL((void*)0)) {
998 return NULL((void*)0);
999 }
1000
1001 return conf;
1002}
1003
1004
1005static void *
1006ngx_http_log_create_loc_conf(ngx_conf_t *cf)
1007{
1008 ngx_http_log_loc_conf_t *conf;
1009
1010 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t));
1011 if (conf == NULL((void*)0)) {
1012 return NULL((void*)0);
1013 }
1014
1015 conf->open_file_cache = NGX_CONF_UNSET_PTR(void *) -1;
1016
1017 return conf;
1018}
1019
1020
1021static char *
1022ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1023{
1024 ngx_http_log_loc_conf_t *prev = parent;
1025 ngx_http_log_loc_conf_t *conf = child;
1026
1027 ngx_http_log_t *log;
1028 ngx_http_log_fmt_t *fmt;
1029 ngx_http_log_main_conf_t *lmcf;
1030
1031 if (conf->open_file_cache == NGX_CONF_UNSET_PTR(void *) -1) {
1032
1033 conf->open_file_cache = prev->open_file_cache;
1034 conf->open_file_cache_valid = prev->open_file_cache_valid;
1035 conf->open_file_cache_min_uses = prev->open_file_cache_min_uses;
1036
1037 if (conf->open_file_cache == NGX_CONF_UNSET_PTR(void *) -1) {
1038 conf->open_file_cache = NULL((void*)0);
1039 }
1040 }
1041
1042 if (conf->logs || conf->off) {
1043 return NGX_CONF_OK((void*)0);
1044 }
1045
1046 conf->logs = prev->logs;
1047 conf->off = prev->off;
1048
1049 if (conf->logs || conf->off) {
1050 return NGX_CONF_OK((void*)0);
1051 }
1052
1053 conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
1054 if (conf->logs == NULL((void*)0)) {
1055 return NGX_CONF_ERROR(void *) -1;
1056 }
1057
1058 log = ngx_array_push(conf->logs);
1059 if (log == NULL((void*)0)) {
1060 return NGX_CONF_ERROR(void *) -1;
1061 }
1062
1063 log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log);
1064 if (log->file == NULL((void*)0)) {
1065 return NGX_CONF_ERROR(void *) -1;
1066 }
1067
1068 log->script = NULL((void*)0);
1069 log->disk_full_time = 0;
1070 log->error_log_time = 0;
1071
1072 lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_log_module
.ctx_index]
;
1073 fmt = lmcf->formats.elts;
1074
1075 /* the default "combined" format */
1076 log->format = &fmt[0];
1077 lmcf->combined_used = 1;
1078
1079 return NGX_CONF_OK((void*)0);
1080}
1081
1082
1083static char *
1084ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1085{
1086 ngx_http_log_loc_conf_t *llcf = conf;
1087
1088 ssize_t size;
1089 ngx_int_t gzip;
1090 ngx_uint_t i, n;
1091 ngx_msec_t flush;
1092 ngx_str_t *value, name, s;
1093 ngx_http_log_t *log;
1094 ngx_http_log_buf_t *buffer;
1095 ngx_http_log_fmt_t *fmt;
1096 ngx_http_log_main_conf_t *lmcf;
1097 ngx_http_script_compile_t sc;
1098
1099 value = cf->args->elts;
1100
1101 if (ngx_strcmp(value[1].data, "off")strcmp((const char *) value[1].data, (const char *) "off") == 0) {
1102 llcf->off = 1;
1103 if (cf->args->nelts == 2) {
1104 return NGX_CONF_OK((void*)0);
1105 }
1106
1107 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1108 "invalid parameter \"%V\"", &value[2]);
1109 return NGX_CONF_ERROR(void *) -1;
1110 }
1111
1112 if (llcf->logs == NULL((void*)0)) {
1113 llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
1114 if (llcf->logs == NULL((void*)0)) {
1115 return NGX_CONF_ERROR(void *) -1;
1116 }
1117 }
1118
1119 lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_log_module
.ctx_index]
;
1120
1121 log = ngx_array_push(llcf->logs);
1122 if (log == NULL((void*)0)) {
1123 return NGX_CONF_ERROR(void *) -1;
1124 }
1125
1126 ngx_memzero(log, sizeof(ngx_http_log_t))(void) ((__builtin_object_size (log, 0) != (size_t) -1) ? __builtin___memset_chk
(log, 0, sizeof(ngx_http_log_t), __builtin_object_size (log,
0)) : __inline_memset_chk (log, 0, sizeof(ngx_http_log_t)))
;
1127
1128 n = ngx_http_script_variables_count(&value[1]);
1129
1130 if (n == 0) {
1131 log->file = ngx_conf_open_file(cf->cycle, &value[1]);
1132 if (log->file == NULL((void*)0)) {
1133 return NGX_CONF_ERROR(void *) -1;
1134 }
1135
1136 } else {
1137 if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK0) {
1138 return NGX_CONF_ERROR(void *) -1;
1139 }
1140
1141 log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
1142 if (log->script == NULL((void*)0)) {
1143 return NGX_CONF_ERROR(void *) -1;
1144 }
1145
1146 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t))(void) ((__builtin_object_size (&sc, 0) != (size_t) -1) ?
__builtin___memset_chk (&sc, 0, sizeof(ngx_http_script_compile_t
), __builtin_object_size (&sc, 0)) : __inline_memset_chk (
&sc, 0, sizeof(ngx_http_script_compile_t)))
;
1147
1148 sc.cf = cf;
1149 sc.source = &value[1];
1150 sc.lengths = &log->script->lengths;
1151 sc.values = &log->script->values;
1152 sc.variables = n;
1153 sc.complete_lengths = 1;
1154 sc.complete_values = 1;
1155
1156 if (ngx_http_script_compile(&sc) != NGX_OK0) {
1157 return NGX_CONF_ERROR(void *) -1;
1158 }
1159 }
1160
1161 if (cf->args->nelts >= 3) {
1162 name = value[2];
1163
1164 if (ngx_strcmp(name.data, "combined")strcmp((const char *) name.data, (const char *) "combined") == 0) {
1165 lmcf->combined_used = 1;
1166 }
1167
1168 } else {
1169 ngx_str_set(&name, "combined")(&name)->len = sizeof("combined") - 1; (&name)->
data = (u_char *) "combined"
;
1170 lmcf->combined_used = 1;
1171 }
1172
1173 fmt = lmcf->formats.elts;
1174 for (i = 0; i < lmcf->formats.nelts; i++) {
1175 if (fmt[i].name.len == name.len
1176 && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
1177 {
1178 log->format = &fmt[i];
1179 break;
1180 }
1181 }
1182
1183 if (log->format == NULL((void*)0)) {
1184 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1185 "unknown log format \"%V\"", &name);
1186 return NGX_CONF_ERROR(void *) -1;
1187 }
1188
1189 size = 0;
1190 flush = 0;
1191 gzip = 0;
1192
1193 for (i = 3; i < cf->args->nelts; i++) {
1194
1195 if (ngx_strncmp(value[i].data, "buffer=", 7)strncmp((const char *) value[i].data, (const char *) "buffer="
, 7)
== 0) {
1196 s.len = value[i].len - 7;
1197 s.data = value[i].data + 7;
1198
1199 size = ngx_parse_size(&s);
1200
1201 if (size == NGX_ERROR-1 || size == 0) {
1202 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1203 "invalid buffer size \"%V\"", &s);
1204 return NGX_CONF_ERROR(void *) -1;
1205 }
1206
1207 continue;
1208 }
1209
1210 if (ngx_strncmp(value[i].data, "flush=", 6)strncmp((const char *) value[i].data, (const char *) "flush="
, 6)
== 0) {
1211 s.len = value[i].len - 6;
1212 s.data = value[i].data + 6;
1213
1214 flush = ngx_parse_time(&s, 0);
1215
1216 if (flush == (ngx_msec_t) NGX_ERROR-1 || flush == 0) {
1217 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1218 "invalid flush time \"%V\"", &s);
1219 return NGX_CONF_ERROR(void *) -1;
1220 }
1221
1222 continue;
1223 }
1224
1225 if (ngx_strncmp(value[i].data, "gzip", 4)strncmp((const char *) value[i].data, (const char *) "gzip", 4
)
== 0
1226 && (value[i].len == 4 || value[i].data[4] == '='))
1227 {
1228#if (NGX_ZLIB1)
1229 if (size == 0) {
1230 size = 64 * 1024;
1231 }
1232
1233 if (value[i].len == 4) {
1234 gzip = Z_BEST_SPEED1;
1235 continue;
1236 }
1237
1238 s.len = value[i].len - 5;
1239 s.data = value[i].data + 5;
1240
1241 gzip = ngx_atoi(s.data, s.len);
1242
1243 if (gzip < 1 || gzip > 9) {
1244 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1245 "invalid compression level \"%V\"", &s);
1246 return NGX_CONF_ERROR(void *) -1;
1247 }
1248
1249 continue;
1250
1251#else
1252 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1253 "nginx was built without zlib support");
1254 return NGX_CONF_ERROR(void *) -1;
1255#endif
1256 }
1257
1258 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1259 "invalid parameter \"%V\"", &value[i]);
1260 return NGX_CONF_ERROR(void *) -1;
1261 }
1262
1263 if (flush && size == 0) {
1264 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1265 "no buffer is defined for access_log \"%V\"",
1266 &value[1]);
1267 return NGX_CONF_ERROR(void *) -1;
1268 }
1269
1270 if (size) {
1271
1272 if (log->script) {
1273 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1274 "buffered logs cannot have variables in name");
1275 return NGX_CONF_ERROR(void *) -1;
1276 }
1277
1278 if (log->file->data) {
1279 buffer = log->file->data;
1280
1281 if (buffer->last - buffer->start != size
1282 || buffer->flush != flush
1283 || buffer->gzip != gzip)
1284 {
1285 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1286 "access_log \"%V\" already defined "
1287 "with conflicting parameters",
1288 &value[1]);
1289 return NGX_CONF_ERROR(void *) -1;
1290 }
1291
1292 return NGX_CONF_OK((void*)0);
1293 }
1294
1295 buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
1296 if (buffer == NULL((void*)0)) {
1297 return NGX_CONF_ERROR(void *) -1;
1298 }
1299
1300 buffer->start = ngx_pnalloc(cf->pool, size);
1301 if (buffer->start == NULL((void*)0)) {
1302 return NGX_CONF_ERROR(void *) -1;
1303 }
1304
1305 buffer->pos = buffer->start;
1306 buffer->last = buffer->start + size;
1307
1308 if (flush) {
1309 buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
1310 if (buffer->event == NULL((void*)0)) {
1311 return NGX_CONF_ERROR(void *) -1;
1312 }
1313
1314 buffer->event->data = log->file;
1315 buffer->event->handler = ngx_http_log_flush_handler;
1316 buffer->event->log = &cf->cycle->new_log;
1317
1318 buffer->flush = flush;
1319 }
1320
1321 buffer->gzip = gzip;
1322
1323 log->file->flush = ngx_http_log_flush;
1324 log->file->data = buffer;
1325 }
1326
1327 return NGX_CONF_OK((void*)0);
1328}
1329
1330
1331static char *
1332ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1333{
1334 ngx_http_log_main_conf_t *lmcf = conf;
1335
1336 ngx_str_t *value;
1337 ngx_uint_t i;
1338 ngx_http_log_fmt_t *fmt;
1339
1340 if (cf->cmd_type != NGX_HTTP_MAIN_CONF0x02000000) {
1341 ngx_conf_log_error(NGX_LOG_WARN5, cf, 0,
1342 "the \"log_format\" directive may be used "
1343 "only on \"http\" level");
1344 }
1345
1346 value = cf->args->elts;
1347
1348 fmt = lmcf->formats.elts;
1349 for (i = 0; i < lmcf->formats.nelts; i++) {
1350 if (fmt[i].name.len == value[1].len
1351 && ngx_strcmp(fmt[i].name.data, value[1].data)strcmp((const char *) fmt[i].name.data, (const char *) value[
1].data)
== 0)
1352 {
1353 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1354 "duplicate \"log_format\" name \"%V\"",
1355 &value[1]);
1356 return NGX_CONF_ERROR(void *) -1;
1357 }
1358 }
1359
1360 fmt = ngx_array_push(&lmcf->formats);
1361 if (fmt == NULL((void*)0)) {
1362 return NGX_CONF_ERROR(void *) -1;
1363 }
1364
1365 fmt->name = value[1];
1366
1367 fmt->flushes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
1368 if (fmt->flushes == NULL((void*)0)) {
1369 return NGX_CONF_ERROR(void *) -1;
1370 }
1371
1372 fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
1373 if (fmt->ops == NULL((void*)0)) {
1374 return NGX_CONF_ERROR(void *) -1;
1375 }
1376
1377 return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2);
1378}
1379
1380
1381static char *
1382ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
1383 ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
1384{
1385 u_char *data, *p, ch;
1386 size_t i, len;
1387 ngx_str_t *value, var;
1388 ngx_int_t *flush;
1389 ngx_uint_t bracket;
1390 ngx_http_log_op_t *op;
1391 ngx_http_log_var_t *v;
1392
1393 value = args->elts;
1394
1395 for ( /* void */ ; s < args->nelts; s++) {
1396
1397 i = 0;
1398
1399 while (i < value[s].len) {
1400
1401 op = ngx_array_push(ops);
1402 if (op == NULL((void*)0)) {
1403 return NGX_CONF_ERROR(void *) -1;
1404 }
1405
1406 data = &value[s].data[i];
1407
1408 if (value[s].data[i] == '$') {
1409
1410 if (++i == value[s].len) {
1411 goto invalid;
1412 }
1413
1414 if (value[s].data[i] == '{') {
1415 bracket = 1;
1416
1417 if (++i == value[s].len) {
1418 goto invalid;
1419 }
1420
1421 var.data = &value[s].data[i];
1422
1423 } else {
1424 bracket = 0;
1425 var.data = &value[s].data[i];
1426 }
1427
1428 for (var.len = 0; i < value[s].len; i++, var.len++) {
1429 ch = value[s].data[i];
1430
1431 if (ch == '}' && bracket) {
1432 i++;
1433 bracket = 0;
1434 break;
1435 }
1436
1437 if ((ch >= 'A' && ch <= 'Z')
1438 || (ch >= 'a' && ch <= 'z')
1439 || (ch >= '0' && ch <= '9')
1440 || ch == '_')
1441 {
1442 continue;
1443 }
1444
1445 break;
1446 }
1447
1448 if (bracket) {
1449 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1450 "the closing bracket in \"%V\" "
1451 "variable is missing", &var);
1452 return NGX_CONF_ERROR(void *) -1;
1453 }
1454
1455 if (var.len == 0) {
1456 goto invalid;
1457 }
1458
1459 for (v = ngx_http_log_vars; v->name.len; v++) {
1460
1461 if (v->name.len == var.len
1462 && ngx_strncmp(v->name.data, var.data, var.len)strncmp((const char *) v->name.data, (const char *) var.data
, var.len)
== 0)
1463 {
1464 op->len = v->len;
1465 op->getlen = NULL((void*)0);
1466 op->run = v->run;
1467 op->data = 0;
1468
1469 goto found;
1470 }
1471 }
1472
1473 if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK0) {
1474 return NGX_CONF_ERROR(void *) -1;
1475 }
1476
1477 if (flushes) {
1478
1479 flush = ngx_array_push(flushes);
1480 if (flush == NULL((void*)0)) {
1481 return NGX_CONF_ERROR(void *) -1;
1482 }
1483
1484 *flush = op->data; /* variable index */
1485 }
1486
1487 found:
1488
1489 continue;
1490 }
1491
1492 i++;
1493
1494 while (i < value[s].len && value[s].data[i] != '$') {
1495 i++;
1496 }
1497
1498 len = &value[s].data[i] - data;
1499
1500 if (len) {
1501
1502 op->len = len;
1503 op->getlen = NULL((void*)0);
1504
1505 if (len <= sizeof(uintptr_t)) {
1506 op->run = ngx_http_log_copy_short;
1507 op->data = 0;
1508
1509 while (len--) {
1510 op->data <<= 8;
1511 op->data |= data[len];
1512 }
1513
1514 } else {
1515 op->run = ngx_http_log_copy_long;
1516
1517 p = ngx_pnalloc(cf->pool, len);
1518 if (p == NULL((void*)0)) {
1519 return NGX_CONF_ERROR(void *) -1;
1520 }
1521
1522 ngx_memcpy(p, data, len)(void) ((__builtin_object_size (p, 0) != (size_t) -1) ? __builtin___memcpy_chk
(p, data, len, __builtin_object_size (p, 0)) : __inline_memcpy_chk
(p, data, len))
;
1523 op->data = (uintptr_t) p;
1524 }
1525 }
1526 }
1527 }
1528
1529 return NGX_CONF_OK((void*)0);
1530
1531invalid:
1532
1533 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0, "invalid parameter \"%s\"", data);
1534
1535 return NGX_CONF_ERROR(void *) -1;
1536}
1537
1538
1539static char *
1540ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1541{
1542 ngx_http_log_loc_conf_t *llcf = conf;
1543
1544 time_t inactive, valid;
1545 ngx_str_t *value, s;
1546 ngx_int_t max, min_uses;
1547 ngx_uint_t i;
1548
1549 if (llcf->open_file_cache != NGX_CONF_UNSET_PTR(void *) -1) {
1550 return "is duplicate";
1551 }
1552
1553 value = cf->args->elts;
1554
1555 max = 0;
1556 inactive = 10;
1557 valid = 60;
1558 min_uses = 1;
1559
1560 for (i = 1; i < cf->args->nelts; i++) {
1561
1562 if (ngx_strncmp(value[i].data, "max=", 4)strncmp((const char *) value[i].data, (const char *) "max=", 4
)
== 0) {
1563
1564 max = ngx_atoi(value[i].data + 4, value[i].len - 4);
1565 if (max == NGX_ERROR-1) {
1566 goto failed;
1567 }
1568
1569 continue;
1570 }
1571
1572 if (ngx_strncmp(value[i].data, "inactive=", 9)strncmp((const char *) value[i].data, (const char *) "inactive="
, 9)
== 0) {
1573
1574 s.len = value[i].len - 9;
1575 s.data = value[i].data + 9;
1576
1577 inactive = ngx_parse_time(&s, 1);
1578 if (inactive == (time_t) NGX_ERROR-1) {
1579 goto failed;
1580 }
1581
1582 continue;
1583 }
1584
1585 if (ngx_strncmp(value[i].data, "min_uses=", 9)strncmp((const char *) value[i].data, (const char *) "min_uses="
, 9)
== 0) {
1586
1587 min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9);
1588 if (min_uses == NGX_ERROR-1) {
1589 goto failed;
1590 }
1591
1592 continue;
1593 }
1594
1595 if (ngx_strncmp(value[i].data, "valid=", 6)strncmp((const char *) value[i].data, (const char *) "valid="
, 6)
== 0) {
1596
1597 s.len = value[i].len - 6;
1598 s.data = value[i].data + 6;
1599
1600 valid = ngx_parse_time(&s, 1);
1601 if (valid == (time_t) NGX_ERROR-1) {
1602 goto failed;
1603 }
1604
1605 continue;
1606 }
1607
1608 if (ngx_strcmp(value[i].data, "off")strcmp((const char *) value[i].data, (const char *) "off") == 0) {
1609
1610 llcf->open_file_cache = NULL((void*)0);
1611
1612 continue;
1613 }
1614
1615 failed:
1616
1617 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1618 "invalid \"open_log_file_cache\" parameter \"%V\"",
1619 &value[i]);
1620 return NGX_CONF_ERROR(void *) -1;
1621 }
1622
1623 if (llcf->open_file_cache == NULL((void*)0)) {
1624 return NGX_CONF_OK((void*)0);
1625 }
1626
1627 if (max == 0) {
1628 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
1629 "\"open_log_file_cache\" must have \"max\" parameter");
1630 return NGX_CONF_ERROR(void *) -1;
1631 }
1632
1633 llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
1634
1635 if (llcf->open_file_cache) {
1636
1637 llcf->open_file_cache_valid = valid;
1638 llcf->open_file_cache_min_uses = min_uses;
1639
1640 return NGX_CONF_OK((void*)0);
1641 }
1642
1643 return NGX_CONF_ERROR(void *) -1;
1644}
1645
1646
1647static ngx_int_t
1648ngx_http_log_init(ngx_conf_t *cf)
1649{
1650 ngx_str_t *value;
1651 ngx_array_t a;
1652 ngx_http_handler_pt *h;
1653 ngx_http_log_fmt_t *fmt;
1654 ngx_http_log_main_conf_t *lmcf;
1655 ngx_http_core_main_conf_t *cmcf;
1656
1657 lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_log_module
.ctx_index]
;
1658
1659 if (lmcf->combined_used) {
1660 if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK0) {
1661 return NGX_ERROR-1;
1662 }
1663
1664 value = ngx_array_push(&a);
1665 if (value == NULL((void*)0)) {
1666 return NGX_ERROR-1;
1667 }
1668
1669 *value = ngx_http_combined_fmt;
1670 fmt = lmcf->formats.elts;
1671
1672 if (ngx_http_log_compile_format(cf, NULL((void*)0), fmt->ops, &a, 0)
1673 != NGX_CONF_OK((void*)0))
1674 {
1675 return NGX_ERROR-1;
1676 }
1677 }
1678
1679 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_core_module
.ctx_index]
;
1680
1681 h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
1682 if (h == NULL((void*)0)) {
1683 return NGX_ERROR-1;
1684 }
1685
1686 *h = ngx_http_log_handler;
1687
1688 return NGX_OK0;
1689}