syscall open

/*******************************************************************************/
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
    long ret;

    if (force_o_largefile())
        flags |= O_LARGEFILE;

    ret = do_sys_open(AT_FDCWD, filename, flags, mode);

    return ret;
}


long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
    struct open_flags op;
    int lookup = build_open_flags(flags, mode, &op);
    char *tmp = getname(filename);
    int fd = PTR_ERR(tmp);

    if (!IS_ERR(tmp)) {
        fd = get_unused_fd_flags(flags);
        if (fd >= 0) {
            struct file *f = do_filp_open(dfd, tmp, &op, lookup);
            if (IS_ERR(f)) {
                put_unused_fd(fd);
                fd = PTR_ERR(f);
            } else {
                fsnotify_open(f);
                fd_install(fd, f);
            }
        }
        putname(tmp);
    }
    return fd;
}


struct open_flags {
    int open_flag;
    umode_t mode;
    int acc_mode;
    int intent;
};

/*根据flag and mode设置 open_flags*/
static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
{
}


/* In order to reduce some races, while at the same time doing additional
 * checking and hopefully speeding things up, we copy filenames to the
 * kernel data space before using them..
 */
char *getname(const char __user * filename)
{
    return getname_flags(filename, 0, NULL);
}

static char *getname_flags(const char __user *filename, int flags, int *empty)
{
    char *result = __getname();
    int retval;

    if (!result)
        return ERR_PTR(-ENOMEM);

    retval = do_getname(filename, result);
    return result;
}

extern struct kmem_cache *names_cachep;
#define __getname_gfp(gfp)    kmem_cache_alloc(names_cachep, (gfp))
#define __getname()        __getname_gfp(GFP_KERNEL)

/* allocate a file descriptor, mark it busy.
 * 从当前进程中得到 fd
 */
#define get_unused_fd_flags(flags) alloc_fd(0, (flags))
/*
 * allocate a file descriptor, mark it busy.
 */
int alloc_fd(unsigned start, unsigned flags)
{
    struct files_struct *files = current->files;
    unsigned int fd;
    int error;
    struct fdtable *fdt;
    /*从fdtabel中找到一个fd, 设置busy flag*/
    fdt = files_fdtable(files);
    __set_open_fd(fd, fdt);
    return fd;
}

struct file *do_filp_open(int dfd, const char *pathname,
        const struct open_flags *op, int flags)
{
    struct nameidata nd;
    struct file *filp;

    filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);

    return filp;
}

static struct file *path_openat(int dfd, const char *pathname,
        struct nameidata *nd, const struct open_flags *op, int flags)
{
    struct file *base = NULL;
    struct file *filp;
    struct path path;
    int error;

    filp = get_empty_filp();
    if (!filp)
        return ERR_PTR(-ENFILE);

    filp->f_flags = op->open_flag;
    nd->intent.open.file = filp;
    nd->intent.open.flags = open_to_namei_flags(op->open_flag);
    nd->intent.open.create_mode = op->mode;

    error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
    if (unlikely(error))
        goto out_filp;

    current->total_link_count = 0;
    error = link_path_walk(pathname, nd);
    filp = do_last(nd, &path, op, pathname);
    return filp;
}

/*
 * Name resolution.
 * This is the basic name resolution function, turning a pathname into
 * the final dentry. We expect 'base' to be positive and a directory.
 *
 * Returns 0 and nd will have valid dentry and mnt on success.
 * Returns error and drops reference to input namei data on failure.
 */
static int link_path_walk(const char *name, struct nameidata *nd)
{
}

/*
 * Handle the last step of open()
 */
static struct file *do_last(struct nameidata *nd, struct path *path,
                const struct open_flags *op, const char *pathname)
{
    struct file *filp;
    filp = nameidata_to_filp(nd);

}

/**
 * nameidata_to_filp - convert a nameidata to an open filp.
 * @nd: pointer to nameidata
 * @flags: open flags
 *
 * Note that this function destroys the original nameidata
 */
struct file *nameidata_to_filp(struct nameidata *nd)
{
    const struct cred *cred = current_cred();
    struct file *filp;

    /* Pick up the filp from the open intent */
    filp = nd->intent.open.file;
    nd->intent.open.file = NULL;

    /* Has the filesystem initialised the file for us? */
    if (filp->f_path.dentry == NULL) {
        path_get(&nd->path);
        filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
                     NULL, cred);
    }
    return filp;
}



static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
                    struct file *f,
                    int (*open)(struct inode *, struct file *),
                    const struct cred *cred)
{
    static const struct file_operations empty_fops = {};
    struct inode *inode;
    int error;

    f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
                FMODE_PREAD | FMODE_PWRITE;

    if (unlikely(f->f_flags & O_PATH))
        f->f_mode = FMODE_PATH;

    inode = dentry->d_inode;

    f->f_mapping = inode->i_mapping;
    f->f_path.dentry = dentry;
    f->f_path.mnt = mnt;
    f->f_pos = 0;
    file_sb_list_add(f, inode->i_sb);

    f->f_op = fops_get(inode->i_fop);


    if (!open && f->f_op)
        open = f->f_op->open;
    if (open) {
        open(inode, f);
    }

    return f;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值