int fat_directory_expand(fat_directory_t *di)
{
	int rc;
	fat_cluster_t mcl, lcl;

	if (!FAT_IS_FAT32(di->bs) && di->nodep->firstc == FAT_CLST_ROOT) {
		/* Can't grow the root directory on FAT12/16. */
		return ENOSPC;
	}
	rc = fat_alloc_clusters(di->bs, di->nodep->idx->service_id, 1, &mcl,
	    &lcl);
	if (rc != EOK)
		return rc;
	rc = fat_zero_cluster(di->bs, di->nodep->idx->service_id, mcl);
	if (rc != EOK) {
		(void) fat_free_clusters(di->bs, di->nodep->idx->service_id,
		    mcl);
		return rc;
	}
	rc = fat_append_clusters(di->bs, di->nodep, mcl, lcl);
	if (rc != EOK) {
		(void) fat_free_clusters(di->bs, di->nodep->idx->service_id,
		    mcl);
		return rc;
	}
	di->nodep->size += BPS(di->bs) * SPC(di->bs);
	di->nodep->dirty = true;		/* need to sync node */
	di->blocks = di->nodep->size / BPS(di->bs);
	
	return EOK;
}
int exfat_bitmap_set_cluster(exfat_bs_t *bs, service_id_t service_id, 
    exfat_cluster_t clst)
{
	fs_node_t *fn;
	block_t *b = NULL;
	exfat_node_t *bitmapp;
	uint8_t *bitmap;
	int rc;

	clst -= EXFAT_CLST_FIRST;
	
	rc = exfat_bitmap_get(&fn, service_id);
	if (rc != EOK)
		return rc;
	bitmapp = EXFAT_NODE(fn);
	
	aoff64_t offset = clst / 8;
	rc = exfat_block_get(&b, bs, bitmapp, offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK) {
		(void) exfat_node_put(fn);
		return rc;
	}
	bitmap = (uint8_t *)b->data;
	bitmap[offset % BPS(bs)] |= (1 << (clst % 8));

	b->dirty = true;
	rc = block_put(b);
	if (rc != EOK) {
		(void) exfat_node_put(fn);
		return rc;
	}
	
	return exfat_node_put(fn);
}
int fat_directory_open(fat_node_t *nodep, fat_directory_t *di)
{
	di->b = NULL;
	di->nodep = nodep;	
	if (di->nodep->type != FAT_DIRECTORY)
		return EINVAL;

	di->bs = block_bb_get(di->nodep->idx->service_id);
	di->blocks = ROUND_UP(nodep->size, BPS(di->bs)) / BPS(di->bs);
	di->pos = 0;
	di->bnum = 0;
	di->last = false;

	return EOK;
}
Exemple #4
0
static int fat_node_sync(fat_node_t *node)
{
	block_t *b;
	fat_bs_t *bs;
	fat_dentry_t *d;
	int rc;

	assert(node->dirty);

	bs = block_bb_get(node->idx->service_id);

	/* Read the block that contains the dentry of interest. */
	rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
	    NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
	    BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	d = ((fat_dentry_t *)b->data) + (node->idx->pdi % DPS(bs));

	d->firstc = host2uint16_t_le(node->firstc);
	if (node->type == FAT_FILE) {
		d->size = host2uint32_t_le(node->size);
	} else if (node->type == FAT_DIRECTORY) {
		d->attr = FAT_ATTR_SUBDIR;
	}

	/* TODO: update other fields? (e.g time fields) */

	b->dirty = true;		/* need to sync block */
	rc = block_put(b);
	return rc;
}
static int fat_directory_block_load(fat_directory_t *di)
{
	uint32_t i;
	int rc;

	i = (di->pos * sizeof(fat_dentry_t)) / BPS(di->bs);
	if (i < di->blocks) {
		if (di->b && di->bnum != i) {
			block_put(di->b);
			di->b = NULL;
		}
		if (!di->b) {
			rc = fat_block_get(&di->b, di->bs, di->nodep, i,
			    BLOCK_FLAGS_NONE);
			if (rc != EOK) {
				di->b = NULL;
				return rc;
			}
			di->bnum = i;
		}
		return EOK;
	}

	return ENOENT;
}
Exemple #6
0
/* stack: ( speed termios - ) */
void mu_set_termios_speed()
{
    struct termios *pti = (struct termios *) TOP;

#define BPS(x)  case x: ST1 = B ## x; break

    switch(ST1)
    {
        BPS(  4800);
        BPS(  9600);
        BPS( 19200);
        BPS( 38400);
        BPS( 57600);
        BPS(115200);
        BPS(230400);
    default:
        return abort_zmsg("Unsupported speed");
    }

#ifdef __CYGWIN__
    /* Cygwin lacks cfsetspeed, so do it by hand. */
    pti->c_ospeed = pti->c_ispeed = ST1;
#else
    cfsetspeed(pti, ST1);
#endif
    DROP(2);
}
Exemple #7
0
/** Get cluster from the first FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which to get.
 * @param value		Output argument holding the value of the cluster.
 *
 * @return		EOK or a negative error code.
 */
