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
;
55 * Implementation of dumm_t.create_guest.
57 static guest_t
* create_guest(private_dumm_t
*this, char *name
, char *kernel
,
58 char *master
, int mem
)
62 guest
= guest_create(this->guest_dir
, name
, kernel
, master
, mem
);
65 this->guests
->insert_last(this->guests
, guest
);
71 * Implementation of dumm_t.create_guest_enumerator.
73 static enumerator_t
* create_guest_enumerator(private_dumm_t
*this)
75 return this->guests
->create_enumerator(this->guests
);
79 * Implementation of dumm_t.delete_guest.
81 static void delete_guest(private_dumm_t
*this, guest_t
*guest
)
83 if (this->guests
->remove(this->guests
, guest
, NULL
))
88 len
= snprintf(buf
, sizeof(buf
), "rm -Rf %s/%s",
89 this->guest_dir
, guest
->get_name(guest
));
90 guest
->destroy(guest
);
91 if (len
> 8 && len
< 512)
99 * Implementation of dumm_t.create_bridge.
101 static bridge_t
* create_bridge(private_dumm_t
*this, char *name
)
105 bridge
= bridge_create(name
);
108 this->bridges
->insert_last(this->bridges
, bridge
);
114 * Implementation of dumm_t.create_bridge_enumerator.
116 static enumerator_t
* create_bridge_enumerator(private_dumm_t
*this)
118 return this->bridges
->create_enumerator(this->bridges
);
122 * Implementation of dumm_t.delete_bridge.
124 static void delete_bridge(private_dumm_t
*this, bridge_t
*bridge
)
126 if (this->bridges
->remove(this->bridges
, bridge
, NULL
))
128 bridge
->destroy(bridge
);
133 * disable the currently enabled template
135 static void clear_template(private_dumm_t
*this)
137 enumerator_t
*enumerator
;
140 free(this->template);
141 this->template = NULL
;
143 enumerator
= this->guests
->create_enumerator(this->guests
);
144 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
146 guest
->load_template(guest
, NULL
);
148 enumerator
->destroy(enumerator
);
152 * Implementation of dumm_t.load_template.
154 static bool load_template(private_dumm_t
*this, char *name
)
156 enumerator_t
*enumerator
;
161 clear_template(this);
168 free(this->template);
169 asprintf(&this->template, "%s/%s", this->template_dir
, name
);
170 len
= snprintf(dir
, sizeof(dir
), "%s/%s", this->template, TEMPLATE_DIR_DIR
);
171 if (len
< 0 || len
>= sizeof(dir
))
176 if (access(this->template, F_OK
) != 0)
177 { /* does not exist, create template */
178 if (mkdir(this->template, PERME
) != 0)
180 DBG1("creating template directory '%s' failed: %m", this->template);
183 if (mkdir(dir
, PERME
) != 0)
185 DBG1("creating template overlay directory '%s' failed: %m", dir
);
189 enumerator
= this->guests
->create_enumerator(this->guests
);
190 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
192 if (!guest
->load_template(guest
, dir
))
194 enumerator
->destroy(enumerator
);
195 clear_template(this);
199 enumerator
->destroy(enumerator
);
204 * Implementation of dumm_t.destroy
206 static void destroy(private_dumm_t
*this)
208 enumerator_t
*enumerator
;
211 this->bridges
->destroy_offset(this->bridges
, offsetof(bridge_t
, destroy
));
213 enumerator
= this->guests
->create_enumerator(this->guests
);
214 while (enumerator
->enumerate(enumerator
, (void**)&guest
))
216 guest
->stop(guest
, NULL
);
218 enumerator
->destroy(enumerator
);
220 while (this->guests
->remove_last(this->guests
, (void**)&guest
) == SUCCESS
)
222 guest
->destroy(guest
);
224 this->guests
->destroy(this->guests
);
225 free(this->guest_dir
);
226 free(this->template_dir
);
227 free(this->template);
233 * load all guests in our working dir
235 static void load_guests(private_dumm_t
*this)
241 dir
= opendir(this->guest_dir
);
247 while ((ent
= readdir(dir
)))
249 if (streq(ent
->d_name
, ".") || streq(ent
->d_name
, ".."))
253 guest
= guest_load(this->guest_dir
, ent
->d_name
);
256 this->guests
->insert_last(this->guests
, guest
);
260 DBG1("loading guest in directory '%s' failed, skipped", ent
->d_name
);
267 * create a dumm instance
269 dumm_t
*dumm_create(char *dir
)
272 private_dumm_t
*this = malloc_thing(private_dumm_t
);
274 this->public.create_guest
= (guest_t
*(*)(dumm_t
*,char*,char*,char*,int))create_guest
;
275 this->public.create_guest_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_guest_enumerator
;
276 this->public.delete_guest
= (void(*)(dumm_t
*,guest_t
*))delete_guest
;
277 this->public.create_bridge
= (bridge_t
*(*)(dumm_t
*, char *name
))create_bridge
;
278 this->public.create_bridge_enumerator
= (enumerator_t
*(*)(dumm_t
*))create_bridge_enumerator
;
279 this->public.delete_bridge
= (void(*)(dumm_t
*,bridge_t
*))delete_bridge
;
280 this->public.load_template
= (bool(*)(dumm_t
*, char *name
))load_template
;
281 this->public.destroy
= (void(*)(dumm_t
*))destroy
;
283 if (dir
&& *dir
== '/')
285 this->dir
= strdup(dir
);
289 if (getcwd(cwd
, sizeof(cwd
)) == NULL
)
296 asprintf(&this->dir
, "%s/%s", cwd
, dir
);
300 this->dir
= strdup(cwd
);
303 this->template = NULL
;
304 asprintf(&this->guest_dir
, "%s/%s", this->dir
, GUEST_DIR
);
305 asprintf(&this->template_dir
, "%s/%s", this->dir
, TEMPLATE_DIR
);
306 this->guests
= linked_list_create();
307 this->bridges
= linked_list_create();
309 if (mkdir(this->guest_dir
, PERME
) < 0 && errno
!= EEXIST
)
311 DBG1("creating guest directory '%s' failed: %m", this->guest_dir
);
315 if (mkdir(this->template_dir
, PERME
) < 0 && errno
!= EEXIST
)
317 DBG1("creating template directory '%s' failed: %m", this->template_dir
);
323 return &this->public;