示例#1
0
文件: stadir.c 项目: vjanandr/inode-2
/*===========================================================================*
 *				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);
}
示例#2
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);
}
示例#3
0
文件: stadir.c 项目: tizzybec/minix
/*===========================================================================*
 *				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;
}
示例#4
0
文件: stadir.c 项目: vjanandr/inode-2
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;
}
示例#5
0
文件: stadir.c 项目: vjanandr/inode-2
/*===========================================================================*
 *                             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);
}
示例#6
0
文件: stadir.c 项目: vjanandr/inode-2
/*===========================================================================*
 *				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;
}
示例#7
0
文件: stadir.c 项目: tizzybec/minix
/*===========================================================================*
 *                             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);
}
示例#8
0
/*===========================================================================*
 *				do_link					     *
 *===========================================================================*/
int do_link()
{
/* Perform the link(name1, name2) system call. */
  int r = 0;
  endpoint_t linked_fs_e, link_lastdir_fs_e;
  struct vnode *vp, *vp_d;

  /* See if 'name1' (file to be linked to) exists. */ 
  if(fetch_name(user_fullpath, PATH_MAX, m_in.name1) < 0) return(err_code);
  if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);

  /* Does the final directory of 'name2' exist? */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.name2) < 0)
	r = err_code;
  else if ((vp_d = last_dir()) == NIL_VNODE)
	r = err_code; 
  if (r != 0) {
	  put_vnode(vp);
	  return(r);
  }

  /* Check for links across devices. */
  if(vp->v_fs_e != vp_d->v_fs_e)
  	r = -EXDEV;
  else 
	r = forbidden(vp_d, W_BIT | X_BIT);

  if (r == 0)
	r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath,
		     vp->v_inode_nr);
  
  put_vnode(vp);
  put_vnode(vp_d);
  return(r);
}
示例#9
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);
}
示例#10
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);
}
示例#11
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;
}
示例#12
0
int show_file_info(char* name) 
{
	int inode;
	Inode temp;
	char original_name_path[30];
	int original_inode = inode_num;//记录当前的inode

	strcpy(original_name_path, name);
	if (eat_path(name) == -1) {
		printf("stat: cannot stat‘%s’: No such file or directory\n", original_name_path);
		return -1;
	}

	inode = check_name(inode_num, name);
	if (inode == -1) {
		printf("stat: cannot stat '%s': No such file or directory\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}
	
	fseek(Disk, InodeBeg + sizeof(Inode)*inode, SEEK_SET);
	fread(&temp, sizeof(Inode), 1, Disk);

	printf("File: '%s'\n", original_name_path);

	printf("Size: %d\tBlocks: %d\t", temp.file_size, temp.blk_num);
	temp.type == Directory ? printf("type: directory\n") : printf("type: regular file\n");

	printf("Inode: %d\t", inode);
	printf("Access: ");
	temp.access[0][user_num] ? printf("r") : printf("-");
	temp.access[1][user_num] ? printf("w") : printf("-");
	temp.access[2][user_num] ? printf("x") : printf("-");
	printf("\n");
	printf("Access: %s", ctime(&temp.i_atime));
	printf("Modify: %s", ctime(&temp.i_mtime));
	printf("Change: %s", ctime(&temp.i_ctime));

	close_dir(inode_num);
	inode_num = original_inode;
	open_dir(inode_num);
	return 0;
}
示例#13
0
/*===========================================================================*
 *				scall_utime				     *
 *===========================================================================*/
int scall_utime(void)
{
	/* Perform the utime(name, timep) system call. */
	register int len;
	int r;
	time_t actime, modtime;
	struct utimbuf ut;
	struct vnode *vp;

	/* Adjust for case of 'timep' being NULL. */
	if (fetch_name(user_fullpath, PATH_MAX, m_in.utime_file) < 0)
		return(err_code);

	if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);

	/* get times buffer if not 0 */
	if (m_in.utime_ptimes != 0) {
		r = sys_datacopy(who_e, (vir_bytes)m_in.utime_ptimes, ENDPT_SELF, (vir_bytes)&ut, sizeof(struct utimbuf));

		if (r != 0)
			return r;
	}

	/* Only the owner of a file or the super user can change its name. */
	r = 0;
	if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = -EPERM;
	if (m_in.utime_ptimes == 0 && r != 0) r = forbidden(vp, W_BIT);
	if (read_only(vp) != 0) r = -EROFS; /* Not even su can touch if R/O */

	if (r == 0) {
		/* Issue request */
		if (m_in.utime_ptimes == 0) {
			actime = modtime = clock_time();
		} else {
			actime = ut.actime;
			modtime = ut.modtime;
		}
		r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
	}

	put_vnode(vp);

	return(r);
}
示例#14
0
/*===========================================================================*
 *				do_truncate				     *
 *===========================================================================*/
int do_truncate()
{
/* truncate_vnode() does the actual work of do_truncate() and do_ftruncate().
 * do_truncate() and do_ftruncate() have to get hold of the inode, either
 * by name or fd, do checks on it, and call truncate_inode() to do the
 * work.
 */
  struct vnode *vp;
  int r;

  /* Temporarily open file */
  if (fetch_name(user_fullpath, PATH_MAX, m_in.m_data6) < 0) return(err_code);
  if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
  
  /* Ask FS to truncate the file */
  if ((r = forbidden(vp, W_BIT)) == 0)
  	r = truncate_vnode(vp, m_in.flength);

  put_vnode(vp);
  return(r);
}
示例#15
0
文件: stadir.c 项目: vjanandr/inode-2
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;
}
示例#16
0
文件: stadir.c 项目: tizzybec/minix
/*===========================================================================*
 *				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);
}
示例#17
0
/*===========================================================================*
 *				do_utime				     *
 *===========================================================================*/
PUBLIC int do_utime()
{
/* Perform the utime(name, timep) system call. */

  register struct inode *rip;
  register int len, r;

  /* 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) != OK) return(err_code);
  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);

  /* Only the owner of a file or the super_user can change its time. */
  r = OK;
  if (rip->i_uid != fp->fp_effuid && !super_user) r = EPERM;
  if (m_in.utime_length == 0 && r != OK) r = forbidden(rip, W_BIT);
  if (read_only(rip) != OK) r = EROFS;	/* not even su can touch if R/O */
  if (r == OK) {
	if (m_in.utime_length == 0) {
		rip->i_atime = clock_time();
		rip->i_mtime = rip->i_atime;
	} else {
		rip->i_atime = m_in.utime_actime;
		rip->i_mtime = m_in.utime_modtime;
	}
	rip->i_update = CTIME;	/* discard any stale ATIME and MTIME flags */
	rip->i_dirt = DIRTY;
  }

  put_inode(rip);
  return(r);
}
示例#18
0
/*===========================================================================*
 *				do_utime				     *
 *===========================================================================*/
PUBLIC int do_utime()
{
/* Perform the utime(name, timep) system call. */
  register int len;
  int r;
  uid_t uid;
  time_t actime, modtime;
  struct vnode *vp;
  
  /* 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) != OK) return(err_code);
  if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) 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(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);
  }

  put_vnode(vp);
  return(r);
}
示例#19
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);
}
示例#20
0
/*===========================================================================*
 *				common_open				     *
 *===========================================================================*/
PUBLIC int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */
  int b, r, exist = TRUE;
  dev_t dev;
  mode_t bits;
  struct filp *fil_ptr, *filp2;
  struct vnode *vp;
  struct vmnt *vmp;
  struct dmap *dp;

  /* 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, &m_in.fd, &fil_ptr)) != OK) return(r);

  /* If O_CREATE is set, try to make the file. */
  if (oflags & O_CREAT) {
        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
	vp = new_node(oflags, omode);
	r = err_code;
	if (r == OK) exist = FALSE; /* We just created the file */
	else if (r != EEXIST) return(r);  /* other error */ 
	else exist = !(oflags & O_EXCL);  /* file exists, if the O_EXCL
					     flag is set this is an error */
  } else {
	/* Scan path name */
	if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
  }

  /* Claim the file descriptor and filp slot and fill them in. */
  fp->fp_filp[m_in.fd] = fil_ptr;
  FD_SET(m_in.fd, &fp->fp_filp_inuse);
  fil_ptr->filp_count = 1;
  fil_ptr->filp_vno = vp;
  fil_ptr->filp_flags = oflags;

  /* Only do the normal open code if we didn't just create the file. */
  if(exist) {
	/* Check protections. */
	if ((r = forbidden(vp, bits)) == OK) {
		/* Opening reg. files, directories, and special files differ */
		switch (vp->v_mode & I_TYPE) {
		   case I_REGULAR:
		   	/* Truncate regular file if O_TRUNC. */
		   	if (oflags & O_TRUNC) {
		   		if ((r = forbidden(vp, W_BIT)) != OK)
		   			break;
		   		truncate_vnode(vp, 0);
		   	}
		   	break;
		   case I_DIRECTORY:
		   	/* Directories may be read but not written. */
		   	r = (bits & W_BIT ? EISDIR : OK);
		   	break;
		   case I_CHAR_SPECIAL:
			/* 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);
		   	break;
		   case I_BLOCK_SPECIAL:
			/* Invoke the driver for special processing. */
			dev = (dev_t) vp->v_sdev;
			r = bdev_open(dev, bits);
			if (r != OK) break;

			/* Check whether the device is mounted or not. If so,
			   then that FS is responsible for this device. Else
			   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) 
					vp->v_bfs_e = vmp->m_fs_e;

			/* Get the driver endpoint of the block spec device */
			dp = &dmap[major(vp->v_sdev)];

			/* Send the driver endpoint to the file system (even
			 * when known already).
			 */
			if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev,
					       dp->dmap_driver)) != OK) {
				printf("VFS: error sending driver endpoint\n");
				bdev_close(dev);
				r = ENXIO;
			}
			break;

		   case I_NAMED_PIPE:
			/* Create a mapped inode on PFS which handles reads
			   and writes to this named pipe. */
			r = map_vnode(vp);
			if (r == OK) {
				vp->v_pipe = I_PIPE;
				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 */
				fil_ptr->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);
				fil_ptr->filp_count = 0; /* don't find self */
				if ((filp2 = find_filp(vp, b)) != NULL) {
					/* Co-reader or writer found. Use it.*/
					fp->fp_filp[m_in.fd] = 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.
					 */
					put_vnode(vp);
				} else {
					/* Nobody else found. Restore filp. */
					fil_ptr->filp_count = 1;
				}
			} 
			break;
		}
	}
  }

  /* If error, release inode. */
  if (r != OK) {
	if (r == SUSPEND) return(r);		/* Oops, just suspended */
	fp->fp_filp[m_in.fd] = NULL;
  	FD_CLR(m_in.fd, &fp->fp_filp_inuse);
	fil_ptr->filp_count= 0;
	put_vnode(vp);     
	fil_ptr->filp_vno = NULL;
	return(r);
  }
  
  return(m_in.fd);
}
示例#21
0
/*===========================================================================*
 *				do_link					     *
 *===========================================================================*/
