📄 nfsdlib.c
字号:
nfsstat authorized; /* request is authorized if == NFS_OK*/ /* Initialize task for VxWorks RPC work */ rpcTaskInit (); transp = svcudp_create(-1); /* Work loop is repeated until catastrophic error encountered */ FOREVER { /* Get the next message */ if (msgQReceive (nfsRequestQ, (char *) &request, sizeof(request), WAIT_FOREVER) == ERROR) { perror ("NFS server aborted abnormally"); return; } /* Break down the incoming message */ local = request.routine; argument = request.argument; xdr_argument = request.xdrArg; xdr_result = request.xdrResult; addr = &request.sockAddr; xid = request.xid; sock = request.socket; /* Create a new RPC transport to reply. Need to do this as * next incoming client request will alter xid field of old * transport, and replies won't match the correct request. */ transp->xp_sock = sock; ((struct svcudp_data *) transp->xp_p2)->su_xid = xid; transp->xp_raddr = *addr; memset (&transp->xp_verf, 0, sizeof(transp->xp_verf)); transp->xp_addrlen = sizeof (transp->xp_raddr); /* Authenticate the request, then call the correct NFS routine */ if (nfsdAuthHook) { authorized = (*nfsdAuthHook) (NFS_PROGRAM, NFS_VERSION, request.procNum, request.sockAddr, argument); } else authorized = NFS_OK; if (authorized != NFS_OK) { result = KHEAP_ALLOC(sizeof (nfsstat)); if (NULL != result) { bzero ((char *)result, sizeof (nfsstat)); } *((nfsstat *) result) = authorized; } else result = (char *) (*local)(argument); /* Send the result */ if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { svcerr_systemerr(transp); } /* Free any space used by RPC/XDR */ if (!svc_freeargs(transp, xdr_argument, argument)) { perror ("unable to free arguments for NFS server"); return; } /* Free space allocated when request was queued up */ KHEAP_FREE((char *)result); KHEAP_FREE((char *)argument); /* Unfortunately, there's no way to tell svc_destroy() to not close * the socket. So, set the socket to -1. svc_destroy() doesn't * check the value of the close() anyway. If errno is set to * S_iosLib_INVALID_FILE_DESCRIPTOR due to the close (-1), reset it * to OK. (svc_destroy() returns NULL, so there's no way to check * its return value.) */ } transp->xp_sock = -1; svc_destroy (transp); if (errno == S_iosLib_INVALID_FILE_DESCRIPTOR) errno = OK; }/******************************************************************************** nfsd - NFS daemon process** Used as the entrypoint to a task spawned from nfsdInit(). This task* sets up the NFS RPC service, and calls svc_run(), which should never return.* nfsdRequestEnqueue() is called from the svc_run() call.** This routine is not declared LOCAL only because the symbol for its entry* point should be displayed by i().* * NOTE: Some of this routine was generated by rpcgen.* * RETURNS: Never returns unless an error is encountered.* * SEE ALSO: nfsdRequestEnqueue().* * NOMANUAL*/void nfsd ( void ) { register SVCXPRT * transp; /* RPC transport */ int sock; /* NFS socket */ struct sockaddr_in addr; /* Address of NFS (port 2049 */ int optVal = NFS_MAXDATA * 2 + sizeof (struct rpc_msg) * 2; /* XXX - too much space is wasted here */ /* Initialize the task to use VxWorks RPC code */ rpcTaskInit(); /* Create NFS socket and bind it to correct address */ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Set up the socket address */ addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons (NFS_PORT); bzero (addr.sin_zero, sizeof (addr.sin_zero)); if (bind (sock, (struct sockaddr *) &addr, sizeof (addr)) == ERROR) { perror ("Could not bind to NFS port address"); return; } /* Unset any previous NFS services */ pmap_unset(NFS_PROGRAM, NFS_VERSION); /* Set socket buffer large enough to accommodate max NFS message */ if ((setsockopt (sock, SOL_SOCKET, SO_SNDBUF, (char *)&optVal, sizeof (optVal)) == ERROR) || (setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *)&optVal, sizeof (optVal)) == ERROR)) return; /* Create RPC transport */ transp = svcudp_create(sock); if (transp == NULL) { fprintf(stderr, "cannot create udp service."); exit(1); } /* Register NFS */ if (!svc_register(transp, NFS_PROGRAM, NFS_VERSION, nfsdRequestEnqueue, IPPROTO_UDP)) { perror ("unable to register (NFS_PROGRAM, NFS_VERSION, udp).\n"); return; } /* Start the RPC service, and never come back */ svc_run(); /* Should never get to this point */ perror ("NFS svc_run returned"); }/******************************************************************************** nfsproc_null_2 - do nothing** RETURNS: A pointer to malloced spaced that contains no information.** NOMANUAL*/void * nfsproc_null_2 ( void ) { nfsdServerStatus.nullCalls++; return ((void *) KHEAP_ALLOC(0)); }/******************************************************************************** nfsproc_getattr_2 - get file attributes** If the reply status is NFS_OK, then the reply attributes contains the* attributes for the file given by the input fhandle.* * RETURNS: A pointer to an attrstat struct.** NOMANUAL*/attrstat * nfsproc_getattr_2 ( nfs_fh * fh /* File handle to get attributes of */ ) { attrstat * retVal = KHEAP_ALLOC(sizeof (attrstat)); /* Struct to fill in */ nfsdServerStatus.getattrCalls++; nfsdFhNtoh ((NFS_FILE_HANDLE *) fh); if (retVal == NULL) return (NULL); /* Get the attributes for the file */ if (nfsdFattrGet ((NFS_FILE_HANDLE *) fh, &retVal->attrstat_u.attributes) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } else retVal->status = NFS_OK; return (retVal); }/******************************************************************************** nfsproc_setattr_2 - set the attributes for a file* * The "attr" argument contains fields which are either -1 or are* the new value for the attributes of "file". If the reply status is* NFS_OK, then the reply attributes have the attributes of the file* after the "SETATTR" operation has completed.* * Notes: The use of -1 to indicate an unused field in "attributes" is* changed in the next version of the protocol.** NOMANUAL*/attrstat * nfsproc_setattr_2 ( sattrargs * attr /* Attributes to change */ ) { attrstat * retVal = KHEAP_ALLOC(sizeof (attrstat));/* Return info */ char * fileName; /* Name of the file being changed */ int fd; /* File descriptor for file being changed */ struct utimbuf timeBuf; /* New time settings for file */ if (retVal == NULL) return (NULL); if ((fileName = (char *) alloca (nfsMaxPath)) == NULL) return (NULL); nfsdServerStatus.setattrCalls++; nfsdFhNtoh ((NFS_FILE_HANDLE *) &attr->file); /* Make sure the file system is writeable */ if (nfsdFsReadOnly((NFS_FILE_HANDLE *) &attr->file)) { retVal->status = NFSERR_ACCES; return (retVal); } if (nfsdFhToName ((NFS_FILE_HANDLE *) &attr->file, fileName) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } if (attr->attributes.mode != -1) /* Currently don't have any way to set the mode */ ; if (attr->attributes.uid != -1) /* Currently don't have any way to set the uid */ ; if (attr->attributes.gid != -1) /* Currently don't have any way to set the gid */ ; if (attr->attributes.size != -1) { /* Set the size of the file using FIOTRUNC ioctl, as VxWorks * doesn't have ftruncate() */ fd = open (fileName, O_RDWR, 0666); if (fd != ERROR) { if (ioctl (fd, FIOTRUNC, attr->attributes.size) == ERROR) { retVal->status = nfsdErrToNfs (errno); close (fd); return (retVal); } else close (fd); } else { retVal->status = nfsdErrToNfs (errno); close (fd); return (retVal); } } /* Set file time. * * As there's no way to set only one of these fields, if only one * is set, set the other one to the same value. */ if (attr->attributes.atime.seconds != -1) timeBuf.modtime = timeBuf.actime = attr->attributes.atime.seconds; if (attr->attributes.mtime.seconds != -1) { timeBuf.modtime = attr->attributes.mtime.seconds; if (attr->attributes.atime.seconds == -1) timeBuf.actime = timeBuf.modtime; } if ((attr->attributes.atime.seconds != -1) || (attr->attributes.mtime.seconds != -1)) if (utime (fileName, &timeBuf) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } /* Get the status information for the file to return */ if (nfsdFattrGet ((NFS_FILE_HANDLE *) &attr->file, &retVal->attrstat_u.attributes) != OK) { retVal->status = nfsdErrToNfs (errno); return (retVal); } retVal->status = NFS_OK; return (retVal); }/******************************************************************************** nfsproc_root_2 - obsolete* * Obsolete. This procedure is no longer used because finding the root* file handle of a filesystem requires moving pathnames between client* and server. To do this right, we would have to define a network* standard representation of pathnames. Instead, the function of* looking up the root file handle is done by the MNTPROC_MNT procedure.* * RETURNS: A pointer to no information.** NOMANUAL*/void * nfsproc_root_2 ( void ) { nfsdServerStatus.setattrCalls++; return ((void *) KHEAP_ALLOC(0)); }/******************************************************************************** nfsproc_lookup_2 -* * If the reply "status" is NFS_OK, then the reply "file" and reply* "attributes" are the file handle and attributes for the file "name"* in the directory given by "dir" in the argument.* * RETURNS: A pointer to a diropres struct, or NULL.** NOMANUAL*/diropres * nfsproc_lookup_2 ( diropargs * dir /* The direcory and file to look up */ ) { diropres * retVal = KHEAP_ALLOC(sizeof (diropres)); /* return status */ if (retVal == NULL) return (NULL); nfsdServerStatus.lookupCalls++; nfsdFhNtoh ((NFS_FILE_HANDLE *) &dir->dir); /* Build file handle for new file */ if (nfsdFhCreate ((NFS_FILE_HANDLE *) &dir->dir, dir->name, (NFS_FILE_HANDLE *) &retVal->diropres_u.diropres.file) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } /* Get the attributes for the newly created file handle */ if (nfsdFattrGet ((NFS_FILE_HANDLE *) &retVal->diropres_u.diropres.file, &retVal->diropres_u.diropres.attributes) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } retVal->status = NFS_OK; nfsdFhHton ((NFS_FILE_HANDLE *) &retVal->diropres_u.diropres.file); return (retVal); }/******************************************************************************** nfsproc_readlink_2 - read from a symbolic link* * VxWorks does not support symbolic links.* * RETURNS: A pointer to an EOPNOTSUPP error.** NOMANUAL*/readlinkres * nfsproc_readlink_2 ( nfs_fh * fh /* File handle to read */ ) { readlinkres * retVal = KHEAP_ALLOC(sizeof (retVal->status)); if (retVal == NULL) return (NULL); /* Increment statistics */ nfsdServerStatus.readlinkCalls++; /* symbolic links not supported */ retVal->status = EOPNOTSUPP; return (retVal); }/******************************************************************************** nfsproc_read_2 - read data from a file* * Returns up to "count" bytes of "data" from the file given by "file",* starting at "offset" bytes from the beginning of the file. The first* byte of the file is at offset zero. The file attributes after the* read takes place are returned in "attributes".* * Notes: The argument "totalcount" is unused, and is removed in the* next protocol revision.** NOMANUAL*/readres * nfsproc_read_2 ( readargs * readFile /* File, offset, and count information */ ) { char * fileName; /* Name of the file being read */ readres * retVal = KHEAP_ALLOC(sizeof (readres) + readFile->count); /* Return information, including read data */ char * readData; /* Address of read data in retVal */ int fd; /* File descriptor for file being read */ int nBytes; /* Number of bytes actually read */ if (retVal == NULL) return (NULL); if ((fileName = (char *) alloca (nfsMaxPath)) == NULL) return (NULL); /* Increment statistics */ nfsdServerStatus.readCalls++; /* set readData to point to the correct position in the return value */ readData = (char *) retVal + sizeof (readres); nfsdFhNtoh ((NFS_FILE_HANDLE *) &readFile->file); if (nfsdFhToName ((NFS_FILE_HANDLE *) &readFile->file, fileName) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } if ((fd = open (fileName, O_RDONLY, 0)) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } if (lseek (fd, readFile->offset, SEEK_SET) == ERROR) { retVal->status = nfsdErrToNfs (errno); close (fd); return (retVal); } if ((nBytes = read (fd, readData, readFile->count)) == ERROR) { retVal->status = nfsdErrToNfs (errno); close (fd); return (retVal); } else { retVal->readres_u.reply.data.data_val = readData; retVal->readres_u.reply.data.data_len = nBytes; } if (close (fd) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } if (nfsdFattrGet ((NFS_FILE_HANDLE *) &readFile->file, &retVal->readres_u.reply.attributes) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } retVal->status = NFS_OK; return (retVal); }/******************************************************************************** nfsproc_writecache_2 - unused*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -