]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/initutils.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <sys/prctl.h>
31 #include "file_utils.h"
32 #include "initutils.h"
37 #include "include/strlcpy.h"
40 lxc_log_define(initutils
, lxc
);
42 static char *copy_global_config_value(char *p
)
50 if (p
[len
-1] == '\n') {
55 retbuf
= malloc(len
+ 1);
59 (void)strlcpy(retbuf
, p
, len
+ 1);
63 const char *lxc_global_config_value(const char *option_name
)
65 static const char * const options
[][2] = {
66 { "lxc.bdev.lvm.vg", DEFAULT_VG
},
67 { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL
},
68 { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT
},
69 { "lxc.bdev.rbd.rbdpool", DEFAULT_RBDPOOL
},
70 { "lxc.lxcpath", NULL
},
71 { "lxc.default_config", NULL
},
72 { "lxc.cgroup.pattern", NULL
},
73 { "lxc.cgroup.use", NULL
},
77 /* placed in the thread local storage pool for non-bionic targets */
79 static thread_local
const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
81 static const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
84 /* user_config_path is freed as soon as it is used */
85 char *user_config_path
= NULL
;
88 * The following variables are freed at bottom unconditionally.
89 * So NULL the value if it is to be returned to the caller
91 char *user_default_config_path
= NULL
;
92 char *user_lxc_path
= NULL
;
93 char *user_cgroup_pattern
= NULL
;
96 const char *user_home
= getenv("HOME");
100 user_config_path
= malloc(sizeof(char) * (22 + strlen(user_home
)));
101 user_default_config_path
= malloc(sizeof(char) * (26 + strlen(user_home
)));
102 user_lxc_path
= malloc(sizeof(char) * (19 + strlen(user_home
)));
104 sprintf(user_config_path
, "%s/.config/lxc/lxc.conf", user_home
);
105 sprintf(user_default_config_path
, "%s/.config/lxc/default.conf", user_home
);
106 sprintf(user_lxc_path
, "%s/.local/share/lxc/", user_home
);
107 user_cgroup_pattern
= strdup("lxc.payload/%n");
110 user_config_path
= strdup(LXC_GLOBAL_CONF
);
111 user_default_config_path
= strdup(LXC_DEFAULT_CONFIG
);
112 user_lxc_path
= strdup(LXCPATH
);
113 user_cgroup_pattern
= strdup(DEFAULT_CGROUP_PATTERN
);
116 const char * const (*ptr
)[2];
118 char buf
[1024], *p
, *p2
;
121 for (i
= 0, ptr
= options
; (*ptr
)[0]; ptr
++, i
++) {
122 if (!strcmp(option_name
, (*ptr
)[0]))
126 free(user_config_path
);
127 free(user_default_config_path
);
129 free(user_cgroup_pattern
);
135 free(user_config_path
);
136 free(user_default_config_path
);
138 free(user_cgroup_pattern
);
142 fin
= fopen_cloexec(user_config_path
, "r");
143 free(user_config_path
);
145 while (fgets(buf
, 1024, fin
)) {
148 p
= strstr(buf
, option_name
);
151 /* see if there was just white space in front
154 for (p2
= buf
; p2
< p
; p2
++) {
155 if (*p2
!= ' ' && *p2
!= '\t')
163 /* see if there was just white space after
166 for (p2
+= strlen(option_name
); p2
< p
; p2
++) {
167 if (*p2
!= ' ' && *p2
!= '\t')
173 while (*p
&& (*p
== ' ' || *p
== '\t')) p
++;
177 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
179 user_lxc_path
= copy_global_config_value(p
);
180 remove_trailing_slashes(user_lxc_path
);
181 values
[i
] = user_lxc_path
;
182 user_lxc_path
= NULL
;
186 values
[i
] = copy_global_config_value(p
);
190 /* could not find value, use default */
191 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
192 remove_trailing_slashes(user_lxc_path
);
193 values
[i
] = user_lxc_path
;
194 user_lxc_path
= NULL
;
196 else if (strcmp(option_name
, "lxc.default_config") == 0) {
197 values
[i
] = user_default_config_path
;
198 user_default_config_path
= NULL
;
200 else if (strcmp(option_name
, "lxc.cgroup.pattern") == 0) {
201 values
[i
] = user_cgroup_pattern
;
202 user_cgroup_pattern
= NULL
;
205 values
[i
] = (*ptr
)[1];
207 /* special case: if default value is NULL,
208 * and there is no config, don't view that
217 free(user_cgroup_pattern
);
218 free(user_default_config_path
);
225 * Sets the process title to the specified title. Note that this may fail if
226 * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
228 int setproctitle(char *title
)
230 static char *proctitle
= NULL
;
231 char buf
[2048], *tmp
;
235 /* We don't really need to know all of this stuff, but unfortunately
236 * PR_SET_MM_MAP requires us to set it all at once, so we have to
237 * figure it out anyway.
239 unsigned long start_data
, end_data
, start_brk
, start_code
, end_code
,
240 start_stack
, arg_start
, arg_end
, env_start
, env_end
,
242 struct prctl_mm_map prctl_map
;
244 f
= fopen_cloexec("/proc/self/stat", "r");
249 tmp
= fgets(buf
, sizeof(buf
), f
);
255 /* Skip the first 25 fields, column 26-28 are start_code, end_code,
257 tmp
= strchr(buf
, ' ');
258 for (i
= 0; i
< 24; i
++) {
261 tmp
= strchr(tmp
+1, ' ');
266 i
= sscanf(tmp
, "%lu %lu %lu", &start_code
, &end_code
, &start_stack
);
270 /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
271 for (i
= 0; i
< 19; i
++) {
274 tmp
= strchr(tmp
+1, ' ');
280 i
= sscanf(tmp
, "%lu %lu %lu %*u %*u %lu %lu",
289 /* Include the null byte here, because in the calculations below we
290 * want to have room for it. */
291 len
= strlen(title
) + 1;
293 proctitle
= realloc(proctitle
, len
);
297 arg_start
= (unsigned long) proctitle
;
298 arg_end
= arg_start
+ len
;
300 brk_val
= syscall(__NR_brk
, 0);
302 prctl_map
= (struct prctl_mm_map
) {
303 .start_code
= start_code
,
304 .end_code
= end_code
,
305 .start_stack
= start_stack
,
306 .start_data
= start_data
,
307 .end_data
= end_data
,
308 .start_brk
= start_brk
,
310 .arg_start
= arg_start
,
312 .env_start
= env_start
,
319 ret
= prctl(PR_SET_MM
, prctl_arg(PR_SET_MM_MAP
), prctl_arg(&prctl_map
),
320 prctl_arg(sizeof(prctl_map
)), prctl_arg(0));
322 (void)strlcpy((char*)arg_start
, title
, len
);
324 SYSWARN("Failed to set cmdline");