off_t write_to_swap(vaddr_t page,off_t offset) { struct uio uio ; struct iovec iovec ; if(offset == -1){ //lock_acquire(file_lock); uio_kinit(&iovec,&uio,(void * )page,PAGE_SIZE,global_offset,UIO_WRITE); } else uio_kinit(&iovec,&uio,(void * )page,PAGE_SIZE,offset,UIO_WRITE); int result=VOP_WRITE(swap_file,&uio); if(result) { panic("write_to_file : VOP_WRITE failed\n"); } if(offset == -1){ global_offset = global_offset + PAGE_SIZE ; return global_offset - PAGE_SIZE ; } else{ return offset; } }
char* read_seg_from_swap(vaddr_t vaddr){ kprintf("About to read segment from swap. given vaddress: %lu \n", (unsigned long)vaddr); char buf[SEG_SZ]; struct iovec iov; struct uio u; int i, result, segNum= -1; for(i=0;i<TABLE_SZ;i++){ if(addrptr[i]!=-1 && vaddr>=addrptr[i] && vaddr<addrptr[i]+SEG_SZ){ segNum = i; } } if(segNum==-1){}//kprintf("segment not found\n");} else kprintf("found seg no %d \n",segNum); u.uio_iovcnt = 1; u.uio_resid = SEG_SZ; // amount to read from the file u.uio_offset = offset[segNum]; //u.uio_segflg = is_executable ? UIO_USERISPACE : UIO_USERSPACE; u.uio_rw = UIO_READ; u.uio_space = curthread->t_addrspace; uio_kinit(&iov, &u, buf, SEG_SZ, 0, UIO_READ); result = VOP_READ(swap_file, &u); return buf; }
/* * Read the directory entry out of slot SLOT of a directory vnode. * The "slot" is the index of the directory entry, starting at 0. */ static int sfs_readdir(struct sfs_vnode *sv, struct sfs_dir *sd, int slot) { struct iovec iov; struct uio ku; off_t actualpos; int result; /* Compute the actual position in the directory to read. */ actualpos = slot * sizeof(struct sfs_dir); /* Set up a uio to do the read */ uio_kinit(&iov, &ku, sd, sizeof(struct sfs_dir), actualpos, UIO_READ); /* do it */ result = sfs_io(sv, &ku); if (result) { return result; } /* We should not hit EOF in the middle of a directory entry */ if (ku.uio_resid > 0) { panic("sfs: readdir: Short entry (inode %u)\n", sv->sv_ino); } /* Done */ return 0; }
void write_seg_to_swap(char* buf, vaddr_t vaddr){ struct iovec iov; struct uio u; int i, result, segNum = -1; for(i=0;i<TABLE_SZ;i++){ if(addrptr[i]!=-1 && vaddr>=addrptr[i] && vaddr<addrptr[i]+SEG_SZ){ segNum = i; } } if(segNum==-1){kprintf("segment not found\n");} u.uio_iovcnt = 1; u.uio_resid = SEG_SZ; // amount to read from the file u.uio_offset = offset[segNum]; //u.uio_segflg = is_executable ? UIO_USERISPACE : UIO_USERSPACE; u.uio_rw = UIO_READ; u.uio_space = curthread->t_addrspace; uio_kinit(&iov, &u, buf, SEG_SZ, 0, UIO_WRITE); result = VOP_WRITE(swap_file, &u); return buf; }
/* * Write (overwrite) the directory entry in slot SLOT of a directory * vnode. */ static int sfs_writedir(struct sfs_vnode *sv, struct sfs_dir *sd, int slot) { struct iovec iov; struct uio ku; off_t actualpos; int result; /* Compute the actual position in the directory. */ KASSERT(slot>=0); actualpos = slot * sizeof(struct sfs_dir); /* Set up a uio to do the write */ uio_kinit(&iov, &ku, sd, sizeof(struct sfs_dir), actualpos, UIO_WRITE); /* do it */ result = sfs_io(sv, &ku); if (result) { return result; } /* Should not end up with a partial entry! */ if (ku.uio_resid > 0) { panic("sfs: writedir: Short write (ino %u)\n", sv->sv_ino); } /* Done */ return 0; }
/* * Command for printing the current directory. */ static int cmd_pwd(int nargs, char **args) { char buf[PATH_MAX+1]; int result; struct iovec iov; struct uio ku; (void)nargs; (void)args; uio_kinit(&iov, &ku, buf, sizeof(buf)-1, 0, UIO_READ); result = vfs_getcwd(&ku); if (result) { kprintf("vfs_getcwd failed (%s)\n", strerror(result)); return result; } /* null terminate */ buf[sizeof(buf)-1-ku.uio_resid] = 0; /* print it */ kprintf("%s\n", buf); return 0; }
int write(int fd, const void *buf, size_t nbytes, ssize_t *ret) { if (fd < 0 || fd > INT_MAX) { return EBADF; } if (buf == NULL) { return EFAULT; } if(fd < 2){ curproc->rt = INTERACTIVE_K; } int err = 0; lock_acquire(glbl_mngr->file_sys_lk); open_file *f = file_list_get(curproc->open_files, fd); lock_release(glbl_mngr->file_sys_lk); if(f == NULL) { return EBADF; } else{ if(f->flags & O_RDONLY) { return EBADF; } else{ lock_acquire(f->file_lk); struct uio write_uio; struct iovec iov; uio_kinit(&iov, &write_uio, (void*)buf, nbytes, f->offset, UIO_WRITE); write_uio.uio_segflg = UIO_USERSPACE; write_uio.uio_space = curproc->p_addrspace; write_uio.uio_resid = nbytes; while(!err && write_uio.uio_resid) { err = VOP_WRITE(f->vfile,&write_uio); //err = f->vfile->vn_ops->vop_write(f->vfile, &write_uio); *ret = nbytes - write_uio.uio_resid; f->offset = write_uio.uio_offset; } lock_release(f->file_lk); } open_file_decref(f); } return err; }
int read_from_disk(vaddr_t page,off_t offset) { struct uio uio ; struct iovec iovec; uio_kinit(&iovec,&uio,(void *)page,PAGE_SIZE,offset,UIO_READ); int result = VOP_READ(swap_file,&uio); if(result) { return result; } return 0 ; }
int read_page(void* kbuf, off_t sw_offset){ struct iovec iovectr; struct uio uiovar; KASSERT(sw_vn != NULL); uio_kinit(&iovectr, &uiovar, kbuf, PAGE_SIZE, sw_offset, UIO_READ); spinlock_release(&cm_lock); int ret = VOP_READ(sw_vn, &uiovar); spinlock_acquire(&cm_lock); if(ret){ return ret; } return 0; }
int __getcwd(userptr_t buf, size_t buflen,int *err) { char path[PATH_MAX]; struct iovec iov; struct uio uio; uio_kinit(&iov,&uio,path,PATH_MAX,0,UIO_READ); *err = vfs_getcwd(&uio); if (*err) { return -1; } *err = copyout((userptr_t)path,buf,buflen); if (*err) { return -1; } return uio.uio_offset; }
/* * swap_io: Does one swap I/O. Panics on failure. * * Synchronization: none specifically. The physical page should be * marked "pinned" (locked) so it won't be touched by other people. */ static void swap_io(paddr_t pa, off_t swapaddr, enum uio_rw rw) { struct iovec iov; struct uio u; vaddr_t va; int result; KASSERT(lock_do_i_hold(global_paging_lock)); KASSERT(pa != INVALID_PADDR); KASSERT(swapaddr % PAGE_SIZE == 0); KASSERT(coremap_pageispinned(pa)); KASSERT(bitmap_isset(swapmap, swapaddr / PAGE_SIZE)); va = coremap_map_swap_page(pa); uio_kinit(&iov, &u, (char *)va, PAGE_SIZE, swapaddr, rw); if (rw==UIO_READ) { result = VOP_READ(swapstore, &u); } else { result = VOP_WRITE(swapstore, &u); } coremap_unmap_swap_page(va, pa); if (result==EIO) { panic("swap: EIO on swapfile (offset %ld)\n", (long)swapaddr); } else if (result==EINVAL) { panic("swap: EINVAL from swapfile (offset %ld)\n", (long)swapaddr); } else if (result) { panic("swap: Error %d from swapfile (offset %ld)\n", result, (long)swapaddr); } }
/* __getcwd() function handler */ int sys_getcwd(userptr_t buf, int * retval){ struct uio user; struct iovec iov; uio_kinit(&iov, &user, buf, BUF_SIZE, 0, UIO_READ); user.uio_segflg = UIO_USERSPACE; user.uio_space = curthread->t_addrspace; if (buf == NULL || buf == (void *) 0x40000000 || buf == (void *) 0x80000000) { return EFAULT; } int err; if ((err = vfs_getcwd(&user) != 0)){ return err; } *retval = BUF_SIZE - user.uio_resid; return 0; }
int _write(int filehandle,void *buf, size_t size,int* retval){ if(filehandle < 0 || filehandle > MAX_FILE_FILETAB){ *retval = -1; return EBADF; } if(curthread->fdesc[filehandle] == NULL) { *retval = -1; return EBADF; } if(! (curthread->fdesc[filehandle]->flags != O_WRONLY || curthread->fdesc[filehandle]->flags!=O_RDWR) ) { *retval = -1; return EINVAL; } lock_acquire(curthread->fdesc[filehandle]->f_lock); struct uio writeuio; struct iovec iov; size_t size1; char *buffer = (char*)kmalloc(size); copyinstr((userptr_t)buf,buffer,strlen(buffer),&size1); uio_kinit(&iov, &writeuio, (void*) buffer, size, curthread->fdesc[filehandle]->offset, UIO_WRITE); int result=VOP_WRITE(curthread->fdesc[filehandle]->vnode, &writeuio); if (result) { kfree(buffer); lock_release(curthread->fdesc[filehandle]->f_lock); *retval = -1; return result; } curthread->fdesc[filehandle]->offset = writeuio.uio_offset; *retval = size - writeuio.uio_resid; kfree(buffer); lock_release(curthread->fdesc[filehandle]->f_lock); return 0; }
int write_page(void* kbuf, off_t* newoffset, int index){ (void)index; struct iovec iovectr; struct uio uiovar; off_t offset; KASSERT(sw_vn != NULL); offset = index * PAGE_SIZE; uio_kinit(&iovectr, &uiovar, kbuf, PAGE_SIZE, offset, UIO_WRITE); spinlock_release(&cm_lock); int ret = VOP_WRITE(sw_vn, &uiovar); spinlock_acquire(&cm_lock); if(ret){ return 1; } *newoffset = offset; return 0; }
static void swap_io( paddr_t paddr, off_t offset, enum uio_rw op ) { struct iovec iov; struct uio uio; vaddr_t vaddr; int res; KASSERT( lock_do_i_hold( giant_paging_lock ) ); KASSERT( curthread->t_vmp_count == 0 || curthread->t_clone ); //get the virtual address. vaddr = PADDR_TO_KVADDR( paddr ); //init the uio request. uio_kinit( &iov, &uio, (char *)vaddr, PAGE_SIZE, offset, op ); //perform the request. res = (op == UIO_READ) ? VOP_READ( vn_sw, &uio ) : VOP_WRITE( vn_sw, &uio ); //if we have a problem ... bail. if( res ) panic( "swap_io: failed to perform a VOP." ); }
/* * Load an ELF executable user program into the current address space. * * Returns the entry point (initial PC) for the program in ENTRYPOINT. */ int load_elf(struct vnode *v, vaddr_t *entrypoint) { Elf_Ehdr eh; /* Executable header */ Elf_Phdr ph; /* "Program header" = segment header */ int result, i; struct iovec iov; struct uio ku; struct addrspace *as; as = curproc_getas(); /* * Read the executable header from offset 0 in the file. */ uio_kinit(&iov, &ku, &eh, sizeof(eh), 0, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on header - file truncated?\n"); return ENOEXEC; } /* * Check to make sure it's a 32-bit ELF-version-1 executable * for our processor type. If it's not, we can't run it. * * Ignore EI_OSABI and EI_ABIVERSION - properly, we should * define our own, but that would require tinkering with the * linker to have it emit our magic numbers instead of the * default ones. (If the linker even supports these fields, * which were not in the original elf spec.) */ if (eh.e_ident[EI_MAG0] != ELFMAG0 || eh.e_ident[EI_MAG1] != ELFMAG1 || eh.e_ident[EI_MAG2] != ELFMAG2 || eh.e_ident[EI_MAG3] != ELFMAG3 || eh.e_ident[EI_CLASS] != ELFCLASS32 || eh.e_ident[EI_DATA] != ELFDATA2MSB || eh.e_ident[EI_VERSION] != EV_CURRENT || eh.e_version != EV_CURRENT || eh.e_type!=ET_EXEC || eh.e_machine!=EM_MACHINE) { return ENOEXEC; } /* * Go through the list of segments and set up the address space. * * Ordinarily there will be one code segment, one read-only * data segment, and one data/bss segment, but there might * conceivably be more. You don't need to support such files * if it's unduly awkward to do so. * * Note that the expression eh.e_phoff + i*eh.e_phentsize is * mandated by the ELF standard - we use sizeof(ph) to load, * because that's the structure we know, but the file on disk * might have a larger structure, so we must use e_phentsize * to find where the phdr starts. */ for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: /* skip */ continue; case PT_PHDR: /* skip */ continue; case PT_MIPS_REGINFO: /* skip */ continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } result = as_define_region(as, ph.p_vaddr, ph.p_memsz, ph.p_flags & PF_R, ph.p_flags & PF_W, ph.p_flags & PF_X); if (result) { return result; } } result = as_prepare_load(as); if (result) { return result; } /* * Now actually load each segment. */ for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: /* skip */ continue; case PT_PHDR: /* skip */ continue; case PT_MIPS_REGINFO: /* skip */ continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } result = load_segment(as, v, ph.p_offset, ph.p_vaddr, ph.p_memsz, ph.p_filesz, ph.p_flags & PF_X); if (result) { return result; } } result = as_complete_load(as); if (result) { return result; } *entrypoint = eh.e_entry; return 0; }
/* * Load an ELF executable user program into the current address space. * * Returns the entry point (initial PC) for the program in ENTRYPOINT. */ int load_elf(struct vnode *v, vaddr_t *entrypoint) { Elf_Ehdr eh; /* Executable header */ Elf_Phdr ph; /* "Program header" = segment header */ int result, i; struct iovec iov; struct uio ku; struct addrspace *as = curthread->t_addrspace; /* * Read the executable header from offset 0 in the file. */ uio_kinit(&iov, &ku, &eh, sizeof(eh), 0, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on header - file truncated?\n"); return ENOEXEC; } /* * Check to make sure it's a 32-bit ELF-version-1 executable * for our processor type. If it's not, we can't run it. * * Ignore EI_OSABI and EI_ABIVERSION - properly, we should * define our own, but that would require tinkering with the * linker to have it emit our magic numbers instead of the * default ones. (If the linker even supports these fields, * which were not in the original elf spec.) */ if (eh.e_ident[EI_MAG0] != ELFMAG0 || eh.e_ident[EI_MAG1] != ELFMAG1 || eh.e_ident[EI_MAG2] != ELFMAG2 || eh.e_ident[EI_MAG3] != ELFMAG3 || eh.e_ident[EI_CLASS] != ELFCLASS32 || eh.e_ident[EI_DATA] != ELFDATA2MSB || eh.e_ident[EI_VERSION] != EV_CURRENT || eh.e_version != EV_CURRENT || eh.e_type!=ET_EXEC || eh.e_machine!=EM_MACHINE) { return ENOEXEC; } /* * Go through the list of segments and set up the address space. * * Ordinarily there will be one code segment, one read-only * data segment, and one data/bss segment, but there might * conceivably be more. You don't need to support such files * if it's unduly awkward to do so. * * Note that the expression eh.e_phoff + i*eh.e_phentsize is * mandated by the ELF standard - we use sizeof(ph) to load, * because that's the structure we know, but the file on disk * might have a larger structure, so we must use e_phentsize * to find where the phdr starts. */ DEBUG(DB_DEMAND,"Num Of Segements:%d\n",eh.e_phnum); for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: /* skip */ continue; case PT_PHDR: /* skip */ continue; case PT_MIPS_REGINFO: /* skip */ continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } DEBUG(DB_DEMAND, "MEM SZ:%d\n",ph.p_memsz); DEBUG(DB_DEMAND, "FILE SZ:%d\n", ph.p_filesz); DEBUG(DB_DEMAND, "VADDR:%p\n",(void*)ph.p_vaddr); result = as_define_region(curthread->t_addrspace, ph.p_vaddr, ph.p_memsz, ph.p_flags & PF_R, ph.p_flags & PF_W, ph.p_flags & PF_X); if (result) { return result; } } result = as_prepare_load(curthread->t_addrspace); if (result) { return result; } /* * Now actually load each segment. */ for (i=0; i<eh.e_phnum; i++) { off_t offset = eh.e_phoff + i*eh.e_phentsize; uio_kinit(&iov, &ku, &ph, sizeof(ph), offset, UIO_READ); DEBUG(DB_DEMAND, "SEGMENT: %d\n",1); result = VOP_READ(v, &ku); if (result) { return result; } if (ku.uio_resid != 0) { /* short read; problem with executable? */ kprintf("ELF: short read on phdr - file truncated?\n"); return ENOEXEC; } switch (ph.p_type) { case PT_NULL: /* skip */ continue; case PT_PHDR: /* skip */ continue; case PT_MIPS_REGINFO: /* skip */ continue; case PT_LOAD: break; default: kprintf("loadelf: unknown segment type %d\n", ph.p_type); return ENOEXEC; } struct addrspace *as = curthread->t_addrspace; vaddr_t va = ph.p_vaddr; DEBUG(DB_DEMAND, "Original VA: %p\n", (void*) va); DEBUG(DB_DEMAND, "Max VA:%p\n", (void*) (va + ph.p_memsz)); // va &= PAGE_FRAME; struct page_table *pt = pgdir_walk(as,va,false); int pt_index = VA_TO_PT_INDEX(va); int permissions = PTE_TO_PERMISSIONS(pt->table[pt_index]); int small_pages = 0; if(ph.p_memsz <= PAGE_SIZE) { DEBUG(DB_DEMAND, "Segement Total Size is < 4k\n"); // pt = pgdir_walk(as,va,false); // pt_index = VA_TO_PT_INDEX(va); // permissions = PTE_TO_PERMISSIONS(pt->table[pt_index]); result = dynamic_load_segment(v, ph.p_offset, va, ph.p_memsz, ph.p_filesz, ph.p_flags & PF_X,permissions); if (result) { return result; } // page->state = DIRTY; small_pages = 1; } else { int filesize = (int) ph.p_filesz; int memsize = (int) ph.p_memsz; off_t cur_offset = ph.p_offset; DEBUG(DB_DEMAND, "Loading >1 Segment\n"); DEBUG(DB_DEMAND, "Original Parameters:\n"); DEBUG(DB_DEMAND, "File Size: %d\n",filesize); DEBUG(DB_DEMAND, "Mem Size: %d\n", memsize); DEBUG(DB_DEMAND, "Offset:%d\n", (int) cur_offset); DEBUG(DB_DEMAND, "VA:%p\n", (void*) va); size_t amt_to_read; int pages = 0; int blank_pages = 0; while(filesize > 0) { // struct page *page = page_alloc(as,va & PAGE_FRAME,permissions); DEBUG(DB_DEMAND, "loading...\n"); DEBUG(DB_DEMAND, "File Size: %d\n",filesize); DEBUG(DB_DEMAND, "Mem Size: %d\n", memsize); DEBUG(DB_DEMAND, "Offset:%d\n", (int) cur_offset); DEBUG(DB_DEMAND, "VA:%p\n", (void*) va); amt_to_read = (filesize - PAGE_SIZE > 0 ? PAGE_SIZE : filesize); result = dynamic_load_segment(v, cur_offset, va, PAGE_SIZE, amt_to_read, ph.p_flags & PF_X,permissions); if (result) { return result; } filesize -= PAGE_SIZE; memsize -= PAGE_SIZE; va += PAGE_SIZE; cur_offset += PAGE_SIZE; // page->state = DIRTY; pages++; } (void)blank_pages; DEBUG(DB_DEMAND,"Empty Pages...\n"); while(memsize > 0) { DEBUG(DB_DEMAND,"Mem Size:%d\n",memsize); DEBUG(DB_DEMAND,"VA: %p\n",(void*) va); bool lock = get_coremap_lock(); struct page *page = page_alloc(as,va & PAGE_FRAME,permissions); release_coremap_lock(lock); va += PAGE_SIZE; memsize -= PAGE_SIZE; KASSERT(page->state == LOCKED); page->state = DIRTY; blank_pages++; } DEBUG(DB_DEMAND, "Small Pages: %d\n", small_pages); DEBUG(DB_DEMAND, "Pages: %d\n", pages); DEBUG(DB_DEMAND, "Blank Pages: %d\n", blank_pages); } // result = load_segment(v, ph.p_offset, ph.p_vaddr, // ph.p_memsz, ph.p_filesz, // ph.p_flags & PF_X); if (result) { return result; } } result = as_complete_load(curthread->t_addrspace); if (result) { return result; } *entrypoint = eh.e_entry; /* Register load complete in addrspace */ as->loadelf_done = true; DEBUG(DB_VM,"LoadELFDone\n"); // kprintf("LoadELF done\n"); return 0; }
static int fstest_write(const char *fs, const char *namesuffix, int stridesize, int stridepos) { struct vnode *vn; int err; int i; size_t shouldbytes=0; size_t bytes=0; off_t pos=0; char name[32]; char buf[32]; struct iovec iov; struct uio ku; int flags; KASSERT(sizeof(buf) > strlen(SLOGAN)); MAKENAME(); flags = O_WRONLY|O_CREAT; if (stridesize == 1) { flags |= O_TRUNC; } /* vfs_open destroys the string it's passed */ strcpy(buf, name); err = vfs_open(buf, flags, 0664, &vn); if (err) { kprintf("Could not open %s for write: %s\n", name, strerror(err)); return -1; } for (i=0; i<NCHUNKS; i++) { if (i % stridesize != stridepos) { pos += strlen(SLOGAN); continue; } strcpy(buf, SLOGAN); rotate(buf, i); uio_kinit(&iov, &ku, buf, strlen(SLOGAN), pos, UIO_WRITE); err = VOP_WRITE(vn, &ku); if (err) { kprintf("%s: Write error: %s\n", name, strerror(err)); vfs_close(vn); vfs_remove(name); return -1; } if (ku.uio_resid > 0) { kprintf("%s: Short write: %lu bytes left over\n", name, (unsigned long) ku.uio_resid); vfs_close(vn); vfs_remove(name); return -1; } bytes += (ku.uio_offset - pos); shouldbytes += strlen(SLOGAN); pos = ku.uio_offset; } vfs_close(vn); if (bytes != shouldbytes) { kprintf("%s: %lu bytes written, should have been %lu!\n", name, (unsigned long) bytes, (unsigned long) (NCHUNKS*strlen(SLOGAN))); vfs_remove(name); return -1; } kprintf("%s: %lu bytes written\n", name, (unsigned long) bytes); return 0; }
static int fstest_read(const char *fs, const char *namesuffix) { struct vnode *vn; int err; int i; size_t bytes=0; char name[32]; char buf[32]; struct iovec iov; struct uio ku; MAKENAME(); /* vfs_open destroys the string it's passed */ strcpy(buf, name); err = vfs_open(buf, O_RDONLY, 0664, &vn); if (err) { kprintf("Could not open test file for read: %s\n", strerror(err)); return -1; } for (i=0; i<NCHUNKS; i++) { uio_kinit(&iov, &ku, buf, strlen(SLOGAN), bytes, UIO_READ); err = VOP_READ(vn, &ku); if (err) { kprintf("%s: Read error: %s\n", name, strerror(err)); vfs_close(vn); return -1; } if (ku.uio_resid > 0) { kprintf("%s: Short read: %lu bytes left over\n", name, (unsigned long) ku.uio_resid); vfs_close(vn); return -1; } buf[strlen(SLOGAN)] = 0; rotate(buf, -i); if (strcmp(buf, SLOGAN)) { kprintf("%s: Test failed: line %d mismatched: %s\n", name, i+1, buf); vfs_close(vn); return -1; } bytes = ku.uio_offset; } vfs_close(vn); if (bytes != NCHUNKS*strlen(SLOGAN)) { kprintf("%s: %lu bytes read, should have been %lu!\n", name, (unsigned long) bytes, (unsigned long) (NCHUNKS*strlen(SLOGAN))); return -1; } kprintf("%s: %lu bytes read\n", name, (unsigned long) bytes); return 0; }
int printfile(int nargs, char **args) { struct vnode *rv, *wv; struct iovec iov; struct uio ku; off_t rpos=0, wpos=0; char buf[128]; char outfile[16]; int result; int done=0; if (nargs != 2) { kprintf("Usage: pf filename\n"); return EINVAL; } /* vfs_open destroys the string it's passed; make a copy */ strcpy(outfile, "con:"); result = vfs_open(args[1], O_RDONLY, 0664, &rv); if (result) { kprintf("printfile: %s\n", strerror(result)); return result; } result = vfs_open(outfile, O_WRONLY, 0664, &wv); if (result) { kprintf("printfile: output: %s\n", strerror(result)); vfs_close(rv); return result; } while (!done) { uio_kinit(&iov, &ku, buf, sizeof(buf), rpos, UIO_READ); result = VOP_READ(rv, &ku); if (result) { kprintf("Read error: %s\n", strerror(result)); break; } rpos = ku.uio_offset; if (ku.uio_resid > 0) { done = 1; } uio_kinit(&iov, &ku, buf, sizeof(buf)-ku.uio_resid, wpos, UIO_WRITE); result = VOP_WRITE(wv, &ku); if (result) { kprintf("Write error: %s\n", strerror(result)); break; } wpos = ku.uio_offset; if (ku.uio_resid > 0) { kprintf("Warning: short write\n"); } } vfs_close(wv); vfs_close(rv); return 0; }