This source file includes following definitions.
- cfcon
- cfdes
- cdcon
- cddes
- nscon
- nsdes
- ncdcon
- ncddes
- info_con
- info_des
- pcon
- pdes
- iofreqcon
- iofreqdes
- scon
- scdes
- cbcon
- cbdes
- ifcon
- ifdes
- qcon
- qdes
- pmix_execute_epilog
- dirpath_destroy
- dirpath_is_empty
- pmix_event_assign
- pmix_event_new
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <src/include/pmix_config.h>
21
22 #include <pmix_common.h>
23 #include <src/include/types.h>
24 #include <src/include/pmix_stdint.h>
25 #include <src/include/pmix_socket_errno.h>
26
27 #include "src/include/pmix_globals.h"
28
29 #ifdef HAVE_STRING_H
30 #include <string.h>
31 #endif
32 #include <fcntl.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
38 #endif
39 #include <ctype.h>
40 #include PMIX_EVENT_HEADER
41 #if HAVE_SYS_STAT_H
42 #include <sys/stat.h>
43 #endif
44 #ifdef HAVE_DIRENT_H
45 #include <dirent.h>
46 #endif
47
48 #include <pmix_common.h>
49
50 #include "src/mca/bfrops/bfrops_types.h"
51 #include "src/class/pmix_hash_table.h"
52 #include "src/class/pmix_list.h"
53 #include "src/threads/threads.h"
54 #include "src/util/argv.h"
55 #include "src/util/os_path.h"
56
57 static void dirpath_destroy(char *path, pmix_cleanup_dir_t *cd,
58 pmix_epilog_t *epi);
59 static bool dirpath_is_empty(const char *path);
60
61 PMIX_EXPORT pmix_lock_t pmix_global_lock = {
62 .mutex = PMIX_MUTEX_STATIC_INIT,
63 .cond = PMIX_CONDITION_STATIC_INIT,
64 .active = false
65 };
66
67 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_namelist_t,
68 pmix_list_item_t,
69 NULL, NULL);
70
71 static void cfcon(pmix_cleanup_file_t *p)
72 {
73 p->path = NULL;
74 }
75 static void cfdes(pmix_cleanup_file_t *p)
76 {
77 if (NULL != p->path) {
78 free(p->path);
79 }
80 }
81 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_cleanup_file_t,
82 pmix_list_item_t,
83 cfcon, cfdes);
84
85 static void cdcon(pmix_cleanup_dir_t *p)
86 {
87 p->path = NULL;
88 p->recurse = false;
89 p->leave_topdir = false;
90 }
91 static void cddes(pmix_cleanup_dir_t *p)
92 {
93 if (NULL != p->path) {
94 free(p->path);
95 }
96 }
97 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_cleanup_dir_t,
98 pmix_list_item_t,
99 cdcon, cddes);
100
101 static void nscon(pmix_namespace_t *p)
102 {
103 p->nspace = NULL;
104 p->nprocs = 0;
105 p->nlocalprocs = 0;
106 p->all_registered = false;
107 p->version_stored = false;
108 p->jobbkt = NULL;
109 p->ndelivered = 0;
110 p->nfinalized = 0;
111 PMIX_CONSTRUCT(&p->ranks, pmix_list_t);
112 memset(&p->compat, 0, sizeof(p->compat));
113 PMIX_CONSTRUCT(&p->epilog.cleanup_dirs, pmix_list_t);
114 PMIX_CONSTRUCT(&p->epilog.cleanup_files, pmix_list_t);
115 PMIX_CONSTRUCT(&p->epilog.ignores, pmix_list_t);
116 PMIX_CONSTRUCT(&p->setup_data, pmix_list_t);
117 }
118 static void nsdes(pmix_namespace_t *p)
119 {
120 if (NULL != p->nspace) {
121 free(p->nspace);
122 }
123 if (NULL != p->jobbkt) {
124 PMIX_RELEASE(p->jobbkt);
125 }
126 PMIX_LIST_DESTRUCT(&p->ranks);
127
128 pmix_execute_epilog(&p->epilog);
129
130 PMIX_LIST_DESTRUCT(&p->epilog.cleanup_dirs);
131 PMIX_LIST_DESTRUCT(&p->epilog.cleanup_files);
132 PMIX_LIST_DESTRUCT(&p->epilog.ignores);
133 PMIX_LIST_DESTRUCT(&p->setup_data);
134 }
135 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_namespace_t,
136 pmix_list_item_t,
137 nscon, nsdes);
138
139 static void ncdcon(pmix_nspace_caddy_t *p)
140 {
141 p->ns = NULL;
142 }
143 static void ncddes(pmix_nspace_caddy_t *p)
144 {
145 if (NULL != p->ns) {
146 PMIX_RELEASE(p->ns);
147 }
148 }
149 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_nspace_caddy_t,
150 pmix_list_item_t,
151 ncdcon, ncddes);
152
153 static void info_con(pmix_rank_info_t *info)
154 {
155 info->peerid = -1;
156 info->gid = info->uid = 0;
157 info->pname.nspace = NULL;
158 info->pname.rank = PMIX_RANK_UNDEF;
159 info->modex_recvd = false;
160 info->proc_cnt = 0;
161 info->server_object = NULL;
162 }
163 static void info_des(pmix_rank_info_t *info)
164 {
165 if (NULL != info->pname.nspace) {
166 free(info->pname.nspace);
167 }
168 }
169 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_rank_info_t,
170 pmix_list_item_t,
171 info_con, info_des);
172
173 static void pcon(pmix_peer_t *p)
174 {
175 p->proc_type = PMIX_PROC_UNDEF;
176 p->protocol = PMIX_PROTOCOL_UNDEF;
177 p->finalized = false;
178 p->info = NULL;
179 p->proc_cnt = 0;
180 p->index = 0;
181 p->sd = -1;
182 p->send_ev_active = false;
183 p->recv_ev_active = false;
184 PMIX_CONSTRUCT(&p->send_queue, pmix_list_t);
185 p->send_msg = NULL;
186 p->recv_msg = NULL;
187 p->commit_cnt = 0;
188 PMIX_CONSTRUCT(&p->epilog.cleanup_dirs, pmix_list_t);
189 PMIX_CONSTRUCT(&p->epilog.cleanup_files, pmix_list_t);
190 PMIX_CONSTRUCT(&p->epilog.ignores, pmix_list_t);
191
192 }
193
194 static void pdes(pmix_peer_t *p)
195 {
196 if (0 <= p->sd) {
197 CLOSE_THE_SOCKET(p->sd);
198 }
199 if (p->send_ev_active) {
200 pmix_event_del(&p->send_event);
201 }
202 if (p->recv_ev_active) {
203 pmix_event_del(&p->recv_event);
204 }
205
206 if (NULL != p->info) {
207 PMIX_RELEASE(p->info);
208 }
209
210 PMIX_LIST_DESTRUCT(&p->send_queue);
211 if (NULL != p->send_msg) {
212 PMIX_RELEASE(p->send_msg);
213 }
214 if (NULL != p->recv_msg) {
215 PMIX_RELEASE(p->recv_msg);
216 }
217
218 pmix_execute_epilog(&p->epilog);
219
220 PMIX_LIST_DESTRUCT(&p->epilog.cleanup_dirs);
221 PMIX_LIST_DESTRUCT(&p->epilog.cleanup_files);
222 PMIX_LIST_DESTRUCT(&p->epilog.ignores);
223 if (NULL != p->nptr) {
224 PMIX_RELEASE(p->nptr);
225 }
226 }
227 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_peer_t,
228 pmix_object_t,
229 pcon, pdes);
230
231 static void iofreqcon(pmix_iof_req_t *p)
232 {
233 p->peer = NULL;
234 memset(&p->pname, 0, sizeof(pmix_name_t));
235 p->channels = PMIX_FWD_NO_CHANNELS;
236 p->cbfunc = NULL;
237 }
238 static void iofreqdes(pmix_iof_req_t *p)
239 {
240 if (NULL != p->peer) {
241 PMIX_RELEASE(p->peer);
242 }
243 if (NULL != p->pname.nspace) {
244 free(p->pname.nspace);
245 }
246 }
247 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_iof_req_t,
248 pmix_list_item_t,
249 iofreqcon, iofreqdes);
250
251
252 static void scon(pmix_shift_caddy_t *p)
253 {
254 PMIX_CONSTRUCT_LOCK(&p->lock);
255 p->codes = NULL;
256 p->ncodes = 0;
257 p->pname.nspace = NULL;
258 p->pname.rank = PMIX_RANK_UNDEF;
259 p->data = NULL;
260 p->ndata = 0;
261 p->key = NULL;
262 p->info = NULL;
263 p->ninfo = 0;
264 p->directives = NULL;
265 p->ndirs = 0;
266 p->evhdlr = NULL;
267 p->iofreq = NULL;
268 p->kv = NULL;
269 p->vptr = NULL;
270 p->cd = NULL;
271 p->tracker = NULL;
272 p->enviro = false;
273 p->cbfunc.relfn = NULL;
274 p->cbdata = NULL;
275 p->ref = 0;
276 }
277 static void scdes(pmix_shift_caddy_t *p)
278 {
279 PMIX_DESTRUCT_LOCK(&p->lock);
280 if (NULL != p->pname.nspace) {
281 free(p->pname.nspace);
282 }
283 if (NULL != p->kv) {
284 PMIX_RELEASE(p->kv);
285 }
286 }
287 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_shift_caddy_t,
288 pmix_object_t,
289 scon, scdes);
290
291 static void cbcon(pmix_cb_t *p)
292 {
293 PMIX_CONSTRUCT_LOCK(&p->lock);
294 p->checked = false;
295 PMIX_CONSTRUCT(&p->data, pmix_buffer_t);
296 p->cbfunc.ptlfn = NULL;
297 p->cbdata = NULL;
298 p->pname.nspace = NULL;
299 p->pname.rank = PMIX_RANK_UNDEF;
300 p->scope = PMIX_SCOPE_UNDEF;
301 p->key = NULL;
302 p->value = NULL;
303 p->procs = NULL;
304 p->nprocs = 0;
305 p->info = NULL;
306 p->ninfo = 0;
307 p->nvals = 0;
308 PMIX_CONSTRUCT(&p->kvs, pmix_list_t);
309 p->copy = false;
310 p->timer_running = false;
311 }
312 static void cbdes(pmix_cb_t *p)
313 {
314 if (p->timer_running) {
315 pmix_event_del(&p->ev);
316 }
317 if (NULL != p->pname.nspace) {
318 free(p->pname.nspace);
319 }
320 PMIX_DESTRUCT(&p->data);
321 PMIX_LIST_DESTRUCT(&p->kvs);
322 }
323 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_cb_t,
324 pmix_list_item_t,
325 cbcon, cbdes);
326
327 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_info_caddy_t,
328 pmix_list_item_t,
329 NULL, NULL);
330
331 static void ifcon(pmix_infolist_t *p)
332 {
333 PMIX_INFO_CONSTRUCT(&p->info);
334 }
335 static void ifdes(pmix_infolist_t *p)
336 {
337 PMIX_INFO_DESTRUCT(&p->info);
338 }
339 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_infolist_t,
340 pmix_list_item_t,
341 ifcon, ifdes);
342
343 static void qcon(pmix_query_caddy_t *p)
344 {
345 PMIX_CONSTRUCT_LOCK(&p->lock);
346 p->queries = NULL;
347 p->nqueries = 0;
348 p->targets = NULL;
349 p->ntargets = 0;
350 p->info = NULL;
351 p->ninfo = 0;
352 PMIX_BYTE_OBJECT_CONSTRUCT(&p->bo);
353 PMIX_CONSTRUCT(&p->results, pmix_list_t);
354 p->cbfunc = NULL;
355 p->valcbfunc = NULL;
356 p->cbdata = NULL;
357 p->relcbfunc = NULL;
358 p->credcbfunc = NULL;
359 p->validcbfunc = NULL;
360 }
361 static void qdes(pmix_query_caddy_t *p)
362 {
363 PMIX_DESTRUCT_LOCK(&p->lock);
364 PMIX_BYTE_OBJECT_DESTRUCT(&p->bo);
365 PMIX_PROC_FREE(p->targets, p->ntargets);
366 PMIX_INFO_FREE(p->info, p->ninfo);
367 PMIX_LIST_DESTRUCT(&p->results);
368 }
369 PMIX_EXPORT PMIX_CLASS_INSTANCE(pmix_query_caddy_t,
370 pmix_object_t,
371 qcon, qdes);
372
373 void pmix_execute_epilog(pmix_epilog_t *epi)
374 {
375 pmix_cleanup_file_t *cf, *cfnext;
376 pmix_cleanup_dir_t *cd, *cdnext;
377 struct stat statbuf;
378 int rc;
379 char **tmp;
380 size_t n;
381
382
383 PMIX_LIST_FOREACH_SAFE(cf, cfnext, &epi->cleanup_files, pmix_cleanup_file_t) {
384
385
386
387 tmp = pmix_argv_split(cf->path, ',');
388 for (n=0; NULL != tmp[n]; n++) {
389 rc = stat(tmp[n], &statbuf);
390 if (0 != rc) {
391 pmix_output_verbose(10, pmix_globals.debug_output,
392 "File %s failed to stat: %d", tmp[n], rc);
393 continue;
394 }
395 if (statbuf.st_uid != epi->uid ||
396 statbuf.st_gid != epi->gid) {
397 pmix_output_verbose(10, pmix_globals.debug_output,
398 "File %s uid/gid doesn't match: uid %lu(%lu) gid %lu(%lu)",
399 cf->path,
400 (unsigned long)statbuf.st_uid, (unsigned long)epi->uid,
401 (unsigned long)statbuf.st_gid, (unsigned long)epi->gid);
402 continue;
403 }
404 rc = unlink(tmp[n]);
405 if (0 != rc) {
406 pmix_output_verbose(10, pmix_globals.debug_output,
407 "File %s failed to unlink: %d", tmp[n], rc);
408 }
409 }
410 pmix_argv_free(tmp);
411 pmix_list_remove_item(&epi->cleanup_files, &cf->super);
412 PMIX_RELEASE(cf);
413 }
414
415
416 PMIX_LIST_FOREACH_SAFE(cd, cdnext, &epi->cleanup_dirs, pmix_cleanup_dir_t) {
417
418
419
420 tmp = pmix_argv_split(cd->path, ',');
421 for (n=0; NULL != tmp[n]; n++) {
422 rc = stat(tmp[n], &statbuf);
423 if (0 != rc) {
424 pmix_output_verbose(10, pmix_globals.debug_output,
425 "Directory %s failed to stat: %d", tmp[n], rc);
426 continue;
427 }
428 if (statbuf.st_uid != epi->uid ||
429 statbuf.st_gid != epi->gid) {
430 pmix_output_verbose(10, pmix_globals.debug_output,
431 "Directory %s uid/gid doesn't match: uid %lu(%lu) gid %lu(%lu)",
432 cd->path,
433 (unsigned long)statbuf.st_uid, (unsigned long)epi->uid,
434 (unsigned long)statbuf.st_gid, (unsigned long)epi->gid);
435 continue;
436 }
437 if ((statbuf.st_mode & S_IRWXU) == S_IRWXU) {
438 dirpath_destroy(tmp[n], cd, epi);
439 } else {
440 pmix_output_verbose(10, pmix_globals.debug_output,
441 "Directory %s lacks permissions", tmp[n]);
442 }
443 }
444 pmix_argv_free(tmp);
445 pmix_list_remove_item(&epi->cleanup_dirs, &cd->super);
446 PMIX_RELEASE(cd);
447 }
448 }
449
450 static void dirpath_destroy(char *path, pmix_cleanup_dir_t *cd, pmix_epilog_t *epi)
451 {
452 int rc;
453 bool is_dir = false;
454 DIR *dp;
455 struct dirent *ep;
456 char *filenm;
457 struct stat buf;
458 pmix_cleanup_file_t *cf;
459
460 if (NULL == path) {
461 return;
462 }
463
464
465 PMIX_LIST_FOREACH(cf, &epi->ignores, pmix_cleanup_file_t) {
466 if (0 == strcmp(cf->path, path)) {
467 return;
468 }
469 }
470
471
472 dp = opendir(path);
473 if (NULL == dp) {
474 return;
475 }
476
477 while (NULL != (ep = readdir(dp))) {
478
479
480
481 if ((0 == strcmp(ep->d_name, ".")) ||
482 (0 == strcmp(ep->d_name, ".."))) {
483 continue;
484 }
485
486
487
488
489
490 filenm = pmix_os_path(false, path, ep->d_name, NULL);
491
492
493 PMIX_LIST_FOREACH(cf, &epi->ignores, pmix_cleanup_file_t) {
494 if (0 == strcmp(cf->path, filenm)) {
495 free(filenm);
496 filenm = NULL;
497 break;
498 }
499 }
500 if (NULL == filenm) {
501 continue;
502 }
503
504
505 is_dir = false;
506
507 rc = stat(filenm, &buf);
508 if (0 > rc) {
509
510
511
512
513
514 free(filenm);
515 continue;
516 }
517
518 if (buf.st_uid != epi->uid ||
519 buf.st_gid != epi->gid) {
520 free(filenm);
521 continue;
522 }
523
524 if (S_ISDIR(buf.st_mode)) {
525 is_dir = true;
526 }
527
528
529
530
531
532 if (is_dir && !cd->recurse) {
533
534 free(filenm);
535 continue;
536 }
537
538
539 if (is_dir && cd->recurse && ((buf.st_mode & S_IRWXU) == S_IRWXU)) {
540 dirpath_destroy(filenm, cd, epi);
541 free(filenm);
542 } else {
543
544 unlink(filenm);
545 free(filenm);
546 }
547 }
548
549
550 closedir(dp);
551
552
553
554 if (0 == strcmp(path, cd->path) && cd->leave_topdir) {
555 return;
556 }
557 if (dirpath_is_empty(path)) {
558 rmdir(path);
559 }
560 }
561
562 static bool dirpath_is_empty(const char *path )
563 {
564 DIR *dp;
565 struct dirent *ep;
566
567 if (NULL != path) {
568 dp = opendir(path);
569 if (NULL != dp) {
570 while ((ep = readdir(dp))) {
571 if ((0 != strcmp(ep->d_name, ".")) &&
572 (0 != strcmp(ep->d_name, ".."))) {
573 closedir(dp);
574 return false;
575 }
576 }
577 closedir(dp);
578 return true;
579 }
580 return false;
581 }
582
583 return true;
584 }
585
586 int pmix_event_assign(struct event *ev, pmix_event_base_t *evbase,
587 int fd, short arg, event_callback_fn cbfn, void *cbd)
588 {
589 #if PMIX_HAVE_LIBEV
590 event_set(ev, fd, arg, cbfn, cbd);
591 event_base_set(evbase, ev);
592 #else
593 event_assign(ev, evbase, fd, arg, cbfn, cbd);
594 #endif
595 return 0;
596 }
597
598 pmix_event_t* pmix_event_new(pmix_event_base_t *b, int fd,
599 short fg, event_callback_fn cbfn, void *cbd)
600 {
601 pmix_event_t *ev = NULL;
602
603 #if PMIX_HAVE_LIBEV
604 ev = (pmix_event_t*)calloc(1, sizeof(pmix_event_t));
605 ev->ev_base = b;
606 #else
607 ev = event_new(b, fd, fg, (event_callback_fn) cbfn, cbd);
608 #endif
609
610 return ev;
611 }