Exemple #1
0
qioerr chpl_fs_get_gid(int* ret, const char* name) {
  struct stat buf;
  int exitStatus = stat(name, &buf);
  if (exitStatus)
    return qio_mkerror_errno();
  *ret = buf.st_gid;
  return 0;
}
Exemple #2
0
/* creates a symlink named linkName to the file orig */
qioerr chpl_fs_symlink(const char* orig, const char* linkName) {
  qioerr err = 0;
  int exitStatus = symlink(orig, linkName);
  if (exitStatus)
    err = qio_mkerror_errno();
  return err;

}
Exemple #3
0
/* Renames the file from oldname to newname, returning a qioerr if one
   occurred. */
qioerr chpl_fs_rename(const char* oldname, const char* newname) {
  qioerr err = 0;
  int exitStatus = rename(oldname, newname);
  // utilizes the C library function rename.
  if (exitStatus)
    err = qio_mkerror_errno();
  return err;
}
Exemple #4
0
qioerr _chpl_fs_check_mode(int* ret, const char* name, int mode_flag) {
  struct stat buf;
  int exitStatus = stat(name, &buf);
  if (exitStatus)
    return qio_mkerror_errno();
  *ret = (buf.st_mode&mode_flag) != 0;
  return 0;
}
Exemple #5
0
// Send a signal to the specified pid
qioerr qio_send_signal(int64_t pid, int sig)
{
  qioerr err = 0;

  int rc = kill(pid, sig);
  if (rc == -1)
    err = qio_mkerror_errno();

  return err;
}
Exemple #6
0
qioerr chpl_fs_realpath(const char* path, const char **shortened) {
  qioerr err = 0;
  *shortened = realpath(path, NULL);
  if (*shortened == NULL) {
    // If an error occurred, shortened will be NULL.  Otherwise, it will
    // contain the cleaned up path.
    err = qio_mkerror_errno();
  }
  return err;
}
Exemple #7
0
qioerr chpl_fs_copy_metadata(const char* source, const char* dest) {
  qioerr err = 0;
  struct stat oldTimes;
  struct utimbuf times;
  int exitStatus = stat(source, &oldTimes);
  if (exitStatus == -1) {
    // Hopefully an error will not occur (as we have checked that the
    // file exists when we perform the other operations on it).  But just in
    // case, check it here.
    err = qio_mkerror_errno();
    return err;
  }
  times.actime = oldTimes.st_atime;  // The access time
  times.modtime = oldTimes.st_mtime; // The modification time
  exitStatus = utime(dest, &times);  // Set the times for dest.
  if (exitStatus == -1) {
    err = qio_mkerror_errno();
  }
  return err;
}
Exemple #8
0
// This routine returns a malloc'd string (through the working_dir pointer)
// that must be deallocated by the caller.
qioerr chpl_fs_cwd(const char** working_dir) {
  qioerr err = 0;
  size_t bufsize = MAXPATHLEN*sizeof(char);
  char* bufptr;
  char* pathbuf = (char *)qio_malloc(bufsize);
  bufptr = getcwd(pathbuf, bufsize);
  if (bufptr == NULL)
    err = qio_mkerror_errno();
  else
    *working_dir = pathbuf;
  return err;
}
Exemple #9
0
/* Returns the current permissions on a file specified by name */
qioerr chpl_fs_viewmode(int* ret, const char* name) {
  struct stat buf;
  int exitStatus = stat(name, &buf);
  if (exitStatus)
    return qio_mkerror_errno();
  *ret = (int)(buf.st_mode&(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX));
  // Stylistic decision: while we have the capacity to make sure all we're
  // getting are the permissions bits in module code, sending that extra
  // information strikes me as unnecessary, since we don't intend to use it at
  // the module level in other circumstances.
  return 0;
}
Exemple #10
0
qioerr hdfs_fsync(void* fl, void* fs)
{
  int got;
  qioerr err_out = 0;

  STARTING_SLOW_SYSCALL;
  got = hdfsFlush(to_hdfs_fs(fs)->hfs, to_hdfs_file(fl)->file);

  if(got == -1)
    err_out = qio_mkerror_errno();
  DONE_SLOW_SYSCALL;

  return err_out;
}
Exemple #11
0
qioerr hdfs_close(void* fl, void* fs)
{
  int got = 0;
  qioerr err_out = 0;

  STARTING_SLOW_SYSCALL;
  got = hdfsCloseFile(to_hdfs_fs(fs)->hfs, to_hdfs_file(fl)->file);

  if(got == -1)
    err_out = qio_mkerror_errno();
  DONE_SLOW_SYSCALL;
  DO_RELEASE((to_hdfs_fs(fs)), hdfs_disconnect_and_free);
  return err_out;
}
Exemple #12
0
qioerr chpl_fs_is_link(int* ret, const char* name) {
  // Note: Cannot use _chpl_fs_check_mode in this case because stat follows
  // symbolic links instead of evaluating the link itself.  The similar
  // comparison is also not valid when an unlinked file is provided.
  struct stat buf;
  int exitStatus = lstat(name, &buf);
  if (exitStatus == -1 && errno == ENOENT) {
    // The link examined does not exist, return false
    *ret = 0;
    return 0;
  } else if (exitStatus) {
    return qio_mkerror_errno();
  }
  *ret = S_ISLNK(buf.st_mode);
  return 0;
}
Exemple #13
0
qioerr chpl_fs_realpath(const char* path, const char **shortened) {
  qioerr err = 0;
  size_t bufsize = MAXPATHLEN*sizeof(char);
  char* bufptr;
  char* pathbuf = (char *)qio_malloc(bufsize);

  bufptr = realpath(path, pathbuf);
  if (bufptr == NULL) {
    // If an error occurred, bufptr will be NULL.  Otherwise, it will
    // point to pathbuf anyways
    err = qio_mkerror_errno();
    qio_free(pathbuf);
  } else {
    *shortened = pathbuf;
  }
  return err;
}
Exemple #14
0
qioerr chpl_fs_exists(int* ret, const char* name) {
  qioerr err = 0;
  struct stat buf;
  // Stat will attempt to follow all symbolic links.  If the link is broken,
  // this means we will detect it and return false.
  int exitStatus = stat(name, &buf);
  if (exitStatus == -1 && errno == ENOENT) {
    // File or directory does not exist, return false
    *ret = 0;
  } else if (exitStatus) {
    // Another error occurred.  Return it.
    err = qio_mkerror_errno();
  } else {
    // The file or directory exists, return true
    *ret = 1;
  }
  return err;
}
Exemple #15
0
static
qioerr hdfs_disconnect_and_free(void* fs)
{
  qioerr err = 0;
  int ret= 0;

  STARTING_SLOW_SYSCALL;
  errno = 0;
  ret = hdfsDisconnect(((hdfs_fs*)fs)->hfs);

  if ((ret == -2) || (ret == -1))  {
    err = qio_mkerror_errno();
  } else errno = 0;
  DONE_SLOW_SYSCALL;

  qio_free(fs);
  return err;
}
Exemple #16
0
qioerr hdfs_open(void** fd, const char* path, int* flags, mode_t mode, qio_hint_t iohints, void* fs)
{
  qioerr err_out = 0;
  int rc;
  hdfs_file* fl = (hdfs_file*)qio_calloc(sizeof(hdfs_file), 1);

  STARTING_SLOW_SYSCALL;
  DO_RETAIN(((hdfs_fs*)fs));

  // assert that we connected
  CREATE_ERROR((to_hdfs_fs(fs)->hfs == NULL), err_out, ECONNREFUSED,"Unable to open HDFS file", error);

  fl->file =  hdfsOpenFile(to_hdfs_fs(fs)->hfs, path, *flags, 0, 0, 0);

  // Assert that we opened the file
  if (fl->file == NULL) {
    err_out = qio_mkerror_errno();
    goto error;
  }

  DONE_SLOW_SYSCALL;

  fl->pathnm = path;

  rc = *flags | ~O_ACCMODE;
  rc &= O_ACCMODE;
  if( rc == O_RDONLY ) {
    *flags |= QIO_FDFLAG_READABLE;
  } else if( rc == O_WRONLY ) {
    *flags |= QIO_FDFLAG_WRITEABLE;
  } else if( rc == O_RDWR ) {
    *flags |= QIO_FDFLAG_READABLE;
    *flags |= QIO_FDFLAG_WRITEABLE;
  }

  *fd = fl; // Set fd to fl and return
  return err_out;

error:
  qio_free(fl);
  return err_out;
}
Exemple #17
0
static
qioerr curl_writev(void* fl, const struct iovec* iov, int iovcnt, ssize_t* num_written_out, void* fs)
{
  CURLcode ret;
  qioerr err_out = 0;
  struct curl_iovec_t write_vec;

  write_vec.total_read = 0;
  write_vec.count = iovcnt;
  write_vec.vec = (struct iovec*)iov;
  write_vec.amt_read = 0;
  write_vec.offset = 0;
  write_vec.curr = 0;

  STARTING_SLOW_SYSCALL;
  /*tell it to "upload" to the URL*/
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_UPLOAD, 1L);
  // set it up to write over curl
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_READFUNCTION, read_data);
  // Tell curl how much data to expect
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_INFILESIZE_LARGE,  (curl_off_t)sys_iov_total_bytes(iov, iovcnt));
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_READDATA, &write_vec);
  ret = curl_easy_perform(to_curl_handle(fl)->curl);
  *num_written_out = write_vec.total_read;

  if (ret != CURLE_OK)
    err_out = qio_mkerror_errno();

  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_UPLOAD, 0L);
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_INFILESIZE_LARGE, 0L);
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_READFUNCTION, NULL);
  curl_easy_setopt(to_curl_handle(fl)->curl, CURLOPT_READDATA, NULL);

  DONE_SLOW_SYSCALL;

  return err_out;
}
Exemple #18
0
qioerr chpl_fs_is_mount(int* ret, const char* name) {
  qioerr err = 0;
  struct stat nBuf, parentBuf;
  int exitStatus = 0;
  size_t nameLen = strlen(name);
  char* parent = (char* ) chpl_mem_allocMany(nameLen + 4, sizeof(char), CHPL_RT_MD_OS_LAYER_TMP_DATA, 0, 0);
  char* safeNameCopy = (char* ) chpl_mem_allocMany(nameLen + 1, sizeof(char), CHPL_RT_MD_OS_LAYER_TMP_DATA, 0, 0);
  strncpy(safeNameCopy, name, nameLen + 1);
  // Need to copy name so that we can use it in the case of links

  err = chpl_fs_is_link(&exitStatus, name);
  if (err) {
    // The stat call in is_link returned an error, which we would encounter too,
    // so return immediately.
    chpl_mem_free(parent, 0, 0);
    chpl_mem_free(safeNameCopy, 0, 0);
    return err;
  } else if (exitStatus) {
    // We are dealing with a link.  Using /.. will refer to the parent of the
    // linked location, rather than the parent of the link itself.  We need to
    // perform some string token action.

    // Lydia note (03/17/2015): when the Path library is more fleshed out, this
    // operation could be done in module code and this function would instead
    // take the name of the parent and child instead of creating the parent name
    // itself.

    char* curTok = strtok(safeNameCopy, "/");
    char* nextTok = strtok(NULL, "/");
    // We need the next token to determine if the path is longer than a single
    // link name.
    assert(curTok != NULL);
    // curTok should never be null.  The only string which would return null is
    // "/", but that directory is not a link, so won't be here in the first
    // place.

    if (nextTok != NULL) {
      // name includes a path longer than just the current symlink.
      // Thus, we should copy up to (but not including) the basename of the
      // path.
      strncpy(parent, curTok, strlen(curTok) + 1);
      curTok = nextTok;
      nextTok = strtok(NULL, "/");
      while (nextTok != NULL) {
        // While we haven't found the end of the path (in nextTok)
        strncat(parent, "/", 1);
        // Restore the lost path separator.
        strncat(parent, curTok, strlen(curTok));
        // Add the current token to the parent list
        curTok = nextTok;
        // And prepare to check if the next token is the last in the path
        nextTok = strtok(NULL, "/");
      }
    } else {
      // name was merely the current symlink rather than a longer path.
      // That means its parent is "." or the current directory.
      strncpy(parent, ".", 2);
    }
  } else {
    // We are not referring to a link, so concatenating "/.." is fine.
    strncpy(parent, name, nameLen + 1);
    strncat(parent, "/..", 3);
    // TODO: Using "/" is not necessarily portable, look into this
  }

  exitStatus = lstat(name, &nBuf);
  if (exitStatus) {
    err = qio_mkerror_errno();
    chpl_mem_free(parent, 0, 0);
    chpl_mem_free(safeNameCopy, 0, 0);
    return err;
  }
  exitStatus = lstat(parent, &parentBuf);
  if (exitStatus) {
    err = qio_mkerror_errno();
  } else {
    if (nBuf.st_dev != parentBuf.st_dev) {
      *ret = 1;
    // Check if the st_dev matches that of its parent directory.
    // If they don't match, it is a mount point.
    } else {
      err = chpl_fs_samefile_string(ret, name, parent);
      // If the parent directory is the same as the current directory, we've
      // reached the root.  If they don't, we know it isn't a mount point
      // because we already know their st_dev matches.
    }
  }
  chpl_mem_free(parent, 0, 0);
  chpl_mem_free(safeNameCopy, 0, 0);
  return err;
}
Exemple #19
0
qioerr hdfs_preadv (void* file, const struct iovec *vector, int count, off_t offset, ssize_t* num_read_out, void* fs)
{
  ssize_t got;
  ssize_t got_total;
  qioerr err_out = 0;
  int i;

  STARTING_SLOW_SYSCALL;

#ifdef HDFS3

  const hdfs_file orig_hfl = *to_hdfs_file(file);
  const hdfs_fs orig_hfs = *to_hdfs_fs(fs);

  hdfsFS hfs = hdfsConnect(orig_hfs.fs_name, orig_hfs.fs_port);
  hdfsFile hfl = hdfsOpenFile(hfs, orig_hfl.pathnm, O_RDONLY, 0, 0, 0);

  //assert connection
  CREATE_ERROR((hfs == NULL), err_out, ECONNREFUSED, "Unable to read HDFS file", error);

  if(hfl == NULL) {
    err_out = qio_mkerror_errno();
    goto error;
  }

#endif

  err_out = 0;
  got_total = 0;
  for(i = 0; i < count; i++) {

#ifdef HDFS3
    hdfsSeek(hfs, hfl, offset+got_total);
    got = hdfsRead(hfs, hfl, (void*)vector[i].iov_base, vector[i].iov_len);
#else
    got = hdfsPread(to_hdfs_fs(fs)->hfs, to_hdfs_file(file)->file, offset + got_total, (void*)vector[i].iov_base, vector[i].iov_len);
#endif

    if( got != -1 ) {
      got_total += got;
    } else {
      err_out = qio_mkerror_errno();
      break;
    }
    if(got != (ssize_t)vector[i].iov_len ) {
      break;
    }
  }

  if( err_out == 0 && got_total == 0 && sys_iov_total_bytes(vector, count) != 0 )
    err_out = qio_int_to_err(EEOF);

  *num_read_out = got_total;

#ifdef HDFS3
  got = hdfsCloseFile(hfs, hfl);
  if(got == -1) { err_out = qio_mkerror_errno(); }

  got = hdfsDisconnect(hfs);
  if(got == -1) { err_out = qio_mkerror_errno(); }

#endif

  DONE_SLOW_SYSCALL;

#ifdef HDFS3
error:
#endif
  return err_out;
}
Exemple #20
0
/* Creates a directory with the given name and settings if possible,
   returning a qioerr if not. If parents != 0, then the callee wishes
   to create all interim directories necessary as well. */
qioerr chpl_fs_mkdir(const char* name, int mode, int parents) {
  qioerr err = 0;
  int exitStatus;
  if (!parents) {
    // Simple, easy.  Callee didn't specify recursive creation, so
    // if something fails, they get to deal with it.
    exitStatus = mkdir(name, mode);
  } else {
    int len = strlen(name);
    char tmp[len+1];
    int index;
    struct stat statRes;
    // We don't actually care about the full result of the stat calls, merely
    // the existence and state of the directory being accessed.
    while (name[len-1] == '/') {
      // In case the caller, in their infinite wisdom, decides to send
      // a directory name of the form "foo///////".
      len--;
      // Note: not being able to mix declarations and code means that
      // tmp must be created larger than might be necessary.
    }
    // Copy each step of the directory path into a temporary string,
    // creating the parent directories as needed. In the case of name
    // being "foo/bar/baz", this means that tmp will be "foo/" and then
    // "foo/bar" for each inner call of mkdir.
    for (index = 0; name[index] != '\0' && index < len; index++) {
      tmp[index] = name[index];
      if(tmp[index] == '/') {
        tmp[index+1] = '\0';
        exitStatus = stat(tmp, &statRes);
        if (exitStatus == -1 && errno == ENOENT) {
          // This error means we could not find the parent directory, so need
          // to create it.
          exitStatus = mkdir(tmp, mode);
        }
        // EEXIST could occur from the mkdir call above if the directory came
        // into existence between when we checked and when we tried to create
        // it.  There's really nothing to be done about it, so skip it and
        // continue on.
        if (exitStatus && errno != EEXIST) {
          // We encountered an error making a parent directory or during the
          // stat call to determine if we need to make a directory.  We will
          // encounter errors for every step after this, so return this one
          // as it will be more informative.
          err = qio_mkerror_errno();
          return err;
        }
      }
    }
    tmp[len] = '\0';
    exitStatus = mkdir(tmp, mode);
    if (exitStatus && errno == EEXIST) {
      // If we encountered EEXIST when creating the last directory, ignore it.
      // This behavior is consistent with the command line mkdir -p behavior.
      exitStatus = 0;
    }
  }
  if (exitStatus) {
    err = qio_mkerror_errno();
  }
  return err;
}