Coverage Report

Created: 2026-04-12 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2o/lib/handler/configurator/access_log.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2014 DeNA Co., Ltd.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include "h2o.h"
23
#include "h2o/configurator.h"
24
25
typedef H2O_VECTOR(h2o_access_log_filehandle_t *) st_h2o_access_log_filehandle_vector_t;
26
27
struct st_h2o_access_log_configurator_t {
28
    h2o_configurator_t super;
29
    st_h2o_access_log_filehandle_vector_t *handles;
30
    st_h2o_access_log_filehandle_vector_t _handles_stack[H2O_CONFIGURATOR_NUM_LEVELS + 1];
31
};
32
33
static int on_config(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
34
0
{
35
0
    struct st_h2o_access_log_configurator_t *self = (void *)cmd->configurator;
36
0
    yoml_t **path, **format = NULL, **escape_node = NULL;
37
0
    int escape = H2O_LOGCONF_ESCAPE_APACHE;
38
0
    h2o_access_log_filehandle_t *fh;
39
40
0
    switch (node->type) {
41
0
    case YOML_TYPE_SCALAR:
42
0
        path = &node;
43
0
        break;
44
0
    case YOML_TYPE_MAPPING:
45
0
        if (h2o_configurator_parse_mapping(cmd, node, "path:s", "format:s,escape:*", &path, &format, &escape_node) != 0)
46
0
            return -1;
47
0
        break;
48
0
    default:
49
0
        h2o_configurator_errprintf(cmd, node, "node must be a scalar or a mapping");
50
0
        return -1;
51
0
    }
52
53
0
    if (escape_node != NULL) {
54
0
        switch (h2o_configurator_get_one_of(cmd, *escape_node, "apache,json")) {
55
0
        case 0:
56
0
            escape = H2O_LOGCONF_ESCAPE_APACHE;
57
0
            break;
58
0
        case 1:
59
0
            escape = H2O_LOGCONF_ESCAPE_JSON;
60
0
            break;
61
0
        default:
62
0
            return -1;
63
0
        }
64
0
    }
65
66
0
    if (!ctx->dry_run) {
67
0
        if ((fh = h2o_access_log_open_handle((*path)->data.scalar, format != NULL ? (*format)->data.scalar : NULL, escape)) == NULL)
68
0
            return -1;
69
0
        h2o_vector_reserve(NULL, self->handles, self->handles->size + 1);
70
0
        self->handles->entries[self->handles->size++] = fh;
71
0
    }
72
73
0
    return 0;
74
0
}
75
76
static int on_config_enter(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
77
0
{
78
0
    struct st_h2o_access_log_configurator_t *self = (void *)_self;
79
0
    size_t i;
80
81
    /* push the stack pointer */
82
0
    ++self->handles;
83
84
    /* link the handles */
85
0
    memset(self->handles, 0, sizeof(*self->handles));
86
0
    h2o_vector_reserve(NULL, self->handles, self->handles[-1].size + 1);
87
0
    for (i = 0; i != self->handles[-1].size; ++i) {
88
0
        h2o_access_log_filehandle_t *fh = self->handles[-1].entries[i];
89
0
        self->handles[0].entries[self->handles[0].size++] = fh;
90
0
        h2o_mem_addref_shared(fh);
91
0
    }
92
93
0
    return 0;
94
0
}
95
96
static int on_config_exit(h2o_configurator_t *_self, h2o_configurator_context_t *ctx, yoml_t *node)
97
0
{
98
0
    struct st_h2o_access_log_configurator_t *self = (void *)_self;
99
0
    size_t i;
100
101
    /* register all handles, and decref them */
102
0
    for (i = 0; i != self->handles->size; ++i) {
103
0
        h2o_access_log_filehandle_t *fh = self->handles->entries[i];
104
0
        if (ctx->pathconf != NULL && !h2o_configurator_at_extension_level(ctx))
105
0
            h2o_access_log_register(ctx->pathconf, fh);
106
0
        h2o_mem_release_shared(fh);
107
0
    }
108
    /* free the vector */
109
0
    free(self->handles->entries);
110
111
    /* pop the stack pointer */
112
0
    --self->handles;
113
114
0
    return 0;
115
0
}
116
117
void h2o_access_log_register_configurator(h2o_globalconf_t *conf)
118
0
{
119
0
    struct st_h2o_access_log_configurator_t *self = (void *)h2o_configurator_create(conf, sizeof(*self));
120
121
0
    self->super.enter = on_config_enter;
122
0
    self->super.exit = on_config_exit;
123
0
    self->handles = self->_handles_stack;
124
125
0
    h2o_configurator_define_command(&self->super, "access-log",
126
0
                                    H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_HOST | H2O_CONFIGURATOR_FLAG_PATH,
127
0
                                    on_config);
128
0
}