Ejemplo n.º 1
0
/**
 * FSAL_access :
 * Tests whether the user or entity identified by its cred
 * can access the object identified by object_handle,
 * as indicated by the access_type parameters.
 *
 * \param object_handle (input):
 *        The handle of the object to test permissions on.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param access_type (input):
 *        Indicates the permissions to test.
 *        This is an inclusive OR of the permissions
 *        to be checked for the user identified by cred.
 *        Permissions constants are :
 *        - FSAL_R_OK : test for read permission
 *        - FSAL_W_OK : test for write permission
 *        - FSAL_X_OK : test for exec permission
 *        - FSAL_F_OK : test for file existence
 * \param object_attributes (optional input/output):
 *        The post operation attributes for the object.
 *        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).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occured.
 */
fsal_status_t VFSFSAL_access(fsal_handle_t * p_object_handle,      /* IN */
                          fsal_op_context_t * p_context,        /* IN */
                          fsal_accessflags_t access_type,       /* IN */
                          fsal_attrib_list_t * p_object_attributes      /* [ IN/OUT ] */
    )
{

  fsal_status_t status;

  /* sanity checks.
   * note : object_attributes is optionnal in VFSFSAL_getattrs.
   */
  if(!p_object_handle || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_access);

  /* 
   * If an error occures during getattr operation,
   * it is returned, even though the access operation succeeded.
   */

  if(p_object_attributes)
    {

      FSAL_SET_MASK(p_object_attributes->asked_attributes,
                    FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE);
      status = VFSFSAL_getattrs(p_object_handle, p_context, p_object_attributes);

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

      status =
          fsal_internal_testAccess(p_context, access_type, NULL, p_object_attributes);

    }
  else
    {                           /* p_object_attributes is NULL */
      fsal_attrib_list_t attrs;

      FSAL_CLEAR_MASK(attrs.asked_attributes);
      FSAL_SET_MASK(attrs.asked_attributes,
                    FSAL_ATTR_OWNER | FSAL_ATTR_GROUP | FSAL_ATTR_ACL | FSAL_ATTR_MODE);

      status = VFSFSAL_getattrs(p_object_handle, p_context, &attrs);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        Return(status.major, status.minor, INDEX_FSAL_access);

      status = fsal_internal_testAccess(p_context, access_type, NULL, &attrs);
    }

  Return(status.major, status.minor, INDEX_FSAL_access);

}
Ejemplo n.º 2
0
fsal_status_t WRAP_VFSFSAL_getattrs(fsal_handle_t * p_filehandle,       /* IN */
                                    fsal_op_context_t * p_context,      /* IN */
                                    fsal_attrib_list_t *
                                    p_object_attributes /* IN/OUT */ )
{
  return VFSFSAL_getattrs((vfsfsal_handle_t *) p_filehandle,
                          (vfsfsal_op_context_t *) p_context, p_object_attributes);
}
Ejemplo n.º 3
0
fsal_status_t VFSFSAL_readdir(vfsfsal_dir_t * p_dir_descriptor, /* IN */
                              vfsfsal_cookie_t start_position,  /* IN */
                              fsal_attrib_mask_t get_attr_mask, /* IN */
                              fsal_mdsize_t buffersize, /* IN */
                              fsal_dirent_t * p_pdirent,        /* OUT */
                              vfsfsal_cookie_t * p_end_position,        /* OUT */
                              fsal_count_t * p_nb_entries,      /* OUT */
                              fsal_boolean_t * p_end_of_dir     /* OUT */
    )
{
  fsal_status_t st;
  fsal_count_t max_dir_entries;
  char buff[BUF_SIZE];
  struct linux_dirent *dp = NULL;
  int bpos = 0;
  int tmpfd = 0;

  char d_type;
  struct stat buffstat;

  int errsv = 0, rc = 0;

  memset(buff, 0, BUF_SIZE);

  /*****************/
  /* sanity checks */
  /*****************/

  if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);

  max_dir_entries = (buffersize / sizeof(fsal_dirent_t));

  /***************************/
  /* seek into the directory */
  /***************************/
  errno = 0;
  if(start_position.data.cookie == 0)
    {
      //rewinddir(p_dir_descriptor->p_dir);
      rc = errno;
    }
  else
    {
      //seekdir(p_dir_descriptor->p_dir, start_position.cookie);
      rc = errno;
    }

  if(rc)
    Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);

  /************************/
  /* browse the directory */
  /************************/

  *p_nb_entries = 0;
  while(*p_nb_entries < max_dir_entries)
    {
    /***********************/
      /* read the next entry */
    /***********************/
      TakeTokenFSCall();
      rc = syscall(SYS_getdents, p_dir_descriptor->fd, buff, BUF_SIZE);
      ReleaseTokenFSCall();
      if(rc < 0)
        {
          rc = errno;
          Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir);
        }
      /* End of directory */
      if(rc == 0)
        {
          *p_end_of_dir = 1;
          break;
        }

    /***********************************/
      /* Get information about the entry */
    /***********************************/

      for(bpos = 0; bpos < rc;)
        {
          dp = (struct linux_dirent *)(buff + bpos);
          d_type = *(buff + bpos + dp->d_reclen - 1);
                                                    /** @todo not used for the moment. Waiting for information on symlink management */
          bpos += dp->d_reclen;

          /* LogFullDebug(COMPONENT_FSAL, "\tino=%8ld|%8lx off=%d|%x reclen=%d|%x name=%s|%d", dp->d_ino, dp->d_ino, (int)dp->d_off, (int)dp->d_off, 
             dp->d_reclen, dp->d_reclen, dp->d_name, (int)dp->d_name[0]  ) ; */

          if(!(*p_nb_entries < max_dir_entries))
            break;

          /* skip . and .. */
          if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
            continue;

          /* build the full path of the file into "fsalpath */
          if(FSAL_IS_ERROR
             (st =
              FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN,
                            &(p_pdirent[*p_nb_entries].name))))
            ReturnStatus(st, INDEX_FSAL_readdir);

          d_type = DT_UNKNOWN;
          if((tmpfd =
              openat(p_dir_descriptor->fd, dp->d_name, O_RDONLY | O_NOFOLLOW, 0600)) < 0)
            {
              if(errno != ELOOP)        /* ( p_dir_descriptor->fd, dp->d_name) is not a symlink */
                Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_readdir);
              else
                d_type = DT_LNK;
            }

          /* get object handle */
          TakeTokenFSCall();
          if(d_type != DT_LNK)
            {
              vfsfsal_handle_t *tmp_handle =
                  (vfsfsal_handle_t *) (&(p_pdirent[*p_nb_entries].handle));

              st = fsal_internal_fd2handle(&p_dir_descriptor->context, tmpfd, tmp_handle);
              close(tmpfd);
            }
          else
            {
              vfsfsal_handle_t *tmp_handle =
                  (vfsfsal_handle_t *) (&(p_pdirent[*p_nb_entries].handle));

              if(fstatat(p_dir_descriptor->fd, dp->d_name, &buffstat, AT_SYMLINK_NOFOLLOW)
                 < 0)
                {
                  ReleaseTokenFSCall();
                  Return(posix2fsal_error(errno), errno, INDEX_FSAL_readdir);
                }

              st = fsal_internal_get_handle_at( p_dir_descriptor->fd, dp->d_name, tmp_handle ) ;
              if(FSAL_IS_ERROR(st))
                {
                  ReleaseTokenFSCall();
                  ReturnStatus(st, INDEX_FSAL_readdir);
                }
              p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask;

              st = posix2fsal_attributes(&buffstat, &p_pdirent[*p_nb_entries].attributes);
              if(FSAL_IS_ERROR(st))
                {
                  ReleaseTokenFSCall();
                  FSAL_CLEAR_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes);
                  FSAL_SET_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes,
                                FSAL_ATTR_RDATTR_ERR);
                  ReturnStatus(st, INDEX_FSAL_getattrs);
                }

            }
          ReleaseTokenFSCall();

          if(FSAL_IS_ERROR(st))
            ReturnStatus(st, INDEX_FSAL_readdir);

    /************************
     * Fills the attributes *
     ************************/
          if(d_type != DT_LNK)
            {
              p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask;

              st = VFSFSAL_getattrs((vfsfsal_handle_t
                                     *) (&(p_pdirent[*p_nb_entries].handle)),
                                    (vfsfsal_op_context_t *) & p_dir_descriptor->context,
                                    &p_pdirent[*p_nb_entries].attributes);
              if(FSAL_IS_ERROR(st))
                {
                  FSAL_CLEAR_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes);
                  FSAL_SET_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes,
                                FSAL_ATTR_RDATTR_ERR);
                }
            }
          //p_pdirent[*p_nb_entries].cookie.cookie = dp->d_off;
          ((vfsfsal_cookie_t *) (&p_pdirent[*p_nb_entries].cookie))->data.cookie = dp->d_off;
          p_pdirent[*p_nb_entries].nextentry = NULL;
          if(*p_nb_entries)
            p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]);

          //(*p_end_position) = p_pdirent[*p_nb_entries].cookie;
          memcpy((char *)p_end_position, (char *)&p_pdirent[*p_nb_entries].cookie,
                 sizeof(vfsfsal_cookie_t));

          (*p_nb_entries)++;

        }                       /* for */
    }                           /* While */

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);

}
Ejemplo n.º 4
0
fsal_status_t VFSFSAL_rename(fsal_handle_t * p_old_parentdir_handle,       /* IN */
                          fsal_name_t * p_old_name,     /* IN */
                          fsal_handle_t * p_new_parentdir_handle,       /* IN */
                          fsal_name_t * p_new_name,     /* IN */
                          fsal_op_context_t * p_context,        /* IN */
                          fsal_attrib_list_t * p_src_dir_attributes,    /* [ IN/OUT ] */
                          fsal_attrib_list_t * p_tgt_dir_attributes     /* [ IN/OUT ] */
    )
{

  int rc, errsv;
  fsal_status_t status;
  struct stat old_parent_buffstat, new_parent_buffstat, buffstat;
  int old_parent_fd, new_parent_fd;
  int src_equal_tgt = FALSE;
  uid_t user = ((vfsfsal_op_context_t *)p_context)->credential.user;

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

  /* Get directory access path by fid */

  TakeTokenFSCall();
  status = fsal_internal_handle2fd(p_context, p_old_parentdir_handle,
                                   &old_parent_fd,
                                   O_RDONLY | O_DIRECTORY);
  ReleaseTokenFSCall();

  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_rename);

  /* retrieve directory metadata for checking access rights */

  TakeTokenFSCall();
  rc = fstat(old_parent_fd, &old_parent_buffstat);
  errsv = errno;
  ReleaseTokenFSCall();

  if(rc)
    {
      close(old_parent_fd);
      if(errsv == ENOENT)
        Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename);
      else
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
    }

  /* optimisation : don't do the job twice if source dir = dest dir  */
  if(!FSAL_handlecmp(p_old_parentdir_handle, p_new_parentdir_handle, &status))
    {
      new_parent_fd = old_parent_fd;
      src_equal_tgt = TRUE;
      new_parent_buffstat = old_parent_buffstat;
    }
  else
    {
      TakeTokenFSCall();
      status = fsal_internal_handle2fd(p_context, p_new_parentdir_handle,
                                       &new_parent_fd,
                                       O_RDONLY | O_DIRECTORY);
      ReleaseTokenFSCall();

      if(FSAL_IS_ERROR(status))
        {
          close(old_parent_fd);
          ReturnStatus(status, INDEX_FSAL_rename);
        }
      /* retrieve destination attrs */
      TakeTokenFSCall();
      rc = fstat(new_parent_fd, &new_parent_buffstat);
      errsv = errno;
      ReleaseTokenFSCall();

      if(rc)
        {
          /* close old and new parent fd */
          close(old_parent_fd);
          close(new_parent_fd);
          if(errsv == ENOENT)
            Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_rename);
          else
            Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
        }

    }

  /* check access rights */

  status = fsal_check_access(p_context, FSAL_W_OK | FSAL_X_OK,
                                    &old_parent_buffstat,
                                    NULL);
  if(FSAL_IS_ERROR(status)) {
    close(old_parent_fd);
    if (!src_equal_tgt)
      close(new_parent_fd);
    ReturnStatus(status, INDEX_FSAL_rename);
  }
  if(!src_equal_tgt)
    {
      status =  fsal_check_access(p_context, FSAL_W_OK | FSAL_X_OK,
                                         &new_parent_buffstat,
                                         NULL);
      if(FSAL_IS_ERROR(status)) {
        close(old_parent_fd);
        close(new_parent_fd);
        ReturnStatus(status, INDEX_FSAL_rename);
      }
    }

  /* build file paths */
  TakeTokenFSCall();
  rc = fstatat(old_parent_fd, p_old_name->name, &buffstat, AT_SYMLINK_NOFOLLOW);
  errsv = errno;
  ReleaseTokenFSCall();
  if(rc) {
    close(old_parent_fd);
    if (!src_equal_tgt)
      close(new_parent_fd);
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
  }

  /* Check sticky bits */

  /* Sticky bit on the source directory => the user who wants to delete the file must own it or its parent dir */
  if((old_parent_buffstat.st_mode & S_ISVTX) &&
     old_parent_buffstat.st_uid != user &&
     buffstat.st_uid != user && user != 0) {
    close(old_parent_fd);
    if (!src_equal_tgt)
      close(new_parent_fd);
    Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
  }

  /* Sticky bit on the target directory => the user who wants to create the file must own it or its parent dir */
  if(new_parent_buffstat.st_mode & S_ISVTX)
    {
      TakeTokenFSCall();
      rc = fstatat(new_parent_fd, p_new_name->name, &buffstat, AT_SYMLINK_NOFOLLOW);
      errsv = errno;
      ReleaseTokenFSCall();

      if(rc < 0)
        {
          if(errsv != ENOENT)
            {
              close(old_parent_fd);
              if (!src_equal_tgt)
                close(new_parent_fd);
              Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);
            }
        }
      else
        {

          if(new_parent_buffstat.st_uid != user
             && buffstat.st_uid != user
             && user != 0)
            {
              close(old_parent_fd);
              if (!src_equal_tgt)
                close(new_parent_fd);
              Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename);
            }
        }
    }

  /*************************************
   * Rename the file on the filesystem *
   *************************************/
  TakeTokenFSCall();
  rc = renameat(old_parent_fd, p_old_name->name, new_parent_fd, p_new_name->name);
  errsv = errno;
  ReleaseTokenFSCall();
  close(old_parent_fd);
  if (!src_equal_tgt)
    close(new_parent_fd);

  if(rc)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_rename);

  /***********************
   * Fill the attributes *
   ***********************/

  if(p_src_dir_attributes)
    {

      status = VFSFSAL_getattrs(p_old_parentdir_handle, p_context, p_src_dir_attributes);

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(p_src_dir_attributes->asked_attributes);
          FSAL_SET_MASK(p_src_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  if(p_tgt_dir_attributes)
    {

      status = VFSFSAL_getattrs(p_new_parentdir_handle, p_context, p_tgt_dir_attributes);

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(p_tgt_dir_attributes->asked_attributes);
          FSAL_SET_MASK(p_tgt_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

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

}
Ejemplo n.º 5
0
/**
 * VFSFSAL_setattrs:
 * Set attributes for the object specified by its filehandle.
 *
 * \param filehandle (input):
 *        The handle of the object to get parameters.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param attrib_set (mandatory input):
 *        The attributes to be set for the object.
 *        It defines the attributes that the caller
 *        wants to set and their values.
 * \param object_attributes (optionnal input/output):
 *        The post operation attributes for the object.
 *        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).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occured.
 */
fsal_status_t VFSFSAL_setattrs(fsal_handle_t * p_filehandle,       /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * p_attrib_set,  /* IN */
                            fsal_attrib_list_t * p_object_attributes    /* [ IN/OUT ] */
    )
{
  vfsfsal_op_context_t * vfs_context = (vfsfsal_op_context_t *) p_context;
  int rc, errsv;
  unsigned int i;
  fsal_status_t status;
  fsal_attrib_list_t attrs;

  int fd;
  struct stat buffstat;

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

  /* local copy of attributes */
  attrs = *p_attrib_set;

  /* It does not make sense to setattr on a symlink */
  /* if(p_filehandle->type == DT_LNK)
     return fsal_internal_setattrs_symlink(p_filehandle, p_context, p_attrib_set,
     p_object_attributes);
   */
  /* First, check that FSAL attributes changes are allowed. */

  /* Is it allowed to change times ? */

  if(!global_fs_info.cansettime)
    {

      if(attrs.asked_attributes
         & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
        {
          /* handled as an unsettable attribute. */
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
        }
    }

  /* apply umask, if mode attribute is to be changed */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      attrs.mode &= (~global_fs_info.umask);
    }

  TakeTokenFSCall();
  status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDONLY);
  ReleaseTokenFSCall();
  if(FSAL_IS_ERROR(status))
   {
     /* Symbolic link are handled here, they are to be opened as O_PATH */
     if( status.minor == ELOOP )
      {
           if(p_object_attributes)
             {
               status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

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

     ReturnStatus( status, INDEX_FSAL_setattrs);
   }

  /* get current attributes */
  TakeTokenFSCall();
  rc = fstat(fd, &buffstat);
  errsv = errno;
  ReleaseTokenFSCall();

  if(rc != 0)
    {
      close(fd);

      if(errsv == ENOENT)
        Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_setattrs);
      else
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
    }

  /***********
   *  CHMOD  *
   ***********/
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {

      /* The POSIX chmod call don't affect the symlink object, but
       * the entry it points to. So we must ignore it.
       */
      if(!S_ISLNK(buffstat.st_mode))
        {

          /* For modifying mode, user must be root or the owner */
          if((vfs_context->credential.user != 0)
             && (vfs_context->credential.user != buffstat.st_uid))
            {
              LogFullDebug(COMPONENT_FSAL,
                           "Permission denied for CHMOD opeartion: current owner=%d, credential=%d",
                           buffstat.st_uid, vfs_context->credential.user);
              close(fd);
              Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
            }

          TakeTokenFSCall();
          rc = fchmod(fd, fsal2unix_mode(attrs.mode));
          errsv = errno;
          ReleaseTokenFSCall();

          if(rc)
            {
              close(fd);
              Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
            }

        }

    }

  /***********
   *  CHOWN  *
   ***********/
  /* Only root can change uid and A normal user must be in the group he wants to set */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
    {

      /* For modifying owner, user must be root or current owner==wanted==client */
      if((vfs_context->credential.user != 0) &&
         ((vfs_context->credential.user != buffstat.st_uid) ||
          (vfs_context->credential.user != attrs.owner)))
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d",
                       buffstat.st_uid, vfs_context->credential.user, attrs.owner);
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
    {

      /* For modifying group, user must be root or current owner */
      if((vfs_context->credential.user != 0)
         && (vfs_context->credential.user != buffstat.st_uid))
        {
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }

      int in_grp = 0;
      /* set in_grp */
      if(vfs_context->credential.group == attrs.group)
        in_grp = 1;
      else
        for(i = 0; i < vfs_context->credential.nbgroups; i++)
          {
            if((in_grp = (attrs.group == vfs_context->credential.alt_groups[i])))
              break;
          }

      /* it must also be in target group */
      if(vfs_context->credential.user != 0 && !in_grp)
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d",
                       buffstat.st_gid, vfs_context->credential.group, attrs.group);
          close(fd);
          Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
        }
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
    {
      /*      LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)",
                        fsalpath.path, FSAL_TEST_MASK(attrs.asked_attributes,
                                                      FSAL_ATTR_OWNER) ? (int)attrs.owner
                        : -1, FSAL_TEST_MASK(attrs.asked_attributes,
			FSAL_ATTR_GROUP) ? (int)attrs.group : -1);*/

      TakeTokenFSCall();
      rc = fchown(fd,
                  FSAL_TEST_MASK(attrs.asked_attributes,
                                 FSAL_ATTR_OWNER) ? (int)attrs.owner : -1,
                  FSAL_TEST_MASK(attrs.asked_attributes,
                                 FSAL_ATTR_GROUP) ? (int)attrs.group : -1);
      ReleaseTokenFSCall();
      if(rc)
        {
          close(fd);
          Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
        }
    }

  /***********
   *  UTIME  *
   ***********/

  /* user must be the owner or have read access to modify 'atime' */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME)
     && (vfs_context->credential.user != 0)
     && (vfs_context->credential.user != buffstat.st_uid)
     && ((status = fsal_check_access(p_context, FSAL_R_OK, &buffstat, NULL)).major
         != ERR_FSAL_NO_ERROR))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }
  /* user must be the owner or have write access to modify 'mtime' */
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME)
     && (vfs_context->credential.user != 0)
     && (vfs_context->credential.user != buffstat.st_uid)
     && ((status = fsal_check_access(p_context, FSAL_W_OK, &buffstat, NULL)).major
         != ERR_FSAL_NO_ERROR))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_setattrs);
    }

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
    {

      struct timeval timebuf[2];

      /* Atime */
      timebuf[0].tv_sec =
          (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t) attrs.
           atime.seconds : buffstat.st_atime);
      timebuf[0].tv_usec = 0;

      /* Mtime */
      timebuf[1].tv_sec =
          (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t) attrs.
           mtime.seconds : buffstat.st_mtime);
      timebuf[1].tv_usec = 0;

      TakeTokenFSCall();
      rc = futimes(fd, timebuf);
      errsv = errno;
      ReleaseTokenFSCall();
      if(rc)
        {
          close(fd);
          Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
        }
    }

  /* Optionaly fills output attributes. */

  if(p_object_attributes)
    {
      status = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

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

    }

  close(fd);
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);

}
Ejemplo n.º 6
0
fsal_status_t VFSFSAL_truncate(fsal_handle_t * p_filehandle,       /* 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 * p_object_attributes    /* [ IN/OUT ] */
    )
{

  int rc, errsv;
  int fd;
  fsal_status_t st;

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

  /* get the path of the file and its handle */
  TakeTokenFSCall();
  st = fsal_internal_handle2fd(p_context, p_filehandle, &fd, O_RDWR);
  ReleaseTokenFSCall();

  if(FSAL_IS_ERROR(st))
    ReturnStatus(st, INDEX_FSAL_truncate);

  /* Executes the POSIX truncate operation */

  TakeTokenFSCall();
  rc = ftruncate(fd, length);
  errsv = errno;
  ReleaseTokenFSCall();

  close(fd);

  /* convert return code */
  if(rc)
    {
      if(errsv == ENOENT)
        Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_truncate);
      else
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_truncate);
    }

  /* Optionally retrieve attributes */
  if(p_object_attributes)
    {

      fsal_status_t st;

      st = VFSFSAL_getattrs(p_filehandle, p_context, p_object_attributes);

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

    }

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

}