static int
fat_get_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
    fat_cluster_t clst, fat_cluster_t *value)
{
	block_t *b, *b1;
	uint16_t byte1, byte2;
	aoff64_t offset;
	int rc;

	offset = (clst + clst / 2);
	if (offset / BPS(bs) >= SF(bs))
		return ERANGE;

	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
	    offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	byte1 = ((uint8_t *) b->data)[offset % BPS(bs)];
	/* This cluster access spans a sector boundary. Check only for FAT12 */
	if ((offset % BPS(bs)) + 1 == BPS(bs)) {
		/* Is this the last sector of FAT? */
		if (offset / BPS(bs) < SF(bs)) {
			/* No, read the next sector */
			rc = block_get(&b1, service_id, 1 + RSCNT(bs) +
			    SF(bs) * fatno + offset / BPS(bs),
			    BLOCK_FLAGS_NONE);
			if (rc != EOK) {
				block_put(b);
				return rc;
			}
			/*
			* Combining value with last byte of current sector and
			* first byte of next sector
			*/
			byte2 = ((uint8_t*) b1->data)[0];

			rc = block_put(b1);
			if (rc != EOK) {
				block_put(b);
				return rc;
			}
		} else {
			/* Yes. This is the last sector of FAT */
			block_put(b);
			return ERANGE;
		}
	} else
		byte2 = ((uint8_t *) b->data)[(offset % BPS(bs)) + 1];

	*value = uint16_t_le2host(byte1 | (byte2 << 8));
	if (IS_ODD(clst))
		*value = (*value) >> 4;
	else
Exemple #8
0
/** Set cluster in FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which is to be set.
 * @param value		Value to set the cluster with.
 *
 * @return		EOK on success or a negative error code.
 */
int
exfat_set_cluster(exfat_bs_t *bs, service_id_t service_id,
    exfat_cluster_t clst, exfat_cluster_t value)
{
	block_t *b;
	aoff64_t offset;
	int rc;

	offset = clst * sizeof(exfat_cluster_t);

	rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	*(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(value);

	b->dirty = true;	/* need to sync block */
	rc = block_put(b);
	return rc;
}
Exemple #9
0
/** Get cluster from the FAT.
 *
 * @param bs		Buffer holding the boot sector for the file system.
 * @param service_id	Service ID for the file system.
 * @param clst		Cluster which to get.
 * @param value		Output argument holding the value of the cluster.
 *
 * @return		EOK or a negative error code.
 */
int
exfat_get_cluster(exfat_bs_t *bs, service_id_t service_id,
    exfat_cluster_t clst, exfat_cluster_t *value)
{
	block_t *b;
	aoff64_t offset;
	int rc;

	offset = clst * sizeof(exfat_cluster_t);

	rc = block_get(&b, service_id, FAT_FS(bs) + offset / BPS(bs), BLOCK_FLAGS_NONE);
	if (rc != EOK)
		return rc;

	*value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));

	rc = block_put(b);

	return rc;
}
Exemple #10
0
void test_basic_interpolation() {
    char *s = "a_string";
    double f = 3.14159;
    bson_bool_t bb = 1;
    time_t t = time(0);
    char *x = "a symbol";
    int i = 123;
    long l = 456789L;
    bcon basic_interpolation[] = {"string", BPS(&s), "f(double)", BPF(&f), "boolean", BPB(&bb), "time", BPT(&t), "symbol", BPX(&x), "int", BPI(&i), "long", BPL(&l), BEND};
    test_bson_from_bcon( basic_interpolation, BCON_OK, BSON_VALID );
}
int fat_directory_get(fat_directory_t *di, fat_dentry_t **d)
{
	int rc;
	
	rc = fat_directory_block_load(di);
	if (rc == EOK) {
		aoff64_t o = di->pos % (BPS(di->bs) / sizeof(fat_dentry_t));
		*d = ((fat_dentry_t *)di->b->data) + o;
	}
	
	return rc;
}
Exemple #12
0
/** Read block from file located on a FAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param nodep		FAT node.
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
fat_block_get(block_t **block, struct fat_bs *bs, fat_node_t *nodep,
    aoff64_t bn, int flags)
{
	fat_cluster_t firstc = nodep->firstc;
	fat_cluster_t currc;
	aoff64_t relbn = bn;
	int rc;

	if (!nodep->size)
		return ELIMIT;

	if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
		goto fall_through;

	if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
	    nodep->lastc_cached_valid) {
	    	/*
		 * This is a request to read a block within the last cluster
		 * when fortunately we have the last cluster number cached.
		 */
		return block_get(block, nodep->idx->service_id,
		    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
	}

	if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
		/*
		 * We can start with the cluster cached by the previous call to
		 * fat_block_get().
		 */
		firstc = nodep->currc_cached_value;
		relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
	}

