Esempio n. 1
0
/*===========================================================================*
 *				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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
/*===========================================================================*
 *				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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
/*===========================================================================*
 *                             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);
}
Esempio n. 6
0
/*===========================================================================*
 *				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);
}
Esempio n. 7
0
/*===========================================================================*
 *                              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);
}
Esempio n. 8
0
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);
}
Esempio n. 10
0
/*===========================================================================*
 *				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;
}
Esempio n. 11
0
/*===========================================================================*
 *                             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);
}
Esempio n. 12
0
/*===========================================================================*
 *				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;
}
Esempio n. 13
0
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);
}
Esempio n. 15
0
/*===========================================================================*
 *				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);
}
Esempio n. 16
0
/*===========================================================================*
 *				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);
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
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;}
Esempio n. 19
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;
}
Esempio n. 20
0
/*===========================================================================*
 *				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);
}
Esempio n. 21
0
/*===========================================================================*
 *				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);
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
/*===========================================================================*
 *				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);
}
Esempio n. 24
0
/* 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;
}
Esempio n. 25
0
/*===========================================================================*
 *				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);
}
Esempio n. 26
0
/*===========================================================================*
 *				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 {
Esempio n. 27
0
/*===========================================================================*
 *				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);
}
Esempio n. 28
0
/*===========================================================================*
 *                              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);
}
Esempio n. 29
0
/*===========================================================================*
 *				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);
}
Esempio n. 30
0
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);
}