1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * fs/nfs/nfs_vfsops.c
3beacf11bSopenharmony_ci *
4beacf11bSopenharmony_ci *   Copyright (C) 2012-2013, 2015, 2017-2018 Gregory Nutt. All rights reserved.
5beacf11bSopenharmony_ci *   Copyright (C) 2012 Jose Pablo Rojas Vargas. All rights reserved.
6beacf11bSopenharmony_ci *   Author: Jose Pablo Rojas Vargas <jrojas@nx-engineering.com>
7beacf11bSopenharmony_ci *           Gregory Nutt <gnutt@nuttx.org>
8beacf11bSopenharmony_ci *
9beacf11bSopenharmony_ci * Leveraged from OpenBSD:
10beacf11bSopenharmony_ci *
11beacf11bSopenharmony_ci *   Copyright (c) 1989, 1993, 1995
12beacf11bSopenharmony_ci *   The Regents of the University of California.  All rights reserved.
13beacf11bSopenharmony_ci *
14beacf11bSopenharmony_ci * This code is derived from software contributed to Berkeley by
15beacf11bSopenharmony_ci * Rick Macklem at The University of Guelph.
16beacf11bSopenharmony_ci *
17beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without
18beacf11bSopenharmony_ci * modification, are permitted provided that the following conditions
19beacf11bSopenharmony_ci * are met:
20beacf11bSopenharmony_ci *
21beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright
22beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer.
23beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
24beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
25beacf11bSopenharmony_ci *    documentation and/or other materials provided with the distribution.
26beacf11bSopenharmony_ci * 3. Neither the name of the University nor the names of its contributors
27beacf11bSopenharmony_ci *    may be used to endorse or promote products derived from this software
28beacf11bSopenharmony_ci *    without specific prior written permission.
29beacf11bSopenharmony_ci *
30beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31beacf11bSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32beacf11bSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33beacf11bSopenharmony_ci * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34beacf11bSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35beacf11bSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36beacf11bSopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37beacf11bSopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38beacf11bSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39beacf11bSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40beacf11bSopenharmony_ci * SUCH DAMAGE.
41beacf11bSopenharmony_ci *
42beacf11bSopenharmony_ci ****************************************************************************/
43beacf11bSopenharmony_ci
44beacf11bSopenharmony_ci/****************************************************************************
45beacf11bSopenharmony_ci * Included Files
46beacf11bSopenharmony_ci ****************************************************************************/
47beacf11bSopenharmony_ci
48beacf11bSopenharmony_ci#include <sys/mount.h>
49beacf11bSopenharmony_ci#include <sys/socket.h>
50beacf11bSopenharmony_ci#include <sys/statfs.h>
51beacf11bSopenharmony_ci#include <sys/stat.h>
52beacf11bSopenharmony_ci#include <stdlib.h>
53beacf11bSopenharmony_ci#include <string.h>
54beacf11bSopenharmony_ci#include <fcntl.h>
55beacf11bSopenharmony_ci#include <semaphore.h>
56beacf11bSopenharmony_ci#include <assert.h>
57beacf11bSopenharmony_ci#include <errno.h>
58beacf11bSopenharmony_ci#include <pthread.h>
59beacf11bSopenharmony_ci#include <unistd.h>
60beacf11bSopenharmony_ci#include "lwip/opt.h"
61beacf11bSopenharmony_ci#include "lwip/sockets.h"
62beacf11bSopenharmony_ci#include "vfs_config.h"
63beacf11bSopenharmony_ci#include "dirent.h"
64beacf11bSopenharmony_ci#include "fs/fs.h"
65beacf11bSopenharmony_ci#include "fs/dirent_fs.h"
66beacf11bSopenharmony_ci#include "nfs.h"
67beacf11bSopenharmony_ci#include "nfs_node.h"
68beacf11bSopenharmony_ci#include "xdr_subs.h"
69beacf11bSopenharmony_ci#include "los_tables.h"
70beacf11bSopenharmony_ci#include "vnode.h"
71beacf11bSopenharmony_ci#include "los_vm_filemap.h"
72beacf11bSopenharmony_ci#include "user_copy.h"
73beacf11bSopenharmony_ci
74beacf11bSopenharmony_ci/****************************************************************************
75beacf11bSopenharmony_ci * Pre-processor Definitions
76beacf11bSopenharmony_ci ****************************************************************************/
77beacf11bSopenharmony_ci/****************************************************************************
78beacf11bSopenharmony_ci * Public Data
79beacf11bSopenharmony_ci ****************************************************************************/
80beacf11bSopenharmony_ci
81beacf11bSopenharmony_ciuint32_t nfs_true;
82beacf11bSopenharmony_ciuint32_t nfs_false;
83beacf11bSopenharmony_ciuint32_t nfs_xdrneg1;
84beacf11bSopenharmony_ciNFSMOUNT_HOOK g_NFSMOUNT_HOOK = (NFSMOUNT_HOOK)(UINTPTR)NULL;
85beacf11bSopenharmony_ci
86beacf11bSopenharmony_ci#ifdef CONFIG_NFS_STATISTICS
87beacf11bSopenharmony_cistruct nfsstats nfsstats;
88beacf11bSopenharmony_ci#endif
89beacf11bSopenharmony_ci
90beacf11bSopenharmony_ci#define USE_GUARDED_CREATE 1
91beacf11bSopenharmony_ci
92beacf11bSopenharmony_ci#ifdef LOSCFG_FS_NFS
93beacf11bSopenharmony_ci/****************************************************************************
94beacf11bSopenharmony_ci * Private Type Definitions
95beacf11bSopenharmony_ci ****************************************************************************/
96beacf11bSopenharmony_ci
97beacf11bSopenharmony_ci#define NFS_DIR_ENTRY_MALLOC(entry)                                           \
98beacf11bSopenharmony_ci  do                                                                          \
99beacf11bSopenharmony_ci    {                                                                         \
100beacf11bSopenharmony_ci      entry = (struct entry3 *)malloc(sizeof(struct entry3));                 \
101beacf11bSopenharmony_ci      if (entry == NULL)                                                      \
102beacf11bSopenharmony_ci        {                                                                     \
103beacf11bSopenharmony_ci          nfs_debug_info("malloc failed\n");                                           \
104beacf11bSopenharmony_ci          error = ENOMEM;                                                     \
105beacf11bSopenharmony_ci          goto errout_with_memory;                                            \
106beacf11bSopenharmony_ci        }                                                                     \
107beacf11bSopenharmony_ci      (void)memset_s(entry, sizeof(struct entry3), 0, sizeof(struct entry3)); \
108beacf11bSopenharmony_ci    }                                                                         \
109beacf11bSopenharmony_ci  while (0)
110beacf11bSopenharmony_ci
111beacf11bSopenharmony_ci#define NFS_DIR_ENTRY_FREE(entry)  \
112beacf11bSopenharmony_ci  do                               \
113beacf11bSopenharmony_ci    {                              \
114beacf11bSopenharmony_ci      free(entry->contents);       \
115beacf11bSopenharmony_ci      entry->contents = NULL;      \
116beacf11bSopenharmony_ci      free(entry);                 \
117beacf11bSopenharmony_ci      entry = NULL;                \
118beacf11bSopenharmony_ci    }                              \
119beacf11bSopenharmony_ci  while (0)
120beacf11bSopenharmony_ci
121beacf11bSopenharmony_ci#define FILENAME_MAX_LEN 50
122beacf11bSopenharmony_cistruct MountOps nfs_mount_operations;
123beacf11bSopenharmony_cistruct VnodeOps nfs_vops;
124beacf11bSopenharmony_cistruct file_operations_vfs nfs_fops;
125beacf11bSopenharmony_cistruct nfs_statinfo_s
126beacf11bSopenharmony_ci{
127beacf11bSopenharmony_ci  uint16_t ns_mode;    /* File access mode */
128beacf11bSopenharmony_ci  uint8_t  ns_type;    /* File type */
129beacf11bSopenharmony_ci  uint64_t ns_size;    /* File size */
130beacf11bSopenharmony_ci  time_t   ns_atime;   /* Time of last access */
131beacf11bSopenharmony_ci  time_t   ns_mtime;   /* Time of last modification */
132beacf11bSopenharmony_ci  time_t   ns_ctime;   /* Time of last status change */
133beacf11bSopenharmony_ci};
134beacf11bSopenharmony_ciextern void nfs_stat_common(struct nfs_statinfo_s *info, struct stat *buf);
135beacf11bSopenharmony_ci
136beacf11bSopenharmony_cistatic mode_t type_to_mode(int type, mode_t permission)
137beacf11bSopenharmony_ci{
138beacf11bSopenharmony_ci  switch (type)
139beacf11bSopenharmony_ci    {
140beacf11bSopenharmony_ci    case VNODE_TYPE_DIR:
141beacf11bSopenharmony_ci      return permission | S_IFDIR;
142beacf11bSopenharmony_ci    case VNODE_TYPE_REG:
143beacf11bSopenharmony_ci      return permission | S_IFREG;
144beacf11bSopenharmony_ci    case VNODE_TYPE_BLK:
145beacf11bSopenharmony_ci      return permission | S_IFBLK;
146beacf11bSopenharmony_ci    case VNODE_TYPE_CHR:
147beacf11bSopenharmony_ci      return permission | S_IFCHR;
148beacf11bSopenharmony_ci    case VNODE_TYPE_FIFO:
149beacf11bSopenharmony_ci      return permission | S_IFIFO;
150beacf11bSopenharmony_ci    default:
151beacf11bSopenharmony_ci      break;
152beacf11bSopenharmony_ci    }
153beacf11bSopenharmony_ci  return permission;
154beacf11bSopenharmony_ci}
155beacf11bSopenharmony_ci
156beacf11bSopenharmony_cistatic int nfs_2_vfs(int result)
157beacf11bSopenharmony_ci{
158beacf11bSopenharmony_ci  int status;
159beacf11bSopenharmony_ci
160beacf11bSopenharmony_ci  if ((result < NFS_OK) || (result > NFSERR_NOTEMPTY))
161beacf11bSopenharmony_ci    {
162beacf11bSopenharmony_ci      return result;
163beacf11bSopenharmony_ci    }
164beacf11bSopenharmony_ci
165beacf11bSopenharmony_ci  /* Nfs errno to Libc errno */
166beacf11bSopenharmony_ci  switch (result)
167beacf11bSopenharmony_ci    {
168beacf11bSopenharmony_ci    case NFSERR_NAMETOL:
169beacf11bSopenharmony_ci      status = ENAMETOOLONG;
170beacf11bSopenharmony_ci      break;
171beacf11bSopenharmony_ci    case NFSERR_NOTEMPTY:
172beacf11bSopenharmony_ci      status = ENOTEMPTY;
173beacf11bSopenharmony_ci      break;
174beacf11bSopenharmony_ci    default:
175beacf11bSopenharmony_ci      status = result;
176beacf11bSopenharmony_ci      break;
177beacf11bSopenharmony_ci    }
178beacf11bSopenharmony_ci
179beacf11bSopenharmony_ci  return status;
180beacf11bSopenharmony_ci}
181beacf11bSopenharmony_ci
182beacf11bSopenharmony_ci/****************************************************************************
183beacf11bSopenharmony_ci * Name: nfs_fileupdate
184beacf11bSopenharmony_ci *
185beacf11bSopenharmony_ci * Description:
186beacf11bSopenharmony_ci *   This is to update the file attributes like size, type. This sends a LOOKUP msg of nfs
187beacf11bSopenharmony_ci *   to get latest file attributes.
188beacf11bSopenharmony_ci *
189beacf11bSopenharmony_ci * Returned Value:
190beacf11bSopenharmony_ci *   0 on success; a positive errno value on failure.
191beacf11bSopenharmony_ci *
192beacf11bSopenharmony_ci ****************************************************************************/
193beacf11bSopenharmony_cistatic int nfs_fileupdate(struct nfsmount *nmp, char *filename,
194beacf11bSopenharmony_ci    struct file_handle *parent_fhandle, struct nfsnode *np)
195beacf11bSopenharmony_ci{
196beacf11bSopenharmony_ci  struct file_handle fhandle;
197beacf11bSopenharmony_ci  int                error;
198beacf11bSopenharmony_ci  struct nfs_fattr   fattr;
199beacf11bSopenharmony_ci
200beacf11bSopenharmony_ci  /* Find the NFS node associate with the path */
201beacf11bSopenharmony_ci
202beacf11bSopenharmony_ci  fhandle.length = parent_fhandle->length;
203beacf11bSopenharmony_ci  (void)memcpy_s(&(fhandle.handle), fhandle.length, &(parent_fhandle->handle), parent_fhandle->length);
204beacf11bSopenharmony_ci  error = nfs_lookup(nmp, filename, &fhandle, &fattr, NULL);
205beacf11bSopenharmony_ci
206beacf11bSopenharmony_ci  if (error != OK)
207beacf11bSopenharmony_ci    {
208beacf11bSopenharmony_ci      nfs_debug_error("nfs_lookup failed returned: %d\n", error);
209beacf11bSopenharmony_ci      return error;
210beacf11bSopenharmony_ci    }
211beacf11bSopenharmony_ci
212beacf11bSopenharmony_ci  /* Update the file handle */
213beacf11bSopenharmony_ci
214beacf11bSopenharmony_ci  error = memcpy_s(&(np->n_fhandle), NFSX_V3FHMAX, &(fhandle.handle), fhandle.length);
215beacf11bSopenharmony_ci  if (error != EOK)
216beacf11bSopenharmony_ci    {
217beacf11bSopenharmony_ci      return ENOBUFS;
218beacf11bSopenharmony_ci    }
219beacf11bSopenharmony_ci
220beacf11bSopenharmony_ci  np->n_fhsize = fhandle.length;
221beacf11bSopenharmony_ci
222beacf11bSopenharmony_ci  /* Save the file attributes */
223beacf11bSopenharmony_ci
224beacf11bSopenharmony_ci  nfs_attrupdate(np, &fattr);
225beacf11bSopenharmony_ci
226beacf11bSopenharmony_ci  return OK;
227beacf11bSopenharmony_ci}
228beacf11bSopenharmony_ci
229beacf11bSopenharmony_ciint vfs_nfs_reclaim(struct Vnode *node)
230beacf11bSopenharmony_ci{
231beacf11bSopenharmony_ci  struct nfsnode  *prev = NULL;
232beacf11bSopenharmony_ci  struct nfsnode  *curr = NULL;
233beacf11bSopenharmony_ci  struct nfsmount *nmp = NULL;
234beacf11bSopenharmony_ci  struct nfsnode  *np = NULL;
235beacf11bSopenharmony_ci  if (node->data == NULL)
236beacf11bSopenharmony_ci    {
237beacf11bSopenharmony_ci      return OK;
238beacf11bSopenharmony_ci    }
239beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(node->originMount->data);
240beacf11bSopenharmony_ci  nfs_mux_take(nmp);
241beacf11bSopenharmony_ci  np = (struct nfsnode*)(node->data);
242beacf11bSopenharmony_ci  int ret;
243beacf11bSopenharmony_ci
244beacf11bSopenharmony_ci  if (np->n_crefs > 1)
245beacf11bSopenharmony_ci    {
246beacf11bSopenharmony_ci      np->n_crefs--;
247beacf11bSopenharmony_ci      ret = OK;
248beacf11bSopenharmony_ci    }
249beacf11bSopenharmony_ci
250beacf11bSopenharmony_ci  /* There are no more references to the file structure.  Now we need to
251beacf11bSopenharmony_ci   * free up all resources associated with the open file.
252beacf11bSopenharmony_ci   *
253beacf11bSopenharmony_ci   * First, find our file structure in the list of file structures
254beacf11bSopenharmony_ci   * containted in the mount structure.
255beacf11bSopenharmony_ci   */
256beacf11bSopenharmony_ci
257beacf11bSopenharmony_ci  else
258beacf11bSopenharmony_ci    {
259beacf11bSopenharmony_ci      /* Assume file structure will not be found.  This should never happen. */
260beacf11bSopenharmony_ci
261beacf11bSopenharmony_ci      ret = -EINVAL;
262beacf11bSopenharmony_ci
263beacf11bSopenharmony_ci      for (prev = NULL, curr = nmp->nm_head;
264beacf11bSopenharmony_ci          curr;
265beacf11bSopenharmony_ci          prev = curr, curr = curr->n_next)
266beacf11bSopenharmony_ci        {
267beacf11bSopenharmony_ci          /* Check if this node is ours */
268beacf11bSopenharmony_ci
269beacf11bSopenharmony_ci          if (np == curr)
270beacf11bSopenharmony_ci            {
271beacf11bSopenharmony_ci              /* Yes.. remove it from the list of file structures */
272beacf11bSopenharmony_ci
273beacf11bSopenharmony_ci              if (prev)
274beacf11bSopenharmony_ci                {
275beacf11bSopenharmony_ci                  /* Remove from mid-list */
276beacf11bSopenharmony_ci
277beacf11bSopenharmony_ci                  prev->n_next = np->n_next;
278beacf11bSopenharmony_ci                }
279beacf11bSopenharmony_ci              else
280beacf11bSopenharmony_ci                {
281beacf11bSopenharmony_ci                  /* Remove from the head of the list */
282beacf11bSopenharmony_ci
283beacf11bSopenharmony_ci                  nmp->nm_head = np->n_next;
284beacf11bSopenharmony_ci                }
285beacf11bSopenharmony_ci
286beacf11bSopenharmony_ci              /* Then deallocate the file structure and return success */
287beacf11bSopenharmony_ci
288beacf11bSopenharmony_ci              free(np->n_name);
289beacf11bSopenharmony_ci              free(np);
290beacf11bSopenharmony_ci              ret = OK;
291beacf11bSopenharmony_ci              break;
292beacf11bSopenharmony_ci            }
293beacf11bSopenharmony_ci        }
294beacf11bSopenharmony_ci    }
295beacf11bSopenharmony_ci
296beacf11bSopenharmony_ci  nfs_mux_release(nmp);
297beacf11bSopenharmony_ci  return ret;
298beacf11bSopenharmony_ci}
299beacf11bSopenharmony_ci
300beacf11bSopenharmony_cistatic int vfs_nfs_stat_internal(struct nfsmount *nmp, struct nfsnode *nfs_node)
301beacf11bSopenharmony_ci{
302beacf11bSopenharmony_ci  int ret;
303beacf11bSopenharmony_ci  struct timespec ts;
304beacf11bSopenharmony_ci  struct rpc_call_fs attr_call;
305beacf11bSopenharmony_ci  struct rpc_reply_getattr attr_reply;
306beacf11bSopenharmony_ci  attr_call.fs.fsroot.length = txdr_unsigned(nfs_node->n_fhsize);
307beacf11bSopenharmony_ci  memcpy_s(&(attr_call.fs.fsroot.handle), sizeof(nfsfh_t), &(nfs_node->n_fhandle), sizeof(nfsfh_t));
308beacf11bSopenharmony_ci  ret = nfs_request(nmp, NFSPROC_GETATTR, &attr_call,
309beacf11bSopenharmony_ci      sizeof(struct file_handle), &attr_reply,
310beacf11bSopenharmony_ci      sizeof(struct rpc_reply_getattr));
311beacf11bSopenharmony_ci  if (ret != OK)
312beacf11bSopenharmony_ci    {
313beacf11bSopenharmony_ci      return ret;
314beacf11bSopenharmony_ci    }
315beacf11bSopenharmony_ci  /* Extract the file mode, file type, and file size. */
316beacf11bSopenharmony_ci
317beacf11bSopenharmony_ci  nfs_node->n_mode  = fxdr_unsigned(uint16_t, attr_reply.attr.fa_mode);
318beacf11bSopenharmony_ci  nfs_node->n_type  = fxdr_unsigned(uint8_t, attr_reply.attr.fa_type);
319beacf11bSopenharmony_ci  nfs_node->n_size  = fxdr_hyper(&attr_reply.attr.fa_size);
320beacf11bSopenharmony_ci
321beacf11bSopenharmony_ci  /* Extract time values as type time_t in units of seconds */
322beacf11bSopenharmony_ci
323beacf11bSopenharmony_ci  fxdr_nfsv3time(&attr_reply.attr.fa_mtime, &ts);
324beacf11bSopenharmony_ci  nfs_node->n_timestamp.tv_sec = ts.tv_sec;
325beacf11bSopenharmony_ci  nfs_node->n_timestamp.tv_nsec = ts.tv_nsec;
326beacf11bSopenharmony_ci
327beacf11bSopenharmony_ci  fxdr_nfsv3time(&attr_reply.attr.fa_atime, &ts);
328beacf11bSopenharmony_ci  nfs_node->n_atime = ts.tv_sec;
329beacf11bSopenharmony_ci
330beacf11bSopenharmony_ci  fxdr_nfsv3time(&attr_reply.attr.fa_ctime, &ts);
331beacf11bSopenharmony_ci  nfs_node->n_ctime = ts.tv_sec;
332beacf11bSopenharmony_ci
333beacf11bSopenharmony_ci  return OK;
334beacf11bSopenharmony_ci}
335beacf11bSopenharmony_ci
336beacf11bSopenharmony_ci/****************************************************************************
337beacf11bSopenharmony_ci * Name: nfs_decode_args
338beacf11bSopenharmony_ci *
339beacf11bSopenharmony_ci * Returned Value:
340beacf11bSopenharmony_ci *   None
341beacf11bSopenharmony_ci *
342beacf11bSopenharmony_ci ****************************************************************************/
343beacf11bSopenharmony_ci
344beacf11bSopenharmony_cistatic void nfs_decode_args(struct nfs_mount_parameters *nprmt,
345beacf11bSopenharmony_ci                            struct nfs_args *argp)
346beacf11bSopenharmony_ci{
347beacf11bSopenharmony_ci  int maxio;
348beacf11bSopenharmony_ci
349beacf11bSopenharmony_ci  /* Get the selected timeout value */
350beacf11bSopenharmony_ci
351beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_TIMEO) != 0 && argp->timeo > 0)
352beacf11bSopenharmony_ci    {
353beacf11bSopenharmony_ci      uint32_t tmp = ((uint32_t)argp->timeo * NFS_HZ + 5) / 10;
354beacf11bSopenharmony_ci      if (tmp < NFS_MINTIMEO)
355beacf11bSopenharmony_ci        {
356beacf11bSopenharmony_ci          tmp = NFS_MINTIMEO;
357beacf11bSopenharmony_ci        }
358beacf11bSopenharmony_ci      else if (tmp > NFS_MAXTIMEO)
359beacf11bSopenharmony_ci        {
360beacf11bSopenharmony_ci          tmp = NFS_MAXTIMEO;
361beacf11bSopenharmony_ci        }
362beacf11bSopenharmony_ci
363beacf11bSopenharmony_ci      nprmt->timeo = tmp;
364beacf11bSopenharmony_ci    }
365beacf11bSopenharmony_ci
366beacf11bSopenharmony_ci  /* Get the selected retransmission count */
367beacf11bSopenharmony_ci
368beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_RETRANS) != 0 && argp->retrans > 1)
369beacf11bSopenharmony_ci    {
370beacf11bSopenharmony_ci      if  (argp->retrans < NFS_MAXREXMIT)
371beacf11bSopenharmony_ci        {
372beacf11bSopenharmony_ci          nprmt->retry = argp->retrans;
373beacf11bSopenharmony_ci        }
374beacf11bSopenharmony_ci      else
375beacf11bSopenharmony_ci        {
376beacf11bSopenharmony_ci          nprmt->retry = NFS_MAXREXMIT;
377beacf11bSopenharmony_ci        }
378beacf11bSopenharmony_ci    }
379beacf11bSopenharmony_ci
380beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_SOFT) == 0)
381beacf11bSopenharmony_ci    {
382beacf11bSopenharmony_ci      nprmt->retry = NFS_MAXREXMIT + 1;  /* Past clip limit */
383beacf11bSopenharmony_ci    }
384beacf11bSopenharmony_ci
385beacf11bSopenharmony_ci  /* Get the maximum amount of data that can be transferred in one packet */
386beacf11bSopenharmony_ci
387beacf11bSopenharmony_ci  if ((argp->sotype == SOCK_DGRAM) != 0)
388beacf11bSopenharmony_ci    {
389beacf11bSopenharmony_ci      maxio = NFS_MAXDGRAMDATA;
390beacf11bSopenharmony_ci    }
391beacf11bSopenharmony_ci  else
392beacf11bSopenharmony_ci    {
393beacf11bSopenharmony_ci      nfs_debug_error("Only SOCK_DRAM is supported\n");
394beacf11bSopenharmony_ci      maxio = NFS_MAXDATA;
395beacf11bSopenharmony_ci    }
396beacf11bSopenharmony_ci
397beacf11bSopenharmony_ci  /* Get the maximum amount of data that can be transferred in one write transfer */
398beacf11bSopenharmony_ci
399beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_WSIZE) != 0 && argp->wsize > 0)
400beacf11bSopenharmony_ci    {
401beacf11bSopenharmony_ci      nprmt->wsize = argp->wsize;
402beacf11bSopenharmony_ci
403beacf11bSopenharmony_ci      /* Round down to multiple of blocksize */
404beacf11bSopenharmony_ci
405beacf11bSopenharmony_ci      nprmt->wsize &= ~(NFS_FABLKSIZE - 1);
406beacf11bSopenharmony_ci      if (nprmt->wsize <= 0)
407beacf11bSopenharmony_ci        {
408beacf11bSopenharmony_ci          nprmt->wsize = NFS_FABLKSIZE;
409beacf11bSopenharmony_ci        }
410beacf11bSopenharmony_ci    }
411beacf11bSopenharmony_ci
412beacf11bSopenharmony_ci  if (nprmt->wsize > maxio)
413beacf11bSopenharmony_ci    {
414beacf11bSopenharmony_ci      nprmt->wsize = maxio;
415beacf11bSopenharmony_ci    }
416beacf11bSopenharmony_ci
417beacf11bSopenharmony_ci  if (nprmt->wsize > MAXBSIZE)
418beacf11bSopenharmony_ci    {
419beacf11bSopenharmony_ci      nprmt->wsize = MAXBSIZE;
420beacf11bSopenharmony_ci    }
421beacf11bSopenharmony_ci
422beacf11bSopenharmony_ci  /* Get the maximum amount of data that can be transferred in one read transfer */
423beacf11bSopenharmony_ci
424beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_RSIZE) != 0 && argp->rsize > 0)
425beacf11bSopenharmony_ci    {
426beacf11bSopenharmony_ci      nprmt->rsize = argp->rsize;
427beacf11bSopenharmony_ci
428beacf11bSopenharmony_ci      /* Round down to multiple of blocksize */
429beacf11bSopenharmony_ci
430beacf11bSopenharmony_ci      nprmt->rsize &= ~(NFS_FABLKSIZE - 1);
431beacf11bSopenharmony_ci      if (nprmt->rsize <= 0)
432beacf11bSopenharmony_ci        {
433beacf11bSopenharmony_ci          nprmt->rsize = NFS_FABLKSIZE;
434beacf11bSopenharmony_ci        }
435beacf11bSopenharmony_ci    }
436beacf11bSopenharmony_ci
437beacf11bSopenharmony_ci  if (nprmt->rsize > maxio)
438beacf11bSopenharmony_ci    {
439beacf11bSopenharmony_ci      nprmt->rsize = maxio;
440beacf11bSopenharmony_ci    }
441beacf11bSopenharmony_ci
442beacf11bSopenharmony_ci  if (nprmt->rsize > MAXBSIZE)
443beacf11bSopenharmony_ci    {
444beacf11bSopenharmony_ci      nprmt->rsize = MAXBSIZE;
445beacf11bSopenharmony_ci    }
446beacf11bSopenharmony_ci
447beacf11bSopenharmony_ci  /* Get the maximum amount of data that can be transferred in directory transfer */
448beacf11bSopenharmony_ci
449beacf11bSopenharmony_ci  if ((argp->flags & NFSMNT_READDIRSIZE) != 0 && argp->readdirsize > 0)
450beacf11bSopenharmony_ci    {
451beacf11bSopenharmony_ci      nprmt->readdirsize = argp->readdirsize;
452beacf11bSopenharmony_ci
453beacf11bSopenharmony_ci      /* Round down to multiple of blocksize */
454beacf11bSopenharmony_ci
455beacf11bSopenharmony_ci      nprmt->readdirsize &= ~(NFS_DIRBLKSIZ - 1);
456beacf11bSopenharmony_ci      if (nprmt->readdirsize < NFS_DIRBLKSIZ)
457beacf11bSopenharmony_ci        {
458beacf11bSopenharmony_ci          nprmt->readdirsize = NFS_DIRBLKSIZ;
459beacf11bSopenharmony_ci        }
460beacf11bSopenharmony_ci    }
461beacf11bSopenharmony_ci  else if (argp->flags & NFSMNT_RSIZE)
462beacf11bSopenharmony_ci    {
463beacf11bSopenharmony_ci      nprmt->readdirsize = nprmt->rsize;
464beacf11bSopenharmony_ci    }
465beacf11bSopenharmony_ci
466beacf11bSopenharmony_ci  if (nprmt->readdirsize > maxio)
467beacf11bSopenharmony_ci    {
468beacf11bSopenharmony_ci      nprmt->readdirsize = maxio;
469beacf11bSopenharmony_ci    }
470beacf11bSopenharmony_ci}
471beacf11bSopenharmony_ci
472beacf11bSopenharmony_ci/****************************************************************************
473beacf11bSopenharmony_ci * Name: nfs_bind
474beacf11bSopenharmony_ci *
475beacf11bSopenharmony_ci * Description:
476beacf11bSopenharmony_ci *  This implements a portion of the mount operation. This function allocates
477beacf11bSopenharmony_ci *  and initializes the mountpoint private data and gets mount information
478beacf11bSopenharmony_ci *  from the NFS server.  The final binding of the private data (containing
479beacf11bSopenharmony_ci *  NFS server mount information) to the  mountpoint is performed by mount().
480beacf11bSopenharmony_ci *
481beacf11bSopenharmony_ci * Returned Value:
482beacf11bSopenharmony_ci *   0 on success; a negated errno value on failure.
483beacf11bSopenharmony_ci *
484beacf11bSopenharmony_ci ****************************************************************************/
485beacf11bSopenharmony_ci
486beacf11bSopenharmony_ciint nfs_bind(struct Vnode *blkdriver, const void *data,
487beacf11bSopenharmony_ci                    void **handle, const char *relpath)
488beacf11bSopenharmony_ci{
489beacf11bSopenharmony_ci  struct nfs_args        *argp = (struct nfs_args *)data;
490beacf11bSopenharmony_ci  struct nfsmount        *nmp = NULL;
491beacf11bSopenharmony_ci  struct rpcclnt             *rpc = NULL;
492beacf11bSopenharmony_ci  struct rpc_call_fs          getattr;
493beacf11bSopenharmony_ci  struct rpc_reply_getattr    resok;
494beacf11bSopenharmony_ci  struct nfs_mount_parameters nprmt;
495beacf11bSopenharmony_ci  uint32_t                    buflen;
496beacf11bSopenharmony_ci  uint32_t                    pathlen;
497beacf11bSopenharmony_ci  uint32_t                    tmp;
498beacf11bSopenharmony_ci  int                         error = 0;
499beacf11bSopenharmony_ci  pthread_mutexattr_t attr;
500beacf11bSopenharmony_ci
501beacf11bSopenharmony_ci  DEBUGASSERT(data && handle);
502beacf11bSopenharmony_ci
503beacf11bSopenharmony_ci  /* Set default values of the parameters.  These may be overridden by
504beacf11bSopenharmony_ci   * settings in the argp->flags.
505beacf11bSopenharmony_ci   */
506beacf11bSopenharmony_ci
507beacf11bSopenharmony_ci  nprmt.timeo       = NFS_TIMEO;
508beacf11bSopenharmony_ci  nprmt.retry       = NFS_RETRANS;
509beacf11bSopenharmony_ci  nprmt.wsize       = NFS_WSIZE;
510beacf11bSopenharmony_ci  nprmt.rsize       = NFS_RSIZE;
511beacf11bSopenharmony_ci  nprmt.readdirsize = NFS_READDIRSIZE;
512beacf11bSopenharmony_ci
513beacf11bSopenharmony_ci  nfs_decode_args(&nprmt, argp);
514beacf11bSopenharmony_ci
515beacf11bSopenharmony_ci  /* Determine the size of a buffer that will hold one RPC data transfer.
516beacf11bSopenharmony_ci   * First, get the maximum size of a read and a write transfer.
517beacf11bSopenharmony_ci   */
518beacf11bSopenharmony_ci
519beacf11bSopenharmony_ci  pathlen = strlen(argp->path);
520beacf11bSopenharmony_ci  if (pathlen >= NFS_MOUNT_PATH_MAX_SIZE) {
521beacf11bSopenharmony_ci      return -ENAMETOOLONG;
522beacf11bSopenharmony_ci  }
523beacf11bSopenharmony_ci
524beacf11bSopenharmony_ci  buflen = SIZEOF_rpc_call_write(nprmt.wsize);
525beacf11bSopenharmony_ci  tmp    = SIZEOF_rpc_reply_read(nprmt.rsize);
526beacf11bSopenharmony_ci
527beacf11bSopenharmony_ci  /* The buffer size will be the maximum of those two sizes */
528beacf11bSopenharmony_ci
529beacf11bSopenharmony_ci  if (tmp > buflen)
530beacf11bSopenharmony_ci    {
531beacf11bSopenharmony_ci      buflen = tmp;
532beacf11bSopenharmony_ci    }
533beacf11bSopenharmony_ci
534beacf11bSopenharmony_ci  /* But don't let the buffer size exceed the MSS of the socket type.
535beacf11bSopenharmony_ci   *
536beacf11bSopenharmony_ci   * In the case where there are multiple network devices with different
537beacf11bSopenharmony_ci   * link layer protocols, each network device may support a different
538beacf11bSopenharmony_ci   * UDP MSS value.  Here we arbitrarily select the minimum MSS for
539beacf11bSopenharmony_ci   * that case.
540beacf11bSopenharmony_ci   */
541beacf11bSopenharmony_ci
542beacf11bSopenharmony_ci  /* Create an instance of the mountpt state structure */
543beacf11bSopenharmony_ci
544beacf11bSopenharmony_ci  nmp = (struct nfsmount *)malloc(SIZEOF_nfsmount(buflen));
545beacf11bSopenharmony_ci  if (!nmp)
546beacf11bSopenharmony_ci    {
547beacf11bSopenharmony_ci      nfs_debug_error("Failed to allocate mountpoint structure\n");
548beacf11bSopenharmony_ci      return -ENOMEM;
549beacf11bSopenharmony_ci    }
550beacf11bSopenharmony_ci
551beacf11bSopenharmony_ci  (void)memset_s(nmp, SIZEOF_nfsmount(buflen), 0, SIZEOF_nfsmount(buflen));
552beacf11bSopenharmony_ci
553beacf11bSopenharmony_ci  /* Save the allocated I/O buffer size */
554beacf11bSopenharmony_ci
555beacf11bSopenharmony_ci  nmp->nm_buflen = (uint16_t)buflen;
556beacf11bSopenharmony_ci
557beacf11bSopenharmony_ci  nmp->nm_so = -1;
558beacf11bSopenharmony_ci
559beacf11bSopenharmony_ci  /* Initialize the allocated mountpt state structure. */
560beacf11bSopenharmony_ci
561beacf11bSopenharmony_ci  (void)pthread_mutexattr_init(&attr);
562beacf11bSopenharmony_ci  (void)pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
563beacf11bSopenharmony_ci  error = pthread_mutex_init(&nmp->nm_mux, &attr);
564beacf11bSopenharmony_ci  if (error)
565beacf11bSopenharmony_ci    {
566beacf11bSopenharmony_ci      return -error;
567beacf11bSopenharmony_ci    }
568beacf11bSopenharmony_ci
569beacf11bSopenharmony_ci  /* Initialize NFS */
570beacf11bSopenharmony_ci
571beacf11bSopenharmony_ci  nfs_true = txdr_unsigned(TRUE);
572beacf11bSopenharmony_ci  nfs_false = txdr_unsigned(FALSE);
573beacf11bSopenharmony_ci  nfs_xdrneg1 = txdr_unsigned(-1);
574beacf11bSopenharmony_ci
575beacf11bSopenharmony_ci  rpcclnt_init();
576beacf11bSopenharmony_ci
577beacf11bSopenharmony_ci  /* Set initial values of other fields */
578beacf11bSopenharmony_ci
579beacf11bSopenharmony_ci  nmp->nm_timeo       = nprmt.timeo;
580beacf11bSopenharmony_ci  nmp->nm_retry       = nprmt.retry;
581beacf11bSopenharmony_ci  nmp->nm_wsize       = nprmt.wsize;
582beacf11bSopenharmony_ci  nmp->nm_rsize       = nprmt.rsize;
583beacf11bSopenharmony_ci  nmp->nm_readdirsize = nprmt.readdirsize;
584beacf11bSopenharmony_ci  nmp->nm_fhsize      = NFSX_V3FHMAX;
585beacf11bSopenharmony_ci
586beacf11bSopenharmony_ci  (void)strncpy_s(nmp->nm_path, sizeof(nmp->nm_path), argp->path, pathlen);
587beacf11bSopenharmony_ci  (void)memcpy_s(&nmp->nm_nam, sizeof(struct sockaddr), &argp->addr, argp->addrlen);
588beacf11bSopenharmony_ci
589beacf11bSopenharmony_ci  /* Set up the sockets and per-host congestion */
590beacf11bSopenharmony_ci
591beacf11bSopenharmony_ci  nmp->nm_sotype  = argp->sotype;
592beacf11bSopenharmony_ci
593beacf11bSopenharmony_ci  if (nmp->nm_sotype == SOCK_DGRAM || nmp->nm_sotype == SOCK_STREAM)
594beacf11bSopenharmony_ci    {
595beacf11bSopenharmony_ci      /* Connection-less... connect now */
596beacf11bSopenharmony_ci
597beacf11bSopenharmony_ci      /* Create an instance of the rpc state structure */
598beacf11bSopenharmony_ci
599beacf11bSopenharmony_ci      rpc = (struct rpcclnt *)malloc(sizeof(struct rpcclnt));
600beacf11bSopenharmony_ci      if (!rpc)
601beacf11bSopenharmony_ci        {
602beacf11bSopenharmony_ci          nfs_debug_error("Failed to allocate rpc structure\n");
603beacf11bSopenharmony_ci          error = ENOMEM;
604beacf11bSopenharmony_ci          goto bad;
605beacf11bSopenharmony_ci        }
606beacf11bSopenharmony_ci
607beacf11bSopenharmony_ci      (void)memset_s(rpc, sizeof(struct rpcclnt), 0, sizeof(struct rpcclnt));
608beacf11bSopenharmony_ci
609beacf11bSopenharmony_ci      nfs_debug_info("Connecting\n");
610beacf11bSopenharmony_ci
611beacf11bSopenharmony_ci      /* Translate nfsmnt flags -> rpcclnt flags */
612beacf11bSopenharmony_ci
613beacf11bSopenharmony_ci      rpc->rc_path       = nmp->nm_path;
614beacf11bSopenharmony_ci      rpc->rc_name       = &nmp->nm_nam;
615beacf11bSopenharmony_ci      rpc->rc_sotype     = nmp->nm_sotype;
616beacf11bSopenharmony_ci      rpc->rc_retry      = nmp->nm_retry;
617beacf11bSopenharmony_ci      rpc->rc_so         = -1;
618beacf11bSopenharmony_ci
619beacf11bSopenharmony_ci      nmp->nm_rpcclnt    = rpc;
620beacf11bSopenharmony_ci
621beacf11bSopenharmony_ci      error = rpcclnt_connect(nmp->nm_rpcclnt);
622beacf11bSopenharmony_ci      if (error != OK)
623beacf11bSopenharmony_ci        {
624beacf11bSopenharmony_ci          nfs_debug_error("nfs_connect failed: %d\n", error);
625beacf11bSopenharmony_ci          goto bad;
626beacf11bSopenharmony_ci        }
627beacf11bSopenharmony_ci    }
628beacf11bSopenharmony_ci
629beacf11bSopenharmony_ci  nmp->nm_mounted        = true;
630beacf11bSopenharmony_ci  nmp->nm_so             = nmp->nm_rpcclnt->rc_so;
631beacf11bSopenharmony_ci  nmp->nm_head           = NULL;
632beacf11bSopenharmony_ci  nmp->nm_dir            = NULL;
633beacf11bSopenharmony_ci  nmp->nm_fhsize         = nmp->nm_rpcclnt->rc_fhsize;
634beacf11bSopenharmony_ci  (void)memcpy_s(&nmp->nm_fh, sizeof(nfsfh_t), &nmp->nm_rpcclnt->rc_fh, sizeof(nfsfh_t));
635beacf11bSopenharmony_ci
636beacf11bSopenharmony_ci  /* Get the file attributes */
637beacf11bSopenharmony_ci
638beacf11bSopenharmony_ci  getattr.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
639beacf11bSopenharmony_ci  (void)memcpy_s(&getattr.fs.fsroot.handle, sizeof(nfsfh_t), &nmp->nm_fh, sizeof(nfsfh_t));
640beacf11bSopenharmony_ci
641beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_GETATTR,
642beacf11bSopenharmony_ci                      (void *)&getattr, /* sizeof(struct FS3args) */
643beacf11bSopenharmony_ci                      (sizeof(getattr.fs.fsroot.length) + nmp->nm_fhsize),
644beacf11bSopenharmony_ci                      (void *)&resok, sizeof(struct rpc_reply_getattr));
645beacf11bSopenharmony_ci  if (error)
646beacf11bSopenharmony_ci    {
647beacf11bSopenharmony_ci      nfs_debug_error("nfs_request failed: %d\n", error);
648beacf11bSopenharmony_ci      goto bad;
649beacf11bSopenharmony_ci    }
650beacf11bSopenharmony_ci
651beacf11bSopenharmony_ci  /* Save the file attributes */
652beacf11bSopenharmony_ci
653beacf11bSopenharmony_ci  (void)memcpy_s(&nmp->nm_fattr, sizeof(struct nfs_fattr), &resok.attr, sizeof(struct nfs_fattr));
654beacf11bSopenharmony_ci
655beacf11bSopenharmony_ci  /* Mounted! */
656beacf11bSopenharmony_ci
657beacf11bSopenharmony_ci  *handle = (void *)nmp;
658beacf11bSopenharmony_ci
659beacf11bSopenharmony_ci  nfs_debug_info("Successfully mounted\n");
660beacf11bSopenharmony_ci  return OK;
661beacf11bSopenharmony_ci
662beacf11bSopenharmony_cibad:
663beacf11bSopenharmony_ci  if (nmp)
664beacf11bSopenharmony_ci    {
665beacf11bSopenharmony_ci      /* Disconnect from the server */
666beacf11bSopenharmony_ci
667beacf11bSopenharmony_ci      if (nmp->nm_rpcclnt)
668beacf11bSopenharmony_ci        {
669beacf11bSopenharmony_ci          rpcclnt_disconnect(nmp->nm_rpcclnt);
670beacf11bSopenharmony_ci          free(nmp->nm_rpcclnt);
671beacf11bSopenharmony_ci          nmp->nm_rpcclnt = NULL;
672beacf11bSopenharmony_ci        }
673beacf11bSopenharmony_ci
674beacf11bSopenharmony_ci      /* Free connection-related resources */
675beacf11bSopenharmony_ci
676beacf11bSopenharmony_ci      (void)pthread_mutex_destroy(&nmp->nm_mux);
677beacf11bSopenharmony_ci
678beacf11bSopenharmony_ci      free(nmp);
679beacf11bSopenharmony_ci      nmp = NULL;
680beacf11bSopenharmony_ci    }
681beacf11bSopenharmony_ci
682beacf11bSopenharmony_ci  return -error; /*lint !e438*/
683beacf11bSopenharmony_ci}
684beacf11bSopenharmony_ci
685beacf11bSopenharmony_ci
686beacf11bSopenharmony_cistatic enum VnodeType filetype_to_vnodetype(uint32_t filetype)
687beacf11bSopenharmony_ci{
688beacf11bSopenharmony_ci  if (filetype < 0 || filetype > 7)
689beacf11bSopenharmony_ci    {
690beacf11bSopenharmony_ci      return VNODE_TYPE_UNKNOWN;
691beacf11bSopenharmony_ci    }
692beacf11bSopenharmony_ci
693beacf11bSopenharmony_ci  enum VnodeType transfer_table[8] =
694beacf11bSopenharmony_ci    {
695beacf11bSopenharmony_ci      VNODE_TYPE_UNKNOWN,
696beacf11bSopenharmony_ci      VNODE_TYPE_REG,
697beacf11bSopenharmony_ci      VNODE_TYPE_DIR,
698beacf11bSopenharmony_ci      VNODE_TYPE_BLK,
699beacf11bSopenharmony_ci      VNODE_TYPE_CHR,
700beacf11bSopenharmony_ci      VNODE_TYPE_LNK,
701beacf11bSopenharmony_ci      VNODE_TYPE_UNKNOWN,
702beacf11bSopenharmony_ci      VNODE_TYPE_FIFO
703beacf11bSopenharmony_ci    };
704beacf11bSopenharmony_ci
705beacf11bSopenharmony_ci  return transfer_table[filetype];
706beacf11bSopenharmony_ci}
707beacf11bSopenharmony_ci
708beacf11bSopenharmony_ciint nfs_mount(const char *server_ip_and_path, const char *mount_path,
709beacf11bSopenharmony_ci              unsigned int uid, unsigned int gid)
710beacf11bSopenharmony_ci{
711beacf11bSopenharmony_ci  struct nfs_args         nfs_args = {0};
712beacf11bSopenharmony_ci  char                    *server_ip_addr = NULL;
713beacf11bSopenharmony_ci  char                    *server_nfs_path = NULL;
714beacf11bSopenharmony_ci  int                     found_colon = 0;
715beacf11bSopenharmony_ci  unsigned int            pos;
716beacf11bSopenharmony_ci  int                     ret = -1;
717beacf11bSopenharmony_ci  struct sockaddr_in      *nfs_srv_addr = NULL;
718beacf11bSopenharmony_ci  size_t len;
719beacf11bSopenharmony_ci
720beacf11bSopenharmony_ci  rpcclnt_setuidgid(uid, gid);
721beacf11bSopenharmony_ci
722beacf11bSopenharmony_ci  len = strlen(server_ip_and_path);
723beacf11bSopenharmony_ci  for (pos = 0; pos < len; pos++)
724beacf11bSopenharmony_ci    {
725beacf11bSopenharmony_ci      if (*(server_ip_and_path + pos) == ':')
726beacf11bSopenharmony_ci        {
727beacf11bSopenharmony_ci          found_colon = 1;
728beacf11bSopenharmony_ci          break;
729beacf11bSopenharmony_ci        }
730beacf11bSopenharmony_ci    }
731beacf11bSopenharmony_ci
732beacf11bSopenharmony_ci  if (!found_colon)
733beacf11bSopenharmony_ci    {
734beacf11bSopenharmony_ci      set_errno(ENOENT);
735beacf11bSopenharmony_ci      goto nfs_mount_out;
736beacf11bSopenharmony_ci    }
737beacf11bSopenharmony_ci
738beacf11bSopenharmony_ci  server_ip_addr = (char *)malloc(pos + 1);
739beacf11bSopenharmony_ci  if (server_ip_addr == NULL)
740beacf11bSopenharmony_ci    {
741beacf11bSopenharmony_ci      nfs_debug_info("malloc failure\n");
742beacf11bSopenharmony_ci      set_errno(ENOMEM);
743beacf11bSopenharmony_ci      goto nfs_mount_out;
744beacf11bSopenharmony_ci    }
745beacf11bSopenharmony_ci
746beacf11bSopenharmony_ci  ret = strncpy_s(server_ip_addr, pos + 1, server_ip_and_path, pos);
747beacf11bSopenharmony_ci  if (ret != EOK)
748beacf11bSopenharmony_ci    {
749beacf11bSopenharmony_ci      set_errno(ENOBUFS);
750beacf11bSopenharmony_ci      goto nfs_free_node_out;
751beacf11bSopenharmony_ci    }
752beacf11bSopenharmony_ci  *(server_ip_addr + pos) = '\0';
753beacf11bSopenharmony_ci  server_nfs_path = (char *)(server_ip_and_path + pos + 1);
754beacf11bSopenharmony_ci
755beacf11bSopenharmony_ci  (void)memset_s(&nfs_args, sizeof(nfs_args), 0, sizeof(nfs_args));
756beacf11bSopenharmony_ci
757beacf11bSopenharmony_ci  if (g_NFSMOUNT_HOOK != NULL)
758beacf11bSopenharmony_ci    {
759beacf11bSopenharmony_ci      g_NFSMOUNT_HOOK(&nfs_args);
760beacf11bSopenharmony_ci    }
761beacf11bSopenharmony_ci
762beacf11bSopenharmony_ci  nfs_args.path = server_nfs_path; /* server nfs dir */
763beacf11bSopenharmony_ci
764beacf11bSopenharmony_ci  nfs_srv_addr = (struct sockaddr_in *)&nfs_args.addr;
765beacf11bSopenharmony_ci  nfs_srv_addr->sin_family = AF_INET;
766beacf11bSopenharmony_ci  ret = inet_pton(AF_INET, server_ip_addr, &nfs_srv_addr->sin_addr.s_addr);
767beacf11bSopenharmony_ci  if (ret != 1)
768beacf11bSopenharmony_ci    {
769beacf11bSopenharmony_ci      ret = -1;
770beacf11bSopenharmony_ci      set_errno(ECONNREFUSED);
771beacf11bSopenharmony_ci      goto nfs_free_node_out;
772beacf11bSopenharmony_ci    }
773beacf11bSopenharmony_ci  nfs_srv_addr->sin_port = htons(PMAPPORT);
774beacf11bSopenharmony_ci
775beacf11bSopenharmony_ci  nfs_args.addrlen = sizeof(nfs_args.addr);
776beacf11bSopenharmony_ci#if (NFS_PROTO_TYPE == NFS_IPPROTO_TCP)
777beacf11bSopenharmony_ci  nfs_args.sotype = SOCK_STREAM;
778beacf11bSopenharmony_ci#elif (NFS_PROTO_TYPE == NFS_IPPROTO_UDP)
779beacf11bSopenharmony_ci  nfs_args.sotype = SOCK_DGRAM;
780beacf11bSopenharmony_ci#endif
781beacf11bSopenharmony_ci
782beacf11bSopenharmony_ci  PRINTK("Mount nfs on %s:%s, uid:%d, gid:%d\n", server_ip_addr, server_nfs_path, uid, gid);
783beacf11bSopenharmony_ci  ret = mount((const char *)NULL, mount_path, "nfs", 0, &nfs_args);
784beacf11bSopenharmony_ci
785beacf11bSopenharmony_cinfs_free_node_out:
786beacf11bSopenharmony_ci  free(server_ip_addr);
787beacf11bSopenharmony_ci
788beacf11bSopenharmony_cinfs_mount_out:
789beacf11bSopenharmony_ci  if (ret)
790beacf11bSopenharmony_ci    {
791beacf11bSopenharmony_ci      perror("mount nfs error");
792beacf11bSopenharmony_ci      return -1;
793beacf11bSopenharmony_ci    }
794beacf11bSopenharmony_ci  PRINTK("Mount nfs finished.\n");
795beacf11bSopenharmony_ci  return 0;
796beacf11bSopenharmony_ci}
797beacf11bSopenharmony_ci
798beacf11bSopenharmony_ciint vfs_nfs_mount(struct Mount *mnt, struct Vnode *device, const void *data)
799beacf11bSopenharmony_ci{
800beacf11bSopenharmony_ci  struct nfsmount *nmp = NULL;
801beacf11bSopenharmony_ci  struct Vnode *vp = NULL;
802beacf11bSopenharmony_ci
803beacf11bSopenharmony_ci  int ret = VnodeAlloc(&nfs_vops, &vp);
804beacf11bSopenharmony_ci  if (ret != OK)
805beacf11bSopenharmony_ci    {
806beacf11bSopenharmony_ci      return -EADDRNOTAVAIL;
807beacf11bSopenharmony_ci    }
808beacf11bSopenharmony_ci
809beacf11bSopenharmony_ci  struct nfsnode *root = zalloc(sizeof(struct nfsnode));
810beacf11bSopenharmony_ci  if (root == NULL)
811beacf11bSopenharmony_ci    {
812beacf11bSopenharmony_ci      (void)VnodeFree(vp);
813beacf11bSopenharmony_ci      return -EADDRNOTAVAIL;
814beacf11bSopenharmony_ci    }
815beacf11bSopenharmony_ci
816beacf11bSopenharmony_ci  ret = nfs_bind(NULL, data, (void **)(&nmp), NULL);
817beacf11bSopenharmony_ci  if (ret != OK || nmp == NULL)
818beacf11bSopenharmony_ci    {
819beacf11bSopenharmony_ci      (void)VnodeFree(vp);
820beacf11bSopenharmony_ci      free(root);
821beacf11bSopenharmony_ci      return -EAGAIN;
822beacf11bSopenharmony_ci    }
823beacf11bSopenharmony_ci  vp->originMount = mnt;
824beacf11bSopenharmony_ci  vp->fop = &nfs_fops;
825beacf11bSopenharmony_ci  vp->data = root;
826beacf11bSopenharmony_ci  root->n_fhsize = nmp->nm_fhsize;
827beacf11bSopenharmony_ci  (void)memcpy_s(&(root->n_fhandle), root->n_fhsize, &(nmp->nm_fh), nmp->nm_fhsize);
828beacf11bSopenharmony_ci  root->n_pfhsize = 0;
829beacf11bSopenharmony_ci  mnt->vnodeCovered = vp;
830beacf11bSopenharmony_ci  mnt->data = nmp;
831beacf11bSopenharmony_ci  root->n_next = nmp->nm_head;
832beacf11bSopenharmony_ci  nmp->nm_head = root;
833beacf11bSopenharmony_ci
834beacf11bSopenharmony_ci  ret = vfs_nfs_stat_internal(nmp, root);
835beacf11bSopenharmony_ci  if (ret == OK)
836beacf11bSopenharmony_ci    {
837beacf11bSopenharmony_ci      vp->type = root->n_type;
838beacf11bSopenharmony_ci    }
839beacf11bSopenharmony_ci  nmp->nm_permission = mnt->vnodeBeCovered->mode & 0777;
840beacf11bSopenharmony_ci  nmp->nm_gid = mnt->vnodeBeCovered->gid;
841beacf11bSopenharmony_ci  nmp->nm_uid = mnt->vnodeBeCovered->uid;
842beacf11bSopenharmony_ci  vp->mode = type_to_mode(vp->type, nmp->nm_permission);
843beacf11bSopenharmony_ci  vp->gid = nmp->nm_gid;
844beacf11bSopenharmony_ci  vp->uid = nmp->nm_uid;
845beacf11bSopenharmony_ci  return OK;
846beacf11bSopenharmony_ci}
847beacf11bSopenharmony_ci
848beacf11bSopenharmony_ciint vfs_nfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp)
849beacf11bSopenharmony_ci{
850beacf11bSopenharmony_ci  int ret;
851beacf11bSopenharmony_ci  struct nfs_fattr obj_attributes;
852beacf11bSopenharmony_ci  struct nfsmount *nmp;
853beacf11bSopenharmony_ci  char filename[len + 1];
854beacf11bSopenharmony_ci  struct file_handle fhandle;
855beacf11bSopenharmony_ci  struct nfsnode *parent_nfs_node = NULL;
856beacf11bSopenharmony_ci  struct nfsnode *nfs_node = NULL;
857beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(parent->originMount->data);
858beacf11bSopenharmony_ci  nfs_mux_take(nmp);
859beacf11bSopenharmony_ci  parent_nfs_node = (struct nfsnode *)parent->data;
860beacf11bSopenharmony_ci  fhandle.length = parent_nfs_node->n_fhsize;
861beacf11bSopenharmony_ci  (void)memcpy_s(&(fhandle.handle), fhandle.length, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize);
862beacf11bSopenharmony_ci  filename[len] = '\0';
863beacf11bSopenharmony_ci  (void)memcpy_s(filename, (len + 1), path, len);
864beacf11bSopenharmony_ci
865beacf11bSopenharmony_ci  ret = nfs_lookup(nmp, filename, &fhandle, &obj_attributes, NULL);
866beacf11bSopenharmony_ci  if (ret != OK)
867beacf11bSopenharmony_ci    {
868beacf11bSopenharmony_ci      nfs_mux_release(nmp);
869beacf11bSopenharmony_ci      return -ENOENT;
870beacf11bSopenharmony_ci    }
871beacf11bSopenharmony_ci
872beacf11bSopenharmony_ci  /* Initialize the file private data.
873beacf11bSopenharmony_ci   *
874beacf11bSopenharmony_ci   * Copy the file handle.
875beacf11bSopenharmony_ci   */
876beacf11bSopenharmony_ci  nfs_node = zalloc(sizeof(struct nfsnode));
877beacf11bSopenharmony_ci  nfs_node->n_fhsize = (uint8_t)fhandle.length;
878beacf11bSopenharmony_ci  memcpy_s(&(nfs_node->n_fhandle), nfs_node->n_fhsize, &(fhandle.handle), fhandle.length);
879beacf11bSopenharmony_ci  nfs_node->n_pfhsize = parent_nfs_node->n_fhsize;
880beacf11bSopenharmony_ci  (void)memcpy_s(&(nfs_node->n_pfhandle), NFSX_V3FHMAX, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize);
881beacf11bSopenharmony_ci  nfs_node->n_name = zalloc(sizeof(filename));
882beacf11bSopenharmony_ci  memcpy_s(nfs_node->n_name, (len + 1), filename, sizeof(filename));
883beacf11bSopenharmony_ci  nfs_node->n_next = nmp->nm_head;
884beacf11bSopenharmony_ci  nmp->nm_head = nfs_node;
885beacf11bSopenharmony_ci
886beacf11bSopenharmony_ci  /* Save the file attributes */
887beacf11bSopenharmony_ci  nfs_attrupdate(nfs_node, &obj_attributes);
888beacf11bSopenharmony_ci
889beacf11bSopenharmony_ci  (void)VnodeAlloc(&nfs_vops, vpp);
890beacf11bSopenharmony_ci  (*vpp)->parent = parent;
891beacf11bSopenharmony_ci  (*vpp)->fop = &nfs_fops;
892beacf11bSopenharmony_ci  (*vpp)->originMount = parent->originMount;
893beacf11bSopenharmony_ci  (*vpp)->data = nfs_node;
894beacf11bSopenharmony_ci  (*vpp)->type = filetype_to_vnodetype(nfs_node->n_type);
895beacf11bSopenharmony_ci  (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission);
896beacf11bSopenharmony_ci  (*vpp)->gid = nmp->nm_gid;
897beacf11bSopenharmony_ci  (*vpp)->uid = nmp->nm_uid;
898beacf11bSopenharmony_ci  nfs_mux_release(nmp);
899beacf11bSopenharmony_ci  return OK;
900beacf11bSopenharmony_ci}
901beacf11bSopenharmony_ci
902beacf11bSopenharmony_ciint vfs_nfs_stat(struct Vnode *node, struct stat *buf)
903beacf11bSopenharmony_ci{
904beacf11bSopenharmony_ci  struct nfsnode *nfs_node = NULL;
905beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
906beacf11bSopenharmony_ci  nfs_mux_take(nmp);
907beacf11bSopenharmony_ci  nfs_node = (struct nfsnode *)node->data;
908beacf11bSopenharmony_ci  buf->st_mode = node->mode;
909beacf11bSopenharmony_ci  buf->st_gid = node->gid;
910beacf11bSopenharmony_ci  buf->st_uid = node->uid;
911beacf11bSopenharmony_ci  buf->st_size    = (off_t)nfs_node->n_size;
912beacf11bSopenharmony_ci  buf->st_blksize = 0;
913beacf11bSopenharmony_ci  buf->st_blocks  = 0;
914beacf11bSopenharmony_ci  buf->st_mtime   = nfs_node->n_timestamp.tv_sec;
915beacf11bSopenharmony_ci  buf->st_atime   = nfs_node->n_atime;
916beacf11bSopenharmony_ci  buf->st_ctime   = nfs_node->n_ctime;
917beacf11bSopenharmony_ci
918beacf11bSopenharmony_ci  /* Adapt to kstat member "long tv_sec" */
919beacf11bSopenharmony_ci  buf->__st_mtim32.tv_sec   = (long)nfs_node->n_timestamp.tv_sec;
920beacf11bSopenharmony_ci  buf->__st_atim32.tv_sec   = (long)nfs_node->n_atime;
921beacf11bSopenharmony_ci  buf->__st_ctim32.tv_sec   = (long)nfs_node->n_ctime;
922beacf11bSopenharmony_ci
923beacf11bSopenharmony_ci  nfs_mux_release(nmp);
924beacf11bSopenharmony_ci  return OK;
925beacf11bSopenharmony_ci}
926beacf11bSopenharmony_ci
927beacf11bSopenharmony_ciint vfs_nfs_opendir(struct Vnode *node, struct fs_dirent_s *dir)
928beacf11bSopenharmony_ci{
929beacf11bSopenharmony_ci  int ret;
930beacf11bSopenharmony_ci  struct nfsdir_s *nfs_dir = NULL;
931beacf11bSopenharmony_ci  struct nfsnode *nfs_node = NULL;
932beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
933beacf11bSopenharmony_ci  if (node->type != VNODE_TYPE_DIR) {
934beacf11bSopenharmony_ci      return -ENOTDIR;
935beacf11bSopenharmony_ci  }
936beacf11bSopenharmony_ci  nfs_mux_take(nmp);
937beacf11bSopenharmony_ci  nfs_node = (struct nfsnode *)node->data;
938beacf11bSopenharmony_ci  ret = nfs_checkmount(nmp);
939beacf11bSopenharmony_ci  if (ret != OK) {
940beacf11bSopenharmony_ci      ret = -ret;
941beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", ret);
942beacf11bSopenharmony_ci      goto errout_with_mutex;
943beacf11bSopenharmony_ci  }
944beacf11bSopenharmony_ci  nfs_dir = (struct nfsdir_s *)malloc(sizeof(struct nfsdir_s));
945beacf11bSopenharmony_ci  if (!nfs_dir) {
946beacf11bSopenharmony_ci      ret = -ENOMEM;
947beacf11bSopenharmony_ci      goto errout_with_mutex;
948beacf11bSopenharmony_ci  }
949beacf11bSopenharmony_ci  nfs_dir->nfs_fhsize = nfs_node->n_fhsize;
950beacf11bSopenharmony_ci  nfs_dir->nfs_cookie[0] = 0;
951beacf11bSopenharmony_ci  nfs_dir->nfs_cookie[1] = 0;
952beacf11bSopenharmony_ci  (void)memcpy_s(nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE, &(nfs_node->n_fhandle), DIRENT_NFS_MAXHANDLE);
953beacf11bSopenharmony_ci  dir->u.fs_dir = (fs_dir_s)nfs_dir;
954beacf11bSopenharmony_ci  ret = OK;
955beacf11bSopenharmony_ci
956beacf11bSopenharmony_ci  nfs_dir->nfs_next = nmp->nm_dir;
957beacf11bSopenharmony_ci  nmp->nm_dir = nfs_dir;
958beacf11bSopenharmony_ci  nfs_dir->nfs_dir = dir;
959beacf11bSopenharmony_ci  nfs_dir->nfs_entries = NULL;
960beacf11bSopenharmony_ci
961beacf11bSopenharmony_cierrout_with_mutex:
962beacf11bSopenharmony_ci  nfs_mux_release(nmp);
963beacf11bSopenharmony_ci  return ret;
964beacf11bSopenharmony_ci}
965beacf11bSopenharmony_ci
966beacf11bSopenharmony_ciint vfs_nfs_readdir(struct Vnode *node, struct fs_dirent_s *dir)
967beacf11bSopenharmony_ci{
968beacf11bSopenharmony_ci  struct nfsmount *nmp;
969beacf11bSopenharmony_ci  struct file_handle fhandle;
970beacf11bSopenharmony_ci  struct nfs_fattr obj_attributes;
971beacf11bSopenharmony_ci  struct nfsdir_s *nfs_dir = NULL;
972beacf11bSopenharmony_ci  struct entry3   *entry = NULL;
973beacf11bSopenharmony_ci  struct entry3   *entry_pos = NULL;
974beacf11bSopenharmony_ci
975beacf11bSopenharmony_ci  /* Use 2 cookies */
976beacf11bSopenharmony_ci
977beacf11bSopenharmony_ci  uint32_t cookies[2];
978beacf11bSopenharmony_ci  uint32_t tmp;
979beacf11bSopenharmony_ci  uint32_t *ptr = NULL;
980beacf11bSopenharmony_ci  size_t d_name_size;
981beacf11bSopenharmony_ci  int reqlen;
982beacf11bSopenharmony_ci  int error = 0;
983beacf11bSopenharmony_ci  int i = 0;
984beacf11bSopenharmony_ci
985beacf11bSopenharmony_ci  /* Sanity checks */
986beacf11bSopenharmony_ci
987beacf11bSopenharmony_ci  /* Recover our private data from the vnode instance */
988beacf11bSopenharmony_ci
989beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(node->originMount->data);
990beacf11bSopenharmony_ci
991beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
992beacf11bSopenharmony_ci
993beacf11bSopenharmony_ci  nfs_mux_take(nmp);
994beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
995beacf11bSopenharmony_ci  if (error != OK)
996beacf11bSopenharmony_ci    {
997beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
998beacf11bSopenharmony_ci      goto errout_with_mutex;
999beacf11bSopenharmony_ci    }
1000beacf11bSopenharmony_ci
1001beacf11bSopenharmony_ci  /* Request a block directory entries, copying directory information from
1002beacf11bSopenharmony_ci   * the dirent structure.
1003beacf11bSopenharmony_ci   */
1004beacf11bSopenharmony_ci  nfs_dir = (struct nfsdir_s *)dir->u.fs_dir;
1005beacf11bSopenharmony_ci  cookies[0] = 0;
1006beacf11bSopenharmony_ci  cookies[1] = 0;
1007beacf11bSopenharmony_ci
1008beacf11bSopenharmony_ci  if (nfs_dir && nfs_dir->nfs_entries && (nfs_dir->nfs_entries->file_id[0] == (uint32_t)EOF))
1009beacf11bSopenharmony_ci    {
1010beacf11bSopenharmony_ci      error = ENOENT;
1011beacf11bSopenharmony_ci      free(nfs_dir->nfs_entries);
1012beacf11bSopenharmony_ci      nfs_dir->nfs_entries = NULL;
1013beacf11bSopenharmony_ci      goto errout_with_mutex;
1014beacf11bSopenharmony_ci    }
1015beacf11bSopenharmony_ci  while (i < dir->read_cnt)
1016beacf11bSopenharmony_ci    {
1017beacf11bSopenharmony_ci      if (!nfs_dir->nfs_entries)
1018beacf11bSopenharmony_ci        {
1019beacf11bSopenharmony_ci          entry_pos = nfs_dir->nfs_entries;
1020beacf11bSopenharmony_ci          do
1021beacf11bSopenharmony_ci            {
1022beacf11bSopenharmony_ci              ptr     = (uint32_t *)&nmp->nm_msgbuffer.readdir.readdir;
1023beacf11bSopenharmony_ci              reqlen  = 0;
1024beacf11bSopenharmony_ci
1025beacf11bSopenharmony_ci              /* Copy the variable length, directory file handle */
1026beacf11bSopenharmony_ci
1027beacf11bSopenharmony_ci              *ptr++  = txdr_unsigned((uint32_t)nfs_dir->nfs_fhsize);
1028beacf11bSopenharmony_ci              reqlen += sizeof(uint32_t);
1029beacf11bSopenharmony_ci
1030beacf11bSopenharmony_ci              (void)memcpy_s(ptr, nfs_dir->nfs_fhsize, nfs_dir->nfs_fhandle, nfs_dir->nfs_fhsize);
1031beacf11bSopenharmony_ci              reqlen += (int)nfs_dir->nfs_fhsize;
1032beacf11bSopenharmony_ci              ptr    += uint32_increment((int)nfs_dir->nfs_fhsize);
1033beacf11bSopenharmony_ci
1034beacf11bSopenharmony_ci              /* Cookie and cookie verifier */
1035beacf11bSopenharmony_ci
1036beacf11bSopenharmony_ci              ptr[0] = cookies[0];
1037beacf11bSopenharmony_ci              ptr[1] = cookies[1];
1038beacf11bSopenharmony_ci              ptr    += 2;
1039beacf11bSopenharmony_ci              reqlen += 2 * sizeof(uint32_t);
1040beacf11bSopenharmony_ci
1041beacf11bSopenharmony_ci              (void)memcpy_s(ptr, DIRENT_NFS_VERFLEN, nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN);
1042beacf11bSopenharmony_ci              ptr    += uint32_increment(DIRENT_NFS_VERFLEN);
1043beacf11bSopenharmony_ci              reqlen += DIRENT_NFS_VERFLEN;
1044beacf11bSopenharmony_ci
1045beacf11bSopenharmony_ci              /* Number of directory entries (We currently only process one entry at a time) */
1046beacf11bSopenharmony_ci
1047beacf11bSopenharmony_ci              *ptr    = txdr_unsigned((uint32_t)nmp->nm_readdirsize);
1048beacf11bSopenharmony_ci              reqlen += sizeof(uint32_t);
1049beacf11bSopenharmony_ci
1050beacf11bSopenharmony_ci              /* And read the directory */
1051beacf11bSopenharmony_ci
1052beacf11bSopenharmony_ci              nfs_statistics(NFSPROC_READDIR);
1053beacf11bSopenharmony_ci              error = nfs_request(nmp, NFSPROC_READDIR,
1054beacf11bSopenharmony_ci                                  (void *)&nmp->nm_msgbuffer.readdir, reqlen,
1055beacf11bSopenharmony_ci                                  (void *)nmp->nm_iobuffer, nmp->nm_buflen);
1056beacf11bSopenharmony_ci
1057beacf11bSopenharmony_ci              if (error != OK)
1058beacf11bSopenharmony_ci                {
1059beacf11bSopenharmony_ci                  nfs_debug_error("nfs_request failed: %d\n", error);
1060beacf11bSopenharmony_ci                  goto errout_with_mutex;
1061beacf11bSopenharmony_ci                }
1062beacf11bSopenharmony_ci
1063beacf11bSopenharmony_ci              /* A new group of entries was successfully read.  Process the
1064beacf11bSopenharmony_ci               * information contained in the response header.  This information
1065beacf11bSopenharmony_ci               * includes:
1066beacf11bSopenharmony_ci               *
1067beacf11bSopenharmony_ci               * 1) Attributes follow indication - 4 bytes
1068beacf11bSopenharmony_ci               * 2) Directory attributes         - sizeof(struct nfs_fattr)
1069beacf11bSopenharmony_ci               * 3) Cookie verifier              - NFSX_V3COOKIEVERF bytes
1070beacf11bSopenharmony_ci               * 4) Values follows indication    - 4 bytes
1071beacf11bSopenharmony_ci               */
1072beacf11bSopenharmony_ci
1073beacf11bSopenharmony_ci              ptr = (uint32_t *)&((struct rpc_reply_readdir *)nmp->nm_iobuffer)->readdir;
1074beacf11bSopenharmony_ci
1075beacf11bSopenharmony_ci              /* Check if attributes follow, if 0 so Skip over the attributes */
1076beacf11bSopenharmony_ci
1077beacf11bSopenharmony_ci              tmp = *ptr++;
1078beacf11bSopenharmony_ci              if (tmp != 0)
1079beacf11bSopenharmony_ci                {
1080beacf11bSopenharmony_ci                  /* Attributes are not currently used */
1081beacf11bSopenharmony_ci
1082beacf11bSopenharmony_ci                  ptr += uint32_increment(sizeof(struct nfs_fattr));
1083beacf11bSopenharmony_ci                }
1084beacf11bSopenharmony_ci
1085beacf11bSopenharmony_ci              /* Save the verification cookie */
1086beacf11bSopenharmony_ci
1087beacf11bSopenharmony_ci              (void)memcpy_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, ptr, DIRENT_NFS_VERFLEN);
1088beacf11bSopenharmony_ci              ptr += uint32_increment(DIRENT_NFS_VERFLEN);
1089beacf11bSopenharmony_ci
1090beacf11bSopenharmony_ci              /* Check if values follow.  If no values follow, then the EOF indication
1091beacf11bSopenharmony_ci               * will appear next.
1092beacf11bSopenharmony_ci               */
1093beacf11bSopenharmony_ci
1094beacf11bSopenharmony_ci              tmp = *ptr++;
1095beacf11bSopenharmony_ci              if (tmp == 0)
1096beacf11bSopenharmony_ci                {
1097beacf11bSopenharmony_ci                  /* No values follow, then the reply should consist only of a 4-byte
1098beacf11bSopenharmony_ci                   * end-of-directory indication.
1099beacf11bSopenharmony_ci                   */
1100beacf11bSopenharmony_ci
1101beacf11bSopenharmony_ci                  tmp = *ptr++;
1102beacf11bSopenharmony_ci                  if (tmp != 0)
1103beacf11bSopenharmony_ci                    {
1104beacf11bSopenharmony_ci                      error = ENOENT;
1105beacf11bSopenharmony_ci                    }
1106beacf11bSopenharmony_ci
1107beacf11bSopenharmony_ci                  /* What would it mean if there were not data and we not at the end of
1108beacf11bSopenharmony_ci                   * file?
1109beacf11bSopenharmony_ci                   */
1110beacf11bSopenharmony_ci
1111beacf11bSopenharmony_ci                  else
1112beacf11bSopenharmony_ci                    {
1113beacf11bSopenharmony_ci                      error = EAGAIN;
1114beacf11bSopenharmony_ci                    }
1115beacf11bSopenharmony_ci                  goto errout_with_mutex;
1116beacf11bSopenharmony_ci                }
1117beacf11bSopenharmony_ci
1118beacf11bSopenharmony_ci              /* If we are not at the end of the directory listing, then a set of entries
1119beacf11bSopenharmony_ci               * will follow the header.  Each entry is of the form:
1120beacf11bSopenharmony_ci               *
1121beacf11bSopenharmony_ci               *    File ID (8 bytes)
1122beacf11bSopenharmony_ci               *    Name length (4 bytes)
1123beacf11bSopenharmony_ci               *    Name string (varaiable size but in multiples of 4 bytes)
1124beacf11bSopenharmony_ci               *    Cookie (8 bytes)
1125beacf11bSopenharmony_ci               *    next entry (4 bytes)
1126beacf11bSopenharmony_ci               */
1127beacf11bSopenharmony_ci
1128beacf11bSopenharmony_ci               do
1129beacf11bSopenharmony_ci                {
1130beacf11bSopenharmony_ci                  NFS_DIR_ENTRY_MALLOC(entry);
1131beacf11bSopenharmony_ci
1132beacf11bSopenharmony_ci                  /* There is an entry. Skip over the file ID and point to the length */
1133beacf11bSopenharmony_ci
1134beacf11bSopenharmony_ci                  entry->file_id[0] = *ptr++;
1135beacf11bSopenharmony_ci                  entry->file_id[1] = *ptr++; /*lint !e662 !e661*/
1136beacf11bSopenharmony_ci
1137beacf11bSopenharmony_ci                  /* Get the length and point to the name */
1138beacf11bSopenharmony_ci
1139beacf11bSopenharmony_ci                  tmp    = *ptr++; /*lint !e662 !e661*/
1140beacf11bSopenharmony_ci                  entry->name_len = fxdr_unsigned(uint32_t, tmp);
1141beacf11bSopenharmony_ci                  entry->contents = (uint8_t *)malloc(entry->name_len + 1);
1142beacf11bSopenharmony_ci                  if (!entry->contents)
1143beacf11bSopenharmony_ci                    {
1144beacf11bSopenharmony_ci                      free(entry);
1145beacf11bSopenharmony_ci                      entry = NULL;
1146beacf11bSopenharmony_ci                      goto errout_with_memory;
1147beacf11bSopenharmony_ci                    }
1148beacf11bSopenharmony_ci                  (void)memset_s(entry->contents, entry->name_len + 1, 0, entry->name_len + 1);
1149beacf11bSopenharmony_ci
1150beacf11bSopenharmony_ci                  error = strncpy_s((char *)entry->contents, entry->name_len + 1, (const char *)ptr, entry->name_len);
1151beacf11bSopenharmony_ci                  if (error != EOK)
1152beacf11bSopenharmony_ci                    {
1153beacf11bSopenharmony_ci                      free(entry->contents);
1154beacf11bSopenharmony_ci                      entry->contents = NULL;
1155beacf11bSopenharmony_ci                      free(entry);
1156beacf11bSopenharmony_ci                      entry = NULL;
1157beacf11bSopenharmony_ci                      error = ENOBUFS;
1158beacf11bSopenharmony_ci                      goto errout_with_memory;
1159beacf11bSopenharmony_ci                    }
1160beacf11bSopenharmony_ci                  /* Increment the pointer past the name (allowing for padding). ptr
1161beacf11bSopenharmony_ci                   * now points to the cookie.
1162beacf11bSopenharmony_ci                   */
1163beacf11bSopenharmony_ci
1164beacf11bSopenharmony_ci                  ptr += uint32_increment(entry->name_len);
1165beacf11bSopenharmony_ci
1166beacf11bSopenharmony_ci                  /* Save the cookie and increment the pointer to the next entry */
1167beacf11bSopenharmony_ci
1168beacf11bSopenharmony_ci                  entry->cookie[0] = *ptr++;
1169beacf11bSopenharmony_ci                  entry->cookie[1] = *ptr++;
1170beacf11bSopenharmony_ci
1171beacf11bSopenharmony_ci                  /* Get the file attributes associated with this name and return
1172beacf11bSopenharmony_ci                   * the file type.
1173beacf11bSopenharmony_ci                   */
1174beacf11bSopenharmony_ci
1175beacf11bSopenharmony_ci                  if (strcmp((char *)entry->contents, ".") == 0 || strcmp((char *)entry->contents, "..") == 0)
1176beacf11bSopenharmony_ci                    {
1177beacf11bSopenharmony_ci                      NFS_DIR_ENTRY_FREE(entry);
1178beacf11bSopenharmony_ci                      continue;
1179beacf11bSopenharmony_ci                    }
1180beacf11bSopenharmony_ci
1181beacf11bSopenharmony_ci                  if (!nfs_dir->nfs_entries)
1182beacf11bSopenharmony_ci                    {
1183beacf11bSopenharmony_ci                      entry_pos = entry;
1184beacf11bSopenharmony_ci                      nfs_dir->nfs_entries = entry;
1185beacf11bSopenharmony_ci                    }
1186beacf11bSopenharmony_ci                  else
1187beacf11bSopenharmony_ci                    {
1188beacf11bSopenharmony_ci                      entry_pos->next = entry;
1189beacf11bSopenharmony_ci                      entry_pos = entry;
1190beacf11bSopenharmony_ci                    }
1191beacf11bSopenharmony_ci                }
1192beacf11bSopenharmony_ci              while (*ptr++);
1193beacf11bSopenharmony_ci              if (entry_pos)
1194beacf11bSopenharmony_ci                {
1195beacf11bSopenharmony_ci                  cookies[0] = entry_pos->cookie[0];
1196beacf11bSopenharmony_ci                  cookies[1] = entry_pos->cookie[1];
1197beacf11bSopenharmony_ci                }
1198beacf11bSopenharmony_ci            }
1199beacf11bSopenharmony_ci          while (!(*ptr));
1200beacf11bSopenharmony_ci
1201beacf11bSopenharmony_ci          if (!nfs_dir->nfs_entries)
1202beacf11bSopenharmony_ci            {
1203beacf11bSopenharmony_ci              error = ENOENT;
1204beacf11bSopenharmony_ci              goto errout_with_mutex;
1205beacf11bSopenharmony_ci            }
1206beacf11bSopenharmony_ci
1207beacf11bSopenharmony_ci          NFS_DIR_ENTRY_MALLOC(entry);
1208beacf11bSopenharmony_ci
1209beacf11bSopenharmony_ci          /* There is an entry. Skip over the file ID and point to the length */
1210beacf11bSopenharmony_ci
1211beacf11bSopenharmony_ci          entry->file_id[0] = (uint32_t)EOF;
1212beacf11bSopenharmony_ci          if (!entry_pos)
1213beacf11bSopenharmony_ci            {
1214beacf11bSopenharmony_ci              error = ENOENT;
1215beacf11bSopenharmony_ci              NFS_DIR_ENTRY_FREE(entry);
1216beacf11bSopenharmony_ci              goto errout_with_mutex;
1217beacf11bSopenharmony_ci            }
1218beacf11bSopenharmony_ci          entry_pos->next = entry;
1219beacf11bSopenharmony_ci          entry_pos = entry;
1220beacf11bSopenharmony_ci        }
1221beacf11bSopenharmony_ci
1222beacf11bSopenharmony_ci      entry_pos = nfs_dir->nfs_entries;
1223beacf11bSopenharmony_ci      if (nfs_dir->nfs_entries->file_id[0] == (uint32_t)EOF)
1224beacf11bSopenharmony_ci        {
1225beacf11bSopenharmony_ci          error = ENOENT;
1226beacf11bSopenharmony_ci          goto errout_with_mutex;
1227beacf11bSopenharmony_ci        }
1228beacf11bSopenharmony_ci
1229beacf11bSopenharmony_ci      d_name_size = sizeof(dir->fd_dir[i].d_name);
1230beacf11bSopenharmony_ci      error = memcpy_s(dir->fd_dir[i].d_name, d_name_size, (const char *)entry_pos->contents, (size_t)entry_pos->name_len);
1231beacf11bSopenharmony_ci      if (error != EOK)
1232beacf11bSopenharmony_ci        {
1233beacf11bSopenharmony_ci          error = ENOBUFS;
1234beacf11bSopenharmony_ci          goto errout_with_memory;
1235beacf11bSopenharmony_ci        }
1236beacf11bSopenharmony_ci      if (entry_pos->name_len >= d_name_size)
1237beacf11bSopenharmony_ci        {
1238beacf11bSopenharmony_ci          dir->fd_dir[i].d_name[d_name_size - 1] = '\0';
1239beacf11bSopenharmony_ci        }
1240beacf11bSopenharmony_ci      else
1241beacf11bSopenharmony_ci        {
1242beacf11bSopenharmony_ci          dir->fd_dir[i].d_name[entry_pos->name_len] = '\0';
1243beacf11bSopenharmony_ci        }
1244beacf11bSopenharmony_ci
1245beacf11bSopenharmony_ci      nfs_dir->nfs_entries = entry_pos->next;
1246beacf11bSopenharmony_ci      NFS_DIR_ENTRY_FREE(entry_pos);
1247beacf11bSopenharmony_ci
1248beacf11bSopenharmony_ci      fhandle.length = (uint32_t)nfs_dir->nfs_fhsize;
1249beacf11bSopenharmony_ci      (void)memcpy_s(&fhandle.handle, DIRENT_NFS_MAXHANDLE, nfs_dir->nfs_fhandle, DIRENT_NFS_MAXHANDLE);
1250beacf11bSopenharmony_ci
1251beacf11bSopenharmony_ci      error = nfs_lookup(nmp, dir->fd_dir[i].d_name, &fhandle, &obj_attributes, NULL);
1252beacf11bSopenharmony_ci      if (error != OK)
1253beacf11bSopenharmony_ci      {
1254beacf11bSopenharmony_ci        nfs_debug_error("nfs_lookup failed: %d\n", error);
1255beacf11bSopenharmony_ci        goto errout_with_memory;
1256beacf11bSopenharmony_ci      }
1257beacf11bSopenharmony_ci
1258beacf11bSopenharmony_ci      /* Set the dirent file type */
1259beacf11bSopenharmony_ci
1260beacf11bSopenharmony_ci      tmp = fxdr_unsigned(uint32_t, obj_attributes.fa_type);
1261beacf11bSopenharmony_ci      switch (tmp)
1262beacf11bSopenharmony_ci        {
1263beacf11bSopenharmony_ci        default:
1264beacf11bSopenharmony_ci        case NFNON:        /* Unknown type */
1265beacf11bSopenharmony_ci        case NFSOCK:       /* Socket */
1266beacf11bSopenharmony_ci        case NFLNK:        /* Symbolic link */
1267beacf11bSopenharmony_ci          break;
1268beacf11bSopenharmony_ci
1269beacf11bSopenharmony_ci        case NFREG:        /* Regular file */
1270beacf11bSopenharmony_ci          dir->fd_dir[i].d_type = DT_REG;
1271beacf11bSopenharmony_ci          break;
1272beacf11bSopenharmony_ci
1273beacf11bSopenharmony_ci        case NFDIR:        /* Directory */
1274beacf11bSopenharmony_ci          dir->fd_dir[i].d_type = DT_DIR;
1275beacf11bSopenharmony_ci          break;
1276beacf11bSopenharmony_ci
1277beacf11bSopenharmony_ci        case NFBLK:        /* Block special device file */
1278beacf11bSopenharmony_ci          dir->fd_dir[i].d_type = DT_BLK;
1279beacf11bSopenharmony_ci          break;
1280beacf11bSopenharmony_ci
1281beacf11bSopenharmony_ci        case NFFIFO:       /* Named FIFO */
1282beacf11bSopenharmony_ci        case NFCHR:        /* Character special device file */
1283beacf11bSopenharmony_ci          dir->fd_dir[i].d_type = DT_CHR;
1284beacf11bSopenharmony_ci          break;
1285beacf11bSopenharmony_ci        }
1286beacf11bSopenharmony_ci      dir->fd_position++;
1287beacf11bSopenharmony_ci      dir->fd_dir[i].d_off = dir->fd_position;
1288beacf11bSopenharmony_ci      dir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent);
1289beacf11bSopenharmony_ci      i++;
1290beacf11bSopenharmony_ci    }
1291beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1292beacf11bSopenharmony_ci  return i;
1293beacf11bSopenharmony_ci
1294beacf11bSopenharmony_cierrout_with_memory:
1295beacf11bSopenharmony_ci  for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries)
1296beacf11bSopenharmony_ci    {
1297beacf11bSopenharmony_ci      nfs_dir->nfs_entries = entry_pos->next;
1298beacf11bSopenharmony_ci      NFS_DIR_ENTRY_FREE(entry_pos);
1299beacf11bSopenharmony_ci    }
1300beacf11bSopenharmony_cierrout_with_mutex:
1301beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1302beacf11bSopenharmony_ci  if (error == ENOENT && i > 0)
1303beacf11bSopenharmony_ci    {
1304beacf11bSopenharmony_ci      return i;
1305beacf11bSopenharmony_ci    }
1306beacf11bSopenharmony_ci  return -error;
1307beacf11bSopenharmony_ci}
1308beacf11bSopenharmony_ciextern int nfs_getfilename(char *dstpath, unsigned int dstpathLen, const char *srcpath, unsigned int maxlen);
1309beacf11bSopenharmony_ciextern int nfs_rename(struct Vnode *mountpt, const char *oldrelpath, const char *newrelpath);
1310beacf11bSopenharmony_ciint vfs_nfs_rename(struct Vnode *from_vnode, struct Vnode *to_parent,
1311beacf11bSopenharmony_ci                   const char *from_name, const char *to_name)
1312beacf11bSopenharmony_ci{
1313beacf11bSopenharmony_ci  int error;
1314beacf11bSopenharmony_ci  int reqlen;
1315beacf11bSopenharmony_ci  int namelen;
1316beacf11bSopenharmony_ci  uint32_t *ptr = NULL;
1317beacf11bSopenharmony_ci  struct Vnode *to_vnode = NULL;
1318beacf11bSopenharmony_ci  struct Vnode *from_parent = from_vnode->parent;
1319beacf11bSopenharmony_ci  struct nfsnode *from_node = NULL;
1320beacf11bSopenharmony_ci  struct nfsnode *to_node = NULL;
1321beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(to_parent->originMount->data);
1322beacf11bSopenharmony_ci
1323beacf11bSopenharmony_ci  nfs_mux_take(nmp);
1324beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
1325beacf11bSopenharmony_ci  if (error != OK)
1326beacf11bSopenharmony_ci    {
1327beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
1328beacf11bSopenharmony_ci      goto errout_with_mutex;
1329beacf11bSopenharmony_ci    }
1330beacf11bSopenharmony_ci
1331beacf11bSopenharmony_ci  from_node = (struct nfsnode *)from_parent->data;
1332beacf11bSopenharmony_ci  to_node = (struct nfsnode *)to_parent->data;
1333beacf11bSopenharmony_ci
1334beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.renamef.rename;
1335beacf11bSopenharmony_ci  reqlen = 0;
1336beacf11bSopenharmony_ci
1337beacf11bSopenharmony_ci  /* Copy the variable length, 'from' directory file handle */
1338beacf11bSopenharmony_ci
1339beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(from_node->n_fhsize);
1340beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1341beacf11bSopenharmony_ci
1342beacf11bSopenharmony_ci  (void)memcpy_s(ptr, from_node->n_fhsize, &from_node->n_fhandle, from_node->n_fhsize);
1343beacf11bSopenharmony_ci  reqlen += (int)from_node->n_fhsize;
1344beacf11bSopenharmony_ci  ptr    += uint32_increment(from_node->n_fhsize);
1345beacf11bSopenharmony_ci
1346beacf11bSopenharmony_ci  /* Copy the variable-length 'from' object name */
1347beacf11bSopenharmony_ci
1348beacf11bSopenharmony_ci  namelen = strlen(from_name);
1349beacf11bSopenharmony_ci
1350beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
1351beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1352beacf11bSopenharmony_ci
1353beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, from_name, namelen);
1354beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
1355beacf11bSopenharmony_ci  ptr    += uint32_increment(namelen);
1356beacf11bSopenharmony_ci
1357beacf11bSopenharmony_ci  /* Copy the variable length, 'to' directory file handle */
1358beacf11bSopenharmony_ci
1359beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(to_node->n_fhsize);
1360beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1361beacf11bSopenharmony_ci
1362beacf11bSopenharmony_ci  (void)memcpy_s(ptr, to_node->n_fhsize, &to_node->n_fhandle, to_node->n_fhsize);
1363beacf11bSopenharmony_ci  ptr    += uint32_increment(to_node->n_fhsize);
1364beacf11bSopenharmony_ci  reqlen += (int)to_node->n_fhsize;
1365beacf11bSopenharmony_ci
1366beacf11bSopenharmony_ci  /* Copy the variable-length 'to' object name */
1367beacf11bSopenharmony_ci
1368beacf11bSopenharmony_ci  namelen = strlen(to_name);
1369beacf11bSopenharmony_ci
1370beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
1371beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1372beacf11bSopenharmony_ci
1373beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, to_name, namelen);
1374beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
1375beacf11bSopenharmony_ci
1376beacf11bSopenharmony_ci  /* Perform the RENAME RPC */
1377beacf11bSopenharmony_ci
1378beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_RENAME);
1379beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_RENAME,
1380beacf11bSopenharmony_ci      (void *)&nmp->nm_msgbuffer.renamef, reqlen,
1381beacf11bSopenharmony_ci      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
1382beacf11bSopenharmony_ci  if (error != OK)
1383beacf11bSopenharmony_ci    {
1384beacf11bSopenharmony_ci      nfs_debug_error("nfs_request returned: %d\n", error);
1385beacf11bSopenharmony_ci      goto errout_with_mutex;
1386beacf11bSopenharmony_ci    }
1387beacf11bSopenharmony_ci
1388beacf11bSopenharmony_ci  error = vfs_nfs_lookup(to_parent, to_name, strlen(to_name), &to_vnode);
1389beacf11bSopenharmony_ci  if (error != OK)
1390beacf11bSopenharmony_ci    {
1391beacf11bSopenharmony_ci      error = -error;
1392beacf11bSopenharmony_ci      nfs_debug_error("nfs_rename not finish\n");
1393beacf11bSopenharmony_ci      goto errout_with_mutex;
1394beacf11bSopenharmony_ci    }
1395beacf11bSopenharmony_ci  vfs_nfs_reclaim(from_vnode);
1396beacf11bSopenharmony_ci  from_vnode->data = to_vnode->data;
1397beacf11bSopenharmony_ci  from_vnode->parent = to_parent;
1398beacf11bSopenharmony_ci  to_vnode->data = NULL;
1399beacf11bSopenharmony_ci  VnodeFree(to_vnode);
1400beacf11bSopenharmony_ci
1401beacf11bSopenharmony_cierrout_with_mutex:
1402beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1403beacf11bSopenharmony_ci  return -error;
1404beacf11bSopenharmony_ci}
1405beacf11bSopenharmony_ci
1406beacf11bSopenharmony_ciint vfs_nfs_mkdir(struct Vnode *parent, const char *dirname, mode_t mode, struct Vnode **vpp)
1407beacf11bSopenharmony_ci{
1408beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data);
1409beacf11bSopenharmony_ci  struct nfsnode *parent_nfs_node = NULL;
1410beacf11bSopenharmony_ci  struct nfs_fattr obj_attributes;
1411beacf11bSopenharmony_ci  struct nfsnode *target_node = NULL;
1412beacf11bSopenharmony_ci  struct file_handle fhandle;
1413beacf11bSopenharmony_ci  uint32_t          *ptr = NULL;
1414beacf11bSopenharmony_ci  uint32_t               tmp;
1415beacf11bSopenharmony_ci  int                    namelen;
1416beacf11bSopenharmony_ci  int                    reqlen;
1417beacf11bSopenharmony_ci  int                    error;
1418beacf11bSopenharmony_ci
1419beacf11bSopenharmony_ci  /* Sanity checks */
1420beacf11bSopenharmony_ci
1421beacf11bSopenharmony_ci  DEBUGASSERT(parent && parent->data);
1422beacf11bSopenharmony_ci
1423beacf11bSopenharmony_ci  /* Check if the mount is still healthy */
1424beacf11bSopenharmony_ci
1425beacf11bSopenharmony_ci  nfs_mux_take(nmp);
1426beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
1427beacf11bSopenharmony_ci  if (error != OK)
1428beacf11bSopenharmony_ci    {
1429beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount: %d\n", error);
1430beacf11bSopenharmony_ci      goto errout_with_mutex;
1431beacf11bSopenharmony_ci    }
1432beacf11bSopenharmony_ci
1433beacf11bSopenharmony_ci  parent_nfs_node = (struct nfsnode *)parent->data;
1434beacf11bSopenharmony_ci
1435beacf11bSopenharmony_ci  /* Format the MKDIR call message arguments */
1436beacf11bSopenharmony_ci
1437beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.mkdir.mkdir;
1438beacf11bSopenharmony_ci  reqlen = 0;
1439beacf11bSopenharmony_ci
1440beacf11bSopenharmony_ci  /* Copy the variable length, directory file handle */
1441beacf11bSopenharmony_ci
1442beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(parent_nfs_node->n_fhsize);
1443beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1444beacf11bSopenharmony_ci
1445beacf11bSopenharmony_ci  memcpy_s(ptr, parent_nfs_node->n_fhsize, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize);
1446beacf11bSopenharmony_ci  ptr    += uint32_increment(parent_nfs_node->n_fhsize);
1447beacf11bSopenharmony_ci  reqlen += (int)parent_nfs_node->n_fhsize;
1448beacf11bSopenharmony_ci
1449beacf11bSopenharmony_ci  /* Copy the variable-length directory name */
1450beacf11bSopenharmony_ci
1451beacf11bSopenharmony_ci  namelen = strlen(dirname);
1452beacf11bSopenharmony_ci
1453beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
1454beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1455beacf11bSopenharmony_ci
1456beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, dirname, namelen);
1457beacf11bSopenharmony_ci  ptr    += uint32_increment(namelen);
1458beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
1459beacf11bSopenharmony_ci
1460beacf11bSopenharmony_ci  /* Set the mode.  NOTE: Here we depend on the fact that the NuttX and NFS
1461beacf11bSopenharmony_ci   * bit settings are the same (at least for the bits of interest).
1462beacf11bSopenharmony_ci   */
1463beacf11bSopenharmony_ci
1464beacf11bSopenharmony_ci  *ptr++  = nfs_true; /* True: mode value follows */
1465beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1466beacf11bSopenharmony_ci
1467beacf11bSopenharmony_ci  if (!mode)
1468beacf11bSopenharmony_ci    {
1469beacf11bSopenharmony_ci      mode = (NFSMODE_IXOTH | NFSMODE_IROTH |
1470beacf11bSopenharmony_ci              NFSMODE_IXGRP | NFSMODE_IRGRP |
1471beacf11bSopenharmony_ci              NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
1472beacf11bSopenharmony_ci    }
1473beacf11bSopenharmony_ci  tmp = mode & (NFSMODE_IXOTH | NFSMODE_IWOTH | NFSMODE_IROTH |
1474beacf11bSopenharmony_ci                NFSMODE_IXGRP | NFSMODE_IWGRP | NFSMODE_IRGRP |
1475beacf11bSopenharmony_ci                NFSMODE_IXUSR | NFSMODE_IWUSR | NFSMODE_IRUSR);
1476beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(tmp);
1477beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1478beacf11bSopenharmony_ci
1479beacf11bSopenharmony_ci  /* Set the user ID to zero */
1480beacf11bSopenharmony_ci
1481beacf11bSopenharmony_ci  *ptr++  = nfs_true;             /* True: Uid value follows */
1482beacf11bSopenharmony_ci  *ptr++  = 0;                    /* UID = 0 (nobody) */
1483beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
1484beacf11bSopenharmony_ci
1485beacf11bSopenharmony_ci  /* Set the group ID to one */
1486beacf11bSopenharmony_ci
1487beacf11bSopenharmony_ci  *ptr++  = nfs_true;            /* True: Gid value follows */
1488beacf11bSopenharmony_ci  *ptr++  = htonl(1);            /* GID = 1 (nogroup) */
1489beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
1490beacf11bSopenharmony_ci
1491beacf11bSopenharmony_ci  /* No size */
1492beacf11bSopenharmony_ci
1493beacf11bSopenharmony_ci  *ptr++  = nfs_false; /* False: No size value follows */
1494beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
1495beacf11bSopenharmony_ci
1496beacf11bSopenharmony_ci  /* Don't change times */
1497beacf11bSopenharmony_ci
1498beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */
1499beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */
1500beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
1501beacf11bSopenharmony_ci
1502beacf11bSopenharmony_ci  /* Perform the MKDIR RPC */
1503beacf11bSopenharmony_ci
1504beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_MKDIR);
1505beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_MKDIR,
1506beacf11bSopenharmony_ci      (void *)&nmp->nm_msgbuffer.mkdir, reqlen,
1507beacf11bSopenharmony_ci      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
1508beacf11bSopenharmony_ci  if (error)
1509beacf11bSopenharmony_ci    {
1510beacf11bSopenharmony_ci      nfs_debug_error("nfs_request failed: %d\n", error);
1511beacf11bSopenharmony_ci      goto errout_with_mutex;
1512beacf11bSopenharmony_ci    }
1513beacf11bSopenharmony_ci
1514beacf11bSopenharmony_ci  fhandle.length = parent_nfs_node->n_fhsize;
1515beacf11bSopenharmony_ci  memcpy_s(&(fhandle.handle), DIRENT_NFS_MAXHANDLE, &(parent_nfs_node->n_fhandle), fhandle.length);
1516beacf11bSopenharmony_ci  error = nfs_lookup(nmp, dirname, &fhandle, &obj_attributes, NULL);
1517beacf11bSopenharmony_ci  if (error)
1518beacf11bSopenharmony_ci    {
1519beacf11bSopenharmony_ci      error = ENOENT;
1520beacf11bSopenharmony_ci      goto errout_with_mutex;
1521beacf11bSopenharmony_ci    }
1522beacf11bSopenharmony_ci
1523beacf11bSopenharmony_ci  /* Initialize the file private data.
1524beacf11bSopenharmony_ci   *
1525beacf11bSopenharmony_ci   * Copy the file handle.
1526beacf11bSopenharmony_ci   */
1527beacf11bSopenharmony_ci  target_node = zalloc(sizeof(struct nfsnode));
1528beacf11bSopenharmony_ci  target_node->n_fhsize = (uint8_t)fhandle.length;
1529beacf11bSopenharmony_ci  memcpy_s(&(target_node->n_fhandle), target_node->n_fhsize, &(fhandle.handle), fhandle.length);
1530beacf11bSopenharmony_ci  target_node->n_pfhsize = parent_nfs_node->n_fhsize;
1531beacf11bSopenharmony_ci  (void)memcpy_s(&(target_node->n_pfhandle), NFSX_V3FHMAX, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize);
1532beacf11bSopenharmony_ci  target_node->n_name = zalloc(sizeof (dirname));
1533beacf11bSopenharmony_ci  memcpy_s(target_node->n_name, sizeof(dirname), dirname, sizeof (dirname));
1534beacf11bSopenharmony_ci  target_node->n_next = nmp->nm_head;
1535beacf11bSopenharmony_ci  nmp->nm_head = target_node;
1536beacf11bSopenharmony_ci
1537beacf11bSopenharmony_ci  /* Save the file attributes */
1538beacf11bSopenharmony_ci  nfs_attrupdate(target_node, &obj_attributes);
1539beacf11bSopenharmony_ci  (void)VnodeAlloc(&nfs_vops, vpp);
1540beacf11bSopenharmony_ci  (*vpp)->parent = parent;
1541beacf11bSopenharmony_ci  (*vpp)->fop = &nfs_fops;
1542beacf11bSopenharmony_ci  (*vpp)->originMount = parent->originMount;
1543beacf11bSopenharmony_ci  (*vpp)->data = target_node;
1544beacf11bSopenharmony_ci  (*vpp)->type = filetype_to_vnodetype(target_node->n_type);
1545beacf11bSopenharmony_ci  (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission);
1546beacf11bSopenharmony_ci  (*vpp)->gid = nmp->nm_gid;
1547beacf11bSopenharmony_ci  (*vpp)->uid = nmp->nm_uid;
1548beacf11bSopenharmony_ci
1549beacf11bSopenharmony_cierrout_with_mutex:
1550beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1551beacf11bSopenharmony_ci  return -error;
1552beacf11bSopenharmony_ci}
1553beacf11bSopenharmony_ci
1554beacf11bSopenharmony_ciint vfs_nfs_write(struct file *filep, const char *buffer, size_t buflen)
1555beacf11bSopenharmony_ci{
1556beacf11bSopenharmony_ci  struct nfsmount       *nmp;
1557beacf11bSopenharmony_ci  struct nfsnode        *np;
1558beacf11bSopenharmony_ci  loff_t                f_pos;
1559beacf11bSopenharmony_ci  size_t                writesize;
1560beacf11bSopenharmony_ci  size_t                bufsize;
1561beacf11bSopenharmony_ci  size_t                byteswritten;
1562beacf11bSopenharmony_ci  size_t                reqlen;
1563beacf11bSopenharmony_ci  uint32_t              *ptr = NULL;
1564beacf11bSopenharmony_ci  uint32_t              tmp;
1565beacf11bSopenharmony_ci  int                   committed = NFSV3WRITE_UNSTABLE;
1566beacf11bSopenharmony_ci  int                   error;
1567beacf11bSopenharmony_ci  char                  *temp_buffer = NULL;
1568beacf11bSopenharmony_ci  struct file_handle    parent_fhandle;
1569beacf11bSopenharmony_ci
1570beacf11bSopenharmony_ci  struct Vnode *node = filep->f_vnode;
1571beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(node->originMount->data);
1572beacf11bSopenharmony_ci  DEBUGASSERT(nmp != NULL);
1573beacf11bSopenharmony_ci
1574beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
1575beacf11bSopenharmony_ci
1576beacf11bSopenharmony_ci  nfs_mux_take(nmp);
1577beacf11bSopenharmony_ci  np  = (struct nfsnode *)node->data;
1578beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
1579beacf11bSopenharmony_ci  if (error != OK)
1580beacf11bSopenharmony_ci    {
1581beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
1582beacf11bSopenharmony_ci      goto errout_with_mutex;
1583beacf11bSopenharmony_ci    }
1584beacf11bSopenharmony_ci
1585beacf11bSopenharmony_ci  parent_fhandle.length = ((struct nfsnode *)node->data)->n_pfhsize;
1586beacf11bSopenharmony_ci  (void)memcpy_s(&(parent_fhandle.handle), NFSX_V3FHMAX,
1587beacf11bSopenharmony_ci      &(((struct nfsnode *)node->data)->n_pfhandle),
1588beacf11bSopenharmony_ci      ((struct nfsnode *)node->data)->n_pfhsize);
1589beacf11bSopenharmony_ci
1590beacf11bSopenharmony_ci  if (filep->f_oflags & O_APPEND)
1591beacf11bSopenharmony_ci    {
1592beacf11bSopenharmony_ci      if (nfs_fileupdate(nmp, np->n_name, &parent_fhandle, np) == OK)
1593beacf11bSopenharmony_ci        {
1594beacf11bSopenharmony_ci          f_pos = np->n_size;
1595beacf11bSopenharmony_ci        }
1596beacf11bSopenharmony_ci      else
1597beacf11bSopenharmony_ci        {
1598beacf11bSopenharmony_ci          error = EAGAIN;
1599beacf11bSopenharmony_ci          goto errout_with_mutex;
1600beacf11bSopenharmony_ci        }
1601beacf11bSopenharmony_ci    }
1602beacf11bSopenharmony_ci  else
1603beacf11bSopenharmony_ci    {
1604beacf11bSopenharmony_ci      f_pos = filep->f_pos;
1605beacf11bSopenharmony_ci    }
1606beacf11bSopenharmony_ci
1607beacf11bSopenharmony_ci  /* Check if the file size would exceed the range of off_t */
1608beacf11bSopenharmony_ci
1609beacf11bSopenharmony_ci  if (np->n_size + buflen < np->n_size)
1610beacf11bSopenharmony_ci    {
1611beacf11bSopenharmony_ci      error = EFBIG;
1612beacf11bSopenharmony_ci      goto errout_with_mutex;
1613beacf11bSopenharmony_ci    }
1614beacf11bSopenharmony_ci
1615beacf11bSopenharmony_ci  /* Allocate memory for data */
1616beacf11bSopenharmony_ci
1617beacf11bSopenharmony_ci  bufsize = (buflen < nmp->nm_wsize) ? buflen : nmp->nm_wsize;
1618beacf11bSopenharmony_ci  temp_buffer = malloc(bufsize);
1619beacf11bSopenharmony_ci  if (temp_buffer == NULL)
1620beacf11bSopenharmony_ci    {
1621beacf11bSopenharmony_ci      error = ENOMEM;
1622beacf11bSopenharmony_ci      goto errout_with_mutex;
1623beacf11bSopenharmony_ci    }
1624beacf11bSopenharmony_ci
1625beacf11bSopenharmony_ci  /* Now loop until we send the entire user buffer */
1626beacf11bSopenharmony_ci
1627beacf11bSopenharmony_ci  writesize = 0;
1628beacf11bSopenharmony_ci  for (byteswritten = 0; byteswritten < buflen; )
1629beacf11bSopenharmony_ci    {
1630beacf11bSopenharmony_ci      /* Make sure that the attempted write size does not exceed the RPC
1631beacf11bSopenharmony_ci       * maximum.
1632beacf11bSopenharmony_ci       */
1633beacf11bSopenharmony_ci
1634beacf11bSopenharmony_ci      writesize = buflen - byteswritten;
1635beacf11bSopenharmony_ci      if (writesize > nmp->nm_wsize)
1636beacf11bSopenharmony_ci        {
1637beacf11bSopenharmony_ci          writesize = nmp->nm_wsize;
1638beacf11bSopenharmony_ci        }
1639beacf11bSopenharmony_ci
1640beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the IO
1641beacf11bSopenharmony_ci       * buffer size.
1642beacf11bSopenharmony_ci       */
1643beacf11bSopenharmony_ci
1644beacf11bSopenharmony_ci      bufsize = SIZEOF_rpc_call_write(writesize);
1645beacf11bSopenharmony_ci      if (bufsize > nmp->nm_buflen)
1646beacf11bSopenharmony_ci        {
1647beacf11bSopenharmony_ci          writesize -= (bufsize - nmp->nm_buflen);
1648beacf11bSopenharmony_ci        }
1649beacf11bSopenharmony_ci
1650beacf11bSopenharmony_ci      /* Copy a chunk of the user data into the temporary buffer */
1651beacf11bSopenharmony_ci
1652beacf11bSopenharmony_ci      if (LOS_CopyToKernel(temp_buffer, writesize, buffer, writesize) != 0)
1653beacf11bSopenharmony_ci        {
1654beacf11bSopenharmony_ci          error = EINVAL;
1655beacf11bSopenharmony_ci          goto errout_with_memfree;
1656beacf11bSopenharmony_ci        }
1657beacf11bSopenharmony_ci
1658beacf11bSopenharmony_ci      /* Initialize the request.  Here we need an offset pointer to the write
1659beacf11bSopenharmony_ci       * arguments, skipping over the RPC header.  Write is unique among the
1660beacf11bSopenharmony_ci       * RPC calls in that the entry RPC calls messasge lies in the I/O buffer
1661beacf11bSopenharmony_ci       */
1662beacf11bSopenharmony_ci
1663beacf11bSopenharmony_ci      ptr     = (uint32_t *)&((struct rpc_call_write *)
1664beacf11bSopenharmony_ci          nmp->nm_iobuffer)->write;
1665beacf11bSopenharmony_ci      reqlen  = 0;
1666beacf11bSopenharmony_ci
1667beacf11bSopenharmony_ci      /* Copy the variable length, file handle */
1668beacf11bSopenharmony_ci
1669beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)np->n_fhsize);
1670beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
1671beacf11bSopenharmony_ci
1672beacf11bSopenharmony_ci      (void)memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize);
1673beacf11bSopenharmony_ci      reqlen += (int)np->n_fhsize;
1674beacf11bSopenharmony_ci      ptr    += uint32_increment((int)np->n_fhsize);
1675beacf11bSopenharmony_ci
1676beacf11bSopenharmony_ci      /* Copy the file offset */
1677beacf11bSopenharmony_ci
1678beacf11bSopenharmony_ci      txdr_hyper((uint64_t)f_pos, ptr);
1679beacf11bSopenharmony_ci      ptr    += 2;
1680beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
1681beacf11bSopenharmony_ci
1682beacf11bSopenharmony_ci      /* Copy the count and stable values */
1683beacf11bSopenharmony_ci
1684beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned(writesize);
1685beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)committed);
1686beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
1687beacf11bSopenharmony_ci
1688beacf11bSopenharmony_ci      /* Copy a chunk of the user data into the I/O buffer from temporary buffer */
1689beacf11bSopenharmony_ci
1690beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned(writesize);
1691beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
1692beacf11bSopenharmony_ci      error = memcpy_s(ptr, writesize, temp_buffer, writesize);
1693beacf11bSopenharmony_ci      if (error != EOK)
1694beacf11bSopenharmony_ci        {
1695beacf11bSopenharmony_ci          error = ENOBUFS;
1696beacf11bSopenharmony_ci          goto errout_with_memfree;
1697beacf11bSopenharmony_ci        }
1698beacf11bSopenharmony_ci      reqlen += uint32_alignup(writesize);
1699beacf11bSopenharmony_ci
1700beacf11bSopenharmony_ci      /* Perform the write */
1701beacf11bSopenharmony_ci
1702beacf11bSopenharmony_ci      nfs_statistics(NFSPROC_WRITE);
1703beacf11bSopenharmony_ci      error = nfs_request(nmp, NFSPROC_WRITE,
1704beacf11bSopenharmony_ci          (void *)nmp->nm_iobuffer, reqlen,
1705beacf11bSopenharmony_ci          (void *)&nmp->nm_msgbuffer.write,
1706beacf11bSopenharmony_ci          sizeof(struct rpc_reply_write));
1707beacf11bSopenharmony_ci      if (error)
1708beacf11bSopenharmony_ci        {
1709beacf11bSopenharmony_ci          goto errout_with_memfree;
1710beacf11bSopenharmony_ci        }
1711beacf11bSopenharmony_ci
1712beacf11bSopenharmony_ci      /* Get a pointer to the WRITE reply data */
1713beacf11bSopenharmony_ci
1714beacf11bSopenharmony_ci      ptr = (uint32_t *)&nmp->nm_msgbuffer.write.write;
1715beacf11bSopenharmony_ci
1716beacf11bSopenharmony_ci      /* Parse file_wcc.  First, check if WCC attributes follow. */
1717beacf11bSopenharmony_ci
1718beacf11bSopenharmony_ci      tmp = *ptr++;
1719beacf11bSopenharmony_ci      if (tmp != 0)
1720beacf11bSopenharmony_ci        {
1721beacf11bSopenharmony_ci          /* Yes.. WCC attributes follow.  But we just skip over them. */
1722beacf11bSopenharmony_ci
1723beacf11bSopenharmony_ci          ptr += uint32_increment(sizeof(struct wcc_attr));
1724beacf11bSopenharmony_ci        }
1725beacf11bSopenharmony_ci
1726beacf11bSopenharmony_ci      /* Check if normal file attributes follow */
1727beacf11bSopenharmony_ci
1728beacf11bSopenharmony_ci      tmp = *ptr++;
1729beacf11bSopenharmony_ci      if (tmp != 0)
1730beacf11bSopenharmony_ci        {
1731beacf11bSopenharmony_ci          /* Yes.. Update the cached file status in the file structure. */
1732beacf11bSopenharmony_ci
1733beacf11bSopenharmony_ci          nfs_attrupdate(np, (struct nfs_fattr *)ptr);
1734beacf11bSopenharmony_ci          ptr += uint32_increment(sizeof(struct nfs_fattr));
1735beacf11bSopenharmony_ci        }
1736beacf11bSopenharmony_ci
1737beacf11bSopenharmony_ci      /* Get the count of bytes actually written */
1738beacf11bSopenharmony_ci
1739beacf11bSopenharmony_ci      tmp = fxdr_unsigned(uint32_t, *ptr);
1740beacf11bSopenharmony_ci      ptr++;
1741beacf11bSopenharmony_ci
1742beacf11bSopenharmony_ci      if (tmp < 1 || tmp > writesize)
1743beacf11bSopenharmony_ci        {
1744beacf11bSopenharmony_ci          error = EIO;
1745beacf11bSopenharmony_ci          goto errout_with_memfree;
1746beacf11bSopenharmony_ci        }
1747beacf11bSopenharmony_ci
1748beacf11bSopenharmony_ci      writesize = tmp;
1749beacf11bSopenharmony_ci      f_pos += writesize;
1750beacf11bSopenharmony_ci      filep->f_pos = f_pos;
1751beacf11bSopenharmony_ci      np->n_fpos = f_pos;
1752beacf11bSopenharmony_ci
1753beacf11bSopenharmony_ci      /* Update the read state data */
1754beacf11bSopenharmony_ci
1755beacf11bSopenharmony_ci      if (filep->f_pos > (loff_t)np->n_size)
1756beacf11bSopenharmony_ci        {
1757beacf11bSopenharmony_ci          np->n_size = f_pos;
1758beacf11bSopenharmony_ci        }
1759beacf11bSopenharmony_ci      byteswritten += writesize;
1760beacf11bSopenharmony_ci      buffer       += writesize;
1761beacf11bSopenharmony_ci  }
1762beacf11bSopenharmony_ci
1763beacf11bSopenharmony_ci  free(temp_buffer);
1764beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1765beacf11bSopenharmony_ci  return byteswritten;
1766beacf11bSopenharmony_cierrout_with_memfree:
1767beacf11bSopenharmony_ci  free(temp_buffer);
1768beacf11bSopenharmony_cierrout_with_mutex:
1769beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1770beacf11bSopenharmony_ci  return -error;
1771beacf11bSopenharmony_ci}
1772beacf11bSopenharmony_ci
1773beacf11bSopenharmony_cissize_t vfs_nfs_writepage(struct Vnode *node, char *buffer, off_t pos, size_t buflen)
1774beacf11bSopenharmony_ci{
1775beacf11bSopenharmony_ci  struct nfsmount       *nmp;
1776beacf11bSopenharmony_ci  struct nfsnode        *np;
1777beacf11bSopenharmony_ci  loff_t                f_pos = pos;
1778beacf11bSopenharmony_ci  size_t                writesize;
1779beacf11bSopenharmony_ci  size_t                bufsize;
1780beacf11bSopenharmony_ci  size_t                byteswritten;
1781beacf11bSopenharmony_ci  size_t                reqlen;
1782beacf11bSopenharmony_ci  uint32_t              *ptr = NULL;
1783beacf11bSopenharmony_ci  uint32_t              tmp;
1784beacf11bSopenharmony_ci  int                   committed = NFSV3WRITE_UNSTABLE;
1785beacf11bSopenharmony_ci  int                   error;
1786beacf11bSopenharmony_ci  char                  *temp_buffer = NULL;
1787beacf11bSopenharmony_ci  struct file_handle    parent_fhandle;
1788beacf11bSopenharmony_ci
1789beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(node->originMount->data);
1790beacf11bSopenharmony_ci  DEBUGASSERT(nmp != NULL);
1791beacf11bSopenharmony_ci
1792beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
1793beacf11bSopenharmony_ci
1794beacf11bSopenharmony_ci  nfs_mux_take(nmp);
1795beacf11bSopenharmony_ci  np  = (struct nfsnode *)node->data;
1796beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
1797beacf11bSopenharmony_ci  if (error != OK)
1798beacf11bSopenharmony_ci    {
1799beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
1800beacf11bSopenharmony_ci      goto errout_with_mutex;
1801beacf11bSopenharmony_ci    }
1802beacf11bSopenharmony_ci
1803beacf11bSopenharmony_ci  parent_fhandle.length = ((struct nfsnode *)node->data)->n_pfhsize;
1804beacf11bSopenharmony_ci  (void)memcpy_s(&(parent_fhandle.handle), NFSX_V3FHMAX,
1805beacf11bSopenharmony_ci      &(((struct nfsnode *)node->data)->n_pfhandle),
1806beacf11bSopenharmony_ci      ((struct nfsnode *)node->data)->n_pfhsize);
1807beacf11bSopenharmony_ci
1808beacf11bSopenharmony_ci  /* Check if the file size would exceed the range of off_t */
1809beacf11bSopenharmony_ci
1810beacf11bSopenharmony_ci  if (np->n_size + buflen < np->n_size)
1811beacf11bSopenharmony_ci    {
1812beacf11bSopenharmony_ci      error = EFBIG;
1813beacf11bSopenharmony_ci      goto errout_with_mutex;
1814beacf11bSopenharmony_ci    }
1815beacf11bSopenharmony_ci
1816beacf11bSopenharmony_ci  /* writepage cannot exceed the file range */
1817beacf11bSopenharmony_ci
1818beacf11bSopenharmony_ci  if (f_pos >= np->n_size)
1819beacf11bSopenharmony_ci    {
1820beacf11bSopenharmony_ci      error = ERANGE;
1821beacf11bSopenharmony_ci      goto errout_with_mutex;
1822beacf11bSopenharmony_ci    }
1823beacf11bSopenharmony_ci
1824beacf11bSopenharmony_ci  buflen = min(buflen, np->n_size - f_pos);
1825beacf11bSopenharmony_ci
1826beacf11bSopenharmony_ci  /* Allocate memory for data */
1827beacf11bSopenharmony_ci
1828beacf11bSopenharmony_ci  bufsize = (buflen < nmp->nm_wsize) ? buflen : nmp->nm_wsize;
1829beacf11bSopenharmony_ci  temp_buffer = malloc(bufsize);
1830beacf11bSopenharmony_ci  if (temp_buffer == NULL)
1831beacf11bSopenharmony_ci    {
1832beacf11bSopenharmony_ci      error = ENOMEM;
1833beacf11bSopenharmony_ci      goto errout_with_mutex;
1834beacf11bSopenharmony_ci    }
1835beacf11bSopenharmony_ci
1836beacf11bSopenharmony_ci  /* Now loop until we send the entire user buffer */
1837beacf11bSopenharmony_ci
1838beacf11bSopenharmony_ci  writesize = 0;
1839beacf11bSopenharmony_ci  for (byteswritten = 0; byteswritten < buflen; )
1840beacf11bSopenharmony_ci    {
1841beacf11bSopenharmony_ci      /* Make sure that the attempted write size does not exceed the RPC
1842beacf11bSopenharmony_ci       * maximum.
1843beacf11bSopenharmony_ci       */
1844beacf11bSopenharmony_ci
1845beacf11bSopenharmony_ci      writesize = buflen - byteswritten;
1846beacf11bSopenharmony_ci      if (writesize > nmp->nm_wsize)
1847beacf11bSopenharmony_ci        {
1848beacf11bSopenharmony_ci          writesize = nmp->nm_wsize;
1849beacf11bSopenharmony_ci        }
1850beacf11bSopenharmony_ci
1851beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the IO
1852beacf11bSopenharmony_ci       * buffer size.
1853beacf11bSopenharmony_ci       */
1854beacf11bSopenharmony_ci
1855beacf11bSopenharmony_ci      bufsize = SIZEOF_rpc_call_write(writesize);
1856beacf11bSopenharmony_ci      if (bufsize > nmp->nm_buflen)
1857beacf11bSopenharmony_ci        {
1858beacf11bSopenharmony_ci          writesize -= (bufsize - nmp->nm_buflen);
1859beacf11bSopenharmony_ci        }
1860beacf11bSopenharmony_ci
1861beacf11bSopenharmony_ci      /* Copy a chunk of the user data into the temporary buffer */
1862beacf11bSopenharmony_ci
1863beacf11bSopenharmony_ci      if (LOS_CopyToKernel(temp_buffer, writesize, buffer, writesize) != 0)
1864beacf11bSopenharmony_ci        {
1865beacf11bSopenharmony_ci          error = EINVAL;
1866beacf11bSopenharmony_ci          goto errout_with_memfree;
1867beacf11bSopenharmony_ci        }
1868beacf11bSopenharmony_ci
1869beacf11bSopenharmony_ci      /* Initialize the request.  Here we need an offset pointer to the write
1870beacf11bSopenharmony_ci       * arguments, skipping over the RPC header.  Write is unique among the
1871beacf11bSopenharmony_ci       * RPC calls in that the entry RPC calls messasge lies in the I/O buffer
1872beacf11bSopenharmony_ci       */
1873beacf11bSopenharmony_ci
1874beacf11bSopenharmony_ci      ptr     = (uint32_t *)&((struct rpc_call_write *)
1875beacf11bSopenharmony_ci          nmp->nm_iobuffer)->write;
1876beacf11bSopenharmony_ci      reqlen  = 0;
1877beacf11bSopenharmony_ci
1878beacf11bSopenharmony_ci      /* Copy the variable length, file handle */
1879beacf11bSopenharmony_ci
1880beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)np->n_fhsize);
1881beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
1882beacf11bSopenharmony_ci
1883beacf11bSopenharmony_ci      (void)memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize);
1884beacf11bSopenharmony_ci      reqlen += (int)np->n_fhsize;
1885beacf11bSopenharmony_ci      ptr    += uint32_increment((int)np->n_fhsize);
1886beacf11bSopenharmony_ci
1887beacf11bSopenharmony_ci      /* Copy the file offset */
1888beacf11bSopenharmony_ci
1889beacf11bSopenharmony_ci      txdr_hyper((uint64_t)f_pos, ptr);
1890beacf11bSopenharmony_ci      ptr    += 2;
1891beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
1892beacf11bSopenharmony_ci
1893beacf11bSopenharmony_ci      /* Copy the count and stable values */
1894beacf11bSopenharmony_ci
1895beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned(writesize);
1896beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)committed);
1897beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
1898beacf11bSopenharmony_ci
1899beacf11bSopenharmony_ci      /* Copy a chunk of the user data into the I/O buffer from temporary buffer */
1900beacf11bSopenharmony_ci
1901beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned(writesize);
1902beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
1903beacf11bSopenharmony_ci      error = memcpy_s(ptr, writesize, temp_buffer, writesize);
1904beacf11bSopenharmony_ci      if (error != EOK)
1905beacf11bSopenharmony_ci        {
1906beacf11bSopenharmony_ci          error = ENOBUFS;
1907beacf11bSopenharmony_ci          goto errout_with_memfree;
1908beacf11bSopenharmony_ci        }
1909beacf11bSopenharmony_ci      reqlen += uint32_alignup(writesize);
1910beacf11bSopenharmony_ci
1911beacf11bSopenharmony_ci      /* Perform the write */
1912beacf11bSopenharmony_ci
1913beacf11bSopenharmony_ci      nfs_statistics(NFSPROC_WRITE);
1914beacf11bSopenharmony_ci      error = nfs_request(nmp, NFSPROC_WRITE,
1915beacf11bSopenharmony_ci          (void *)nmp->nm_iobuffer, reqlen,
1916beacf11bSopenharmony_ci          (void *)&nmp->nm_msgbuffer.write,
1917beacf11bSopenharmony_ci          sizeof(struct rpc_reply_write));
1918beacf11bSopenharmony_ci      if (error)
1919beacf11bSopenharmony_ci        {
1920beacf11bSopenharmony_ci          goto errout_with_memfree;
1921beacf11bSopenharmony_ci        }
1922beacf11bSopenharmony_ci
1923beacf11bSopenharmony_ci      /* Get a pointer to the WRITE reply data */
1924beacf11bSopenharmony_ci
1925beacf11bSopenharmony_ci      ptr = (uint32_t *)&nmp->nm_msgbuffer.write.write;
1926beacf11bSopenharmony_ci
1927beacf11bSopenharmony_ci      /* Parse file_wcc.  First, check if WCC attributes follow. */
1928beacf11bSopenharmony_ci
1929beacf11bSopenharmony_ci      tmp = *ptr++;
1930beacf11bSopenharmony_ci      if (tmp != 0)
1931beacf11bSopenharmony_ci        {
1932beacf11bSopenharmony_ci          /* Yes.. WCC attributes follow.  But we just skip over them. */
1933beacf11bSopenharmony_ci
1934beacf11bSopenharmony_ci          ptr += uint32_increment(sizeof(struct wcc_attr));
1935beacf11bSopenharmony_ci        }
1936beacf11bSopenharmony_ci
1937beacf11bSopenharmony_ci      /* Check if normal file attributes follow */
1938beacf11bSopenharmony_ci
1939beacf11bSopenharmony_ci      tmp = *ptr++;
1940beacf11bSopenharmony_ci      if (tmp != 0)
1941beacf11bSopenharmony_ci        {
1942beacf11bSopenharmony_ci          /* Yes.. Update the cached file status in the file structure. */
1943beacf11bSopenharmony_ci
1944beacf11bSopenharmony_ci          nfs_attrupdate(np, (struct nfs_fattr *)ptr);
1945beacf11bSopenharmony_ci          ptr += uint32_increment(sizeof(struct nfs_fattr));
1946beacf11bSopenharmony_ci        }
1947beacf11bSopenharmony_ci
1948beacf11bSopenharmony_ci      /* Get the count of bytes actually written */
1949beacf11bSopenharmony_ci
1950beacf11bSopenharmony_ci      tmp = fxdr_unsigned(uint32_t, *ptr);
1951beacf11bSopenharmony_ci      ptr++;
1952beacf11bSopenharmony_ci
1953beacf11bSopenharmony_ci      if (tmp < 1 || tmp > writesize)
1954beacf11bSopenharmony_ci        {
1955beacf11bSopenharmony_ci          error = EIO;
1956beacf11bSopenharmony_ci          goto errout_with_memfree;
1957beacf11bSopenharmony_ci        }
1958beacf11bSopenharmony_ci
1959beacf11bSopenharmony_ci      writesize = tmp;
1960beacf11bSopenharmony_ci      f_pos += writesize;
1961beacf11bSopenharmony_ci      np->n_fpos = f_pos;
1962beacf11bSopenharmony_ci
1963beacf11bSopenharmony_ci      byteswritten += writesize;
1964beacf11bSopenharmony_ci      buffer       += writesize;
1965beacf11bSopenharmony_ci  }
1966beacf11bSopenharmony_ci
1967beacf11bSopenharmony_ci  free(temp_buffer);
1968beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1969beacf11bSopenharmony_ci  return byteswritten;
1970beacf11bSopenharmony_cierrout_with_memfree:
1971beacf11bSopenharmony_ci  free(temp_buffer);
1972beacf11bSopenharmony_cierrout_with_mutex:
1973beacf11bSopenharmony_ci  nfs_mux_release(nmp);
1974beacf11bSopenharmony_ci  return -error;
1975beacf11bSopenharmony_ci}
1976beacf11bSopenharmony_ci
1977beacf11bSopenharmony_cioff_t vfs_nfs_seek(struct file *filep, off_t offset, int whence)
1978beacf11bSopenharmony_ci{
1979beacf11bSopenharmony_ci  struct Vnode *node = filep->f_vnode;
1980beacf11bSopenharmony_ci  struct nfsnode  *np = NULL;
1981beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
1982beacf11bSopenharmony_ci  int                        error;
1983beacf11bSopenharmony_ci  off_t                      position;
1984beacf11bSopenharmony_ci
1985beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
1986beacf11bSopenharmony_ci
1987beacf11bSopenharmony_ci  nfs_mux_take(nmp);
1988beacf11bSopenharmony_ci  np = (struct nfsnode *)node->data;
1989beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
1990beacf11bSopenharmony_ci  if (error != OK)
1991beacf11bSopenharmony_ci    {
1992beacf11bSopenharmony_ci      nfs_debug_info("nfs_checkmount failed: %d\n", error);
1993beacf11bSopenharmony_ci      goto errout_with_mutex;
1994beacf11bSopenharmony_ci    }
1995beacf11bSopenharmony_ci
1996beacf11bSopenharmony_ci
1997beacf11bSopenharmony_ci  switch (whence)
1998beacf11bSopenharmony_ci    {
1999beacf11bSopenharmony_ci    case SEEK_SET: /* The offset is set to offset bytes. */
2000beacf11bSopenharmony_ci      position = offset;
2001beacf11bSopenharmony_ci      break;
2002beacf11bSopenharmony_ci
2003beacf11bSopenharmony_ci    case SEEK_CUR: /* The offset is set to its current location plus offset bytes. */
2004beacf11bSopenharmony_ci      position = offset + filep->f_pos;
2005beacf11bSopenharmony_ci      break;
2006beacf11bSopenharmony_ci
2007beacf11bSopenharmony_ci    case SEEK_END: /* The offset is set to the size of the file plus offset bytes. */
2008beacf11bSopenharmony_ci      position = offset + np->n_size;
2009beacf11bSopenharmony_ci      break;
2010beacf11bSopenharmony_ci
2011beacf11bSopenharmony_ci    default:
2012beacf11bSopenharmony_ci      error = EINVAL;
2013beacf11bSopenharmony_ci      goto errout_with_mutex;
2014beacf11bSopenharmony_ci    }
2015beacf11bSopenharmony_ci
2016beacf11bSopenharmony_ci  /* Attempts to set the position beyound the end of file will
2017beacf11bSopenharmony_ci   * work if the file is open for write access.
2018beacf11bSopenharmony_ci   */
2019beacf11bSopenharmony_ci
2020beacf11bSopenharmony_ci  if ((position > (off_t)np->n_size) && ((np->n_oflags & O_WRONLY) == 0) &&
2021beacf11bSopenharmony_ci      ((np->n_oflags & O_RDWR) == 0))
2022beacf11bSopenharmony_ci  {
2023beacf11bSopenharmony_ci      position = np->n_size;
2024beacf11bSopenharmony_ci  }
2025beacf11bSopenharmony_ci
2026beacf11bSopenharmony_ci  /* position less than 0 should be reset to 0 */
2027beacf11bSopenharmony_ci
2028beacf11bSopenharmony_ci  if (position < 0)
2029beacf11bSopenharmony_ci  {
2030beacf11bSopenharmony_ci      position = 0;
2031beacf11bSopenharmony_ci  }
2032beacf11bSopenharmony_ci
2033beacf11bSopenharmony_ci  np->n_fpos = (loff_t)position;
2034beacf11bSopenharmony_ci  filep->f_pos = np->n_fpos;
2035beacf11bSopenharmony_ci  if (position > (off_t)np->n_size)
2036beacf11bSopenharmony_ci  {
2037beacf11bSopenharmony_ci      np->n_size = (loff_t)position;
2038beacf11bSopenharmony_ci  }
2039beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2040beacf11bSopenharmony_ci  return (off_t)filep->f_pos;
2041beacf11bSopenharmony_ci
2042beacf11bSopenharmony_cierrout_with_mutex:
2043beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2044beacf11bSopenharmony_ci  return -error;
2045beacf11bSopenharmony_ci}
2046beacf11bSopenharmony_ci
2047beacf11bSopenharmony_cissize_t vfs_nfs_readpage(struct Vnode *node, char *buffer, off_t pos)
2048beacf11bSopenharmony_ci{
2049beacf11bSopenharmony_ci  struct nfsnode            *np;
2050beacf11bSopenharmony_ci  struct rpc_reply_read     *read_response = NULL;
2051beacf11bSopenharmony_ci  size_t                     readsize;
2052beacf11bSopenharmony_ci  size_t                     tmp;
2053beacf11bSopenharmony_ci  size_t                     bytesread;
2054beacf11bSopenharmony_ci  size_t                     reqlen;
2055beacf11bSopenharmony_ci  uint32_t                  *ptr = NULL;
2056beacf11bSopenharmony_ci  int                        error = 0;
2057beacf11bSopenharmony_ci  struct file_handle         parent_fhandle;
2058beacf11bSopenharmony_ci  int                        buflen = PAGE_SIZE;
2059beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
2060beacf11bSopenharmony_ci
2061beacf11bSopenharmony_ci  DEBUGASSERT(nmp != NULL);
2062beacf11bSopenharmony_ci
2063beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
2064beacf11bSopenharmony_ci
2065beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2066beacf11bSopenharmony_ci  np  = (struct nfsnode *)node->data;
2067beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2068beacf11bSopenharmony_ci  if (error != OK)
2069beacf11bSopenharmony_ci    {
2070beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2071beacf11bSopenharmony_ci      goto errout_with_mutex;
2072beacf11bSopenharmony_ci    }
2073beacf11bSopenharmony_ci
2074beacf11bSopenharmony_ci
2075beacf11bSopenharmony_ci  parent_fhandle.length = ((struct nfsnode *)node->data)->n_pfhsize;
2076beacf11bSopenharmony_ci  (void)memcpy_s(&(parent_fhandle.handle), NFSX_V3FHMAX,
2077beacf11bSopenharmony_ci      &(((struct nfsnode *)node->data)->n_pfhandle),
2078beacf11bSopenharmony_ci      ((struct nfsnode *)node->data)->n_pfhsize);
2079beacf11bSopenharmony_ci  error = nfs_fileupdate(nmp, np->n_name, &parent_fhandle, np);
2080beacf11bSopenharmony_ci  if (error != OK)
2081beacf11bSopenharmony_ci    {
2082beacf11bSopenharmony_ci      nfs_debug_info("nfs_fileupdate failed: %d\n", error);
2083beacf11bSopenharmony_ci      goto errout_with_mutex;
2084beacf11bSopenharmony_ci    }
2085beacf11bSopenharmony_ci
2086beacf11bSopenharmony_ci  /* Get the number of bytes left in the file and truncate read count so that
2087beacf11bSopenharmony_ci   * it does not exceed the number of bytes left in the file.
2088beacf11bSopenharmony_ci   */
2089beacf11bSopenharmony_ci
2090beacf11bSopenharmony_ci  if (pos >= np->n_size) {
2091beacf11bSopenharmony_ci      error = EFAULT;
2092beacf11bSopenharmony_ci      nfs_debug_info("readpage out of file range: %d\n", error);
2093beacf11bSopenharmony_ci      goto errout_with_mutex;
2094beacf11bSopenharmony_ci  }
2095beacf11bSopenharmony_ci
2096beacf11bSopenharmony_ci  tmp = np->n_size - pos;
2097beacf11bSopenharmony_ci  if (buflen > tmp)
2098beacf11bSopenharmony_ci    {
2099beacf11bSopenharmony_ci      buflen = tmp;
2100beacf11bSopenharmony_ci    }
2101beacf11bSopenharmony_ci
2102beacf11bSopenharmony_ci  /* Now loop until we fill the user buffer (or hit the end of the file) */
2103beacf11bSopenharmony_ci
2104beacf11bSopenharmony_ci  for (bytesread = 0; bytesread < buflen; )
2105beacf11bSopenharmony_ci    {
2106beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the RPC maximum */
2107beacf11bSopenharmony_ci
2108beacf11bSopenharmony_ci      readsize = buflen - bytesread;
2109beacf11bSopenharmony_ci      if (readsize > nmp->nm_rsize)
2110beacf11bSopenharmony_ci        {
2111beacf11bSopenharmony_ci          readsize = nmp->nm_rsize;
2112beacf11bSopenharmony_ci        }
2113beacf11bSopenharmony_ci
2114beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the IO buffer size */
2115beacf11bSopenharmony_ci
2116beacf11bSopenharmony_ci      tmp = SIZEOF_rpc_reply_read(readsize);
2117beacf11bSopenharmony_ci      if (tmp > nmp->nm_buflen)
2118beacf11bSopenharmony_ci        {
2119beacf11bSopenharmony_ci          readsize -= (tmp - nmp->nm_buflen);
2120beacf11bSopenharmony_ci        }
2121beacf11bSopenharmony_ci
2122beacf11bSopenharmony_ci      /* Initialize the request */
2123beacf11bSopenharmony_ci
2124beacf11bSopenharmony_ci      ptr     = (uint32_t *)&nmp->nm_msgbuffer.read.read;
2125beacf11bSopenharmony_ci      reqlen  = 0;
2126beacf11bSopenharmony_ci
2127beacf11bSopenharmony_ci      /* Copy the variable length, file handle */
2128beacf11bSopenharmony_ci
2129beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)np->n_fhsize);
2130beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
2131beacf11bSopenharmony_ci
2132beacf11bSopenharmony_ci      memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize);
2133beacf11bSopenharmony_ci      reqlen += (int)np->n_fhsize;
2134beacf11bSopenharmony_ci      ptr    += uint32_increment((int)np->n_fhsize);
2135beacf11bSopenharmony_ci
2136beacf11bSopenharmony_ci      /* Copy the file offset */
2137beacf11bSopenharmony_ci
2138beacf11bSopenharmony_ci      txdr_hyper((uint64_t)pos, ptr);
2139beacf11bSopenharmony_ci      ptr += 2;
2140beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
2141beacf11bSopenharmony_ci
2142beacf11bSopenharmony_ci      /* Set the readsize */
2143beacf11bSopenharmony_ci
2144beacf11bSopenharmony_ci      *ptr = txdr_unsigned(readsize);
2145beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
2146beacf11bSopenharmony_ci
2147beacf11bSopenharmony_ci      /* Perform the read */
2148beacf11bSopenharmony_ci
2149beacf11bSopenharmony_ci      nfs_statistics(NFSPROC_READ);
2150beacf11bSopenharmony_ci      error = nfs_request(nmp, NFSPROC_READ,
2151beacf11bSopenharmony_ci          (void *)&nmp->nm_msgbuffer.read, reqlen,
2152beacf11bSopenharmony_ci          (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2153beacf11bSopenharmony_ci      if (error)
2154beacf11bSopenharmony_ci        {
2155beacf11bSopenharmony_ci          nfs_debug_error("nfs_request failed: %d\n", error);
2156beacf11bSopenharmony_ci          goto errout_with_mutex;
2157beacf11bSopenharmony_ci        }
2158beacf11bSopenharmony_ci
2159beacf11bSopenharmony_ci      /* The read was successful.  Get a pointer to the beginning of the NFS
2160beacf11bSopenharmony_ci       * response data.
2161beacf11bSopenharmony_ci       */
2162beacf11bSopenharmony_ci
2163beacf11bSopenharmony_ci      read_response = (struct rpc_reply_read *)nmp->nm_iobuffer;
2164beacf11bSopenharmony_ci      readsize = fxdr_unsigned(uint32_t, read_response->read.hdr.count);
2165beacf11bSopenharmony_ci
2166beacf11bSopenharmony_ci      /* Copy the read data into the user buffer */
2167beacf11bSopenharmony_ci
2168beacf11bSopenharmony_ci      if (LOS_CopyFromKernel(buffer, buflen, (const void *)read_response->read.data, readsize) != 0)
2169beacf11bSopenharmony_ci        {
2170beacf11bSopenharmony_ci          error = EINVAL;
2171beacf11bSopenharmony_ci          goto errout_with_mutex;
2172beacf11bSopenharmony_ci        }
2173beacf11bSopenharmony_ci
2174beacf11bSopenharmony_ci      /* Update the read state data */
2175beacf11bSopenharmony_ci
2176beacf11bSopenharmony_ci      pos          += readsize;
2177beacf11bSopenharmony_ci      np->n_fpos   += readsize;
2178beacf11bSopenharmony_ci      bytesread    += readsize;
2179beacf11bSopenharmony_ci      buffer       += readsize;
2180beacf11bSopenharmony_ci
2181beacf11bSopenharmony_ci      /* Check if we hit the end of file */
2182beacf11bSopenharmony_ci
2183beacf11bSopenharmony_ci      if (read_response->read.hdr.eof != 0)
2184beacf11bSopenharmony_ci        {
2185beacf11bSopenharmony_ci          break;
2186beacf11bSopenharmony_ci        }
2187beacf11bSopenharmony_ci    }
2188beacf11bSopenharmony_ci
2189beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2190beacf11bSopenharmony_ci  return bytesread;
2191beacf11bSopenharmony_ci
2192beacf11bSopenharmony_cierrout_with_mutex:
2193beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2194beacf11bSopenharmony_ci  return -error;
2195beacf11bSopenharmony_ci}
2196beacf11bSopenharmony_ci
2197beacf11bSopenharmony_cissize_t vfs_nfs_read(struct file *filep, char *buffer, size_t buflen)
2198beacf11bSopenharmony_ci{
2199beacf11bSopenharmony_ci  struct nfsnode            *np;
2200beacf11bSopenharmony_ci  struct rpc_reply_read     *read_response = NULL;
2201beacf11bSopenharmony_ci  size_t                     readsize;
2202beacf11bSopenharmony_ci  size_t                     tmp;
2203beacf11bSopenharmony_ci  size_t                     bytesread;
2204beacf11bSopenharmony_ci  size_t                     reqlen;
2205beacf11bSopenharmony_ci  uint32_t                  *ptr = NULL;
2206beacf11bSopenharmony_ci  int                        error = 0;
2207beacf11bSopenharmony_ci  struct file_handle         parent_fhandle;
2208beacf11bSopenharmony_ci
2209beacf11bSopenharmony_ci  struct Vnode *node = filep->f_vnode;
2210beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
2211beacf11bSopenharmony_ci
2212beacf11bSopenharmony_ci  DEBUGASSERT(nmp != NULL);
2213beacf11bSopenharmony_ci
2214beacf11bSopenharmony_ci  /* Make sure that the mount is still healthy */
2215beacf11bSopenharmony_ci
2216beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2217beacf11bSopenharmony_ci  np  = (struct nfsnode *)node->data;
2218beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2219beacf11bSopenharmony_ci  if (error != OK)
2220beacf11bSopenharmony_ci    {
2221beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2222beacf11bSopenharmony_ci      goto errout_with_mutex;
2223beacf11bSopenharmony_ci    }
2224beacf11bSopenharmony_ci
2225beacf11bSopenharmony_ci
2226beacf11bSopenharmony_ci  parent_fhandle.length = ((struct nfsnode *)node->data)->n_pfhsize;
2227beacf11bSopenharmony_ci  (void)memcpy_s(&(parent_fhandle.handle), NFSX_V3FHMAX,
2228beacf11bSopenharmony_ci      &(((struct nfsnode *)node->data)->n_pfhandle),
2229beacf11bSopenharmony_ci      ((struct nfsnode *)node->data)->n_pfhsize);
2230beacf11bSopenharmony_ci  error = nfs_fileupdate(nmp, np->n_name, &parent_fhandle, np);
2231beacf11bSopenharmony_ci  if (error != OK)
2232beacf11bSopenharmony_ci    {
2233beacf11bSopenharmony_ci      nfs_debug_info("nfs_fileupdate failed: %d\n", error);
2234beacf11bSopenharmony_ci      goto errout_with_mutex;
2235beacf11bSopenharmony_ci    }
2236beacf11bSopenharmony_ci
2237beacf11bSopenharmony_ci  /* Get the number of bytes left in the file and truncate read count so that
2238beacf11bSopenharmony_ci   * it does not exceed the number of bytes left in the file.
2239beacf11bSopenharmony_ci   */
2240beacf11bSopenharmony_ci
2241beacf11bSopenharmony_ci  tmp = np->n_size - filep->f_pos;
2242beacf11bSopenharmony_ci  if (buflen > tmp)
2243beacf11bSopenharmony_ci    {
2244beacf11bSopenharmony_ci      buflen = tmp;
2245beacf11bSopenharmony_ci    }
2246beacf11bSopenharmony_ci
2247beacf11bSopenharmony_ci  /* Now loop until we fill the user buffer (or hit the end of the file) */
2248beacf11bSopenharmony_ci
2249beacf11bSopenharmony_ci  for (bytesread = 0; bytesread < buflen; )
2250beacf11bSopenharmony_ci    {
2251beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the RPC maximum */
2252beacf11bSopenharmony_ci
2253beacf11bSopenharmony_ci      readsize = buflen - bytesread;
2254beacf11bSopenharmony_ci      if (readsize > nmp->nm_rsize)
2255beacf11bSopenharmony_ci        {
2256beacf11bSopenharmony_ci          readsize = nmp->nm_rsize;
2257beacf11bSopenharmony_ci        }
2258beacf11bSopenharmony_ci
2259beacf11bSopenharmony_ci      /* Make sure that the attempted read size does not exceed the IO buffer size */
2260beacf11bSopenharmony_ci
2261beacf11bSopenharmony_ci      tmp = SIZEOF_rpc_reply_read(readsize);
2262beacf11bSopenharmony_ci      if (tmp > nmp->nm_buflen)
2263beacf11bSopenharmony_ci        {
2264beacf11bSopenharmony_ci          readsize -= (tmp - nmp->nm_buflen);
2265beacf11bSopenharmony_ci        }
2266beacf11bSopenharmony_ci
2267beacf11bSopenharmony_ci      /* Initialize the request */
2268beacf11bSopenharmony_ci
2269beacf11bSopenharmony_ci      ptr     = (uint32_t *)&nmp->nm_msgbuffer.read.read;
2270beacf11bSopenharmony_ci      reqlen  = 0;
2271beacf11bSopenharmony_ci
2272beacf11bSopenharmony_ci      /* Copy the variable length, file handle */
2273beacf11bSopenharmony_ci
2274beacf11bSopenharmony_ci      *ptr++  = txdr_unsigned((uint32_t)np->n_fhsize);
2275beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
2276beacf11bSopenharmony_ci
2277beacf11bSopenharmony_ci      memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize);
2278beacf11bSopenharmony_ci      reqlen += (int)np->n_fhsize;
2279beacf11bSopenharmony_ci      ptr    += uint32_increment((int)np->n_fhsize);
2280beacf11bSopenharmony_ci
2281beacf11bSopenharmony_ci      /* Copy the file offset */
2282beacf11bSopenharmony_ci
2283beacf11bSopenharmony_ci      txdr_hyper((uint64_t)filep->f_pos, ptr);
2284beacf11bSopenharmony_ci      ptr += 2;
2285beacf11bSopenharmony_ci      reqlen += 2*sizeof(uint32_t);
2286beacf11bSopenharmony_ci
2287beacf11bSopenharmony_ci      /* Set the readsize */
2288beacf11bSopenharmony_ci
2289beacf11bSopenharmony_ci      *ptr = txdr_unsigned(readsize);
2290beacf11bSopenharmony_ci      reqlen += sizeof(uint32_t);
2291beacf11bSopenharmony_ci
2292beacf11bSopenharmony_ci      /* Perform the read */
2293beacf11bSopenharmony_ci
2294beacf11bSopenharmony_ci      nfs_statistics(NFSPROC_READ);
2295beacf11bSopenharmony_ci      error = nfs_request(nmp, NFSPROC_READ,
2296beacf11bSopenharmony_ci          (void *)&nmp->nm_msgbuffer.read, reqlen,
2297beacf11bSopenharmony_ci          (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2298beacf11bSopenharmony_ci      if (error)
2299beacf11bSopenharmony_ci        {
2300beacf11bSopenharmony_ci          nfs_debug_error("nfs_request failed: %d\n", error);
2301beacf11bSopenharmony_ci          goto errout_with_mutex;
2302beacf11bSopenharmony_ci        }
2303beacf11bSopenharmony_ci
2304beacf11bSopenharmony_ci      /* The read was successful.  Get a pointer to the beginning of the NFS
2305beacf11bSopenharmony_ci       * response data.
2306beacf11bSopenharmony_ci       */
2307beacf11bSopenharmony_ci
2308beacf11bSopenharmony_ci      read_response = (struct rpc_reply_read *)nmp->nm_iobuffer;
2309beacf11bSopenharmony_ci      readsize = fxdr_unsigned(uint32_t, read_response->read.hdr.count);
2310beacf11bSopenharmony_ci
2311beacf11bSopenharmony_ci      /* Copy the read data into the user buffer */
2312beacf11bSopenharmony_ci
2313beacf11bSopenharmony_ci      if (LOS_CopyFromKernel(buffer, buflen, (const void *)read_response->read.data, readsize) != 0)
2314beacf11bSopenharmony_ci        {
2315beacf11bSopenharmony_ci          error = EINVAL;
2316beacf11bSopenharmony_ci          goto errout_with_mutex;
2317beacf11bSopenharmony_ci        }
2318beacf11bSopenharmony_ci
2319beacf11bSopenharmony_ci      /* Update the read state data */
2320beacf11bSopenharmony_ci
2321beacf11bSopenharmony_ci      filep->f_pos += readsize;
2322beacf11bSopenharmony_ci      np->n_fpos   += readsize;
2323beacf11bSopenharmony_ci      bytesread    += readsize;
2324beacf11bSopenharmony_ci      buffer       += readsize;
2325beacf11bSopenharmony_ci
2326beacf11bSopenharmony_ci      /* Check if we hit the end of file */
2327beacf11bSopenharmony_ci
2328beacf11bSopenharmony_ci      if (read_response->read.hdr.eof != 0)
2329beacf11bSopenharmony_ci        {
2330beacf11bSopenharmony_ci          break;
2331beacf11bSopenharmony_ci        }
2332beacf11bSopenharmony_ci    }
2333beacf11bSopenharmony_ci
2334beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2335beacf11bSopenharmony_ci  return bytesread;
2336beacf11bSopenharmony_ci
2337beacf11bSopenharmony_cierrout_with_mutex:
2338beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2339beacf11bSopenharmony_ci  return -error;
2340beacf11bSopenharmony_ci}
2341beacf11bSopenharmony_ci
2342beacf11bSopenharmony_ciint vfs_nfs_create(struct Vnode *parent, const char *filename, int mode, struct Vnode **vpp)
2343beacf11bSopenharmony_ci{
2344beacf11bSopenharmony_ci  uint32_t           *ptr = NULL;
2345beacf11bSopenharmony_ci  uint32_t            tmp;
2346beacf11bSopenharmony_ci  int                 namelen;
2347beacf11bSopenharmony_ci  int                 reqlen;
2348beacf11bSopenharmony_ci  int                 error;
2349beacf11bSopenharmony_ci  struct nfsnode *parent_nfs_node = (struct nfsnode *)parent->data;
2350beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data);
2351beacf11bSopenharmony_ci  struct nfsnode *np = zalloc(sizeof(struct nfsnode));
2352beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2353beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2354beacf11bSopenharmony_ci  if (error != OK)
2355beacf11bSopenharmony_ci    {
2356beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2357beacf11bSopenharmony_ci      goto errout_with_mutex;
2358beacf11bSopenharmony_ci    }
2359beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.create.create;
2360beacf11bSopenharmony_ci  reqlen = 0;
2361beacf11bSopenharmony_ci
2362beacf11bSopenharmony_ci  /* Copy the variable length, directory file handle */
2363beacf11bSopenharmony_ci
2364beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(parent_nfs_node->n_fhsize);
2365beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2366beacf11bSopenharmony_ci
2367beacf11bSopenharmony_ci  (void)memcpy_s(ptr, parent_nfs_node->n_fhsize, &parent_nfs_node->n_fhandle, parent_nfs_node->n_fhsize);
2368beacf11bSopenharmony_ci  reqlen += (int)parent_nfs_node->n_fhsize;
2369beacf11bSopenharmony_ci  ptr    += uint32_increment(parent_nfs_node->n_fhsize);
2370beacf11bSopenharmony_ci
2371beacf11bSopenharmony_ci  /* Copy the variable-length file name */
2372beacf11bSopenharmony_ci
2373beacf11bSopenharmony_ci  namelen = strlen(filename);
2374beacf11bSopenharmony_ci
2375beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
2376beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2377beacf11bSopenharmony_ci
2378beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, filename, namelen);
2379beacf11bSopenharmony_ci  ptr    += uint32_increment(namelen);
2380beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
2381beacf11bSopenharmony_ci
2382beacf11bSopenharmony_ci  /* Set the creation mode */
2383beacf11bSopenharmony_ci
2384beacf11bSopenharmony_ci#ifdef USE_GUARDED_CREATE
2385beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3CREATE_GUARDED);
2386beacf11bSopenharmony_ci#else
2387beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3CREATE_EXCLUSIVE);
2388beacf11bSopenharmony_ci#endif
2389beacf11bSopenharmony_ci
2390beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2391beacf11bSopenharmony_ci
2392beacf11bSopenharmony_ci  /* Mode information is not provided if EXCLUSIVE creation is used.
2393beacf11bSopenharmony_ci   * in this case, we must call SETATTR after successfully creating
2394beacf11bSopenharmony_ci   * the file.
2395beacf11bSopenharmony_ci   */
2396beacf11bSopenharmony_ci
2397beacf11bSopenharmony_ci  /* Set the mode.  NOTE: Here we depend on the fact that the NuttX and NFS
2398beacf11bSopenharmony_ci   * bit settings are the same (at least for the bits of interest).
2399beacf11bSopenharmony_ci   */
2400beacf11bSopenharmony_ci
2401beacf11bSopenharmony_ci  *ptr++  = nfs_true; /* True: mode value follows */
2402beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2403beacf11bSopenharmony_ci
2404beacf11bSopenharmony_ci  tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP |
2405beacf11bSopenharmony_ci      NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR);
2406beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(tmp);
2407beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2408beacf11bSopenharmony_ci
2409beacf11bSopenharmony_ci  /* Set the user ID to zero */
2410beacf11bSopenharmony_ci
2411beacf11bSopenharmony_ci  *ptr++  = nfs_true;             /* True: Uid value follows */
2412beacf11bSopenharmony_ci  *ptr++  = 0;                    /* UID = 0 (nobody) */
2413beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
2414beacf11bSopenharmony_ci
2415beacf11bSopenharmony_ci  /* Set the group ID to one */
2416beacf11bSopenharmony_ci
2417beacf11bSopenharmony_ci  *ptr++  = nfs_true;            /* True: Gid value follows */
2418beacf11bSopenharmony_ci  *ptr++  = htonl(1);            /* GID = 1 (nogroup) */
2419beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
2420beacf11bSopenharmony_ci
2421beacf11bSopenharmony_ci  /* Set the size to zero */
2422beacf11bSopenharmony_ci
2423beacf11bSopenharmony_ci  *ptr++  = nfs_true;            /* True: Size value follows */
2424beacf11bSopenharmony_ci  *ptr++  = 0;                   /* Size = 0 */
2425beacf11bSopenharmony_ci  *ptr++  = 0;
2426beacf11bSopenharmony_ci  reqlen += 3*sizeof(uint32_t);
2427beacf11bSopenharmony_ci
2428beacf11bSopenharmony_ci  /* Don't change times */
2429beacf11bSopenharmony_ci
2430beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */
2431beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */
2432beacf11bSopenharmony_ci  reqlen += 2*sizeof(uint32_t);
2433beacf11bSopenharmony_ci
2434beacf11bSopenharmony_ci  /* Send the NFS request.  Note there is special logic here to handle version 3
2435beacf11bSopenharmony_ci   * exclusive open semantics.
2436beacf11bSopenharmony_ci   */
2437beacf11bSopenharmony_ci
2438beacf11bSopenharmony_ci  do
2439beacf11bSopenharmony_ci    {
2440beacf11bSopenharmony_ci      nfs_statistics(NFSPROC_CREATE);
2441beacf11bSopenharmony_ci      error = nfs_request(nmp, NFSPROC_CREATE,
2442beacf11bSopenharmony_ci          (void *)&nmp->nm_msgbuffer.create, reqlen,
2443beacf11bSopenharmony_ci          (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2444beacf11bSopenharmony_ci    }
2445beacf11bSopenharmony_ci  while (0);
2446beacf11bSopenharmony_ci
2447beacf11bSopenharmony_ci  /* Check for success */
2448beacf11bSopenharmony_ci
2449beacf11bSopenharmony_ci  if (error != OK)
2450beacf11bSopenharmony_ci    {
2451beacf11bSopenharmony_ci      *vpp = NULL;
2452beacf11bSopenharmony_ci      goto errout_with_mutex;
2453beacf11bSopenharmony_ci    }
2454beacf11bSopenharmony_ci
2455beacf11bSopenharmony_ci  /* Parse the returned data */
2456beacf11bSopenharmony_ci
2457beacf11bSopenharmony_ci  ptr = (uint32_t *)&((struct rpc_reply_create *)
2458beacf11bSopenharmony_ci      nmp->nm_iobuffer)->create;
2459beacf11bSopenharmony_ci
2460beacf11bSopenharmony_ci  /* Save the file handle in the file data structure */
2461beacf11bSopenharmony_ci
2462beacf11bSopenharmony_ci  tmp = *ptr++;  /* handle_follows */
2463beacf11bSopenharmony_ci  if (!tmp)
2464beacf11bSopenharmony_ci    {
2465beacf11bSopenharmony_ci      nfs_debug_error("no file handle follows\n");
2466beacf11bSopenharmony_ci      error = EINVAL;
2467beacf11bSopenharmony_ci      goto errout_with_mutex;
2468beacf11bSopenharmony_ci    }
2469beacf11bSopenharmony_ci
2470beacf11bSopenharmony_ci  tmp = *ptr++;
2471beacf11bSopenharmony_ci  tmp = fxdr_unsigned(uint32_t, tmp);
2472beacf11bSopenharmony_ci  DEBUGASSERT(tmp <= NFSX_V3FHMAX);
2473beacf11bSopenharmony_ci
2474beacf11bSopenharmony_ci  np->n_fhsize      = (uint8_t)tmp;
2475beacf11bSopenharmony_ci  (void)memcpy_s(&np->n_fhandle, tmp, ptr, tmp);
2476beacf11bSopenharmony_ci  ptr += uint32_increment(tmp);
2477beacf11bSopenharmony_ci
2478beacf11bSopenharmony_ci  /* Save the attributes in the file data structure */
2479beacf11bSopenharmony_ci
2480beacf11bSopenharmony_ci  tmp = *ptr;  /* handle_follows */
2481beacf11bSopenharmony_ci  if (!tmp)
2482beacf11bSopenharmony_ci    {
2483beacf11bSopenharmony_ci      nfs_debug_info("WARNING: no file attributes\n");
2484beacf11bSopenharmony_ci    }
2485beacf11bSopenharmony_ci  else
2486beacf11bSopenharmony_ci    {
2487beacf11bSopenharmony_ci      /* Initialize the file attributes */
2488beacf11bSopenharmony_ci
2489beacf11bSopenharmony_ci      nfs_attrupdate(np, (struct nfs_fattr *)ptr);
2490beacf11bSopenharmony_ci    }
2491beacf11bSopenharmony_ci
2492beacf11bSopenharmony_ci  /* Any following dir_wcc data is ignored for now */
2493beacf11bSopenharmony_ci  np->n_crefs = 1;
2494beacf11bSopenharmony_ci
2495beacf11bSopenharmony_ci  /* Attach the private data to the struct file instance */
2496beacf11bSopenharmony_ci
2497beacf11bSopenharmony_ci  /* Then insert the new instance at the head of the list in the mountpoint
2498beacf11bSopenharmony_ci   * tructure. It needs to be there (1) to handle error conditions that effect
2499beacf11bSopenharmony_ci   * all files, and (2) to inform the umount logic that we are busy.  We
2500beacf11bSopenharmony_ci   * cannot unmount the file system if this list is not empty!
2501beacf11bSopenharmony_ci   */
2502beacf11bSopenharmony_ci
2503beacf11bSopenharmony_ci  np->n_next   = nmp->nm_head;
2504beacf11bSopenharmony_ci  nmp->nm_head = np;
2505beacf11bSopenharmony_ci
2506beacf11bSopenharmony_ci  np->n_pfhsize     = parent_nfs_node->n_fhsize;
2507beacf11bSopenharmony_ci  (void)memcpy_s(&(np->n_pfhandle), NFSX_V3FHMAX, &(parent_nfs_node->n_fhandle), parent_nfs_node->n_fhsize);
2508beacf11bSopenharmony_ci
2509beacf11bSopenharmony_ci  np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED);
2510beacf11bSopenharmony_ci  np->n_name = zalloc(namelen + 1);
2511beacf11bSopenharmony_ci  memcpy_s(np->n_name, (namelen + 1), filename, (namelen + 1));
2512beacf11bSopenharmony_ci
2513beacf11bSopenharmony_ci  (void)VnodeAlloc(&nfs_vops, vpp);
2514beacf11bSopenharmony_ci  (*vpp)->parent = parent;
2515beacf11bSopenharmony_ci  (*vpp)->fop = &nfs_fops;
2516beacf11bSopenharmony_ci  (*vpp)->originMount = parent->originMount;
2517beacf11bSopenharmony_ci  (*vpp)->data = np;
2518beacf11bSopenharmony_ci  (*vpp)->type = filetype_to_vnodetype(np->n_type);
2519beacf11bSopenharmony_ci  (*vpp)->mode = type_to_mode((*vpp)->type, nmp->nm_permission);
2520beacf11bSopenharmony_ci  (*vpp)->gid = nmp->nm_gid;
2521beacf11bSopenharmony_ci  (*vpp)->uid = nmp->nm_uid;
2522beacf11bSopenharmony_ci
2523beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2524beacf11bSopenharmony_ci  return OK;
2525beacf11bSopenharmony_ci
2526beacf11bSopenharmony_cierrout_with_mutex:
2527beacf11bSopenharmony_ci  if (np)
2528beacf11bSopenharmony_ci    {
2529beacf11bSopenharmony_ci      free(np);
2530beacf11bSopenharmony_ci    }
2531beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2532beacf11bSopenharmony_ci  return -error;
2533beacf11bSopenharmony_ci}
2534beacf11bSopenharmony_ci
2535beacf11bSopenharmony_ciint vfs_nfs_unlink(struct Vnode *parent, struct Vnode *target, const char *filename)
2536beacf11bSopenharmony_ci{
2537beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data);
2538beacf11bSopenharmony_ci  struct nfsnode  *parent_node = NULL;
2539beacf11bSopenharmony_ci  struct nfsnode  *target_node = NULL;
2540beacf11bSopenharmony_ci  int reqlen;
2541beacf11bSopenharmony_ci  int namelen;
2542beacf11bSopenharmony_ci  uint32_t *ptr = NULL;
2543beacf11bSopenharmony_ci  int error;
2544beacf11bSopenharmony_ci
2545beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2546beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2547beacf11bSopenharmony_ci  if (error != OK)
2548beacf11bSopenharmony_ci    {
2549beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2550beacf11bSopenharmony_ci      goto errout_with_mutex;
2551beacf11bSopenharmony_ci    }
2552beacf11bSopenharmony_ci
2553beacf11bSopenharmony_ci  parent_node = (struct nfsnode*)(parent->data);
2554beacf11bSopenharmony_ci  target_node = (struct nfsnode*)(target->data);
2555beacf11bSopenharmony_ci
2556beacf11bSopenharmony_ci  if (target_node->n_type == NFDIR)
2557beacf11bSopenharmony_ci    {
2558beacf11bSopenharmony_ci      nfs_debug_error("try to remove a directory\n");
2559beacf11bSopenharmony_ci      error = EISDIR;
2560beacf11bSopenharmony_ci      goto errout_with_mutex;
2561beacf11bSopenharmony_ci    }
2562beacf11bSopenharmony_ci
2563beacf11bSopenharmony_ci  /* Create the REMOVE RPC call arguments */
2564beacf11bSopenharmony_ci
2565beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.removef.remove;
2566beacf11bSopenharmony_ci  reqlen = 0;
2567beacf11bSopenharmony_ci
2568beacf11bSopenharmony_ci  /* Copy the variable length, directory file handle */
2569beacf11bSopenharmony_ci
2570beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(parent_node->n_fhsize);
2571beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2572beacf11bSopenharmony_ci
2573beacf11bSopenharmony_ci  (void)memcpy_s(ptr, parent_node->n_fhsize, &parent_node->n_fhandle, parent_node->n_fhsize);
2574beacf11bSopenharmony_ci  reqlen += (int)parent_node->n_fhsize;
2575beacf11bSopenharmony_ci  ptr    += uint32_increment(parent_node->n_fhsize);
2576beacf11bSopenharmony_ci
2577beacf11bSopenharmony_ci  /* Copy the variable-length file name */
2578beacf11bSopenharmony_ci
2579beacf11bSopenharmony_ci  namelen = strlen(filename);
2580beacf11bSopenharmony_ci
2581beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
2582beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2583beacf11bSopenharmony_ci
2584beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, filename, namelen);
2585beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
2586beacf11bSopenharmony_ci
2587beacf11bSopenharmony_ci  /* Perform the REMOVE RPC call */
2588beacf11bSopenharmony_ci
2589beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_REMOVE);
2590beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_REMOVE,
2591beacf11bSopenharmony_ci      (void *)&nmp->nm_msgbuffer.removef, reqlen,
2592beacf11bSopenharmony_ci      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2593beacf11bSopenharmony_ci
2594beacf11bSopenharmony_cierrout_with_mutex:
2595beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2596beacf11bSopenharmony_ci  return -error;
2597beacf11bSopenharmony_ci}
2598beacf11bSopenharmony_ci
2599beacf11bSopenharmony_ciint vfs_nfs_rmdir(struct Vnode *parent, struct Vnode *target, const char *dirname)
2600beacf11bSopenharmony_ci{
2601beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(parent->originMount->data);
2602beacf11bSopenharmony_ci  struct nfsnode  *parent_node = NULL;
2603beacf11bSopenharmony_ci  struct nfsnode  *target_node = NULL;
2604beacf11bSopenharmony_ci  int reqlen;
2605beacf11bSopenharmony_ci  int namelen;
2606beacf11bSopenharmony_ci  uint32_t *ptr = NULL;
2607beacf11bSopenharmony_ci  int error;
2608beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2609beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2610beacf11bSopenharmony_ci  if (error != OK)
2611beacf11bSopenharmony_ci    {
2612beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2613beacf11bSopenharmony_ci      goto errout_with_mutex;
2614beacf11bSopenharmony_ci    }
2615beacf11bSopenharmony_ci
2616beacf11bSopenharmony_ci  parent_node = (struct nfsnode*)(parent->data);
2617beacf11bSopenharmony_ci  target_node = (struct nfsnode*)(target->data);
2618beacf11bSopenharmony_ci
2619beacf11bSopenharmony_ci  if (target_node->n_type != NFDIR)
2620beacf11bSopenharmony_ci    {
2621beacf11bSopenharmony_ci      nfs_debug_error("try to remove a non-dir\n");
2622beacf11bSopenharmony_ci      return -ENOTDIR;
2623beacf11bSopenharmony_ci    }
2624beacf11bSopenharmony_ci
2625beacf11bSopenharmony_ci  /* Set up the RMDIR call message arguments */
2626beacf11bSopenharmony_ci
2627beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.rmdir.rmdir;
2628beacf11bSopenharmony_ci  reqlen = 0;
2629beacf11bSopenharmony_ci
2630beacf11bSopenharmony_ci  /* Copy the variable length, directory file handle */
2631beacf11bSopenharmony_ci
2632beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(parent_node->n_fhsize);
2633beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2634beacf11bSopenharmony_ci
2635beacf11bSopenharmony_ci  (void)memcpy_s(ptr, parent_node->n_fhsize, &parent_node->n_fhandle, parent_node->n_fhsize);
2636beacf11bSopenharmony_ci  reqlen += (int)parent_node->n_fhsize;
2637beacf11bSopenharmony_ci  ptr    += uint32_increment(parent_node->n_fhsize);
2638beacf11bSopenharmony_ci
2639beacf11bSopenharmony_ci  /* Copy the variable-length directory name */
2640beacf11bSopenharmony_ci
2641beacf11bSopenharmony_ci  namelen = strlen(dirname);
2642beacf11bSopenharmony_ci
2643beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(namelen);
2644beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2645beacf11bSopenharmony_ci
2646beacf11bSopenharmony_ci  (void)memcpy_s(ptr, namelen, dirname, namelen);
2647beacf11bSopenharmony_ci  reqlen += uint32_alignup(namelen);
2648beacf11bSopenharmony_ci
2649beacf11bSopenharmony_ci  /* Perform the RMDIR RPC */
2650beacf11bSopenharmony_ci
2651beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_RMDIR);
2652beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_RMDIR,
2653beacf11bSopenharmony_ci      (void *)&nmp->nm_msgbuffer.rmdir, reqlen,
2654beacf11bSopenharmony_ci      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2655beacf11bSopenharmony_ci
2656beacf11bSopenharmony_cierrout_with_mutex:
2657beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2658beacf11bSopenharmony_ci  return -nfs_2_vfs(error);
2659beacf11bSopenharmony_ci}
2660beacf11bSopenharmony_ci
2661beacf11bSopenharmony_ci
2662beacf11bSopenharmony_ciint vfs_nfs_close(struct Vnode *node)
2663beacf11bSopenharmony_ci{
2664beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
2665beacf11bSopenharmony_ci  struct nfsnode  *np = NULL;
2666beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2667beacf11bSopenharmony_ci  np = (struct nfsnode*)(node->data);
2668beacf11bSopenharmony_ci  /* Decrement the reference count.  If the reference count would not
2669beacf11bSopenharmony_ci   * decrement to zero, then that is all we have to do.
2670beacf11bSopenharmony_ci   */
2671beacf11bSopenharmony_ci
2672beacf11bSopenharmony_ci  if (np->n_crefs > 1)
2673beacf11bSopenharmony_ci    {
2674beacf11bSopenharmony_ci      np->n_crefs--;
2675beacf11bSopenharmony_ci    }
2676beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2677beacf11bSopenharmony_ci  return OK;
2678beacf11bSopenharmony_ci}
2679beacf11bSopenharmony_ci
2680beacf11bSopenharmony_ciint vfs_nfs_close_file(struct file *filep)
2681beacf11bSopenharmony_ci{
2682beacf11bSopenharmony_ci  struct Vnode *node = (struct Vnode *)filep->f_vnode;
2683beacf11bSopenharmony_ci  return vfs_nfs_close(node);
2684beacf11bSopenharmony_ci}
2685beacf11bSopenharmony_ci
2686beacf11bSopenharmony_ciint vfs_nfs_closedir(struct Vnode *node, struct fs_dirent_s *dir)
2687beacf11bSopenharmony_ci{
2688beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
2689beacf11bSopenharmony_ci  struct nfsdir_s  *prev = NULL;
2690beacf11bSopenharmony_ci  struct nfsdir_s  *curr = NULL;
2691beacf11bSopenharmony_ci  struct nfsdir_s      *nfs_dir;
2692beacf11bSopenharmony_ci  struct entry3        *entry_pos = NULL;
2693beacf11bSopenharmony_ci  int                  ret;
2694beacf11bSopenharmony_ci
2695beacf11bSopenharmony_ci  /* Sanity checks */
2696beacf11bSopenharmony_ci  nfs_dir = (struct nfsdir_s *)(dir->u.fs_dir);
2697beacf11bSopenharmony_ci
2698beacf11bSopenharmony_ci  DEBUGASSERT(nmp != NULL);
2699beacf11bSopenharmony_ci
2700beacf11bSopenharmony_ci  /* Get exclusive access to the mount structure. */
2701beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2702beacf11bSopenharmony_ci
2703beacf11bSopenharmony_ci
2704beacf11bSopenharmony_ci  for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries)
2705beacf11bSopenharmony_ci    {
2706beacf11bSopenharmony_ci      nfs_dir->nfs_entries = entry_pos->next;
2707beacf11bSopenharmony_ci      NFS_DIR_ENTRY_FREE(entry_pos);
2708beacf11bSopenharmony_ci    }
2709beacf11bSopenharmony_ci
2710beacf11bSopenharmony_ci  /* Assume file structure will not be found.  This should never happen. */
2711beacf11bSopenharmony_ci
2712beacf11bSopenharmony_ci  ret = EINVAL;
2713beacf11bSopenharmony_ci
2714beacf11bSopenharmony_ci  for (prev = (struct nfsdir_s  *)NULL, curr = nmp->nm_dir;
2715beacf11bSopenharmony_ci      curr;
2716beacf11bSopenharmony_ci      prev = curr, curr = curr->nfs_next)
2717beacf11bSopenharmony_ci    {
2718beacf11bSopenharmony_ci      /* Check if this node is ours */
2719beacf11bSopenharmony_ci
2720beacf11bSopenharmony_ci      if (nfs_dir == curr)
2721beacf11bSopenharmony_ci        {
2722beacf11bSopenharmony_ci          /* Yes.. remove it from the list of file structures */
2723beacf11bSopenharmony_ci
2724beacf11bSopenharmony_ci          if (prev)
2725beacf11bSopenharmony_ci            {
2726beacf11bSopenharmony_ci              /* Remove from mid-list */
2727beacf11bSopenharmony_ci
2728beacf11bSopenharmony_ci              prev->nfs_next = nfs_dir->nfs_next;
2729beacf11bSopenharmony_ci            }
2730beacf11bSopenharmony_ci          else
2731beacf11bSopenharmony_ci            {
2732beacf11bSopenharmony_ci              /* Remove from the head of the list */
2733beacf11bSopenharmony_ci
2734beacf11bSopenharmony_ci              nmp->nm_dir= nfs_dir->nfs_next;
2735beacf11bSopenharmony_ci            }
2736beacf11bSopenharmony_ci
2737beacf11bSopenharmony_ci          /* Then deallocate the file structure and return success */
2738beacf11bSopenharmony_ci
2739beacf11bSopenharmony_ci          free(nfs_dir);
2740beacf11bSopenharmony_ci          nfs_dir = NULL;
2741beacf11bSopenharmony_ci          ret = OK;
2742beacf11bSopenharmony_ci          break;
2743beacf11bSopenharmony_ci        }
2744beacf11bSopenharmony_ci    }
2745beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2746beacf11bSopenharmony_ci
2747beacf11bSopenharmony_ci  return -ret; /*lint !e438*/
2748beacf11bSopenharmony_ci}
2749beacf11bSopenharmony_ci
2750beacf11bSopenharmony_ci/****************************************************************************
2751beacf11bSopenharmony_ci * Name: nfs_fsinfo
2752beacf11bSopenharmony_ci *
2753beacf11bSopenharmony_ci * Description:
2754beacf11bSopenharmony_ci *   Return information about root directory.
2755beacf11bSopenharmony_ci *
2756beacf11bSopenharmony_ci * Returned Value:
2757beacf11bSopenharmony_ci *   0 on success; positive errno value on failure
2758beacf11bSopenharmony_ci *
2759beacf11bSopenharmony_ci * Assumptions:
2760beacf11bSopenharmony_ci *   The caller has exclusive access to the NFS mount structure
2761beacf11bSopenharmony_ci *
2762beacf11bSopenharmony_ci ****************************************************************************/
2763beacf11bSopenharmony_ci
2764beacf11bSopenharmony_ciint nfs_fsinfo(struct nfsmount *nmp)
2765beacf11bSopenharmony_ci{
2766beacf11bSopenharmony_ci  struct rpc_call_fs fsinfo;
2767beacf11bSopenharmony_ci  struct rpc_reply_fsinfo fsp;
2768beacf11bSopenharmony_ci  struct nfs_fsinfo *rep_info = NULL;
2769beacf11bSopenharmony_ci  uint32_t pref;
2770beacf11bSopenharmony_ci  uint32_t max;
2771beacf11bSopenharmony_ci  int error = 0;
2772beacf11bSopenharmony_ci
2773beacf11bSopenharmony_ci  fsinfo.fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
2774beacf11bSopenharmony_ci  fsinfo.fs.fsroot.handle = nmp->nm_fh;
2775beacf11bSopenharmony_ci
2776beacf11bSopenharmony_ci  /* Request FSINFO from the server */
2777beacf11bSopenharmony_ci
2778beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_FSINFO);
2779beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_FSINFO,
2780beacf11bSopenharmony_ci                      (void *)&fsinfo, sizeof(struct FS3args),
2781beacf11bSopenharmony_ci                      (void *)&fsp, sizeof(struct rpc_reply_fsinfo));
2782beacf11bSopenharmony_ci  if (error)
2783beacf11bSopenharmony_ci    {
2784beacf11bSopenharmony_ci      return error;
2785beacf11bSopenharmony_ci    }
2786beacf11bSopenharmony_ci
2787beacf11bSopenharmony_ci  if (txdr_unsigned(fsp.fsinfo.obj_attributes.obj_attribute_follow) == 1)
2788beacf11bSopenharmony_ci    {
2789beacf11bSopenharmony_ci      rep_info = (struct nfs_fsinfo *)&fsp.fsinfo.fs_rtmax;
2790beacf11bSopenharmony_ci    }
2791beacf11bSopenharmony_ci  else
2792beacf11bSopenharmony_ci    {
2793beacf11bSopenharmony_ci      rep_info = (struct nfs_fsinfo *)((void *)(&fsp.fsinfo.obj_attributes.attributes));
2794beacf11bSopenharmony_ci    }
2795beacf11bSopenharmony_ci
2796beacf11bSopenharmony_ci  /* Save the root file system attributes */
2797beacf11bSopenharmony_ci  pref = fxdr_unsigned(uint32_t, rep_info->fs_wtpref);
2798beacf11bSopenharmony_ci  if (pref < nmp->nm_wsize)
2799beacf11bSopenharmony_ci    {
2800beacf11bSopenharmony_ci      nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1);
2801beacf11bSopenharmony_ci    }
2802beacf11bSopenharmony_ci
2803beacf11bSopenharmony_ci  max = fxdr_unsigned(uint32_t, rep_info->fs_wtmax);
2804beacf11bSopenharmony_ci  if (max < nmp->nm_wsize)
2805beacf11bSopenharmony_ci    {
2806beacf11bSopenharmony_ci      nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
2807beacf11bSopenharmony_ci      if (nmp->nm_wsize == 0)
2808beacf11bSopenharmony_ci        {
2809beacf11bSopenharmony_ci          nmp->nm_wsize = max;
2810beacf11bSopenharmony_ci        }
2811beacf11bSopenharmony_ci    }
2812beacf11bSopenharmony_ci
2813beacf11bSopenharmony_ci  pref = fxdr_unsigned(uint32_t, rep_info->fs_rtpref);
2814beacf11bSopenharmony_ci  if (pref < nmp->nm_rsize)
2815beacf11bSopenharmony_ci    {
2816beacf11bSopenharmony_ci      nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1);
2817beacf11bSopenharmony_ci    }
2818beacf11bSopenharmony_ci
2819beacf11bSopenharmony_ci  max = fxdr_unsigned(uint32_t, rep_info->fs_rtmax);
2820beacf11bSopenharmony_ci  if (max < nmp->nm_rsize)
2821beacf11bSopenharmony_ci    {
2822beacf11bSopenharmony_ci      nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
2823beacf11bSopenharmony_ci      if (nmp->nm_rsize == 0)
2824beacf11bSopenharmony_ci        {
2825beacf11bSopenharmony_ci          nmp->nm_rsize = max;
2826beacf11bSopenharmony_ci        }
2827beacf11bSopenharmony_ci    }
2828beacf11bSopenharmony_ci
2829beacf11bSopenharmony_ci  pref = fxdr_unsigned(uint32_t, rep_info->fs_dtpref);
2830beacf11bSopenharmony_ci  if (pref < nmp->nm_readdirsize)
2831beacf11bSopenharmony_ci    {
2832beacf11bSopenharmony_ci      nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1);
2833beacf11bSopenharmony_ci    }
2834beacf11bSopenharmony_ci
2835beacf11bSopenharmony_ci  if (max < nmp->nm_readdirsize)
2836beacf11bSopenharmony_ci    {
2837beacf11bSopenharmony_ci      nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
2838beacf11bSopenharmony_ci      if (nmp->nm_readdirsize == 0)
2839beacf11bSopenharmony_ci        {
2840beacf11bSopenharmony_ci          nmp->nm_readdirsize = max;
2841beacf11bSopenharmony_ci        }
2842beacf11bSopenharmony_ci    }
2843beacf11bSopenharmony_ci
2844beacf11bSopenharmony_ci  return OK;
2845beacf11bSopenharmony_ci}
2846beacf11bSopenharmony_ci
2847beacf11bSopenharmony_ciint vfs_nfs_statfs(struct Mount *mountpt, struct statfs *sbp)
2848beacf11bSopenharmony_ci{
2849beacf11bSopenharmony_ci  struct nfsmount *nmp;
2850beacf11bSopenharmony_ci  struct rpc_call_fs *fsstat = NULL;
2851beacf11bSopenharmony_ci  struct rpc_reply_fsstat *sfp = NULL;
2852beacf11bSopenharmony_ci  struct nfs_statfs_ctx  *stfp = NULL;
2853beacf11bSopenharmony_ci  int error = 0;
2854beacf11bSopenharmony_ci  uint64_t tquad;
2855beacf11bSopenharmony_ci
2856beacf11bSopenharmony_ci  /* Get the mountpoint private data from the vnode structure */
2857beacf11bSopenharmony_ci
2858beacf11bSopenharmony_ci  nmp = (struct nfsmount *)mountpt->data;
2859beacf11bSopenharmony_ci
2860beacf11bSopenharmony_ci  /* Check if the mount is still healthy */
2861beacf11bSopenharmony_ci
2862beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2863beacf11bSopenharmony_ci  error = nfs_checkmount(nmp);
2864beacf11bSopenharmony_ci  if (error != OK)
2865beacf11bSopenharmony_ci    {
2866beacf11bSopenharmony_ci      nfs_debug_error("nfs_checkmount failed: %d\n", error);
2867beacf11bSopenharmony_ci      goto errout_with_mutex;
2868beacf11bSopenharmony_ci    }
2869beacf11bSopenharmony_ci
2870beacf11bSopenharmony_ci  /* Fill in the statfs info */
2871beacf11bSopenharmony_ci
2872beacf11bSopenharmony_ci  sbp->f_type = NFS_SUPER_MAGIC;
2873beacf11bSopenharmony_ci
2874beacf11bSopenharmony_ci  error = nfs_fsinfo(nmp);
2875beacf11bSopenharmony_ci  if (error)
2876beacf11bSopenharmony_ci    {
2877beacf11bSopenharmony_ci      nfs_debug_error("nfs_fsinfo failed: %d\n", error);
2878beacf11bSopenharmony_ci      goto errout_with_mutex;
2879beacf11bSopenharmony_ci    }
2880beacf11bSopenharmony_ci
2881beacf11bSopenharmony_ci  fsstat = &nmp->nm_msgbuffer.fsstat;
2882beacf11bSopenharmony_ci  fsstat->fs.fsroot.length = txdr_unsigned(nmp->nm_fhsize);
2883beacf11bSopenharmony_ci  (void)memcpy_s(&fsstat->fs.fsroot.handle, sizeof(nfsfh_t), &nmp->nm_fh, sizeof(nfsfh_t));
2884beacf11bSopenharmony_ci
2885beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_FSSTAT);
2886beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_FSSTAT,
2887beacf11bSopenharmony_ci                      (void *)fsstat, sizeof(struct FS3args),
2888beacf11bSopenharmony_ci                      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2889beacf11bSopenharmony_ci  if (error)
2890beacf11bSopenharmony_ci    {
2891beacf11bSopenharmony_ci      goto errout_with_mutex;
2892beacf11bSopenharmony_ci    }
2893beacf11bSopenharmony_ci
2894beacf11bSopenharmony_ci  sfp                   = (struct rpc_reply_fsstat *)nmp->nm_iobuffer;
2895beacf11bSopenharmony_ci  if (txdr_unsigned(sfp->fsstat.attributes_follow) == 1)
2896beacf11bSopenharmony_ci    {
2897beacf11bSopenharmony_ci      stfp = (struct nfs_statfs_ctx *)&sfp->fsstat.sf_tbytes;
2898beacf11bSopenharmony_ci    }
2899beacf11bSopenharmony_ci  else
2900beacf11bSopenharmony_ci    {
2901beacf11bSopenharmony_ci      stfp = (struct nfs_statfs_ctx *)&sfp->fsstat.obj_attributes;
2902beacf11bSopenharmony_ci    }
2903beacf11bSopenharmony_ci
2904beacf11bSopenharmony_ci  sbp->f_bsize          = NFS_FABLKSIZE;
2905beacf11bSopenharmony_ci  tquad                 = fxdr_hyper(&stfp->sf_tbytes); /*lint !e571*/
2906beacf11bSopenharmony_ci  sbp->f_blocks         = tquad / (uint64_t) NFS_FABLKSIZE;
2907beacf11bSopenharmony_ci  tquad                 = fxdr_hyper(&stfp->sf_fbytes); /*lint !e571*/
2908beacf11bSopenharmony_ci  sbp->f_bfree          = tquad / (uint64_t) NFS_FABLKSIZE;
2909beacf11bSopenharmony_ci  tquad                 = fxdr_hyper(&stfp->sf_abytes); /*lint !e571*/
2910beacf11bSopenharmony_ci  sbp->f_bavail         = tquad / (uint64_t) NFS_FABLKSIZE;
2911beacf11bSopenharmony_ci  tquad                 = fxdr_hyper(&stfp->sf_tfiles); /*lint !e571*/
2912beacf11bSopenharmony_ci  sbp->f_files          = tquad;
2913beacf11bSopenharmony_ci  tquad                 = fxdr_hyper(&stfp->sf_ffiles); /*lint !e571*/
2914beacf11bSopenharmony_ci  sbp->f_ffree          = tquad;
2915beacf11bSopenharmony_ci  sbp->f_namelen        = NAME_MAX;
2916beacf11bSopenharmony_ci  sbp->f_flags          = mountpt->mountFlags;
2917beacf11bSopenharmony_ci
2918beacf11bSopenharmony_cierrout_with_mutex:
2919beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2920beacf11bSopenharmony_ci  return -error;
2921beacf11bSopenharmony_ci}
2922beacf11bSopenharmony_ci
2923beacf11bSopenharmony_cistatic int vfs_nfs_rewinddir(struct Vnode *node, struct fs_dirent_s *dir)
2924beacf11bSopenharmony_ci{
2925beacf11bSopenharmony_ci  struct nfsdir_s *nfs_dir = NULL;
2926beacf11bSopenharmony_ci  struct entry3   *entry_pos = NULL;
2927beacf11bSopenharmony_ci
2928beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
2929beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2930beacf11bSopenharmony_ci  /* Reset the NFS-specific portions of dirent structure, retaining only the
2931beacf11bSopenharmony_ci   * file handle.
2932beacf11bSopenharmony_ci   */
2933beacf11bSopenharmony_ci
2934beacf11bSopenharmony_ci  nfs_dir = (struct nfsdir_s *)dir->u.fs_dir;
2935beacf11bSopenharmony_ci  (void)memset_s(nfs_dir->nfs_verifier, DIRENT_NFS_VERFLEN, 0, DIRENT_NFS_VERFLEN);
2936beacf11bSopenharmony_ci  nfs_dir->nfs_cookie[0] = 0;
2937beacf11bSopenharmony_ci  nfs_dir->nfs_cookie[1] = 0;
2938beacf11bSopenharmony_ci  for (entry_pos = nfs_dir->nfs_entries; entry_pos != NULL; entry_pos = nfs_dir->nfs_entries)
2939beacf11bSopenharmony_ci    {
2940beacf11bSopenharmony_ci      nfs_dir->nfs_entries = entry_pos->next;
2941beacf11bSopenharmony_ci      NFS_DIR_ENTRY_FREE(entry_pos);
2942beacf11bSopenharmony_ci    }
2943beacf11bSopenharmony_ci  free(nfs_dir->nfs_entries);
2944beacf11bSopenharmony_ci  nfs_dir->nfs_entries = NULL;
2945beacf11bSopenharmony_ci  nfs_mux_release(nmp);
2946beacf11bSopenharmony_ci  return OK;
2947beacf11bSopenharmony_ci}
2948beacf11bSopenharmony_ci
2949beacf11bSopenharmony_ciint vfs_nfs_truncate(struct Vnode *node, off_t length)
2950beacf11bSopenharmony_ci{
2951beacf11bSopenharmony_ci  uint32_t *ptr;
2952beacf11bSopenharmony_ci  int reqlen;
2953beacf11bSopenharmony_ci  int error;
2954beacf11bSopenharmony_ci
2955beacf11bSopenharmony_ci  struct nfsmount *nmp = NULL;
2956beacf11bSopenharmony_ci  struct nfsnode  *np = NULL;
2957beacf11bSopenharmony_ci
2958beacf11bSopenharmony_ci  nmp = (struct nfsmount *)(node->originMount->data);
2959beacf11bSopenharmony_ci  nfs_mux_take(nmp);
2960beacf11bSopenharmony_ci  np = (struct nfsnode*)(node->data);
2961beacf11bSopenharmony_ci
2962beacf11bSopenharmony_ci  /* Create the SETATTR RPC call arguments */
2963beacf11bSopenharmony_ci
2964beacf11bSopenharmony_ci  ptr    = (uint32_t *)&nmp->nm_msgbuffer.setattr.setattr;
2965beacf11bSopenharmony_ci  reqlen = 0;
2966beacf11bSopenharmony_ci
2967beacf11bSopenharmony_ci  /* Copy the variable length, directory file handle */
2968beacf11bSopenharmony_ci
2969beacf11bSopenharmony_ci  *ptr++  = txdr_unsigned(np->n_fhsize);
2970beacf11bSopenharmony_ci  reqlen += sizeof(uint32_t);
2971beacf11bSopenharmony_ci
2972beacf11bSopenharmony_ci  (void)memcpy_s(ptr, np->n_fhsize, &np->n_fhandle, np->n_fhsize);
2973beacf11bSopenharmony_ci  reqlen += (int)np->n_fhsize;
2974beacf11bSopenharmony_ci  ptr    += uint32_increment(np->n_fhsize);
2975beacf11bSopenharmony_ci
2976beacf11bSopenharmony_ci  /* Copy the variable-length attributes */
2977beacf11bSopenharmony_ci
2978beacf11bSopenharmony_ci  *ptr++  = nfs_false;                        /* Don't change mode */
2979beacf11bSopenharmony_ci  *ptr++  = nfs_false;                        /* Don't change uid */
2980beacf11bSopenharmony_ci  *ptr++  = nfs_false;                        /* Don't change gid */
2981beacf11bSopenharmony_ci  *ptr++  = nfs_true;                         /* Use the following size */
2982beacf11bSopenharmony_ci  *ptr++  = length;                           /* Truncate to the specified length */
2983beacf11bSopenharmony_ci  *ptr++  = 0;
2984beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_TOSERVER);   /* Use the server's time */
2985beacf11bSopenharmony_ci  *ptr++  = htonl(NFSV3SATTRTIME_TOSERVER);   /* Use the server's time */
2986beacf11bSopenharmony_ci  *ptr++  = nfs_false;                        /* No guard value */
2987beacf11bSopenharmony_ci  reqlen += 9 * sizeof(uint32_t);
2988beacf11bSopenharmony_ci
2989beacf11bSopenharmony_ci  /* Perform the SETATTR RPC */
2990beacf11bSopenharmony_ci
2991beacf11bSopenharmony_ci  nfs_statistics(NFSPROC_SETATTR);
2992beacf11bSopenharmony_ci  error = nfs_request(nmp, NFSPROC_SETATTR,
2993beacf11bSopenharmony_ci                      (void *)&nmp->nm_msgbuffer.setattr, reqlen,
2994beacf11bSopenharmony_ci                      (void *)nmp->nm_iobuffer, nmp->nm_buflen);
2995beacf11bSopenharmony_ci  if (error != OK)
2996beacf11bSopenharmony_ci    {
2997beacf11bSopenharmony_ci      nfs_mux_release(nmp);
2998beacf11bSopenharmony_ci      nfs_debug_error("nfs_request failed: %d\n", error);
2999beacf11bSopenharmony_ci      return -error;
3000beacf11bSopenharmony_ci    }
3001beacf11bSopenharmony_ci
3002beacf11bSopenharmony_ci  /* Indicate that the file now has zero length */
3003beacf11bSopenharmony_ci
3004beacf11bSopenharmony_ci  np->n_size = length;
3005beacf11bSopenharmony_ci  nfs_mux_release(nmp);
3006beacf11bSopenharmony_ci  return OK;
3007beacf11bSopenharmony_ci}
3008beacf11bSopenharmony_ci
3009beacf11bSopenharmony_cistatic int vfs_nfs_unmount(struct Mount *mnt, struct Vnode **blkDriver)
3010beacf11bSopenharmony_ci{
3011beacf11bSopenharmony_ci  (void)blkDriver;
3012beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)mnt->data;
3013beacf11bSopenharmony_ci  int error;
3014beacf11bSopenharmony_ci
3015beacf11bSopenharmony_ci  DEBUGASSERT(nmp);
3016beacf11bSopenharmony_ci
3017beacf11bSopenharmony_ci  /* Get exclusive access to the mount structure */
3018beacf11bSopenharmony_ci
3019beacf11bSopenharmony_ci  nfs_mux_take(nmp);
3020beacf11bSopenharmony_ci
3021beacf11bSopenharmony_ci  /* Are there any open files?  We can tell if there are open files by looking
3022beacf11bSopenharmony_ci   * at the list of file structures in the mount structure.  If this list
3023beacf11bSopenharmony_ci   * not empty, then there are open files and we cannot unmount now (or a
3024beacf11bSopenharmony_ci   * crash is sure to follow).
3025beacf11bSopenharmony_ci   * The root of nfs is the head of the nfsnode list, it will be released later,
3026beacf11bSopenharmony_ci   * so now skip checking it.
3027beacf11bSopenharmony_ci   */
3028beacf11bSopenharmony_ci  if (nmp->nm_head == NULL)
3029beacf11bSopenharmony_ci    {
3030beacf11bSopenharmony_ci      error = ENODEV;
3031beacf11bSopenharmony_ci      goto errout_with_mutex;
3032beacf11bSopenharmony_ci    }
3033beacf11bSopenharmony_ci
3034beacf11bSopenharmony_ci  if (nmp->nm_head->n_next != NULL || nmp->nm_dir != NULL)
3035beacf11bSopenharmony_ci    {
3036beacf11bSopenharmony_ci      nfs_debug_error("There are open files: %p or directories: %p\n", nmp->nm_head, nmp->nm_dir);
3037beacf11bSopenharmony_ci
3038beacf11bSopenharmony_ci      /* This implementation currently only supports unmounting if there are
3039beacf11bSopenharmony_ci       * no open file references.
3040beacf11bSopenharmony_ci       */
3041beacf11bSopenharmony_ci
3042beacf11bSopenharmony_ci      error = EBUSY;
3043beacf11bSopenharmony_ci      goto errout_with_mutex;
3044beacf11bSopenharmony_ci    }
3045beacf11bSopenharmony_ci
3046beacf11bSopenharmony_ci  /* No open file... Umount the file system. */
3047beacf11bSopenharmony_ci
3048beacf11bSopenharmony_ci  error = rpcclnt_umount(nmp->nm_rpcclnt);
3049beacf11bSopenharmony_ci  if (error)
3050beacf11bSopenharmony_ci    {
3051beacf11bSopenharmony_ci      nfs_debug_error("rpcclnt_umount failed: %d\n", error);
3052beacf11bSopenharmony_ci      goto errout_with_mutex;
3053beacf11bSopenharmony_ci    }
3054beacf11bSopenharmony_ci
3055beacf11bSopenharmony_ci  /* Disconnect from the server */
3056beacf11bSopenharmony_ci
3057beacf11bSopenharmony_ci  rpcclnt_disconnect(nmp->nm_rpcclnt);
3058beacf11bSopenharmony_ci
3059beacf11bSopenharmony_ci  /* And free any allocated resources */
3060beacf11bSopenharmony_ci
3061beacf11bSopenharmony_ci  nfs_mux_release(nmp);
3062beacf11bSopenharmony_ci  (void)pthread_mutex_destroy(&nmp->nm_mux);
3063beacf11bSopenharmony_ci  free(nmp->nm_rpcclnt);
3064beacf11bSopenharmony_ci  nmp->nm_rpcclnt = NULL;
3065beacf11bSopenharmony_ci  free(nmp);
3066beacf11bSopenharmony_ci  nmp = NULL;
3067beacf11bSopenharmony_ci
3068beacf11bSopenharmony_ci  return -error;
3069beacf11bSopenharmony_ci
3070beacf11bSopenharmony_cierrout_with_mutex:
3071beacf11bSopenharmony_ci  nfs_mux_release(nmp);
3072beacf11bSopenharmony_ci  return -error;
3073beacf11bSopenharmony_ci}
3074beacf11bSopenharmony_ci
3075beacf11bSopenharmony_cistatic int nfs_check_timestamp(struct timespec *origin, struct timespec *new)
3076beacf11bSopenharmony_ci{
3077beacf11bSopenharmony_ci  return (origin->tv_sec == new->tv_sec) && (origin->tv_nsec == new->tv_nsec);
3078beacf11bSopenharmony_ci}
3079beacf11bSopenharmony_ci
3080beacf11bSopenharmony_cistatic int vfs_nfs_open(struct file *filep)
3081beacf11bSopenharmony_ci{
3082beacf11bSopenharmony_ci  int ret;
3083beacf11bSopenharmony_ci  struct timespec ts;
3084beacf11bSopenharmony_ci  struct rpc_call_fs attr_call;
3085beacf11bSopenharmony_ci  struct rpc_reply_getattr attr_reply;
3086beacf11bSopenharmony_ci  struct Vnode *node = filep->f_vnode;
3087beacf11bSopenharmony_ci  struct nfsnode *nfs_node = NULL;
3088beacf11bSopenharmony_ci  struct nfsmount *nmp = (struct nfsmount *)(node->originMount->data);
3089beacf11bSopenharmony_ci  struct file_handle parent_fhandle = {0};
3090beacf11bSopenharmony_ci
3091beacf11bSopenharmony_ci  nfs_mux_take(nmp);
3092beacf11bSopenharmony_ci  nfs_node = (struct nfsnode *)node->data;
3093beacf11bSopenharmony_ci  attr_call.fs.fsroot.length = txdr_unsigned(nfs_node->n_fhsize);
3094beacf11bSopenharmony_ci  memcpy_s(&(attr_call.fs.fsroot.handle), sizeof(nfsfh_t), &(nfs_node->n_fhandle), sizeof(nfsfh_t));
3095beacf11bSopenharmony_ci
3096beacf11bSopenharmony_ci  ret = nfs_request(nmp, NFSPROC_GETATTR, &attr_call,
3097beacf11bSopenharmony_ci      sizeof(struct file_handle), &attr_reply,
3098beacf11bSopenharmony_ci      sizeof(struct rpc_reply_getattr));
3099beacf11bSopenharmony_ci  if (ret != OK)
3100beacf11bSopenharmony_ci    {
3101beacf11bSopenharmony_ci      if (ret == NFSERR_STALE)
3102beacf11bSopenharmony_ci      {
3103beacf11bSopenharmony_ci        /* If the file handle is stale, update it */
3104beacf11bSopenharmony_ci        OsFileCacheRemove(&(node->mapping));
3105beacf11bSopenharmony_ci        parent_fhandle.length = ((struct nfsnode *)node->parent->data)->n_fhsize;
3106beacf11bSopenharmony_ci        memcpy_s(&(parent_fhandle.handle), parent_fhandle.length,
3107beacf11bSopenharmony_ci            &(((struct nfsnode *)node->parent->data)->n_fhandle),
3108beacf11bSopenharmony_ci            ((struct nfsnode *)node->parent->data)->n_fhsize);
3109beacf11bSopenharmony_ci        ret = nfs_fileupdate(nmp, nfs_node->n_name, &parent_fhandle, nfs_node);
3110beacf11bSopenharmony_ci      }
3111beacf11bSopenharmony_ci      nfs_mux_release(nmp);
3112beacf11bSopenharmony_ci      return ret;
3113beacf11bSopenharmony_ci    }
3114beacf11bSopenharmony_ci
3115beacf11bSopenharmony_ci  /* Extract time values as timestamp */
3116beacf11bSopenharmony_ci
3117beacf11bSopenharmony_ci  fxdr_nfsv3time(&attr_reply.attr.fa_mtime, &ts);
3118beacf11bSopenharmony_ci  if (!nfs_check_timestamp(&(nfs_node->n_timestamp), &ts))
3119beacf11bSopenharmony_ci    {
3120beacf11bSopenharmony_ci      OsFileCacheRemove(&(node->mapping));
3121beacf11bSopenharmony_ci      nfs_node->n_timestamp.tv_sec = ts.tv_sec;
3122beacf11bSopenharmony_ci      nfs_node->n_timestamp.tv_nsec = ts.tv_nsec;
3123beacf11bSopenharmony_ci    }
3124beacf11bSopenharmony_ci
3125beacf11bSopenharmony_ci  nfs_mux_release(nmp);
3126beacf11bSopenharmony_ci
3127beacf11bSopenharmony_ci  return OK;
3128beacf11bSopenharmony_ci}
3129beacf11bSopenharmony_ci
3130beacf11bSopenharmony_cistruct MountOps nfs_mount_operations =
3131beacf11bSopenharmony_ci{
3132beacf11bSopenharmony_ci  .Mount = vfs_nfs_mount,
3133beacf11bSopenharmony_ci  .Unmount = vfs_nfs_unmount,
3134beacf11bSopenharmony_ci  .Statfs= vfs_nfs_statfs,
3135beacf11bSopenharmony_ci};
3136beacf11bSopenharmony_ci
3137beacf11bSopenharmony_cistruct VnodeOps nfs_vops =
3138beacf11bSopenharmony_ci{
3139beacf11bSopenharmony_ci  .Lookup = vfs_nfs_lookup,
3140beacf11bSopenharmony_ci  .Getattr = vfs_nfs_stat,
3141beacf11bSopenharmony_ci  .Opendir = vfs_nfs_opendir,
3142beacf11bSopenharmony_ci  .Readdir = vfs_nfs_readdir,
3143beacf11bSopenharmony_ci  .Rename = vfs_nfs_rename,
3144beacf11bSopenharmony_ci  .Mkdir = vfs_nfs_mkdir,
3145beacf11bSopenharmony_ci  .Create = vfs_nfs_create,
3146beacf11bSopenharmony_ci  .ReadPage = vfs_nfs_readpage,
3147beacf11bSopenharmony_ci  .WritePage = vfs_nfs_writepage,
3148beacf11bSopenharmony_ci  .Unlink =  vfs_nfs_unlink,
3149beacf11bSopenharmony_ci  .Rmdir = vfs_nfs_rmdir,
3150beacf11bSopenharmony_ci  .Reclaim = vfs_nfs_reclaim,
3151beacf11bSopenharmony_ci  .Closedir = vfs_nfs_closedir,
3152beacf11bSopenharmony_ci  .Close = vfs_nfs_close,
3153beacf11bSopenharmony_ci  .Rewinddir = vfs_nfs_rewinddir,
3154beacf11bSopenharmony_ci  .Truncate = vfs_nfs_truncate,
3155beacf11bSopenharmony_ci};
3156beacf11bSopenharmony_ci
3157beacf11bSopenharmony_cistruct file_operations_vfs nfs_fops =
3158beacf11bSopenharmony_ci{
3159beacf11bSopenharmony_ci  .open = vfs_nfs_open,
3160beacf11bSopenharmony_ci  .seek = vfs_nfs_seek,
3161beacf11bSopenharmony_ci  .write = vfs_nfs_write,
3162beacf11bSopenharmony_ci  .read = vfs_nfs_read,
3163beacf11bSopenharmony_ci  .mmap = OsVfsFileMmap,
3164beacf11bSopenharmony_ci  .close = vfs_nfs_close_file,
3165beacf11bSopenharmony_ci};
3166beacf11bSopenharmony_ciFSMAP_ENTRY(nfs_fsmap, "nfs", nfs_mount_operations, FALSE, FALSE);
3167beacf11bSopenharmony_ci#endif
3168