nfs4: Make Inode::Access() use cached attributes
This commit is contained in:
@@ -445,48 +445,76 @@ Inode::ReadLink(void* buffer, size_t* length)
|
|||||||
status_t
|
status_t
|
||||||
Inode::Access(int mode)
|
Inode::Access(int mode)
|
||||||
{
|
{
|
||||||
do {
|
int acc = 0;
|
||||||
RPC::Server* serv = fFileSystem->Server();
|
|
||||||
Request request(serv);
|
|
||||||
RequestBuilder& req = request.Builder();
|
|
||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
if (fFileSystem->IsAttrSupported(FATTR4_MODE)) {
|
||||||
req.Access();
|
status_t result = _UpdateAttrCache();
|
||||||
|
|
||||||
status_t result = request.Send();
|
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
ReplyInterpreter& reply = request.Reply();
|
// Root squashing and owner mapping problems may make this function
|
||||||
|
// return false values. However, since due to race condition it can
|
||||||
|
// not be used for anything critical, it is not a serius problem.
|
||||||
|
|
||||||
if (_HandleErrors(reply.NFS4Error(), serv))
|
mode_t nodeMode = fAttrCache.st_mode;
|
||||||
continue;
|
uint8 userMode = (nodeMode & S_IRWXU) >> 6;
|
||||||
|
uint8 groupMode = (nodeMode & S_IRWXG) >> 3;
|
||||||
|
uint8 otherMode = (nodeMode & S_IRWXO);
|
||||||
|
|
||||||
reply.PutFH();
|
uid_t uid = geteuid();
|
||||||
|
if (uid == 0)
|
||||||
|
acc = userMode | groupMode | otherMode | R_OK | W_OK;
|
||||||
|
else if (uid == fAttrCache.st_uid)
|
||||||
|
acc = userMode;
|
||||||
|
else if (getegid() == fAttrCache.st_gid)
|
||||||
|
acc = groupMode;
|
||||||
|
else
|
||||||
|
acc = otherMode;
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
RPC::Server* serv = fFileSystem->Server();
|
||||||
|
Request request(serv);
|
||||||
|
RequestBuilder& req = request.Builder();
|
||||||
|
|
||||||
uint32 allowed;
|
req.PutFH(fInfo.fHandle);
|
||||||
result = reply.Access(NULL, &allowed);
|
req.Access();
|
||||||
if (result != B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
int acc = 0;
|
status_t result = request.Send();
|
||||||
if ((allowed & ACCESS4_READ) != 0)
|
if (result != B_OK)
|
||||||
acc |= R_OK;
|
return result;
|
||||||
|
|
||||||
if (fType == NF4DIR && (allowed & ACCESS4_LOOKUP) != 0)
|
ReplyInterpreter& reply = request.Reply();
|
||||||
acc |= X_OK | R_OK;
|
|
||||||
|
|
||||||
if (fType != NF4DIR && (allowed & ACCESS4_EXECUTE) != 0)
|
if (_HandleErrors(reply.NFS4Error(), serv))
|
||||||
acc |= X_OK;
|
continue;
|
||||||
|
|
||||||
if ((allowed & ACCESS4_MODIFY) != 0)
|
reply.PutFH();
|
||||||
acc |= W_OK;
|
|
||||||
|
|
||||||
if ((mode & acc) != mode)
|
uint32 allowed;
|
||||||
return B_NOT_ALLOWED;
|
result = reply.Access(NULL, &allowed);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
return B_OK;
|
if ((allowed & ACCESS4_READ) != 0)
|
||||||
} while (true);
|
acc |= R_OK;
|
||||||
|
|
||||||
|
if (fType == NF4DIR && (allowed & ACCESS4_LOOKUP) != 0)
|
||||||
|
acc |= X_OK | R_OK;
|
||||||
|
|
||||||
|
if (fType != NF4DIR && (allowed & ACCESS4_EXECUTE) != 0)
|
||||||
|
acc |= X_OK;
|
||||||
|
|
||||||
|
if ((allowed & ACCESS4_MODIFY) != 0)
|
||||||
|
acc |= W_OK;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mode & acc) != mode)
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user