fsread.c 1.21 KB
#include <PR/bcp.h>
#include "os.h"
#include "os_bbcard.h"
#include "os_bbfs.h"
#include "bbint.h"
s32
osBbFRead(s32 fd, u32 off, void* buf, u32 len) {
    s32 rv = BBFS_ERR_INVALID;
    BbInode* in;
    u32 count, b, i;
    BbFat16* fat;
#ifdef _DEBUG
    if ((u32)buf&15) return rv;
#endif
    if (fd < 0 || fd >= BB_INODE16_ENTRIES) return rv;
    if ((rv = __osBbFsGetAccess()) < 0) return rv;
    fat = __osBbFat;
    in = fat->inode+fd;
    /* check size, etc */
    rv = BBFS_ERR_INVALID;
    if (!in->type) goto error;
    if ((off & (BB_FL_BLOCK_SIZE-1)) || off >= in->size) goto error;
    if (off+len < off) goto error; /* overflow */
    if (off+len > in->size) len = in->size-off;
    if (!len) {
	rv = 0;
	goto error;
    }

    /* find starting block */
    b = in->block;
    for(i = 0; i < BB_FL_BYTE_TO_BLOCK(off); i++)
	b = BB_FAT16_NEXT(fat,b);
    count = 0;
    while(len > 0) {
	if (b == 0 || b >= __osBbFsBlocks-BB_FAT16_BLOCKS) goto error;
	if ((rv = osBbCardReadBlock(0, b, buf, 0)) < 0) goto error;
	b = BB_FAT16_NEXT(fat,b);
	buf += BB_FL_BLOCK_SIZE;
	len -= len > BB_FL_BLOCK_SIZE ? BB_FL_BLOCK_SIZE : len;
	count += BB_FL_BLOCK_SIZE;
    }
    rv = count;
error:
    __osBbFsRelAccess();
    return rv;
}