예제 #1
0
int nfs4_op_readlink(struct nfs_argop4 *op, compound_data_t *data,
		     struct nfs_resop4 *resp)
{
	READLINK4res * const res_READLINK4 = &resp->nfs_resop4_u.opreadlink;
	cache_inode_status_t cache_status;
	struct gsh_buffdesc link_buffer = {.addr = NULL,
		.len = 0
	};

	resp->resop = NFS4_OP_READLINK;
	res_READLINK4->status = NFS4_OK;

	/*
	 * Do basic checks on a filehandle You can readlink only on a link
	 * ...
	 */
	res_READLINK4->status =
	    nfs4_sanity_check_FH(data, SYMBOLIC_LINK, false);

	if (res_READLINK4->status != NFS4_OK)
		return res_READLINK4->status;

	/* Using cache_inode_readlink */
	cache_status = cache_inode_readlink(data->current_entry, &link_buffer);

	if (cache_status != CACHE_INODE_SUCCESS) {
		res_READLINK4->status = nfs4_Errno(cache_status);
		return res_READLINK4->status;
	}

	res_READLINK4->READLINK4res_u.resok4.link.utf8string_val =
	    link_buffer.addr;

	/* NFSv4 does not require the \NUL terminator. */
	res_READLINK4->READLINK4res_u.resok4.link.utf8string_len =
	    link_buffer.len - 1;

	res_READLINK4->status = NFS4_OK;
	return res_READLINK4->status;
}				/* nfs4_op_readlink */

