text: /*
   * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   *                         University Research and Technology
   *                         Corporation.  All rights reserved.
   * Copyright (c) 2004-2011 The University of Tennessee and The University
   *                         of Tennessee Research Foundation.  All rights
   *                         reserved.
   * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   *                         University of Stuttgart.  All rights reserved.
   * Copyright (c) 2004-2005 The Regents of the University of California.
   *                         All rights reserved.
   * Copyright (c) 2008-2016 University of Houston. All rights reserved.
   * Copyright (c) 2015-2016 Research Organization for Information Science
   *                         and Technology (RIST). All rights reserved.
   * Copyright (c) 2018      Cisco Systems, Inc.  All rights reserved
   * $COPYRIGHT$
   *
   * Additional copyrights may follow
   *
   * $HEADER$
   */
  
  
  #include "ompi_config.h"
  
  #include <stdio.h>
  
  #include "opal/mca/base/base.h"
  #include "opal/util/path.h"
  #include "opal/util/printf.h"
  #include "opal/util/string_copy.h"
  
  #include "ompi/mca/mca.h"
  #include "ompi/mca/fs/fs.h"
  #include "ompi/mca/fs/base/base.h"
  #include "ompi/mca/common/ompio/common_ompio.h"
  
  #ifdef HAVE_SYS_STATFS_H
  #include <sys/statfs.h> /* or <sys/vfs.h> */
  #endif
  #ifdef HAVE_SYS_PARAM_H
  #include <sys/param.h>
  #endif
  #ifdef HAVE_SYS_MOUNT_H
  #include <sys/mount.h>
  #endif
  #ifdef HAVE_SYS_STAT_H
  #include <sys/stat.h>
  #endif
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif
  
  void mca_fs_base_get_parent_dir ( char *filename, char **dirnamep)
  {
      int err;
      char *dir = NULL, *slash;
      struct stat statbuf;
  
      if (strlen(filename) < 1) {
          opal_asprintf(dirnamep, ".%s", OPAL_PATH_SEP);
          return;
      }
  
      err = lstat(filename, &statbuf);
  
      if (err || (!S_ISLNK(statbuf.st_mode))) {
  	/* no such file, or file is not a link; these are the "normal"
  	 * cases where we can just return the parent directory.
  	 */
  	dir = strdup(filename);
      }
      else {
  	/* filename is a symlink.  we've presumably already tried
  	 * to stat it and found it to be missing (dangling link),
  	 * but this code doesn't care if the target is really there
  	 * or not.
  	 */
  	int namelen;
  	char linkbuf[PATH_MAX+1];
  
  	namelen = readlink(filename, linkbuf, PATH_MAX);
  	if (namelen == -1) {
  	    /* something strange has happened between the time that
  	     * we determined that this was a link and the time that
  	     * we attempted to read it; punt and use the old name.
  	     */
  	    dir = strdup(filename);
  	}
  	else {
  	    /* successfully read the link */
  	    linkbuf[namelen] = '\0'; /* readlink doesn't null terminate */
  	    dir = strdup(linkbuf);
  	}
      }
  
      slash = strrchr(dir, '/');
      if (!slash) {
          // It is guaranteed in this case that "dir" will be at least 2
          // characters long.
          opal_string_copy(dir, ".", 2);
      } else {
  	if (slash == dir) {
              *(dir + 1) = '\0';
          } else {
              *slash = '\0';
          }
      }
  
      *dirnamep = dir;
      return;
  }
  
  int  mca_fs_base_get_fstype(char *fname )
  {
      int ompio_type = UFS;
      char *fstype=NULL;
      bool ret = opal_path_nfs ( fname, &fstype );
  
      if ( false == ret ) {
          char *dir;
          mca_fs_base_get_parent_dir (fname, &dir );
          ret = opal_path_nfs (dir, &fstype);
          free(dir);
          if ( false == ret ) {
              return ompio_type;
          }
      }
      if ( 0 == strncasecmp(fstype, "lustre", sizeof("lustre")) ) {
          ompio_type = LUSTRE;
      }
      else if ( 0 == strncasecmp(fstype, "pvfs2", sizeof("pvfs2"))) {
          ompio_type = PVFS2;
      }
      else if ( 0 == strncasecmp(fstype, "ime", sizeof("ime"))) {
          ompio_type = IME;
      }
      else if ( 0 == strncasecmp(fstype, "gpfs", sizeof("gpfs"))) {
          ompio_type = GPFS;
      }
  
      free (fstype);
      return ompio_type;
  }
  
  int mca_fs_base_get_mpi_err(int errno_val)
  {
      int ret;
      switch (errno_val) {
          case EACCES:
              ret = MPI_ERR_ACCESS;
              break;
          case ENAMETOOLONG:
          case EISDIR:
              ret = MPI_ERR_BAD_FILE;
              break;
          case ENOENT:
              ret = MPI_ERR_NO_SUCH_FILE;
              break;
          case EROFS:
              ret = MPI_ERR_READ_ONLY;
              break;
          case EEXIST:
              ret = MPI_ERR_FILE_EXISTS;
              break;
          case ENOSPC:
              ret = MPI_ERR_NO_SPACE;
              break;
          case EDQUOT:
              ret = MPI_ERR_QUOTA;
              break;
          case ETXTBSY:
              ret = MPI_ERR_FILE_IN_USE;
              break;
          case EBADF:
              ret = MPI_ERR_FILE;
              break;
          default:
              ret = MPI_ERR_OTHER;
              break;
      }
      return ret;
  }
  
  int mca_fs_base_get_file_perm(ompio_file_t *fh)
  {
      int old_mask;
      int perm = fh->f_perm;
  
      if (OMPIO_PERM_NULL == perm) {
          old_mask = umask(022);
          umask(old_mask);
          perm = old_mask ^ 0666;
      }
      return perm;
  }
  
  int mca_fs_base_get_file_amode(int rank, int access_mode)
  {
      int amode = 0;
  
      if (access_mode & MPI_MODE_RDONLY) {
          amode = amode | O_RDONLY;
      }
      if (access_mode & MPI_MODE_WRONLY) {
          amode = amode | O_WRONLY;
      }
      if (access_mode & MPI_MODE_RDWR) {
          amode = amode | O_RDWR;
      }
  
      /* MODE_CREATE and MODE_EXCL should only be set by one process */
      if(OMPIO_ROOT == rank) {
          if (access_mode & MPI_MODE_CREATE) {
              amode = amode | O_CREAT;
          }
          if (access_mode & MPI_MODE_EXCL) {
              amode = amode | O_EXCL;
          }
      }
  
      return amode;
  }
  