Ejemplo n.º 1
0
__export int open_file(const char *name, int flags, struct com32_filedata *filedata)
{
    int rv;
    struct file *file;
    char mangled_name[FILENAME_MAX];

    dprintf("open_file %s\n", name);

    mangle_name(mangled_name, name);
    rv = searchdir(mangled_name, flags);

    if (rv < 0)
	return rv;

    file = handle_to_file(rv);

    if (file->inode->mode != DT_REG) {
	_close_file(file);
	return -1;
    }

    filedata->size	= file->inode->size;
    filedata->blocklg2	= SECTOR_SHIFT(file->fs);
    filedata->handle	= rv;

    return rv;
}
Ejemplo n.º 2
0
void getfsbytes(com32sys_t *regs)
{
    int sectors;
    bool have_more;
    uint32_t bytes_read;
    char *buf;
    struct file *file;
    uint16_t handle;

    handle = regs->esi.w[0];
    file = handle_to_file(handle);

    sectors = regs->ecx.w[0] >> SECTOR_SHIFT(file->fs);

    buf = MK_PTR(regs->es, regs->ebx.w[0]);
    bytes_read = file->fs->fs_ops->getfssec(file, buf, sectors, &have_more);

    /*
     * If we reach EOF, the filesystem driver will have already closed
     * the underlying file... this really should be cleaner.
     */
    if (!have_more) {
	_close_file(file);
        regs->esi.w[0] = 0;
    }

    regs->ecx.l = bytes_read;
}
Ejemplo n.º 3
0
static struct inode *iso_get_inode(struct fs_info *fs,
				   const struct iso_dir_entry *de)
{
    struct inode *inode = new_iso_inode(fs);
    int blktosec = BLOCK_SHIFT(fs) - SECTOR_SHIFT(fs);

    if (!inode)
	return NULL;

    dprintf("Getting inode for: %.*s\n", de->name_len, de->name);

    inode->mode   = get_inode_mode(de->flags);
    inode->size   = de->size_le;
    PVT(inode)->lba = de->extent_le;
    inode->blocks = (inode->size + BLOCK_SIZE(fs) - 1) >> BLOCK_SHIFT(fs);

    /* We have a single extent for all data */
    inode->next_extent.pstart = (sector_t)de->extent_le << blktosec;
    inode->next_extent.len    = (sector_t)inode->blocks << blktosec;

    return inode;
}
Ejemplo n.º 4
0
void pm_load_high(com32sys_t *regs)
{
    struct fs_info *fs;
    uint32_t bytes;
    uint32_t zero_mask;
    bool have_more;
    uint32_t bytes_read;
    char *buf, *limit;
    struct file *file;
    uint32_t sector_mask;
    size_t pad;
    uint32_t retflags = 0;

    bytes     = regs->eax.l;
    zero_mask = regs->edx.w[0];
    buf       = (char *)regs->edi.l;
    limit     = (char *)(regs->ebp.l & ~zero_mask);
    file      = handle_to_file(regs->esi.w[0]);
    fs        = file->fs;

    sector_mask = SECTOR_SIZE(fs) - 1;

    while (bytes) {
	uint32_t sectors;
	uint32_t chunk;

	if (buf + SECTOR_SIZE(fs) > limit) {
	    /* Can't fit even one more sector in... */
	    retflags = EFLAGS_OF;
	    break;
	}

	chunk = bytes;

	if (regs->ebx.w[0]) {
	    call16((void (*)(void))(size_t)regs->ebx.w[0], &zero_regs, NULL);
	    chunk = min(chunk, MAX_CHUNK);
	}

	if (chunk > (((char *)limit - buf) & ~sector_mask))
	    chunk = ((char *)limit - buf) & ~sector_mask;

	sectors = (chunk + sector_mask) >> SECTOR_SHIFT(fs);
	bytes_read = fs->fs_ops->getfssec(file, buf, sectors, &have_more);

	if (bytes_read > chunk)
	    bytes_read = chunk;

	buf += bytes_read;
	bytes -= bytes_read;

	if (!have_more) {
	    /*
	     * If we reach EOF, the filesystem driver will have already closed
	     * the underlying file... this really should be cleaner.
	     */
	    _close_file(file);
	    regs->esi.w[0] = 0;
	    retflags = EFLAGS_CF;
	    break;
	}
    }

    pad = (size_t)buf & zero_mask;
    if (pad)
	memset(buf, 0, pad);

    regs->ebx.l = (size_t)buf;
    regs->edi.l = (size_t)buf + pad;
    set_flags(regs, retflags);
}
Ejemplo n.º 5
0
uint32_t generic_getfssec(struct file *file, char *buf,
			  int sectors, bool *have_more)
{
    struct inode *inode = file->inode;
    struct fs_info *fs = file->fs;
    struct disk *disk = fs->fs_dev->disk;
    uint32_t bytes_read = 0;
    uint32_t bytes_left = inode->size - file->offset;
    uint32_t sectors_left =
	(bytes_left + SECTOR_SIZE(fs) - 1) >> SECTOR_SHIFT(fs);
    uint32_t lsector;

    if (sectors > sectors_left)
	sectors = sectors_left;

    if (!sectors)
	return 0;

    lsector = file->offset >> SECTOR_SHIFT(fs);
    dprintf("Offset: %u  lsector: %u\n", file->offset, lsector);

    if (lsector < inode->this_extent.lstart ||
	lsector >= inode->this_extent.lstart + inode->this_extent.len) {
	/* inode->this_extent unusable, maybe next_extent is... */
	inode->this_extent = inode->next_extent;
    }

    if (lsector < inode->this_extent.lstart ||
	lsector >= inode->this_extent.lstart + inode->this_extent.len) {
	/* Still nothing useful... */
	inode->this_extent.lstart = lsector;
	inode->this_extent.len = 0;
    } else {
	/* We have some usable information */
	uint32_t delta = lsector - inode->this_extent.lstart;
	inode->this_extent.lstart = lsector;
	inode->this_extent.len -= delta;
	inode->this_extent.pstart
	    = next_psector(inode->this_extent.pstart, delta);
    }

    dprintf("this_extent: lstart %u pstart %llu len %u\n",
	    inode->this_extent.lstart,
	    inode->this_extent.pstart,
	    inode->this_extent.len);

    while (sectors) {
	uint32_t chunk;
	size_t len;

	while (sectors > inode->this_extent.len) {
	    if (!inode->next_extent.len ||
		inode->next_extent.lstart !=
		inode->this_extent.lstart + inode->this_extent.len)
		get_next_extent(inode);

	    if (!inode->this_extent.len) {
		/* Doesn't matter if it's contiguous... */
		inode->this_extent = inode->next_extent;
		if (!inode->next_extent.len) {
		    sectors = 0; /* Failed to get anything... we're dead */
		    break;
		}
	    } else if (inode->next_extent.len &&
		inode->next_extent.pstart == next_pstart(&inode->this_extent)) {
		/* Coalesce extents and loop */
		inode->this_extent.len += inode->next_extent.len;
	    } else {
		/* Discontiguous extents */
		break;
	    }
	}

	dprintf("this_extent: lstart %u pstart %llu len %u\n",
		inode->this_extent.lstart,
		inode->this_extent.pstart,
		inode->this_extent.len);

	chunk = min(sectors, inode->this_extent.len);
	len = chunk << SECTOR_SHIFT(fs);

	dprintf("   I/O: inode %p @ %u start %llu len %u\n",
		inode, inode->this_extent.lstart,
		inode->this_extent.pstart, chunk);

	if (inode->this_extent.pstart == EXTENT_ZERO) {
	    memset(buf, 0, len);
	} else {
	    disk->rdwr_sectors(disk, buf, inode->this_extent.pstart, chunk, 0);
	    inode->this_extent.pstart += chunk;
	}

	buf += len;
	sectors -= chunk;
	bytes_read += len;
	inode->this_extent.lstart += chunk;
	inode->this_extent.len -= chunk;
    }

    bytes_read = min(bytes_read, bytes_left);
    file->offset += bytes_read;

    if (have_more)
	*have_more = bytes_read < bytes_left;

    return bytes_read;
}