fswrite.c
3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <PR/bcp.h>
#include "os.h"
#include "os_bbcard.h"
#include "os_bbfs.h"
#include "bbint.h"
u16
__osBbFReallocBlock(BbInode* in, u16 block, BbFatEntry newVal) {
u16 b, ob, prev = 0;
s32 incr, rv;
BbFat16* fat = __osBbFat;
/* find new block */
if (in->size > 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;
}
while(b < __osBbFsBlocks && BB_FAT16_NEXT(fat,b) != BB_FAT_AVAIL)
b += incr;
if (b >= __osBbFsBlocks) goto error;
/* find old block */
ob = in->block;
while(ob != block) {
prev = ob;
ob = BB_FAT16_NEXT(fat,ob);
}
if (prev)
BB_FAT16_NEXT(fat,prev) = b;
else
in->block = b;
BB_FAT16_NEXT(fat,b) = BB_FAT16_NEXT(fat,ob);
BB_FAT16_NEXT(fat,ob) = newVal;
/* sync the metadata */
if ((rv = __osBbFsSync(0)) == 0)
return b;
/*XXXblythe now what to do?*/
error:
return BB_FAT_BAD;
}
s32
osBbFWrite(s32 fd, u32 off, const void* buf, u32 len) {
s32 rv;
BbInode* in;
u32 count, b, i;
BbFat16* fat;
#define MULTIPLANE
#ifdef MULTIPLANE
u16 blocks[4], n;
#endif
#ifdef _DEBUG
if ((u32)buf&15) return BBFS_ERR_INVALID;
#endif
if (fd < 0 || fd >= BB_INODE16_ENTRIES) return BBFS_ERR_INVALID;
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 (len & (BB_FL_BLOCK_SIZE-1)) goto error;
if (off+len < off) goto error; /* overflow */
if (off+len > in->size) goto error;
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;
#ifdef MULTIPLANE
/* do 4 blocks at a time */
while(len > 0) {
for(n = 0; len > 0 && n < 4; n++) {
if (b == 0 || b >= __osBbFsBlocks-BB_FAT16_BLOCKS) goto error;
blocks[n] = b;
b = BB_FAT16_NEXT(fat,b);
len = len > BB_FL_BLOCK_SIZE ? len - BB_FL_BLOCK_SIZE : 0;
count += BB_FL_BLOCK_SIZE;
}
if ((rv = osBbCardEraseBlocks(0, blocks, n)) < 0 ||
(rv = osBbCardWriteBlocks(0, blocks, n, buf, 0)) < 0) {
int i;
if (rv != BBFS_ERR_FAIL) goto error;
/* determine which blocks are bad, by repeating one at a time */
for(i = 0; i < n; i++) {
u16 b = blocks[i];
retry:
if ((rv = osBbCardEraseBlock(0, b)) < 0 ||
(rv = osBbCardWriteBlock(0, b, buf+i*BB_FL_BLOCK_SIZE, 0)) < 0) {
if (rv != BBFS_ERR_FAIL ||
(b = __osBbFReallocBlock(in, b, BB_FAT_BAD)) == BB_FAT_BAD) goto error;
goto retry;
}
}
}
buf += BB_FL_BLOCK_SIZE*n;
}
#else
while(len > 0) {
if (b == 0 || b >= __osBbFsBlocks-BB_FAT16_BLOCKS) goto error;
retry:
if ((rv = osBbCardEraseBlock(0, b)) < 0 ||
(rv = osBbCardWriteBlock(0, b, buf, 0)) < 0) {
if (rv != BBFS_ERR_FAIL ||
(b = __osBbFReallocBlock(in, b, BB_FAT_BAD)) == BB_FAT_BAD) goto error;
goto retry;
}
b = BB_FAT16_NEXT(fat,b);
buf += BB_FL_BLOCK_SIZE;
len = len > BB_FL_BLOCK_SIZE ? len - BB_FL_BLOCK_SIZE : 0;
count += BB_FL_BLOCK_SIZE;
}
#endif
rv = count;
error:
__osBbFsRelAccess();
return rv;
}