Ejemplo n.º 1
0
fsal_status_t FUSEFSAL_truncate(fsal_handle_t *handle, /* IN */
                                fsal_op_context_t * p_context,      /* IN */
                                fsal_size_t length,     /* IN */
                                fsal_file_t * file_descriptor,      /* Unused in this FSAL */
                                fsal_attrib_list_t * object_attributes  /* [ IN/OUT ] */
    )
{

  int rc;
  char object_path[FSAL_MAX_PATH_LEN];
  fusefsal_handle_t * filehandle = (fusefsal_handle_t *)handle;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!filehandle || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate);

  if(!p_fs_ops->truncate)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_truncate);

  /* get the full path for the object */
  rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator,
                     object_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_truncate);

  /* set context for the next operation, so it can be retrieved by FS thread */
  fsal_set_thread_context(p_context);

  TakeTokenFSCall();
  rc = p_fs_ops->truncate(object_path, (off_t) length);
  ReleaseTokenFSCall();

  if(rc)
    Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_truncate);

  if(object_attributes)
    {

      fsal_status_t st;

      st = FUSEFSAL_getattrs(handle, p_context, object_attributes);

      if(FSAL_IS_ERROR(st))
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  /* No error occured */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate);

}
Ejemplo n.º 2
0
fsal_status_t FUSEFSAL_close(fsal_file_t * file_desc  /* IN */
    )
{

  int rc;
  char file_path[FSAL_MAX_PATH_LEN];
  fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;

  /* sanity checks. */
  if(!file_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);

  /* get the full path for file inode */
  rc = NamespacePath(file_descriptor->file_handle.data.inode,
                     file_descriptor->file_handle.data.device,
                     file_descriptor->file_handle.data.validator, file_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_close);

  if(!p_fs_ops->release)
    /* ignore this call */
    Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);

  /* set context so it can be retrieved by FS */
  fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context);

  LogFullDebug(COMPONENT_FSAL, "FSAL_close: FH=%"PRId64, file_descriptor->file_info.fh);

  TakeTokenFSCall();

  rc = p_fs_ops->release(file_path, &file_descriptor->file_info);

  ReleaseTokenFSCall();

  if(rc)
    Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_close);

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);

}
Ejemplo n.º 3
0
/**
 * FSAL_closedir :
 * Free the resources allocated for reading directory entries.
 *
 * \param dir_descriptor (input):
 *        Pointer to a directory descriptor filled by FSAL_opendir.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_IO, ...
 */
fsal_status_t FUSEFSAL_closedir(fsal_dir_t * dir_desc     /* IN */
    )
{

  int rc;
  char dir_path[FSAL_MAX_PATH_LEN];
  fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc;

  /* sanity checks */
  if(!dir_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);

  /* get the full path for dir inode */
  rc = NamespacePath(dir_descriptor->dir_handle.data.inode,
                     dir_descriptor->dir_handle.data.device,
                     dir_descriptor->dir_handle.data.validator, dir_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_closedir);

  if(!p_fs_ops->releasedir)
    /* ignore this call */
    Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);

  /* set context so it can be retrieved by FS */
  fsal_set_thread_context((fsal_op_context_t *) &dir_descriptor->context);

  /* release the resources used for reading directory */

  TakeTokenFSCall();

  rc = p_fs_ops->releasedir(dir_path, &dir_descriptor->dir_info);

  ReleaseTokenFSCall();

  if(rc)
    Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_closedir);

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);

}
Ejemplo n.º 4
0
/**
 * FSAL_open:
 * Open a regular file for reading/writing its data content.
 *
 * \param filehandle (input):
 *        Handle of the file to be read/modified.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param openflags (input):
 *        Flags that indicates behavior for file opening and access.
 *        This is an inclusive OR of the following values
 *        ( such of them are not compatible) :
 *        - FSAL_O_RDONLY: opening file for reading only.
 *        - FSAL_O_RDWR: opening file for reading and writing.
 *        - FSAL_O_WRONLY: opening file for writting only.
 *        - FSAL_O_APPEND: always write at the end of the file.
 *        - FSAL_O_TRUNC: truncate the file to 0 on opening.
 * \param file_descriptor (output):
 *        The file descriptor to be used for FSAL_read/write operations.
 * \param file_attributes (optionnal input/output):
 *        Post operation attributes.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR     (no error)
 *      - ERR_FSAL_ACCESS       (user doesn't have the permissions for opening the file)
 *      - ERR_FSAL_STALE        (filehandle does not address an existing object)
 *      - ERR_FSAL_INVAL        (filehandle does not address a regular file,
 *                               or open flags are conflicting)
 *      - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *      - Other error codes can be returned :
 *        ERR_FSAL_IO, ...
 */
