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