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