/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
/*===========================================================================* * 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; }
int do_recinode() { struct vnode *vp; struct vmnt *vmp; int r; size_t nrblks; char fullpath[PATH_MAX]; struct lookup resolve; size_t vname1_length; vir_bytes vname1; vname1 = job_m_in.m_lc_vfs_inodes.name; vname1_length = job_m_in.m_lc_vfs_inodes.len; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_recoverinode(vp->v_fs_e, vp->v_inode_nr); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return r; }
/*===========================================================================* * do_lstat * *===========================================================================*/ int do_lstat(void) { /* Perform the lstat(name, buf) system call. */ struct vnode *vp; struct vmnt *vmp; int r; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = job_m_in.m_lc_vfs_stat.name; vname1_length = job_m_in.m_lc_vfs_stat.len; statbuf = job_m_in.m_lc_vfs_stat.buf; lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_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; }
/*===========================================================================* * do_lstat * *===========================================================================*/ int do_lstat() { /* Perform the lstat(name, buf) system call. */ struct vnode *vp; struct vmnt *vmp; int r; char fullpath[PATH_MAX]; struct lookup resolve; int old_stat = 0; vir_bytes vname1, statbuf; size_t vname1_length; vname1 = (vir_bytes) job_m_in.name1; vname1_length = (size_t) job_m_in.name1_length; statbuf = (vir_bytes) job_m_in.name2; lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (job_call_nr == PREV_LSTAT) old_stat = 1; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return(r); }
/*===========================================================================* * do_link * *===========================================================================*/ int do_link() { /* Perform the link(name1, name2) system call. */ int r = 0; endpoint_t linked_fs_e, link_lastdir_fs_e; struct vnode *vp, *vp_d; /* See if 'name1' (file to be linked to) exists. */ if(fetch_name(user_fullpath, PATH_MAX, m_in.name1) < 0) return(err_code); if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); /* Does the final directory of 'name2' exist? */ if (fetch_name(user_fullpath, PATH_MAX, m_in.name2) < 0) r = err_code; else if ((vp_d = last_dir()) == NIL_VNODE) r = err_code; if (r != 0) { put_vnode(vp); return(r); } /* Check for links across devices. */ if(vp->v_fs_e != vp_d->v_fs_e) r = -EXDEV; else r = forbidden(vp_d, W_BIT | X_BIT); if (r == 0) r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath, vp->v_inode_nr); put_vnode(vp); put_vnode(vp_d); return(r); }
/*===========================================================================* * do_link * *===========================================================================*/ int do_link() { /* Perform the link(name1, name2) system call. */ int r = OK; struct vnode *vp = NULL, *dirp = NULL; struct vmnt *vmp1 = NULL, *vmp2 = NULL; char fullpath[PATH_MAX]; struct lookup resolve; vir_bytes vname1, vname2; size_t vname1_length, vname2_length; vname1 = (vir_bytes) job_m_in.name1; vname1_length = job_m_in.name1_length; vname2 = (vir_bytes) job_m_in.name2; vname2_length = job_m_in.name2_length; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp); resolve.l_vmnt_lock = VMNT_WRITE; resolve.l_vnode_lock = VNODE_READ; /* See if 'name1' (file to be linked to) exists. */ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); /* Does the final directory of 'name2' exist? */ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_WRITE; if (fetch_name(vname2, vname2_length, fullpath) != OK) r = err_code; else if ((dirp = last_dir(&resolve, fp)) == NULL) r = err_code; if (r != OK) { unlock_vnode(vp); unlock_vmnt(vmp1); put_vnode(vp); return(r); } /* Check for links across devices. */ if (vp->v_fs_e != dirp->v_fs_e) r = EXDEV; else r = forbidden(fp, dirp, W_BIT | X_BIT); if (r == OK) r = req_link(vp->v_fs_e, dirp->v_inode_nr, fullpath, vp->v_inode_nr); unlock_vnode(vp); unlock_vnode(dirp); if (vmp2 != NULL) unlock_vmnt(vmp2); unlock_vmnt(vmp1); put_vnode(vp); put_vnode(dirp); return(r); }
/*===========================================================================* * 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); }
int lsr_work(char * path){ //printf("lsr_work in open.c - %s\n",path); struct vnode *vp; struct vmnt *vmp; //struct dmap *dp; struct lookup resolve; lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if ((vp = eat_path(&resolve, fp)) == NULL) { printf("Error: file does not exist.\n"); return(err_code); } if (vmp != NULL) unlock_vmnt(vmp); struct filp * f; struct fproc * fprc; struct filp * filp_fproc; for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (f->filp_count != 0 && f->filp_vno == vp) { for(fprc = &fproc[0]; fprc < &fproc[NR_PROCS]; fprc++){ if(fprc != NULL){ for(int i=0;i<OPEN_MAX;i++){ filp_fproc = fprc->fp_filp[i]; if(filp_fproc == f)printf("proc id: %d\n",fprc->fp_pid); } } } } } // check if immediate first //if(vp->v_mode int ret = req_listblocknum(vp->v_fs_e, vp->v_inode_nr, vp->v_dev); unlock_vnode(vp); put_vnode(vp); return ret; }
int 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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
int do_fileinfo(void) { struct vnode *vp; struct vmnt *vmp; int r; size_t nrblks; vir_bytes blockBuffer; char fullpath[PATH_MAX]; struct lookup resolve; size_t vname1_length; vir_bytes vname1; blockBuffer = job_m_in.m_lc_vfs_inodes.buff; nrblks = job_m_in.m_lc_vfs_inodes.nbr_blks; vname1 = job_m_in.m_lc_vfs_inodes.name; vname1_length = job_m_in.m_lc_vfs_inodes.len; lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp); resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_READ; if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code); if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code); // r = req_nrblocks(vp->v_fs_e, vp->v_inode_nr, blockBuffer); r = req_blocks(vp->v_fs_e, vp->v_inode_nr,who_e, blockBuffer,nrblks); // fprocinfo(vp); unlock_vnode(vp); unlock_vmnt(vmp); put_vnode(vp); return OK; }
/*===========================================================================* * do_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); }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
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; }
/*修改文件读写权限*/ 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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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; }
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; }
/*===========================================================================* * 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); }
/*===========================================================================* * 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); }
/*创建新的目录项*/ 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; }
/*===========================================================================* * 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); }