// SPDX-License-Identifier: LGPL-3.0-or-later
/*
 * vim:noexpandtab:shiftwidth=8:tabstop=8:
 *
 * Copyright CEA/DAM/DIF  (2008)
 * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
 *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * ---------------------------------------
 */

/**
 * @file  nfs3_getattr.c
 * @brief Implements the NFSv3 GETATTR proc
 */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/file.h> /* for having FNDELAY */
#include "hashtable.h"
#include "log.h"
#include "gsh_rpc.h"
#include "nfs23.h"
#include "nfs4.h"
#include "mount.h"
#include "nfs_core.h"
#include "nfs_exports.h"
#include "nfs_proto_functions.h"
#include "nfs_convert.h"
#include "nfs_proto_tools.h"

/**
 *
 * @brief Get attributes for a file
 *
 * Get attributes for a file. Implements NFSPROC3_GETATTR.
 *
 * @param[in]  arg     NFS arguments union
 * @param[in]  req     SVC request related to this call
 * @param[out] res     Structure to contain the result of the call
 *
 * @retval NFS_REQ_OK if successful
 * @retval NFS_REQ_DROP if failed but retryable
 * @retval NFS_REQ_FAILED if failed and not retryable
 */

int nfs3_getattr(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *obj = NULL;
	int rc = NFS_REQ_OK;
	struct fsal_attrlist *attrs;
	fsal_status_t status;

	attrs = &res->res_getattr3.GETATTR3res_u.resok.obj_attributes;

	LogNFS3_Operation(COMPONENT_NFSPROTO, req, &arg->arg_getattr3.object,
			  "");

	fsal_prepare_attrs(attrs, ATTRS_NFS3);

	obj = nfs3_FhandleToCache(&arg->arg_getattr3.object,
				  &res->res_getattr3.status, &rc);

	if (obj == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		LogFullDebug(COMPONENT_NFSPROTO, "nfs_Getattr returning %d",
			     rc);
		goto out;
	}

	status = obj->obj_ops->getattrs(obj, attrs);

	if (FSAL_IS_ERROR(status)) {
		LogFullDebug(COMPONENT_NFSPROTO,
			     "failed getattr: fsal_status=%s",
			     fsal_err_txt(status));
		if (nfs_RetryableError(status.major)) {
			/* Drop retryable errors. */
			rc = NFS_REQ_DROP;
		} else {
			res->res_getattr3.status = nfs3_Errno_status(status);
			rc = NFS_REQ_OK;
		}
		goto out;
	}

	nfs3_Fixup_FSALattr(obj, attrs);

	res->res_getattr3.status = NFS3_OK;

	LogFullDebug(COMPONENT_NFSPROTO, "nfs_Getattr succeeded");
	rc = NFS_REQ_OK;

out:

	/* Done with the attrs (NFSv3 doesn't use ANY of the reffed attributes)
	 */
	fsal_release_attrs(attrs);

	/* return references */
	if (obj)
		obj->obj_ops->put_ref(obj);

	return rc;
}

/**
 * @brief Free the result structure allocated for nfs3_getattr.
 *
 * @param[in,out] resp Result structure
 *
 */
void nfs3_getattr_free(nfs_res_t *resp)
{
	/* Nothing to do here */
}
