]>
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"
35 #include "memory_utils.h"
38 #include "include/strlcpy.h"
41 lxc_log_define(initutils
, lxc
);
43 static char *copy_global_config_value(char *p
)
51 if (p
[len
-1] == '\n') {
56 retbuf
= malloc(len
+ 1);
60 (void)strlcpy(retbuf
, p
, len
+ 1);
64 const char *lxc_global_config_value(const char *option_name
)
66 static const char * const options
[][2] = {
67 { "lxc.bdev.lvm.vg", DEFAULT_VG
},
68 { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL
},
69 { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT
},
70 { "lxc.bdev.rbd.rbdpool", DEFAULT_RBDPOOL
},
71 { "lxc.lxcpath", NULL
},
72 { "lxc.default_config", NULL
},
73 { "lxc.cgroup.pattern", NULL
},
74 { "lxc.cgroup.use", NULL
},
78 /* placed in the thread local storage pool for non-bionic targets */
80 static thread_local
const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
82 static const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
85 /* user_config_path is freed as soon as it is used */
86 char *user_config_path
= NULL
;
89 * The following variables are freed at bottom unconditionally.
90 * So NULL the value if it is to be returned to the caller
92 char *user_default_config_path
= NULL
;
93 char *user_lxc_path
= NULL
;
94 char *user_cgroup_pattern
= NULL
;
97 const char *user_home
= getenv("HOME");
101 user_config_path
= malloc(sizeof(char) * (22 + strlen(user_home
)));
102 user_default_config_path
= malloc(sizeof(char) * (26 + strlen(user_home
)));
103 user_lxc_path
= malloc(sizeof(char) * (19 + strlen(user_home
)));
105 sprintf(user_config_path
, "%s/.config/lxc/lxc.conf", user_home
);
106 sprintf(user_default_config_path
, "%s/.config/lxc/default.conf", user_home
);
107 sprintf(user_lxc_path
, "%s/.local/share/lxc/", user_home
);
108 user_cgroup_pattern
= strdup("lxc.payload/%n");
111 user_config_path
= strdup(LXC_GLOBAL_CONF
);
112 user_default_config_path
= strdup(LXC_DEFAULT_CONFIG
);
113 user_lxc_path
= strdup(LXCPATH
);
114 user_cgroup_pattern
= strdup(DEFAULT_CGROUP_PATTERN
);
117 const char * const (*ptr
)[2];
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 __do_free
char *line
= NULL
;
147 char *slider1
, *slider2
;
149 while (getline(&line
, &len
, fin
) > 0) {
153 slider1
= strstr(line
, option_name
);
157 /* see if there was just white space in front
160 for (slider2
= line
; slider2
< slider1
; slider2
++)
161 if (*slider2
!= ' ' && *slider2
!= '\t')
164 if (slider2
< slider1
)
167 slider1
= strchr(slider1
, '=');
171 /* see if there was just white space after
174 for (slider2
+= strlen(option_name
); slider2
< slider1
;
176 if (*slider2
!= ' ' && *slider2
!= '\t')
179 if (slider2
< slider1
)
183 while (*slider1
&& (*slider1
== ' ' || *slider1
== '\t'))
189 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
191 user_lxc_path
= copy_global_config_value(slider1
);
192 remove_trailing_slashes(user_lxc_path
);
193 values
[i
] = user_lxc_path
;
194 user_lxc_path
= NULL
;
198 values
[i
] = copy_global_config_value(slider1
);
203 /* could not find value, use default */
204 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
205 remove_trailing_slashes(user_lxc_path
);
206 values
[i
] = user_lxc_path
;
207 user_lxc_path
= NULL
;
209 else if (strcmp(option_name
, "lxc.default_config") == 0) {
210 values
[i
] = user_default_config_path
;
211 user_default_config_path
= NULL
;
213 else if (strcmp(option_name
, "lxc.cgroup.pattern") == 0) {
214 values
[i
] = user_cgroup_pattern
;
215 user_cgroup_pattern
= NULL
;
218 values
[i
] = (*ptr
)[1];
220 /* special case: if default value is NULL,
221 * and there is no config, don't view that
230 free(user_cgroup_pattern
);
231 free(user_default_config_path
);
238 * Sets the process title to the specified title. Note that this may fail if
239 * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
241 int setproctitle(char *title
)
243 __do_fclose
FILE *f
= NULL
;
245 char *buf_ptr
, *tmp_proctitle
;
246 char buf
[LXC_LINELEN
];
248 ssize_t bytes_read
= 0;
249 static char *proctitle
= NULL
;
252 * We don't really need to know all of this stuff, but unfortunately
253 * PR_SET_MM_MAP requires us to set it all at once, so we have to
254 * figure it out anyway.
256 unsigned long start_data
, end_data
, start_brk
, start_code
, end_code
,
257 start_stack
, arg_start
, arg_end
, env_start
, env_end
, brk_val
;
258 struct prctl_mm_map prctl_map
;
260 f
= fopen_cloexec("/proc/self/stat", "r");
268 bytes_read
= lxc_read_nointr(fd
, buf
, sizeof(buf
) - 1);
272 buf
[bytes_read
] = '\0';
274 /* Skip the first 25 fields, column 26-28 are start_code, end_code,
276 buf_ptr
= strchr(buf
, ' ');
277 for (i
= 0; i
< 24; i
++) {
280 buf_ptr
= strchr(buf_ptr
+ 1, ' ');
285 i
= sscanf(buf_ptr
, "%lu %lu %lu", &start_code
, &end_code
, &start_stack
);
289 /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
290 for (i
= 0; i
< 19; i
++) {
293 buf_ptr
= strchr(buf_ptr
+ 1, ' ');
299 i
= sscanf(buf_ptr
, "%lu %lu %lu %*u %*u %lu %lu", &start_data
,
300 &end_data
, &start_brk
, &env_start
, &env_end
);
304 /* Include the null byte here, because in the calculations below we
305 * want to have room for it. */
306 len
= strlen(title
) + 1;
308 tmp_proctitle
= realloc(proctitle
, len
);
312 proctitle
= tmp_proctitle
;
314 arg_start
= (unsigned long)proctitle
;
315 arg_end
= arg_start
+ len
;
317 brk_val
= syscall(__NR_brk
, 0);
319 prctl_map
= (struct prctl_mm_map
){
320 .start_code
= start_code
,
321 .end_code
= end_code
,
322 .start_stack
= start_stack
,
323 .start_data
= start_data
,
324 .end_data
= end_data
,
325 .start_brk
= start_brk
,
327 .arg_start
= arg_start
,
329 .env_start
= env_start
,
336 ret
= prctl(PR_SET_MM
, prctl_arg(PR_SET_MM_MAP
), prctl_arg(&prctl_map
),
337 prctl_arg(sizeof(prctl_map
)), prctl_arg(0));
339 (void)strlcpy((char *)arg_start
, title
, len
);
341 SYSWARN("Failed to set cmdline");