/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ static struct file *do_filp_open(int dfd, const char *filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) namei_flags++; error = open_namei(dfd, filename, namei_flags, mode, &nd); if (!error){ /* if(active_transaction() && !shadow(nd.dentry->d_inode)){ printk(KERN_ERR "Not shadow for file %s, %p\n", filename, &nd.dentry->d_inode); printk(KERN_ERR "Dentry = %p, %p, %p\n", &nd.dentry, nd.dentry, shadow(nd.dentry)); OSA_MAGIC(OSA_BREAKSIM); } KSTM_BUG_ON(active_transaction() && !shadow(nd.dentry->d_inode)); */ return nameidata_to_filp(&nd, flags); } return ERR_PTR(error); }
static int isofs_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { int error; char * pnt; if (!dir) { dir = current->fs->root; dir->i_count++; } if (!inode) { iput(dir); *res_inode = NULL; return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput(dir); *res_inode = inode; return 0; } if ((current->link_count > 5) || !(pnt = get_rock_ridge_symlink(inode))) { iput(dir); iput(inode); *res_inode = NULL; return -ELOOP; } iput(inode); current->link_count++; error = open_namei(pnt,flag,mode,res_inode,dir); current->link_count--; kfree(pnt); return error; }
int shim_do_openat (int dfd, const char * filename, int flags, int mode) { if (!filename || test_user_string(filename)) return -EFAULT; if (*filename == '/') return shim_do_open(filename, flags, mode); struct shim_dentry * dir = NULL; int ret = 0; if ((ret = path_startat(dfd, &dir)) < 0) return ret; struct shim_handle * hdl = get_new_handle(); if (!hdl) { ret = -ENOMEM; goto out; } ret = open_namei(hdl, dir, filename, flags, mode, NULL); if (ret < 0) goto out_hdl; ret = set_new_fd_handle(hdl, flags & O_CLOEXEC ? FD_CLOEXEC : 0, NULL); out_hdl: put_handle(hdl); out: put_dentry(dir); return ret; }
static unix_socket *unix_find_other(char *path, int *error) { int old_fs; int err; struct inode *inode; unix_socket *u; old_fs=get_fs(); set_fs(get_ds()); err = open_namei(path, 2, S_IFSOCK, &inode, NULL); set_fs(old_fs); if(err<0) { *error=err; return NULL; } u=unix_find_socket(inode); iput(inode); if(u==NULL) { *error=-ECONNREFUSED; return NULL; } return u; }
static int unix_connect(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len, int flags) { char fname[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1]; struct sockaddr_un sockun; struct unix_proto_data *serv_upd; struct inode *inode; unsigned short old_ds; int i; if (sockaddr_len <= 0 || sockaddr_len > sizeof(struct sockaddr_un)) return -EINVAL; if (sock->state == SS_CONNECTING) return -EINPROGRESS; if (sock->state == SS_CONNECTED) return -EISCONN; memcpy(&sockun, uservaddr, sockaddr_len); sockun.sun_path[sockaddr_len] = '\0'; if (sockun.sun_family != AF_UNIX) return -EINVAL; /* * Try to open the name in the filesystem - this is how we identify ourselves * and our server. Note that we don't hold onto the inode much, just enough to * find our server. When we're connected, we mooch off the server. */ memcpy(fname, sockun.sun_path, sockaddr_len); fname[sockaddr_len] = '\0'; old_ds = current->t_regs.ds; current->t_regs.ds = get_ds(); i = open_namei(fname, 2, S_IFSOCK, &inode, NULL); current->t_regs.ds = old_ds; if (i < 0) return i; serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode); iput(inode); if (!serv_upd) return -EINVAL; if ((i = sock_awaitconn(sock, serv_upd->socket, flags)) < 0) return i; if (sock->conn) { unix_data_ref(UN_DATA(sock->conn)); UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */ } return 0; }
static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) { char *cp, *interp, *i_name; int retval; if (strncmp (bprm->buf, "<!--applet", 10)) return -ENOEXEC; iput(bprm->inode); bprm->dont_iput=1; /* * OK, we've set the interpreter name * Splice in (1) the interpreter's name for argv[0] (_PATH_BSHELL) * (2) the name of the appletviewer wrapper for argv[1] (_PATH_APPLET) * (3) filename of html file (replace argv[0]) * * This is done in reverse order, because of how the * user environment and arguments are stored. */ remove_arg_zero(bprm); i_name = bprm->filename; bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; strcpy (bprm->buf, binfmt_java_appletviewer); cp = bprm->buf; bprm->p = copy_strings(1, &cp, bprm->page, bprm->p, 2); bprm->argc++; strcpy (bprm->buf, _PATH_SH); interp = bprm->buf; if ((i_name = strrchr (bprm->buf, '/')) != NULL) i_name++; else i_name = bprm->buf; bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; if (!bprm->p) return -E2BIG; /* * OK, now restart the process with the interpreter's inode. * Note that we use open_namei() as the name is now in kernel * space, and we don't need to copy it. */ retval = open_namei(interp, 0, 0, &bprm->inode, NULL); if (retval) return retval; bprm->dont_iput=0; retval=prepare_binprm(bprm); if(retval<0) return retval; return search_binary_handler(bprm,regs); }
int open(char* filename,int mode,int flag) //int sys_open(char* filename,int mode,int flag) { struct m_inode *inode; struct file *f; int i; int fd = -1; //句柄 //搜索没用过的句柄 for(i = 0;i < NR_OPEN;i++) { if(current->filp[i] == NULL) { fd = i; break; } } if(fd < 0 || fd > NR_OPEN) { panic("filp is full (PID %d)\n",proc2pid(current)); } f = file_table; for(i = 0;i < NR_FILE;i++,f++) { if(!f->f_count) { break; } } if(i < 0 || i > NR_FILE) { panic("file_table is full (PID %d)\n",proc2pid(current)); } (current->filp[fd] = f)->f_count++; // printk("root_inode->i_dev = %d\n",root_inode->i_dev); if((i = open_namei(filename,mode,flag,&inode)) != 0) { current->filp[fd] = NULL; f->f_count = 0; return i; } //返回文件句柄 // printk("open inode->i_num = %d\n",inode->i_num); f->f_inode = inode; f->f_count = 1; f->f_flag = flag; f->f_mode = mode; f->f_pos = 0; // printk("open:fd = %d\n",fd); return fd; }
static void rootfs_open(object_t caller,void *pathname,int flag, umode_t mode) { int res; struct inode *inode; res = open_namei(super->s_root,pathname,flag,mode,&inode); if(res) { fs_dbg("%d opoen_namei(%s,%o,%o,%p).\n", res,pathname,flag,mode,&inode); ret(caller,res); } else { ret(caller,normal_open(inode,pathname,flag,mode)); } }
static int minix_follow_link(register struct inode *dir, register struct inode *inode, int flag, int mode, struct inode **res_inode) { /* * FIXME: #1 Stack use is too high * #2 Needs to be current->link_count as this is blocking */ int error; struct buffer_head *bh; static int link_count = 0; __u16 ds, *pds; *res_inode = NULL; if (!dir) { dir = current->fs.root; dir->i_count++; } if (!inode) { iput(dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput(dir); *res_inode = inode; return 0; } if ( /* current-> */ link_count > 5) { iput(inode); iput(dir); return -ELOOP; } bh = minix_bread(inode, 0, 0); iput(inode); if (!bh) { iput(dir); return -EIO; } /* current-> */ link_count++; map_buffer(bh); pds = ¤t->t_regs.ds; ds = *pds; *pds = kernel_ds; error = open_namei(bh->b_data, flag, mode, res_inode, dir); *pds = ds; /* current-> */ link_count--; unmap_brelse(bh); return error; }
/* Follow a symbolic link chain by calling open_namei recursively until an inode is found. Return 0 if ok, or a negative error code if not. */ static int UMSDOS_follow_link( struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { int ret = -ELOOP; *res_inode = NULL; if (current->link_count < 5) { char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL); if (path == NULL){ ret = -ENOMEM; }else{ if (!dir) { dir = current->fs[1].root; dir->i_count++; } if (!inode){ PRINTK (("symlink: inode = NULL\n")); ret = -ENOENT; }else if (!S_ISLNK(inode->i_mode)){ PRINTK (("symlink: Not ISLNK\n")); *res_inode = inode; inode = NULL; ret = 0; }else{ ret = umsdos_readlink_x (inode,path ,umsdos_file_read_kmem,PATH_MAX-1); if (ret > 0){ path[ret] = '\0'; PRINTK (("follow :%s: %d ",path,ret)); iput(inode); inode = NULL; current->link_count++; ret = open_namei(path,flag,mode,res_inode,dir); current->link_count--; dir = NULL; }else{ ret = -EIO; } } kfree (path); } } iput(inode); iput(dir); PRINTK (("follow_link ret %d\n",ret)); return ret; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ static int do_open(const char * filename,int flags,int mode, int fd) { struct inode * inode; struct file * f; int flag,error; f = get_empty_filp(); if (!f) return -ENFILE; f->f_flags = flag = flags; f->f_mode = (flag+1) & O_ACCMODE; if (f->f_mode) flag++; if (flag & O_TRUNC) flag |= 2; error = open_namei(filename,flag,mode,&inode,NULL); if (error) goto cleanup_file; if (f->f_mode & FMODE_WRITE) { error = get_write_access(inode); if (error) goto cleanup_inode; } f->f_inode = inode; f->f_pos = 0; f->f_reada = 0; f->f_op = NULL; if (inode->i_op) f->f_op = inode->i_op->default_file_ops; if (f->f_op && f->f_op->open) { error = f->f_op->open(inode,f); if (error) goto cleanup_all; } f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); current->files->fd[fd] = f; return 0; cleanup_all: if (f->f_mode & FMODE_WRITE) put_write_access(inode); cleanup_inode: iput(inode); cleanup_file: f->f_count--; return error; }
/* * bind a name to a socket. this is where much of the work is done. we * allocate a fresh page for the buffer, grab the appropriate inode and * set things up. * * XXX what should we do if an address is already bound? here we return * EINVAL, but it may be necessary to re-bind. i think thats what bsd does * in the case of datagram sockets */ static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr, int sockaddr_len) { struct unix_proto_data *upd = UN_DATA(sock); char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1]; int i; unsigned long old_fs; PRINTK("unix_proto_bind: socket 0x%x, len=%d\n", sock, sockaddr_len); if (sockaddr_len <= UN_PATH_OFFSET || sockaddr_len >= sizeof(struct sockaddr_un)) { PRINTK("unix_proto_bind: bad length %d\n", sockaddr_len); return -EINVAL; } if (upd->sockaddr_len || upd->inode) { printk("unix_proto_bind: already bound!\n"); return -EINVAL; } verify_area(umyaddr, sockaddr_len); memcpy_fromfs(&upd->sockaddr_un, umyaddr, sockaddr_len); if (upd->sockaddr_un.sun_family != AF_UNIX) { PRINTK("unix_proto_bind: family is %d, not AF_UNIX (%d)\n", upd->sockaddr_un.sun_family, AF_UNIX); return -EINVAL; } memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET); fname[sockaddr_len-UN_PATH_OFFSET] = '\0'; old_fs = get_fs(); set_fs(get_ds()); i = do_mknod(fname, S_IFSOCK | 0777, 0); if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode); set_fs(old_fs); if (i < 0) { printk("unix_proto_bind: can't open socket %s\n", fname); return i; } upd->sockaddr_len = sockaddr_len; /* now its legal */ PRINTK("unix_proto_bind: bound socket address: "); #ifdef SOCK_DEBUG sockaddr_un_printk(&upd->sockaddr_un, upd->sockaddr_len); #endif return 0; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ static struct file *do_filp_open(int dfd, const char *filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) namei_flags++; error = open_namei(dfd, filename, namei_flags, mode, &nd); if (!error) return nameidata_to_filp(&nd, flags); return ERR_PTR(error); }
static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, ext2_ino_t inode, int link_count, char *buf, ext2_ino_t *res_inode) { char *pathname; char *buffer = 0; errcode_t retval; struct ext2_inode ei; blk64_t blk; #ifdef NAMEI_DEBUG printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", root, dir, inode, link_count); #endif retval = ext2fs_read_inode (fs, inode, &ei); if (retval) return retval; if (!LINUX_S_ISLNK (ei.i_mode)) { *res_inode = inode; return 0; } if (link_count++ >= EXT2FS_MAX_NESTED_LINKS) return EXT2_ET_SYMLINK_LOOP; if (ext2fs_inode_data_blocks(fs,&ei)) { retval = ext2fs_bmap2(fs, inode, &ei, NULL, 0, 0, NULL, &blk); if (retval) return retval; retval = ext2fs_get_mem(fs->blocksize, &buffer); if (retval) return retval; retval = io_channel_read_blk64(fs->io, blk, 1, buffer); if (retval) { ext2fs_free_mem(&buffer); return retval; } pathname = buffer; } else pathname = (char *)&(ei.i_block[0]); retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, link_count, buf, res_inode); if (buffer) ext2fs_free_mem(&buffer); return retval; }
static int nfs_follow_link(struct inode *dir, struct inode *inode, int flag, int mode, struct inode **res_inode) { int error, *mem; unsigned int len; char *res, *res2; *res_inode = NULL; if (!dir) { dir = current->fs->root; dir->i_count++; } if (!inode) { iput(dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput(dir); *res_inode = inode; return 0; } if (current->link_count > 5) { iput(inode); iput(dir); return -ELOOP; } error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem, &res, &len, NFS_MAXPATHLEN); if (error) { iput(inode); iput(dir); kfree(mem); return error; } while ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_NFS)) == NULL) { schedule(); } memcpy(res2, res, len); res2[len] = '\0'; kfree(mem); iput(inode); current->link_count++; error = open_namei(res2, flag, mode, res_inode, dir); current->link_count--; kfree_s(res2, NFS_MAXPATHLEN + 1); return error; }
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; unix_socket *sk=sock->data; int old_fs; int err; if(sk->protinfo.af_unix.name) return -EINVAL; /* Already bound */ if(addr_len>sizeof(struct sockaddr_un) || addr_len<3 || sunaddr->sun_family!=AF_UNIX) return -EINVAL; unix_mkname(sunaddr, addr_len); /* * Put ourselves in the filesystem */ if(sk->protinfo.af_unix.inode!=NULL) return -EINVAL; sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL); if(sk->protinfo.af_unix.name==NULL) return -ENOMEM; memcpy(sk->protinfo.af_unix.name, sunaddr->sun_path, addr_len+1); old_fs=get_fs(); set_fs(get_ds()); err=do_mknod(sk->protinfo.af_unix.name,S_IFSOCK|S_IRWXUGO,0); if(err==0) err=open_namei(sk->protinfo.af_unix.name, 2, S_IFSOCK, &sk->protinfo.af_unix.inode, NULL); set_fs(old_fs); if(err<0) { kfree_s(sk->protinfo.af_unix.name,addr_len+1); sk->protinfo.af_unix.name=NULL; if(err==-EEXIST) return -EADDRINUSE; else return err; } return 0; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ struct file *filp_open(const char * filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) namei_flags++; if (namei_flags & O_TRUNC) namei_flags |= 2; error = open_namei(filename, namei_flags, mode, &nd); if (!error) return dentry_open(nd.dentry, nd.mnt, flags); return ERR_PTR(error); }
errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, const char *name, ext2_ino_t *inode) { char *buf; errcode_t retval; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); retval = ext2fs_get_mem(fs->blocksize, &buf); if (retval) return retval; retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0, buf, inode); ext2fs_free_mem(&buf); return retval; }
static int ext2_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { int error; struct buffer_head * bh = NULL; char * link; *res_inode = NULL; if (!dir) { dir = current->fs->root; dir->i_count++; } if (!inode) { iput (dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput (dir); *res_inode = inode; return 0; } if (current->link_count > 5) { iput (dir); iput (inode); return -ELOOP; } if (inode->i_blocks) { if (!(bh = ext2_bread (inode, 0, 0, &error))) { iput (dir); iput (inode); return -EIO; } link = bh->b_data; } else link = (char *) inode->u.ext2_i.i_data; UPDATE_ATIME(inode); current->link_count++; error = open_namei (link, flag, mode, res_inode, dir); current->link_count--; iput (inode); if (bh) brelse (bh); return error; }
static int unix_bind(struct socket *sock, struct sockaddr *umyaddr, int sockaddr_len) { char fname[UNIX_PATH_MAX + 1]; struct unix_proto_data *upd = sock->data; unsigned short old_ds; int i; if (sockaddr_len <= 0 || sockaddr_len > sizeof(struct sockaddr_un)) return -EINVAL; if (upd->sockaddr_len || upd->inode) return -EINVAL; /* already bound */ memcpy(&upd->sockaddr_un, umyaddr, sockaddr_len); upd->sockaddr_un.sun_path[sockaddr_len] = '\0'; if (upd->sockaddr_un.sun_family != AF_UNIX) return -EINVAL; memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len); fname[sockaddr_len] = '\0'; old_ds = current->t_regs.ds; current->t_regs.ds = get_ds(); i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0); if (i == 0) i = open_namei(fname, 0, S_IFSOCK, &upd->inode, NULL); current->t_regs.ds = old_ds; if (i < 0) { #if 0 printk("UNIX: bind: can't open socket %s\n", fname); #endif if (i == -EEXIST) i = -EADDRINUSE; return i; } upd->sockaddr_len = sockaddr_len; /* now it's legal */ return 0; }
errcode_t cmfs_namei(cmfs_filesys *fs, uint64_t root, uint64_t cwd, const char *name, uint64_t *inode) { char *buf; errcode_t ret; ret = cmfs_malloc_block(fs->fs_io, &buf); if (ret) goto out; ret = open_namei(fs, root, cwd, name, strlen(name), 0, 0, buf, inode); cmfs_free(&buf); out: return ret; }
int shim_do_open (const char * file, int flags, mode_t mode) { if (!file || !(*file)) return -EINVAL; struct shim_handle * hdl = get_new_handle(); if (!hdl) return -ENOMEM; int ret = 0; ret = open_namei(hdl, NULL, file, flags, mode, NULL); if (ret < 0) goto out; ret = set_new_fd_handle(hdl, flags & O_CLOEXEC ? FD_CLOEXEC : 0, NULL); out: put_handle(hdl); return ret; }
static void rootfs_stat(object_t caller,void *pathname,struct stat *stat_buf) { int res; struct inode *inode; res = open_namei(super->s_root,pathname,O_RDONLY,0666,&inode); if(!res && stat_buf) { stat_buf->st_dev = inode->i_rdev; stat_buf->st_gid = inode->i_gid; stat_buf->st_ino = inode->i_ino; stat_buf->st_uid = inode->i_uid; stat_buf->st_mode = inode->i_mode; stat_buf->st_size = inode->i_size; stat_buf->st_atime = inode->i_atime.tv_sec; stat_buf->st_ctime = inode->i_ctime.tv_sec; stat_buf->st_mtime = inode->i_mtime.tv_sec; stat_buf->st_nlink = inode->i_nlinks; } ret(caller,res); }
static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, ext2_ino_t inode, int link_count, char *buf, ext2_ino_t *res_inode) { char *pathname; char *buffer = 0; errcode_t retval; struct ext2_inode ei; #ifdef NAMEI_DEBUG printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", root, dir, inode, link_count); #endif retval = ext2fs_read_inode (fs, inode, &ei); if (retval) return retval; if (!LINUX_S_ISLNK (ei.i_mode)) { *res_inode = inode; return 0; } if (link_count++ > 5) { return EXT2_ET_SYMLINK_LOOP; } /* FIXME-64: Actually, this is FIXME EXTENTS */ if (ext2fs_inode_data_blocks(fs,&ei)) { retval = ext2fs_get_mem(fs->blocksize, &buffer); if (retval) return retval; retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer); if (retval) { ext2fs_free_mem(&buffer); return retval; } pathname = buffer; } else pathname = (char *)&(ei.i_block[0]); retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, link_count, buf, res_inode); if (buffer) ext2fs_free_mem(&buffer); return retval; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ struct file *filp_open(const char * filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; namei_flags = flags; /* * flag转换,因为open_namei对flag的约定与open调用不一致,所以需要作一些转换 * */ if ((namei_flags+1) & O_ACCMODE) namei_flags++; if (namei_flags & O_TRUNC) namei_flags |= 2; /*通过路径名找到一个nd结构,即dentry和vfsmount*/ error = open_namei(filename, namei_flags, mode, &nd); if (!error) return dentry_open(nd.dentry, nd.mnt, flags); return ERR_PTR(error); }
static int ext_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { int error; unsigned short fs; struct buffer_head * bh; *res_inode = NULL; if (!dir) { dir = current->root; dir->i_count++; } if (!inode) { iput(dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput(dir); *res_inode = inode; return 0; } if (current->link_count > 5) { iput(dir); iput(inode); return -ELOOP; } if (!(bh = ext_bread(inode, 0, 0))) { iput(inode); iput(dir); return -EIO; } iput(inode); __asm__("mov %%fs,%0":"=r" (fs)); __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10)); current->link_count++; error = open_namei(bh->b_data,flag,mode,res_inode,dir); current->link_count--; __asm__("mov %0,%%fs"::"r" (fs)); brelse(bh); return error; }
static int minix_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { int error; struct buffer_head * bh; *res_inode = NULL; if (!dir) { dir = current->root; dir->i_count++; } if (!inode) { iput(dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput(dir); *res_inode = inode; return 0; } if (current->link_count > 5) { iput(inode); iput(dir); return -ELOOP; } if (!(bh = minix_bread(inode, 0, 0))) { iput(inode); iput(dir); return -EIO; } iput(inode); current->link_count++; error = open_namei(bh->b_data,flag,mode,res_inode,dir); current->link_count--; brelse(bh); return error; }
int sys_open(char *filename, int flags, int mode) { struct inode *inode; register struct inode *pinode; struct file *f; int error, flag; flag = flags; if ((mode_t)((flags + 1) & O_ACCMODE)) flag++; if (flag & (O_TRUNC | O_CREAT)) flag |= FMODE_WRITE; error = open_namei(filename, flag, mode, &inode, NULL); if(error) goto exit_open; pinode = inode; error = open_filp(flags, pinode, &f); if(error) goto cleanup_inode; f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); /* * We have to do this last, because we mustn't export * an incomplete fd to other processes which may share * the same file table with us. */ if ((error = get_unused_fd(f)) > -1) goto exit_open; close_filp(pinode, f); cleanup_inode: iput(pinode); exit_open: return error; }
/* * Note that while the flag value (low two bits) for sys_open means: * 00 - read-only * 01 - write-only * 10 - read-write * 11 - special * it is changed into * 00 - no permissions needed * 01 - read-permission * 10 - write-permission * 11 - read-write * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ struct file *filp_open(const char * filename, int flags, int mode) { int namei_flags, error; struct nameidata nd; struct file *f; namei_flags = flags; if ((namei_flags+1) & O_ACCMODE) namei_flags++; if (namei_flags & O_TRUNC) namei_flags |= 2; error = -ENFILE; f = get_empty_filp(); if (f == NULL) return ERR_PTR(error); error = open_namei(filename, namei_flags, mode, &nd); if (!error) return __dentry_open(nd.dentry, nd.mnt, flags, f); put_filp(f); return ERR_PTR(error); }
/* * XXX - blatantly stolen from ext2fs */ static int ufs_follow_link(struct inode * dir, struct inode * inode, int flag, int mode, struct inode ** res_inode) { unsigned long int block; int error; struct buffer_head * bh; char * link; bh = NULL; if (inode->i_sb->u.ufs_sb.s_flags & (UFS_DEBUG|UFS_DEBUG_LINKS)) { printk("ufs_follow_link: called on ino %lu dev %u/%u\n", dir->i_ino, MAJOR(dir->i_dev), MINOR(dir->i_dev)); } *res_inode = NULL; if (!dir) { dir = current->fs->root; dir->i_count++; } if (!inode) { iput (dir); return -ENOENT; } if (!S_ISLNK(inode->i_mode)) { iput (dir); *res_inode = inode; return 0; } if (current->link_count > 5) { iput (dir); iput (inode); return -ELOOP; } if (inode->i_blocks) { /* read the link from disk */ /* XXX - error checking */ block = ufs_bmap(inode, 0); bh = bread(inode->i_dev, block, BLOCK_SIZE); if (bh == NULL) { printk("ufs_follow_link: can't read block 0 for ino %lu on dev %u/%u\n", inode->i_ino, MAJOR(inode->i_dev), MINOR(inode->i_dev)); iput(dir); iput(inode); return(-EIO); } link = bh->b_data; } else { /* fast symlink */ link = (char *)&(inode->u.ufs_i.ui_db[0]); } current->link_count++; error = open_namei (link, flag, mode, res_inode, dir); current->link_count--; iput (inode); if (bh) { brelse (bh); } return(error); }