fsal_status_t FUSEFSAL_open(fsal_handle_t * file_hdl,     /* IN */
                            fsal_op_context_t * p_context,  /* IN */
                            fsal_openflags_t openflags, /* IN */
                            fsal_file_t * file_desc,  /* OUT */
                            fsal_attrib_list_t * file_attributes        /* [ IN/OUT ] */
    )
{

  int rc = 0;
  char object_path[FSAL_MAX_PATH_LEN];
  int file_info_provided = FALSE;
  fusefsal_handle_t * filehandle = (fusefsal_handle_t *)file_hdl;
  fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;

  /* sanity checks.
   * note : file_attributes is optional.
   */
  if(!filehandle || !p_context || !file_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open);

  /* get the full path for this file */
  rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator,
                     object_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_open);

  memset(file_descriptor, 0, sizeof(fusefsal_file_t));

  /* set access mode flags */

  file_descriptor->file_info.flags = 0;

  if(openflags & FSAL_O_RDONLY)
    file_descriptor->file_info.flags |= O_RDONLY;
  if(openflags & FSAL_O_WRONLY)
    file_descriptor->file_info.flags |= O_WRONLY;
  if(openflags & FSAL_O_RDWR)
    file_descriptor->file_info.flags |= O_RDWR;

  /* set context for the next operation, so it can be retrieved by FS thread */
  fsal_set_thread_context(p_context);

  /* check open call */

  if(p_fs_ops->open)
    {
      LogFullDebug(COMPONENT_FSAL, "Call to open( %s, %#X )", object_path, file_descriptor->file_info.flags);

      TakeTokenFSCall();
      rc = p_fs_ops->open(object_path, &(file_descriptor->file_info));
      ReleaseTokenFSCall();

      if(rc)
        Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);

      file_info_provided = TRUE;

    }
  else
    {
      LogFullDebug(COMPONENT_FSAL, "no open command provided");

      /* ignoring open */
      memset(&(file_descriptor->file_info), 0, sizeof(struct ganefuse_file_info));
    }

  /* check open flags (only FSAL_O_TRUNC and FSAL_O_APPEND are used for FUSE filesystems) */

  if(openflags & FSAL_O_TRUNC)
    {
      if(file_info_provided && p_fs_ops->ftruncate)
        {
          LogFullDebug(COMPONENT_FSAL, "call to ftruncate on file since FSAL_O_TRUNC was set");

          /* ftruncate the file */
          TakeTokenFSCall();
          rc = p_fs_ops->ftruncate(object_path, 0, &(file_descriptor->file_info));
          ReleaseTokenFSCall();

          if(rc)
            Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
        }
      else if(p_fs_ops->truncate)
        {
          LogFullDebug(COMPONENT_FSAL, "call to truncate on file since FSAL_O_TRUNC was set");

          /* truncate the file */
          TakeTokenFSCall();
          rc = p_fs_ops->truncate(object_path, 0);
          ReleaseTokenFSCall();

          if(rc)
            Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);
        }
      /* else: ignoring flag */
    }

  if(openflags & FSAL_O_APPEND)
    {
      struct stat stbuf;

      /* In this case, this only solution is to get file attributes */

      if(file_info_provided && p_fs_ops->fgetattr)
        {
          rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info));
        }
      else
        {
          rc = p_fs_ops->getattr(object_path, &stbuf);
        }

      if(rc)
        Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_open);

      file_descriptor->current_offset = stbuf.st_size;
    }
  else
    {
      file_descriptor->current_offset = 0;
    }

  /* fill the file descriptor structure */
  file_descriptor->file_handle = *filehandle;

  /* backup context */
  file_descriptor->context = *(fusefsal_op_context_t *)p_context;

  if(file_info_provided)
    LogFullDebug(COMPONENT_FSAL, "FSAL_open: FH=%"PRId64, file_descriptor->file_info.fh);

  if(file_attributes)
    {
      fsal_status_t status;

      status = FUSEFSAL_getattrs((fsal_handle_t *)filehandle, p_context, file_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(file_attributes->asked_attributes);
          FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open);

}
Ejemplo n.º 5
0
/**
 * FSAL_write:
 * Perform a write operation on an opened file.
 *
 * \param file_descriptor (input):
 *        The file descriptor returned by FSAL_open.
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param seek_descriptor (optional input):
 *        Specifies the position where data is to be written.
 *        If not specified, data will be written at the current position.
 * \param buffer_size (input):
 *        Amount (in bytes) of data to be written.
 * \param buffer (input):
 *        Address in memory of the data to write to file.
 * \param write_amount (output):
 *        Pointer to the amount of data (in bytes) that have been written
 *        during this call.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR     (no error)
 *      - ERR_FSAL_INVAL        (invalid parameter)
 *      - ERR_FSAL_NOT_OPENED   (tried to write in a non-opened fusefsal_file_t)
 *      - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *      - Other error codes can be returned :
 *        ERR_FSAL_IO, ERR_FSAL_NOSPC, ERR_FSAL_DQUOT...
 */
