Coverage Report

Created: 2025-07-18 06:08

/src/avahi/avahi-daemon/ini-file-parser.c
Line
Count
Source (jump to first uncovered line)
1
/***
2
  This file is part of avahi.
3
4
  avahi is free software; you can redistribute it and/or modify it
5
  under the terms of the GNU Lesser General Public License as
6
  published by the Free Software Foundation; either version 2.1 of the
7
  License, or (at your option) any later version.
8
9
  avahi is distributed in the hope that it will be useful, but WITHOUT
10
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12
  Public License for more details.
13
14
  You should have received a copy of the GNU Lesser General Public
15
  License along with avahi; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17
  USA.
18
***/
19
20
#ifdef HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include <stdio.h>
25
#include <string.h>
26
#include <errno.h>
27
#include <ctype.h>
28
29
#include <avahi-common/malloc.h>
30
#include <avahi-core/log.h>
31
32
#include "ini-file-parser.h"
33
34
202
AvahiIniFile* avahi_ini_file_load(const char *fname) {
35
202
    AvahiIniFile *f;
36
202
    FILE *fo;
37
202
    AvahiIniFileGroup *group = NULL;
38
202
    unsigned line;
39
40
202
    assert(fname);
41
42
202
    if (!(fo = fopen(fname, "r"))) {
43
0
        avahi_log_error("Failed to open file '%s': %s", fname, strerror(errno));
44
0
        return NULL;
45
0
    }
46
47
202
    f = avahi_new(AvahiIniFile, 1);
48
202
    AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups);
49
202
    f->n_groups = 0;
50
51
202
    line = 0;
52
2.95k
    while (!feof(fo)) {
53
2.78k
        char ln[1024], *s, *e;
54
2.78k
        AvahiIniFilePair *pair;
55
56
2.78k
        if (!(fgets(ln, sizeof(ln), fo)))
57
10
            break;
58
59
2.77k
        line++;
60
61
2.77k
        s = ln + strspn(ln, " \t");
62
2.77k
        s[strcspn(s, "\r\n")] = 0;
63
64
        /* Skip comments and empty lines */
65
2.77k
        if (*s == '#' || *s == '%' || *s == 0)
66
740
            continue;
67
68
2.03k
        if (*s == '[') {
69
            /* new group */
70
71
708
            if (!(e = strchr(s, ']'))) {
72
1
                avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s);
73
1
                goto fail;
74
1
            }
75
76
707
            *e = 0;
77
78
707
            group = avahi_new(AvahiIniFileGroup, 1);
79
707
            group->name = avahi_strdup(s+1);
80
707
            group->n_pairs = 0;
81
707
            AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs);
82
83
707
            AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group);
84
707
            f->n_groups++;
85
1.32k
        } else {
86
87
            /* Normal assignment */
88
1.32k
            if (!(e = strchr(s, '='))) {
89
24
                avahi_log_error("Missing assignment in %s:%u: <%s>", fname, line, s);
90
24
                goto fail;
91
24
            }
92
93
1.30k
            if (!group) {
94
1
                avahi_log_error("Assignment outside group in %s:%u <%s>", fname, line, s);
95
1
                goto fail;
96
1
            }
97
98
            /* Split the key and the value */
99
1.30k
            *(e++) = 0;
100
101
1.30k
            pair = avahi_new(AvahiIniFilePair, 1);
102
1.30k
            pair->key = avahi_strdup(s);
103
1.30k
            pair->value = avahi_strdup(e);
104
105
1.30k
            AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair);
106
1.30k
            group->n_pairs++;
107
1.30k
        }
108
2.03k
    }
109
110
176
    fclose(fo);
111
112
176
    return f;
113
114
26
fail:
115
116
26
    if (fo)
117
26
        fclose(fo);
118
119
26
    if (f)
120
26
        avahi_ini_file_free(f);
121
122
26
    return NULL;
123
202
}
124
125
202
void avahi_ini_file_free(AvahiIniFile *f) {
126
202
    AvahiIniFileGroup *g;
127
202
    assert(f);
128
129
909
    while ((g = f->groups)) {
130
707
        AvahiIniFilePair *p;
131
132
2.00k
        while ((p = g->pairs)) {
133
1.30k
            avahi_free(p->key);
134
1.30k
            avahi_free(p->value);
135
136
1.30k
            AVAHI_LLIST_REMOVE(AvahiIniFilePair, pairs, g->pairs, p);
137
1.30k
            avahi_free(p);
138
1.30k
        }
139
140
707
        avahi_free(g->name);
141
142
707
        AVAHI_LLIST_REMOVE(AvahiIniFileGroup, groups, f->groups, g);
143
707
        avahi_free(g);
144
707
    }
145
146
202
    avahi_free(f);
147
202
}
148
149
1.30k
char** avahi_split_csv(const char *t) {
150
1.30k
    unsigned n_comma = 0;
151
1.30k
    const char *p;
152
1.30k
    char **r, **i;
153
154
9.94k
    for (p = t; *p; p++)
155
8.64k
        if (*p == ',')
156
3.59k
            n_comma++;
157
158
1.30k
    i = r = avahi_new(char*, n_comma+2);
159
160
4.89k
    for (;;) {
161
4.89k
        size_t n, l = strcspn(t, ",");
162
4.89k
        const char *c;
163
164
        /* Ignore leading blanks */
165
4.89k
        for (c = t, n = l; isblank(*c); c++, n--);
166
167
        /* Ignore trailing blanks */
168
5.33k
        for (; n > 0 && isblank(c[n-1]); n--);
169
170
4.89k
        *(i++) = avahi_strndup(c, n);
171
172
4.89k
        t += l;
173
174
4.89k
        if (*t == 0)
175
1.30k
            break;
176
177
3.59k
        assert(*t == ',');
178
3.59k
        t++;
179
3.59k
    }
180
181
1.30k
    *i = NULL;
182
183
1.30k
    return r;
184
1.30k
}
185
186
1.30k
void avahi_strfreev(char **p) {
187
1.30k
    char **i;
188
189
1.30k
    if (!p)
190
0
        return;
191
192
6.19k
    for (i = p; *i; i++)
193
4.89k
        avahi_free(*i);
194
195
1.30k
    avahi_free(p);
196
1.30k
}