Coverage Report

Created: 2025-07-11 06:49

/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
196
AvahiIniFile* avahi_ini_file_load(const char *fname) {
35
196
    AvahiIniFile *f;
36
196
    FILE *fo;
37
196
    AvahiIniFileGroup *group = NULL;
38
196
    unsigned line;
39
40
196
    assert(fname);
41
42
196
    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
196
    f = avahi_new(AvahiIniFile, 1);
48
196
    AVAHI_LLIST_HEAD_INIT(AvahiIniFileGroup, f->groups);
49
196
    f->n_groups = 0;
50
51
196
    line = 0;
52
2.90k
    while (!feof(fo)) {
53
2.75k
        char ln[1024], *s, *e;
54
2.75k
        AvahiIniFilePair *pair;
55
56
2.75k
        if (!(fgets(ln, sizeof(ln), fo)))
57
10
            break;
58
59
2.74k
        line++;
60
61
2.74k
        s = ln + strspn(ln, " \t");
62
2.74k
        s[strcspn(s, "\r\n")] = 0;
63
64
        /* Skip comments and empty lines */
65
2.74k
        if (*s == '#' || *s == '%' || *s == 0)
66
711
            continue;
67
68
2.02k
        if (*s == '[') {
69
            /* new group */
70
71
706
            if (!(e = strchr(s, ']'))) {
72
2
                avahi_log_error("Unclosed group header in %s:%u: <%s>", fname, line, s);
73
2
                goto fail;
74
2
            }
75
76
704
            *e = 0;
77
78
704
            group = avahi_new(AvahiIniFileGroup, 1);
79
704
            group->name = avahi_strdup(s+1);
80
704
            group->n_pairs = 0;
81
704
            AVAHI_LLIST_HEAD_INIT(AvahiIniFilePair, group->pairs);
82
83
704
            AVAHI_LLIST_PREPEND(AvahiIniFileGroup, groups, f->groups, group);
84
704
            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.29k
            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.29k
            *(e++) = 0;
100
101
1.29k
            pair = avahi_new(AvahiIniFilePair, 1);
102
1.29k
            pair->key = avahi_strdup(s);
103
1.29k
            pair->value = avahi_strdup(e);
104
105
1.29k
            AVAHI_LLIST_PREPEND(AvahiIniFilePair, pairs, group->pairs, pair);
106
1.29k
            group->n_pairs++;
107
1.29k
        }
108
2.02k
    }
109
110
169
    fclose(fo);
111
112
169
    return f;
113
114
27
fail:
115
116
27
    if (fo)
117
27
        fclose(fo);
118
119
27
    if (f)
120
27
        avahi_ini_file_free(f);
121
122
27
    return NULL;
123
196
}
124
125
196
void avahi_ini_file_free(AvahiIniFile *f) {
126
196
    AvahiIniFileGroup *g;
127
196
    assert(f);
128
129
900
    while ((g = f->groups)) {
130
704
        AvahiIniFilePair *p;
131
132
2.00k
        while ((p = g->pairs)) {
133
1.29k
            avahi_free(p->key);
134
1.29k
            avahi_free(p->value);
135
136
1.29k
            AVAHI_LLIST_REMOVE(AvahiIniFilePair, pairs, g->pairs, p);
137
1.29k
            avahi_free(p);
138
1.29k
        }
139
140
704
        avahi_free(g->name);
141
142
704
        AVAHI_LLIST_REMOVE(AvahiIniFileGroup, groups, f->groups, g);
143
704
        avahi_free(g);
144
704
    }
145
146
196
    avahi_free(f);
147
196
}
148
149
1.29k
char** avahi_split_csv(const char *t) {
150
1.29k
    unsigned n_comma = 0;
151
1.29k
    const char *p;
152
1.29k
    char **r, **i;
153
154
9.84k
    for (p = t; *p; p++)
155
8.54k
        if (*p == ',')
156
3.06k
            n_comma++;
157
158
1.29k
    i = r = avahi_new(char*, n_comma+2);
159
160
4.36k
    for (;;) {
161
4.36k
        size_t n, l = strcspn(t, ",");
162
4.36k
        const char *c;
163
164
        /* Ignore leading blanks */
165
4.36k
        for (c = t, n = l; isblank(*c); c++, n--);
166
167
        /* Ignore trailing blanks */
168
4.62k
        for (; n > 0 && isblank(c[n-1]); n--);
169
170
4.36k
        *(i++) = avahi_strndup(c, n);
171
172
4.36k
        t += l;
173
174
4.36k
        if (*t == 0)
175
1.29k
            break;
176
177
3.06k
        assert(*t == ',');
178
3.06k
        t++;
179
3.06k
    }
180
181
1.29k
    *i = NULL;
182
183
1.29k
    return r;
184
1.29k
}
185
186
1.29k
void avahi_strfreev(char **p) {
187
1.29k
    char **i;
188
189
1.29k
    if (!p)
190
0
        return;
191
192
5.66k
    for (i = p; *i; i++)
193
4.36k
        avahi_free(*i);
194
195
1.29k
    avahi_free(p);
196
1.29k
}