/**
 * @brief Free memory allocated for READLINK result
 *
 * This function frees the memory allocated for the resutl of the
 * NFS4_OP_READLINK operation.
 *
 * @param[in,out] resp nfs4_op results
*/
void nfs4_op_readlink_Free(nfs_resop4 *res)
{
	READLINK4res *resp = &res->nfs_resop4_u.opreadlink;

	if (resp->status == NFS4_OK
	    && resp->READLINK4res_u.resok4.link.utf8string_val)
		gsh_free(resp->READLINK4res_u.resok4.link.utf8string_val);
	return;
}				/* nfs4_op_readlink_Free */
예제 #2
0
int _9p_readlink(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;

	struct _9p_fid *pfid = NULL;

	cache_inode_status_t cache_status;
	struct gsh_buffdesc link_buffer = {.addr = NULL,
		.len = 0
	};

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);

	LogDebug(COMPONENT_9P, "TREADLINK: tag=%u fid=%u", (u32) *msgtag,
		 *fid);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply);

	pfid = req9p->pconn->fids[*fid];

	/* Check that it is a valid fid */
	if (pfid == NULL || pfid->pentry == NULL) {
		LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid);
		return _9p_rerror(req9p, msgtag, EIO, plenout, preply);
	}

	_9p_init_opctx(pfid, req9p);

	/* let's do the job */
	cache_status =
	    cache_inode_readlink(pfid->pentry, &link_buffer);

	if (cache_status != CACHE_INODE_SUCCESS)
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);

	/* Build the reply */
	_9p_setinitptr(cursor, preply, _9P_RREADLINK);
	_9p_setptr(cursor, msgtag, u16);

	_9p_setstr(cursor, link_buffer.len - 1, link_buffer.addr);

	_9p_setendptr(cursor, preply);
	_9p_checkbound(cursor, preply, plenout);

	LogDebug(COMPONENT_9P, "RREADLINK: tag=%u fid=%u link=%s", *msgtag,
		 (u32) *fid, (char *) link_buffer.addr);

	gsh_free(link_buffer.addr);
	return 1;
}
예제 #3
0
int nfs4_op_readlink(struct nfs_argop4 *op,
                     compound_data_t * data, struct nfs_resop4 *resp)
{
  cache_inode_status_t cache_status;
  fsal_path_t symlink_path;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_readlink";

  resp->resop = NFS4_OP_READLINK;
  res_READLINK4.status = NFS4_OK;

  /* If there is no FH */
  if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
      res_READLINK4.status = NFS4ERR_NOFILEHANDLE;
      return NFS4ERR_NOFILEHANDLE;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
      res_READLINK4.status = NFS4ERR_BADHANDLE;
      return NFS4ERR_BADHANDLE;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
      res_READLINK4.status = NFS4ERR_FHEXPIRED;
      return NFS4ERR_FHEXPIRED;
    }

  /* You can readlink only on a link ... */
  if(data->current_filetype != SYMBOLIC_LINK)
    {
      /* As said on page 194 of RFC3530, return NFS4ERR_INVAL in this case */
      res_READLINK4.status = NFS4ERR_INVAL;
      return res_READLINK4.status;
    }

  /* Using cache_inode_readlink */
  if(cache_inode_readlink(data->current_entry,
                          &symlink_path,
                          data->ht,
                          data->pclient,
                          data->pcontext, &cache_status) == CACHE_INODE_SUCCESS)
    {
      /* Alloc read link */

      if((res_READLINK4.READLINK4res_u.resok4.link.utf8string_val =
          (char *)Mem_Alloc_Label(symlink_path.len, "nfs4_op_readlink")) == NULL)
        {
          res_READLINK4.status = NFS4ERR_INVAL;
          return res_READLINK4.status;
        }

      /* convert the fsal path to a utf8 string */
      if(str2utf8((char *)symlink_path.path, &res_READLINK4.READLINK4res_u.resok4.link)
         == -1)
        {
          res_READLINK4.status = NFS4ERR_INVAL;
          return res_READLINK4.status;
        }

      res_READLINK4.status = NFS4_OK;
      return res_READLINK4.status;
    }

  res_READLINK4.status = nfs4_Errno(cache_status);
  return res_READLINK4.status;
}                               /* nfs4_op_readlink */
예제 #4
0
int _9p_readlink( _9p_request_data_t * preq9p, 
                  void  * pworker_data,
                  u32 * plenout, 
                  char * preply)
{
  char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ;
  nfs_worker_data_t * pwkrdata = (nfs_worker_data_t *)pworker_data ;

  u16 * msgtag = NULL ;
  u32 * fid    = NULL ;

  _9p_fid_t * pfid = NULL ;

  int rc = 0 ; 
  int err = 0 ;

  fsal_path_t symlink_data;
  cache_inode_status_t cache_status ;

  if ( !preq9p || !pworker_data || !plenout || !preply )
   return -1 ;
  /* Get data */
  _9p_getptr( cursor, msgtag, u16 ) ; 
  _9p_getptr( cursor, fid,    u32 ) ; 

  LogDebug( COMPONENT_9P, "TREADLINK: tag=%u fid=%u",(u32)*msgtag, *fid ) ;
             
  if( *fid >= _9P_FID_PER_CONN )
    {
      err = ERANGE ;
      rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ;
      return rc ;
    }

  pfid = &preq9p->pconn->fids[*fid] ;

  /* let's do the job */
  if( cache_inode_readlink( pfid->pentry,
 		            &symlink_data,
                            pwkrdata->ht,
                            &pwkrdata->cache_inode_client,
                            &pfid->fsal_op_context, 
                            &cache_status ) != CACHE_INODE_SUCCESS )
    {
      err = _9p_tools_errno( cache_status ) ; ;
      rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ;
      return rc ;
    }

  /* Build the reply */
  _9p_setinitptr( cursor, preply, _9P_RREADLINK ) ;
  _9p_setptr( cursor, msgtag, u16 ) ;

  _9p_setstr( cursor, strlen( symlink_data.path ), symlink_data.path ) ;

  _9p_setendptr( cursor, preply ) ;
  _9p_checkbound( cursor, preply, plenout ) ;

  LogDebug( COMPONENT_9P, "RREADLINK: tag=%u fid=%u link=%s", *msgtag, (u32)*fid, symlink_data.path ) ;

  return 1 ;
}
예제 #5
0
int nfs_Readlink(nfs_arg_t * parg,
                 exportlist_t * pexport,
                 fsal_op_context_t * pcontext,
                 cache_inode_client_t * pclient,
                 hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres)
{
  static char __attribute__ ((__unused__)) funcName[] = "nfs_Readlink";

  cache_entry_t *pentry = NULL;
  fsal_attrib_list_t attr;
  cache_inode_file_type_t filetype;
  cache_inode_status_t cache_status;
  int rc;
  fsal_path_t symlink_data;
  char *ptr = NULL;

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_readlink3.READLINK3res_u.resfail.symlink_attributes.attributes_follow =
          FALSE;
    }
  /* Convert file handle into a vnode */
  if((pentry = nfs_FhandleToCache(preq->rq_vers,
                                  &(parg->arg_readlink2),
                                  &(parg->arg_readlink3.symlink),
                                  NULL,
                                  &(pres->res_readlink2.status),
                                  &(pres->res_readlink3.status),
                                  NULL, &attr, pcontext, pclient, ht, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* Extract the filetype */
  filetype = cache_inode_fsal_type_convert(attr.type);

  /* Sanity Check: the pentry must be a link */
  if(filetype != SYMBOLIC_LINK)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_readlink2.status = NFSERR_IO;
          break;

        case NFS_V3:
          pres->res_readlink3.status = NFS3ERR_INVAL;
        }                       /* switch */
      return NFS_REQ_OK;
    }

  /* if */
  /* Perform readlink on the pentry */
  if(cache_inode_readlink(pentry,
                          &symlink_data,
                          ht, pclient, pcontext, &cache_status) == CACHE_INODE_SUCCESS)
    {
      if((ptr = Mem_Alloc(FSAL_MAX_NAME_LEN)) == NULL)
        {
          switch (preq->rq_vers)
            {
            case NFS_V2:
              pres->res_readlink2.status = NFSERR_NXIO;
              break;

            case NFS_V3:
              pres->res_readlink3.status = NFS3ERR_IO;
            }                   /* switch */
          return NFS_REQ_OK;
        }

      strcpy(ptr, symlink_data.path);

      /* Reply to the client (think about Mem_Free data after use ) */
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_readlink2.READLINK2res_u.data = ptr;
          pres->res_readlink2.status = NFS_OK;
          break;

        case NFS_V3:
          pres->res_readlink3.READLINK3res_u.resok.data = ptr;
          nfs_SetPostOpAttr(pcontext, pexport,
                            pentry,
                            &attr,
                            &(pres->res_readlink3.READLINK3res_u.resok.
                              symlink_attributes));
          pres->res_readlink3.status = NFS3_OK;
          break;
        }
      return NFS_REQ_OK;
    }

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      return NFS_REQ_DROP;
    }

  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_readlink2.status,
                      &pres->res_readlink3.status,
                      pentry,
                      &(pres->res_readlink3.READLINK3res_u.resfail.symlink_attributes),
                      NULL, NULL, NULL, NULL, NULL, NULL);

  return NFS_REQ_OK;
}                               /* nfs_Readlink */
예제 #6
0
int nfs3_readlink(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	cache_entry_t *entry = NULL;
	cache_inode_status_t cache_status;
	struct gsh_buffdesc link_buffer = {
		.addr = NULL,
		.len = 0
	};
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers,
				 &(arg->arg_readlink3.symlink),
				 NULL, str);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Readlink handle: %s",
			 str);
	}

	/* to avoid setting it on each error case */
	res->res_readlink3.READLINK3res_u.resfail.symlink_attributes.
	    attributes_follow = false;

	entry = nfs3_FhandleToCache(&arg->arg_readlink3.symlink,
				    &res->res_readlink3.status,
				    &rc);

	if (entry == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	/* Sanity Check: the entry must be a link */
	if (entry->type != SYMBOLIC_LINK) {
		res->res_readlink3.status = NFS3ERR_INVAL;
		rc = NFS_REQ_OK;
		goto out;
	}

	cache_status = cache_inode_readlink(entry, &link_buffer);

	if (cache_status != CACHE_INODE_SUCCESS) {
		res->res_readlink3.status = nfs3_Errno(cache_status);
		nfs_SetPostOpAttr(entry,
				  &res->res_readlink3.READLINK3res_u.resfail.
				  symlink_attributes);

		if (nfs_RetryableError(cache_status))
			rc = NFS_REQ_DROP;

		goto out;
	}

	/* Reply to the client */
	res->res_readlink3.READLINK3res_u.resok.data = link_buffer.addr;

	nfs_SetPostOpAttr(entry,
			  &res->res_readlink3.READLINK3res_u.
			  resok.symlink_attributes);
	res->res_readlink3.status = NFS3_OK;

	rc = NFS_REQ_OK;

 out:
	/* return references */
	if (entry)
		cache_inode_put(entry);

	return rc;
}				/* nfs3_readlink */

/**
 * @brief Free the result structure allocated for nfs3_readlink.
 *
 * This function frees the result structure allocated for
 * nfs3_readlink.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_readlink_free(nfs_res_t *res)
{
	if (res->res_readlink3.status == NFS3_OK)
		gsh_free(res->res_readlink3.READLINK3res_u.resok.data);
}