?? nfsdrv.c
字號:
char * fullName, /* full file or directory name */ int perm /* 4:read 2:write 1:execute */ ) { diropres dirResult; /* directory info returned via nfs */ nfs_fh dirHandle; /* file's directory file handle */ int retVal; /* return from nfsLookUpByName */ /* NFS permissions */ int nfsPerms; /* permissions of the opened file */ char machineName [AUTH_UNIX_FIELD_LEN]; int uid; /* user ID */ int gid; /* group ID */ int nGids; /* number of groups */ int gids [MAX_GRPS]; /* array of group IDs */ BOOL sameUid = FALSE; /* set to TRUE if users match */ BOOL sameGid = FALSE; /* set to TRUE if groups match */ bzero ((char *) &dirResult, sizeof (dirResult)); bzero ((char *) &dirHandle, sizeof (dirHandle)); bzero ((char *) &gids, sizeof (int) * MAX_GRPS); if ((retVal = nfsLookUpByName (pNfsDev->host, fullName, &pNfsDev->fileHandle, &dirResult, &dirHandle)) != OK) return (retVal); /* ERROR/FOLLOW_LINK. errno has S_nfsLib prefix */ nfsPerms = dirResult.diropres_u.diropres.attributes.mode; nfsAuthUnixGet (machineName, &uid, &gid, &nGids, gids); sameUid = (uid == dirResult.diropres_u.diropres.attributes.uid ? TRUE : FALSE); if (gid == dirResult.diropres_u.diropres.attributes.gid) sameGid = TRUE; else while (nGids) if (gids [--nGids] == dirResult.diropres_u.diropres.attributes.gid) { sameGid = TRUE; break; } /* Check "other" permissions */ if (!sameGid && !sameUid && ((nfsPerms & perm) == perm)) goto permission_ok; /* check group permissions */ else if (sameGid && ((nfsPerms & (perm << 3)) == (perm << 3))) goto permission_ok; /* check user permissions */ else if (sameUid && ((nfsPerms & (perm << 6)) == (perm << 6))) goto permission_ok; else { errno = S_nfsDrv_PERMISSION_DENIED; return (ERROR); /* caller should set EACCES to errno */ }permission_ok: return (OK); }/********************************************************************************* nfsOpen - open an NFS file** This routine opens the remote file.* Called only by the I/O system.** RETURNS: pointer to open network file descriptor || FOLLOW_LINK || ERROR*/LOCAL int nfsOpen ( NFS_DEV * pNfsDev, /* pointer to nfs device */ char * fileName, /* remote file or directory name to open */ int flags, /* O_RDONLY, O_WRONLY, or O_RDWR and O_CREAT */ int mode /* UNIX chmod style */ ) { int status = OK; char *fullName; /* full file or directory name */ FAST NFS_FD * nfsFd; diropres dirResult; /* directory info returned via nfs */ int retVal; nfs_fh dirHandle; /* file's directory file handle */ int openMode = flags & FD_MODE; /* mode to open file with */ /* (O_RDONLY, O_WRONLY, or O_RDWR */ /* NFS permissions */ int filePermissions; /* permissions of the opened file */ int requestPerms = 0; /* requested file permissions */ char machineName [AUTH_UNIX_FIELD_LEN]; int uid; /* user ID */ int gid; /* group ID */ int nGids; /* number of groups */ int gids [MAX_GRPS]; /* array of group IDs */ BOOL correctPerms = FALSE; /* set to TRUE if perms match */ BOOL sameUid = FALSE; /* set to TRUE if users match */ BOOL sameGid = FALSE; /* set to TRUE if groups match */ if ((openMode != O_RDONLY) && (openMode != O_WRONLY) && (openMode != O_RDWR)) { errnoSet (S_nfsDrv_BAD_FLAG_MODE); return (ERROR); } if (strlen (fileName) >= nfsMaxPath) { errnoSet (S_nfsLib_NFSERR_NAMETOOLONG); return (ERROR); } if ((fullName = (char *) alloca (nfsMaxPath)) == NULL) return (ERROR); if (fileName [0] == EOS) { if (flags & O_CREAT) { errnoSet (S_nfsDrv_CREATE_NO_FILE_NAME); return (ERROR); } (void) strcpy (fullName, "."); } else (void) strcpy (fullName, fileName); /* truncate file - check the file has write-permission */ if (flags & O_TRUNC) { int err; #define READ_PERMISSION 2 if ((err = nfsChkFilePerms (pNfsDev, fullName, READ_PERMISSION)) == FOLLOW_LINK) return (FOLLOW_LINK); else if (err == ERROR && errno == S_nfsDrv_PERMISSION_DENIED) return (ERROR); /* i.e. don't return if NFSERR_NOENT */ else if (err == OK) { /* the file has write-permission, go for deletion */ retVal = nfsDelete (pNfsDev, fullName); if ((retVal == ERROR) && !(flags & O_CREAT)) return (ERROR); else { if (retVal == FOLLOW_LINK) { (void) strcpy (fileName, fullName); return (FOLLOW_LINK); } } } } /* O_TRUNC */ if ((flags & O_CREAT) || (flags & O_TRUNC)) /* create file or directory */ { retVal = nfsLookUpByName (pNfsDev->host, fullName, &pNfsDev->fileHandle, &dirResult, &dirHandle); if (retVal == FOLLOW_LINK) { (void) strcpy (fileName, fullName); return (FOLLOW_LINK); } status = nfsThingCreate (pNfsDev->host, fullName, &pNfsDev->fileHandle, &dirResult, &dirHandle, (u_int)mode); } else /* open existing file or directory */ { status = nfsLookUpByName (pNfsDev->host, fullName, &pNfsDev->fileHandle, &dirResult, &dirHandle); } if (status == ERROR) return (ERROR); /* Check file permissions */ filePermissions = dirResult.diropres_u.diropres.attributes.mode; switch (openMode) { case O_RDONLY: requestPerms = 4; break; case O_WRONLY: requestPerms = 2; break; case O_RDWR: requestPerms = 6; break; } /* Check if uid and gid match file uid and gid */ nfsAuthUnixGet (machineName, &uid, &gid, &nGids, gids); sameUid = (uid == dirResult.diropres_u.diropres.attributes.uid ? TRUE : FALSE); if (gid == dirResult.diropres_u.diropres.attributes.gid) sameGid = TRUE; else while (nGids) if (gids [--nGids] == dirResult.diropres_u.diropres.attributes.gid) { sameGid = TRUE; break; } /* Check "other" permissions */ if (!sameGid && !sameUid && ((filePermissions & requestPerms) == requestPerms)) correctPerms = TRUE; /* check group permissions */ else if (sameGid && ((filePermissions & (requestPerms << 3)) == (requestPerms << 3))) correctPerms = TRUE; /* check user permissions */ else if (sameUid && ((filePermissions & (requestPerms << 6)) == (requestPerms << 6))) correctPerms = TRUE; else { errno = S_nfsDrv_PERMISSION_DENIED; return (ERROR); } /* * If the name returned by nfsLookUpByName doesn't start with a * slash, then nfsLookUpByName has changed the name to the link, but the * name no longer includes the name of the correct device. If you pass * this to iosDevFind, it returns a path on the default device, which is * wrong (unless, of course, you get lucky and you are in fact looking * for something on the default device). So, need to prepend the name of * the NFS device if fullName doesn't include it already. */ if (status == FOLLOW_LINK) { if (fullName [0] != '/') { pathCat (pNfsDev->devHdr.name, fullName, fileName); } else { (void) strcpy (fileName, fullName); } } if (status != OK) return (status); if ((nfsFd = (NFS_FD *) KHEAP_ALLOC(sizeof (NFS_FD) + nfsCacheSize)) == NULL) return (ERROR); /* fill in file descriptor with newly retrieved information */ bcopy ((char *) &dirResult.diropres_u.diropres.file, (char *) &nfsFd->fileHandle, sizeof (nfs_fh)); bcopy ((char *) &dirHandle, (char *) &nfsFd->dirHandle, sizeof (nfs_fh)); bcopy ((char *) &dirResult.diropres_u.diropres.attributes, (char *) &nfsFd->fileAttr, sizeof (fattr)); nfsFd->fileCurByte = 0; nfsFd->mode = openMode; nfsFd->cacheValid = FALSE; nfsFd->cacheBuf = (char *) ((u_int) nfsFd + sizeof (NFS_FD)); nfsFd->cacheCurByte = nfsFd->cacheBuf; nfsFd->cacheDirty = FALSE; nfsFd->cacheBytesLeft = 0; nfsFd->nfsDev = pNfsDev; nfsFd->nfsFdSem = semMCreate (mutexOptionsNfsDrv); if (nfsFd->nfsFdSem == NULL) { free ( (char *)nfsFd); return (ERROR); } return ((int) nfsFd); }/********************************************************************************* nfsClose - close a remote file** Called only by the I/O system.** RETURNS: OK or ERROR if file failed to flush*/LOCAL STATUS nfsClose ( FAST NFS_FD *nfsFd /* nfs file descriptor */ ) { int status = OK; semTake (nfsFd->nfsFdSem, WAIT_FOREVER); if (nfsFd->cacheDirty) status = nfsCacheFlush (nfsFd); semDelete (nfsFd->nfsFdSem); /* terminate nfs fd semaphore */ KHEAP_FREE((char *) nfsFd); /* close client if "auto close" is selected */ if (nfsAutoClose) nfsClientClose (); return (status == ERROR ? ERROR : OK); }/********************************************************************************* nfsRead - read bytes from remote file** nfsRead reads the specified number of bytes from the open NFS* file and puts them into a buffer. Bytes are read starting* from the point marked by the file pointer. The file pointer is then* updated to point immediately after the last character that was read.** A cache is used for keeping nfs network reads and writes down to a minimum.** Called only by the I/O system.** SIDE EFFECTS: moves file pointer** RETURNS: number of bytes read or ERROR.*/LOCAL int nfsRead ( FAST NFS_FD *nfsFd, /* pointer to open network file descriptor */ char *buf, /* pointer to buffer to receive bytes */ FAST int maxBytes /* max number of bytes to read into buffer */ ) { int nRead; /* number of bytes read from cache or net */ int nCacheRead; /* number of bytes read into cache */ int readCount; /* cum. no. of bytes read into user's buf */ STATUS status = OK; /* check for valid maxBytes */ if (maxBytes < 0) { errnoSet (S_nfsDrv_INVALID_NUMBER_OF_BYTES); return (ERROR); } if (maxBytes == 0) return (0); /* if file opened for O_WRONLY, don't read */ if (nfsFd->mode == O_WRONLY) { errnoSet (S_nfsDrv_WRITE_ONLY_CANNOT_READ); return (ERROR); } readCount = 0; semTake (nfsFd->nfsFdSem, WAIT_FOREVER); if (nfsCacheSize == 0) { /* no caching */ readCount = nfsFileRead (nfsFd->nfsDev->host, &nfsFd->fileHandle, nfsFd->fileCurByte, (unsigned) maxBytes, buf, &nfsFd->fileAttr); if (readCount < 0) { semGive (nfsFd->nfsFdSem); return (ERROR); } status = nfsSeek (nfsFd, (int) nfsFd->fileCurByte + readCount); } else { /* read from cache */ while ((readCount < maxBytes) && (status != ERROR)) { /* keep reading until all bytes requested are read, * or an error occurs, * or the end of file is hit */ if (!nfsFd->cacheValid) { /* if the cache isn't valid, * freshen it by reading across the net. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -