/*===========================================================================* * actual_llseek * *===========================================================================*/ int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence, u64_t offset) { /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; u64_t pos, newpos; int r = OK; long off_hi = ex64hi(offset); /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ)) == NULL) { return(err_code); } /* No lseek on pipes. */ if (S_ISFIFO(rfilp->filp_vno->v_mode)) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(seekwhence) { case SEEK_SET: pos = cvu64(0); break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; default: unlock_filp(rfilp); return(EINVAL); } newpos = pos + offset; /* Check for overflow. */ if ((off_hi > 0) && cmp64(newpos, pos) < 0) r = EINVAL; else if ((off_hi < 0) && cmp64(newpos, pos) > 0) r = EINVAL; else { /* insert the new position into the output message */ m_out->reply_l1 = ex64lo(newpos); m_out->reply_l2 = ex64hi(newpos); if (cmp64(newpos, rfilp->filp_pos) != 0) { rfilp->filp_pos = newpos; /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
int dupvm(struct fproc *rfp, int pfd, int *vmfd, struct filp **newfilp) { int result, procfd; struct filp *f = NULL; struct fproc *vmf = &fproc[VM_PROC_NR]; *newfilp = NULL; if ((f = get_filp2(rfp, pfd, VNODE_READ)) == NULL) { printf("VFS dupvm: get_filp2 failed\n"); return EBADF; } if(!f->filp_vno->v_vmnt->m_haspeek) { unlock_filp(f); printf("VFS dupvm: no peek available\n"); return EINVAL; } assert(f->filp_vno); assert(f->filp_vno->v_vmnt); if (!S_ISREG(f->filp_vno->v_mode) && !S_ISBLK(f->filp_vno->v_mode)) { printf("VFS: mmap regular/blockdev only; dev 0x%x ino %d has mode 0%o\n", (int) f->filp_vno->v_dev, (int) f->filp_vno->v_inode_nr, (int) f->filp_vno->v_mode); unlock_filp(f); return EINVAL; } /* get free FD in VM */ if((result=get_fd(vmf, 0, 0, &procfd, NULL)) != OK) { unlock_filp(f); printf("VFS dupvm: getfd failed\n"); return result; } *vmfd = procfd; f->filp_count++; assert(f->filp_count > 0); vmf->fp_filp[procfd] = f; /* mmap FD's are inuse */ FD_SET(procfd, &vmf->fp_filp_inuse); *newfilp = f; return OK; }
int dupvm(struct fproc *rfp, int pfd, int *vmfd, struct filp **newfilp) { int result, procfd; struct filp *f = NULL; struct fproc *vmf = fproc_addr(VM_PROC_NR); *newfilp = NULL; if ((f = get_filp2(rfp, pfd, VNODE_READ)) == NULL) { printf("VFS dupvm: get_filp2 failed\n"); return EBADF; } if(!(f->filp_vno->v_vmnt->m_fs_flags & RES_HASPEEK)) { unlock_filp(f); #if 0 /* Noisy diagnostic for mmap() by ld.so */ printf("VFS dupvm: no peek available\n"); #endif return EINVAL; } assert(f->filp_vno); assert(f->filp_vno->v_vmnt); if (!S_ISREG(f->filp_vno->v_mode) && !S_ISBLK(f->filp_vno->v_mode)) { printf("VFS: mmap regular/blockdev only; dev 0x%llx ino %llu has mode 0%o\n", f->filp_vno->v_dev, f->filp_vno->v_inode_nr, f->filp_vno->v_mode); unlock_filp(f); return EINVAL; } /* get free FD in VM */ if((result=get_fd(vmf, 0, 0, &procfd, NULL)) != OK) { unlock_filp(f); printf("VFS dupvm: getfd failed\n"); return result; } *vmfd = procfd; f->filp_count++; assert(f->filp_count > 0); vmf->fp_filp[procfd] = f; *newfilp = f; return OK; }
/*===========================================================================* * actual_lseek * *===========================================================================*/ int actual_lseek(struct fproc *rfp, int seekfd, int seekwhence, off_t offset, off_t *newposp) { register struct filp *rfilp; int r = OK; off_t pos, newpos; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ)) == NULL) { return(err_code); } /* No lseek on pipes. */ if (S_ISFIFO(rfilp->filp_vno->v_mode)) { unlock_filp(rfilp); return(ESPIPE); } /* The value of 'whence' determines the start position to use. */ switch(seekwhence) { case SEEK_SET: pos = 0; break; case SEEK_CUR: pos = rfilp->filp_pos; break; case SEEK_END: pos = rfilp->filp_vno->v_size; break; default: unlock_filp(rfilp); return(EINVAL); } newpos = pos + offset; /* Check for overflow. */ if ((offset > 0) && (newpos <= pos)) { r = EOVERFLOW; } else if ((offset < 0) && (newpos >= pos)) { r = EOVERFLOW; } else { if (newposp != NULL) *newposp = newpos; if (newpos != rfilp->filp_pos) { rfilp->filp_pos = newpos; /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); } } unlock_filp(rfilp); return(r); }
/*===========================================================================* * close_fd * *===========================================================================*/ int close_fd(struct fproc * rfp, int fd_nr, int may_suspend) { /* Perform the close(fd) system call. */ register struct filp *rfilp; register struct vnode *vp; struct file_lock *flp; int r, lock_count; /* First locate the vnode that belongs to the file descriptor. */ if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code); vp = rfilp->filp_vno; /* first, make all future get_filp2()'s fail; otherwise * we might try to close the same fd in different threads */ rfp->fp_filp[fd_nr] = NULL; r = close_filp(rfilp, may_suspend); FD_CLR(fd_nr, &rfp->fp_cloexec_set); /* Check to see if the file is locked. If so, release all locks. */ if (nr_locks > 0) { lock_count = nr_locks; /* save count of locks */ for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) { if (flp->lock_type == 0) continue; /* slot not in use */ if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) { flp->lock_type = 0; nr_locks--; } } if (nr_locks < lock_count) lock_revive(); /* one or more locks released */ } return(r); }
/*===========================================================================* * actual_read_write_peek * *===========================================================================*/ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd, vir_bytes io_buf, size_t io_nbytes) { /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */ struct filp *f; tll_access_t locktype; int r; int ro = 1; if(rw_flag == WRITING) ro = 0; scratch(rfp).file.fd_nr = io_fd; scratch(rfp).io.io_buffer = io_buf; scratch(rfp).io.io_nbytes = io_nbytes; locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ; if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype)) == NULL) return(err_code); assert(f->filp_count > 0); if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) { unlock_filp(f); return(EBADF); } if (scratch(rfp).io.io_nbytes == 0) { unlock_filp(f); return(0); /* so char special files need not check for 0*/ } r = read_write(rfp, rw_flag, f, scratch(rfp).io.io_buffer, scratch(rfp).io.io_nbytes, who_e); unlock_filp(f); return(r); }