Changeset 0f57d0e in mainline for uspace/srv/fs/fat/fat_fat.c
- Timestamp:
- 2008-10-26T14:10:53Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b1178d0
- Parents:
- 033ef7d3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_fat.c
r033ef7d3 r0f57d0e 36 36 */ 37 37 38 #include "fat_fat.h" 39 #include "fat_dentry.h" 40 #include "fat.h" 41 #include "../../vfs/vfs.h" 42 #include <libfs.h> 43 #include <errno.h> 44 #include <byteorder.h> 45 #include <align.h> 46 #include <assert.h> 47 48 block_t * 49 _fat_block_get(dev_handle_t dev_handle, fat_cluster_t firstc, off_t offset) 50 { 51 block_t *bb; 52 block_t *b; 53 unsigned bps; 54 unsigned spc; 55 unsigned rscnt; /* block address of the first FAT */ 56 unsigned fatcnt; 57 unsigned rde; 58 unsigned rds; /* root directory size */ 59 unsigned sf; 60 unsigned ssa; /* size of the system area */ 61 unsigned clusters; 62 fat_cluster_t clst = firstc; 63 unsigned i; 64 65 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 66 bps = uint16_t_le2host(FAT_BS(bb)->bps); 67 spc = FAT_BS(bb)->spc; 68 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 69 fatcnt = FAT_BS(bb)->fatcnt; 70 rde = uint16_t_le2host(FAT_BS(bb)->root_ent_max); 71 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); 72 block_put(bb); 73 74 rds = (sizeof(fat_dentry_t) * rde) / bps; 75 rds += ((sizeof(fat_dentry_t) * rde) % bps != 0); 76 ssa = rscnt + fatcnt * sf + rds; 77 78 if (firstc == FAT_CLST_ROOT) { 79 /* root directory special case */ 80 assert(offset < rds); 81 b = block_get(dev_handle, rscnt + fatcnt * sf + offset, bps); 82 return b; 83 } 84 85 clusters = offset / spc; 86 for (i = 0; i < clusters; i++) { 87 unsigned fsec; /* sector offset relative to FAT1 */ 88 unsigned fidx; /* FAT1 entry index */ 89 90 assert(clst >= FAT_CLST_FIRST && clst < FAT_CLST_BAD); 91 fsec = (clst * sizeof(fat_cluster_t)) / bps; 92 fidx = clst % (bps / sizeof(fat_cluster_t)); 93 /* read FAT1 */ 94 b = block_get(dev_handle, rscnt + fsec, bps); 95 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 96 assert(clst != FAT_CLST_BAD); 97 assert(clst < FAT_CLST_LAST1); 98 block_put(b); 99 } 100 101 b = block_get(dev_handle, ssa + (clst - FAT_CLST_FIRST) * spc + 102 offset % spc, bps); 103 104 return b; 105 } 106 107 /** Return number of blocks allocated to a file. 108 * 109 * @param dev_handle Device handle of the device with the file. 110 * @param firstc First cluster of the file. 111 * 112 * @return Number of blocks allocated to the file. 113 */ 114 uint16_t 115 _fat_blcks_get(dev_handle_t dev_handle, fat_cluster_t firstc) 116 { 117 block_t *bb; 118 block_t *b; 119 unsigned bps; 120 unsigned spc; 121 unsigned rscnt; /* block address of the first FAT */ 122 unsigned clusters = 0; 123 fat_cluster_t clst = firstc; 124 125 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 126 bps = uint16_t_le2host(FAT_BS(bb)->bps); 127 spc = FAT_BS(bb)->spc; 128 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 129 block_put(bb); 130 131 if (firstc == FAT_CLST_RES0) { 132 /* No space allocated to the file. */ 133 return 0; 134 } 135 136 while (clst < FAT_CLST_LAST1) { 137 unsigned fsec; /* sector offset relative to FAT1 */ 138 unsigned fidx; /* FAT1 entry index */ 139 140 assert(clst >= FAT_CLST_FIRST); 141 fsec = (clst * sizeof(fat_cluster_t)) / bps; 142 fidx = clst % (bps / sizeof(fat_cluster_t)); 143 /* read FAT1 */ 144 b = block_get(dev_handle, rscnt + fsec, bps); 145 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 146 assert(clst != FAT_CLST_BAD); 147 block_put(b); 148 clusters++; 149 } 150 151 return clusters * spc; 152 } 153 154 uint16_t fat_bps_get(dev_handle_t dev_handle) 155 { 156 block_t *bb; 157 uint16_t bps; 158 159 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 160 assert(bb != NULL); 161 bps = uint16_t_le2host(FAT_BS(bb)->bps); 162 block_put(bb); 163 164 return bps; 165 } 166 167 /** Fill the gap between EOF and a new file position. 168 * 169 * @param nodep FAT node with the gap. 170 * @param mcl First cluster in an independent cluster chain that will 171 * be later appended to the end of the node's own cluster 172 * chain. If pos is still in the last allocated cluster, 173 * this argument is ignored. 174 * @param pos Position in the last node block. 175 */ 176 void fat_fill_gap(fat_node_t *nodep, fat_cluster_t mcl, off_t pos) 177 { 178 uint16_t bps; 179 unsigned spc; 180 block_t *bb, *b; 181 off_t o, boundary; 182 183 bb = block_get(nodep->idx->dev_handle, BS_BLOCK, BS_SIZE); 184 bps = uint16_t_le2host(FAT_BS(bb)->bps); 185 spc = FAT_BS(bb)->spc; 186 block_put(bb); 187 188 boundary = ROUND_UP(nodep->size, bps * spc); 189 190 /* zero out already allocated space */ 191 for (o = nodep->size - 1; o < pos && o < boundary; 192 o = ALIGN_DOWN(o + bps, bps)) { 193 b = fat_block_get(nodep, o / bps); 194 memset(b->data + o % bps, 0, bps - o % bps); 195 b->dirty = true; /* need to sync node */ 196 block_put(b); 197 } 198 199 if (o >= pos) 200 return; 201 202 /* zero out the initial part of the new cluster chain */ 203 for (o = boundary; o < pos; o += bps) { 204 b = _fat_block_get(nodep->idx->dev_handle, mcl, 205 (o - boundary) / bps); 206 memset(b->data, 0, min(bps, pos - o)); 207 b->dirty = true; /* need to sync node */ 208 block_put(b); 209 } 210 } 211 212 void 213 fat_mark_cluster(dev_handle_t dev_handle, unsigned fatno, fat_cluster_t clst, 214 fat_cluster_t value) 215 { 216 /* TODO */ 217 } 218 219 void 220 fat_alloc_shadow_clusters(dev_handle_t dev_handle, fat_cluster_t *lifo, 221 unsigned nclsts) 222 { 223 /* TODO */ 224 } 225 226 int 227 fat_alloc_clusters(dev_handle_t dev_handle, unsigned nclsts, fat_cluster_t *mcl, 228 fat_cluster_t *lcl) 229 { 230 uint16_t bps; 231 uint16_t rscnt; 232 uint16_t sf; 233 block_t *bb, *blk; 234 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 235 unsigned found = 0; /* top of the free cluster number stack */ 236 unsigned b, c, cl; 237 238 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 239 if (lifo) 240 return ENOMEM; 241 242 bb = block_get(dev_handle, BS_BLOCK, BS_SIZE); 243 bps = uint16_t_le2host(FAT_BS(bb)->bps); 244 rscnt = uint16_t_le2host(FAT_BS(bb)->rscnt); 245 sf = uint16_t_le2host(FAT_BS(bb)->sec_per_fat); 246 block_put(bb); 247 248 /* 249 * Search FAT1 for unused clusters. 250 */ 251 for (b = 0, cl = 0; b < sf; blk++) { 252 blk = block_get(dev_handle, rscnt + b, bps); 253 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { 254 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 255 if (*clst == FAT_CLST_RES0) { 256 /* 257 * The cluster is free. Put it into our stack 258 * of found clusters and mark it as non-free. 259 */ 260 lifo[found] = cl; 261 if (found == 0) 262 *clst = FAT_CLST_LAST1; 263 else 264 *clst = lifo[found - 1]; 265 blk->dirty = true; /* need to sync block */ 266 if (++found == nclsts) { 267 /* we are almost done */ 268 block_put(blk); 269 /* update the shadow copies of FAT */ 270 fat_alloc_shadow_clusters(dev_handle, 271 lifo, nclsts); 272 *mcl = lifo[found - 1]; 273 *lcl = lifo[0]; 274 free(lifo); 275 return EOK; 276 } 277 } 278 } 279 block_put(blk); 280 } 281 282 /* 283 * We could not find enough clusters. Now we need to free the clusters 284 * we have allocated so far. 285 */ 286 while (found--) 287 fat_mark_cluster(dev_handle, FAT1, lifo[found], FAT_CLST_RES0); 288 289 free(lifo); 290 return ENOSPC; 291 } 292 293 void fat_append_clusters(fat_node_t *nodep, fat_cluster_t mcl) 294 { 295 } 38 296 39 297 /**
Note:
See TracChangeset
for help on using the changeset viewer.