]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxccontainer.c
api: add set_cgroup_item and get_cgroup_item (to c api)
[mirror_lxc.git] / src / lxc / lxccontainer.c
1 /* liblxcapi
2 *
3 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2012 Canonical Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "lxc.h"
21 #include "state.h"
22 #include "lxccontainer.h"
23 #include "conf.h"
24 #include "config.h"
25 #include "confile.h"
26 #include "cgroup.h"
27 #include "commands.h"
28 #include "log.h"
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <errno.h>
33
34 lxc_log_define(lxc_container, lxc);
35
36 /* LOCKING
37 * c->privlock protects the struct lxc_container from multiple threads.
38 * c->slock protects the on-disk container data
39 * NOTHING mutexes two independent programs with their own struct
40 * lxc_container for the same c->name, between API calls. For instance,
41 * c->config_read(); c->start(); Between those calls, data on disk
42 * could change (which shouldn't bother the caller unless for instance
43 * the rootfs get moved). c->config_read(); update; c->config_write();
44 * Two such updaters could race. The callers should therefore check their
45 * results. Trying to prevent that would necessarily expose us to deadlocks
46 * due to hung callers. So I prefer to keep the locks only within our own
47 * functions, not across functions.
48 *
49 * If you're going to fork while holding a lxccontainer, increment
50 * c->numthreads (under privlock) before forking. When deleting,
51 * decrement numthreads under privlock, then if it hits 0 you can delete.
52 * Do not ever use a lxccontainer whose numthreads you did not bump.
53 */
54
55 static void lxc_container_free(struct lxc_container *c)
56 {
57 if (!c)
58 return;
59
60 if (c->configfile) {
61 free(c->configfile);
62 c->configfile = NULL;
63 }
64 if (c->error_string) {
65 free(c->error_string);
66 c->error_string = NULL;
67 }
68 if (c->slock) {
69 sem_close(c->slock);
70 c->slock = NULL;
71 }
72 if (c->privlock) {
73 sem_destroy(c->privlock);
74 free(c->privlock);
75 c->privlock = NULL;
76 }
77 if (c->name) {
78 free(c->name);
79 c->name = NULL;
80 }
81 if (c->lxc_conf) {
82 lxc_conf_free(c->lxc_conf);
83 c->lxc_conf = NULL;
84 }
85 free(c);
86 }
87
88 int lxc_container_get(struct lxc_container *c)
89 {
90 if (!c)
91 return 0;
92
93 if (lxclock(c->privlock, 0))
94 return 0;
95 if (c->numthreads < 1) {
96 // bail without trying to unlock, bc the privlock is now probably
97 // in freed memory
98 return 0;
99 }
100 c->numthreads++;
101 lxcunlock(c->privlock);
102 return 1;
103 }
104
105 int lxc_container_put(struct lxc_container *c)
106 {
107 if (!c)
108 return -1;
109 if (lxclock(c->privlock, 0))
110 return -1;
111 if (--c->numthreads < 1) {
112 lxcunlock(c->privlock);
113 lxc_container_free(c);
114 return 1;
115 }
116 lxcunlock(c->privlock);
117 return 0;
118 }
119
120 static bool file_exists(char *f)
121 {
122 struct stat statbuf;
123
124 return stat(f, &statbuf) == 0;
125 }
126
127 static bool lxcapi_is_defined(struct lxc_container *c)
128 {
129 struct stat statbuf;
130 bool ret = false;
131 int statret;
132
133 if (!c)
134 return false;
135
136 if (lxclock(c->privlock, 0))
137 return false;
138 if (!c->configfile)
139 goto out;
140 statret = stat(c->configfile, &statbuf);
141 if (statret != 0)
142 goto out;
143 ret = true;
144
145 out:
146 lxcunlock(c->privlock);
147 return ret;
148 }
149
150 static const char *lxcapi_state(struct lxc_container *c)
151 {
152 const char *ret;
153 lxc_state_t s;
154
155 if (!c)
156 return NULL;
157 if (lxclock(c->slock, 0))
158 return NULL;
159 s = lxc_getstate(c->name);
160 ret = lxc_state2str(s);
161 lxcunlock(c->slock);
162
163 return ret;
164 }
165
166 static bool is_stopped_nolock(struct lxc_container *c)
167 {
168 lxc_state_t s;
169 s = lxc_getstate(c->name);
170 return (s == STOPPED);
171 }
172
173 static bool lxcapi_is_running(struct lxc_container *c)
174 {
175 const char *s;
176
177 if (!c)
178 return false;
179 s = lxcapi_state(c);
180 if (!s || strcmp(s, "STOPPED") == 0)
181 return false;
182 return true;
183 }
184
185 static bool lxcapi_freeze(struct lxc_container *c)
186 {
187 int ret;
188 if (!c)
189 return false;
190
191 if (lxclock(c->slock, 0))
192 return false;
193 ret = lxc_freeze(c->name);
194 lxcunlock(c->slock);
195 if (ret)
196 return false;
197 return true;
198 }
199
200 static bool lxcapi_unfreeze(struct lxc_container *c)
201 {
202 int ret;
203 if (!c)
204 return false;
205
206 if (lxclock(c->slock, 0))
207 return false;
208 ret = lxc_unfreeze(c->name);
209 lxcunlock(c->slock);
210 if (ret)
211 return false;
212 return true;
213 }
214
215 static pid_t lxcapi_init_pid(struct lxc_container *c)
216 {
217 pid_t ret;
218 if (!c)
219 return -1;
220
221 if (lxclock(c->slock, 0))
222 return -1;
223 ret = get_init_pid(c->name);
224 lxcunlock(c->slock);
225 return ret;
226 }
227
228 static bool load_config_locked(struct lxc_container *c, const char *fname)
229 {
230 if (!c->lxc_conf)
231 c->lxc_conf = lxc_conf_init();
232 if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
233 return true;
234 return false;
235 }
236
237 static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file)
238 {
239 bool ret = false;
240 const char *fname;
241 if (!c)
242 return false;
243
244 fname = c->configfile;
245 if (alt_file)
246 fname = alt_file;
247 if (!fname)
248 return false;
249 if (lxclock(c->slock, 0))
250 return false;
251 ret = load_config_locked(c, fname);
252 lxcunlock(c->slock);
253 return ret;
254 }
255
256 static void lxcapi_want_daemonize(struct lxc_container *c)
257 {
258 if (!c)
259 return;
260 c->daemonize = 1;
261 }
262
263 static bool lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
264 {
265 int ret;
266
267 if (!c)
268 return false;
269
270 ret = lxc_wait(c->name, state, timeout);
271 return ret == 0;
272 }
273
274
275 static bool wait_on_daemonized_start(struct lxc_container *c)
276 {
277 /* we'll probably want to make this timeout configurable? */
278 int timeout = 5, ret, status;
279
280 /*
281 * our child is going to fork again, then exit. reap the
282 * child
283 */
284 ret = wait(&status);
285 if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
286 DEBUG("failed waiting for first dual-fork child");
287 return lxcapi_wait(c, "RUNNING", timeout);
288 }
289
290 /*
291 * I can't decide if it'd be more convenient for callers if we accept '...',
292 * or a null-terminated array (i.e. execl vs execv)
293 */
294 static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
295 {
296 int ret;
297 struct lxc_conf *conf;
298 int daemonize = 0;
299 char *default_args[] = {
300 "/sbin/init",
301 '\0',
302 };
303
304 /* container exists */
305 if (!c)
306 return false;
307 /* container has been setup */
308 if (!c->lxc_conf)
309 return false;
310
311 /* is this app meant to be run through lxcinit, as in lxc-execute? */
312 if (useinit && !argv)
313 return false;
314
315 if (lxclock(c->privlock, 0))
316 return false;
317 conf = c->lxc_conf;
318 daemonize = c->daemonize;
319 lxcunlock(c->privlock);
320
321 if (useinit) {
322 ret = lxc_execute(c->name, argv, 1, conf);
323 return ret == 0 ? true : false;
324 }
325
326 if (!argv)
327 argv = default_args;
328
329 /*
330 * say, I'm not sure - what locks do we want here? Any?
331 * Is liblxc's locking enough here to protect the on disk
332 * container? We don't want to exclude things like lxc_info
333 * while container is running...
334 */
335 if (daemonize) {
336 if (!lxc_container_get(c))
337 return false;
338 pid_t pid = fork();
339 if (pid < 0) {
340 lxc_container_put(c);
341 return false;
342 }
343 if (pid != 0)
344 return wait_on_daemonized_start(c);
345 /* second fork to be reparented by init */
346 pid = fork();
347 if (pid < 0) {
348 SYSERROR("Error doing dual-fork");
349 return false;
350 }
351 if (pid != 0)
352 exit(0);
353 /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */
354 if (chdir("/")) {
355 SYSERROR("Error chdir()ing to /.");
356 return false;
357 }
358 close(0);
359 close(1);
360 close(2);
361 open("/dev/null", O_RDONLY);
362 open("/dev/null", O_RDWR);
363 open("/dev/null", O_RDWR);
364 setsid();
365 }
366
367 if (putenv("container=lxc")) {
368 fprintf(stderr, "failed to set environment variable");
369 if (daemonize) {
370 lxc_container_put(c);
371 exit(1);
372 } else {
373 return false;
374 }
375 }
376
377 reboot:
378 conf->reboot = 0;
379 ret = lxc_start(c->name, argv, conf);
380
381 if (conf->reboot) {
382 INFO("container requested reboot");
383 conf->reboot = 0;
384 if (conf->maincmd_fd)
385 close(conf->maincmd_fd);
386 conf->maincmd_fd = 0;
387 goto reboot;
388 }
389
390 if (daemonize) {
391 lxc_container_put(c);
392 exit (ret == 0 ? true : false);
393 } else {
394 return (ret == 0 ? true : false);
395 }
396 }
397
398 /*
399 * note there MUST be an ending NULL
400 */
401 static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
402 {
403 va_list ap;
404 char **inargs = NULL, **temp;
405 int n_inargs = 0;
406 bool bret = false;
407
408 /* container exists */
409 if (!c)
410 return false;
411
412 /* build array of arguments if any */
413 va_start(ap, useinit);
414 while (1) {
415 char *arg;
416 arg = va_arg(ap, char *);
417 if (!arg)
418 break;
419 n_inargs++;
420 temp = realloc(inargs, n_inargs * sizeof(*inargs));
421 if (!temp)
422 goto out;
423 inargs = temp;
424 inargs[n_inargs - 1] = strdup(arg); // not sure if it's safe not to copy
425 }
426 va_end(ap);
427
428 /* add trailing NULL */
429 if (n_inargs) {
430 n_inargs++;
431 temp = realloc(inargs, n_inargs * sizeof(*inargs));
432 if (!temp)
433 goto out;
434 inargs = temp;
435 inargs[n_inargs - 1] = NULL;
436 }
437
438 bret = lxcapi_start(c, useinit, inargs);
439
440 out:
441 if (inargs) {
442 int i;
443 for (i = 0; i < n_inargs; i++) {
444 if (inargs[i])
445 free(inargs[i]);
446 }
447 free(inargs);
448 }
449
450 return bret;
451 }
452
453 static bool lxcapi_stop(struct lxc_container *c)
454 {
455 int ret;
456
457 if (!c)
458 return false;
459
460 ret = lxc_stop(c->name);
461
462 return ret == 0;
463 }
464
465 static bool valid_template(char *t)
466 {
467 struct stat statbuf;
468 int statret;
469
470 statret = stat(t, &statbuf);
471 if (statret == 0)
472 return true;
473 return false;
474 }
475
476 /*
477 * create the standard expected container dir
478 */
479 static bool create_container_dir(struct lxc_container *c)
480 {
481 char *s;
482 int len, ret;
483
484 len = strlen(LXCPATH) + strlen(c->name) + 2;
485 s = malloc(len);
486 if (!s)
487 return false;
488 ret = snprintf(s, len, "%s/%s", LXCPATH, c->name);
489 if (ret < 0 || ret >= len) {
490 free(s);
491 return false;
492 }
493 ret = mkdir(s, 0755);
494 if (ret) {
495 if (errno == EEXIST)
496 ret = 0;
497 else
498 SYSERROR("failed to create container path for %s\n", c->name);
499 }
500 free(s);
501 return ret == 0;
502 }
503
504 /*
505 * backing stores not (yet) supported
506 * for ->create, argv contains the arguments to pass to the template,
507 * terminated by NULL. If no arguments, you can just pass NULL.
508 */
509 static bool lxcapi_create(struct lxc_container *c, char *t, char *const argv[])
510 {
511 bool bret = false;
512 pid_t pid;
513 int ret, status;
514 char *tpath = NULL;
515 int len, nargs = 0;
516 char **newargv;
517
518 if (!c)
519 return false;
520
521 len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
522 tpath = malloc(len);
523 if (!tpath)
524 return false;
525 ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
526 if (ret < 0 || ret >= len)
527 goto out;
528 if (!valid_template(tpath)) {
529 ERROR("bad template: %s\n", t);
530 goto out;
531 }
532
533 if (!create_container_dir(c))
534 goto out;
535
536 if (!c->save_config(c, NULL)) {
537 ERROR("failed to save starting configuration for %s\n", c->name);
538 goto out;
539 }
540
541 /* we're going to fork. but since we'll wait for our child, we
542 don't need to lxc_container_get */
543
544 if (lxclock(c->slock, 0)) {
545 ERROR("failed to grab global container lock for %s\n", c->name);
546 goto out;
547 }
548
549 pid = fork();
550 if (pid < 0) {
551 SYSERROR("failed to fork task for container creation template\n");
552 goto out_unlock;
553 }
554
555 if (pid == 0) { // child
556 char *patharg, *namearg;
557 int i;
558
559 close(0);
560 close(1);
561 close(2);
562 open("/dev/null", O_RDONLY);
563 open("/dev/null", O_RDWR);
564 open("/dev/null", O_RDWR);
565
566 /*
567 * create our new array, pre-pend the template name and
568 * base args
569 */
570 if (argv)
571 for (; argv[nargs]; nargs++) ;
572 nargs += 3; // template, path and name args
573 newargv = malloc(nargs * sizeof(*newargv));
574 if (!newargv)
575 exit(1);
576 newargv[0] = t;
577
578 len = strlen(LXCPATH) + strlen(c->name) + strlen("--path=") + 2;
579 patharg = malloc(len);
580 if (!patharg)
581 exit(1);
582 ret = snprintf(patharg, len, "--path=%s/%s", LXCPATH, c->name);
583 if (ret < 0 || ret >= len)
584 exit(1);
585 newargv[1] = patharg;
586 len = strlen("--name=") + strlen(c->name) + 1;
587 namearg = malloc(len);
588 if (!namearg)
589 exit(1);
590 ret = snprintf(namearg, len, "--name=%s", c->name);
591 if (ret < 0 || ret >= len)
592 exit(1);
593 newargv[2] = namearg;
594
595 /* add passed-in args */
596 if (argv)
597 for (i = 3; i < nargs; i++)
598 newargv[i] = argv[i-3];
599
600 /* add trailing NULL */
601 nargs++;
602 newargv = realloc(newargv, nargs * sizeof(*newargv));
603 if (!newargv)
604 exit(1);
605 newargv[nargs - 1] = NULL;
606
607 /* execute */
608 ret = execv(tpath, newargv);
609 SYSERROR("failed to execute template %s", tpath);
610 exit(1);
611 }
612
613 again:
614 ret = waitpid(pid, &status, 0);
615 if (ret == -1) {
616 if (errno == -EINTR)
617 goto again;
618 SYSERROR("waitpid failed");
619 goto out_unlock;
620 }
621 if (ret != pid)
622 goto again;
623 if (!WIFEXITED(status)) { // did not exit normally
624 // we could set an error code and string inside the
625 // container_struct here if we like
626 ERROR("container creation template exited abnormally\n");
627 goto out_unlock;
628 }
629
630 if (WEXITSTATUS(status) != 0) {
631 ERROR("container creation template for %s exited with %d\n",
632 c->name, WEXITSTATUS(status));
633 goto out_unlock;
634 }
635
636 // now clear out the lxc_conf we have, reload from the created
637 // container
638 if (c->lxc_conf)
639 lxc_conf_free(c->lxc_conf);
640 c->lxc_conf = NULL;
641 bret = load_config_locked(c, c->configfile);
642
643 out_unlock:
644 lxcunlock(c->slock);
645 out:
646 if (tpath)
647 free(tpath);
648 return bret;
649 }
650
651 static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
652 {
653 bool retv;
654 pid_t pid;
655
656 if (!c)
657 return false;
658
659 if (!timeout)
660 timeout = -1;
661 if (!c->is_running(c))
662 return true;
663 pid = c->init_pid(c);
664 if (pid <= 0)
665 return true;
666 kill(pid, SIGPWR);
667 retv = c->wait(c, "STOPPED", timeout);
668 if (!retv && timeout > 0) {
669 c->stop(c);
670 retv = c->wait(c, "STOPPED", 0); // 0 means don't wait
671 }
672 return retv;
673 }
674
675 static bool lxcapi_createl(struct lxc_container *c, char *t, ...)
676 {
677 bool bret = false;
678 char **args = NULL, **temp;
679 va_list ap;
680 int nargs = 0;
681
682 if (!c)
683 return false;
684
685 /*
686 * since we're going to wait for create to finish, I don't think we
687 * need to get a copy of the arguments.
688 */
689 va_start(ap, t);
690 while (1) {
691 char *arg;
692 arg = va_arg(ap, char *);
693 if (!arg)
694 break;
695 nargs++;
696 temp = realloc(args, (nargs+1) * sizeof(*args));
697 if (!temp)
698 goto out;
699 args = temp;
700 args[nargs - 1] = arg;
701 }
702 va_end(ap);
703 args[nargs] = NULL;
704
705 bret = c->create(c, t, args);
706
707 out:
708 if (args)
709 free(args);
710 return bret;
711 }
712
713 static bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
714 {
715 int ret;
716
717 if (!c || !c->lxc_conf)
718 return false;
719 if (lxclock(c->privlock, 0)) {
720 return false;
721 }
722 ret = lxc_clear_config_item(c->lxc_conf, key);
723 lxcunlock(c->privlock);
724 return ret == 0;
725 }
726
727 static int lxcapi_get_config_item(struct lxc_container *c, const char *key, char *retv, int inlen)
728 {
729 int ret;
730
731 if (!c || !c->lxc_conf)
732 return -1;
733 if (lxclock(c->privlock, 0)) {
734 return -1;
735 }
736 ret = lxc_get_config_item(c->lxc_conf, key, retv, inlen);
737 lxcunlock(c->privlock);
738 return ret;
739 }
740
741 static int lxcapi_get_keys(struct lxc_container *c, const char *key, char *retv, int inlen)
742 {
743 if (!key)
744 return lxc_listconfigs(retv, inlen);
745 /*
746 * Support 'lxc.network.<idx>', i.e. 'lxc.network.0'
747 * This is an intelligent result to show which keys are valid given
748 * the type of nic it is
749 */
750 if (!c || !c->lxc_conf)
751 return -1;
752 if (lxclock(c->privlock, 0))
753 return -1;
754 int ret = -1;
755 if (strncmp(key, "lxc.network.", 12) == 0)
756 ret = lxc_list_nicconfigs(c->lxc_conf, key, retv, inlen);
757 lxcunlock(c->privlock);
758 return ret;
759 }
760
761
762 /* default config file - should probably come through autoconf */
763 #define LXC_DEFAULT_CONFIG "/etc/lxc/lxc.conf"
764 static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
765 {
766 if (!alt_file)
767 alt_file = c->configfile;
768 if (!alt_file)
769 return false; // should we write to stdout if no file is specified?
770 if (!c->lxc_conf)
771 if (!c->load_config(c, LXC_DEFAULT_CONFIG)) {
772 ERROR("Error loading default configuration file %s while saving %s\n", LXC_DEFAULT_CONFIG, c->name);
773 return false;
774 }
775
776 FILE *fout = fopen(alt_file, "w");
777 if (!fout)
778 return false;
779 if (lxclock(c->privlock, 0)) {
780 fclose(fout);
781 return false;
782 }
783 write_config(fout, c->lxc_conf);
784 fclose(fout);
785 lxcunlock(c->privlock);
786 return true;
787 }
788
789 static bool lxcapi_destroy(struct lxc_container *c)
790 {
791 pid_t pid;
792 int ret, status;
793
794 if (!c)
795 return false;
796
797 pid = fork();
798 if (pid < 0)
799 return false;
800 if (pid == 0) { // child
801 ret = execlp("lxc-destroy", "lxc-destroy", "-n", c->name, NULL);
802 perror("execl");
803 exit(1);
804 }
805
806 again:
807 ret = waitpid(pid, &status, 0);
808 if (ret == -1) {
809 if (errno == -EINTR)
810 goto again;
811 perror("waitpid");
812 return false;
813 }
814 if (ret != pid)
815 goto again;
816 if (!WIFEXITED(status)) { // did not exit normally
817 // we could set an error code and string inside the
818 // container_struct here if we like
819 return false;
820 }
821
822 return WEXITSTATUS(status) == 0;
823 }
824
825 static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v)
826 {
827 int ret;
828 bool b = false;
829 struct lxc_config_t *config;
830
831 if (!c)
832 return false;
833
834 if (lxclock(c->privlock, 0))
835 return false;
836
837 if (!c->lxc_conf)
838 c->lxc_conf = lxc_conf_init();
839 if (!c->lxc_conf)
840 goto err;
841 config = lxc_getconfig(key);
842 if (!config)
843 goto err;
844 ret = config->cb(key, v, c->lxc_conf);
845 if (!ret)
846 b = true;
847
848 err:
849 lxcunlock(c->privlock);
850 return b;
851 }
852
853 static char *lxcapi_config_file_name(struct lxc_container *c)
854 {
855 if (!c || !c->configfile)
856 return NULL;
857 return strdup(c->configfile);
858 }
859
860 static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
861 {
862 int ret;
863 bool b = false;
864
865 if (!c)
866 return false;
867
868 if (lxclock(c->privlock, 0))
869 return false;
870
871 if (is_stopped_nolock(c))
872 goto err;
873
874 ret = lxc_cgroup_set(c->name, subsys, value);
875 if (!ret)
876 b = true;
877 err:
878 lxcunlock(c->privlock);
879 return b;
880 }
881
882 static int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
883 {
884 int ret = -1;
885
886 if (!c || !c->lxc_conf)
887 return -1;
888
889 if (lxclock(c->privlock, 0))
890 return -1;
891
892 if (is_stopped_nolock(c))
893 goto out;
894
895 ret = lxc_cgroup_get(c->name, subsys, retv, inlen);
896
897 out:
898 lxcunlock(c->privlock);
899 return ret;
900 }
901
902
903 struct lxc_container *lxc_container_new(const char *name)
904 {
905 struct lxc_container *c;
906 int ret, len;
907
908 c = malloc(sizeof(*c));
909 if (!c) {
910 fprintf(stderr, "failed to malloc lxc_container\n");
911 return NULL;
912 }
913 memset(c, 0, sizeof(*c));
914
915 c->name = malloc(strlen(name)+1);
916 if (!c->name) {
917 fprintf(stderr, "Error allocating lxc_container name\n");
918 goto err;
919 }
920 strcpy(c->name, name);
921
922 c->numthreads = 1;
923 c->slock = lxc_newlock(name);
924 if (!c->slock) {
925 fprintf(stderr, "failed to create lock\n");
926 goto err;
927 }
928
929 c->privlock = lxc_newlock(NULL);
930 if (!c->privlock) {
931 fprintf(stderr, "failed to alloc privlock\n");
932 goto err;
933 }
934
935 len = strlen(LXCPATH)+strlen(c->name)+strlen("/config")+2;
936 c->configfile = malloc(len);
937 if (!c->configfile) {
938 fprintf(stderr, "Error allocating config file pathname\n");
939 goto err;
940 }
941 ret = snprintf(c->configfile, len, "%s/%s/config", LXCPATH, c->name);
942 if (ret < 0 || ret >= len) {
943 fprintf(stderr, "Error printing out config file name\n");
944 goto err;
945 }
946
947 if (file_exists(c->configfile))
948 lxcapi_load_config(c, NULL);
949
950 // assign the member functions
951 c->is_defined = lxcapi_is_defined;
952 c->state = lxcapi_state;
953 c->is_running = lxcapi_is_running;
954 c->freeze = lxcapi_freeze;
955 c->unfreeze = lxcapi_unfreeze;
956 c->init_pid = lxcapi_init_pid;
957 c->load_config = lxcapi_load_config;
958 c->want_daemonize = lxcapi_want_daemonize;
959 c->start = lxcapi_start;
960 c->startl = lxcapi_startl;
961 c->stop = lxcapi_stop;
962 c->config_file_name = lxcapi_config_file_name;
963 c->wait = lxcapi_wait;
964 c->set_config_item = lxcapi_set_config_item;
965 c->destroy = lxcapi_destroy;
966 c->save_config = lxcapi_save_config;
967 c->get_keys = lxcapi_get_keys;
968 c->create = lxcapi_create;
969 c->createl = lxcapi_createl;
970 c->shutdown = lxcapi_shutdown;
971 c->clear_config_item = lxcapi_clear_config_item;
972 c->get_config_item = lxcapi_get_config_item;
973 c->get_cgroup_item = lxcapi_get_cgroup_item;
974 c->set_cgroup_item = lxcapi_set_cgroup_item;
975
976 /* we'll allow the caller to update these later */
977 if (lxc_log_init(NULL, NULL, "lxc_container", 0)) {
978 fprintf(stderr, "failed to open log\n");
979 goto err;
980 }
981
982 /*
983 * default configuration file is $LXCPATH/$NAME/config
984 */
985
986 return c;
987
988 err:
989 lxc_container_free(c);
990 return NULL;
991 }
992
993 int lxc_get_wait_states(const char **states)
994 {
995 int i;
996
997 if (states)
998 for (i=0; i<MAX_STATE; i++)
999 states[i] = lxc_state2str(i);
1000 return MAX_STATE;
1001 }