]>
Commit | Line | Data |
---|---|---|
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 | 39 | lxc_log_define(parse, lxc); |
cb698658 | 40 | |
9994d140 CB |
41 | void *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 | ||
63 | int lxc_strmunmap(void *addr, size_t length) | |
64 | { | |
65 | return munmap(addr, length + 1); | |
66 | } | |
67 | ||
872c1f04 | 68 | int 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 |
113 | on_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 | 125 | int 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 | } |