PUBLIC int do_link()
{
/* Perform the link(name1, name2) system call. */

  register struct inode *ip, *rip;
  register int r;
  char string[NAME_MAX];
  struct inode *new_ip;

  /* See if 'name' (file to be linked) exists. */
  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);

  /* Check to see if the file has maximum number of links already. */
  r = OK;
  if (rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX))
	r = EMLINK;

  /* Only super_user may link to directories. */
  if (r == OK)
	if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;

  /* If error with 'name', return the inode. */
  if (r != OK) {
	put_inode(rip);
	return(r);
  }

  /* Does the final directory of 'name2' exist? */
  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
	put_inode(rip);
	return(err_code);
  }
  if ( (ip = last_dir(user_path, string)) == NIL_INODE) r = err_code;

  /* If 'name2' exists in full (even if no space) set 'r' to error. */
  if (r == OK) {
	if ( (new_ip = advance(ip, string)) == NIL_INODE) {
		r = err_code;
		if (r == ENOENT) r = OK;
	} else {
		put_inode(new_ip);
		r = EEXIST;
	}
  }

  /* Check for links across devices. */
  if (r == OK)
	if (rip->i_dev != ip->i_dev) r = EXDEV;

  /* Try to link. */
  if (r == OK)
	r = search_dir(ip, string, &rip->i_num, ENTER);

  /* If success, register the linking. */
  if (r == OK) {
	rip->i_nlinks++;
	rip->i_update |= CTIME;
	rip->i_dirt = DIRTY;
  }

  /* Done.  Release both inodes. */
  put_inode(rip);
  put_inode(ip);
  return(r);
}
示例#22
0
int file_edit(char* name)
{
	char original_name_path[30];
	int original_inode = inode_num;//记录当前的inode
	strcpy(original_name_path, name);
	if (eat_path(name) == -1) {
		printf("错误:文件路径出错!‘%s’\n", original_name_path);
		return -1;
	}
	if (type_check(name) == Directory) {
		printf("错误:'%s'文件不存在!\n", name);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}
	if (type_check(name) == -1) {
		printf("错误:'%s'文件不存在!\n", name);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (file_read(name) == -1) {//文件读取失败
		printf("错误:无读写‘%s’文件权限!\n", name);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	BuffModifyTimeBeforeEdit = getBuffModifyTime();//文件信息载入到buff.txt后,获取buff.txt的修改时间,用来判断载入的内容在记事本中是否被修改
	/*
	SYSTEMTIME *STime = new SYSTEMTIME;
	FileTimeToSystemTime(&BuffModifyTimeBeforeEdit, STime);
	printf("%d-%d-%d-%d-%d-%d\n", STime->wYear, STime->wMonth, STime->wDay, STime->wHour, STime->wMinute, STime->wSecond);
	*/
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	LPTSTR szCmdline = _tcsdup(TEXT("notepad.exe buff.txt"));

	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	ZeroMemory(&pi, sizeof(pi));

	// 打开子进程
	if (!CreateProcess(NULL,   // No module name (use command line)
		szCmdline,      // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		0,              // No creation flags
		NULL,           // Use parent's environment block
		NULL,           // Use parent's starting directory
		&si,            // Pointer to STARTUPINFO structure
		&pi)           // Pointer to PROCESS_INFORMATION structure
		)
	{
		printf("CreateProcess failed (%d).\n", GetLastError());
		return 0;
	}

	// Wait until child process exits.
	WaitForSingleObject(pi.hProcess, INFINITE);

	// Close process and thread handles.
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	Sleep(10);
	BuffModifyTimeAfterEdit = getBuffModifyTime();//buff.txt关闭后,获取buff.txt的修改时间,用来判断载入的内容在记事本中是否被修改
	/*
	SYSTEMTIME *STime = new SYSTEMTIME;
	FileTimeToSystemTime(&BuffModifyTimeAfterEdit, STime);
	printf("%d-%d-%d-%d-%d-%d\n", STime->wYear, STime->wMonth, STime->wDay, STime->wHour, STime->wMinute, STime->wSecond);
	*/
	if (BuffModifyTimeBeforeEdit.dwLowDateTime == BuffModifyTimeAfterEdit.dwLowDateTime
		&& BuffModifyTimeBeforeEdit.dwHighDateTime == BuffModifyTimeAfterEdit.dwHighDateTime) {
								//若buff.txt的修改时间没有发生变化。则载入记事本的内容没有发生改变,则不必重新写入		
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}
	
	if (file_write(name) == -1) { //将数据从BUFF写入文件
		printf("错误:文件类型为只读,无法修改!\n");
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	close_dir(inode_num);
	inode_num = original_inode;
	open_dir(inode_num);
	return 0;
}
示例#23
0
/*修改文件读写权限*/
int change_mode(char* parameter, char* name)
{
	int inode;
	Inode temp;
	char original_name_path[30];
	int original_inode = inode_num;//记录当前的inode

	strcpy(original_name_path, name);
	if (eat_path(name) == -1) {
		printf("chmod: cannot access‘%s’: No such file or directory\n", original_name_path);
		return -1;
	}
	inode = check_name(inode_num, name);
	if (inode == -1) {
		printf("stat: cannot stat '%s': No such file or directory\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	fseek(Disk, InodeBeg + sizeof(Inode)*inode, SEEK_SET);
	fread(&temp, sizeof(Inode), 1, Disk);

	if (strcmp(parameter, "+r") == 0) {
		temp.access[0][user_num] = 1;
		temp.i_ctime = time(NULL);
	}
	else if (strcmp(parameter, "-r") == 0) {
		temp.access[0][user_num] = 0;
		temp.i_ctime = time(NULL);
	}
	else if (strcmp(parameter, "+w") == 0) {
		temp.access[1][user_num] = 1;
		temp.i_ctime = time(NULL);
	}
	else if (strcmp(parameter, "-w") == 0) {
		temp.access[1][user_num] = 0;
		temp.i_ctime = time(NULL);
	}
	else if (strcmp(parameter, "+x") == 0) {
		temp.access[2][user_num] = 1;
		temp.i_ctime = time(NULL);
	}
	else if (strcmp(parameter, "-x") == 0) {
		temp.access[2][user_num] = 0;
		temp.i_ctime = time(NULL);
	}
	else {
		printf("chmod: invalid option -- '%s'\n", parameter);
	}

	/*将修改后的Inode写回*/
	fseek(Disk, InodeBeg + sizeof(Inode)*inode, SEEK_SET);
	fwrite(&temp, sizeof(Inode), 1, Disk);

	close_dir(inode_num);
	inode_num = original_inode;
	open_dir(inode_num);
	return 0;
}
示例#24
0
文件: exec.c 项目: vivekp/minix-1
/*===========================================================================*
 *				pm_exec					     *
 *===========================================================================*/
PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
		   vir_bytes frame_len, vir_bytes *pc)
{
/* 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, r1, round, proc_s;
  vir_bytes vsp;
  struct fproc *rfp;
  struct vnode *vp;
  char *cp;
  static char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
  struct exec_info execi;
  int i;

  okendpt(proc_e, &proc_s);
  rfp = fp = &fproc[proc_s];
  who_e = proc_e;
  who_p = proc_s;
  super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */

  /* Get the exec file name. */
  if ((r = fetch_name(path, path_len, 0)) != OK) return(r);

  /* Fetch the stack from the user before destroying the old core image. */
  if (frame_len > ARG_MAX) {
		printf("VFS: pm_exec: stack too big\n");
		return(ENOMEM);	/* stack too big */
	}
  r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
  		   (phys_bytes) frame_len);
  if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
        printf("pm_exec: sys_datacopy failed\n");
        return(r);	
  }

  /* The default is to keep the original user and group IDs */
  execi.new_uid = rfp->fp_effuid;
  execi.new_gid = rfp->fp_effgid;

  for (round= 0; round < 2; round++) {
	/* round = 0 (first attempt), or 1 (interpreted script) */

	/* Save the name of the program */
	(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);

	strncpy(execi.progname, cp, PROC_NAME_LEN-1);
	execi.progname[PROC_NAME_LEN-1] = '\0';
	execi.setugid = 0;

	/* Open executable */
	if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
	execi.vp = vp;

	if ((vp->v_mode & I_TYPE) != I_REGULAR) 
		r = ENOEXEC;
	else if ((r1 = forbidden(vp, X_BIT)) != OK)
		r = r1;
	else
		r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR,
			     (char *) &(execi.sb), 0, 0);
	if (r != OK) {
	    put_vnode(vp);
	    return(r);
	}

        if (round == 0) {
		/* Deal with setuid/setgid executables */
		if (vp->v_mode & I_SET_UID_BIT) {
			execi.new_uid = vp->v_uid;
			execi.setugid = 1;
		}
		if (vp->v_mode & I_SET_GID_BIT) {
			execi.new_gid = vp->v_gid;
			execi.setugid = 1;
		}
        }

	r = map_header(&execi.hdr, execi.vp);
	if (r != OK) {
	    put_vnode(vp);
	    return(r);
	}

	if (!is_script(execi.hdr, execi.vp->v_size) || round != 0)
		break;

	/* Get fresh copy of the file name. */
	if ((r = fetch_name(path, path_len, 0)) != OK) 
		printf("VFS pm_exec: 2nd fetch_name failed\n");
	else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK) 
		printf("VFS pm_exec: patch_stack failed\n");
	put_vnode(vp);
	if (r != OK) return(r);
  }

  execi.proc_e = proc_e;
  execi.frame_len = frame_len;

  for(i = 0; exec_loaders[i].load_object != NULL; i++) {
      r = (*exec_loaders[i].load_object)(&execi);
      /* Loaded successfully, so no need to try other loaders */
      if (r == OK) break;
  }
  put_vnode(vp);

  /* No exec loader could load the object */
  if (r != OK) {
	return(ENOEXEC);
  }

  /* Save off PC */
  *pc = execi.pc;

  /* Patch up stack and copy it from VFS to new core image. */
  vsp = execi.stack_top;
  vsp -= frame_len;
  patch_ptr(mbuf, vsp);
  if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
		   (phys_bytes)frame_len)) != OK) {
	printf("VFS: datacopy failed (%d) trying to copy to %lu\n", r, vsp);
	return(r);
  }

  if (r != OK) return(r);
  clo_exec(rfp);

  if (execi.setugid) {
	/* If after loading the image we're still allowed to run with
	 * setuid or setgid, change the credentials now */
	rfp->fp_effuid = execi.new_uid;
	rfp->fp_effgid = execi.new_gid;
  }

  /* This child has now exec()ced. */
  rfp->fp_execced = 1;

  return(OK);
}
示例#25
0
/*===========================================================================*
 *				get_read_vp				     *
 *===========================================================================*/
