Rev 2863 | Rev 2876 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2863 | Rev 2864 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2008 Jakub Jermar |
2 | * Copyright (c) 2008 Jakub Jermar |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /** @addtogroup fs |
29 | /** @addtogroup fs |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | 32 | ||
33 | /** |
33 | /** |
34 | * @file fat_ops.c |
34 | * @file fat_ops.c |
35 | * @brief Implementation of VFS operations for the FAT file system server. |
35 | * @brief Implementation of VFS operations for the FAT file system server. |
36 | */ |
36 | */ |
37 | 37 | ||
38 | #include "fat.h" |
38 | #include "fat.h" |
39 | #include "../../vfs/vfs.h" |
39 | #include "../../vfs/vfs.h" |
40 | #include <libfs.h> |
40 | #include <libfs.h> |
41 | #include <ipc/ipc.h> |
41 | #include <ipc/ipc.h> |
42 | #include <async.h> |
42 | #include <async.h> |
43 | #include <errno.h> |
43 | #include <errno.h> |
44 | #include <string.h> |
44 | #include <string.h> |
45 | #include <byteorder.h> |
45 | #include <byteorder.h> |
46 | #include <libadt/hash_table.h> |
46 | #include <libadt/hash_table.h> |
47 | #include <libadt/list.h> |
47 | #include <libadt/list.h> |
48 | #include <assert.h> |
48 | #include <assert.h> |
49 | #include <futex.h> |
49 | #include <futex.h> |
50 | 50 | ||
51 | #define BS_BLOCK 0 |
51 | #define BS_BLOCK 0 |
52 | 52 | ||
53 | #define FIN_KEY_DEV_HANDLE 0 |
53 | #define FIN_KEY_DEV_HANDLE 0 |
54 | #define FIN_KEY_INDEX 1 |
54 | #define FIN_KEY_INDEX 1 |
55 | 55 | ||
56 | /** Futex protecting both fin_hash and ffn_head. */ |
- | |
57 | futex_t fin_futex = FUTEX_INITIALIZER; |
- | |
58 | - | ||
59 | /** Hash table of FAT in-core nodes. */ |
56 | /** Hash table of FAT in-core nodes. */ |
60 | hash_table_t fin_hash; |
57 | hash_table_t fin_hash; |
61 | 58 | ||
62 | /** List of free FAT in-core nodes. */ |
59 | /** List of free FAT in-core nodes. */ |
63 | link_t ffn_head; |
60 | link_t ffn_head; |
64 | 61 | ||
65 | #define FAT_NAME_LEN 8 |
62 | #define FAT_NAME_LEN 8 |
66 | #define FAT_EXT_LEN 3 |
63 | #define FAT_EXT_LEN 3 |
67 | 64 | ||
68 | #define FAT_PAD ' ' |
65 | #define FAT_PAD ' ' |
69 | 66 | ||
70 | #define FAT_DENTRY_UNUSED 0x00 |
67 | #define FAT_DENTRY_UNUSED 0x00 |
71 | #define FAT_DENTRY_E5_ESC 0x05 |
68 | #define FAT_DENTRY_E5_ESC 0x05 |
72 | #define FAT_DENTRY_DOT 0x2e |
69 | #define FAT_DENTRY_DOT 0x2e |
73 | #define FAT_DENTRY_ERASED 0xe5 |
70 | #define FAT_DENTRY_ERASED 0xe5 |
74 | 71 | ||
75 | static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
72 | static void dentry_name_canonify(fat_dentry_t *d, char *buf) |
76 | { |
73 | { |
77 | int i; |
74 | int i; |
78 | 75 | ||
79 | for (i = 0; i < FAT_NAME_LEN; i++) { |
76 | for (i = 0; i < FAT_NAME_LEN; i++) { |
80 | if (d->name[i] == FAT_PAD) { |
77 | if (d->name[i] == FAT_PAD) { |
81 | buf++; |
78 | buf++; |
82 | break; |
79 | break; |
83 | } |
80 | } |
84 | if (d->name[i] == FAT_DENTRY_E5_ESC) |
81 | if (d->name[i] == FAT_DENTRY_E5_ESC) |
85 | *buf++ = 0xe5; |
82 | *buf++ = 0xe5; |
86 | else |
83 | else |
87 | *buf++ = d->name[i]; |
84 | *buf++ = d->name[i]; |
88 | } |
85 | } |
89 | if (d->ext[0] != FAT_PAD) |
86 | if (d->ext[0] != FAT_PAD) |
90 | *buf++ = '.'; |
87 | *buf++ = '.'; |
91 | for (i = 0; i < FAT_EXT_LEN; i++) { |
88 | for (i = 0; i < FAT_EXT_LEN; i++) { |
92 | if (d->ext[i] == FAT_PAD) { |
89 | if (d->ext[i] == FAT_PAD) { |
93 | *buf = '\0'; |
90 | *buf = '\0'; |
94 | return; |
91 | return; |
95 | } |
92 | } |
96 | if (d->ext[i] == FAT_DENTRY_E5_ESC) |
93 | if (d->ext[i] == FAT_DENTRY_E5_ESC) |
97 | *buf++ = 0xe5; |
94 | *buf++ = 0xe5; |
98 | else |
95 | else |
99 | *buf++ = d->ext[i]; |
96 | *buf++ = d->ext[i]; |
100 | } |
97 | } |
101 | } |
98 | } |
102 | 99 | ||
103 | /* TODO and also move somewhere else */ |
100 | /* TODO and also move somewhere else */ |
104 | typedef struct { |
101 | typedef struct { |
105 | void *data; |
102 | void *data; |
106 | } block_t; |
103 | } block_t; |
107 | 104 | ||
108 | static block_t *block_get(dev_handle_t dev_handle, off_t offset) |
105 | static block_t *block_get(dev_handle_t dev_handle, off_t offset) |
109 | { |
106 | { |
110 | return NULL; /* TODO */ |
107 | return NULL; /* TODO */ |
111 | } |
108 | } |
112 | 109 | ||
113 | static void block_put(block_t *block) |
110 | static void block_put(block_t *block) |
114 | { |
111 | { |
115 | /* TODO */ |
112 | /* TODO */ |
116 | } |
113 | } |
117 | 114 | ||
- | 115 | static fat_idx_t *fat_idx_map(fat_cluster_t pfc, unsigned pdi) |
|
- | 116 | { |
|
- | 117 | return NULL; /* TODO */ |
|
- | 118 | } |
|
118 | 119 | ||
119 | #define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
120 | #define FAT_BS(b) ((fat_bs_t *)((b)->data)) |
120 | 121 | ||
- | 122 | #define FAT_CLST_RES0 0x0000 |
|
- | 123 | #define FAT_CLST_RES1 0x0001 /* internally used to mark root directory */ |
|
121 | #define FAT_CLST_FIRST 0x0002 |
124 | #define FAT_CLST_FIRST 0x0002 |
122 | #define FAT_CLST_BAD 0xfff7 |
125 | #define FAT_CLST_BAD 0xfff7 |
123 | #define FAT_CLST_LAST1 0xfff8 |
126 | #define FAT_CLST_LAST1 0xfff8 |
124 | #define FAT_CLST_LAST8 0xffff |
127 | #define FAT_CLST_LAST8 0xffff |
125 | 128 | ||
126 | /** Convert cluster number to an index within a FAT. |
- | |
127 | * |
- | |
128 | * Format Identifier and cluster numbering is considered. |
- | |
129 | */ |
- | |
130 | #define C2FAT_IDX(c) (1 + (c) - FAT_CLST_FIRST) |
- | |
131 | - | ||
132 | static block_t *fat_block_get(dev_handle_t dev_handle, fs_index_t index, |
129 | static block_t *fat_block_get(fat_node_t *nodep, off_t offset) |
133 | off_t offset) |
- | |
134 | { |
130 | { |
135 | block_t *bb; |
131 | block_t *bb; |
136 | block_t *b; |
132 | block_t *b; |
137 | unsigned bps; |
133 | unsigned bps; |
138 | unsigned spc; |
134 | unsigned spc; |
139 | unsigned rscnt; /* block address of the first FAT */ |
135 | unsigned rscnt; /* block address of the first FAT */ |
140 | unsigned fatcnt; |
136 | unsigned fatcnt; |
141 | unsigned rde; |
137 | unsigned rde; |
142 | unsigned rds; /* root directory size */ |
138 | unsigned rds; /* root directory size */ |
143 | unsigned sf; |
139 | unsigned sf; |
144 | unsigned ssa; /* size of the system area */ |
140 | unsigned ssa; /* size of the system area */ |
145 | unsigned clusters; |
141 | unsigned clusters; |
146 | unsigned clst = index; |
142 | fat_cluster_t clst = nodep->firstc; |
147 | unsigned i; |
143 | unsigned i; |
148 | 144 | ||
149 | bb = block_get(dev_handle, BS_BLOCK); |
145 | bb = block_get(nodep->idx->dev_handle, BS_BLOCK); |
150 | bps = uint16_t_le2host(FAT_BS(bb)->bps); |
146 | bps = uint16_t_le2host(FAT_BS(bb)->bps); |
151 | spc = FAT_BS(bb)->spc; |
147 | spc = FAT_BS(bb)->spc; |
152 | rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
148 | rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); |
153 | fatcnt = FAT_BS(bb)->fatcnt; |
149 | fatcnt = FAT_BS(bb)->fatcnt; |
154 | rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
150 | rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); |
155 | sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); |
151 | sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); |
156 | block_put(bb); |
152 | block_put(bb); |
157 | 153 | ||
158 | rds = (sizeof(fat_dentry_t) * rde) / bps; |
154 | rds = (sizeof(fat_dentry_t) * rde) / bps; |
159 | rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
155 | rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); |
160 | ssa = rscnt + fatcnt * sf + rds; |
156 | ssa = rscnt + fatcnt * sf + rds; |
161 | 157 | ||
162 | if (!index) { |
158 | if (nodep->idx->index == FAT_CLST_RES1) { |
163 | /* root directory special case */ |
159 | /* root directory special case */ |
164 | assert(offset < rds); |
160 | assert(offset < rds); |
- | 161 | b = block_get(nodep->idx->dev_handle, |
|
165 | b = block_get(dev_handle, rscnt + fatcnt * sf + offset); |
162 | rscnt + fatcnt * sf + offset); |
166 | return b; |
163 | return b; |
167 | } |
164 | } |
168 | 165 | ||
169 | clusters = offset / spc; |
166 | clusters = offset / spc; |
170 | for (i = 0; i < clusters; i++) { |
167 | for (i = 0; i < clusters; i++) { |
171 | unsigned fsec; /* sector offset relative to FAT1 */ |
168 | unsigned fsec; /* sector offset relative to FAT1 */ |
172 | unsigned fidx; /* FAT1 entry index */ |
169 | unsigned fidx; /* FAT1 entry index */ |
173 | 170 | ||
174 | assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); |
171 | assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); |
175 | fsec = (C2FAT_IDX(clst) * sizeof(uint16_t)) / bps; |
172 | fsec = (clst * sizeof(fat_cluster_t)) / bps; |
176 | fidx = C2FAT_IDX(clst) % (bps / sizeof(uint16_t)); |
173 | fidx = clst % (bps / sizeof(fat_cluster_t)); |
177 | /* read FAT1 */ |
174 | /* read FAT1 */ |
178 | b = block_get(dev_handle, rscnt + fsec); |
175 | b = block_get(nodep->idx->dev_handle, rscnt + fsec); |
179 | clst = uint16_t_le2host(((uint16_t *)b->data)[fidx]); |
176 | clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); |
180 | assert(clst != FAT_CLST_BAD); |
177 | assert(clst != FAT_CLST_BAD); |
181 | assert(clst < FAT_CLST_LAST1); |
178 | assert(clst < FAT_CLST_LAST1); |
182 | block_put(b); |
179 | block_put(b); |
183 | } |
180 | } |
184 | 181 | ||
185 | b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + |
182 | b = block_get(nodep->idx->dev_handle, ssa + |
186 | offset % spc); |
183 | (clst - FAT_CLST_FIRST) * spc + offset % spc); |
187 | 184 | ||
188 | return b; |
185 | return b; |
189 | } |
186 | } |
190 | 187 | ||
191 | static void fat_node_initialize(fat_node_t *node) |
188 | static void fat_node_initialize(fat_node_t *node) |
192 | { |
189 | { |
193 | futex_initialize(&node->lock, 1); |
190 | node->idx = NULL; |
194 | node->type = 0; |
191 | node->type = 0; |
195 | node->index = 0; |
- | |
196 | node->pindex = 0; |
- | |
197 | node->dev_handle = 0; |
- | |
198 | link_initialize(&node->fin_link); |
192 | link_initialize(&node->fin_link); |
199 | link_initialize(&node->ffn_link); |
193 | link_initialize(&node->ffn_link); |
200 | node->size = 0; |
194 | node->size = 0; |
201 | node->lnkcnt = 0; |
195 | node->lnkcnt = 0; |
202 | node->refcnt = 0; |
196 | node->refcnt = 0; |
203 | node->dirty = false; |
197 | node->dirty = false; |
204 | } |
198 | } |
205 | 199 | ||
206 | static uint16_t fat_bps_get(dev_handle_t dev_handle) |
200 | static uint16_t fat_bps_get(dev_handle_t dev_handle) |
207 | { |
201 | { |
208 | block_t *bb; |
202 | block_t *bb; |
209 | uint16_t bps; |
203 | uint16_t bps; |
210 | 204 | ||
211 | bb = block_get(dev_handle, BS_BLOCK); |
205 | bb = block_get(dev_handle, BS_BLOCK); |
212 | assert(bb != NULL); |
206 | assert(bb != NULL); |
213 | bps = uint16_t_le2host(FAT_BS(bb)->bps); |
207 | bps = uint16_t_le2host(FAT_BS(bb)->bps); |
214 | block_put(bb); |
208 | block_put(bb); |
215 | 209 | ||
216 | return bps; |
210 | return bps; |
217 | } |
211 | } |
218 | 212 | ||
219 | typedef enum { |
213 | typedef enum { |
220 | FAT_DENTRY_SKIP, |
214 | FAT_DENTRY_SKIP, |
221 | FAT_DENTRY_LAST, |
215 | FAT_DENTRY_LAST, |
222 | FAT_DENTRY_VALID |
216 | FAT_DENTRY_VALID |
223 | } fat_dentry_clsf_t; |
217 | } fat_dentry_clsf_t; |
224 | 218 | ||
225 | static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d) |
219 | static fat_dentry_clsf_t fat_classify_dentry(fat_dentry_t *d) |
226 | { |
220 | { |
227 | if (d->attr & FAT_ATTR_VOLLABEL) { |
221 | if (d->attr & FAT_ATTR_VOLLABEL) { |
228 | /* volume label entry */ |
222 | /* volume label entry */ |
229 | return FAT_DENTRY_SKIP; |
223 | return FAT_DENTRY_SKIP; |
230 | } |
224 | } |
231 | if (d->name[0] == FAT_DENTRY_ERASED) { |
225 | if (d->name[0] == FAT_DENTRY_ERASED) { |
232 | /* not-currently-used entry */ |
226 | /* not-currently-used entry */ |
233 | return FAT_DENTRY_SKIP; |
227 | return FAT_DENTRY_SKIP; |
234 | } |
228 | } |
235 | if (d->name[0] == FAT_DENTRY_UNUSED) { |
229 | if (d->name[0] == FAT_DENTRY_UNUSED) { |
236 | /* never used entry */ |
230 | /* never used entry */ |
237 | return FAT_DENTRY_LAST; |
231 | return FAT_DENTRY_LAST; |
238 | } |
232 | } |
239 | if (d->name[0] == FAT_DENTRY_DOT) { |
233 | if (d->name[0] == FAT_DENTRY_DOT) { |
240 | /* |
234 | /* |
241 | * Most likely '.' or '..'. |
235 | * Most likely '.' or '..'. |
242 | * It cannot occur in a regular file name. |
236 | * It cannot occur in a regular file name. |
243 | */ |
237 | */ |
244 | return FAT_DENTRY_SKIP; |
238 | return FAT_DENTRY_SKIP; |
245 | } |
239 | } |
246 | return FAT_DENTRY_VALID; |
240 | return FAT_DENTRY_VALID; |
247 | } |
241 | } |
248 | 242 | ||
249 | static void fat_sync_node(fat_node_t *node) |
243 | static void fat_sync_node(fat_node_t *node) |
250 | { |
244 | { |
251 | /* TODO */ |
245 | /* TODO */ |
252 | } |
246 | } |
253 | 247 | ||
254 | /** Instantiate a FAT in-core node. */ |
248 | /** Instantiate a FAT in-core node. */ |
255 | static void * |
249 | static void * |
256 | fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
250 | fat_node_get(dev_handle_t dev_handle, fs_index_t index) |
257 | { |
251 | { |
258 | return NULL; /* TODO */ |
252 | return NULL; /* TODO */ |
259 | } |
253 | } |
260 | 254 | ||
261 | static void fat_node_put(void *node) |
255 | static void fat_node_put(void *node) |
262 | { |
256 | { |
263 | /* TODO */ |
257 | /* TODO */ |
264 | } |
258 | } |
265 | 259 | ||
266 | static void *fat_create(int flags) |
260 | static void *fat_create(int flags) |
267 | { |
261 | { |
268 | return NULL; /* not supported at the moment */ |
262 | return NULL; /* not supported at the moment */ |
269 | } |
263 | } |
270 | 264 | ||
271 | static int fat_destroy(void *node) |
265 | static int fat_destroy(void *node) |
272 | { |
266 | { |
273 | return ENOTSUP; /* not supported at the moment */ |
267 | return ENOTSUP; /* not supported at the moment */ |
274 | } |
268 | } |
275 | 269 | ||
276 | static bool fat_link(void *prnt, void *chld, const char *name) |
270 | static bool fat_link(void *prnt, void *chld, const char *name) |
277 | { |
271 | { |
278 | return false; /* not supported at the moment */ |
272 | return false; /* not supported at the moment */ |
279 | } |
273 | } |
280 | 274 | ||
281 | static int fat_unlink(void *prnt, void *chld) |
275 | static int fat_unlink(void *prnt, void *chld) |
282 | { |
276 | { |
283 | return ENOTSUP; /* not supported at the moment */ |
277 | return ENOTSUP; /* not supported at the moment */ |
284 | } |
278 | } |
285 | 279 | ||
286 | static void *fat_match(void *prnt, const char *component) |
280 | static void *fat_match(void *prnt, const char *component) |
287 | { |
281 | { |
288 | fat_node_t *parentp = (fat_node_t *)prnt; |
282 | fat_node_t *parentp = (fat_node_t *)prnt; |
289 | char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
283 | char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
290 | unsigned i, j; |
284 | unsigned i, j; |
291 | unsigned bps; /* bytes per sector */ |
285 | unsigned bps; /* bytes per sector */ |
292 | unsigned dps; /* dentries per sector */ |
286 | unsigned dps; /* dentries per sector */ |
293 | unsigned blocks; |
287 | unsigned blocks; |
294 | fat_dentry_t *d; |
288 | fat_dentry_t *d; |
295 | block_t *b; |
289 | block_t *b; |
296 | 290 | ||
297 | bps = fat_bps_get(parentp->dev_handle); |
291 | bps = fat_bps_get(parentp->idx->dev_handle); |
298 | dps = bps / sizeof(fat_dentry_t); |
292 | dps = bps / sizeof(fat_dentry_t); |
299 | blocks = parentp->size / bps + (parentp->size % bps != 0); |
293 | blocks = parentp->size / bps + (parentp->size % bps != 0); |
300 | for (i = 0; i < blocks; i++) { |
294 | for (i = 0; i < blocks; i++) { |
301 | unsigned dentries; |
295 | unsigned dentries; |
302 | 296 | ||
303 | b = fat_block_get(parentp->dev_handle, parentp->index, i); |
297 | b = fat_block_get(parentp, i); |
304 | dentries = (i == blocks - 1) ? |
298 | dentries = (i == blocks - 1) ? |
305 | parentp->size % sizeof(fat_dentry_t) : |
299 | parentp->size % sizeof(fat_dentry_t) : |
306 | dps; |
300 | dps; |
307 | for (j = 0; j < dentries; j++) { |
301 | for (j = 0; j < dentries; j++) { |
308 | d = ((fat_dentry_t *)b->data) + j; |
302 | d = ((fat_dentry_t *)b->data) + j; |
309 | switch (fat_classify_dentry(d)) { |
303 | switch (fat_classify_dentry(d)) { |
310 | case FAT_DENTRY_SKIP: |
304 | case FAT_DENTRY_SKIP: |
311 | continue; |
305 | continue; |
312 | case FAT_DENTRY_LAST: |
306 | case FAT_DENTRY_LAST: |
313 | block_put(b); |
307 | block_put(b); |
314 | return NULL; |
308 | return NULL; |
315 | default: |
309 | default: |
316 | case FAT_DENTRY_VALID: |
310 | case FAT_DENTRY_VALID: |
317 | dentry_name_canonify(d, name); |
311 | dentry_name_canonify(d, name); |
318 | break; |
312 | break; |
319 | } |
313 | } |
320 | if (strcmp(name, component) == 0) { |
314 | if (strcmp(name, component) == 0) { |
321 | /* hit */ |
315 | /* hit */ |
- | 316 | fat_idx_t *idx = fat_idx_map(parentp->firstc, |
|
- | 317 | i * dps + j); |
|
322 | void *node = fat_node_get(parentp->dev_handle, |
318 | void *node = fat_node_get(idx->dev_handle, |
323 | (fs_index_t)uint16_t_le2host(d->firstc)); |
319 | idx->index); |
324 | block_put(b); |
320 | block_put(b); |
325 | return node; |
321 | return node; |
326 | } |
322 | } |
327 | } |
323 | } |
328 | block_put(b); |
324 | block_put(b); |
329 | } |
325 | } |
330 | 326 | ||
331 | return NULL; |
327 | return NULL; |
332 | } |
328 | } |
333 | 329 | ||
334 | static fs_index_t fat_index_get(void *node) |
330 | static fs_index_t fat_index_get(void *node) |
335 | { |
331 | { |
336 | fat_node_t *fnodep = (fat_node_t *)node; |
332 | fat_node_t *fnodep = (fat_node_t *)node; |
337 | if (!fnodep) |
333 | if (!fnodep) |
338 | return 0; |
334 | return 0; |
339 | return fnodep->index; |
335 | return fnodep->idx->index; |
340 | } |
336 | } |
341 | 337 | ||
342 | static size_t fat_size_get(void *node) |
338 | static size_t fat_size_get(void *node) |
343 | { |
339 | { |
344 | return ((fat_node_t *)node)->size; |
340 | return ((fat_node_t *)node)->size; |
345 | } |
341 | } |
346 | 342 | ||
347 | static unsigned fat_lnkcnt_get(void *node) |
343 | static unsigned fat_lnkcnt_get(void *node) |
348 | { |
344 | { |
349 | return ((fat_node_t *)node)->lnkcnt; |
345 | return ((fat_node_t *)node)->lnkcnt; |
350 | } |
346 | } |
351 | 347 | ||
352 | static bool fat_has_children(void *node) |
348 | static bool fat_has_children(void *node) |
353 | { |
349 | { |
354 | fat_node_t *nodep = (fat_node_t *)node; |
350 | fat_node_t *nodep = (fat_node_t *)node; |
355 | unsigned bps; |
351 | unsigned bps; |
356 | unsigned dps; |
352 | unsigned dps; |
357 | unsigned blocks; |
353 | unsigned blocks; |
358 | block_t *b; |
354 | block_t *b; |
359 | unsigned i, j; |
355 | unsigned i, j; |
360 | 356 | ||
361 | if (nodep->type != FAT_DIRECTORY) |
357 | if (nodep->type != FAT_DIRECTORY) |
362 | return false; |
358 | return false; |
363 | 359 | ||
364 | bps = fat_bps_get(nodep->dev_handle); |
360 | bps = fat_bps_get(nodep->idx->dev_handle); |
365 | dps = bps / sizeof(fat_dentry_t); |
361 | dps = bps / sizeof(fat_dentry_t); |
366 | 362 | ||
367 | blocks = nodep->size / bps + (nodep->size % bps != 0); |
363 | blocks = nodep->size / bps + (nodep->size % bps != 0); |
368 | 364 | ||
369 | for (i = 0; i < blocks; i++) { |
365 | for (i = 0; i < blocks; i++) { |
370 | unsigned dentries; |
366 | unsigned dentries; |
371 | fat_dentry_t *d; |
367 | fat_dentry_t *d; |
372 | 368 | ||
373 | b = fat_block_get(nodep->dev_handle, nodep->index, i); |
369 | b = fat_block_get(nodep, i); |
374 | dentries = (i == blocks - 1) ? |
370 | dentries = (i == blocks - 1) ? |
375 | nodep->size % sizeof(fat_dentry_t) : |
371 | nodep->size % sizeof(fat_dentry_t) : |
376 | dps; |
372 | dps; |
377 | for (j = 0; j < dentries; j++) { |
373 | for (j = 0; j < dentries; j++) { |
378 | d = ((fat_dentry_t *)b->data) + j; |
374 | d = ((fat_dentry_t *)b->data) + j; |
379 | switch (fat_classify_dentry(d)) { |
375 | switch (fat_classify_dentry(d)) { |
380 | case FAT_DENTRY_SKIP: |
376 | case FAT_DENTRY_SKIP: |
381 | continue; |
377 | continue; |
382 | case FAT_DENTRY_LAST: |
378 | case FAT_DENTRY_LAST: |
383 | block_put(b); |
379 | block_put(b); |
384 | return false; |
380 | return false; |
385 | default: |
381 | default: |
386 | case FAT_DENTRY_VALID: |
382 | case FAT_DENTRY_VALID: |
387 | block_put(b); |
383 | block_put(b); |
388 | return true; |
384 | return true; |
389 | } |
385 | } |
390 | block_put(b); |
386 | block_put(b); |
391 | return true; |
387 | return true; |
392 | } |
388 | } |
393 | block_put(b); |
389 | block_put(b); |
394 | } |
390 | } |
395 | 391 | ||
396 | return false; |
392 | return false; |
397 | } |
393 | } |
398 | 394 | ||
399 | static void *fat_root_get(dev_handle_t dev_handle) |
395 | static void *fat_root_get(dev_handle_t dev_handle) |
400 | { |
396 | { |
401 | return fat_node_get(dev_handle, 0); |
397 | return fat_node_get(dev_handle, FAT_CLST_RES1); |
402 | } |
398 | } |
403 | 399 | ||
404 | static char fat_plb_get_char(unsigned pos) |
400 | static char fat_plb_get_char(unsigned pos) |
405 | { |
401 | { |
406 | return fat_reg.plb_ro[pos % PLB_SIZE]; |
402 | return fat_reg.plb_ro[pos % PLB_SIZE]; |
407 | } |
403 | } |
408 | 404 | ||
409 | static bool fat_is_directory(void *node) |
405 | static bool fat_is_directory(void *node) |
410 | { |
406 | { |
411 | return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
407 | return ((fat_node_t *)node)->type == FAT_DIRECTORY; |
412 | } |
408 | } |
413 | 409 | ||
414 | static bool fat_is_file(void *node) |
410 | static bool fat_is_file(void *node) |
415 | { |
411 | { |
416 | return ((fat_node_t *)node)->type == FAT_FILE; |
412 | return ((fat_node_t *)node)->type == FAT_FILE; |
417 | } |
413 | } |
418 | 414 | ||
419 | /** libfs operations */ |
415 | /** libfs operations */ |
420 | libfs_ops_t fat_libfs_ops = { |
416 | libfs_ops_t fat_libfs_ops = { |
421 | .match = fat_match, |
417 | .match = fat_match, |
422 | .node_get = fat_node_get, |
418 | .node_get = fat_node_get, |
423 | .node_put = fat_node_put, |
419 | .node_put = fat_node_put, |
424 | .create = fat_create, |
420 | .create = fat_create, |
425 | .destroy = fat_destroy, |
421 | .destroy = fat_destroy, |
426 | .link = fat_link, |
422 | .link = fat_link, |
427 | .unlink = fat_unlink, |
423 | .unlink = fat_unlink, |
428 | .index_get = fat_index_get, |
424 | .index_get = fat_index_get, |
429 | .size_get = fat_size_get, |
425 | .size_get = fat_size_get, |
430 | .lnkcnt_get = fat_lnkcnt_get, |
426 | .lnkcnt_get = fat_lnkcnt_get, |
431 | .has_children = fat_has_children, |
427 | .has_children = fat_has_children, |
432 | .root_get = fat_root_get, |
428 | .root_get = fat_root_get, |
433 | .plb_get_char = fat_plb_get_char, |
429 | .plb_get_char = fat_plb_get_char, |
434 | .is_directory = fat_is_directory, |
430 | .is_directory = fat_is_directory, |
435 | .is_file = fat_is_file |
431 | .is_file = fat_is_file |
436 | }; |
432 | }; |
437 | 433 | ||
438 | void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
434 | void fat_lookup(ipc_callid_t rid, ipc_call_t *request) |
439 | { |
435 | { |
440 | libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
436 | libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request); |
441 | } |
437 | } |
442 | 438 | ||
443 | /** |
439 | /** |
444 | * @} |
440 | * @} |
445 | */ |
441 | */ |
446 | 442 |