/*===========================================================================* * 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); }
void dissector_init_ethernet(int fnttype) { dissector_init_entry(fnttype); dissector_init_layer_2(fnttype); dissector_init_layer_3(fnttype); dissector_init_exit(fnttype); lookup_init(LT_PORTS_UDP); lookup_init(LT_PORTS_TCP); lookup_init(LT_ETHERTYPES); lookup_init(LT_OUI); }
/*===========================================================================* * do_chroot * *===========================================================================*/ int do_chroot(void) { /* Perform the chroot(name) system call. * syscall might provide 'name' embedded in the message. */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; if (!super_user) return(EPERM); /* only su may chroot() */ if (copy_path(fullpath, sizeof(fullpath)) != OK) return(err_code); /* Try to open the directory */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = change_into(&fp->fp_rd, vp); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
int do_recinode() { struct vnode *vp; struct vmnt *vmp; int r; size_t nrblks; char fullpath[PATH_MAX]; struct lookup resolve; size_t vname1_length; vir_bytes vname1; vname1 = job_m_in.m_lc_vfs_inodes.name; vname1_length = job_m_in.m_lc_vfs_inodes.len; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_recoverinode(vp->v_fs_e, vp->v_inode_nr); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
/*===========================================================================* * do_lstat * *===========================================================================*/ int do_lstat(void) { /* Perform the lstat(name, buf) system call. */ struct vnode *vp; struct vmnt *vmp; int r; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = job_m_in.m_lc_vfs_stat.name; vname1_length = job_m_in.m_lc_vfs_stat.len; statbuf = job_m_in.m_lc_vfs_stat.buf; lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_mkdir * *===========================================================================*/ PUBLIC int do_mkdir() { /* Perform the mkdir(name, mode) system call. */ mode_t bits; /* mode bits for the new inode */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) return(err_code); bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if ((vp->v_mode & I_TYPE) != I_DIRECTORY) { r = ENOTDIR; } else if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) { r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * name_to_dev * *===========================================================================*/ static dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX]) { /* Convert the block special file in 'user_fullpath' to a device number. * If the given path is not a block special file, but 'allow_mountpt' is set * and the path is the root node of a mounted file system, return that device * number. In all other cases, return NO_DEV and an error code in 'err_code'. */ dev_t dev; struct vnode *vp; struct vmnt *vmp; struct lookup resolve; lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; /* Request lookup */ if ((vp = eat_path(&resolve, fp)) == NULL) return(NO_DEV); if (S_ISBLK(vp->v_mode)) { dev = vp->v_sdev; } else if (allow_mountpt && vp->v_vmnt->m_root_node == vp) { dev = vp->v_dev; } else { err_code = ENOTBLK; dev = NO_DEV; } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(dev); }
void setup_this(void){ lookup = (t_lookup *)lookup_init(1); table = (t_table *)table_init(1000, 1); rk_clipper = (t_rk_mother *)rk_mother_init(&rk_clipper_func, 1, 0, 1, 1); install_obj(&lookup->od); install_obj(&table->od); install_obj(&rk_clipper->od); c_sig_freq = init_lin_ctl(0, CTL_T_LIN, 1); c_sig_level = init_lin_ctl(1, CTL_T_LIN, 1); c_out_level = init_lin_ctl(2, CTL_T_LIN, 1); c_fb_in = init_lin_ctl(3, CTL_T_LIN, 1); c_fb_out = init_lin_ctl(4, CTL_T_LIN, 1); c_clip_gain = init_lin_ctl(5, CTL_T_LIN, 1); level_lin_ctl(c_sig_freq, sig_freq); level_lin_ctl(c_sig_level, sig_level); level_lin_ctl(c_out_level, out_level); level_lin_ctl(c_fb_in, fb_in); level_lin_ctl(c_fb_out, fb_out); level_lin_ctl(c_clip_gain, clip_gain); }
/*===========================================================================* * do_mkdir * *===========================================================================*/ int do_mkdir(void) { /* Perform the mkdir(name, mode) system call. */ mode_t bits; /* mode bits for the new inode */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; mode_t dirmode; if (copy_path(fullpath, sizeof(fullpath)) != OK) return(err_code); dirmode = job_m_in.m_lc_vfs_path.mode; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; bits = I_DIRECTORY | (dirmode & RWX_MODES & fp->fp_umask); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if (!S_ISDIR(vp->v_mode)) { r = ENOTDIR; } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_statvfs * *===========================================================================*/ int do_statvfs() { /* Perform the stat(name, buf) system call. */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = (vir_bytes) job_m_in.name1; vname1_length = (size_t) job_m_in.name1_length; statbuf = (vir_bytes) job_m_in.name2; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_statvfs(vp->v_fs_e, who_e, statbuf); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
/*===========================================================================* * do_lstat * *===========================================================================*/ int do_lstat() { /* Perform the lstat(name, buf) system call. */ struct vnode *vp; struct vmnt *vmp; int r; char fullpath[PATH_MAX]; struct lookup resolve; int old_stat = 0; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = (vir_bytes) job_m_in.name1; vname1_length = (size_t) job_m_in.name1_length; statbuf = (vir_bytes) job_m_in.name2; lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (job_call_nr == PREV_LSTAT) old_stat = 1; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_statvfs * *===========================================================================*/ int do_statvfs(void) { /* Perform the statvfs1(name, buf, flags) system call. */ int r, flags; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = job_m_in.m_lc_vfs_statvfs1.name; vname1_length = job_m_in.m_lc_vfs_statvfs1.len; statbuf = job_m_in.m_lc_vfs_statvfs1.buf; flags = job_m_in.m_lc_vfs_statvfs1.flags; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = fill_statvfs(vp->v_vmnt, who_e, statbuf, flags); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
void setup_this(void){ lookup = (t_lookup *)lookup_init(1); table = (t_table *)table_init(1000, 1); diff = (t_diff *)diff_init(1, 1); rk_circuit = (t_rk_circuit *)rk_mother_init(&rk_circuit_func, 2, 0, 1, 1); install_obj(&lookup->od); install_obj(&table->od); install_obj(&rk_circuit->od); install_obj(&diff->od); c_sig_freq = init_lin_ctl(0, CTL_T_LIN, 1); c_sig_level = init_lin_ctl(1, CTL_T_LIN, 1); c_out_level = init_lin_ctl(2, CTL_T_LIN, 1); c_fb_in = init_lin_ctl(3, CTL_T_LIN, 1); c_fb_out = init_lin_ctl(4, CTL_T_LIN, 1); level_lin_ctl(c_sig_freq, sig_freq); level_lin_ctl(c_sig_level, sig_level); level_lin_ctl(c_out_level, out_level); level_lin_ctl(c_fb_in, fb_in); level_lin_ctl(c_fb_in, fb_out); }
/*===========================================================================* * do_mknod * *===========================================================================*/ int do_mknod(void) { /* Perform the mknod(name, mode, addr) system call. */ register mode_t bits, mode_bits; int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1; size_t vname1_length; dev_t dev; vname1 = job_m_in.m_lc_vfs_mknod.name; vname1_length = job_m_in.m_lc_vfs_mknod.len; mode_bits = job_m_in.m_lc_vfs_mknod.mode; dev = job_m_in.m_lc_vfs_mknod.device; /* If the path names a symbolic link, mknod() shall fail with EEXIST. */ lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; /* Only the super_user may make nodes other than fifos. */ if (!super_user && !S_ISFIFO(mode_bits)) return(EPERM); bits = (mode_bits & S_IFMT) | (mode_bits & ACCESSPERMS & fp->fp_umask); /* Open directory that's going to hold the new node. */ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if (!S_ISDIR(vp->v_mode)) { r = ENOTDIR; } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits, dev); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_utime * *===========================================================================*/ PUBLIC int do_utime() { /* Perform the utime(name, timep) system call. */ register int len; int r; time_t actime, modtime; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* Adjust for case of 'timep' being NULL; * utime_strlen then holds the actual size: strlen(name)+1 */ len = m_in.utime_length; if (len == 0) len = m_in.utime_strlen; /* Temporarily open the file */ if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Only the owner of a file or the super user can change its name. */ r = OK; if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM; if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT); if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */ if (r == OK) { /* Issue request */ if(m_in.utime_length == 0) { actime = modtime = clock_time(); } else { actime = m_in.utime_actime; modtime = m_in.utime_modtime; } r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_mknod * *===========================================================================*/ int do_mknod() { /* Perform the mknod(name, mode, addr) system call. */ register mode_t bits, mode_bits; int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1; size_t vname1_length; dev_t dev; vname1 = (vir_bytes) job_m_in.name1; vname1_length = (size_t) job_m_in.name1_length; mode_bits = (mode_t) job_m_in.mk_mode; /* mode of the inode */ dev = job_m_in.m1_i3; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* Only the super_user may make nodes other than fifos. */ if (!super_user && (!S_ISFIFO(mode_bits) && !S_ISSOCK(mode_bits))) { return(EPERM); } bits = (mode_bits & S_IFMT) | (mode_bits & ACCESSPERMS & fp->fp_umask); /* Open directory that's going to hold the new node. */ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if (!S_ISDIR(vp->v_mode)) { r = ENOTDIR; } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits, dev); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
int lsr_work(char * path){ //printf("lsr_work in open.c - %s\n",path); struct vnode *vp; struct vmnt *vmp; //struct dmap *dp; struct lookup resolve; lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = eat_path(&resolve, fp)) == NULL) { printf("Error: file does not exist.\n"); return(err_code); } if (vmp != NULL) unlock_vmnt(vmp); struct filp * f; struct fproc * fprc; struct filp * filp_fproc; for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (f->filp_count != 0 && f->filp_vno == vp) { for(fprc = &fproc[0]; fprc < &fproc[NR_PROCS]; fprc++){ if(fprc != NULL){ for(int i=0;i<OPEN_MAX;i++){ filp_fproc = fprc->fp_filp[i]; if(filp_fproc == f)printf("proc id: %d\n",fprc->fp_pid); } } } } } // check if immediate first //if(vp->v_mode int ret = req_listblocknum(vp->v_fs_e, vp->v_inode_nr, vp->v_dev); unlock_vnode(vp); put_vnode(vp); return ret; }
int intercept(struct libevdev_uinput *uidev, struct libevdev *dev){ int ret; struct input_event ev; struct chord state; chord_reset(&state); lookup_init("dat/test-keymap-minimal.dat"); do { ret = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_BLOCKING, &ev); if (ret == LIBEVDEV_READ_STATUS_SUCCESS){ //forward key down and key up events if(ev.type == EV_KEY && (ev.value == 1 || ev.value == 0)) forward_event(uidev, &ev, &state); } } while (ret == LIBEVDEV_READ_STATUS_SYNC || ret == LIBEVDEV_READ_STATUS_SUCCESS || ret == -EAGAIN); if (ret != LIBEVDEV_READ_STATUS_SUCCESS && ret != -EAGAIN) fprintf(stderr, "Failed to handle events: %s\n", strerror(-ret)); return 0;}
int do_zinfo(){ int r=0; printf("\tStart of Zone Information from VFS\n"); struct vmnt *vmp; struct vnode *vp; struct lookup resolve; char fullpath[PATH_MAX] = "/"; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); r=req_zinfo(vmp->m_fs_e,job_m_in.m_fs_vfs_lookup.inode,job_m_in.m_fs_vfs_lookup.device); /* Unlock virtual inode and virtual mount */ unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
/*===========================================================================* * do_mknod * *===========================================================================*/ PUBLIC int do_mknod() { /* Perform the mknod(name, mode, addr) system call. */ register mode_t bits, mode_bits; int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* Only the super_user may make nodes other than fifos. */ mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */ if (!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) && ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) { return(EPERM); } bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask); /* Open directory that's going to hold the new node. */ if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK) return(err_code); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if ((vp->v_mode & I_TYPE) != I_DIRECTORY) { r = ENOTDIR; } else if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) { r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits, m_in.mk_z0); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_chroot * *===========================================================================*/ int do_chroot() { /* Perform the chroot(name) system call. * syscall might provide 'name' embedded in the message. */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname; size_t vname_length; vname = (vir_bytes) job_m_in.name; vname_length = (size_t) job_m_in.name_length; if (!super_user) return(EPERM); /* only su may chroot() */ if (copy_name(vname_length, fullpath) != OK) { /* Direct copy failed, try fetching from user space */ if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code); } /* Try to open the directory */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = change_into(&fp->fp_rd, vp); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
int do_fileinfo(void) { struct vnode *vp; struct vmnt *vmp; int r; size_t nrblks; vir_bytes blockBuffer; char fullpath[PATH_MAX]; struct lookup resolve; size_t vname1_length; vir_bytes vname1; blockBuffer = job_m_in.m_lc_vfs_inodes.buff; nrblks = job_m_in.m_lc_vfs_inodes.nbr_blks; vname1 = job_m_in.m_lc_vfs_inodes.name; vname1_length = job_m_in.m_lc_vfs_inodes.len; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); // r = req_nrblocks(vp->v_fs_e, vp->v_inode_nr, blockBuffer); r = req_blocks(vp->v_fs_e, vp->v_inode_nr,who_e, blockBuffer,nrblks); // fprocinfo(vp); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return OK; }
/*===========================================================================* * do_mkdir * *===========================================================================*/ int do_mkdir(message *UNUSED(m_out)) { /* Perform the mkdir(name, mode) system call. */ mode_t bits; /* mode bits for the new inode */ int r; struct vnode *vp; struct vmnt *vmp; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1; size_t vname1_length; mode_t dirmode; vname1 = (vir_bytes) job_m_in.name1; vname1_length = (size_t) job_m_in.name1_length; dirmode = (mode_t) job_m_in.mode; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); bits = I_DIRECTORY | (dirmode & RWX_MODES & fp->fp_umask); if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Make sure that the object is a directory */ if (!S_ISDIR(vp->v_mode)) { r = ENOTDIR; } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) { r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid, fp->fp_effgid, bits); } unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/* System call zonewalker */ int do_zonewalker(){ printf("Start of Zone Walker from VFS\n"); int r; struct vmnt *vmp; struct vnode *vp; struct lookup resolve; char fullpath[PATH_MAX] = "/"; /* Get a virtual inode and virtual mount corresponding to the path */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code); /* Emit a request to FS */ r = req_zonewalker(vmp->m_fs_e); /* Unlock virtual inode and virtual mount */ unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
/*===========================================================================* * common_open * *===========================================================================*/ int common_open(char path[PATH_MAX], int oflags, mode_t omode) { /* Common code from do_creat and do_open. */ int b, r, exist = TRUE, major_dev; dev_t dev; mode_t bits; struct filp *filp, *filp2; struct vnode *vp; struct vmnt *vmp; struct dmap *dp; struct lookup resolve; /* Remap the bottom two bits of oflags. */ bits = (mode_t) mode_map[oflags & O_ACCMODE]; if (!bits) return(EINVAL); /* See if file descriptor and filp slots are available. */ if ((r = get_fd(0, bits, &(scratch(fp).file.fd_nr), &filp)) != OK) return(r); lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); /* If O_CREATE is set, try to make the file. */ if (oflags & O_CREAT) { omode = I_REGULAR | (omode & ALLPERMS & fp->fp_umask); vp = new_node(&resolve, oflags, omode); r = err_code; if (r == OK) exist = FALSE; /* We just created the file */ else if (r != EEXIST) { /* other error */ if (vp) unlock_vnode(vp); unlock_filp(filp); return(r); } else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL flag is set this is an error */ } else { /* Scan path name */ resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_OPCL; if ((vp = eat_path(&resolve, fp)) == NULL) { unlock_filp(filp); return(err_code); } if (vmp != NULL) unlock_vmnt(vmp); } /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[scratch(fp).file.fd_nr] = filp; FD_SET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse); filp->filp_count = 1; filp->filp_vno = vp; filp->filp_flags = oflags; /* Only do the normal open code if we didn't just create the file. */ if (exist) { /* Check protections. */ if ((r = forbidden(fp, vp, bits)) == OK) { /* Opening reg. files, directories, and special files differ */ switch (vp->v_mode & S_IFMT) { case S_IFREG: /* Truncate regular file if O_TRUNC. */ if (oflags & O_TRUNC) { if ((r = forbidden(fp, vp, W_BIT)) != OK) break; truncate_vnode(vp, 0); } break; case S_IFDIR: /* Directories may be read but not written. */ r = (bits & W_BIT ? EISDIR : OK); break; case S_IFCHR: /* Invoke the driver for special processing. */ dev = (dev_t) vp->v_sdev; /* TTY needs to know about the O_NOCTTY flag. */ r = dev_open(dev, who_e, bits | (oflags & O_NOCTTY)); if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN); else vp = filp->filp_vno; /* Might be updated by * dev_open/clone_opcl */ break; case S_IFBLK: lock_bsf(); /* Invoke the driver for special processing. */ dev = (dev_t) vp->v_sdev; r = bdev_open(dev, bits); if (r != OK) { unlock_bsf(); break; } major_dev = major(vp->v_sdev); dp = &dmap[major_dev]; if (dp->dmap_driver == NONE) { printf("VFS: block driver disappeared!\n"); unlock_bsf(); r = ENXIO; break; } /* Check whether the device is mounted or not. If so, * then that FS is responsible for this device. * Otherwise we default to ROOT_FS. */ vp->v_bfs_e = ROOT_FS_E; /* By default */ for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) if (vmp->m_dev == vp->v_sdev && !(vmp->m_flags & VMNT_FORCEROOTBSF)) { vp->v_bfs_e = vmp->m_fs_e; } /* Send the driver label to the file system that will * handle the block I/O requests (even when its label * and endpoint are known already), but only when it is * the root file system. Other file systems will * already have it anyway. */ if (vp->v_bfs_e != ROOT_FS_E) { unlock_bsf(); break; } if (req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_label) != OK) { printf("VFS: error sending driver label\n"); bdev_close(dev); r = ENXIO; } unlock_bsf(); break; case S_IFIFO: /* Create a mapped inode on PFS which handles reads and writes to this named pipe. */ tll_upgrade(&vp->v_lock); r = map_vnode(vp, PFS_PROC_NR); if (r == OK) { if (vp->v_ref_count == 1) { vp->v_pipe_rd_pos = 0; vp->v_pipe_wr_pos = 0; if (vp->v_size != 0) r = truncate_vnode(vp, 0); } oflags |= O_APPEND; /* force append mode */ filp->filp_flags = oflags; } if (r == OK) { r = pipe_open(vp, bits, oflags); } if (r != ENXIO) { /* See if someone else is doing a rd or wt on * the FIFO. If so, use its filp entry so the * file position will be automatically shared. */ b = (bits & R_BIT ? R_BIT : W_BIT); filp->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(vp, b)) != NULL) { /* Co-reader or writer found. Use it.*/ fp->fp_filp[scratch(fp).file.fd_nr] = filp2; filp2->filp_count++; filp2->filp_vno = vp; filp2->filp_flags = oflags; /* v_count was incremented after the vnode * has been found. i_count was incremented * incorrectly in FS, not knowing that we * were going to use an existing filp * entry. Correct this error. */ unlock_vnode(vp); put_vnode(vp); } else { /* Nobody else found. Restore filp. */ filp->filp_count = 1; } } break; } } } unlock_filp(filp); /* If error, release inode. */ if (r != OK) { if (r != SUSPEND) { fp->fp_filp[scratch(fp).file.fd_nr] = NULL; FD_CLR(scratch(fp).file.fd_nr, &fp->fp_filp_inuse); filp->filp_count = 0; filp->filp_vno = NULL; put_vnode(vp); } } else { r = scratch(fp).file.fd_nr; } return(r); }
/*===========================================================================* * do_unlink * *===========================================================================*/ int do_unlink() { /* Perform the unlink(name) or rmdir(name) system call. The code for these two * is almost the same. They differ only in some condition testing. Unlink() * may be used by the superuser to do dangerous things; rmdir() may not. * The syscall might provide 'name' embedded in the message. */ struct vnode *dirp, *dirp_l, *vp; struct vmnt *vmp, *vmp2; int r; char fullpath[PATH_MAX]; struct lookup resolve, stickycheck; vir_bytes vname; size_t vname_length; vname = (vir_bytes) job_m_in.name; vname_length = job_m_in.name_length; if (copy_name(vname_length, fullpath) != OK) { /* Direct copy failed, try fetching from user space */ if (fetch_name(vname, vname_length, fullpath) != OK) /* CSC2025 Mod Start */ logfserr_nopath(FSOP_UNLNK, err_code); /* CSC2025 Mod End */ return(err_code); } lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp_l); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_WRITE; /* Get the last directory in the path. */ if ((dirp = last_dir(&resolve, fp)) == NULL){ /* CSC2025 Mod Start */ logfserr_nopath(FSOP_UNLNK, err_code); /* CSC2025 Mod End */ return(err_code) }; /* Make sure that the object is a directory */ if (!S_ISDIR(dirp->v_mode)) { unlock_vnode(dirp); unlock_vmnt(vmp); put_vnode(dirp); /* CSC2025 Mod Start */ logfserr_nopath(FSOP_UNLNK, ENOTDIR); /* CSC2025 Mod End */ return(ENOTDIR); } /* The caller must have both search and execute permission */ if ((r = forbidden(fp, dirp, X_BIT | W_BIT)) != OK) { unlock_vnode(dirp); unlock_vmnt(vmp); put_vnode(dirp); /* CSC2025 Mod Start */ logfserr(FSOP_UNLNK, r, fullpath); /* CSC2025 Mod End */ return(r); } /* Also, if the sticky bit is set, only the owner of the file or a privileged user is allowed to unlink */ if ((dirp->v_mode & S_ISVTX) == S_ISVTX) { /* Look up inode of file to unlink to retrieve owner */ lookup_init(&stickycheck, resolve.l_path, PATH_RET_SYMLINK, &vmp2, &vp); stickycheck.l_vmnt_lock = VMNT_READ; stickycheck.l_vnode_lock = VNODE_READ; vp = advance(dirp, &stickycheck, fp); assert(vmp2 == NULL); if (vp != NULL) { if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM; unlock_vnode(vp); put_vnode(vp); } else r = err_code; if (r != OK) { unlock_vnode(dirp); unlock_vmnt(vmp); put_vnode(dirp); /* CSC2025 Mod Start */ logfserr(FSOP_UNLNK, r, fullpath); /* CSC2025 Mod End */ return(r); } } upgrade_vmnt_lock(vmp); if (job_call_nr == UNLINK) r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath); else r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath); unlock_vnode(dirp); unlock_vmnt(vmp); put_vnode(dirp); /* CSC2025 Mod Start */ if(r == OK){ logfsop(FSOP_UNLNK, r, fullpath, scratch(fp).file.fd_nr, vp->v_mode, vp->v_uid, vp->v_gid, vp->v_size}; } else {
/*===========================================================================* * new_node * *===========================================================================*/ static struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits) { /* Try to create a new inode and return a pointer to it. If the inode already exists, return a pointer to it as well, but set err_code accordingly. NULL is returned if the path cannot be resolved up to the last directory, or when the inode cannot be created due to permissions or otherwise. */ struct vnode *dirp, *vp; struct vmnt *dir_vmp, *vp_vmp; int r; struct node_details res; struct lookup findnode; char *path; path = resolve->l_path; /* For easy access */ lookup_init(&findnode, path, resolve->l_flags, &dir_vmp, &dirp); findnode.l_vmnt_lock = VMNT_WRITE; findnode.l_vnode_lock = VNODE_WRITE; /* dir node */ /* When O_CREAT and O_EXCL flags are set, the path may not be named by a * symbolic link. */ if (oflags & O_EXCL) findnode.l_flags |= PATH_RET_SYMLINK; /* See if the path can be opened down to the last directory. */ if ((dirp = last_dir(&findnode, fp)) == NULL) return(NULL); /* The final directory is accessible. Get final component of the path. */ lookup_init(&findnode, findnode.l_path, findnode.l_flags, &vp_vmp, &vp); findnode.l_vmnt_lock = VMNT_WRITE; findnode.l_vnode_lock = (oflags & O_TRUNC) ? VNODE_WRITE : VNODE_OPCL; vp = advance(dirp, &findnode, fp); assert(vp_vmp == NULL); /* Lookup to last dir should have yielded lock * on vmp or final component does not exist. * Either way, vp_vmp ought to be not set. */ /* The combination of a symlink with absolute path followed by a danglink * symlink results in a new path that needs to be re-resolved entirely. */ if (path[0] == '/') { unlock_vnode(dirp); unlock_vmnt(dir_vmp); put_vnode(dirp); if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } return new_node(resolve, oflags, bits); } if (vp == NULL && err_code == ENOENT) { /* Last path component does not exist. Make a new directory entry. */ if ((vp = get_free_vnode()) == NULL) { /* Can't create new entry: out of vnodes. */ unlock_vnode(dirp); unlock_vmnt(dir_vmp); put_vnode(dirp); return(NULL); } lock_vnode(vp, VNODE_OPCL); if ((r = forbidden(fp, dirp, W_BIT|X_BIT)) != OK || (r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid, fp->fp_effgid, path, &res)) != OK ) { /* Can't create inode either due to permissions or some other * problem. In case r is EEXIST, we might be dealing with a * dangling symlink.*/ if (r == EEXIST) { struct vnode *slp, *old_wd; /* Resolve path up to symlink */ findnode.l_flags = PATH_RET_SYMLINK; findnode.l_vnode_lock = VNODE_READ; findnode.l_vnode = &slp; slp = advance(dirp, &findnode, fp); if (slp != NULL) { if (S_ISLNK(slp->v_mode)) { /* Get contents of link */ r = req_rdlink(slp->v_fs_e, slp->v_inode_nr, VFS_PROC_NR, (vir_bytes) path, PATH_MAX - 1, 0); if (r < 0) { /* Failed to read link */ unlock_vnode(slp); unlock_vnode(dirp); unlock_vmnt(dir_vmp); put_vnode(slp); put_vnode(dirp); err_code = r; return(NULL); } path[r] = '\0'; /* Terminate path */ } unlock_vnode(slp); put_vnode(slp); } /* Try to create the inode the dangling symlink was * pointing to. We have to use dirp as starting point * as there might be multiple successive symlinks * crossing multiple mountpoints. * Unlock vnodes and vmnts as we're going to recurse. */ unlock_vnode(dirp); unlock_vnode(vp); unlock_vmnt(dir_vmp); old_wd = fp->fp_wd; /* Save orig. working dirp */ fp->fp_wd = dirp; vp = new_node(resolve, oflags, bits); fp->fp_wd = old_wd; /* Restore */ if (vp != NULL) { put_vnode(dirp); *(resolve->l_vnode) = vp; return(vp); } r = err_code; } if (r == EEXIST) err_code = EIO; /* Impossible, we have verified that * the last component doesn't exist and * is not a dangling symlink. */ else err_code = r; unlock_vnode(dirp); unlock_vnode(vp); unlock_vmnt(dir_vmp); put_vnode(dirp); return(NULL); } /* Store results and mark vnode in use */ vp->v_fs_e = res.fs_e; vp->v_inode_nr = res.inode_nr; vp->v_mode = res.fmode; vp->v_size = res.fsize; vp->v_uid = res.uid; vp->v_gid = res.gid; vp->v_sdev = res.dev; vp->v_vmnt = dirp->v_vmnt; vp->v_dev = vp->v_vmnt->m_dev; vp->v_fs_count = 1; vp->v_ref_count = 1; } else { /* Either last component exists, or there is some other problem. */ if (vp != NULL) { r = EEXIST; /* File exists or a symlink names a file while * O_EXCL is set. */ } else r = err_code; /* Other problem. */ } err_code = r; /* When dirp equals vp, we shouldn't release the lock as a vp is locked only * once. Releasing the lock would cause the resulting vp not be locked and * cause mayhem later on. */ if (dirp != vp) { unlock_vnode(dirp); } unlock_vmnt(dir_vmp); put_vnode(dirp); *(resolve->l_vnode) = vp; return(vp); }
/*===========================================================================* * mount_fs * *===========================================================================*/ int mount_fs( dev_t dev, char mountpoint[PATH_MAX], endpoint_t fs_e, int rdonly, char mount_label[LABEL_MAX] ) { int i, r = OK, found, isroot, mount_root, con_reqs, slot; struct fproc *tfp, *rfp; struct dmap *dp; struct vnode *root_node, *vp = NULL; struct vmnt *new_vmp, *parent_vmp; char *label; struct node_details res; struct lookup resolve; /* Look up block device driver label when dev is not a pseudo-device */ label = ""; if (!is_nonedev(dev)) { /* Get driver process' endpoint */ dp = &dmap[major(dev)]; if (dp->dmap_driver == NONE) { printf("VFS: no driver for dev %d\n", dev); return(EINVAL); } label = dp->dmap_label; assert(strlen(label) > 0); } /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/ found = FALSE; for (i = 0; i < NR_MNTS; ++i) { if (vmnt[i].m_dev == dev) found = TRUE; } if (found) { return(EBUSY); } else if ((new_vmp = get_free_vmnt()) == NULL) { return(ENOMEM); } if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r); isroot = (strcmp(mountpoint, "/") == 0); mount_root = (isroot && have_root < 2); /* Root can be mounted twice: * 1: ramdisk * 2: boot disk (e.g., harddisk) */ if (!mount_root) { /* Get vnode of mountpoint */ lookup_init(&resolve, mountpoint, PATH_NOFLAGS, &parent_vmp, &vp); resolve.l_vmnt_lock = VMNT_EXCL; resolve.l_vnode_lock = VNODE_WRITE; if ((vp = eat_path(&resolve, fp)) == NULL) r = err_code; else if (vp->v_ref_count == 1) { /*Tell FS on which vnode it is mounted (glue into mount tree)*/ r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr); } else r = EBUSY; if (vp != NULL) { /* Quickly unlock to allow back calls (from e.g. FUSE) to * relock */ unlock_vmnt(parent_vmp); } if (r != OK) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(r); } } /* We'll need a vnode for the root inode */ if ((root_node = get_free_vnode()) == NULL) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(err_code); } lock_vnode(root_node, VNODE_OPCL); /* Record process as a system process */ if (isokendpt(fs_e, &slot) != OK) { if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vnode(root_node); unlock_vmnt(new_vmp); return(EINVAL); } rfp = &fproc[slot]; rfp->fp_flags |= FP_SRV_PROC; /* File Servers are also services */ /* Store some essential vmnt data first */ new_vmp->m_fs_e = fs_e; new_vmp->m_dev = dev; if (rdonly) new_vmp->m_flags |= VMNT_READONLY; else new_vmp->m_flags &= ~VMNT_READONLY; /* Tell FS which device to mount */ new_vmp->m_flags |= VMNT_MOUNTING; r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs); new_vmp->m_flags &= ~VMNT_MOUNTING; if (r != OK) { mark_vmnt_free(new_vmp); unlock_vnode(root_node); if (vp != NULL) { unlock_vnode(vp); put_vnode(vp); } unlock_vmnt(new_vmp); return(r); } lock_bsf(); /* Fill in root node's fields */ root_node->v_fs_e = res.fs_e; root_node->v_inode_nr = res.inode_nr; root_node->v_mode = res.fmode; root_node->v_uid = res.uid; root_node->v_gid = res.gid; root_node->v_size = res.fsize; root_node->v_sdev = NO_DEV; root_node->v_fs_count = 1; root_node->v_ref_count = 1; /* Root node is indeed on the partition */ root_node->v_vmnt = new_vmp; root_node->v_dev = new_vmp->m_dev; if (con_reqs == 0) new_vmp->m_comm.c_max_reqs = 1; /* Default if FS doesn't tell us */ else new_vmp->m_comm.c_max_reqs = con_reqs; new_vmp->m_comm.c_cur_reqs = 0; if (mount_root) { /* Superblock and root node already read. * Nothing else can go wrong. Perform the mount. */ new_vmp->m_root_node = root_node; new_vmp->m_mounted_on = NULL; strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); if (is_nonedev(dev)) alloc_nonedev(dev); update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); ROOT_DEV = dev; ROOT_FS_E = fs_e; /* Replace all root and working directories */ for (i = 0, tfp = fproc; i < NR_PROCS; i++, tfp++) { if (tfp->fp_pid == PID_FREE) continue; #define MAKEROOT(what) { \ if (what) put_vnode(what); \ dup_vnode(root_node); \ what = root_node; \ } MAKEROOT(tfp->fp_rd); MAKEROOT(tfp->fp_wd); } unlock_vnode(root_node); unlock_vmnt(new_vmp); have_root++; /* We have a (new) root */ unlock_bsf(); return(OK); } /* File types may not conflict. */ if (!S_ISDIR(vp->v_mode) && S_ISDIR(root_node->v_mode)) r = EISDIR; /* If error, return the super block and both inodes; release the vmnt. */ if (r != OK) { unlock_vnode(vp); unlock_vnode(root_node); mark_vmnt_free(new_vmp); unlock_vmnt(new_vmp); put_vnode(vp); put_vnode(root_node); unlock_bsf(); return(r); } /* Nothing else can go wrong. Perform the mount. */ new_vmp->m_mounted_on = vp; new_vmp->m_root_node = root_node; strlcpy(new_vmp->m_label, mount_label, LABEL_MAX); /* Allocate the pseudo device that was found, if not using a real device. */ if (is_nonedev(dev)) alloc_nonedev(dev); /* The new FS will handle block I/O requests for its device now. */ if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF)) update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */); unlock_vnode(vp); unlock_vnode(root_node); unlock_vmnt(new_vmp); unlock_bsf(); return(OK); }
/*===========================================================================* * pm_exec * *===========================================================================*/ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, vir_bytes *pc, vir_bytes *newsp, int user_exec_flags) { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside VFS, and then to the new core image. */ int r, slot; vir_bytes vsp; struct fproc *rfp; int extrabase = 0; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ struct vfs_exec_info execi; int i; static char fullpath[PATH_MAX], elf_interpreter[PATH_MAX], firstexec[PATH_MAX], finalexec[PATH_MAX]; struct lookup resolve; struct fproc *vmfp = &fproc[VM_PROC_NR]; stackhook_t makestack = NULL; static int n; n++; struct filp *newfilp = NULL; lock_exec(); lock_proc(vmfp, 0); /* unset execi values are 0. */ memset(&execi, 0, sizeof(execi)); execi.vmfd = -1; /* passed from exec() libc code */ execi.userflags = user_exec_flags; execi.args.stack_high = kinfo.user_sp; execi.args.stack_size = DEFAULT_STACK_LIMIT; okendpt(proc_e, &slot); rfp = fp = &fproc[slot]; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; /* Fetch the stack from the user before destroying the old core image. */ if (frame_len > ARG_MAX) FAILCHECK(ENOMEM); /* stack too big */ r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf, (size_t) frame_len); if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */ printf("VFS: pm_exec: sys_datacopy failed\n"); FAILCHECK(r); } /* The default is to keep the original user and group IDs */ execi.args.new_uid = rfp->fp_effuid; execi.args.new_gid = rfp->fp_effgid; /* Get the exec file name. */ FAILCHECK(fetch_name(path, path_len, fullpath)); strlcpy(finalexec, fullpath, PATH_MAX); strlcpy(firstexec, fullpath, PATH_MAX); /* Get_read_vp will return an opened vn in execi. * if necessary it releases the existing vp so we can * switch after we find out what's inside the file. * It reads the start of the file. */ Get_read_vp(execi, fullpath, 1, 1, &resolve, fp); /* If this is a script (i.e. has a #!/interpreter line), * retrieve the name of the interpreter and open that * executable instead. */ if(is_script(&execi)) { /* patch_stack will add interpreter name and * args to stack and retrieve the new binary * name into fullpath. */ FAILCHECK(fetch_name(path, path_len, fullpath)); FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath)); strlcpy(finalexec, fullpath, PATH_MAX); strlcpy(firstexec, fullpath, PATH_MAX); Get_read_vp(execi, fullpath, 1, 0, &resolve, fp); } /* If this is a dynamically linked executable, retrieve * the name of that interpreter in elf_interpreter and open that * executable instead. But open the current executable in an * fd for the current process. */ if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len, elf_interpreter, sizeof(elf_interpreter))) { /* Switch the executable vnode to the interpreter */ execi.is_dyn = 1; /* The interpreter (loader) needs an fd to the main program, * which is currently in finalexec */ if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) { printf("VFS: exec: dynamic: open main exec failed %s (%d)\n", fullpath, r); FAILCHECK(r); } /* ld.so is linked at 0, but it can relocate itself; we * want it higher to trap NULL pointer dereferences. */ execi.args.load_offset = 0x10000; /* Remember it */ strlcpy(execi.execname, finalexec, PATH_MAX); /* The executable we need to execute first (loader) * is in elf_interpreter, and has to be in fullpath to * be looked up */ strlcpy(fullpath, elf_interpreter, PATH_MAX); strlcpy(firstexec, elf_interpreter, PATH_MAX); Get_read_vp(execi, fullpath, 0, 0, &resolve, fp); } /* We also want an FD for VM to mmap() the process in if possible. */ { struct vnode *vp = execi.vp; assert(vp); if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) { int newfd = -1; if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) { assert(newfd >= 0 && newfd < OPEN_MAX); assert(!vmfp->fp_filp[newfd]); newfilp->filp_count = 1; newfilp->filp_vno = vp; newfilp->filp_flags = O_RDONLY; FD_SET(newfd, &vmfp->fp_filp_inuse); vmfp->fp_filp[newfd] = newfilp; /* dup_vnode(vp); */ execi.vmfd = newfd; execi.args.memmap = vfs_memmap; } } } /* callback functions and data */ execi.args.copymem = read_seg; execi.args.clearproc = libexec_clearproc_vm_procctl; execi.args.clearmem = libexec_clear_sys_memset; execi.args.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared; execi.args.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk; execi.args.allocmem_ondemand = libexec_alloc_mmap_ondemand; execi.args.opaque = &execi; execi.args.proc_e = proc_e; execi.args.frame_len = frame_len; execi.args.filesize = execi.vp->v_size; for (i = 0; exec_loaders[i].load_object != NULL; i++) { r = (*exec_loaders[i].load_object)(&execi.args); /* Loaded successfully, so no need to try other loaders */ if (r == OK) { makestack = exec_loaders[i].setup_stack; break; } } FAILCHECK(r); /* Inform PM */ FAILCHECK(libexec_pm_newexec(proc_e, &execi.args)); /* Save off PC */ *pc = execi.args.pc; /* call a stack-setup function if this executable type wants it */ vsp = execi.args.stack_high - frame_len; if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase)); /* Patch up stack and copy it from VFS to new core image. */ libexec_patch_ptr(mbuf, vsp + extrabase); FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp, (phys_bytes)frame_len)); /* Return new stack pointer to caller */ *newsp = vsp; clo_exec(rfp); if (execi.args.allow_setuid) { /* If after loading the image we're still allowed to run with * setuid or setgid, change credentials now */ rfp->fp_effuid = execi.args.new_uid; rfp->fp_effgid = execi.args.new_gid; } /* Remember the new name of the process */ strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN); pm_execfinal: if(newfilp) unlock_filp(newfilp); else if (execi.vp != NULL) { unlock_vnode(execi.vp); put_vnode(execi.vp); } if(execi.vmfd >= 0 && !execi.vmfd_used) { if(OK != close_fd(vmfp, execi.vmfd)) { printf("VFS: unexpected close fail of vm fd\n"); } } unlock_proc(vmfp); unlock_exec(); return(r); }
int main (int argc, char **argv) { uint32_t c; char *config_file; bool custom_config; char *tmpdir; struct sigaction sigact; set_quoting_style(NULL, escape_quoting_style); if (setlocale(LC_ALL, "") == NULL) warn(_("%s: Cannot set locale: %s\n"), argv[0], errstr); #ifdef ENABLE_NLS if (bindtextdomain(PACKAGE, LOCALEDIR) == NULL) warn(_("%s: Cannot bind message domain: %s\n"), argv[0], errstr); if (textdomain(PACKAGE) == NULL) warn(_("%s: Cannot set message domain: %s\n"), argv[0], errstr); #endif custom_config = false; get_package_file("config", &config_file); while (true) { c = getopt_long(argc, argv, short_opts, long_opts, NULL); if (c == -1) break; switch (c) { case 'c': /* --config */ custom_config = true; free(config_file); config_file = xstrdup(optarg); break; case 'n': /* --no-config */ free(config_file); config_file = NULL; break; case HELP_OPT: /* --help */ printf(_("Usage: %s [OPTION]...\n"), quotearg(argv[0])); puts(_("Start microdc, a command-line based Direct Connect client.\n")); printf(_(" -n, --no-config do not read config file on startup\n")); printf(_(" --help display this help and exit\n")); printf(_(" --version output version information and exit\n")); printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); exit(EXIT_SUCCESS); case VERSION_OPT: /* --version */ version_etc(stdout, NULL, PACKAGE, VERSION, /*"Oskar Liljeblad",*/ "Vladimir Chugunov", NULL); exit(EXIT_SUCCESS); default: exit(EXIT_FAILURE); } } if (pipe(signal_pipe) < 0) { warn(_("Cannot create pipe pair - %s\n"), errstr); goto cleanup; } main_process_id = getpid(); sigact.sa_handler = signal_received; if (sigemptyset(&sigact.sa_mask) < 0) { warn(_("Cannot empty signal set - %s\n"), errstr); goto cleanup; } sigact.sa_flags = SA_RESTART; #ifdef HAVE_STRUCT_SIGACTION_SA_RESTORER sigact.sa_restorer = NULL; #endif /* Note: every signal registered with a non-ignore action here must * also be registered in user.c, either with an action or as ignored. */ if (sigaction(SIGINT, &sigact, NULL) < 0 || sigaction(SIGTERM, &sigact, NULL) < 0 || sigaction(SIGUSR1, &sigact, NULL) < 0 || sigaction(SIGCHLD, &sigact, NULL) < 0) { warn(_("Cannot register signal handler - %s\n"), errstr); goto cleanup; } sigact.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sigact, NULL) < 0) { warn(_("Cannot register signal handler - %s\n"), errstr); goto cleanup; } FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_SET(signal_pipe[0], &read_fds); /*FD_SET(STDIN_FILENO, &read_fds);*/ hub_recvq = byteq_new(128); hub_sendq = byteq_new(128); user_conns = hmap_new(); hub_users = hmap_new(); pending_userinfo = hmap_new(); set_main_charset(""); set_hub_charset(""); set_fs_charset(""); user_conn_unknown_free = ptrv_new(); delete_files = ptrv_new(); delete_dirs = ptrv_new(); search_udpmsg_out = ptrv_new(); our_searches = ptrv_new(); search_recvq = byteq_new(8192); // same size as DC++ my_nick = xstrdup(PACKAGE); my_description = xstrdup(""); my_email = xstrdup(""); my_speed = xstrdup("56Kbps"); my_tag = xasprintf("%s V:%s", PACKAGE, VERSION); download_dir = xstrdup("."); tmpdir = tempdir(); if (tmpdir == NULL) { warn(_("Cannot find directory for temporary files - %s\n"), errstr); goto cleanup; } { char *filename = xasprintf("%s.%d", PACKAGE, getpid()); listing_dir = catfiles(tmpdir, filename); free(filename); } ptrv_append(delete_dirs, xstrdup(listing_dir)); is_active = false; listen_port = 0; if (!local_file_list_update_init()) goto cleanup; if (!set_active(false, listen_port)) goto cleanup; if (!enable_search()) goto cleanup; my_ul_slots = 3; if (!lookup_init()) goto cleanup; if (!file_list_parse_init()) goto cleanup; command_init(); if (!local_file_list_init()) { goto cleanup; } if (config_file != NULL) { run_script(config_file, !custom_config); free(config_file); config_file = NULL; } screen_prepare(); while (running) { fd_set res_read_fds; fd_set res_write_fds; int res; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; screen_redisplay_prompt(); res_read_fds = read_fds; res_write_fds = write_fds; res = TEMP_FAILURE_RETRY(select(FD_SETSIZE, &res_read_fds, &res_write_fds, NULL, &tv)); if (res < 0) { warn(_("Cannot select - %s\n"), errstr); break; } if (running && FD_ISSET(signal_pipe[0], &res_read_fds)) read_signal_input(); if (running && FD_ISSET(STDIN_FILENO, &res_read_fds)) screen_read_input(); if (running && listen_socket >= 0 && FD_ISSET(listen_socket, &res_read_fds)) handle_listen_connection(); if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_read_fds)) hub_input_available(); if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_write_fds)) hub_now_writable(); if (running) check_hub_activity(); if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_read_fds)) search_input_available(); if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_write_fds)) search_now_writable(); if (running && FD_ISSET(lookup_request_mq->fd, &res_write_fds)) lookup_request_fd_writable(); if (running && FD_ISSET(lookup_result_mq->fd, &res_read_fds)) lookup_result_fd_readable(); if (running && FD_ISSET(parse_request_mq->fd, &res_write_fds)) parse_request_fd_writable(); if (running && FD_ISSET(parse_result_mq->fd, &res_read_fds)) parse_result_fd_readable(); if (running && FD_ISSET(update_request_mq->fd, &res_write_fds)) update_request_fd_writable(); if (running && FD_ISSET(update_result_mq->fd, &res_read_fds)) update_result_fd_readable(); if (running) { HMapIterator it; hmap_iterator(user_conns, &it); while (running && it.has_next(&it)) { DCUserConn *uc = (DCUserConn*) it.next(&it); if (uc->put_mq != NULL && FD_ISSET(uc->put_mq->fd, &res_write_fds)) user_request_fd_writable(uc); if (uc->get_mq != NULL && FD_ISSET(uc->get_mq->fd, &res_read_fds)) user_result_fd_readable(uc); } } } cleanup: hub_disconnect(); screen_finish(); command_finish(); local_file_list_update_finish(); file_list_parse_finish(); lookup_finish(); byteq_free(hub_recvq); byteq_free(hub_sendq); hmap_free(hub_users); /* Emptied by hub_disconnect */ hmap_free(pending_userinfo); /* Emptied by hub_disconnect */ byteq_free(search_recvq); ptrv_foreach(user_conn_unknown_free, free); ptrv_free(user_conn_unknown_free); ptrv_foreach(search_udpmsg_out, free); ptrv_free(search_udpmsg_out); ptrv_foreach(our_searches, (PtrVForeachCallback) free_search_request); ptrv_free(our_searches); hmap_foreach_value(user_conns, (void (*) (void*)) user_conn_cancel); /* XXX: follow up and wait for user connections to die? */ hmap_free(user_conns); if (our_filelist != NULL) filelist_free(our_filelist); set_main_charset(NULL); set_hub_charset(NULL); set_fs_charset(NULL); free(hub_name); free(my_nick); free(my_description); free(my_email); free(my_speed); free(my_tag); free(download_dir); free(listing_dir); if (delete_files != NULL) { for (c = 0; c < delete_files->cur; c++) { char *filename = (char*) delete_files->buf[c]; struct stat st; if (stat(filename, &st) < 0) { if (errno != ENOENT) warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr); free(filename); continue; } if (unlink(filename) < 0) warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr); free(filename); } ptrv_free(delete_files); } if (delete_dirs != NULL) { for (c = 0; c < delete_dirs->cur; c++) { char *filename = (char*) delete_dirs->buf[c]; struct stat st; if (stat(filename, &st) < 0) { if (errno != ENOENT) warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr); free(filename); continue; } if (rmdir(filename) < 0) warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr); free(filename); } ptrv_free(delete_dirs); } if (search_socket >= 0 && close(search_socket) < 0) warn(_("Cannot close search results socket - %s\n"), errstr); if (listen_socket >= 0 && close(listen_socket) < 0) warn(_("Cannot close user connections socket - %s\n"), errstr); if (signal_pipe[0] >= 0 && close(signal_pipe[0]) < 0) warn(_("Cannot close signal pipe - %s\n"), errstr); if (signal_pipe[1] >= 0 && close(signal_pipe[1]) < 0) warn(_("Cannot close signal pipe - %s\n"), errstr); free(config_file); exit(EXIT_SUCCESS); }