-
Notifications
You must be signed in to change notification settings - Fork 198
/
fs.c
187 lines (165 loc) · 3.64 KB
/
fs.c
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* fs.c
*
* Error-handling wrappers around FatFS.
*
* Written & released by Keir Fraser <[email protected]>
*
* This is free and unencumbered software released into the public domain.
* See the file COPYING for more details, or visit <http://unlicense.org>.
*/
static struct cancellation fs_cancellation[2];
static struct cancellation *next_cancellation = &fs_cancellation[0];
static FRESULT fs_fresult;
FRESULT F_call_cancellable(int (*fn)(void *), void *arg)
{
FRESULT res;
struct cancellation *c = next_cancellation++;
ASSERT((c - fs_cancellation) < ARRAY_SIZE(fs_cancellation));
ASSERT(!cancellation_is_active(c));
(void)call_cancellable_fn(c, fn, arg);
next_cancellation--;
res = fs_fresult;
fs_fresult = FR_OK;
return res;
}
static void handle_fr(FRESULT fr)
{
struct cancellation *c = next_cancellation - 1;
ASSERT(!fs_fresult && (c >= fs_cancellation));
if (fr == FR_OK)
return;
fs_fresult = fr;
cancel_call(c);
}
void F_die(FRESULT fr)
{
handle_fr(fr);
}
static BYTE mask_mode(BYTE mode)
{
if (volume_readonly())
mode &= FA_READ;
return mode;
}
FRESULT F_try_open(FIL *fp, const TCHAR *path, BYTE mode)
{
FRESULT fr = f_open(fp, path, mask_mode(mode));
switch (fr) {
case FR_NO_FILE:
case FR_NO_PATH:
break;
default:
handle_fr(fr);
break;
}
return fr;
}
void F_open(FIL *fp, const TCHAR *path, BYTE mode)
{
FRESULT fr = f_open(fp, path, mask_mode(mode));
handle_fr(fr);
}
void F_close(FIL *fp)
{
FRESULT fr = f_close(fp);
handle_fr(fr);
}
void F_read(FIL *fp, void *buff, UINT btr, UINT *br)
{
UINT _br;
FRESULT fr = f_read(fp, buff, btr, &_br);
if (br != NULL) {
*br = _br;
} else if (_br < btr) {
memset((char *)buff + _br, 0, btr - _br);
}
handle_fr(fr);
}
#if !FF_FS_READONLY
void F_write(FIL *fp, const void *buff, UINT btw, UINT *bw)
{
UINT _bw;
FRESULT fr;
if (volume_readonly()) {
/* Read-only: silently drop. */
if (bw) *bw = btw;
return;
}
if (!fp->dir_ptr) {
/* File cannot be resized. Clip the write size. */
btw = min_t(UINT, btw, f_size(fp) - f_tell(fp));
}
fr = f_write(fp, buff, btw, &_bw);
if (bw != NULL) {
*bw = _bw;
} else if ((fr == FR_OK) && (_bw < btw)) {
fr = FR_DISK_FULL;
}
handle_fr(fr);
}
void F_sync(FIL *fp)
{
FRESULT fr = f_sync(fp);
handle_fr(fr);
}
void F_truncate(FIL *fp)
{
FRESULT fr = volume_readonly() ? FR_OK : f_truncate(fp);
handle_fr(fr);
}
#endif /* !FF_FS_READONLY */
void F_lseek(FIL *fp, FSIZE_t ofs)
{
FRESULT fr;
#if !FF_FS_READONLY
if (!fp->dir_ptr) {
/* File cannot be resized. Clip the seek offset. */
ofs = min(ofs, f_size(fp));
}
#endif
fr = f_lseek(fp, ofs);
handle_fr(fr);
}
void F_opendir(DIR *dp, const TCHAR *path)
{
FRESULT fr = f_opendir(dp, path);
handle_fr(fr);
}
void F_closedir(DIR *dp)
{
FRESULT fr = f_closedir(dp);
handle_fr(fr);
}
void F_readdir(DIR *dp, FILINFO *fno)
{
FRESULT fr = f_readdir(dp, fno);
handle_fr(fr);
}
void F_findfirst(DIR *dp, FILINFO *fno, const TCHAR *path,
const TCHAR *pattern)
{
FRESULT fr = f_findfirst(dp, fno, path, pattern);
handle_fr(fr);
}
void F_findnext(DIR *dp, FILINFO *fno)
{
FRESULT fr = f_findnext(dp, fno);
handle_fr(fr);
}
#if !defined(BOOTLOADER)
void F_chdir(const TCHAR *path)
{
FRESULT fr = f_chdir(path);
handle_fr(fr);
}
#endif
/*
* Local variables:
* mode: C
* c-file-style: "Linux"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/