fscreate.c 2.29 KB
#include <PR/bcp.h>
#include <os.h>
#include "os_bbfs.h"
#include "bbint.h"

void
__osBbFsFormatName(char fname[BB_INODE16_NAMELEN], const char* name) {
    int i, j;
    /* reformat name to XXXXXXXXYYY filling with 0s */
    for(i = 0; name[i] && name[i] != '.' && i < BB_INODE16_NAMELEN-3; i++)
	fname[i] = name[i];
    for(j = i; j < BB_INODE16_NAMELEN-3; j++) fname[j] = '\0';
    if (name[i] == '.') {
	i++;
	while(name[i] && j < BB_INODE16_NAMELEN)
	    fname[j++] = name[i++];
    }
    while(j < BB_INODE16_NAMELEN)
	fname[j++] = '\0';
}

s32
osBbFCreate(const char* name, u8 type, u32 len) {
    u16 i, b, prev = 0;
    BbInode* in = 0;
    BbFat16* fat;
    s32 rv = 0, incr;
    char fname[BB_INODE16_NAMELEN];

    if (len&(BB_FL_BLOCK_SIZE-1)) return BBFS_ERR_INVALID;
    __osBbFsFormatName(fname, name);
    if (!fname[0]) return BBFS_ERR_INVALID;
    if ((rv = __osBbFsGetAccess()) < 0) return rv;
    fat = __osBbFat;
    /* check if entry already exists and find free inode */
    rv = BBFS_ERR_EXISTS;
    for(i = 0; i < BB_INODE16_ENTRIES; i++) {
	if (fat->inode[i].type && bcmp(fname, fat->inode[i].name, BB_INODE16_NAMELEN) == 0)
	    goto error;
	if (fat->inode[i].type == 0 && !in)
	    in = fat->inode+i;
    }
    if (!in) {
	rv = BBFS_ERR_SPACE;
	goto error;
    }

    if (len > BB_BIG_FILE_THRESHOLD) {
	/* big files go low in the fat */
	b = BB_FL_BYTE_TO_BLOCK(BB_SYSTEM_AREA_SIZE); incr = 1;
    } else {
	/* small files at the other end */
	b = __osBbFsBlocks-1; incr = -1;
    }
    in->block = BB_FAT_LAST;
    for(i = 0; i < BB_FL_BYTE_TO_BLOCK(len+BB_FL_BLOCK_SIZE-1); i++) {
	/* allocate a block */
	while(b < __osBbFsBlocks && BB_FAT16_NEXT(fat,b) != BB_FAT_AVAIL)
	    b += incr;
	if (b >= __osBbFsBlocks) goto error_undo;
	BB_FAT16_NEXT(fat,b) = BB_FAT_LAST;
	if (prev) BB_FAT16_NEXT(fat,prev) = b;
	else in->block = b;
	prev = b;
    }
    bcopy(fname, in->name, BB_INODE16_NAMELEN);
    in->type = 1;
    in->size = len;
    if ((rv = __osBbFsSync(0)) == 0) {
	rv = in-fat->inode;
	goto out;
    }
error_undo:
    /* deallocate pending allocations */
    b = in->block;
    while(b != BB_FAT_LAST) {
	u16 n = BB_FAT16_NEXT(fat,b);
	BB_FAT16_NEXT(fat,b) = BB_FAT_AVAIL;
	b = n;
    }
    in->name[0] = in->size = in->block = 0;
    rv = BBFS_ERR_SPACE;
error:
out:
    __osBbFsRelAccess();
    return rv;
}