2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include <sys/types.h>
27 #include <utils/linked_list.h>
31 #define PERME (S_IRWXU | S_IRWXG)
32 #define GUEST_DIR "guests"
34 typedef struct private_dumm_t private_dumm_t
;
36 struct private_dumm_t
{
37 /** public dumm interface */
41 /** directory of guests */
43 /** directory of loaded template */
45 /** list of managed guests */
46 linked_list_t
*guests
;
47 /** list of managed bridges */
48 linked_list_t
*bridges
;
52 * Implementation of dumm_t.create_guest.
54 static guest_t
* create_guest(private_dumm_t
*this, char *name
, char *kernel
,
55 char *master
, int mem
)
59 guest
= guest_create(this->guest_dir
, name
, kernel
, master
, mem
);
62 this->guests
->insert_last(this->guests
, guest
);
68 * Implementation of dumm_t.create_guest_enumerator.
70 static enumerator_t
* create_guest_enumerator(private_dumm_t
*this)
72 return this->guests
->create_enumerator(this->guests
);
76 * Implementation of dumm_t.delete_guest.
78 static void delete_guest(private_dumm_t
*this, guest_t
*guest
)
80 if (this->guests
->remove(this->guests
, guest
, NULL
))
85 len
= snprintf(buf
, sizeof(buf
), "rm -Rf %s/%s",
86 this->guest_dir
, guest
->get_name(guest
));
87 guest
->destroy(guest
);
88 if (len
> 8 && len
< 512)
96 * Implementation of dumm_t.create_bridge.
98 static bridge_t
* create_bridge(private_dumm_t
*this, char *name
)
102 bridge
= bridge_create(name
);
105 this->bridges
->insert_last(this->bridges
, bridge
);
111 * Implementation of dumm_t.create_bridge_enumerator.
113 static enumerator_t
* create_bridge_enumerator(private_dumm_t
*this)
115 return this->bridges
->create_enumerator(this->bridges
);
119 * Implementation of dumm_t.delete_bridge.
121 static void delete_bridge(private_dumm_t
*this, bridge_t
*bridge
)
123 if (this->bridges
->remove(this->bridges
, bridge
, NULL
))
125 bridge
->destroy(bridge
);
130 * disable the currently enabled template
132 static void clear_template(private_dumm_t
*this)
134 enumerator_t
*enumerator
;
137 free(this->template);
138 this->template = NULL
;
140 enumerator
= this->guests
->create_enumerator(this->guests
);
141 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
143 guest
->load_template(guest
, NULL
);
145 enumerator
->destroy(enumerator
);
149 * Implementation of dumm_t.load_template.
151 static bool load_template(private_dumm_t
*this, char *dir
)
153 enumerator_t
*enumerator
;
156 clear_template(this);
162 if (strlen(dir
) > PATH_MAX
)
164 DBG1("template directory string '%s' is too long", dir
);
168 this->template = strdup(dir
);
169 if (access(this->template, F_OK
) != 0)
170 { /* does not exist, create template */
171 if (!mkdir_p(this->template, PERME
))
173 DBG1("creating template directory '%s' failed: %m", this->template);
177 enumerator
= this->guests
->create_enumerator(this->guests
);
178 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
180 if (!guest
->load_template(guest
, this->template))
182 enumerator
->destroy(enumerator
);
183 clear_template(this);
187 enumerator
->destroy(enumerator
);
192 * Implementation of dumm_t.destroy
194 static void destroy(private_dumm_t
*this)
196 enumerator_t
*enumerator
;
199 this->bridges
->destroy_offset(this->bridges
, offsetof(bridge_t
, destroy
));
201 enumerator
= this->guests
->create_enumerator(this->guests
);
202 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
204 guest
->stop(guest
, NULL
);
206 enumerator
->destroy(enumerator
);
208 while (this->guests
->remove_last(this->guests
, (void**)&guest
) == SUCCESS
)
210 guest
->destroy(guest
);
212 this->guests
->destroy(this->guests
);
213 free(this->guest_dir
);
214 free(this->template);
220 * load all guests in our working dir
222 static void load_guests(private_dumm_t
*this)
228 dir
= opendir(this->guest_dir
);
234 while ((ent
= readdir(dir
)))
236 if (streq(ent
->d_name
, ".") || streq(ent
->d_name
, ".."))
240 guest
= guest_load(this->guest_dir
, ent
->d_name
);
243 this->guests
->insert_last(this->guests
, guest
);
247 DBG1("loading guest in directory '%s' failed, skipped", ent
->d_name
);
254 * create a dumm instance
256 dumm_t
*dumm_create(char *dir
)
259 private_dumm_t
*this = malloc_thing(private_dumm_t
);
261 this->public.create_guest
= (guest_t
*(*)(dumm_t
*,char*,char*,char*,int))create_guest
;
262 this->public.create_guest_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_guest_enumerator
;
263 this->public.delete_guest
= (void(*)(dumm_t
*,guest_t
*))delete_guest
;
264 this->public.create_bridge
= (bridge_t
*(*)(dumm_t
*, char *name
))create_bridge
;
265 this->public.create_bridge_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_bridge_enumerator
;
266 this->public.delete_bridge
= (void(*)(dumm_t
*,bridge_t
*))delete_bridge
;
267 this->public.load_template
= (bool(*)(dumm_t
*, char *name
))load_template
;
268 this->public.destroy
= (void(*)(dumm_t
*))destroy
;
270 if (dir
&& *dir
== '/')
272 this->dir
= strdup(dir
);
276 if (getcwd(cwd
, sizeof(cwd
)) == NULL
)
283 asprintf(&this->dir
, "%s/%s", cwd
, dir
);
287 this->dir
= strdup(cwd
);
290 this->template = NULL
;
291 asprintf(&this->guest_dir
, "%s/%s", this->dir
, GUEST_DIR
);
292 this->guests
= linked_list_create();
293 this->bridges
= linked_list_create();
295 if (mkdir(this->guest_dir
, PERME
) < 0 && errno
!= EEXIST
)
297 DBG1("creating guest directory '%s' failed: %m", this->guest_dir
);
303 return &this->public;