]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/parse.c
parse: report errors when failing config parsing
[mirror_lxc.git] / src / lxc / parse.c
CommitLineData
cb698658 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
cb698658 8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
cb698658 22 */
9994d140 23
d38dd64a
CB
24#ifndef _GNU_SOURCE
25#define _GNU_SOURCE 1
26#endif
cb698658 27#include <dirent.h>
9994d140 28#include <errno.h>
d38dd64a 29#include <stdio.h>
9994d140
CB
30#include <stdlib.h>
31#include <string.h>
32#include <sys/mman.h>
cb698658 33
d38dd64a
CB
34#include "config.h"
35#include "log.h"
cb698658 36#include "parse.h"
6a44839f 37#include "utils.h"
36eb9bde 38
ac2cecc4 39lxc_log_define(parse, lxc);
cb698658 40
9994d140
CB
41void *lxc_strmmap(void *addr, size_t length, int prot, int flags, int fd,
42 off_t offset)
43{
44 void *tmp = NULL, *overlap = NULL;
45
46 /* We establish an anonymous mapping that is one byte larger than the
47 * underlying file. The pages handed to us are zero filled. */
48 tmp = mmap(addr, length + 1, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
49 if (tmp == MAP_FAILED)
50 return tmp;
51
52 /* Now we establish a fixed-address mapping starting at the address we
53 * received from our anonymous mapping and replace all bytes excluding
54 * the additional \0-byte with the file. This allows us to use normal
55 * string-handling functions. */
56 overlap = mmap(tmp, length, prot, MAP_FIXED | flags, fd, offset);
57 if (overlap == MAP_FAILED)
58 munmap(tmp, length + 1);
59
60 return overlap;
61}
62
63int lxc_strmunmap(void *addr, size_t length)
64{
65 return munmap(addr, length + 1);
66}
67
872c1f04 68int lxc_file_for_each_line_mmap(const char *file, lxc_file_cb callback, void *data)
9994d140 69{
872c1f04 70 int fd, saved_errno;
834027f1 71 char *buf, *line;
9994d140 72 struct stat st;
44dec7ef 73 int ret = 0;
9994d140
CB
74
75 fd = open(file, O_RDONLY | O_CLOEXEC);
872c1f04
CB
76 if (fd < 0) {
77 SYSERROR("Failed to open config file \"%s\"", file);
9994d140 78 return -1;
872c1f04 79 }
9994d140
CB
80
81 ret = fstat(fd, &st);
82 if (ret < 0) {
872c1f04
CB
83 SYSERROR("Failed to stat config file \"%s\"", file);
84 goto on_error;
9994d140
CB
85 }
86
872c1f04
CB
87 ret = 0;
88 if (st.st_size == 0)
89 goto on_error;
9994d140 90
872c1f04 91 ret = -1;
2291ea4a
CB
92 buf = lxc_strmmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
93 MAP_PRIVATE | MAP_POPULATE, fd, 0);
9994d140 94 if (buf == MAP_FAILED) {
872c1f04
CB
95 SYSERROR("Failed to map config file \"%s\"", file);
96 goto on_error;
9994d140
CB
97 }
98
834027f1 99 lxc_iterate_parts(line, buf, "\n\0") {
9994d140
CB
100 ret = callback(line, data);
101 if (ret) {
102 /* Callback rv > 0 means stop here callback rv < 0 means
103 * error.
104 */
105 if (ret < 0)
872c1f04
CB
106 ERROR("Failed to parse config file \"%s\" at "
107 "line \"%s\"",
108 file, line);
9994d140
CB
109 break;
110 }
111 }
112
872c1f04
CB
113on_error:
114 ret = lxc_strmunmap(buf, st.st_size);
115 if (ret < 0)
116 SYSERROR("Failed to unmap config file \"%s\"", file);
117
118 saved_errno = errno;
9994d140 119 close(fd);
872c1f04
CB
120 errno = saved_errno;
121
44dec7ef 122 return ret;
9994d140
CB
123}
124
2382ecff 125int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
cb698658 126{
127 FILE *f;
4fcc0112 128 int err = 0;
2382ecff
CC
129 char *line = NULL;
130 size_t len = 0;
cb698658 131
132 f = fopen(file, "r");
133 if (!f) {
36eb9bde 134 SYSERROR("failed to open %s", file);
cb698658 135 return -1;
136 }
137
2382ecff
CC
138 while (getline(&line, &len, f) != -1) {
139 err = callback(line, data);
48e2f384 140 if (err) {
1a0e70ac
CB
141 /* Callback rv > 0 means stop here callback rv < 0 means
142 * error.
143 */
8daccdb4
SH
144 if (err < 0)
145 ERROR("Failed to parse config: %s", line);
2382ecff 146 break;
48e2f384 147 }
cb698658 148 }
2382ecff 149
f10fad2f 150 free(line);
cb698658 151 fclose(f);
152 return err;
153}