📄 nfslib.c
字号:
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 ) {#ifdef _WRS_VXWORKS_5_X FAST RPC_STATICS *pRPCModList = pTcb->pRPCModList;#else FAST RPC_STATICS *pRPCModList = pTcb->pLcb->pRPCModList;#endif /* _WRS_VXWORKS_5_X */ if (pRPCModList != NULL) { nfsClientCacheCleanUp (pRPCModList->nfsClientCache); if (pRPCModList->nfsClientCache != NULL) { KHEAP_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 *) KHEAP_ALLOC(sizeof (NFS_MODULE_STATICS)); if (taskRpcStatics->nfsClientCache == NULL) return (ERROR); bzero ((char *)taskRpcStatics->nfsClientCache, sizeof (NFS_MODULE_STATICS)); } 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** This routine is used to set up structures that are part of a valid* NFS client cache. If successful, the client cache is marked as valid.*/LOCAL STATUS nfsClientCacheSetUp ( FAST NFS_MODULE_STATICS *ms, /* pointer to client cache */ char * host, /* server's host name */ u_int prognum, /* RPC program number */ u_int versnum /* RPC version number */ ) { int hp; /* host's inet address */ struct sockaddr_in server_addr; struct timeval timeout; int optval; /* check if cached client is appropriate */ if (ms->valid && ms->oldprognum == prognum && ms->oldversnum == versnum && strcmp (ms->oldhost, host) == 0 && ms->authCount == nfsAuthCount) { return (OK); /* reuse old client */ } /* get rid of any old client and create new one */ nfsClientCacheCleanUp (ms); if ((hp = hostGetByName (host)) == ERROR) return (ERROR); timeout.tv_sec = nfsReXmitSec; timeout.tv_usec = nfsReXmitUSec; server_addr.sin_addr.s_addr = hp; server_addr.sin_family = AF_INET; server_addr.sin_port = htons (0); ms->socket = RPC_ANYSOCK; if ((ms->client = clntudp_create(&server_addr, prognum, versnum, timeout, &ms->socket)) == NULL) { server_addr.sin_port = htons (NFS_PORT); ms->client = clntudp_create (&server_addr, prognum, versnum, timeout, &ms->socket); if (ms->client == NULL) return (ERROR); } optval = nfsSockBufSize; if ((setsockopt (ms->socket, SOL_SOCKET, SO_SNDBUF, (char *)&optval, sizeof (optval)) == ERROR) || (setsockopt (ms->socket, SOL_SOCKET, SO_RCVBUF, (char *)&optval, sizeof (optval)) == ERROR)) { nfsClientCacheCleanUp (ms); return (ERROR); } ms->client->cl_auth = authunix_create (nfsAuthUnix.machname, nfsAuthUnix.uid, nfsAuthUnix.gid, nfsAuthUnix.len, nfsAuthUnix.aup_gids); if (ms->client->cl_auth == NULL) { nfsClientCacheCleanUp (ms); errnoSet (S_nfsLib_NFS_AUTH_UNIX_FAILED); return (ERROR); } ms->oldprognum = prognum; ms->oldversnum = versnum; ms->authCount = nfsAuthCount; (void) strcpy (ms->oldhost, host); ms->valid = TRUE; return (OK); }/********************************************************************************* nfsClientCall - make an NFS request to the server using RPC** This is the routine which does the actual RPC call to the server.* All NFS routines which communicate with the file server use this routine.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -