Example #1
0
int dfs_chmod(const char *path, mode_t mode)
{
  TRACE1("chmod", path)

#if PERMS
  // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(path);
  assert(dfs);
  assert('/' == *path);

  hdfsFS userFS;
  // if not connected, try to connect and fail out if we can't.
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
    ERROR("Could not connect to HDFS");
    return -EIO;
  }

  if (hdfsChmod(userFS, path, (short)mode)) {
    ERROR("Could not chmod %s to %d", path, (int)mode);
    return -EIO;
  }
#endif
  return 0;
}
/**
 * For now implement truncate here and only for size == 0.
 * Weak implementation in that we just delete the file and 
 * then re-create it, but don't set the user, group, and times to the old
 * file's metadata. 
 */
int dfs_truncate(const char *path, off_t size)
{
  TRACE1("truncate", path)

  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  assert(path);
  assert('/' == *path);
  assert(dfs);

  if (size != 0) {
    return -ENOTSUP;
  }

  int ret = dfs_unlink(path);
  if (ret != 0) {
    return ret;
  }

  hdfsFS userFS = doConnectAsUser(dfs->nn_hostname, dfs->nn_port);
  if (userFS == NULL) {
    ERROR("Could not connect");
    ret = -EIO;
    goto cleanup;
  }

  int flags = O_WRONLY | O_CREAT;

  hdfsFile file;
  if ((file = (hdfsFile)hdfsOpenFile(userFS, path, flags,  0, 0, 0)) == NULL) {
    ERROR("Could not connect open file %s", path);
    ret = -EIO;
    goto cleanup;
  }

  if (hdfsCloseFile(userFS, file) != 0) {
    ERROR("Could not close file %s", path);
    ret = -EIO;
    goto cleanup;
  }

cleanup:
  if (doDisconnect(userFS)) {
    ret = -EIO;
  }
  return ret;
}
int dfs_mkdir(const char *path, mode_t mode)
{
  TRACE1("mkdir", path)

  // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(path);
  assert(dfs);
  assert('/' == *path);

  if (is_protected(path)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to create the directory: %s", path);
    return -EACCES;
  }

  if (dfs->read_only) {
    syslog(LOG_ERR,"ERROR: hdfs is configured as read-only, cannot create the directory %s\n",path);
    return -EACCES;
  }
  
  hdfsFS userFS;
  // if not connected, try to connect and fail out if we can't.
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
    syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__);
    return -EIO;
  }

  // In theory the create and chmod should be atomic.

  if (hdfsCreateDirectory(userFS, path)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to create directory %s",path);
    return -EIO;
  }

#if PERMS
  if (hdfsChmod(userFS, path, (short)mode)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to chmod %s to %d",path, (int)mode);
    return -EIO;
  }
#endif
  return 0;

}
Example #4
0
int dfs_access(const char *path, int mask)
{
  TRACE1("access", path)
  // bugbug - I think we need the FileSystemAPI/libhdfs to expose this!
  // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(dfs);
  assert(path);

  hdfsFS userFS;
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port)) == NULL) {
    ERROR("Could not connect to HDFS");
    return -EIO;
  }
  //  return hdfsAccess(userFS, path, mask);
  return 0;
}
Example #5
0
int dfs_statfs(const char *path, struct statvfs *st)
{
  TRACE1("statfs",path)

  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  assert(path);
  assert(st);
  assert(dfs);

  memset(st,0,sizeof(struct statvfs));

  hdfsFS userFS = doConnectAsUser(dfs->nn_hostname, dfs->nn_port);
  if (userFS == NULL) {
    ERROR("Could not connect");
    return -EIO;
  }

  const tOffset cap   = hdfsGetCapacity(userFS);
  const tOffset used  = hdfsGetUsed(userFS);
  const tOffset bsize = hdfsGetDefaultBlockSize(userFS);

  if (doDisconnect(userFS)) {
    return -EIO;
  }

  st->f_bsize   =  bsize;
  st->f_frsize  =  bsize;
  st->f_blocks  =  cap/bsize;
  st->f_bfree   =  (cap-used)/bsize;
  st->f_bavail  =  (cap-used)/bsize;
  st->f_files   =  1000;
  st->f_ffree   =  500;
  st->f_favail  =  500;
  st->f_fsid    =  1023;
  st->f_flag    =  ST_RDONLY | ST_NOSUID;
  st->f_namemax =  1023;

  return 0;
}
int dfs_rename(const char *from, const char *to)
{
  TRACE1("rename", from) 

 // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(from);
  assert(to);
  assert(dfs);

  assert('/' == *from);
  assert('/' == *to);

  if (is_protected(from) || is_protected(to)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to rename: %s %s", from, to);
    return -EACCES;
  }

  if (dfs->read_only) {
    syslog(LOG_ERR,"ERROR: hdfs is configured as read-only, cannot rename the directory %s\n",from);
    return -EACCES;
  }

  hdfsFS userFS;
  // if not connected, try to connect and fail out if we can't.
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
    syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__);
    return -EIO;
  }

  if (hdfsRename(userFS, from, to)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to rename %s to %s",from, to);
    return -EIO;
  }

  return 0;

}
int dfs_unlink(const char *path)
{
  TRACE1("unlink", path)

  // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(path);
  assert(dfs);
  assert('/' == *path);

  if (is_protected(path)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to delete a protected directory: %s ",path);
    return -EACCES;
  }

  if (dfs->read_only) {
    syslog(LOG_ERR,"ERROR: hdfs is configured as read-only, cannot create the directory %s\n",path);
    return -EACCES;
  }

  hdfsFS userFS;
  // if not connected, try to connect and fail out if we can't.
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
    syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__);
    return -EIO;
  }


  if (hdfsDeleteWithTrash(userFS, path, dfs->usetrash)) {
    syslog(LOG_ERR,"ERROR: hdfs trying to delete the file %s",path);
    return -EIO;
  }

  return 0;

}
int dfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                       off_t offset, struct fuse_file_info *fi)
{
  TRACE1("readdir",path)

  (void) offset;
  (void) fi;

  // retrieve dfs specific data
  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(dfs);
  assert(path);
  assert(buf);

  int path_len = strlen(path);

  hdfsFS userFS;
  // if not connected, try to connect and fail out if we can't.
  if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
    syslog(LOG_ERR, "ERROR: could not connect to dfs %s:%d\n", __FILE__, __LINE__);
    return -EIO;
  }

  // call dfs to read the dir
  int numEntries = 0;
  hdfsFileInfo *info = hdfsListDirectory(userFS,path,&numEntries);
  userFS = NULL;

  // NULL means either the directory doesn't exist or maybe IO error.
  if (NULL == info) {
    return -ENOENT;
  }

  int i ;
  for (i = 0; i < numEntries; i++) {

    // check the info[i] struct
    if (NULL == info[i].mName) {
      syslog(LOG_ERR,"ERROR: for <%s> info[%d].mName==NULL %s:%d", path, i, __FILE__,__LINE__);
      continue;
    }

    struct stat st;
    fill_stat_structure(&info[i], &st);

    // hack city: todo fix the below to something nicer and more maintainable but
    // with good performance
    // strip off the path but be careful if the path is solely '/'
    // NOTE - this API started returning filenames as full dfs uris
    const char *const str = info[i].mName + dfs->dfs_uri_len + path_len + ((path_len == 1 && *path == '/') ? 0 : 1);

    // pack this entry into the fuse buffer
    int res = 0;
    if ((res = filler(buf,str,&st,0)) != 0) {
      syslog(LOG_ERR, "ERROR: readdir filling the buffer %d %s:%d\n",res, __FILE__, __LINE__);
    }
  }

  // insert '.' and '..'
  const char *const dots [] = { ".",".."};
  for (i = 0 ; i < 2 ; i++)
    {
      struct stat st;
      memset(&st, 0, sizeof(struct stat));

      // set to 0 to indicate not supported for directory because we cannot (efficiently) get this info for every subdirectory
      st.st_nlink =  0;

      // setup stat size and acl meta data
      st.st_size    = 512;
      st.st_blksize = 512;
      st.st_blocks  =  1;
      st.st_mode    = (S_IFDIR | 0777);
      st.st_uid     = default_id;
      st.st_gid     = default_id;
      // todo fix below times
      st.st_atime   = 0;
      st.st_mtime   = 0;
      st.st_ctime   = 0;

      const char *const str = dots[i];

      // flatten the info using fuse's function into a buffer
      int res = 0;
      if ((res = filler(buf,str,&st,0)) != 0) {
        syslog(LOG_ERR, "ERROR: readdir filling the buffer %d %s:%d", res, __FILE__, __LINE__);
      }
    }
  // free the info pointers
  hdfsFreeFileInfo(info,numEntries);
  return 0;
}
Example #9
0
int dfs_open(const char *path, struct fuse_file_info *fi)
{
  TRACE1("open", path)

  dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

  // check params and the context var
  assert(path);
  assert('/' == *path);
  assert(dfs);

  int ret = 0;

  // 0x8000 is always passed in and hadoop doesn't like it, so killing it here
  // bugbug figure out what this flag is and report problem to Hadoop JIRA
  int flags = (fi->flags & 0x7FFF);

  // retrieve dfs specific data
  dfs_fh *fh = (dfs_fh*)calloc(1, sizeof (dfs_fh));
  if (fh == NULL) {
    ERROR("Malloc of new file handle failed");
    return -EIO;
  }

  fh->fs = doConnectAsUser(dfs->nn_hostname, dfs->nn_port);
  if (fh->fs == NULL) {
    ERROR("Could not connect to dfs");
    return -EIO;
  }

  if (flags & O_RDWR) {
    hdfsFileInfo *info = hdfsGetPathInfo(fh->fs,path);
    if (info == NULL) {
      // File does not exist (maybe?); interpret it as a O_WRONLY
      // If the actual error was something else, we'll get it again when
      // we try to open the file.
      flags ^= O_RDWR;
      flags |= O_WRONLY;
    } else {
      // File exists; open this as read only.
      flags ^= O_RDWR;
      flags |= O_RDONLY;
    }
  }

  if ((fh->hdfsFH = hdfsOpenFile(fh->fs, path, flags,  0, 0, 0)) == NULL) {
    ERROR("Could not open file %s (errno=%d)", path, errno);
    if (errno == 0 || errno == EINTERNAL) {
      return -EIO;
    }
    return -errno;
  }

  pthread_mutex_init(&fh->mutex, NULL);

  if (fi->flags & O_WRONLY || fi->flags & O_CREAT) {
    fh->buf = NULL;
  } else  {
    assert(dfs->rdbuffer_size > 0);
    fh->buf = (char*)malloc(dfs->rdbuffer_size * sizeof(char));
    if (NULL == fh->buf) {
      ERROR("Could not allocate memory for a read for file %s\n", path);
      ret = -EIO;
    }
    fh->buffersStartOffset = 0;
    fh->bufferSize = 0;
  }
  fi->fh = (uint64_t)fh;

  return ret;
}
Example #10
0
int dfs_statfs(const char *path, struct statvfs *st)
{
    TRACE1("statfs",path)

    // retrieve dfs specific data
    dfs_context *dfs = (dfs_context*)fuse_get_context()->private_data;

    // check params and the context var
    assert(path);
    assert(st);
    assert(dfs);

    // init the stat structure
    memset(st,0,sizeof(struct statvfs));

    hdfsFS userFS;
    // if not connected, try to connect and fail out if we can't.
    if ((userFS = doConnectAsUser(dfs->nn_hostname,dfs->nn_port))== NULL) {
        ERROR("Could not connect");
        return -EIO;
    }

    const tOffset cap   = hdfsGetCapacity(userFS);
    const tOffset used  = hdfsGetUsed(userFS);
    const tOffset bsize = hdfsGetDefaultBlockSize(userFS);

    // fill in the statvfs structure

    /* FOR REFERENCE:
       struct statvfs {
       unsigned long  f_bsize;    // file system block size
       unsigned long  f_frsize;   // fragment size
       fsblkcnt_t     f_blocks;   // size of fs in f_frsize units
       fsblkcnt_t     f_bfree;    // # free blocks
       fsblkcnt_t     f_bavail;   // # free blocks for non-root
       fsfilcnt_t     f_files;    // # inodes
       fsfilcnt_t     f_ffree;    // # free inodes
       fsfilcnt_t     f_favail;   // # free inodes for non-root
       unsigned long  f_fsid;     // file system id
       unsigned long  f_flag;     / mount flags
       unsigned long  f_namemax;  // maximum filename length
       };
    */

    st->f_bsize   =  bsize;
    st->f_frsize  =  bsize;

    st->f_blocks  =  cap/bsize;

    st->f_bfree   =  (cap-used)/bsize;
    st->f_bavail  =  (cap-used)/bsize;

    st->f_files   =  1000;
    st->f_ffree   =  500;
    st->f_favail  =  500;
    st->f_fsid    =  1023;
    st->f_flag    =  ST_RDONLY | ST_NOSUID;
    st->f_namemax =  1023;

    return 0;
}