root/opal/mca/pmix/pmix4x/pmix/src/util/path.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pmix_path_is_absolute
  2. pmix_path_find
  3. pmix_path_findv
  4. pmix_path_access
  5. path_env_load
  6. list_env_get
  7. pmix_find_absolute_path
  8. pmix_check_mtab
  9. pmix_path_nfs
  10. pmix_path_df

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2007 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2009-2014 Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2010      IBM Corporation.  All rights reserved.
  14  * Copyright (c) 2012-2013 Los Alamos National Security, LLC.
  15  *                         All rights reserved.
  16  * Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
  17  * Copyright (c) 2016      University of Houston. All rights reserved.
  18  * Copyright (c) 2018      Research Organization for Information Science
  19  *                         and Technology (RIST). All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  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  * Sanity check to ensure we have either statfs or statvfs
  81  */
  82 #if !defined(HAVE_STATFS) && !defined(HAVE_STATVFS)
  83 #error Must have either statfs() or statvfs()
  84 #endif
  85 
  86 /*
  87  * Note that some OS's (e.g., NetBSD and Solaris) have statfs(), but
  88  * no struct statfs (!).  So check to make sure we have struct statfs
  89  * before allowing the use of statfs().
  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  *  Locates a file with certain permissions
 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     /* If absolute path is given, return it without searching. */
 120     if( pmix_path_is_absolute(fname) ) {
 121         return pmix_path_access(fname, NULL, mode);
 122     }
 123 
 124     /* Initialize. */
 125 
 126     fullpath = NULL;
 127     i = 0;
 128 
 129     /* Consider each directory until the file is found.  Thus, the
 130        order of directories is important. */
 131 
 132     while (pathv[i] && NULL == fullpath) {
 133 
 134         /* Replace environment variable at the head of the string. */
 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  * Locates a file with certain permissions from a list of search paths
 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     /* Set the local search paths. */
 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     /* Replace the "." path by the working directory. */
 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     /* If we didn't find "." in the path and we have a wrkdir, append
 204        the wrkdir to the end of the path */
 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  *  Forms a complete pathname and checks it for existance and
 220  *  permissions
 221  *
 222  *  Accepts:
 223  *      -fname File name
 224  *      -path  Path prefix
 225  *      -mode  Target permissions which must be satisfied
 226  *
 227  *  Returns:
 228  *      -Full pathname of located file Success
 229  *      -NULL Failure
 230  */
 231 char *pmix_path_access(char *fname, char *path, int mode)
 232 {
 233     char *fullpath = NULL;
 234     struct stat buf;
 235 
 236     /* Allocate space for the full pathname. */
 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     /* first check to see - is this a file or a directory? We
 246      * only want files
 247      */
 248     if (0 != stat(fullpath, &buf)) {
 249         /* couldn't stat the path - obviously, this also meets the
 250          * existence check, if that was requested
 251          */
 252         free(fullpath);
 253         return NULL;
 254     }
 255 
 256     if (!(S_IFREG & buf.st_mode) &&
 257         !(S_IFLNK & buf.st_mode)) {
 258         /* this isn't a regular file or a symbolic link, so
 259          * ignore it
 260          */
 261         free(fullpath);
 262         return NULL;
 263     }
 264 
 265     /* check the permissions */
 266     if ((X_OK & mode) && !(S_IXUSR & buf.st_mode)) {
 267         /* if they asked us to check executable permission,
 268          * and that isn't set, then return NULL
 269          */
 270         free(fullpath);
 271         return NULL;
 272     }
 273     if ((R_OK & mode) && !(S_IRUSR & buf.st_mode)) {
 274         /* if they asked us to check read permission,
 275          * and that isn't set, then return NULL
 276          */
 277         free(fullpath);
 278         return NULL;
 279     }
 280     if ((W_OK & mode) && !(S_IWUSR & buf.st_mode)) {
 281         /* if they asked us to check write permission,
 282          * and that isn't set, then return NULL
 283          */
 284         free(fullpath);
 285         return NULL;
 286     }
 287 
 288     /* must have met all criteria! */
 289     return fullpath;
 290 }
 291 
 292 
 293 /**
 294  *
 295  *  Loads argument array with $PATH env var.
 296  *
 297  *  Accepts
 298  *      -path String contiaing the $PATH
 299  *      -argc Pointer to argc
 300  *      -argv Pointer to list of argv
 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     /* Loop through the paths (delimited by PATHENVSEP), adding each
 313        one to argv. */
 314 
 315     while ('\0' != *path) {
 316 
 317         /* Locate the delimiter. */
 318 
 319         for (p = path; *p && (*p != PMIX_ENV_SEP); ++p) {
 320             continue;
 321         }
 322 
 323         /* Add the path. */
 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         /* Skip past the delimiter, if present. */
 334 
 335         if (*path) {
 336             ++path;
 337         }
 338     }
 339 }
 340 
 341 
 342 /**
 343  *  Gets value of variable in list or environment. Looks in the list first
 344  *
 345  *  Accepts:
 346  *      -var  String variable
 347  *      -list Pointer to environment list
 348  *
 349  *  Returns:
 350  *      -List Pointer to environment list Success
 351  *      -NULL Failure
 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  * Try to figure out the absolute path based on the application name
 372  * (usually argv[0]). If the path is already absolute return a copy, if
 373  * it start with . look into the current directory, if not dig into
 374  * the $PATH.
 375  * In case of error or if executable was not found (as an example if
 376  * the application did a cwd between the start and this call), the
 377  * function will return NULL. Otherwise, an newly allocated string
 378  * will be returned.
 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) ) { /* already absolute path */
 386         abs_app_name = app_name;
 387     } else if ( '.' == app_name[0] ||
 388                NULL != strchr(app_name, PMIX_PATH_SEP[0])) {
 389         /* the app is in the current directory or below it */
 390         pcwd = getcwd( cwd, PMIX_PATH_MAX );
 391         if( NULL == pcwd ) {
 392             /* too bad there is no way we can get the app absolute name */
 393             return NULL;
 394         }
 395         abs_app_name = pmix_os_path( false, pcwd, app_name, NULL );
 396     } else {
 397         /* Otherwise try to search for the application in the PATH ... */
 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  * Read real FS type from /etc/mtab, needed to translate autofs fs type into real fs type
 418  * TODO: solaris? OSX?
 419  * Limitations: autofs on solaris/osx will be assumed as "nfs" type
 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  * @brief Figure out, whether fname is on network file system
 448  *
 449  * Try to figure out, whether the file name specified through fname is
 450  * on any network file system (currently NFS, Lustre, Panasas and GPFS).
 451  *
 452  * If the file is not created, the parent directory is checked.
 453  * This allows checking for NFS prior to opening the file.
 454  *
 455  * @fname[in]          File name to check
 456  * @fstype[out]        File system type if retval is true
 457  *
 458  * @retval true                If fname is on NFS, Lustre, Panasas or GPFS
 459  * @retval false               otherwise
 460  *
 461  *
 462  * Linux:
 463  *   statfs(const char *path, struct statfs *buf);
 464  *          with fsid_t  f_fsid;  (in kernel struct{ int val[2] };)
 465  *          return 0 success, -1 on failure with errno set.
 466  *   statvfs (const char *path, struct statvfs *buf);
 467  *          with unsigned long  f_fsid;   -- returns wrong info
 468  *          return 0 success, -1 on failure with errno set.
 469  * Solaris:
 470  *   statvfs (const char *path, struct statvfs *buf);
 471  *          with f_basetype, contains a string of length FSTYPSZ
 472  *          return 0 success, -1 on failure with errno set.
 473  * FreeBSD:
 474  *   statfs(const char *path, struct statfs *buf);
 475  *          with f_fstypename, contains a string of length MFSNAMELEN
 476  *          return 0 success, -1 on failure with errno set.
 477  *          compliant with: 4.4BSD.
 478  * NetBSD:
 479  *   statvfs (const char *path, struct statvfs *buf);
 480  *          with f_fstypename, contains a string of length VFS_NAMELEN
 481  *          return 0 success, -1 on failure with errno set.
 482  * Mac OSX (10.6.2 through 10.9):
 483  *   statvfs(const char * restrict path, struct statvfs * restrict buf);
 484  *          with fsid    Not meaningful in this implementation.
 485  *          is just a wrapper around statfs()
 486  *   statfs(const char *path, struct statfs *buf);
 487  *          with f_fstypename, contains a string of length MFSTYPENAMELEN
 488  *          return 0 success, -1 on failure with errno set.
 489  */
 490 #ifndef LL_SUPER_MAGIC
 491 #define LL_SUPER_MAGIC                    0x0BD00BD0     /* Lustre magic number */
 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     /* Panasas FS */
 498 #endif
 499 #ifndef GPFS_SUPER_MAGIC
 500 #define GPFS_SUPER_MAGIC  0x47504653    /* Thats GPFS in ASCII */
 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      * Be sure to update the test (test/util/pmix_path_nfs.c)
 527      * while adding a new Network/Cluster Filesystem here
 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      * First, get the OS-dependent struct stat(v)fs buf.  This may
 545      * return the ESTALE error on NFS, if the underlying file/path has
 546      * changed.
 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     /* In case some error with the current filename, try the parent
 563        directory */
 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         /* Stop the search, when we have searched past root '/' */
 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     /* Next, extract the magic value */
 593     for (i = 0; i < FS_TYPES_NUM; i++) {
 594 #if defined(USE_STATFS)
 595         /* These are uses of struct statfs */
 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         /* These are uses of struct statvfs */
 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     /* now set the amount of free space available on path */
 714                                /* sometimes buf.f_bavail is negative */
 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 }

/* [<][>][^][v][top][bottom][index][help] */