Changes in uspace/srv/fs/fat/fat_fat.c [5f116e7:d70d80ed] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
r5f116e7 rd70d80ed 46 46 #include <align.h> 47 47 #include <assert.h> 48 #include <fibril_sync .h>48 #include <fibril_synch.h> 49 49 #include <mem.h> 50 51 /* 52 * Convenience macros for computing some frequently used values from the 53 * primitive boot sector members. 54 */ 55 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 56 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 57 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 58 59 #define CLBN2PBN(bs, cl, bn) \ 60 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 50 61 51 62 /** … … 59 70 * 60 71 * @param bs Buffer holding the boot sector for the file. 61 * @param dev _handle Device handle of the device with the file.72 * @param devmap_handle Device handle of the device with the file. 62 73 * @param firstc First cluster to start the walk with. 63 * @param lastc If non-NULL, output argument hodling the last cluster number visited. 74 * @param lastc If non-NULL, output argument hodling the last cluster 75 * number visited. 76 * @param numc If non-NULL, output argument holding the number of 77 * clusters seen during the walk. 64 78 * @param max_clusters Maximum number of clusters to visit. 65 79 * 66 * @return Number of clusters seen during the walk.67 */ 68 uint16_t69 fat_cluster_walk(fat_bs_t *bs, dev _handle_t dev_handle, fat_cluster_t firstc,70 fat_cluster_t *lastc, uint16_t max_clusters)80 * @return EOK on success or a negative error code. 81 */ 82 int 83 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 84 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 71 85 { 72 86 block_t *b; 73 unsigned bps;74 unsigned rscnt; /* block address of the first FAT */75 87 uint16_t clusters = 0; 76 88 fat_cluster_t clst = firstc; 77 78 bps = uint16_t_le2host(bs->bps); 79 rscnt = uint16_t_le2host(bs->rscnt); 89 int rc; 80 90 81 91 if (firstc == FAT_CLST_RES0) { … … 83 93 if (lastc) 84 94 *lastc = firstc; 85 return 0; 95 if (numc) 96 *numc = 0; 97 return EOK; 86 98 } 87 99 88 100 while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { 89 bn_t fsec; /* sector offset relative to FAT1 */101 aoff64_t fsec; /* sector offset relative to FAT1 */ 90 102 unsigned fidx; /* FAT1 entry index */ 91 103 … … 93 105 if (lastc) 94 106 *lastc = clst; /* remember the last cluster number */ 95 fsec = (clst * sizeof(fat_cluster_t)) / bps;96 fidx = clst % ( bps/ sizeof(fat_cluster_t));107 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 108 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 97 109 /* read FAT1 */ 98 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 110 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec, 111 BLOCK_FLAGS_NONE); 112 if (rc != EOK) 113 return rc; 99 114 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 100 115 assert(clst != FAT_CLST_BAD); 101 block_put(b); 116 rc = block_put(b); 117 if (rc != EOK) 118 return rc; 102 119 clusters++; 103 120 } … … 105 122 if (lastc && clst < FAT_CLST_LAST1) 106 123 *lastc = clst; 107 108 return clusters; 124 if (numc) 125 *numc = clusters; 126 127 return EOK; 109 128 } 110 129 111 130 /** Read block from file located on a FAT file system. 112 131 * 132 * @param block Pointer to a block pointer for storing result. 113 133 * @param bs Buffer holding the boot sector of the file system. 114 * @param dev_handle Device handle of the file system. 115 * @param firstc First cluster used by the file. Can be zero if the file 116 * is empty. 134 * @param nodep FAT node. 117 135 * @param bn Block number. 118 136 * @param flags Flags passed to libblock. 119 137 * 120 * @return Block structure holding the requested block. 121 */ 122 block_t * 123 _fat_block_get(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc, 124 bn_t bn, int flags) 125 { 126 block_t *b; 127 unsigned bps; 128 unsigned rscnt; /* block address of the first FAT */ 129 unsigned rde; 130 unsigned rds; /* root directory size */ 131 unsigned sf; 132 unsigned ssa; /* size of the system area */ 133 unsigned clusters, max_clusters; 134 fat_cluster_t lastc; 135 136 bps = uint16_t_le2host(bs->bps); 137 rscnt = uint16_t_le2host(bs->rscnt); 138 rde = uint16_t_le2host(bs->root_ent_max); 139 sf = uint16_t_le2host(bs->sec_per_fat); 140 141 rds = (sizeof(fat_dentry_t) * rde) / bps; 142 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); 143 ssa = rscnt + bs->fatcnt * sf + rds; 144 145 if (firstc == FAT_CLST_ROOT) { 138 * @return EOK on success or a negative error code. 139 */ 140 int 141 fat_block_get(block_t **block, struct fat_bs *bs, fat_node_t *nodep, 142 aoff64_t bn, int flags) 143 { 144 fat_cluster_t firstc = nodep->firstc; 145 fat_cluster_t currc; 146 aoff64_t relbn = bn; 147 int rc; 148 149 if (!nodep->size) 150 return ELIMIT; 151 152 if (nodep->firstc == FAT_CLST_ROOT) 153 goto fall_through; 154 155 if (((((nodep->size - 1) / BPS(bs)) / SPC(bs)) == bn / SPC(bs)) && 156 nodep->lastc_cached_valid) { 157 /* 158 * This is a request to read a block within the last cluster 159 * when fortunately we have the last cluster number cached. 160 */ 161 return block_get(block, nodep->idx->devmap_handle, 162 CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags); 163 } 164 165 if (nodep->currc_cached_valid && bn >= nodep->currc_cached_bn) { 166 /* 167 * We can start with the cluster cached by the previous call to 168 * fat_block_get(). 169 */ 170 firstc = nodep->currc_cached_value; 171 relbn -= (nodep->currc_cached_bn / SPC(bs)) * SPC(bs); 172 } 173 174 fall_through: 175 rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc, 176 &currc, relbn, flags); 177 if (rc != EOK) 178 return rc; 179 180 /* 181 * Update the "current" cluster cache. 182 */ 183 nodep->currc_cached_valid = true; 184 nodep->currc_cached_bn = bn; 185 nodep->currc_cached_value = currc; 186 187 return rc; 188 } 189 190 /** Read block from file located on a FAT file system. 191 * 192 * @param block Pointer to a block pointer for storing result. 193 * @param bs Buffer holding the boot sector of the file system. 194 * @param devmap_handle Device handle of the file system. 195 * @param fcl First cluster used by the file. Can be zero if the file 196 * is empty. 197 * @param clp If not NULL, address where the cluster containing bn 198 * will be stored. 199 * stored 200 * @param bn Block number. 201 * @param flags Flags passed to libblock. 202 * 203 * @return EOK on success or a negative error code. 204 */ 205 int 206 _fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle, 207 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 208 { 209 uint16_t clusters; 210 unsigned max_clusters; 211 fat_cluster_t c; 212 int rc; 213 214 /* 215 * This function can only operate on non-zero length files. 216 */ 217 if (fcl == FAT_CLST_RES0) 218 return ELIMIT; 219 220 if (fcl == FAT_CLST_ROOT) { 146 221 /* root directory special case */ 147 assert(bn < rds); 148 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags); 149 return b; 150 } 151 152 max_clusters = bn / bs->spc; 153 clusters = fat_cluster_walk(bs, dev_handle, firstc, &lastc, 154 max_clusters); 222 assert(bn < RDS(bs)); 223 rc = block_get(block, devmap_handle, 224 RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags); 225 return rc; 226 } 227 228 max_clusters = bn / SPC(bs); 229 rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters); 230 if (rc != EOK) 231 return rc; 155 232 assert(clusters == max_clusters); 156 233 157 b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc + 158 bn % bs->spc, flags); 159 160 return b; 234 rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags); 235 236 if (clp) 237 *clp = c; 238 239 return rc; 161 240 } 162 241 … … 170 249 * this argument is ignored. 171 250 * @param pos Position in the last node block. 172 * /173 void fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, off_t pos) 174 { 175 uint16_t bps; 176 unsigned spc; 251 * 252 * @return EOK on success or a negative error code. 253 */ 254 int fat_fill_gap(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, aoff64_t pos) 255 { 177 256 block_t *b; 178 off_t o, boundary; 179 180 bps = uint16_t_le2host(bs->bps); 181 spc = bs->spc; 182 183 boundary = ROUND_UP(nodep->size, bps * spc); 257 aoff64_t o, boundary; 258 int rc; 259 260 boundary = ROUND_UP(nodep->size, BPS(bs) * SPC(bs)); 184 261 185 262 /* zero out already allocated space */ 186 263 for (o = nodep->size; o < pos && o < boundary; 187 o = ALIGN_DOWN(o + bps, bps)) {188 int flags = (o % bps== 0) ?264 o = ALIGN_DOWN(o + BPS(bs), BPS(bs))) { 265 int flags = (o % BPS(bs) == 0) ? 189 266 BLOCK_FLAGS_NOREAD : BLOCK_FLAGS_NONE; 190 b = fat_block_get(bs, nodep, o / bps, flags); 191 memset(b->data + o % bps, 0, bps - o % bps); 267 rc = fat_block_get(&b, bs, nodep, o / BPS(bs), flags); 268 if (rc != EOK) 269 return rc; 270 memset(b->data + o % BPS(bs), 0, BPS(bs) - o % BPS(bs)); 192 271 b->dirty = true; /* need to sync node */ 193 block_put(b); 272 rc = block_put(b); 273 if (rc != EOK) 274 return rc; 194 275 } 195 276 196 277 if (o >= pos) 197 return ;278 return EOK; 198 279 199 280 /* zero out the initial part of the new cluster chain */ 200 for (o = boundary; o < pos; o += bps) { 201 b = _fat_block_get(bs, nodep->idx->dev_handle, mcl, 202 (o - boundary) / bps, BLOCK_FLAGS_NOREAD); 203 memset(b->data, 0, min(bps, pos - o)); 281 for (o = boundary; o < pos; o += BPS(bs)) { 282 rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl, 283 NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD); 284 if (rc != EOK) 285 return rc; 286 memset(b->data, 0, min(BPS(bs), pos - o)); 204 287 b->dirty = true; /* need to sync node */ 205 block_put(b); 206 } 288 rc = block_put(b); 289 if (rc != EOK) 290 return rc; 291 } 292 293 return EOK; 207 294 } 208 295 … … 210 297 * 211 298 * @param bs Buffer holding the boot sector for the file system. 212 * @param dev _handle Device handle for the file system.299 * @param devmap_handle Device handle for the file system. 213 300 * @param clst Cluster which to get. 214 * 215 * @return Value found in the cluster. 216 */ 217 fat_cluster_t 218 fat_get_cluster(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t clst) 301 * @param value Output argument holding the value of the cluster. 302 * 303 * @return EOK or a negative error code. 304 */ 305 int 306 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 307 fat_cluster_t clst, fat_cluster_t *value) 219 308 { 220 309 block_t *b; 221 uint16_t bps; 222 uint16_t rscnt; 223 fat_cluster_t *cp, value; 224 225 bps = uint16_t_le2host(bs->bps); 226 rscnt = uint16_t_le2host(bs->rscnt); 227 228 b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps, 229 BLOCK_FLAGS_NONE); 230 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 231 value = uint16_t_le2host(*cp); 232 block_put(b); 310 fat_cluster_t *cp; 311 int rc; 312 313 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 314 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 315 if (rc != EOK) 316 return rc; 317 cp = (fat_cluster_t *)b->data + 318 clst % (BPS(bs) / sizeof(fat_cluster_t)); 319 *value = uint16_t_le2host(*cp); 320 rc = block_put(b); 233 321 234 return value;322 return rc; 235 323 } 236 324 … … 238 326 * 239 327 * @param bs Buffer holding the boot sector for the file system. 240 * @param dev _handle Device handle for the file system.328 * @param devmap_handle Device handle for the file system. 241 329 * @param fatno Number of the FAT instance where to make the change. 242 330 * @param clst Cluster which is to be set. 243 331 * @param value Value to set the cluster with. 244 */ 245 void 246 fat_set_cluster(fat_bs_t *bs, dev_handle_t dev_handle, unsigned fatno, 332 * 333 * @return EOK on success or a negative error code. 334 */ 335 int 336 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 247 337 fat_cluster_t clst, fat_cluster_t value) 248 338 { 249 339 block_t *b; 250 uint16_t bps;251 uint16_t rscnt;252 uint16_t sf;253 340 fat_cluster_t *cp; 254 255 bps = uint16_t_le2host(bs->bps); 256 rscnt = uint16_t_le2host(bs->rscnt);257 sf = uint16_t_le2host(bs->sec_per_fat);258 259 assert(fatno < bs->fatcnt);260 b = block_get(dev_handle, rscnt + sf * fatno +261 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE);262 cp = (fat_cluster_t *)b->data + clst % (bps/ sizeof(fat_cluster_t));341 int rc; 342 343 assert(fatno < FATCNT(bs)); 344 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 345 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 346 if (rc != EOK) 347 return rc; 348 cp = (fat_cluster_t *)b->data + 349 clst % (BPS(bs) / sizeof(fat_cluster_t)); 263 350 *cp = host2uint16_t_le(value); 264 351 b->dirty = true; /* need to sync block */ 265 block_put(b); 352 rc = block_put(b); 353 return rc; 266 354 } 267 355 … … 269 357 * 270 358 * @param bs Buffer holding the boot sector of the file system. 271 * @param dev _handle Device handle of the file system.359 * @param devmap_handle Device handle of the file system. 272 360 * @param lifo Chain of allocated clusters. 273 361 * @param nclsts Number of clusters in the lifo chain. 274 */ 275 void fat_alloc_shadow_clusters(fat_bs_t *bs, dev_handle_t dev_handle, 362 * 363 * @return EOK on success or a negative error code. 364 */ 365 int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, 276 366 fat_cluster_t *lifo, unsigned nclsts) 277 367 { 278 368 uint8_t fatno; 279 369 unsigned c; 370 int rc; 280 371 281 372 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 282 373 for (c = 0; c < nclsts; c++) { 283 fat_set_cluster(bs, dev_handle, fatno, lifo[c],374 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 284 375 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); 376 if (rc != EOK) 377 return rc; 285 378 } 286 379 } 380 381 return EOK; 287 382 } 288 383 … … 295 390 * 296 391 * @param bs Buffer holding the boot sector of the file system. 297 * @param dev _handle Device handle of the file system.392 * @param devmap_handle Device handle of the file system. 298 393 * @param nclsts Number of clusters to allocate. 299 394 * @param mcl Output parameter where the first cluster in the chain … … 305 400 */ 306 401 int 307 fat_alloc_clusters(fat_bs_t *bs, dev _handle_t dev_handle, unsigned nclsts,402 fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts, 308 403 fat_cluster_t *mcl, fat_cluster_t *lcl) 309 404 { 310 uint16_t bps;311 uint16_t rscnt;312 uint16_t sf;313 405 block_t *blk; 314 406 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 315 407 unsigned found = 0; /* top of the free cluster number stack */ 316 408 unsigned b, c, cl; 409 int rc; 317 410 318 411 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 319 412 if (!lifo) 320 413 return ENOMEM; 321 322 bps = uint16_t_le2host(bs->bps);323 rscnt = uint16_t_le2host(bs->rscnt);324 sf = uint16_t_le2host(bs->sec_per_fat);325 414 326 415 /* … … 328 417 */ 329 418 fibril_mutex_lock(&fat_alloc_lock); 330 for (b = 0, cl = 0; b < sf; b++) { 331 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE); 332 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { 419 for (b = 0, cl = 0; b < SF(bs); b++) { 420 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b, 421 BLOCK_FLAGS_NONE); 422 if (rc != EOK) 423 goto error; 424 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 425 /* 426 * Check if the entire cluster is physically there. 427 * This check becomes necessary when the file system is 428 * created with fewer total sectors than how many is 429 * inferred from the size of the file allocation table 430 * or when the last cluster ends beyond the end of the 431 * device. 432 */ 433 if ((cl >= FAT_CLST_FIRST) && 434 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 435 rc = block_put(blk); 436 if (rc != EOK) 437 goto error; 438 goto out; 439 } 440 333 441 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 334 442 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { … … 344 452 if (++found == nclsts) { 345 453 /* we are almost done */ 346 block_put(blk); 454 rc = block_put(blk); 455 if (rc != EOK) 456 goto error; 347 457 /* update the shadow copies of FAT */ 348 fat_alloc_shadow_clusters(bs, 349 dev_handle, lifo, nclsts); 458 rc = fat_alloc_shadow_clusters(bs, 459 devmap_handle, lifo, nclsts); 460 if (rc != EOK) 461 goto error; 350 462 *mcl = lifo[found - 1]; 351 463 *lcl = lifo[0]; … … 356 468 } 357 469 } 358 block_put(blk); 359 } 470 rc = block_put(blk); 471 if (rc != EOK) { 472 error: 473 fibril_mutex_unlock(&fat_alloc_lock); 474 free(lifo); 475 return rc; 476 } 477 } 478 out: 360 479 fibril_mutex_unlock(&fat_alloc_lock); 361 480 … … 365 484 */ 366 485 while (found--) { 367 fat_set_cluster(bs, dev_handle, FAT1, lifo[found],486 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 368 487 FAT_CLST_RES0); 488 if (rc != EOK) { 489 free(lifo); 490 return rc; 491 } 369 492 } 370 493 … … 376 499 * 377 500 * @param bs Buffer hodling the boot sector of the file system. 378 * @param dev _handle Device handle of the file system.501 * @param devmap_handle Device handle of the file system. 379 502 * @param firstc First cluster in the chain which is to be freed. 380 */ 381 void 382 fat_free_clusters(fat_bs_t *bs, dev_handle_t dev_handle, fat_cluster_t firstc) 503 * 504 * @return EOK on success or a negative return code. 505 */ 506 int 507 fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc) 383 508 { 384 509 unsigned fatno; 385 510 fat_cluster_t nextc; 511 int rc; 386 512 387 513 /* Mark all clusters in the chain as free in all copies of FAT. */ 388 514 while (firstc < FAT_CLST_LAST1) { 389 515 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); 390 nextc = fat_get_cluster(bs, dev_handle, firstc); 391 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 392 fat_set_cluster(bs, dev_handle, fatno, firstc, 516 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 517 if (rc != EOK) 518 return rc; 519 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 520 rc = fat_set_cluster(bs, devmap_handle, fatno, firstc, 393 521 FAT_CLST_RES0); 522 if (rc != EOK) 523 return rc; 524 } 525 394 526 firstc = nextc; 395 527 } 528 529 return EOK; 396 530 } 397 531 … … 401 535 * @param nodep Node representing the file. 402 536 * @param mcl First cluster of the cluster chain to append. 403 */ 404 void fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl) 405 { 406 dev_handle_t dev_handle = nodep->idx->dev_handle; 407 fat_cluster_t lcl; 537 * @param lcl Last cluster of the cluster chain to append. 538 * 539 * @return EOK on success or a negative error code. 540 */ 541 int 542 fat_append_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t mcl, 543 fat_cluster_t lcl) 544 { 545 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 546 fat_cluster_t lastc; 408 547 uint8_t fatno; 409 410 if (fat_cluster_walk(bs, dev_handle, nodep->firstc, &lcl, 411 (uint16_t) -1) ==0) {548 int rc; 549 550 if (nodep->firstc == FAT_CLST_RES0) { 412 551 /* No clusters allocated to the node yet. */ 413 552 nodep->firstc = mcl; 414 nodep->dirty = true; /* need to sync node */ 415 return; 416 } 417 418 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 419 fat_set_cluster(bs, nodep->idx->dev_handle, fatno, lcl, mcl); 553 nodep->dirty = true; /* need to sync node */ 554 } else { 555 if (nodep->lastc_cached_valid) { 556 lastc = nodep->lastc_cached_value; 557 nodep->lastc_cached_valid = false; 558 } else { 559 rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc, 560 &lastc, NULL, (uint16_t) -1); 561 if (rc != EOK) 562 return rc; 563 } 564 565 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 566 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno, 567 lastc, mcl); 568 if (rc != EOK) 569 return rc; 570 } 571 } 572 573 nodep->lastc_cached_valid = true; 574 nodep->lastc_cached_value = lcl; 575 576 return EOK; 420 577 } 421 578 … … 424 581 * @param bs Buffer holding the boot sector of the file system. 425 582 * @param nodep FAT node where the chopping will take place. 426 * @param l astcLast cluster which will remain in the node. If this583 * @param lcl Last cluster which will remain in the node. If this 427 584 * argument is FAT_CLST_RES0, then all clusters will 428 585 * be chopped off. 429 */ 430 void fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lastc) 431 { 432 dev_handle_t dev_handle = nodep->idx->dev_handle; 433 if (lastc == FAT_CLST_RES0) { 586 * 587 * @return EOK on success or a negative return code. 588 */ 589 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 590 { 591 int rc; 592 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; 593 594 /* 595 * Invalidate cached cluster numbers. 596 */ 597 nodep->lastc_cached_valid = false; 598 if (nodep->currc_cached_value != lcl) 599 nodep->currc_cached_valid = false; 600 601 if (lcl == FAT_CLST_RES0) { 434 602 /* The node will have zero size and no clusters allocated. */ 435 fat_free_clusters(bs, dev_handle, nodep->firstc); 603 rc = fat_free_clusters(bs, devmap_handle, nodep->firstc); 604 if (rc != EOK) 605 return rc; 436 606 nodep->firstc = FAT_CLST_RES0; 437 607 nodep->dirty = true; /* need to sync node */ … … 440 610 unsigned fatno; 441 611 442 nextc = fat_get_cluster(bs, dev_handle, lastc); 612 rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc); 613 if (rc != EOK) 614 return rc; 443 615 444 616 /* Terminate the cluster chain in all copies of FAT. */ 445 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) 446 fat_set_cluster(bs, dev_handle, fatno, lastc, FAT_CLST_LAST1); 617 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 618 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 619 FAT_CLST_LAST1); 620 if (rc != EOK) 621 return rc; 622 } 447 623 448 624 /* Free all following clusters. */ 449 fat_free_clusters(bs, dev_handle, nextc); 450 } 451 } 452 453 void 454 fat_zero_cluster(struct fat_bs *bs, dev_handle_t dev_handle, fat_cluster_t c) 625 rc = fat_free_clusters(bs, devmap_handle, nextc); 626 if (rc != EOK) 627 return rc; 628 } 629 630 /* 631 * Update and re-enable the last cluster cache. 632 */ 633 nodep->lastc_cached_valid = true; 634 nodep->lastc_cached_value = lcl; 635 636 return EOK; 637 } 638 639 int 640 fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c) 455 641 { 456 642 int i; 457 643 block_t *b; 458 unsigned bps; 459 460 bps = uint16_t_le2host(bs->bps); 461 462 for (i = 0; i < bs->spc; i++) { 463 b = _fat_block_get(bs, dev_handle, c, i, BLOCK_FLAGS_NOREAD); 464 memset(b->data, 0, bps); 644 int rc; 645 646 for (i = 0; i < SPC(bs); i++) { 647 rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i, 648 BLOCK_FLAGS_NOREAD); 649 if (rc != EOK) 650 return rc; 651 memset(b->data, 0, BPS(bs)); 465 652 b->dirty = true; 466 block_put(b); 467 } 653 rc = block_put(b); 654 if (rc != EOK) 655 return rc; 656 } 657 658 return EOK; 659 } 660 661 /** Perform basic sanity checks on the file system. 662 * 663 * Verify if values of boot sector fields are sane. Also verify media 664 * descriptor. This is used to rule out cases when a device obviously 665 * does not contain a fat file system. 666 */ 667 int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle) 668 { 669 fat_cluster_t e0, e1; 670 unsigned fat_no; 671 int rc; 672 673 /* Check number of FATs. */ 674 if (bs->fatcnt == 0) 675 return ENOTSUP; 676 677 /* Check total number of sectors. */ 678 679 if (bs->totsec16 == 0 && bs->totsec32 == 0) 680 return ENOTSUP; 681 682 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 683 bs->totsec16 != bs->totsec32) 684 return ENOTSUP; 685 686 /* Check media descriptor. Must be between 0xf0 and 0xff. */ 687 if ((bs->mdesc & 0xf0) != 0xf0) 688 return ENOTSUP; 689 690 /* Check number of sectors per FAT. */ 691 if (bs->sec_per_fat == 0) 692 return ENOTSUP; 693 694 /* 695 * Check that the root directory entries take up whole blocks. 696 * This check is rather strict, but it allows us to treat the root 697 * directory and non-root directories uniformly in some places. 698 * It can be removed provided that functions such as fat_read() are 699 * sanitized to support file systems with this property. 700 */ 701 if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) % 702 uint16_t_le2host(bs->bps) != 0) 703 return ENOTSUP; 704 705 /* Check signature of each FAT. */ 706 707 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 708 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); 709 if (rc != EOK) 710 return EIO; 711 712 rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1); 713 if (rc != EOK) 714 return EIO; 715 716 /* Check that first byte of FAT contains the media descriptor. */ 717 if ((e0 & 0xff) != bs->mdesc) 718 return ENOTSUP; 719 720 /* 721 * Check that remaining bits of the first two entries are 722 * set to one. 723 */ 724 if ((e0 >> 8) != 0xff || e1 != 0xffff) 725 return ENOTSUP; 726 } 727 728 return EOK; 468 729 } 469 730
Note:
See TracChangeset
for help on using the changeset viewer.