static int get_read_vp(struct vfs_exec_info *execi,
  char *fullpath, int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp)
{
/* Make the executable that we want to exec() into the binary pointed
 * to by 'fullpath.' This function fills in necessary details in the execi
 * structure, such as opened vnode. It unlocks and releases the vnode if
 * it was already there. This makes it easy to change the executable
 * during the exec(), which is often necessary, by calling this function
 * more than once. This is specifically necessary when we discover the
 * executable is actually a script or a dynamically linked executable.
 */
	int r;

	/* Caller wants to switch vp to the file in 'fullpath.'
	 * unlock and put it first if there is any there.
	 */
	if(execi->vp) {
		unlock_vnode(execi->vp);
		put_vnode(execi->vp);
		execi->vp = NULL;
	}

	/* Remember/overwrite the executable name if requested. */
	if(copyprogname) {
		char *cp = strrchr(fullpath, '/');
		if(cp) cp++;
		else cp = fullpath;
		strlcpy(execi->args.progname, cp, sizeof(execi->args.progname));
		execi->args.progname[sizeof(execi->args.progname)-1] = '\0';
	}

	/* Open executable */
	if ((execi->vp = eat_path(resolve, fp)) == NULL)
		return err_code;

	unlock_vmnt(execi->vmp);

	if (!S_ISREG(execi->vp->v_mode))
		return ENOEXEC;
	else if ((r = forbidden(fp, execi->vp, X_BIT)) != OK)
		return r;
	else
		r = req_stat(execi->vp->v_fs_e, execi->vp->v_inode_nr,
			VFS_PROC_NR, (vir_bytes) &(execi->sb));

	if (r != OK) return r;

	/* If caller wants us to, honour suid/guid mode bits. */
        if (sugid) {
		/* Deal with setuid/setgid executables */
		if (execi->vp->v_mode & I_SET_UID_BIT) {
			execi->args.new_uid = execi->vp->v_uid;
			execi->args.allow_setuid = 1;
		}
		if (execi->vp->v_mode & I_SET_GID_BIT) {
			execi->args.new_gid = execi->vp->v_gid;
			execi->args.allow_setuid = 1;
		}
        }

	/* Read in first chunk of file. */
	if((r=map_header(execi)) != OK)
		return r;

	return OK;
}
示例#26
0
int remove_file(int inode, char* name, int deepth, int type)
{
	char original_name_path[30];
	int original_inode = inode_num;//记录当前的inode

	strcpy(original_name_path, name);
	if (eat_path(name) == -1) {
		if (type == Directory)
			printf("rmdir: failed to remove‘%s’: No such file or directory\n", original_name_path);
		if (type == File)
			printf("rm: cannot remove‘%s’: No such file or directory\n", original_name_path);
		return -1;
	}

	int check_type_result = type_check(name);
	if (check_type_result == -1) {//要删除的文件不存在
		if (type == Directory)
			printf("rmdir: failed to remove '%s': No such file or directory\n", original_name_path);
		if (type == File)
			printf("rm: cannot remove '%s': No such file or directory\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	Inode father_inode;
	/*读取要删除的目录或文件的父目录的Inode*/
	fseek(Disk, InodeBeg + sizeof(Inode)*inode_num, SEEK_SET);
	fread(&father_inode, sizeof(father_inode), 1, Disk);

	if (father_inode.access[1] == 0) { //要删除的目录或文件的父目录不允许写
		if (type == Directory)
			printf("rmdir: failed to remove ‘%s’: Permission denied\n", original_name_path);
		if (type == File)
			printf("rm: cannot remove‘%s’: Permission denied\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (check_type_result == Directory && type == File) {//删除的文件类型与对应指令不符,如:尝试用rm删除目录
		printf("rm: cannot remove '%s': Not a file\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}
	if (check_type_result == File && type == Directory) {//删除的文件类型与对应指令不符,如:用rmdir删除文件
		printf("rmdir: failed to remove '%s': Not a directory\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	del_file(inode_num, name, 0);

	close_dir(inode_num);
	inode_num = original_inode;
	open_dir(inode_num);
	return 0;
}
示例#27
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);
}
示例#28
0
/*===========================================================================*
 *				do_mount				     *
 *===========================================================================*/
PUBLIC int do_mount()
{
/* Perform the mount(name, mfile, rd_only) system call. */

  register struct inode *rip, *root_ip;
  struct super_block *xp, *sp;
  dev_t dev;
  mode_t bits;
  int rdir, mdir;		/* TRUE iff {root|mount} file is dir */
  int i, r, found;
  struct fproc *tfp;

  /* Only the super-user may do MOUNT. */
  if (!super_user) return(EPERM);

  /* If 'name' is not for a block special file, return error. */
  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);

  /* Scan super block table to see if dev already mounted & find a free slot.*/
  sp = NIL_SUPER;
  found = FALSE;
  for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
	if (xp->s_dev == dev)
	{
		/* is it mounted already? */
		found = TRUE;
		sp= xp;
		break;
	}
	if (xp->s_dev == NO_DEV) sp = xp;	/* record free slot */
  }
  if (found)
  {
	printf(
"do_mount: s_imount = 0x%x (%x, %d), s_isup = 0x%x (%x, %d), fp_rootdir = 0x%x\n",
		xp->s_imount, xp->s_imount->i_dev, xp->s_imount->i_num,
		xp->s_isup, xp->s_isup->i_dev, xp->s_isup->i_num,
		fproc[FS_PROC_NR].fp_rootdir);
	/* It is possible that we have an old root lying around that 
	 * needs to be remounted.
	 */
	if (xp->s_imount != xp->s_isup ||
		xp->s_isup == fproc[FS_PROC_NR].fp_rootdir)
	{
		/* Normally, s_imount refers to the mount point. For a root
		 * filesystem, s_imount is equal to the root inode. We assume
		 * that the root of FS is always the real root. If the two
		 * inodes are different or if the root of FS is equal two the
		 * root of the filesystem we found, we found a filesystem that
		 * is in use.
		 */
		return(EBUSY);	/* already mounted */
	}

	if (root_dev == xp->s_dev)
	{
		panic("fs", "inconsistency remounting old root",
			NO_NUM);
	}

	/* Now get the inode of the file to be mounted on. */
	if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
		return(err_code);
	}

	if ( (rip = eat_path(user_path)) == NIL_INODE) {
		return(err_code);
	}

	r = OK;

	/* It may not be special. */
	bits = rip->i_mode & I_TYPE;
	if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL)
		r = ENOTDIR;

	/* Get the root inode of the mounted file system. */
	root_ip= sp->s_isup;

	/* File types of 'rip' and 'root_ip' may not conflict. */
	if (r == OK) {
		mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY); 
						/* TRUE iff dir */
		rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
		if (!mdir && rdir) r = EISDIR;
	}

	/* If error, return the mount point. */
	if (r != OK) {
		put_inode(rip);
		return(r);
	}

	/* Nothing else can go wrong.  Perform the mount. */
	rip->i_mount = I_MOUNT;	/* this bit says the inode is
				 * mounted on
				 */
	put_inode(sp->s_imount);
	sp->s_imount = rip;
	sp->s_rd_only = m_in.rd_only;
	allow_newroot= 0;		/* The root is now fixed */
	return(OK);
  }
  if (sp == NIL_SUPER) return(ENFILE);	/* no super block available */

  /* Open the device the file system lives on. */
  if (dev_open(dev, who_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) 
  	return(EINVAL);

  /* Make the cache forget about blocks it has open on the filesystem */
  (void) do_sync();
  invalidate(dev);

  /* Fill in the super block. */
  sp->s_dev = dev;		/* read_super() needs to know which dev */
  r = read_super(sp);

  /* Is it recognized as a Minix filesystem? */
  if (r != OK) {
	dev_close(dev);
	sp->s_dev = NO_DEV;
	return(r);
  }

  /* Now get the inode of the file to be mounted on. */
  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
	dev_close(dev);
	sp->s_dev = NO_DEV;
	return(err_code);
  }

  if (strcmp(user_path, "/") == 0 && allow_newroot)
  {
	printf("Replacing root\n");

	/* Get the root inode of the mounted file system. */
	if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
	if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
		r = EINVAL;
	}

	/* If error, return the super block and both inodes; release the
	 * maps.
	 */
	if (r != OK) {
		put_inode(root_ip);
		(void) do_sync();
		invalidate(dev);
		dev_close(dev);
		sp->s_dev = NO_DEV;
		return(r);
	}

	/* Nothing else can go wrong.  Perform the mount. */
	sp->s_imount = root_ip;
	dup_inode(root_ip);
	sp->s_isup = root_ip;
	sp->s_rd_only = m_in.rd_only;
	root_dev= dev;

	/* Replace all root and working directories */
	for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++)
	{
		if (tfp->fp_pid == PID_FREE)
			continue;
		if (tfp->fp_rootdir == NULL)
			panic("fs", "do_mount: null rootdir", i);
		put_inode(tfp->fp_rootdir);
		dup_inode(root_ip);
		tfp->fp_rootdir= root_ip;

		if (tfp->fp_workdir == NULL)
			panic("fs", "do_mount: null workdir", i);
		put_inode(tfp->fp_workdir);
		dup_inode(root_ip);
		tfp->fp_workdir= root_ip;
	}

	/* Leave the old filesystem lying around. */
	return(OK);
  }

  if ( (rip = eat_path(user_path)) == NIL_INODE) {
	dev_close(dev);
	sp->s_dev = NO_DEV;
	return(err_code);
  }

  /* It may not be busy. */
  r = OK;
  if (rip->i_count > 1) r = EBUSY;

  /* It may not be special. */
  bits = rip->i_mode & I_TYPE;
  if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;

  /* Get the root inode of the mounted file system. */
  root_ip = NIL_INODE;		/* if 'r' not OK, make sure this is defined */
  if (r == OK) {
	if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
  }
  if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
  	r = EINVAL;
  }

  /* File types of 'rip' and 'root_ip' may not conflict. */
  if (r == OK) {
	mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
	rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
	if (!mdir && rdir) r = EISDIR;
  }

  /* If error, return the super block and both inodes; release the maps. */
  if (r != OK) {
	put_inode(rip);
	put_inode(root_ip);
	(void) do_sync();
	invalidate(dev);
	dev_close(dev);
	sp->s_dev = NO_DEV;
	return(r);
  }

  /* Nothing else can go wrong.  Perform the mount. */
  rip->i_mount = I_MOUNT;	/* this bit says the inode is mounted on */
  sp->s_imount = rip;
  sp->s_isup = root_ip;
  sp->s_rd_only = m_in.rd_only;
  allow_newroot= 0;		/* The root is now fixed */
  return(OK);
}
示例#29
0
/*创建新的目录项*/
int make_file(int inode, char* name, int type)
{
	char original_name_path[30];
	int original_inode = inode_num;//记录当前的inode

	strcpy(original_name_path, name);
	if (eat_path(name) == -1) {
		if (type == File)
			printf("touch: cannot touch‘%s’: No such file or directory\n", original_name_path);
		if (type == Directory)
			printf("mkdir: cannot create directory ‘%s’: No such file or directory\n", original_name_path);
		return -1;
	}

	int new_node;
	int blk_need = 1;//本目录需要增加磁盘块则blk_need=2
	int t;
	Inode temp;

	/*读取当前目录的Inode*/
	fseek(Disk, InodeBeg + sizeof(Inode)*inode, SEEK_SET);
	fread(&temp, sizeof(Inode), 1, Disk);

	if (temp.access[1] == 0) { //当前目录不允许写
		if (type == Directory)
			printf("mkdir: cannot create directory ‘%s’: Permission denied\n", original_name_path);
		if (type == File)
			printf("touch: cannot touch ‘%s’: Permission denied\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}
	if (dir_num>MaxDirNum) {//超过了目录文件能包含的最大目录项
		if (type == Directory)
			printf("mkdir: cannot create directory '%s' : Directory full\n", original_name_path);
		if (type == File)
			printf("touch: cannot create file '%s' : Directory full\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (check_name(inode, name) != -1) {//防止重命名
		if (type == Directory)
			printf("mkdir: cannnot create directory '%s' : Directory exist\n", original_name_path);
		if (type == File)
			printf("touch: cannot create file '%s' : File exist\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (dir_num / DirPerBlk != (dir_num + 1) / DirPerBlk) {//本目录也要增加磁盘块
		blk_need = 2;
	}

	//	printf("blk_used:%d\n",super_blk.blk_used);
	if (super_blk.blk_used + blk_need>BlkNum) {
		if (type == Directory)
			printf("mkdir: cannot create directory '%s' :Block used up\n", original_name_path);
		if (type == File)
			printf("touch: cannot create file '%s' : Block used up\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (blk_need == 2) {//本目录需要增加磁盘块
		t = curr_inode.blk_num++;
		curr_inode.blk_identifier[t] = get_blk();
	}

	/*申请inode*/
	new_node = apply_inode();

	if (new_node == -1) {
		if (type == Directory)
			printf("mkdir: cannot create directory '%s' :Inode used up\n", original_name_path);
		if (type == File)
			printf("touch: cannot create file '%s' : Inode used up\n", original_name_path);
		close_dir(inode_num);
		inode_num = original_inode;
		open_dir(inode_num);
		return -1;
	}

	if (type == Directory) {
		/*初始化新建目录的inode*/
		init_dir_inode(new_node, inode);
	}
	else if (type == File) {
		/*初始化新建文件的inode*/
		init_file_inode(new_node);
	}

	strcpy(dir_table[dir_num].name, name);
	dir_table[dir_num++].inode_num = new_node;

	close_dir(inode_num);
	inode_num = original_inode;
	open_dir(inode_num);
	return 0;
}
示例#30
0
/*===========================================================================*
 *				common_open				     *
 *===========================================================================*/
PRIVATE int common_open(register int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */

  struct inode *rip, *ldirp;
  int r, b, exist = TRUE;
  dev_t dev;
  mode_t bits;
  off_t pos;
  struct filp *fil_ptr, *filp2;

  /* Remap the bottom two bits of oflags. */
  bits = (mode_t) mode_map[oflags & O_ACCMODE];

  /* See if file descriptor and filp slots are available. */
  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);

  /* If O_CREATE is set, try to make the file. */ 
  if (oflags & O_CREAT) {
  	/* Create a new inode by calling new_node(). */
        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
    	rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL);
    	r = err_code;
        put_inode(ldirp);
    	if (r == OK) exist = FALSE;      /* we just created the file */
	else if (r != EEXIST) return(r); /* other error */
	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
					    flag is set this is an error */
  } else {
	 /* Scan path name. */
    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  }

  /* Claim the file descriptor and filp slot and fill them in. */
  fp->fp_filp[m_in.fd] = fil_ptr;
  FD_SET(m_in.fd, &fp->fp_filp_inuse);
  fil_ptr->filp_count = 1;
  fil_ptr->filp_ino = rip;
  fil_ptr->filp_flags = oflags;

  /* Only do the normal open code if we didn't just create the file. */
  if (exist) {
  	/* Check protections. */
  	if ((r = forbidden(rip, bits)) == OK) {
  		/* Opening reg. files directories and special files differ. */
	  	switch (rip->i_mode & I_TYPE) {
    		   case I_REGULAR: 
			/* Truncate regular file if O_TRUNC. */
			if (oflags & O_TRUNC) {
				if ((r = forbidden(rip, W_BIT)) !=OK) break;
				truncate_inode(rip, 0);
				wipe_inode(rip);
				/* Send the inode from the inode cache to the
				 * block cache, so it gets written on the next
				 * cache flush.
				 */
				rw_inode(rip, WRITING);
			}
			break;
 
	    	   case I_DIRECTORY: 
			/* Directories may be read but not written. */
			r = (bits & W_BIT ? EISDIR : OK);
			break;

	     	   case I_CHAR_SPECIAL:
     		   case I_BLOCK_SPECIAL:
			/* Invoke the driver for special processing. */
			dev = (dev_t) rip->i_zone[0];
			r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
			break;

		   case I_NAMED_PIPE:
			oflags |= O_APPEND;	/* force append mode */
			fil_ptr->filp_flags = oflags;
			r = pipe_open(rip, 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);
				fil_ptr->filp_count = 0; /* don't find self */
				if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
					/* Co-reader or writer found. Use it.*/
					fp->fp_filp[m_in.fd] = filp2;
					filp2->filp_count++;
					filp2->filp_ino = rip;
					filp2->filp_flags = oflags;

					/* i_count was incremented incorrectly
					 * by eatpath above, not knowing that
					 * we were going to use an existing
					 * filp entry.  Correct this error.
					 */
					rip->i_count--;
				} else {
					/* Nobody else found.  Restore filp. */
					fil_ptr->filp_count = 1;
					if (b == R_BIT)
					     pos = rip->i_zone[V2_NR_DZONES+0];
					else
					     pos = rip->i_zone[V2_NR_DZONES+1];
					fil_ptr->filp_pos = pos;
				}
			}
			break;
 		}
  	}
  }

  /* If error, release inode. */
  if (r != OK) {
	if (r == SUSPEND) return(r);		/* Oops, just suspended */
	fp->fp_filp[m_in.fd] = NIL_FILP;
  	FD_CLR(m_in.fd, &fp->fp_filp_inuse);
	fil_ptr->filp_count= 0;
	put_inode(rip);
	return(r);
  }
  
  return(m_in.fd);
}