fsal_status_t FUSEFSAL_write(fsal_file_t * file_desc, /* IN */
                             fsal_op_context_t * p_context,     /* IN */
                             fsal_seek_t * seek_descriptor,     /* IN */
                             fsal_size_t buffer_size,   /* IN */
                             caddr_t buffer,    /* IN */
                             fsal_size_t * write_amount /* OUT */
    )
{
  size_t req_size;
  int rc;
  off_t seekoffset = 0;
  struct stat stbuf;
  char object_path[FSAL_MAX_PATH_LEN];
  fusefsal_file_t * file_descriptor = (fusefsal_file_t *)file_desc;

  /* sanity checks. */
  if(!file_descriptor || !buffer || !write_amount)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);

  if(!p_fs_ops->write)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_write);

  /* initialize returned values */

  *write_amount = 0;

  req_size = (size_t) buffer_size;

  /* set context so it can be retrieved by FS */
  fsal_set_thread_context((fsal_op_context_t *) &file_descriptor->context);

  LogFullDebug(COMPONENT_FSAL, "FSAL_write: FH=%"PRId64, file_descriptor->file_info.fh);

  /* get file's full path */
  rc = NamespacePath(file_descriptor->file_handle.data.inode,
                     file_descriptor->file_handle.data.device,
                     file_descriptor->file_handle.data.validator, object_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_write);

  if(seek_descriptor)
    {

      switch (seek_descriptor->whence)
        {
        case FSAL_SEEK_SET:
          /* set absolute position to offset */
          seekoffset = seek_descriptor->offset;
          break;

        case FSAL_SEEK_CUR:
          /* current position + offset */
          seekoffset = file_descriptor->current_offset + seek_descriptor->offset;
          break;

        case FSAL_SEEK_END:
          /* set end of file + offset */
          /* in this case, the only solution is to get entry attributes */

          if(p_fs_ops->fgetattr)
            {
              rc = p_fs_ops->fgetattr(object_path, &stbuf, &(file_descriptor->file_info));
            }
          else
            {
              rc = p_fs_ops->getattr(object_path, &stbuf);
            }

          if(rc)
            Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write);

          seekoffset = (off_t) stbuf.st_size + seek_descriptor->offset;

          break;

        default:
          LogCrit(COMPONENT_FSAL, "FSAL_write: Invalid seek parameter: whence=%d",
                  seek_descriptor->whence);
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_write);
        }
    }
  else
    {
      seekoffset = file_descriptor->current_offset;
    }

  TakeTokenFSCall();
  rc = p_fs_ops->write(object_path, buffer, req_size, seekoffset,
                       &(file_descriptor->file_info));
  ReleaseTokenFSCall();

  if(rc < 0)
    Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_write);

  file_descriptor->current_offset = seekoffset + (off_t) rc;

  *write_amount = (fsal_size_t) rc;

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);
}
Ejemplo n.º 6
0
/** Initializes filesystem, security management... */
static int FS_Specific_Init(fusefs_specific_initinfo_t * fs_init_info)
{

  int rc = 0;
  fsal_op_context_t ctx;
  struct stat stbuf;
  unsigned int root_gen;

  struct ganefuse_conn_info conn = {
    .proto_major = 0,           /* XXX is another value necessary ? */
    .proto_minor = 0,           /* XXX is another value necessary ? */
    .async_read = 0,
    .max_write = global_fs_info.maxwrite,
    .max_readahead = global_fs_info.maxread,
    .reserved = {0}
  };

  /* set filesystems operations and opaque info */
  p_fs_ops = fs_init_info->fs_ops;
  fs_user_data = fs_init_info->user_data;

  /* create a "fake" context in case init use it */

  fs_private_data = NULL;

  FUSEFSAL_InitClientContext(&ctx);
  fsal_set_thread_context(&ctx);

  /* call filesystem's init */

  if(p_fs_ops->init)
    {
      fs_private_data = p_fs_ops->init(&conn);
    }

  /* reset context now fs_private_data is known */

  FUSEFSAL_InitClientContext(&ctx);
  fsal_set_thread_context(&ctx);

  /* initialize namespace by getting root inode number
   * getattr is mandatory !
   */

  if(!p_fs_ops->getattr)
    return -ENOSYS;

  rc = p_fs_ops->getattr("/", &stbuf);

  if(rc)
    {
      LogCrit(COMPONENT_FSAL,
              "FSAL INIT: Could not call initial 'getattr' on filesystem root");

      return rc;
    }

  /* generation based on ctime for avoiding stale handles */
  root_gen = stbuf.st_ctime;

  if(stbuf.st_ino == 0)
    {
      /* filesystem does not provide inodes ! */
      LogCrit(COMPONENT_FSAL, "WARNING in lookup: filesystem does not provide inode numbers");
      /* root will have inode nbr 1 */
      stbuf.st_ino = 1;
    }

  /* initialize namespace */
  rc = NamespaceInit(stbuf.st_ino, stbuf.st_dev, &root_gen);

  return rc;

}

