aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-07-27 20:07:24 +0000
committerChristian Grothoff <christian@grothoff.org>2009-07-27 20:07:24 +0000
commitfe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4 (patch)
tree81738f3a8a167533ddf001a72809dfa5015186de
parentc5cda378386d01412ada7fbf8d51317bab1ab695 (diff)
downloadgnunet-fe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4.tar.gz
gnunet-fe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4.zip
mktemp
-rw-r--r--BUGS2
-rw-r--r--src/datacache/datacache.c13
-rw-r--r--src/datacache/plugin_datacache_sqlite.c24
-rw-r--r--src/include/gnunet_constants.h6
-rw-r--r--src/include/gnunet_disk_lib.h14
-rw-r--r--src/include/gnunet_os_lib.h4
-rw-r--r--src/include/gnunet_testing_lib.h2
-rw-r--r--src/testing/testing.c529
-rw-r--r--src/util/disk.c46
9 files changed, 606 insertions, 34 deletions
diff --git a/BUGS b/BUGS
index d3790ac2e..a6339547e 100644
--- a/BUGS
+++ b/BUGS
@@ -10,8 +10,6 @@ sane end-user should care about this codebase yet anyway.
10 - only connect() sockets that are ready (select()) [Nils] 10 - only connect() sockets that are ready (select()) [Nils]
11 [On W32, we need to select after calling socket before 11 [On W32, we need to select after calling socket before
12 doing connect etc.] 12 doing connect etc.]
13 - Add "DISK" API for creating of temporary files
14 (as used in datacache/ module) [Nils?]
15* SERVER: 13* SERVER:
16 - inefficient memmove 14 - inefficient memmove
17* TRANSPORT: 15* TRANSPORT:
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c
index 421acac0f..3b233d16d 100644
--- a/src/datacache/datacache.c
+++ b/src/datacache/datacache.c
@@ -121,7 +121,6 @@ GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
121 const struct GNUNET_CONFIGURATION_Handle *cfg, 121 const struct GNUNET_CONFIGURATION_Handle *cfg,
122 const char *section) 122 const char *section)
123{ 123{
124 int fd;
125 unsigned int bf_size; 124 unsigned int bf_size;
126 unsigned long long quota; 125 unsigned long long quota;
127 struct GNUNET_DATACACHE_Handle *ret; 126 struct GNUNET_DATACACHE_Handle *ret;
@@ -152,14 +151,13 @@ GNUNET_DATACACHE_create (struct GNUNET_SCHEDULER_Handle *sched,
152 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ 151 bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */
153 152
154 ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle)); 153 ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle));
155 ret->bloom_name = GNUNET_strdup ("/tmp/datacachebloomXXXXXX"); 154 ret->bloom_name = GNUNET_DISK_mktemp ("datacachebloom");
156 fd = mkstemp (ret->bloom_name); 155
157 if (fd != -1) 156 if (ret->bloom_name)
158 { 157 {
159 ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name, 158 ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name,
160 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */ 159 quota / 1024, /* 8 bit per entry in DB, expect 1k entries */
161 5); 160 5);
162 CLOSE (fd);
163 } 161 }
164 else 162 else
165 { 163 {
@@ -206,7 +204,10 @@ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h)
206 GNUNET_free (h->section); 204 GNUNET_free (h->section);
207 if (h->bloom_name != NULL) 205 if (h->bloom_name != NULL)
208 { 206 {
209 UNLINK (h->bloom_name); 207 if (0 != UNLINK (h->bloom_name))
208 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
209 "unlink",
210 h->bloom_name);
210 GNUNET_free (h->bloom_name); 211 GNUNET_free (h->bloom_name);
211 } 212 }
212 GNUNET_free (h); 213 GNUNET_free (h);
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c
index 5493dbb90..63f8cbd67 100644
--- a/src/datacache/plugin_datacache_sqlite.c
+++ b/src/datacache/plugin_datacache_sqlite.c
@@ -346,35 +346,15 @@ libgnunet_plugin_datacache_sqlite_init (void *cls)
346 struct Plugin *plugin; 346 struct Plugin *plugin;
347 char *fn; 347 char *fn;
348 char *fn_utf8; 348 char *fn_utf8;
349 int fd;
350 sqlite3 *dbh; 349 sqlite3 *dbh;
351 char *tmpl;
352 const char *tmpdir;
353 char *emsg; 350 char *emsg;
354 351
355 tmpdir = getenv ("TMPDIR"); 352 fn = GNUNET_DISK_mktemp ("gnunet-datacache");
356 tmpdir = tmpdir ? tmpdir : "/tmp"; 353 if (fn == NULL)
357
358#define TEMPLATE "/gnunet-dstoreXXXXXX"
359 tmpl = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1);
360 strcpy (tmpl, tmpdir);
361 strcat (tmpl, TEMPLATE);
362#undef TEMPLATE
363#ifdef MINGW
364 fn = (char *) GNUNET_malloc (MAX_PATH + 1);
365 plibc_conv_to_win_path (tmpl, fn);
366 GNUNET_free (tmpl);
367#else
368 fn = tmpl;
369#endif
370 fd = mkstemp (fn);
371 if (fd == -1)
372 { 354 {
373 GNUNET_break (0); 355 GNUNET_break (0);
374 GNUNET_free (fn);
375 return NULL; 356 return NULL;
376 } 357 }
377 CLOSE (fd);
378 fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn), 358 fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn),
379#ifdef ENABLE_NLS 359#ifdef ENABLE_NLS
380 nl_langinfo (CODESET) 360 nl_langinfo (CODESET)
diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h
index 99ed77537..2c917cc59 100644
--- a/src/include/gnunet_constants.h
+++ b/src/include/gnunet_constants.h
@@ -49,6 +49,12 @@ extern "C"
49 */ 49 */
50#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) 50#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
51 51
52/**
53 * How long do we wait after a FORK+EXEC before testing for the
54 * resulting process to be up (port open, waitpid, etc.)?
55 */
56#define GNUNET_CONSTANTS_EXEC_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
57
52 58
53#if 0 /* keep Emacsens' auto-indent happy */ 59#if 0 /* keep Emacsens' auto-indent happy */
54{ 60{
diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h
index 7f463b83e..49f2ece48 100644
--- a/src/include/gnunet_disk_lib.h
+++ b/src/include/gnunet_disk_lib.h
@@ -126,7 +126,19 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle *h, off_t offset,
126 * @return GNUNET_OK on success, GNUNET_SYSERR on error 126 * @return GNUNET_OK on success, GNUNET_SYSERR on error
127 */ 127 */
128int GNUNET_DISK_file_size (const char *filename, 128int GNUNET_DISK_file_size (const char *filename,
129 unsigned long long *size, int includeSymLinks); 129 unsigned long long *size, int includeSymLinks);
130
131
132/**
133 * Create an (empty) temporary file on disk.
134 *
135 * @param template component to use for the name;
136 * does NOT contain "XXXXXX" or "/tmp/".
137 * @return NULL on error, otherwise name of fresh
138 * file on disk in directory for temporary files
139 */
140char *
141GNUNET_DISK_mktemp (const char *template);
130 142
131 143
132/** 144/**
diff --git a/src/include/gnunet_os_lib.h b/src/include/gnunet_os_lib.h
index cce805ba0..3af4f72a3 100644
--- a/src/include/gnunet_os_lib.h
+++ b/src/include/gnunet_os_lib.h
@@ -149,6 +149,7 @@ int GNUNET_OS_set_process_priority (pid_t proc,
149 */ 149 */
150pid_t GNUNET_OS_start_process (const char *filename, ...); 150pid_t GNUNET_OS_start_process (const char *filename, ...);
151 151
152
152/** 153/**
153 * Start a process. 154 * Start a process.
154 * 155 *
@@ -159,6 +160,7 @@ pid_t GNUNET_OS_start_process (const char *filename, ...);
159 */ 160 */
160pid_t GNUNET_OS_start_process_v (const char *filename, char *const argv[]); 161pid_t GNUNET_OS_start_process_v (const char *filename, char *const argv[]);
161 162
163
162/** 164/**
163 * Retrieve the status of a process 165 * Retrieve the status of a process
164 * @param proc process ID 166 * @param proc process ID
@@ -169,6 +171,7 @@ pid_t GNUNET_OS_start_process_v (const char *filename, char *const argv[]);
169int GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type, 171int GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type,
170 unsigned long *code); 172 unsigned long *code);
171 173
174
172/** 175/**
173 * Wait for a process 176 * Wait for a process
174 * @param proc process ID to wait for 177 * @param proc process ID to wait for
@@ -176,6 +179,7 @@ int GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type
176 */ 179 */
177int GNUNET_OS_process_wait (pid_t proc); 180int GNUNET_OS_process_wait (pid_t proc);
178 181
182
179#if 0 /* keep Emacsens' auto-indent happy */ 183#if 0 /* keep Emacsens' auto-indent happy */
180{ 184{
181#endif 185#endif
diff --git a/src/include/gnunet_testing_lib.h b/src/include/gnunet_testing_lib.h
index 782eb8741..a40457a5d 100644
--- a/src/include/gnunet_testing_lib.h
+++ b/src/include/gnunet_testing_lib.h
@@ -85,7 +85,7 @@ typedef void (*GNUNET_TESTING_NotifyDaemonRunning)(void *cls,
85 */ 85 */
86struct GNUNET_TESTING_Daemon * 86struct GNUNET_TESTING_Daemon *
87GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, 87GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
88 struct GNUNET_CONFIGURATION_Handle *cfg, 88 const struct GNUNET_CONFIGURATION_Handle *cfg,
89 const char *hostname, 89 const char *hostname,
90 GNUNET_TESTING_NotifyDaemonRunning cb, 90 GNUNET_TESTING_NotifyDaemonRunning cb,
91 void *cb_cls); 91 void *cb_cls);
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 598015340..e425171bb 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -30,8 +30,37 @@
30 */ 30 */
31#include "platform.h" 31#include "platform.h"
32#include "gnunet_arm_service.h" 32#include "gnunet_arm_service.h"
33#include "gnunet_constants.h"
33#include "gnunet_testing_lib.h" 34#include "gnunet_testing_lib.h"
34 35
36#define DEBUG_TESTING GNUNET_YES
37
38/**
39 * How long do we wait after starting gnunet-service-arm
40 * for the core service to be alive?
41 */
42#define GNUNET_ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
43
44/**
45 * How many times are we willing to try to
46 * wait for "scp" or "gnunet-service-arm" to
47 * complete (waitpid) before giving up?
48 */
49#define MAX_EXEC_WAIT_RUNS 50
50
51/**
52 * Phases of starting GNUnet on a system.
53 */
54enum StartPhase
55 {
56 SP_COPYING,
57 SP_COPIED,
58 SP_START_ARMING,
59 SP_START_CORE,
60 SP_START_DONE
61 };
62
63
35/** 64/**
36 * Handle for a GNUnet daemon (technically a set of 65 * Handle for a GNUnet daemon (technically a set of
37 * daemons; the handle is really for the master ARM 66 * daemons; the handle is really for the master ARM
@@ -39,10 +68,304 @@
39 */ 68 */
40struct GNUNET_TESTING_Daemon 69struct GNUNET_TESTING_Daemon
41{ 70{
71 /**
72 * Our scheduler.
73 */
74 struct GNUNET_SCHEDULER_Handle *sched;
75
76 /**
77 * Our configuration.
78 */
79 const struct GNUNET_CONFIGURATION_Handle *cfg;
80
81 /**
82 * Host to run GNUnet on.
83 */
84 char *hostname;
85
86 /**
87 * Username we are using.
88 */
89 char *username;
90
91 /**
92 * Name of the configuration file
93 */
94 char *cfgfile;
95
96 /**
97 * Function to call when the peer is running.
98 */
99 GNUNET_TESTING_NotifyDaemonRunning cb;
100
101 /**
102 * Closure for cb.
103 */
104 void *cb_cls;
105
106 /**
107 * Arguments from "daemon_stop" call.
108 */
109 GNUNET_TESTING_NotifyCompletion dead_cb;
110
111 /**
112 * Closure for 'dead_cb'.
113 */
114 void *dead_cb_cls;
115
116 /**
117 * Flag to indicate that we've already been asked
118 * to terminate (but could not because some action
119 * was still pending).
120 */
121 int dead;
122
123 /**
124 * PID of the process that we started last.
125 */
126 pid_t pid;
127
128 /**
129 * How many iterations have we been waiting for
130 * the started process to complete?
131 */
132 unsigned int wait_runs;
133
134 /**
135 * In which phase are we during the start of
136 * this process?
137 */
138 enum StartPhase phase;
139
140 /**
141 * ID of the current task.
142 */
143 GNUNET_SCHEDULER_Task task;
144
42}; 145};
43 146
44 147
45/** 148/**
149 * Function called after GNUNET_CORE_connect has succeeded
150 * (or failed for good). Note that the private key of the
151 * peer is intentionally not exposed here; if you need it,
152 * your process should try to read the private key file
153 * directly (which should work if you are authorized...).
154 *
155 * @param cls closure
156 * @param server handle to the server, NULL if we failed
157 * @param my_identity ID of this peer, NULL if we failed
158 * @param publicKey public key of this peer, NULL if we failed
159 */
160static void
161testing_init (void *cls,
162 struct GNUNET_CORE_Handle * server,
163 const struct GNUNET_PeerIdentity *
164 my_identity,
165 const struct
166 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
167 publicKey)
168{
169 struct GNUNET_TESTING_Daemon *d = cls;
170 GNUNET_TESTING_NotifyDaemonRunning cb;
171
172 d->phsae = SP_START_DONE;
173 cb = d->cb;
174 d->cb = NULL;
175 if (server == NULL)
176 {
177 cb (d->cb_cls, NULL, d->cfg, d,
178 _("Failed to connect to core service\n"));
179 if (GNUNET_YES == d->dead)
180 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls);
181 return;
182 }
183#if DEBUG_TESTING
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
185 "Successfully started peer `%4s'.\n",
186 GNUNET_i2s(my_identity));
187#endif
188 if (GNUNET_YES == d->dead)
189 GNUNET_TESTING_daemon_stop (d, d->dead_cb, d->dead_cb_cls);
190 else
191 cb (d->cb_cls, my_identity, d->cfg, d, NULL);
192}
193
194
195/**
196 * Finite-state machine for starting GNUnet.
197 *
198 * @param cls our "struct GNUNET_TESTING_Daemon"
199 * @param tc unused
200 */
201static void
202start_fsm (void *cls,
203 const struct GNUNET_SCHEDULER_TaskContext *tc)
204{
205 struct GNUNET_TESTING_Daemon * d = cls;
206 GNUNET_TESTING_NotifyDaemonRunning cb;
207 enum GNUNET_OS_ProcessStatusType type;
208 unsigned long code;
209 char *dst;
210
211 d->task = GNUNET_SCHEDULER_NO_TASK;
212 switch (d->phase)
213 {
214 case SP_COPYING:
215 /* confirm copying complete */
216 if (GNUNET_OK !=
217 GNUNET_OS_process_status (d->pid,
218 &type,
219 &code))
220 {
221 d->wait_runs++;
222 if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
223 {
224 cb = d->cb;
225 d->cb = NULL;
226 cb (d->cb_cls,
227 NULL,
228 d->cfg,
229 d,
230 _("`scp' does not seem to terminate.\n"));
231 return;
232 }
233 /* wait some more */
234 d->task
235 = GNUNET_SCHEDULER_add_delayed (sched,
236 GNUNET_NO,
237 GNUNET_SCHEDULER_PRIORITY_KEEP,
238 GNUNET_SCHEDULER_NO_TASK,
239 GNUNET_CONSTANTS_EXEC_WAIT,
240 &start_fsm,
241 d);
242 return;
243 }
244 if ( (type != GNUNET_OS_PROCESS_EXITED) ||
245 (code != 0) )
246 {
247 cb = d->cb;
248 d->cb = NULL;
249 cb (d->cb_cls,
250 NULL,
251 d->cfg,
252 d,
253 _("`scp' did not complete cleanly.\n"));
254 return;
255 }
256#if DEBUG_TESTING
257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
258 "Successfully copied configuration file.\n");
259#endif
260 d->phase = SP_COPIED;
261 /* fall-through */
262 case SP_COPIED:
263 /* start GNUnet on remote host */
264 if (NULL == hostname)
265 {
266 d->pid = GNUNET_OS_start_process ("gnunet-service-arm",
267 "gnunet-service-arm",
268 "-c",
269 d->cfgfile,
270 "-d",
271 NULL);
272 }
273 else
274 {
275 if (username != NULL)
276 GNUNET_asprintf (&dst,
277 "%s@%s",
278 username,
279 hostname);
280 else
281 dst = GNUNET_strdup (hostname);
282 d->pid = GNUNET_OS_start_process ("ssh",
283 "ssh",
284 dst,
285 "gnunet-service-arm",
286 "-c",
287 d->cfgfile,
288 "-d",
289 NULL);
290 GNUNET_free (dst);
291 }
292 if (-1 == d->pid)
293 {
294 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
295 _("Could not start `%s' process to start GNUnet.\n"),
296 (NULL == hostname) ? "gnunet-service-arm" : "ssh");
297 cb = d->cb;
298 d->cb = NULL;
299 cb (d->cb_cls,
300 NULL,
301 d->cfg,
302 d,
303 (NULL == d->hostname)
304 ? _("Failed to start `gnunet-service-arm' process.\n")
305 : _("Failed to start `ssh' process.\n"));
306 }
307 d->phase = SP_START_ARMING;
308 d->wait_runs = 0;
309 break;
310 case SP_START_ARMING:
311 if (GNUNET_OK !=
312 GNUNET_OS_process_status (d->pid,
313 &type,
314 &code))
315 {
316 d->wait_runs++;
317 if (d->wait_runs > MAX_EXEC_WAIT_RUNS)
318 {
319 cb = d->cb;
320 d->cb = NULL;
321 cb (d->cb_cls,
322 NULL,
323 d->cfg,
324 d,
325 (NULL == d->hostname)
326 ? _("`gnunet-service-arm' does not seem to terminate.\n")
327 : _("`ssh' does not seem to terminate.\n"));
328 return;
329 }
330 /* wait some more */
331 d->task
332 = GNUNET_SCHEDULER_add_delayed (sched,
333 GNUNET_NO,
334 GNUNET_SCHEDULER_PRIORITY_KEEP,
335 GNUNET_SCHEDULER_NO_TASK,
336 GNUNET_CONSTANTS_EXEC_WAIT,
337 &start_fsm,
338 d);
339 return;
340 }
341#if DEBUG_TESTING
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Successfully started `%s'.\n",
344 "gnunet-service-arm");
345#endif
346 d->phase = SP_START_CORE;
347 GNUNET_CORE_connect (d->sched,
348 d->cfg,
349 timeout,
350 d,
351 &testing_init,
352 NULL, NULL, NULL,
353 NULL, GNUNET_NO,
354 NULL, GNUNET_NO,
355 no_handlers);
356 break;
357 case SP_START_CORE:
358 GNUNET_break (0);
359 break;
360 case SP_START_DONE:
361 GNUNET_break (0);
362 break;
363 }
364 return ret;
365}
366
367
368/**
46 * Starts a GNUnet daemon. GNUnet must be installed on the target 369 * Starts a GNUnet daemon. GNUnet must be installed on the target
47 * system and available in the PATH. The machine must furthermore be 370 * system and available in the PATH. The machine must furthermore be
48 * reachable via "ssh" (unless the hostname is "NULL") without the 371 * reachable via "ssh" (unless the hostname is "NULL") without the
@@ -58,12 +381,111 @@ struct GNUNET_TESTING_Daemon
58 */ 381 */
59struct GNUNET_TESTING_Daemon * 382struct GNUNET_TESTING_Daemon *
60GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, 383GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched,
61 struct GNUNET_CONFIGURATION_Handle *cfg, 384 const struct GNUNET_CONFIGURATION_Handle *cfg,
62 const char *hostname, 385 const char *hostname,
63 GNUNET_TESTING_NotifyDaemonRunning cb, 386 GNUNET_TESTING_NotifyDaemonRunning cb,
64 void *cb_cls) 387 void *cb_cls)
65{ 388{
66 return NULL; 389 static struct GNUNET_CORE_MessageHandler no_handlers[] =
390 { NULL, 0, 0 };
391 struct GNUNET_TESTING_Daemon * ret;
392 char *arg;
393 char *username;
394 int unused;
395
396 ret = GNUNET_malloc (sizeof(struct GNUNET_TESTING_Daemon));
397 ret->sched = sched;
398 ret->cfg = cfg;
399 ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname);
400 ret->cfgfile = GNUNET_DISK_mktemp ("gnunet-testing-config");
401 if (NULL == ret->cfgfile)
402 {
403 GNUNET_free_non_null (ret->hostname);
404 GNUNET_free (ret);
405 return NULL;
406 }
407 ret->cb = cb;
408 ret->cb_cls = cb_cls;
409 /* 1) write configuration to temporary file */
410 if (GNUNET_OK !=
411 GNUNET_CONFIGURATION_write (cfg,
412 ret->cfgfile))
413 {
414 if (0 != UNLINK (ret->cfgfile))
415 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
416 "unlink",
417 ret->cfgfile);
418 GNUNET_free_non_null (ret->hostname);
419 GNUNET_free (ret->cfgfile);
420 GNUNET_free (ret);
421 return NULL;
422 }
423 if (GNUNET_OK !=
424 GNUNET_CONFIGURATION_get_value_string (cfg,
425 "TESTING",
426 "USERNAME",
427 &username))
428 {
429 if (NULL != getenv ("USER"))
430 username = GNUNET_strdup (getenv("USER"));
431 else
432 username = NULL;
433 }
434 ret->username = username;
435
436 /* 2) copy file to remote host */
437 if (NULL != hostname)
438 {
439 ret->phase = SP_COPYING;
440 if (NULL != username)
441 GNUNET_asprintf (&arg,
442 "%s@%s:%s",
443 username,
444 hostname,
445 ret->cfgfile);
446 else
447 GNUNET_asprintf (&arg,
448 "%s:%s",
449 hostname,
450 ret->cfgfile);
451 ret->pid = GNUNET_OS_start_process ("scp",
452 "scp",
453 ret->cfgfile,
454 arg,
455 NULL);
456 if (-1 == ret->pid)
457 {
458 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
459 _("Could not start `%s' process to copy configuration file.\n"),
460 "scp");
461 if (0 != UNLINK (ret->cfgfile))
462 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
463 "unlink",
464 ret->cfgfile);
465 GNUNET_free_non_null (ret->hostname);
466 GNUNET_free_non_null (ret->username);
467 GNUNET_free (ret->cfgfile);
468 GNUNET_free (ret);
469 return NULL;
470 }
471 ret->task
472 = GNUNET_SCHEDULER_add_delayed (sched,
473 GNUNET_NO,
474 GNUNET_SCHEDULER_PRIORITY_KEEP,
475 GNUNET_SCHEDULER_NO_TASK,
476 GNUNET_CONSTANTS_EXEC_WAIT,
477 &start_fsm,
478 ret);
479 GNUNET_free (arg);
480 return;
481 }
482 ret->phase = SP_COPIED;
483 ret->task
484 = GNUNET_SCHEDULER_add_continuation (sched,
485 GNUNET_NO,
486 &start_fsm,
487 ret,
488 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
67} 489}
68 490
69 491
@@ -78,6 +500,108 @@ void GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
78 GNUNET_TESTING_NotifyCompletion cb, 500 GNUNET_TESTING_NotifyCompletion cb,
79 void * cb_cls) 501 void * cb_cls)
80{ 502{
503 if (NULL != d->cb)
504 {
505 d->dead = GNUNET_YES;
506 d->dead_cb = cb;
507 d->dead_cb_cls = cb_cls;
508 return;
509 }
510
511 /* FIXME: shutdown processes! */
512 char *cmd;
513 int length;
514 unsigned int is_local = 0;
515 int unused;
516 FILE *output;
517 pid_t pid;
518
519 if (strcmp (tokill->hostname, "localhost") == 0)
520 {
521 is_local = 1;
522 }
523
524 if (is_local)
525 {
526 length = snprintf (NULL, 0, "cat %s", tokill->pid);
527 cmd = GNUNET_malloc (length + 1);
528 snprintf (cmd, length + 1, "cat %s", tokill->pid);
529 }
530 else
531 {
532 length =
533 snprintf (NULL, 0, "ssh %s@%s cat %s", tokill->username,
534 tokill->hostname, tokill->pid);
535 cmd = GNUNET_malloc (length + 1);
536 snprintf (cmd, length + 1, "ssh %s@%s cat %s", tokill->username,
537 tokill->hostname, tokill->pid);
538 }
539#if VERBOSE
540 fprintf (stderr, _("exec command is : %s \n"), cmd);
541#endif
542
543 output = popen (cmd, "r");
544 GNUNET_free (cmd);
545 if (fscanf (output, "%d", &pid) == 1)
546 {
547#if VERBOSE
548 fprintf (stderr, _("Got pid %d\n"), pid);
549#endif
550 }
551 else
552 {
553 return -1;
554 }
555
556 if (is_local)
557 {
558 length = snprintf (NULL, 0, "kill %d", pid);
559 cmd = GNUNET_malloc (length + 1);
560 snprintf (cmd, length + 1, "kill %d", pid);
561 }
562 else
563 {
564 length =
565 snprintf (NULL, 0, "ssh %s@%s kill %d", tokill->username,
566 tokill->hostname, pid);
567 cmd = GNUNET_malloc (length + 1);
568 snprintf (cmd, length + 1, "ssh %s@%s kill %d",
569 tokill->username, tokill->hostname, pid);
570
571 }
572#if VERBOSE
573 fprintf (stderr, _("exec command is : %s \n"), cmd);
574#endif
575
576 unused = system (cmd);
577
578 GNUNET_free (cmd);
579
580 /* state clean up and notifications */
581 if (0 != UNLINK (d->cfgfile))
582 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
583 "unlink",
584 d->cfgfile);
585 if (d->hostname != NULL)
586 {
587 GNUNET_asprintf (&cmd,
588 "ssh %s@%s rm %s &",
589 d->username,
590 d->hostname,
591 d->cfgfile);
592#if DEBUG_TESTING
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594 _("exec command is: `%s'\n"),
595 cmd);
596#endif
597 unused = system (cmd);
598 GNUNET_free (cmd);
599 }
600 GNUNET_free (d->cfgfile);
601 GNUNET_free_non_null (d->hostname);
602 GNUNET_free_non_null (d->username);
603 GNUNET_free (d);
604 cb (cb_cls, NULL);
81} 605}
82 606
83 607
@@ -94,6 +618,7 @@ void GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
94 GNUNET_TESTING_NotifyCompletion cb, 618 GNUNET_TESTING_NotifyCompletion cb,
95 void * cb_cls) 619 void * cb_cls)
96{ 620{
621 cb (cb_cls, "not implemented");
97} 622}
98 623
99 624
diff --git a/src/util/disk.c b/src/util/disk.c
index 857370c5b..738839807 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -194,6 +194,52 @@ GNUNET_DISK_file_size (const char *filename,
194 194
195 195
196/** 196/**
197 * Create an (empty) temporary file on disk.
198 *
199 * @param template component to use for the name;
200 * does NOT contain "XXXXXX" or "/tmp/".
201 * @return NULL on error, otherwise name of fresh
202 * file on disk in directory for temporary files
203 */
204char *
205GNUNET_DISK_mktemp (const char *template)
206{
207 const char *tmpdir;
208 int fd;
209 char *tmpl;
210 char *fn;
211
212 tmpdir = getenv ("TMPDIR");
213 tmpdir = tmpdir ? tmpdir : "/tmp";
214
215 GNUNET_asprintf (&tmpl,
216 "%s%s%s%s",
217 tmpdir,
218 DIR_SEPARATOR_STR,
219 template,
220 "XXXXXX");
221#ifdef MINGW
222 fn = (char *) GNUNET_malloc (MAX_PATH + 1);
223 plibc_conv_to_win_path (tmpl, fn);
224 GNUNET_free (tmpl);
225#else
226 fn = tmpl;
227#endif
228 fd = mkstemp (fn);
229 if (fd == -1)
230 {
231 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
232 "mkstemp",
233 fn);
234 GNUNET_free (fn);
235 return NULL;
236 }
237 CLOSE (fd);
238 return fn;
239}
240
241
242/**
197 * Get the number of blocks that are left on the partition that 243 * Get the number of blocks that are left on the partition that
198 * contains the given file (for normal users). 244 * contains the given file (for normal users).
199 * 245 *