This source file includes following definitions.
- pmix_path_is_absolute
- pmix_path_find
- pmix_path_findv
- pmix_path_access
- path_env_load
- list_env_get
- pmix_find_absolute_path
- pmix_check_mtab
- pmix_path_nfs
- pmix_path_df
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <src/include/pmix_config.h>
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #ifdef HAVE_SHLWAPI_H
36 #include <shlwapi.h>
37 #endif
38 #ifdef HAVE_SYS_PARAM_H
39 #include <sys/param.h>
40 #endif
41 #ifdef HAVE_SYS_MOUNT_H
42 #include <sys/mount.h>
43 #endif
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
46 #endif
47 #ifdef HAVE_SYS_STAT_H
48 #include <sys/stat.h>
49 #endif
50 #ifdef HAVE_SYS_VFS_H
51 #include <sys/vfs.h>
52 #endif
53 #ifdef HAVE_SYS_STATFS_H
54 #include <sys/statfs.h>
55 #endif
56 #ifdef HAVE_SYS_STATVFS_H
57 #include <sys/statvfs.h>
58 #endif
59 #ifdef HAVE_MNTENT_H
60 #include <mntent.h>
61 #endif
62 #ifdef HAVE_PATHS_H
63 #include <paths.h>
64 #endif
65
66 #ifdef _PATH_MOUNTED
67 #define MOUNTED_FILE _PATH_MOUNTED
68 #else
69 #define MOUNTED_FILE "/etc/mtab"
70 #endif
71
72
73 #include "src/include/pmix_stdint.h"
74 #include "src/util/output.h"
75 #include "src/util/path.h"
76 #include "src/util/os_path.h"
77 #include "src/util/argv.h"
78
79
80
81
82 #if !defined(HAVE_STATFS) && !defined(HAVE_STATVFS)
83 #error Must have either statfs() or statvfs()
84 #endif
85
86
87
88
89
90
91 #if defined(HAVE_STATFS) && \
92 (defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || \
93 defined(HAVE_STRUCT_STATFS_F_TYPE))
94 #define USE_STATFS 1
95 #endif
96
97 static void path_env_load(char *path, int *pargc, char ***pargv);
98 static char *list_env_get(char *var, char **list);
99
100 bool pmix_path_is_absolute( const char *path )
101 {
102 if( PMIX_PATH_SEP[0] == *path ) {
103 return true;
104 }
105 return false;
106 }
107
108
109
110
111 char *pmix_path_find(char *fname, char **pathv, int mode, char **envv)
112 {
113 char *fullpath;
114 char *delimit;
115 char *env;
116 char *pfix;
117 int i;
118
119
120 if( pmix_path_is_absolute(fname) ) {
121 return pmix_path_access(fname, NULL, mode);
122 }
123
124
125
126 fullpath = NULL;
127 i = 0;
128
129
130
131
132 while (pathv[i] && NULL == fullpath) {
133
134
135 if ('$' == *pathv[i]) {
136 delimit = strchr(pathv[i], PMIX_PATH_SEP[0]);
137 if (delimit) {
138 *delimit = '\0';
139 }
140 env = list_env_get(pathv[i]+1, envv);
141 if (delimit) {
142 *delimit = PMIX_PATH_SEP[0];
143 }
144 if (NULL != env) {
145 if (!delimit) {
146 fullpath = pmix_path_access(fname, env, mode);
147 } else {
148 pfix = (char*) malloc(strlen(env) + strlen(delimit) + 1);
149 if (NULL == pfix) {
150 return NULL;
151 }
152 strcpy(pfix, env);
153 strcat(pfix, delimit);
154 fullpath = pmix_path_access(fname, pfix, mode);
155 free(pfix);
156 }
157 }
158 }
159 else {
160 fullpath = pmix_path_access(fname, pathv[i], mode);
161 }
162 i++;
163 }
164 return pmix_make_filename_os_friendly(fullpath);
165 }
166
167
168
169
170 char *pmix_path_findv(char *fname, int mode, char **envv, char *wrkdir)
171 {
172 char **dirv;
173 char *fullpath;
174 char *path;
175 int dirc;
176 int i;
177 bool found_dot = false;
178
179
180
181 dirc = 0;
182 dirv = NULL;
183
184 if (NULL != (path = list_env_get("PATH", envv))) {
185 path_env_load(path, &dirc, &dirv);
186 }
187
188
189
190 if (NULL != wrkdir) {
191 for (i = 0; i < dirc; ++i) {
192 if (0 == strcmp(dirv[i], ".")) {
193 found_dot = true;
194 free(dirv[i]);
195 dirv[i] = strdup(wrkdir);
196 if (NULL == dirv[i]){
197 return NULL;
198 }
199 }
200 }
201 }
202
203
204
205
206 if (!found_dot && NULL != wrkdir) {
207 pmix_argv_append(&dirc, &dirv, wrkdir);
208 }
209
210 if(NULL == dirv)
211 return NULL;
212 fullpath = pmix_path_find(fname, dirv, mode, envv);
213 pmix_argv_free(dirv);
214 return fullpath;
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231 char *pmix_path_access(char *fname, char *path, int mode)
232 {
233 char *fullpath = NULL;
234 struct stat buf;
235
236
237 if (NULL == path) {
238 fullpath = pmix_os_path(false, fname, NULL);
239 } else {
240 fullpath = pmix_os_path(false, path, fname, NULL);
241 }
242 if (NULL == fullpath)
243 return NULL;
244
245
246
247
248 if (0 != stat(fullpath, &buf)) {
249
250
251
252 free(fullpath);
253 return NULL;
254 }
255
256 if (!(S_IFREG & buf.st_mode) &&
257 !(S_IFLNK & buf.st_mode)) {
258
259
260
261 free(fullpath);
262 return NULL;
263 }
264
265
266 if ((X_OK & mode) && !(S_IXUSR & buf.st_mode)) {
267
268
269
270 free(fullpath);
271 return NULL;
272 }
273 if ((R_OK & mode) && !(S_IRUSR & buf.st_mode)) {
274
275
276
277 free(fullpath);
278 return NULL;
279 }
280 if ((W_OK & mode) && !(S_IWUSR & buf.st_mode)) {
281
282
283
284 free(fullpath);
285 return NULL;
286 }
287
288
289 return fullpath;
290 }
291
292
293
294
295
296
297
298
299
300
301
302 static void path_env_load(char *path, int *pargc, char ***pargv)
303 {
304 char *p;
305 char saved;
306
307 if (NULL == path) {
308 *pargc = 0;
309 return;
310 }
311
312
313
314
315 while ('\0' != *path) {
316
317
318
319 for (p = path; *p && (*p != PMIX_ENV_SEP); ++p) {
320 continue;
321 }
322
323
324
325 if (p != path) {
326 saved = *p;
327 *p = '\0';
328 pmix_argv_append(pargc, pargv, path);
329 *p = saved;
330 path = p;
331 }
332
333
334
335 if (*path) {
336 ++path;
337 }
338 }
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353 static char *list_env_get(char *var, char **list)
354 {
355 size_t n;
356
357 if (NULL != list) {
358 n = strlen(var);
359
360 while (NULL != *list) {
361 if ((0 == strncmp(var, *list, n)) && ('=' == (*list)[n])) {
362 return (*list + n + 1);
363 }
364 ++list;
365 }
366 }
367 return getenv(var);
368 }
369
370
371
372
373
374
375
376
377
378
379
380 char* pmix_find_absolute_path( char* app_name )
381 {
382 char* abs_app_name;
383 char cwd[PMIX_PATH_MAX], *pcwd;
384
385 if( pmix_path_is_absolute(app_name) ) {
386 abs_app_name = app_name;
387 } else if ( '.' == app_name[0] ||
388 NULL != strchr(app_name, PMIX_PATH_SEP[0])) {
389
390 pcwd = getcwd( cwd, PMIX_PATH_MAX );
391 if( NULL == pcwd ) {
392
393 return NULL;
394 }
395 abs_app_name = pmix_os_path( false, pcwd, app_name, NULL );
396 } else {
397
398 abs_app_name = pmix_path_findv( app_name, X_OK, NULL, NULL );
399 }
400
401 if( NULL != abs_app_name ) {
402 char* resolved_path = (char*)malloc(PMIX_PATH_MAX);
403 if (NULL == realpath( abs_app_name, resolved_path )) {
404 free(resolved_path);
405 free(abs_app_name);
406 return NULL;
407 }
408 if( abs_app_name != app_name ) {
409 free(abs_app_name);
410 }
411 return resolved_path;
412 }
413 return NULL;
414 }
415
416
417
418
419
420
421
422 static char *pmix_check_mtab(char *dev_path)
423 {
424
425 #ifdef HAVE_MNTENT_H
426 FILE * mtab = NULL;
427 struct mntent * part = NULL;
428
429 if ((mtab = setmntent(MOUNTED_FILE, "r")) != NULL) {
430 while (NULL != (part = getmntent(mtab))) {
431 if ((NULL != part->mnt_dir) &&
432 (NULL != part->mnt_type) &&
433 (0 == strcmp(part->mnt_dir, dev_path)))
434 {
435 endmntent(mtab);
436 return strdup(part->mnt_type);
437 }
438 }
439 endmntent(mtab);
440 }
441 #endif
442 return NULL;
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490 #ifndef LL_SUPER_MAGIC
491 #define LL_SUPER_MAGIC 0x0BD00BD0
492 #endif
493 #ifndef NFS_SUPER_MAGIC
494 #define NFS_SUPER_MAGIC 0x6969
495 #endif
496 #ifndef PAN_KERNEL_FS_CLIENT_SUPER_MAGIC
497 #define PAN_KERNEL_FS_CLIENT_SUPER_MAGIC 0xAAD7AAEA
498 #endif
499 #ifndef GPFS_SUPER_MAGIC
500 #define GPFS_SUPER_MAGIC 0x47504653
501 #endif
502 #ifndef AUTOFS_SUPER_MAGIC
503 #define AUTOFS_SUPER_MAGIC 0x0187
504 #endif
505 #ifndef PVFS2_SUPER_MAGIC
506 #define PVFS2_SUPER_MAGIC 0x20030528
507 #endif
508
509 #define MASK2 0xffff
510 #define MASK4 0xffffffff
511
512 bool pmix_path_nfs(char *fname, char **ret_fstype)
513 {
514 int i;
515 int fsrc = -1;
516 int vfsrc = -1;
517 int trials;
518 char * file = strdup (fname);
519 #if defined(USE_STATFS)
520 struct statfs fsbuf;
521 #endif
522 #if defined(HAVE_STATVFS)
523 struct statvfs vfsbuf;
524 #endif
525
526
527
528
529 static struct fs_types_t {
530 unsigned long long f_fsid;
531 unsigned long long f_mask;
532 const char * f_fsname;
533 } fs_types[] = {
534 {LL_SUPER_MAGIC, MASK4, "lustre"},
535 {NFS_SUPER_MAGIC, MASK2, "nfs"},
536 {AUTOFS_SUPER_MAGIC, MASK2, "autofs"},
537 {PAN_KERNEL_FS_CLIENT_SUPER_MAGIC, MASK4, "panfs"},
538 {GPFS_SUPER_MAGIC, MASK4, "gpfs"},
539 {PVFS2_SUPER_MAGIC, MASK4, "pvfs2"}
540 };
541 #define FS_TYPES_NUM (int)(sizeof (fs_types)/sizeof (fs_types[0]))
542
543
544
545
546
547
548 again:
549 #if defined(USE_STATFS)
550 trials = 5;
551 do {
552 fsrc = statfs(file, &fsbuf);
553 } while (-1 == fsrc && ESTALE == errno && (0 < --trials));
554 #endif
555 #if defined(HAVE_STATVFS)
556 trials = 5;
557 do {
558 vfsrc = statvfs(file, &vfsbuf);
559 } while (-1 == vfsrc && ESTALE == errno && (0 < --trials));
560 #endif
561
562
563
564 if (-1 == fsrc && -1 == vfsrc) {
565 char * last_sep;
566
567 PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: stat(v)fs on file:%s failed errno:%d directory:%s\n",
568 fname, errno, file));
569 if (EPERM == errno) {
570 free(file);
571 if ( NULL != ret_fstype ) {
572 *ret_fstype = NULL;
573 }
574 return false;
575 }
576
577 last_sep = strrchr(file, PMIX_PATH_SEP[0]);
578
579 if (NULL == last_sep || (1 == strlen(last_sep) &&
580 PMIX_PATH_SEP[0] == *last_sep)) {
581 free (file);
582 if ( NULL != ret_fstype ) {
583 *ret_fstype=NULL;
584 }
585 return false;
586 }
587 *last_sep = '\0';
588
589 goto again;
590 }
591
592
593 for (i = 0; i < FS_TYPES_NUM; i++) {
594 #if defined(USE_STATFS)
595
596 # if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME)
597 if (0 == fsrc &&
598 0 == strncasecmp(fs_types[i].f_fsname, fsbuf.f_fstypename,
599 sizeof(fsbuf.f_fstypename))) {
600 goto found;
601 }
602 # endif
603 # if defined(HAVE_STRUCT_STATFS_F_TYPE)
604 if (0 == fsrc &&
605 fs_types[i].f_fsid == (fsbuf.f_type & fs_types[i].f_mask)) {
606 goto found;
607 }
608 # endif
609 #endif
610
611 #if defined(HAVE_STATVFS)
612
613 # if defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
614 if (0 == vfsrc &&
615 0 == strncasecmp(fs_types[i].f_fsname, vfsbuf.f_basetype,
616 sizeof(vfsbuf.f_basetype))) {
617 goto found;
618 }
619 # endif
620 # if defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
621 if (0 == vfsrc &&
622 0 == strncasecmp(fs_types[i].f_fsname, vfsbuf.f_fstypename,
623 sizeof(vfsbuf.f_fstypename))) {
624 goto found;
625 }
626 # endif
627 #endif
628 }
629
630 free (file);
631 if ( NULL != ret_fstype ) {
632 *ret_fstype=NULL;
633 }
634 return false;
635
636 #if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || \
637 defined(HAVE_STRUCT_STATFS_F_TYPE) || \
638 defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || \
639 defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)
640 found:
641 #endif
642
643 free (file);
644 if (AUTOFS_SUPER_MAGIC == fs_types[i].f_fsid) {
645 char *fs_type = pmix_check_mtab(fname);
646 int x;
647 if (NULL != fs_type) {
648 for (x = 0; x < FS_TYPES_NUM; x++) {
649 if (AUTOFS_SUPER_MAGIC == fs_types[x].f_fsid) {
650 continue;
651 }
652 if (0 == strcasecmp(fs_types[x].f_fsname, fs_type)) {
653 PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: file:%s on fs:%s\n", fname, fs_type));
654 free(fs_type);
655 if ( NULL != ret_fstype ) {
656 *ret_fstype = strdup(fs_types[x].f_fsname);
657 }
658 return true;
659 }
660 }
661 free(fs_type);
662 if ( NULL != ret_fstype ) {
663 *ret_fstype=NULL;
664 }
665 return false;
666 }
667 }
668
669 PMIX_OUTPUT_VERBOSE((10, 0, "pmix_path_nfs: file:%s on fs:%s\n",
670 fname, fs_types[i].f_fsname));
671 if ( NULL != ret_fstype ) {
672 *ret_fstype = strdup (fs_types[i].f_fsname);
673 }
674 return true;
675
676 #undef FS_TYPES_NUM
677 }
678
679 int
680 pmix_path_df(const char *path,
681 uint64_t *out_avail)
682 {
683 int rc = -1;
684 int trials = 5;
685 int err = 0;
686 #if defined(USE_STATFS)
687 struct statfs buf;
688 #elif defined(HAVE_STATVFS)
689 struct statvfs buf;
690 #endif
691
692 if (NULL == path || NULL == out_avail) {
693 return PMIX_ERROR;
694 }
695 *out_avail = 0;
696
697 do {
698 #if defined(USE_STATFS)
699 rc = statfs(path, &buf);
700 #elif defined(HAVE_STATVFS)
701 rc = statvfs(path, &buf);
702 #endif
703 err = errno;
704 } while (-1 == rc && ESTALE == err && (--trials > 0));
705
706 if (-1 == rc) {
707 PMIX_OUTPUT_VERBOSE((10, 2, "pmix_path_df: stat(v)fs on "
708 "path: %s failed with errno: %d (%s)\n",
709 path, err, strerror(err)));
710 return PMIX_ERROR;
711 }
712
713
714
715 *out_avail = buf.f_bsize * ((int)buf.f_bavail < 0 ? 0 : buf.f_bavail);
716
717 PMIX_OUTPUT_VERBOSE((10, 2, "pmix_path_df: stat(v)fs states "
718 "path: %s has %"PRIu64 " B of free space.",
719 path, *out_avail));
720
721 return PMIX_SUCCESS;
722 }