/**
 * FSAL_Init : Initializes the FileSystem Abstraction Layer.
 *
 * \param init_info (input, fsal_parameter_t *) :
 *        Pointer to a structure that contains
 *        all initialization parameters for the FSAL.
 *        Specifically, it contains settings about
 *        the filesystem on which the FSAL is based,
 *        security settings, logging policy and outputs,
 *        and other general FSAL options.
 *
 * \return Major error codes :
 *         ERR_FSAL_NO_ERROR     (initialisation OK)
 *         ERR_FSAL_FAULT        (init_info pointer is null)
 *         ERR_FSAL_SERVERFAULT  (misc FSAL error)
 *         ERR_FSAL_ALREADY_INIT (The FS is already initialized)
 *         ERR_FSAL_BAD_INIT     (FS specific init error,
 *                                minor error code gives the reason
 *                                for this error.)
 *         ERR_FSAL_SEC_INIT     (Security context init error).
 */
fsal_status_t FUSEFSAL_Init(fsal_parameter_t * init_info        /* IN */
    )
{

  fsal_status_t status;
  int rc;

  /* sanity check.  */

  if(!init_info)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);

  /* proceeds FSAL internal status initialization */

  status = fsal_internal_init_global(&(init_info->fsal_info),
                                     &(init_info->fs_common_info));

  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_Init);

  /* initialize filesystem stuff */

  if(rc = FS_Specific_Init((fusefs_specific_initinfo_t *) &init_info->fs_specific_info))
    Return(ERR_FSAL_BAD_INIT, -rc, INDEX_FSAL_Init);

  /* Everything went OK. */

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init);

}
Ejemplo n.º 7
0
/**
 * FSAL_opendir :
 *     Opens a directory for reading its content.
 *
 * \param dir_handle (input)
 *         the handle of the directory to be opened.
 * \param p_context (input)
 *         Permission context for the operation (user, export context...).
 * \param dir_descriptor (output)
 *         pointer to an allocated structure that will receive
 *         directory stream informations, on successfull completion.
 * \param dir_attributes (optional output)
 *         On successfull completion,the structure pointed
 *         by dir_attributes receives the new directory attributes.
 *         Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_ACCESS       (user does not have read permission on directory)
 *        - ERR_FSAL_STALE        (dir_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_IO, ...
 */
fsal_status_t FUSEFSAL_opendir(fsal_handle_t * dir_hdl,  /* IN */
                               fsal_op_context_t * p_context,       /* IN */
                               fsal_dir_t * dir_desc,     /* OUT */
                               fsal_attrib_list_t * dir_attributes      /* [ IN/OUT ] */
    )
{
  int rc;
  char object_path[FSAL_MAX_PATH_LEN];
  fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc;
  fusefsal_handle_t * dir_handle = (fusefsal_handle_t *)dir_hdl;

  /* sanity checks
   * note : dir_attributes is optionnal.
   */
  if(!dir_handle || !p_context || !dir_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);

  /* get the full path for this directory */
  rc = NamespacePath(dir_handle->data.inode, dir_handle->data.device, dir_handle->data.validator,
                     object_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_opendir);

  memset(dir_descriptor, 0, sizeof(fsal_dir_t));

  /* set context for the next operation, so it can be retrieved by FS thread */
  fsal_set_thread_context(p_context);

  /* check opendir call */

  if(p_fs_ops->opendir)
    {
      TakeTokenFSCall();
      rc = p_fs_ops->opendir(object_path, &(dir_descriptor->dir_info));
      ReleaseTokenFSCall();

      if(rc)
        Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_opendir);
    }
  else
    {
      /* ignoring opendir */
      memset(&(dir_descriptor->dir_info), 0, sizeof(struct ganefuse_file_info));
    }

  /* fill the dir descriptor structure */
  dir_descriptor->dir_handle = *dir_handle;

  /* backup context */
  dir_descriptor->context = *(fusefsal_op_context_t *)p_context;

  /* optionaly get attributes */
  if(dir_attributes)
    {
      fsal_status_t status;

      status = FUSEFSAL_getattrs(dir_hdl, p_context, dir_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(dir_attributes->asked_attributes);
          FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);

}
Ejemplo n.º 8
0
/**
 * FSAL_readdir :
 *     Read the entries of an opened directory.
 *
 * \param dir_descriptor (input):
 *        Pointer to the directory descriptor filled by FSAL_opendir.
 * \param start_position (input):
 *        Cookie that indicates the first object to be read during
 *        this readdir operation.
 *        This should be :
 *        - FSAL_READDIR_FROM_BEGINNING for reading the content
 *          of the directory from the beginning.
 *        - The end_position parameter returned by the previous
 *          call to FSAL_readdir.
 * \param get_attr_mask (input)
 *        Specify the set of attributes to be retrieved for directory entries.
 * \param buffersize (input)
 *        The size (in bytes) of the buffer where
 *        the direntries are to be stored.
 * \param pdirent (output)
 *        Adresse of the buffer where the direntries are to be stored.
 * \param end_position (output)
 *        Cookie that indicates the current position in the directory.
 * \param nb_entries (output)
 *        Pointer to the number of entries read during the call.
 * \param end_of_dir (output)
 *        Pointer to a boolean that indicates if the end of dir
 *        has been reached during the call.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_IO, ...
 */
fsal_status_t FUSEFSAL_readdir(fsal_dir_t * dir_desc,     /* IN */
                               fsal_cookie_t start_position,        /* IN */
                               fsal_attrib_mask_t get_attr_mask,        /* IN */
                               fsal_mdsize_t buffersize,        /* IN */
                               fsal_dirent_t * pdirent, /* OUT */
                               fsal_cookie_t * end_position,        /* OUT */
                               fsal_count_t * nb_entries,       /* OUT */
                               fsal_boolean_t * end_of_dir      /* OUT */
    )
{
  int rc;
  char dir_path[FSAL_MAX_PATH_LEN];
  fsal_dirbuff_t reqbuff;
  unsigned int i;
  fsal_status_t st;
  fusefsal_dir_t * dir_descriptor = (fusefsal_dir_t *)dir_desc;

  /* sanity checks */

  if(!dir_descriptor || !pdirent || !end_position || !nb_entries || !end_of_dir)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);

  /* get the full path for dir inode */
  rc = NamespacePath(dir_descriptor->dir_handle.data.inode,
                     dir_descriptor->dir_handle.data.device,
                     dir_descriptor->dir_handle.data.validator, dir_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_readdir);

  if(!p_fs_ops->readdir && !p_fs_ops->getdir)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_readdir);

  /* set context so it can be retrieved by FS */
  fsal_set_thread_context((fsal_op_context_t *) &dir_descriptor->context);

  /* prepare reaadir structure */

  reqbuff.getattr_mask = get_attr_mask;
  reqbuff.nb_entries = 0;
  reqbuff.max_entries = (buffersize / sizeof(fsal_dirent_t));
  reqbuff.p_entries = pdirent;
  reqbuff.status.major = 0;
  reqbuff.status.minor = 0;
  memcpy( (char *)&reqbuff.begin_off, (char *)&start_position.data, sizeof( off_t ) ) ;
  reqbuff.curr_off = 0 ;

  TakeTokenFSCall();

  if(p_fs_ops->readdir)
    rc = p_fs_ops->readdir(dir_path, (void *)&reqbuff, ganefuse_fill_dir,
                           (off_t)start_position.data, &dir_descriptor->dir_info);
  else
    rc = p_fs_ops->getdir(dir_path, (ganefuse_dirh_t) & reqbuff, ganefuse_dirfil_old);

  ReleaseTokenFSCall();

  if(rc)
    Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_readdir);
  else if(FSAL_IS_ERROR(reqbuff.status))
    Return(reqbuff.status.major, reqbuff.status.minor, INDEX_FSAL_readdir);

  /* if no entry found */

  if(reqbuff.nb_entries == 0)
    {
      *end_position = start_position;
      *end_of_dir = TRUE;
      *nb_entries = 0;

      LogFullDebug(COMPONENT_FSAL, "No entries found");

      Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
    }

  /* at least 1 entry found */

  /* we must do some operations on the final dirent array:
   * - chaining entries together
   * - if the filesystem did not provide stat buffers,
   *   we must do lookup operations.
   * - adding dir entries to namespace
   */

  for(i = 0; i < reqbuff.nb_entries; i++)
    {
      /* 1) chaining entries together */

      if(i == reqbuff.nb_entries - 1)
        {                       /* last entry */
          pdirent[i].nextentry = NULL;
          *end_position = pdirent[i].cookie;
        }
      else
        pdirent[i].nextentry = &(pdirent[i + 1]);

      /* 2) check weither the filesystem provided stat buff */

      if(((fusefsal_handle_t *) &pdirent[i].handle)->data.inode == INODE_TO_BE_COMPLETED)
        {
          /* If not, make a lookup operation for this entry.
           * (this with automatically add it to namespace) */

          pdirent[i].attributes.asked_attributes = get_attr_mask;

          LogFullDebug(COMPONENT_FSAL, "Inode to be completed");

          st = FUSEFSAL_lookup((fsal_handle_t *) &dir_descriptor->dir_handle,
                               &pdirent[i].name,
                               (fsal_op_context_t *) &dir_descriptor->context,
                               &pdirent[i].handle, &pdirent[i].attributes);

          if(FSAL_IS_ERROR(st))
            Return(st.major, st.minor, INDEX_FSAL_readdir);
        }
      else
        {
          /* 3) just add entry to namespace except for '.' and '..'
           *    Also set a validator for this entry.
           */

          if(strcmp(pdirent[i].name.name, ".") && strcmp(pdirent[i].name.name, ".."))
            {
              LogFullDebug(COMPONENT_FSAL, "adding entry to namespace: %lX.%ld %s",
                     ((fusefsal_handle_t *) &pdirent[i].handle)->data.device,
                     ((fusefsal_handle_t *) &pdirent[i].handle)->data.inode, pdirent[i].name.name);

              ((fusefsal_handle_t *) &pdirent[i].handle)->data.validator = pdirent[i].attributes.ctime.seconds;

              NamespaceAdd(dir_descriptor->dir_handle.data.inode,
                           dir_descriptor->dir_handle.data.device,
                           dir_descriptor->dir_handle.data.validator,
                           pdirent[i].name.name,
                           ((fusefsal_handle_t *) &pdirent[i].handle)->data.inode,
                           ((fusefsal_handle_t *) &pdirent[i].handle)->data.device,
			   &(((fusefsal_handle_t *) &pdirent[i].handle)->data.validator));
            }
        }

    }

  /* end of dir was reached if not enough entries were provided */
  *end_of_dir = (reqbuff.nb_entries < reqbuff.max_entries);
  *nb_entries = reqbuff.nb_entries;

  LogFullDebug(COMPONENT_FSAL, "EOD = %d", *end_of_dir);

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);

}
Ejemplo n.º 9
0
fsal_status_t FUSEFSAL_rename(fusefsal_handle_t * old_parentdir_handle, /* IN */
                              fsal_name_t * p_old_name, /* IN */
                              fusefsal_handle_t * new_parentdir_handle, /* IN */
                              fsal_name_t * p_new_name, /* IN */
                              fusefsal_op_context_t * p_context,        /* IN */
                              fsal_attrib_list_t * src_dir_attributes,  /* [ IN/OUT ] */
                              fsal_attrib_list_t * tgt_dir_attributes   /* [ IN/OUT ] */
    )
{

  int rc = 0;
  char src_dir_path[FSAL_MAX_PATH_LEN];
  char tgt_dir_path[FSAL_MAX_PATH_LEN];
  char src_obj_path[FSAL_MAX_PATH_LEN];
  char tgt_obj_path[FSAL_MAX_PATH_LEN];

  /* sanity checks.
   * note : src/tgt_dir_attributes are optional.
   */
  if(!old_parentdir_handle ||
     !new_parentdir_handle || !p_old_name || !p_new_name || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  if(!p_fs_ops->rename)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_rename);

  /* get full path for parent source handle */
  rc = NamespacePath(old_parentdir_handle->data.inode, old_parentdir_handle->data.device,
                     old_parentdir_handle->data.validator, src_dir_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_rename);

  /* get full path for parent target handle */
  rc = NamespacePath(new_parentdir_handle->data.inode, new_parentdir_handle->data.device,
                     new_parentdir_handle->data.validator, tgt_dir_path);
  if(rc)
    Return(ERR_FSAL_STALE, rc, INDEX_FSAL_rename);

  /* build full path for source entry */
  FSAL_internal_append_path(src_obj_path, src_dir_path, p_old_name->name);

  /* build full path for target entry */
  FSAL_internal_append_path(tgt_obj_path, tgt_dir_path, p_new_name->name);

  /* set context for the next operation, so it can be retrieved by FS thread */
  fsal_set_thread_context(p_context);

  TakeTokenFSCall();

  rc = p_fs_ops->rename(src_obj_path, tgt_obj_path);

  ReleaseTokenFSCall();

  /* Regarding FALSE parameter of function fuse2fsal_error:
   * here, if error is ENOENT, we don't know weither the father handle is STALE
   * or if the source entry does not exist.
   * We choose returning ENOENT since the parent exists in the namespace,
   * so it it more likely to exist than the children.
   */
  if(rc)
    Return(fuse2fsal_error(rc, FALSE), rc, INDEX_FSAL_rename);

  /* If operation succeeded, impact the namespace */
  NamespaceRename(old_parentdir_handle->data.inode, old_parentdir_handle->data.device,
                  old_parentdir_handle->data.validator, p_old_name->name,
                  new_parentdir_handle->data.inode, new_parentdir_handle->data.device,
                  new_parentdir_handle->data.validator, p_new_name->name);

  /* Last parent post op attributes if asked */

  if(src_dir_attributes)
    {
      fsal_status_t st;

      st = FUSEFSAL_getattrs(old_parentdir_handle, p_context, src_dir_attributes);

      if(FSAL_IS_ERROR(st))
        {
          FSAL_CLEAR_MASK(src_dir_attributes->asked_attributes);
          FSAL_SET_MASK(src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  /* New parent post op attributes if asked */

  if(tgt_dir_attributes)
    {
      fsal_status_t st;

      /* optimization when src=tgt : */

      if(!FUSEFSAL_handlecmp(old_parentdir_handle, new_parentdir_handle, &st)
         && src_dir_attributes)
        {

          /* If source dir = target dir, we just copy the attributes.
           * to avoid doing another getattr.
           */

          (*tgt_dir_attributes) = (*src_dir_attributes);

        }
      else
        {

          /* get attributes */
          st = FUSEFSAL_getattrs(new_parentdir_handle, p_context, tgt_dir_attributes);

          if(FSAL_IS_ERROR(st))
            {
              FSAL_CLEAR_MASK(tgt_dir_attributes->asked_attributes);
              FSAL_SET_MASK(tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
            }

        }

    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);

}