📄 nfslib.c
字号:
writeArgs.data.data_val = data + nTotalWrite; writeArgs.offset = offset + nTotalWrite; bzero ((char *) &writeResult, sizeof (attrstat)); if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_WRITE, xdr_writeargs, (char *) &writeArgs, xdr_attrstat, (char *) &writeResult) == ERROR) { return (ERROR); /* XXX if some writes have been done and there was an error, * nTotalWrite should be returned */ } if (writeResult.status != NFS_OK) { nfsErrnoSet (writeResult.status); return (ERROR); } nTotalWrite += nWrite; } bcopy ((char *) &writeResult.attrstat_u.attributes, (char *) pNewAttr, sizeof (fattr)); /* if nfs write returned ok, then all bytes were written */ return (count); }/********************************************************************************* nfsFileRead - read from a file** Reads as many bytes as are requested if that many bytes are left before* the end of file.** RETURNS: number of characters read or ERROR** NOMANUAL*/int nfsFileRead ( char * hostName, nfs_fh * pHandle, /* file handle of file being read */ unsigned offset, /* start at offset bytes from beg. of file */ unsigned count, /* number bytes to read up to */ char * buf, /* buffer that data is read into */ fattr * pNewAttr /* arguments returned from server */ ) { FAST unsigned nRead = 0; /* number of bytes read in one read */ FAST unsigned nTotalRead = 0; /* bytes read in all reads together */ readargs readArgs; /* arguments to pass to nfs server */ readres readReply; if (nfsInit () != OK) return (ERROR); bzero ((char *) &readArgs, sizeof (readArgs)); bcopy ((char *) pHandle, (char *) &readArgs.file, sizeof (nfs_fh)); while (nTotalRead < count) { if (count - nTotalRead > nfsMaxMsgLen) readArgs.count = nfsMaxMsgLen; else readArgs.count = count - nTotalRead; readArgs.offset = offset + nTotalRead; bzero ((char *) &readReply, sizeof (readReply)); /* make xdr buffer point to caller's buffer */ readReply.readres_u.reply.data.data_val = buf + nTotalRead; if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READ, xdr_readargs, (char *) &readArgs, xdr_readres, (char *) &readReply) == ERROR) { return (ERROR); } if (readReply.status != NFS_OK) { nfsErrnoSet (readReply.status); return (ERROR); } /* check for end of file (data_len == 0) */ if ((nRead = readReply.readres_u.reply.data.data_len) == 0) break; /* update attributes */ bcopy ((char *) &(readReply.readres_u.reply.attributes), (char *) pNewAttr, sizeof (fattr)); nTotalRead += nRead; } /* while not all bytes requested have been read */ return (nTotalRead); }/********************************************************************************* nfsLinkGet - gets name of real file from a symbolic link** RETURNS: OK or ERROR*/LOCAL STATUS nfsLinkGet ( char * hostName, nfs_fh * pHandle, /* file handle of file being read */ nfspath realPath /* the actual pathname gets returned here */ ) { readlinkres pathStatus; if (nfsInit () != OK) return (ERROR); bzero ((char *) &pathStatus, sizeof (readlinkres)); /* make xdr buffer point to caller's buffer */ pathStatus.readlinkres_u.data = realPath; if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READLINK, xdr_nfs_fh, (char *) pHandle, xdr_readlinkres, (char *) &pathStatus) == ERROR) { return (ERROR); } if (pathStatus.status != NFS_OK) { nfsErrnoSet (pathStatus.status); return (ERROR); } return (OK); }#if 0/********************************************************************************* nfsDirRead - read entries from a directory** RETURNS: OK or ERROR*/LOCAL STATUS nfsDirRead ( char * hostName, nfs_fh * pDirHandle, nfscookie cookie, /* hand this cookie to the server. The cookie * marks a place in the directory where entries * are to be read from */ unsigned count, /* number of bytes that nfs may return */ readdirres *pReadDirRes /* return the results of directory read here */ ) { readdirargs readDirArgs; if (nfsInit () != OK) return (ERROR); bzero ((char *) &readDirArgs, sizeof (readdirargs)); bcopy ((char *) pDirHandle, (char *) &readDirArgs.dir, sizeof (nfs_fh)); bcopy (cookie, readDirArgs.cookie, sizeof (nfscookie)); readDirArgs.count = count; bzero ((char *) pReadDirRes, sizeof (*pReadDirRes)); if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READDIR, xdr_readdirargs, (char *) &readDirArgs, xdr_readdirres, (char *) pReadDirRes) == ERROR) { return (ERROR); } if (pReadDirRes->status != NFS_OK) { nfsErrnoSet (pReadDirRes->status); return (ERROR); } /* normally, the readdirres structure would be freed up here, but * the calling routine needs its information, so the calling routine * must call clntudp_freeres after calling nfsDirRead */ return (OK); }/********************************************************************************* nfsDirResFree - free the rcp readdirres result structure** RETURNS: TRUE if successful, FALSE if error*/LOCAL BOOL nfsDirResFree ( readdirres *pReadDirRes ) { return (clntudp_freeres (taskRpcStatics->nfsClientCache->client, xdr_readdirres, (caddr_t) pReadDirRes)); }#endif/********************************************************************************* nfsDirReadOne - read one directory entry** Read one directory entry on the host from the directory represented by* the file handle *pDirHandle. Update the DIR structure that is passed* in and pointed to by pDir.** NOTE:* There is actually no way to tell the server we want only one entry.* We only want one entry, but we have to provide a buffer for the maximum* length filename, where the buffer size is specified in the "count" param* to nfsDirRead. The server will return as many entries as will fit in* this buffer. We will return the first entry to the caller and throw* away the rest. A subsequent call with the cookie of the previous* entry will acquire the next entry, even though it may have been* sent in previous call.** In the future, we could cache several entries at a time and just return* them to the caller, one at a time.** RETURNS: OK, or ERROR if dir read fails,* returns ERROR but errno unchanged if EOF** NOMANUAL*/STATUS nfsDirReadOne ( char * hostName, /* host name */ nfs_fh * pDirHandle, /* file handle of directory */ DIR * pDir /* ptr to DIR structure, return values here */ ) { readdirres readRes; readdirargs readDirArgs; bzero ((char *) &readRes, sizeof (readRes)); if (nfsInit () != OK) return (ERROR); bzero ((char *) &readDirArgs, sizeof (readdirargs)); bcopy ((char *) pDirHandle, (char *) &readDirArgs.dir, sizeof (nfs_fh)); bcopy ((char *) &pDir->dd_cookie, readDirArgs.cookie, sizeof (nfscookie)); /* readDirArgs.count = sizeof (struct readdirres) + sizeof (struct entry) + NAME_MAX; */ /* For reasons yet unknown to me, the HP server expects the value of count to be AT LEAST 512 in order to successfully read directory files mounted from HP. Sun server does not have this limitation. */ readDirArgs.count = READDIR_MAXLEN; if (nfsClientCall (hostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_READDIR, xdr_readdirargs, (char *) &readDirArgs, xdr_readdirres, (char *) &readRes) == ERROR) { return (ERROR); } if (readRes.status != NFS_OK) { nfsErrnoSet (readRes.status); return (ERROR); } if (readRes.readdirres_u.reply.entries == NULL && readRes.readdirres_u.reply.eof) { /* No entries were returned - must be end of file. * (Note that xdr_readdirresOne hack discarded EOF flag.) * Return ERROR, but don't alter errno because there is no real error. * (Thank you POSIX for this lovely, clear construct.) */ /* * Need to set errno to OK, otherwise ls will print out an error * message at the end of every directory listing. */ errnoSet (OK); return (ERROR); } strcpy (pDir->dd_dirent.d_name, readRes.readdirres_u.reply.entries[0].name); /* update caller's cookie */ bcopy (readRes.readdirres_u.reply.entries[0].cookie, (char *) &pDir->dd_cookie, sizeof (nfscookie)); /* free the memory used by RPC */ clnt_freeres (taskRpcStatics->nfsClientCache->client, xdr_readdirres, (caddr_t) &readRes); return (OK); }/********************************************************************************* nfsFileAttrGet - get file attributes and put them in a stat structure** NOMANUAL*/void nfsFileAttrGet ( FAST fattr * pFattr, /* ptr to nfs file attributes */ FAST struct stat * pStat /* ptr to stat struct, return attrs here */ ) { /* * INTERNAL: block information is kept in the fattr * structure, but we decided not to hold it in the * stat structure. It could be added later. */ pStat->st_ino = (ULONG) pFattr->fileid; pStat->st_mode = pFattr->mode; pStat->st_nlink = pFattr->nlink; pStat->st_uid = pFattr->uid; pStat->st_gid = pFattr->gid; pStat->st_rdev = 0; /* unused */ pStat->st_size = pFattr->size; pStat->st_atime = pFattr->atime.seconds; pStat->st_mtime = pFattr->mtime.seconds; pStat->st_ctime = pFattr->ctime.seconds; pStat->st_blksize = 0; pStat->st_blocks = 0; }/******************************************************************************** nfsFsAttrGet - get file system attributes across NFS** This routine does an FSTATFS across NFS.** NOMANUAL*/STATUS nfsFsAttrGet ( char* pHostName, /* host name */ nfs_fh* pDirHandle, /* file handle of directory */ struct statfs* pArg /* return value here */ ) { int status; statfsres retStat; status = nfsClientCall (pHostName, NFS_PROGRAM, NFS_VERSION, NFSPROC_STATFS, xdr_fhandle, (char *)pDirHandle, xdr_statfsres, (char *)&retStat); if (retStat.status != NFS_OK) { nfsErrnoSet (retStat.status); return (ERROR); } pArg->f_type = 0; pArg->f_bsize = retStat.statfsres_u.reply.bsize; pArg->f_blocks = retStat.statfsres_u.reply.blocks; pArg->f_bfree = retStat.statfsres_u.reply.bfree; pArg->f_bavail = retStat.statfsres_u.reply.bavail; /* The following are undefined for NFS under vxWorks and * so are set to 0. */ pArg->f_files = 0; /* total file nodes in file system */ pArg->f_ffree = 0; /* free file nodes in fs */ clnt_freeres (taskRpcStatics->nfsClientCache->client, xdr_statfsres, (caddr_t)&retStat); return (OK); }/********************************************************************************* nfsDeleteHook - cleanup NFS data structures*/LOCAL void nfsDeleteHook ( WIND_TCB *pTcb ) { FAST RPC_STATICS *pRPCModList = pTcb->pRPCModList; if (pRPCModList != NULL) { nfsClientCacheCleanUp (pRPCModList->nfsClientCache); if (pRPCModList->nfsClientCache != NULL) { free ((char *) pRPCModList->nfsClientCache); pRPCModList->nfsClientCache = NULL; } } }/********************************************************************************* nfsInit - initialize NFS** nfsInit must be called by a task before it uses NFS.* It is okay to call this routine more than once.** RETURNS: OK or ERROR** NOMANUAL*/LOCAL STATUS nfsInit (void) { /* make sure rpc is initialized for this task */ if (rpcTaskInit () == ERROR) return (ERROR); /* if first nfs use by this task, initialize nfs stuff for this task */ if (taskRpcStatics->nfsClientCache == NULL) { /* if this the very first use of NFS in the system, add nfsDeleteHook */ if (!nfsInstalled) { if (taskDeleteHookAdd ((FUNCPTR)nfsDeleteHook) == ERROR) return (ERROR); nfsInstalled = TRUE; } /* allocate nfs specific stuff for this task */ taskRpcStatics->nfsClientCache = (NFS_MODULE_STATICS *) calloc (1, sizeof (NFS_MODULE_STATICS)); if (taskRpcStatics->nfsClientCache == NULL) return (ERROR); } return (OK); }/********************************************************************************* nfsClientCacheCleanUp - clean up the NFS client cache** This routine is used to free up structures that are part of a valid* NFS client cache. The client cache is marked as invalid.*/LOCAL void nfsClientCacheCleanUp ( FAST NFS_MODULE_STATICS *pClientCache /* pointer to client cache */ ) { if ((pClientCache != NULL) && (pClientCache->valid)) { pClientCache->valid = FALSE; /* close client socket */ if (pClientCache->socket > 0) {#if 0 close (pClientCache->socket);#endif pClientCache->socket = NONE; } pClientCache->oldhost[0] = EOS; /* destroy authorization and client */ if (pClientCache->client != NULL) { if (pClientCache->client->cl_auth != NULL) { auth_destroy (pClientCache->client->cl_auth); pClientCache->client->cl_auth = NULL; } clnt_destroy (pClientCache->client); pClientCache->client = NULL; } } }/********************************************************************************* nfsClientCacheSetUp - set up the NFS client cache
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -