2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include <sys/types.h>
26 #include <utils/linked_list.h>
30 #define PERME (S_IRWXU | S_IRWXG)
31 #define GUEST_DIR "guests"
32 #define TEMPLATE_DIR "templates"
33 #define TEMPLATE_DIR_DIR "diff"
35 typedef struct private_dumm_t private_dumm_t
;
37 struct private_dumm_t
{
38 /** public dumm interface */
42 /** directory of guests */
44 /** directory of templates */
46 /** directory of loaded template */
48 /** list of managed guests */
49 linked_list_t
*guests
;
50 /** list of managed bridges */
51 linked_list_t
*bridges
;
52 /** do not catch signals if we are destroying */
57 * Implementation of dumm_t.create_guest.
59 static guest_t
* create_guest(private_dumm_t
*this, char *name
, char *kernel
,
60 char *master
, int mem
)
64 guest
= guest_create(this->guest_dir
, name
, kernel
, master
, mem
);
67 this->guests
->insert_last(this->guests
, guest
);
73 * Implementation of dumm_t.create_guest_enumerator.
75 static enumerator_t
* create_guest_enumerator(private_dumm_t
*this)
77 return this->guests
->create_enumerator(this->guests
);
81 * Implementation of dumm_t.delete_guest.
83 static void delete_guest(private_dumm_t
*this, guest_t
*guest
)
85 if (this->guests
->remove(this->guests
, guest
, NULL
))
90 len
= snprintf(buf
, sizeof(buf
), "rm -Rf %s/%s",
91 this->guest_dir
, guest
->get_name(guest
));
92 guest
->destroy(guest
);
93 if (len
> 8 && len
< 512)
101 * Implementation of dumm_t.create_bridge.
103 static bridge_t
* create_bridge(private_dumm_t
*this, char *name
)
107 bridge
= bridge_create(name
);
110 this->bridges
->insert_last(this->bridges
, bridge
);
116 * Implementation of dumm_t.create_bridge_enumerator.
118 static enumerator_t
* create_bridge_enumerator(private_dumm_t
*this)
120 return this->bridges
->create_enumerator(this->bridges
);
124 * Implementation of dumm_t.delete_bridge.
126 static void delete_bridge(private_dumm_t
*this, bridge_t
*bridge
)
128 if (this->bridges
->remove(this->bridges
, bridge
, NULL
))
130 bridge
->destroy(bridge
);
135 * disable the currently enabled template
137 static void clear_template(private_dumm_t
*this)
139 enumerator_t
*enumerator
;
142 free(this->template);
143 this->template = NULL
;
145 enumerator
= this->guests
->create_enumerator(this->guests
);
146 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
148 guest
->load_template(guest
, NULL
);
150 enumerator
->destroy(enumerator
);
154 * Implementation of dumm_t.load_template.
156 static bool load_template(private_dumm_t
*this, char *name
)
158 enumerator_t
*enumerator
;
163 clear_template(this);
170 free(this->template);
171 asprintf(&this->template, "%s/%s", this->template_dir
, name
);
172 len
= snprintf(dir
, sizeof(dir
), "%s/%s", this->template, TEMPLATE_DIR_DIR
);
173 if (len
< 0 || len
>= sizeof(dir
))
178 if (access(this->template, F_OK
) != 0)
179 { /* does not exist, create template */
180 if (mkdir(this->template, PERME
) != 0)
182 DBG1("creating template directory '%s' failed: %m", this->template);
185 if (mkdir(dir
, PERME
) != 0)
187 DBG1("creating template overlay directory '%s' failed: %m", dir
);
191 enumerator
= this->guests
->create_enumerator(this->guests
);
192 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
194 if (!guest
->load_template(guest
, dir
))
196 enumerator
->destroy(enumerator
);
197 clear_template(this);
201 enumerator
->destroy(enumerator
);
206 * Implementation of dumm_t.destroy
208 static void destroy(private_dumm_t
*this)
210 enumerator_t
*enumerator
;
213 this->bridges
->destroy_offset(this->bridges
, offsetof(bridge_t
, destroy
));
215 enumerator
= this->guests
->create_enumerator(this->guests
);
216 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
218 guest
->stop(guest
, NULL
);
220 enumerator
->destroy(enumerator
);
222 this->destroying
= TRUE
;
223 this->guests
->destroy_offset(this->guests
, offsetof(guest_t
, destroy
));
224 free(this->guest_dir
);
225 free(this->template_dir
);
226 free(this->template);
232 * load all guests in our working dir
234 static void load_guests(private_dumm_t
*this)
240 dir
= opendir(this->guest_dir
);
246 while ((ent
= readdir(dir
)))
248 if (streq(ent
->d_name
, ".") || streq(ent
->d_name
, ".."))
252 guest
= guest_load(this->guest_dir
, ent
->d_name
);
255 this->guests
->insert_last(this->guests
, guest
);
259 DBG1("loading guest in directory '%s' failed, skipped", ent
->d_name
);
266 * create a dumm instance
268 dumm_t
*dumm_create(char *dir
)
271 private_dumm_t
*this = malloc_thing(private_dumm_t
);
273 this->public.create_guest
= (guest_t
*(*)(dumm_t
*,char*,char*,char*,int))create_guest
;
274 this->public.create_guest_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_guest_enumerator
;
275 this->public.delete_guest
= (void(*)(dumm_t
*,guest_t
*))delete_guest
;
276 this->public.create_bridge
= (bridge_t
*(*)(dumm_t
*, char *name
))create_bridge
;
277 this->public.create_bridge_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_bridge_enumerator
;
278 this->public.delete_bridge
= (void(*)(dumm_t
*,bridge_t
*))delete_bridge
;
279 this->public.load_template
= (bool(*)(dumm_t
*, char *name
))load_template
;
280 this->public.destroy
= (void(*)(dumm_t
*))destroy
;
282 this->destroying
= FALSE
;
284 if (dir
&& *dir
== '/')
286 this->dir
= strdup(dir
);
290 if (getcwd(cwd
, sizeof(cwd
)) == NULL
)
297 asprintf(&this->dir
, "%s/%s", cwd
, dir
);
301 this->dir
= strdup(cwd
);
304 this->template = NULL
;
305 asprintf(&this->guest_dir
, "%s/%s", this->dir
, GUEST_DIR
);
306 asprintf(&this->template_dir
, "%s/%s", this->dir
, TEMPLATE_DIR
);
307 this->guests
= linked_list_create();
308 this->bridges
= linked_list_create();
310 if (mkdir(this->guest_dir
, PERME
) < 0 && errno
!= EEXIST
)
312 DBG1("creating guest directory '%s' failed: %m", this->guest_dir
);
316 if (mkdir(this->template_dir
, PERME
) < 0 && errno
!= EEXIST
)
318 DBG1("creating template directory '%s' failed: %m", this->template_dir
);
324 return &this->public;