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; }
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; }
/* 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); }
/** 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
/** 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; }
/** 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; }
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; }
/** 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; }
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; }
/** 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; }
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; }
/** 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; }
/* 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); }