root/opal/util/path.c

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

DEFINITIONS

This source file includes following definitions.
  1. opal_path_is_absolute
  2. opal_path_find
  3. opal_path_findv
  4. opal_path_access
  5. path_env_load
  6. list_env_get
  7. opal_find_absolute_path
  8. opal_check_mtab
  9. opal_path_nfs
  10. opal_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-2018 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      Intel, Inc.  All rights reserved.
  17  * Copyright (c) 2016      University of Houston. All rights reserved.
  18  * Copyright (c) 2016      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 "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  * Sanity check to ensure we have either statfs or statvfs
  84  */
  85 #if !defined(HAVE_STATFS) && !defined(HAVE_STATVFS)
  86 #error Must have either statfs() or statvfs()
  87 #endif
  88 
  89 /*
  90  * Note that some OS's (e.g., NetBSD and Solaris) have statfs(), but
  91  * no struct statfs (!).  So check to make sure we have struct statfs
  92  * before allowing the use of statfs().
  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  *  Locates a file with certain permissions
 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     /* If absolute path is given, return it without searching. */
 122     if( opal_path_is_absolute(fname) ) {
 123         return opal_path_access(fname, NULL, mode);
 124     }
 125 
 126     /* Initialize. */
 127 
 128     fullpath = NULL;
 129     i = 0;
 130 
 131     /* Consider each directory until the file is found.  Thus, the
 132        order of directories is important. */
 133 
 134     while (pathv[i] && NULL == fullpath) {
 135 
 136         /* Replace environment variable at the head of the string. */
 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  * Locates a file with certain permissions from a list of search paths
 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     /* Set the local search paths. */
 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     /* Replace the "." path by the working directory. */
 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     /* If we didn't find "." in the path and we have a wrkdir, append
 201        the wrkdir to the end of the path */
 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  *  Forms a complete pathname and checks it for existance and
 217  *  permissions
 218  *
 219  *  Accepts:
 220  *      -fname File name
 221  *      -path  Path prefix
 222  *      -mode  Target permissions which must be satisfied
 223  *
 224  *  Returns:
 225  *      -Full pathname of located file Success
 226  *      -NULL Failure
 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     /* Allocate space for the full pathname. */
 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     /* first check to see - is this a file or a directory? We
 245      * only want files
 246      */
 247     if (0 != stat(fullpath, &buf)) {
 248         /* couldn't stat the path - obviously, this also meets the
 249          * existence check, if that was requested
 250          */
 251         free(fullpath);
 252         return NULL;
 253     }
 254 
 255     if (!(S_IFREG & buf.st_mode) &&
 256         !(S_IFLNK & buf.st_mode)) {
 257         /* this isn't a regular file or a symbolic link, so
 258          * ignore it
 259          */
 260         free(fullpath);
 261         return NULL;
 262     }
 263 
 264     /* check the permissions */
 265     if ((X_OK & mode) && !(S_IXUSR & buf.st_mode)) {
 266         /* if they asked us to check executable permission,
 267          * and that isn't set, then return NULL
 268          */
 269         free(fullpath);
 270         return NULL;
 271     }
 272     if ((R_OK & mode) && !(S_IRUSR & buf.st_mode)) {
 273         /* if they asked us to check read permission,
 274          * and that isn't set, then return NULL
 275          */
 276         free(fullpath);
 277         return NULL;
 278     }
 279     if ((W_OK & mode) && !(S_IWUSR & buf.st_mode)) {
 280         /* if they asked us to check write permission,
 281          * and that isn't set, then return NULL
 282          */
 283         free(fullpath);
 284         return NULL;
 285     }
 286 
 287     /* must have met all criteria! */
 288     return fullpath;
 289 }
 290 
 291 
 292 /**
 293  *
 294  *  Loads argument array with $PATH env var.
 295  *
 296  *  Accepts
 297  *      -path String contiaing the $PATH
 298  *      -argc Pointer to argc
 299  *      -argv Pointer to list of argv
 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     /* Loop through the paths (delimited by PATHENVSEP), adding each
 312        one to argv. */
 313 
 314     while ('\0' != *path) {
 315 
 316         /* Locate the delimiter. */
 317 
 318         for (p = path; *p && (*p != OPAL_ENV_SEP); ++p) {
 319             continue;
 320         }
 321 
 322         /* Add the path. */
 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         /* Skip past the delimiter, if present. */
 333 
 334         if (*path) {
 335             ++path;
 336         }
 337     }
 338 }
 339 
 340 
 341 /**
 342  *  Gets value of variable in list or environment. Looks in the list first
 343  *
 344  *  Accepts:
 345  *      -var  String variable
 346  *      -list Pointer to environment list
 347  *
 348  *  Returns:
 349  *      -List Pointer to environment list Success
 350  *      -NULL Failure
 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  * Try to figure out the absolute path based on the application name
 371  * (usually argv[0]). If the path is already absolute return a copy, if
 372  * it start with . look into the current directory, if not dig into
 373  * the $PATH.
 374  * In case of error or if executable was not found (as an example if
 375  * the application did a cwd between the start and this call), the
 376  * function will return NULL. Otherwise, an newly allocated string
 377  * will be returned.
 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) ) { /* already absolute path */
 385         abs_app_name = app_name;
 386     } else if ( '.' == app_name[0] ||
 387                NULL != strchr(app_name, OPAL_PATH_SEP[0])) {
 388         /* the app is in the current directory or below it */
 389         pcwd = getcwd( cwd, OPAL_PATH_MAX );
 390         if( NULL == pcwd ) {
 391             /* too bad there is no way we can get the app absolute name */
 392             return NULL;
 393         }
 394         abs_app_name = opal_os_path( false, pcwd, app_name, NULL );
 395     } else {
 396         /* Otherwise try to search for the application in the PATH ... */
 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  * Read real FS type from /etc/mtab, needed to translate autofs fs type into real fs type
 411  * TODO: solaris? OSX?
 412  * Limitations: autofs on solaris/osx will be assumed as "nfs" type
 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  * @brief Figure out, whether fname is on network file system
 441  *
 442  * Try to figure out, whether the file name specified through fname is
 443  * on any network file system (currently NFS, Lustre, Panasas and GPFS).
 444  *
 445  * If the file is not created, the parent directory is checked.
 446  * This allows checking for NFS prior to opening the file.
 447  *
 448  * @fname[in]          File name to check
 449  * @fstype[out]        File system type if retval is true
 450  *
 451  * @retval true                If fname is on NFS, Lustre, Panasas or GPFS
 452  * @retval false               otherwise
 453  *
 454  *
 455  * Linux:
 456  *   statfs(const char *path, struct statfs *buf);
 457  *          with fsid_t  f_fsid;  (in kernel struct{ int val[2] };)
 458  *          return 0 success, -1 on failure with errno set.
 459  *   statvfs (const char *path, struct statvfs *buf);
 460  *          with unsigned long  f_fsid;   -- returns wrong info
 461  *          return 0 success, -1 on failure with errno set.
 462  * Solaris:
 463  *   statvfs (const char *path, struct statvfs *buf);
 464  *          with f_basetype, contains a string of length FSTYPSZ
 465  *          return 0 success, -1 on failure with errno set.
 466  * FreeBSD:
 467  *   statfs(const char *path, struct statfs *buf);
 468  *          with f_fstypename, contains a string of length MFSNAMELEN
 469  *          return 0 success, -1 on failure with errno set.
 470  *          compliant with: 4.4BSD.
 471  * NetBSD:
 472  *   statvfs (const char *path, struct statvfs *buf);
 473  *          with f_fstypename, contains a string of length VFS_NAMELEN
 474  *          return 0 success, -1 on failure with errno set.
 475  * Mac OSX (10.6.2 through 10.9):
 476  *   statvfs(const char * restrict path, struct statvfs * restrict buf);
 477  *          with fsid    Not meaningful in this implementation.
 478  *          is just a wrapper around statfs()
 479  *   statfs(const char *path, struct statfs *buf);
 480  *          with f_fstypename, contains a string of length MFSTYPENAMELEN
 481  *          return 0 success, -1 on failure with errno set.
 482  */
 483 #ifndef LL_SUPER_MAGIC
 484 #define LL_SUPER_MAGIC                    0x0BD00BD0     /* Lustre magic number */
 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     /* Panasas FS */
 491 #endif
 492 #ifndef GPFS_SUPER_MAGIC
 493 #define GPFS_SUPER_MAGIC  0x47504653    /* Thats GPFS in ASCII */
 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      * Be sure to update the test (test/util/opal_path_nfs.c)
 520      * while adding a new Network/Cluster Filesystem here
 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      * First, get the OS-dependent struct stat(v)fs buf.  This may
 538      * return the ESTALE error on NFS, if the underlying file/path has
 539      * changed.
 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     /* In case some error with the current filename, try the parent
 556        directory */
 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         /* Stop the search, when we have searched past root '/' */
 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     /* Next, extract the magic value */
 586     for (i = 0; i < FS_TYPES_NUM; i++) {
 587 #if defined(USE_STATFS)
 588         /* These are uses of struct statfs */
 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         /* These are uses of struct statvfs */
 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     /* now set the amount of free space available on path */
 702                                /* sometimes buf.f_bavail is negative */
 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 }

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