/*===========================================================================* * do_link * *===========================================================================*/ PUBLIC int do_link() { /* Perform the link(name1, name2) system call. */ int r; endpoint_t linked_fs_e, link_lastdir_fs_e; struct vnode *vp_o, *vp_d; if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); /* Request lookup */ if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r; linked_fs_e = vp_o->v_fs_e; /* Does the final directory of 'name2' exist? */ if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { put_vnode(vp_o); return(err_code); } /* Request lookup */ if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK) { put_vnode(vp_o); return r; } link_lastdir_fs_e = vp_d->v_fs_e; /* Check for links across devices. */ if (linked_fs_e != link_lastdir_fs_e) { put_vnode(vp_o); put_vnode(vp_d); return EXDEV; } /* Make sure that the object is a directory */ if ((vp_d->v_mode & I_TYPE) != I_DIRECTORY) { put_vnode(vp_o); put_vnode(vp_d); return ENOTDIR; } r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/); if (r != OK) { put_vnode(vp_o); put_vnode(vp_d); return r; } /* Issue request */ r= req_link(linked_fs_e, vp_d->v_inode_nr, user_fullpath, vp_o->v_inode_nr); put_vnode(vp_o); put_vnode(vp_d); return r; }
/*===========================================================================* * do_link * *===========================================================================*/ int do_link() { /* Perform the link(name1, name2) system call. */ int r = 0; endpoint_t linked_fs_e, link_lastdir_fs_e; struct vnode *vp, *vp_d; /* See if 'name1' (file to be linked to) exists. */ if(fetch_name(user_fullpath, PATH_MAX, m_in.name1) < 0) return(err_code); if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); /* Does the final directory of 'name2' exist? */ if (fetch_name(user_fullpath, PATH_MAX, m_in.name2) < 0) r = err_code; else if ((vp_d = last_dir()) == NIL_VNODE) r = err_code; if (r != 0) { put_vnode(vp); return(r); } /* Check for links across devices. */ if(vp->v_fs_e != vp_d->v_fs_e) r = -EXDEV; else r = forbidden(vp_d, W_BIT | X_BIT); if (r == 0) r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath, vp->v_inode_nr); put_vnode(vp); put_vnode(vp_d); return(r); }
/*===========================================================================* * do_link * *===========================================================================*/ int do_link() { /* Perform the link(name1, name2) system call. */ int r = OK; struct vnode *vp = NULL, *dirp = NULL; struct vmnt *vmp1 = NULL, *vmp2 = NULL; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, vname2; size_t vname1_length, vname2_length; vname1 = (vir_bytes) job_m_in.name1; vname1_length = job_m_in.name1_length; vname2 = (vir_bytes) job_m_in.name2; vname2_length = job_m_in.name2_length; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* See if 'name1' (file to be linked to) exists. */ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Does the final directory of 'name2' exist? */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_WRITE; if (fetch_name(vname2, vname2_length, fullpath) != OK) r = err_code; else if ((dirp = last_dir(&resolve, fp)) == NULL) r = err_code; if (r != OK) { unlock_vnode(vp); unlock_vmnt(vmp1); put_vnode(vp); return(r); } /* Check for links across devices. */ if (vp->v_fs_e != dirp->v_fs_e) r = EXDEV; else r = forbidden(fp, dirp, W_BIT | X_BIT); if (r == OK) r = req_link(vp->v_fs_e, dirp->v_inode_nr, fullpath, vp->v_inode_nr); unlock_vnode(vp); unlock_vnode(dirp); if (vmp2 != NULL) unlock_vmnt(vmp2); unlock_vmnt(vmp1); put_vnode(vp); put_vnode(dirp); return(r); }