]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/initutils.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "file_utils.h"
11 #include "initutils.h"
14 #include "memory_utils.h"
17 #include "include/strlcpy.h"
20 lxc_log_define(initutils
, lxc
);
22 static char *copy_global_config_value(char *p
)
30 if (p
[len
-1] == '\n') {
35 retbuf
= malloc(len
+ 1);
39 (void)strlcpy(retbuf
, p
, len
+ 1);
43 const char *lxc_global_config_value(const char *option_name
)
45 static const char * const options
[][2] = {
46 { "lxc.bdev.lvm.vg", DEFAULT_VG
},
47 { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL
},
48 { "lxc.bdev.zfs.root", DEFAULT_ZFSROOT
},
49 { "lxc.bdev.rbd.rbdpool", DEFAULT_RBDPOOL
},
50 { "lxc.lxcpath", NULL
},
51 { "lxc.default_config", NULL
},
52 { "lxc.cgroup.pattern", NULL
},
53 { "lxc.cgroup.use", NULL
},
57 /* placed in the thread local storage pool for non-bionic targets */
59 static thread_local
const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
61 static const char *values
[sizeof(options
) / sizeof(options
[0])] = {0};
64 /* user_config_path is freed as soon as it is used */
65 char *user_config_path
= NULL
;
68 * The following variables are freed at bottom unconditionally.
69 * So NULL the value if it is to be returned to the caller
71 char *user_default_config_path
= NULL
;
72 char *user_lxc_path
= NULL
;
73 char *user_cgroup_pattern
= NULL
;
76 const char *user_home
= getenv("HOME");
80 user_config_path
= malloc(sizeof(char) * (22 + strlen(user_home
)));
81 user_default_config_path
= malloc(sizeof(char) * (26 + strlen(user_home
)));
82 user_lxc_path
= malloc(sizeof(char) * (19 + strlen(user_home
)));
84 sprintf(user_config_path
, "%s/.config/lxc/lxc.conf", user_home
);
85 sprintf(user_default_config_path
, "%s/.config/lxc/default.conf", user_home
);
86 sprintf(user_lxc_path
, "%s/.local/share/lxc/", user_home
);
87 user_cgroup_pattern
= strdup("%n");
90 user_config_path
= strdup(LXC_GLOBAL_CONF
);
91 user_default_config_path
= strdup(LXC_DEFAULT_CONFIG
);
92 user_lxc_path
= strdup(LXCPATH
);
93 user_cgroup_pattern
= strdup(DEFAULT_CGROUP_PATTERN
);
96 const char * const (*ptr
)[2];
100 for (i
= 0, ptr
= options
; (*ptr
)[0]; ptr
++, i
++) {
101 if (!strcmp(option_name
, (*ptr
)[0]))
105 free(user_config_path
);
106 free(user_default_config_path
);
108 free(user_cgroup_pattern
);
114 free(user_config_path
);
115 free(user_default_config_path
);
117 free(user_cgroup_pattern
);
121 fin
= fopen_cloexec(user_config_path
, "r");
122 free(user_config_path
);
124 __do_free
char *line
= NULL
;
126 char *slider1
, *slider2
;
128 while (getline(&line
, &len
, fin
) > 0) {
132 slider1
= strstr(line
, option_name
);
136 /* see if there was just white space in front
139 for (slider2
= line
; slider2
< slider1
; slider2
++)
140 if (*slider2
!= ' ' && *slider2
!= '\t')
143 if (slider2
< slider1
)
146 slider1
= strchr(slider1
, '=');
150 /* see if there was just white space after
153 for (slider2
+= strlen(option_name
); slider2
< slider1
;
155 if (*slider2
!= ' ' && *slider2
!= '\t')
158 if (slider2
< slider1
)
162 while (*slider1
&& (*slider1
== ' ' || *slider1
== '\t'))
168 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
170 user_lxc_path
= copy_global_config_value(slider1
);
171 remove_trailing_slashes(user_lxc_path
);
172 values
[i
] = user_lxc_path
;
173 user_lxc_path
= NULL
;
177 values
[i
] = copy_global_config_value(slider1
);
182 /* could not find value, use default */
183 if (strcmp(option_name
, "lxc.lxcpath") == 0) {
184 remove_trailing_slashes(user_lxc_path
);
185 values
[i
] = user_lxc_path
;
186 user_lxc_path
= NULL
;
188 else if (strcmp(option_name
, "lxc.default_config") == 0) {
189 values
[i
] = user_default_config_path
;
190 user_default_config_path
= NULL
;
192 else if (strcmp(option_name
, "lxc.cgroup.pattern") == 0) {
193 values
[i
] = user_cgroup_pattern
;
194 user_cgroup_pattern
= NULL
;
197 values
[i
] = (*ptr
)[1];
199 /* special case: if default value is NULL,
200 * and there is no config, don't view that
209 free(user_cgroup_pattern
);
210 free(user_default_config_path
);
217 * Sets the process title to the specified title. Note that this may fail if
218 * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
220 int setproctitle(char *title
)
222 __do_fclose
FILE *f
= NULL
;
224 char *buf_ptr
, *tmp_proctitle
;
225 char buf
[LXC_LINELEN
];
227 ssize_t bytes_read
= 0;
228 static char *proctitle
= NULL
;
231 * We don't really need to know all of this stuff, but unfortunately
232 * PR_SET_MM_MAP requires us to set it all at once, so we have to
233 * figure it out anyway.
235 unsigned long start_data
, end_data
, start_brk
, start_code
, end_code
,
236 start_stack
, arg_start
, arg_end
, env_start
, env_end
, brk_val
;
237 struct prctl_mm_map prctl_map
;
239 f
= fopen_cloexec("/proc/self/stat", "r");
247 bytes_read
= lxc_read_nointr(fd
, buf
, sizeof(buf
) - 1);
251 buf
[bytes_read
] = '\0';
253 /* Skip the first 25 fields, column 26-28 are start_code, end_code,
255 buf_ptr
= strchr(buf
, ' ');
256 for (i
= 0; i
< 24; i
++) {
259 buf_ptr
= strchr(buf_ptr
+ 1, ' ');
264 i
= sscanf(buf_ptr
, "%lu %lu %lu", &start_code
, &end_code
, &start_stack
);
268 /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
269 for (i
= 0; i
< 19; i
++) {
272 buf_ptr
= strchr(buf_ptr
+ 1, ' ');
278 i
= sscanf(buf_ptr
, "%lu %lu %lu %*u %*u %lu %lu", &start_data
,
279 &end_data
, &start_brk
, &env_start
, &env_end
);
283 /* Include the null byte here, because in the calculations below we
284 * want to have room for it. */
285 len
= strlen(title
) + 1;
287 tmp_proctitle
= realloc(proctitle
, len
);
291 proctitle
= tmp_proctitle
;
293 arg_start
= (unsigned long)proctitle
;
294 arg_end
= arg_start
+ len
;
296 brk_val
= syscall(__NR_brk
, 0);
298 prctl_map
= (struct prctl_mm_map
){
299 .start_code
= start_code
,
300 .end_code
= end_code
,
301 .start_stack
= start_stack
,
302 .start_data
= start_data
,
303 .end_data
= end_data
,
304 .start_brk
= start_brk
,
306 .arg_start
= arg_start
,
308 .env_start
= env_start
,
315 ret
= prctl(PR_SET_MM
, prctl_arg(PR_SET_MM_MAP
), prctl_arg(&prctl_map
),
316 prctl_arg(sizeof(prctl_map
)), prctl_arg(0));
318 (void)strlcpy((char *)arg_start
, title
, len
);
320 SYSWARN("Failed to set cmdline");