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 }