diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-07-27 20:07:24 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-07-27 20:07:24 +0000 |
commit | fe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4 (patch) | |
tree | 81738f3a8a167533ddf001a72809dfa5015186de /src | |
parent | c5cda378386d01412ada7fbf8d51317bab1ab695 (diff) | |
download | gnunet-fe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4.tar.gz gnunet-fe9ed98ff54df7d65dd0a0f787c86a734ef4d1a4.zip |
mktemp
Diffstat (limited to 'src')
-rw-r--r-- | src/datacache/datacache.c | 13 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_sqlite.c | 24 | ||||
-rw-r--r-- | src/include/gnunet_constants.h | 6 | ||||
-rw-r--r-- | src/include/gnunet_disk_lib.h | 14 | ||||
-rw-r--r-- | src/include/gnunet_os_lib.h | 4 | ||||
-rw-r--r-- | src/include/gnunet_testing_lib.h | 2 | ||||
-rw-r--r-- | src/testing/testing.c | 529 | ||||
-rw-r--r-- | src/util/disk.c | 46 |
8 files changed, 606 insertions, 32 deletions
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 | */ |
128 | int GNUNET_DISK_file_size (const char *filename, | 128 | int 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 | */ | ||
140 | char * | ||
141 | GNUNET_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 | */ |
150 | pid_t GNUNET_OS_start_process (const char *filename, ...); | 150 | pid_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 | */ |
160 | pid_t GNUNET_OS_start_process_v (const char *filename, char *const argv[]); | 161 | pid_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[]); | |||
169 | int GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type, | 171 | int 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 | */ |
177 | int GNUNET_OS_process_wait (pid_t proc); | 180 | int 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 | */ |
86 | struct GNUNET_TESTING_Daemon * | 86 | struct GNUNET_TESTING_Daemon * |
87 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | 87 | GNUNET_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 | */ | ||
54 | enum 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 | */ |
40 | struct GNUNET_TESTING_Daemon | 69 | struct 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 | */ | ||
160 | static void | ||
161 | testing_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 | */ | ||
201 | static void | ||
202 | start_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 | */ |
59 | struct GNUNET_TESTING_Daemon * | 382 | struct GNUNET_TESTING_Daemon * |
60 | GNUNET_TESTING_daemon_start (struct GNUNET_SCHEDULER_Handle *sched, | 383 | GNUNET_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 | */ | ||
204 | char * | ||
205 | GNUNET_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 | * |