fall_through:
	rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
	    &currc, relbn, flags);
	if (rc != EOK)
		return rc;

	/*
	 * Update the "current" cluster cache.
	 */
	nodep->currc_cached_valid = true;
	nodep->currc_cached_bn = bn;
	nodep->currc_cached_value = currc;

	return rc;
}
Exemple #13
0
int
exfat_read_uctable(exfat_bs_t *bs, exfat_node_t *nodep, uint8_t *uctable)
{
	size_t i, blocks, count;
	block_t *b;
	int rc;
	blocks = ROUND_UP(nodep->size, BPS(bs))/BPS(bs);
	count = BPS(bs);
	
	for (i = 0; i < blocks; i++) {
		rc = exfat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NOREAD);
		if (rc != EOK)
			return rc;
		if (i == blocks - 1)
			count = nodep->size - i * BPS(bs);
		memcpy(uctable, b->data, count);
		uctable += count;
		rc = block_put(b);
		if (rc != EOK)
			return rc;
	}

	return EOK;
}
Exemple #14
0
/** Read block from file located on a exFAT file system.
 *
 * @param block		Pointer to a block pointer for storing result.
 * @param bs		Buffer holding the boot sector of the file system.
 * @param nodep		FAT node.
 * @param bn		Block number.
 * @param flags		Flags passed to libblock.
 *
 * @return		EOK on success or a negative error code.
 */
int
exfat_block_get(block_t **block, exfat_bs_t *bs, exfat_node_t *nodep,
    aoff64_t bn, int flags)
{
	exfat_cluster_t firstc = nodep->firstc;
	exfat_cluster_t currc = 0;
	aoff64_t relbn = bn;
	int rc;

	if (!nodep->size)
		return ELIMIT;

	if (nodep->fragmented) {
		if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) &&
		    nodep->lastc_cached_valid) {
			/*
			 * This is a request to read a block within the last cluster
			 * when fortunately we have the last cluster number cached.
			 */
			return block_get(block, nodep->idx->service_id, DATA_FS(bs) + 
		        (nodep->lastc_cached_value-EXFAT_CLST_FIRST)*SPC(bs) + 
			    (bn % SPC(bs)), flags);
		}

		if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) {
			/*
			* We can start with the cluster cached by the previous call to
			* fat_block_get().
			*/
			firstc = nodep->currc_cached_value;
			relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs);
		}
	}

	rc = exfat_block_get_by_clst(block, bs, nodep->idx->service_id,
	    nodep->fragmented, firstc, &currc, relbn, flags);
	if (rc != EOK)
		return rc;

	/*
	 * Update the "current" cluster cache.
	 */
	nodep->currc_cached_valid = true;
	nodep->currc_cached_bn = bn;
	nodep->currc_cached_value = currc;

	return rc;
}
Exemple #15
0
int
exfat_zero_cluster(exfat_bs_t *bs, service_id_t service_id, exfat_cluster_t c)
{
	size_t i;
	block_t *b;
	int rc;

	for (i = 0; i < SPC(bs); i++) {
		rc = exfat_block_get_by_clst(&b, bs, service_id, false, c, NULL,
		    i, BLOCK_FLAGS_NOREAD);
		if (rc != EOK)
			return rc;
		memset(b->data, 0, BPS(bs));
		b->dirty = true;
		rc = block_put(b);
		if (rc != EOK)
			return rc;
	}

	return EOK;
}
Exemple #16
0
/** Fill the gap between EOF and a new file position.
 *
 * @param bs		Buffer holding the boot sector for nodep.
 * @param nodep		FAT node with the gap.
 * @param mcl		First cluster in an independent cluster chain that will
 *			be later appended to the end of the node's own cluster
 *			chain. If pos is still in the last allocated cluster,
 *			this argument is ignored.
 * @param pos		Position in the last node block.
 *
 * @return		EOK on success or a negative error code.
 */
int
fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos)
{
	block_t *b;
	aoff64_t o, boundary;
	int rc;

	boundary = ROUND_UP(nodep->size, BPS(bs) * SPC(bs));

	/* zero out already allocated space */
	for (o = nodep->size; o < pos && o < boundary;
	    o = ALIGN_DOWN(o + BPS(bs), BPS(bs))) {
	    	int flags = (o % BPS(bs) == 0) ?
		    BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE;
		rc = fat_block_get(&b, bs, nodep, o / BPS(bs), flags);
		if (rc != EOK)
			return rc;
		memset(b->data + o % BPS(bs), 0, BPS(bs) - o % BPS(bs));
		b->dirty = true;		/* need to sync node */
		rc = block_put(b);
		if (rc != EOK)
			return rc;
	}

	if (o >= pos)
		return EOK;

	/* zero out the initial part of the new cluster chain */
	for (o = boundary; o < pos; o += BPS(bs)) {
		rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
		    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
		if (rc != EOK)
			return rc;
		memset(b->data, 0, min(BPS(bs), pos - o));
		b->dirty = true;		/* need to sync node */
		rc = block_put(b);
		if (rc != EOK)
			return rc;
	}

	return EOK;
}
Exemple #17
0
/* Set up uart stuff; expects DDR register to already be set up */
void serial_init_rx(void)
{
	outp(BPS(115200, CPUFREQ), UBRR);
	outp(inp(UCR) | (1 << RXCIE) | (1 << RXEN), UCR);
}