Changeset 5dfb1948 in mainline
- Timestamp:
- 2011-06-27T16:45:48Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bba3d90
- Parents:
- 7194a60
- Location:
- uspace/srv/fs/fat
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_directory.c
r7194a60 r5dfb1948 37 37 38 38 #include "fat_directory.h" 39 #include "fat_fat.h" 39 40 #include <libblock.h> 40 41 #include <errno.h> … … 136 137 aoff64_t _pos = di->pos; 137 138 int rc; 139 138 140 di->pos = pos; 139 141 rc = fat_directory_block_load(di); … … 175 177 (di->checksum == FAT_LFN_CHKSUM(d))) { 176 178 /* Right order! */ 177 fat_lfn_ copy_entry(d, di->wname, &di->lfn_offset);179 fat_lfn_get_entry(d, di->wname, &di->lfn_offset); 178 180 } else { 179 181 /* Something wrong with order. Skip this long entries set */ … … 190 192 (FAT_LFN_COUNT(d) - 1)) + fat_lfn_size(d); 191 193 di->lfn_offset = di->lfn_size; 192 fat_lfn_ copy_entry(d, di->wname, &di->lfn_offset);194 fat_lfn_get_entry(d, di->wname, &di->lfn_offset); 193 195 di->checksum = FAT_LFN_CHKSUM(d); 194 196 } … … 200 202 (di->checksum == fat_dentry_chksum(d->name))) { 201 203 di->wname[di->lfn_size] = '\0'; 202 if ( utf16_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK)204 if (wstr_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK) 203 205 fat_dentry_name_get(d, name); 204 206 } … … 254 256 } 255 257 256 int fat_directory_write(fat_directory_t *di, char *name, fat_dentry_t *de) 257 { 258 /* TODO: create LFN records if necessarry and create SFN record */ 258 int fat_directory_write(fat_directory_t *di, const char *name, fat_dentry_t *de) 259 { 260 int rc; 261 rc = str_to_wstr(di->wname, FAT_LFN_NAME_SIZE, name); 262 if (rc != EOK) 263 return rc; 264 if (fat_dentry_is_sfn(di->wname)) { 265 /* NAME could be directly stored in dentry without creating LFN */ 266 fat_dentry_name_set(de, name); 267 268 if (fat_directory_is_sfn_exist(di, de)) 269 return EEXIST; 270 rc = fat_directory_lookup_free(di, 1); 271 if (rc != EOK) 272 return rc; 273 rc = fat_directory_write_dentry(di, de); 274 if (rc != EOK) 275 return rc; 276 277 return EOK; 278 } 279 else 280 { 281 /* We should create long entries to store name */ 282 di->lfn_size = wstr_length(di->wname); 283 di->long_entry_count = di->lfn_size / FAT_LFN_ENTRY_SIZE; 284 if (di->lfn_size % FAT_LFN_ENTRY_SIZE) 285 di->long_entry_count++; 286 rc = fat_directory_lookup_free(di, di->long_entry_count+1); 287 if (rc != EOK) 288 return rc; 289 aoff64_t start_pos = di->pos; 290 291 /* Write Short entry */ 292 rc = fat_directory_create_sfn(di, de); 293 if (rc != EOK) 294 return rc; 295 di->checksum = fat_dentry_chksum(de->name); 296 297 rc = fat_directory_seek(di, start_pos+di->long_entry_count); 298 if (rc != EOK) 299 return rc; 300 rc = fat_directory_write_dentry(di, de); 301 if (rc != EOK) 302 return rc; 303 304 /* Write Long entry by parts */ 305 di->lfn_offset = 0; 306 fat_dentry_t *d; 307 size_t idx = 0; 308 do { 309 rc = fat_directory_prev(di); 310 if (rc != EOK) 311 return rc; 312 rc = fat_directory_get(di, &d); 313 if (rc != EOK) 314 return rc; 315 fat_lfn_set_entry(di->wname, &di->lfn_offset, di->lfn_size+1, d); 316 FAT_LFN_CHKSUM(d) = di->checksum; 317 FAT_LFN_ORDER(d) = ++idx; 318 di->b->dirty = true; 319 } while (di->lfn_offset < di->lfn_size); 320 FAT_LFN_ORDER(d) |= FAT_LFN_LAST; 321 322 rc = fat_directory_seek(di, start_pos+di->long_entry_count); 323 if (rc != EOK) 324 return rc; 325 return EOK; 326 } 327 } 328 329 int fat_directory_create_sfn(fat_directory_t *di, fat_dentry_t *de) 330 { 331 char name[FAT_NAME_LEN+1]; 332 char ext[FAT_EXT_LEN+1]; 333 char number[FAT_NAME_LEN+1]; 334 memset(name, FAT_PAD, FAT_NAME_LEN); 335 memset(ext, FAT_PAD, FAT_EXT_LEN); 336 memset(number, FAT_PAD, FAT_NAME_LEN); 337 338 size_t name_len = wstr_size(di->wname); 339 wchar_t *pdot = wstr_rchr(di->wname, '.'); 340 ext[FAT_EXT_LEN] = '\0'; 341 if (pdot) { 342 pdot++; 343 wstr_to_ascii(ext, pdot, FAT_EXT_LEN, FAT_SFN_CHAR); 344 name_len = (pdot - di->wname - 1); 345 } 346 if (name_len > FAT_NAME_LEN) 347 name_len = FAT_NAME_LEN; 348 wstr_to_ascii(name, di->wname, name_len, FAT_SFN_CHAR); 349 350 size_t idx; 351 for (idx=1; idx <= FAT_MAX_SFN; idx++) { 352 if (size_t_str(idx, 10, number, FAT_NAME_LEN-2)!=EOK) 353 return EOVERFLOW; 354 355 /* Fill de->name with FAT_PAD */ 356 memset(de->name, FAT_PAD, FAT_NAME_LEN+FAT_EXT_LEN); 357 /* Copy ext */ 358 memcpy(de->ext, ext, str_size(ext)); 359 /* Copy name */ 360 memcpy(de->name, name, str_size(name)); 361 362 /* Copy number */ 363 size_t offset; 364 if (str_size(name)+str_size(number)+1 >FAT_NAME_LEN) 365 offset = FAT_NAME_LEN - str_size(number)-1; 366 else 367 offset = str_size(name); 368 de->name[offset] = '~'; 369 offset++; 370 memcpy(de->name+offset, number, str_size(number)); 371 372 if (!fat_directory_is_sfn_exist(di, de)) 373 return EOK; 374 } 375 return ERANGE; 376 } 377 378 int fat_directory_write_dentry(fat_directory_t *di, fat_dentry_t *de) 379 { 380 fat_dentry_t *d; 381 int rc; 382 383 rc = fat_directory_get(di, &d); 384 if (rc!=EOK) 385 return rc; 386 memcpy(d, de, sizeof(fat_dentry_t)); 387 di->b->dirty = true; 259 388 return EOK; 260 389 } 261 390 262 391 int fat_directory_expand(fat_directory_t *di) 392 { 393 int rc; 394 fat_cluster_t mcl, lcl; 395 396 if (!FAT_IS_FAT32(di->bs) && di->nodep->firstc == FAT_CLST_ROOT) { 397 /* Can't grow the root directory on FAT12/16. */ 398 return ENOSPC; 399 } 400 rc = fat_alloc_clusters(di->bs, di->nodep->idx->devmap_handle, 1, &mcl, &lcl); 401 if (rc != EOK) 402 return rc; 403 rc = fat_zero_cluster(di->bs, di->nodep->idx->devmap_handle, mcl); 404 if (rc != EOK) { 405 (void) fat_free_clusters(di->bs, di->nodep->idx->devmap_handle, mcl); 406 return rc; 407 } 408 rc = fat_append_clusters(di->bs, di->nodep, mcl, lcl); 409 if (rc != EOK) { 410 (void) fat_free_clusters(di->bs, di->nodep->idx->devmap_handle, mcl); 411 return rc; 412 } 413 di->nodep->size += BPS(di->bs) * SPC(di->bs); 414 di->nodep->dirty = true; /* need to sync node */ 415 di->blocks = di->nodep->size / BPS(di->bs); 416 417 return EOK; 418 } 419 420 int fat_directory_lookup_free(fat_directory_t *di, size_t count) 421 { 422 fat_dentry_t *d; 423 size_t found; 424 aoff64_t pos; 425 426 do { 427 found = 0; 428 pos=0; 429 fat_directory_seek(di, 0); 430 do { 431 if (fat_directory_get(di, &d) == EOK) { 432 switch (fat_classify_dentry(d)) { 433 case FAT_DENTRY_LAST: 434 case FAT_DENTRY_FREE: 435 if (found==0) pos = di->pos; 436 found++; 437 if (found == count) { 438 fat_directory_seek(di, pos); 439 return EOK; 440 } 441 break; 442 case FAT_DENTRY_VALID: 443 case FAT_DENTRY_LFN: 444 case FAT_DENTRY_SKIP: 445 default: 446 found = 0; 447 break; 448 } 449 } 450 } while (fat_directory_next(di) == EOK); 451 } while (fat_directory_expand(di) == EOK); 452 return ENOSPC; 453 } 454 455 int fat_directory_lookup_name(fat_directory_t *di, const char *name, fat_dentry_t **de) 456 { 457 char entry[FAT_LFN_NAME_SIZE]; 458 fat_directory_seek(di, 0); 459 while (fat_directory_read(di, entry, de) == EOK) { 460 if (fat_dentry_namecmp(entry, name) == 0) { 461 return EOK; 462 } else { 463 if (fat_directory_next(di) != EOK) 464 break; 465 } 466 } 467 return ENOENT; 468 } 469 470 bool fat_directory_is_sfn_exist(fat_directory_t *di, fat_dentry_t *de) 471 { 472 fat_dentry_t *d; 473 fat_directory_seek(di, 0); 474 do { 475 if (fat_directory_get(di, &d) == EOK) { 476 switch (fat_classify_dentry(d)) { 477 case FAT_DENTRY_LAST: 478 return false; 479 case FAT_DENTRY_VALID: 480 if (bcmp(de->name, d->name, FAT_NAME_LEN+FAT_EXT_LEN)==0) 481 return true; 482 break; 483 default: 484 case FAT_DENTRY_LFN: 485 case FAT_DENTRY_SKIP: 486 case FAT_DENTRY_FREE: 487 break; 488 } 489 } 490 } while (fat_directory_next(di) == EOK); 491 return false; 492 } 263 493 264 494 /** -
uspace/srv/fs/fat/fat_directory.h
r7194a60 r5dfb1948 38 38 #include "fat_dentry.h" 39 39 40 #define FAT_MAX_SFN 9999 41 40 42 typedef struct { 41 43 /* Directory data */ … … 48 50 bool last; 49 51 /* Long entry data */ 50 uint16_t wname[FAT_LFN_MAX_COUNT * FAT_LFN_ENTRY_SIZE];52 wchar_t wname[FAT_LFN_NAME_SIZE]; 51 53 size_t lfn_offset; 52 54 size_t lfn_size; … … 62 64 extern int fat_directory_next(fat_directory_t *); 63 65 extern int fat_directory_prev(fat_directory_t *); 64 extern int fat_directory_seek(fat_directory_t *, aoff64_t pos);66 extern int fat_directory_seek(fat_directory_t *, aoff64_t); 65 67 extern int fat_directory_get(fat_directory_t *, fat_dentry_t **); 66 extern int fat_directory_dirty(fat_directory_t *);67 68 68 69 extern int fat_directory_read(fat_directory_t *, char *, fat_dentry_t **); 69 extern int fat_directory_write(fat_directory_t *, c har *, fat_dentry_t *);70 extern int fat_directory_write(fat_directory_t *, const char *, fat_dentry_t *); 70 71 extern int fat_directory_erase(fat_directory_t *); 72 extern int fat_directory_lookup_name(fat_directory_t *, const char *, fat_dentry_t **); 73 extern bool fat_directory_is_sfn_exist(fat_directory_t *, fat_dentry_t *); 74 75 extern int fat_directory_lookup_free(fat_directory_t *di, size_t count); 76 extern int fat_directory_write_dentry(fat_directory_t *di, fat_dentry_t *de); 77 extern int fat_directory_create_sfn(fat_directory_t *di, fat_dentry_t *de); 78 extern int fat_directory_expand(fat_directory_t *di); 71 79 72 80
Note:
See TracChangeset
for help on using the changeset viewer.