console.c revision 95ee490bbdb97ab2b4f1dfa63a0a26e0dd1c2f17
/* liblxcapi
*
* Copyright © 2013 Oracle.
*
* Authors:
* Dwight Engen <dwight.engen@oracle.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <lxc/lxccontainer.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#define TTYCNT 4
#define TTYCNT_STR "4"
#define TSTNAME "lxcconsoletest"
#define MAXCONSOLES 512
#define TSTERR(fmt, ...) do { \
fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
} while (0)
static void test_console_close_all(int ttyfd[MAXCONSOLES],
int masterfd[MAXCONSOLES])
{
int i;
for (i = 0; i < MAXCONSOLES; i++) {
if (masterfd[i] != -1) {
close(masterfd[i]);
masterfd[i] = -1;
}
if (ttyfd[i] != -1) {
close(ttyfd[i]);
ttyfd[i] = -1;
}
}
}
static int test_console_running_container(struct lxc_container *c)
{
int nrconsoles, i, ret = -1;
int ttynum [MAXCONSOLES];
int ttyfd [MAXCONSOLES];
int masterfd[MAXCONSOLES];
for (i = 0; i < MAXCONSOLES; i++)
ttynum[i] = ttyfd[i] = masterfd[i] = -1;
ttynum[0] = 1;
ret = c->console_getfd(c, &ttynum[0], &masterfd[0]);
if (ret < 0) {
TSTERR("console allocate failed");
goto err1;
}
ttyfd[0] = ret;
if (ttynum[0] != 1) {
TSTERR("console allocate got bad ttynum %d", ttynum[0]);
goto err2;
}
/* attempt to alloc same ttynum */
ret = c->console_getfd(c, &ttynum[0], &masterfd[1]);
if (ret != -1) {
TSTERR("console allocate should fail for allocated ttynum %d", ttynum[0]);
goto err2;
}
close(masterfd[0]); masterfd[0] = -1;
close(ttyfd[0]); ttyfd[0] = -1;
/* ensure we can allocate all consoles, we do this a few times to
* show that the closes are freeing up the allocated slots
*/
for (i = 0; i < 10; i++) {
for (nrconsoles = 0; nrconsoles < MAXCONSOLES; nrconsoles++) {
ret = c->console_getfd(c, &ttynum[nrconsoles], &masterfd[nrconsoles]);
if (ret < 0)
break;
ttyfd[nrconsoles] = ret;
}
if (nrconsoles != TTYCNT) {
TSTERR("didn't allocate all consoles %d != %d", nrconsoles, TTYCNT);
goto err2;
}
test_console_close_all(ttyfd, masterfd);
}
ret = 0;
err2:
test_console_close_all(ttyfd, masterfd);
err1:
return ret;
}
/* test_container: test console function
*
* @lxcpath : the lxcpath in which to create the container
* @group : name of the container group or NULL for default "lxc"
* @name : name of the container
* @template : template to use when creating the container
*/
static int test_console(const char *lxcpath,
const char *group, const char *name,
const char *template)
{
int ret;
struct lxc_container *c = NULL;
if (lxcpath) {
ret = mkdir(lxcpath, 0755);
if (ret < 0 && errno != EEXIST) {
TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno));
goto out1;
}
}
ret = -1;
if ((c = lxc_container_new(name, lxcpath)) == NULL) {
TSTERR("instantiating container %s", name);
goto out1;
}
if (c->is_defined(c)) {
c->stop(c);
c->destroy(c);
c = lxc_container_new(name, lxcpath);
}
if (!c->createl(c, template, NULL, NULL, 0, NULL)) {
TSTERR("creating container %s", name);
goto out2;
}
c->load_config(c, NULL);
c->set_config_item(c, "lxc.tty", TTYCNT_STR);
c->save_config(c, NULL);
c->want_daemonize(c, true);
if (!c->startl(c, 0, NULL)) {
TSTERR("starting container %s", name);
goto out3;
}
ret = test_console_running_container(c);
c->stop(c);
out3:
c->destroy(c);
out2:
lxc_container_put(c);
out1:
return ret;
}
int main(int argc, char *argv[])
{
int ret;
ret = test_console(NULL, NULL, TSTNAME, "busybox");
if (ret < 0)
goto err1;
ret = test_console("/var/lib/lxctest2", NULL, TSTNAME, "busybox");
if (ret < 0)
goto err1;
printf("All tests passed\n");
err1:
return ret;
}