struct file *do_last(struct nameidata *nd, struct path *path,
int open_flag, int acc_mode,
int mode, const char *pathname)
{
if (!(open_flag & O_CREAT)) {
error = do_lookup(nd, &nd->last, path);
if (error)
goto exit;
error = -ENOENT;//不让以创建方式打开,那么如果找不到则返回
if (!path->dentry->d_inode)
goto exit_dput;
goto ok;
}
/* Negative dentry, just create the file */
if (!path->dentry->d_inode) {
error = mnt_want_write(nd->path.mnt);
=>int mnt_want_write(struct vfsmount *mnt)
{
if (__mnt_is_readonly(mnt)) {
dec_mnt_writers(mnt);
ret = -EROFS;//打开失败,由于是只读模式
goto out;
}
out:
return ret;
}
if (error)
goto exit_mutex_unlock;
}
ok:
filp = finish_open(nd, open_flag, acc_mode);
=>struct file *finish_open(struct nameidata *nd,
int open_flag, int acc_mode)
{
error = may_open(&nd->path, acc_mode, open_flag);
=>int may_open(struct path *path, int acc_mode, int flag)
{
error = inode_permission(inode, acc_mode);
=>int inode_permission(struct inode *inode, int mask)
{
if (mask & MAY_WRITE) {//写模式下权限的判断
umode_t mode = inode->i_mode;
/*
* Nobody gets write access to a read-only fs.
*/
if (IS_RDONLY(inode) &&
(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
return -EROFS;//只读
/*
* Nobody gets write access to an immutable file.
*/
if (IS_IMMUTABLE(inode))
return -EACCES;
}
}
if (error)
return error;
}
if (error) {
if (will_truncate)
mnt_drop_write(nd->path.mnt);
goto exit;
}
}
return filp;
exit_mutex_unlock:
mutex_unlock(&dir->d_inode->i_mutex);
exit_dput:
path_put_conditional(path, nd);
exit:
if (!IS_ERR(nd->intent.open.file))
release_open_intent(nd);
path_put(&nd->path);
return ERR_PTR(error);
}