Changes in / [375ab5e:7fadb65] in mainline
- Files:
-
- 23 deleted
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r375ab5e r7fadb65 102 102 $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \ 103 103 $(USPACE_PATH)/srv/fs/fat/fat \ 104 $(USPACE_PATH)/srv/fs/exfat/exfat \105 104 $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \ 106 105 $(USPACE_PATH)/srv/taskmon/taskmon \ … … 149 148 $(USPACE_PATH)/app/dload/dload \ 150 149 $(USPACE_PATH)/app/edit/edit \ 151 $(USPACE_PATH)/app/filecrc/filecrc \152 $(USPACE_PATH)/app/filegen/filegen \153 150 $(USPACE_PATH)/app/ext2info/ext2info \ 154 151 $(USPACE_PATH)/app/kill/kill \ -
uspace/Makefile
r375ab5e r7fadb65 39 39 app/devctl \ 40 40 app/edit \ 41 app/filecrc \42 app/filegen \43 41 app/ext2info \ 44 42 app/getterm \ … … 81 79 srv/bd/part/guid_part \ 82 80 srv/bd/part/mbr_part \ 83 srv/fs/exfat \84 81 srv/fs/fat \ 85 82 srv/fs/tmpfs \ -
uspace/app/mkfat/fat.h
r375ab5e r7fadb65 38 38 #define BS_BLOCK 0 39 39 #define BS_SIZE 512 40 40 41 #define DIRENT_SIZE 32 41 42 #define FAT12_CLST_MAX 408543 #define FAT16_CLST_MAX 6552544 45 #define FAT12 1246 #define FAT16 1647 #define FAT32 3248 49 #define FAT_SIZE(a) ((a==FAT12)? 1.5 : ( (a==FAT16)? 2 : 4 ) )50 42 51 43 typedef struct fat_bs { -
uspace/app/mkfat/mkfat.c
r375ab5e r7fadb65 35 35 * @brief Tool for creating new FAT file systems. 36 36 * 37 * Currently we can create 12/16/32-bit FAT.37 * Currently we can only create 16-bit FAT. 38 38 */ 39 39 … … 55 55 #define div_round_up(a, b) (((a) + (b) - 1) / (b)) 56 56 57 /** Defaultfile-system parameters */57 /** Predefined file-system parameters */ 58 58 enum { 59 default_sector_size = 512,60 default_sectors_per_cluster = 4,61 default_fat_count = 2,62 default_reserved_clusters = 2,63 default_media_descriptor = 0xF8 /**< fixed disk */59 sector_size = 512, 60 sectors_per_cluster = 8, 61 fat_count = 2, 62 reserved_clusters = 2, 63 media_descriptor = 0xF8 /**< fixed disk */ 64 64 }; 65 65 66 66 /** Configurable file-system parameters */ 67 67 typedef struct fat_cfg { 68 int fat_type; /* FAT12 = 12, FAT16 = 16, FAT32 = 32 */69 size_t sector_size;70 68 uint32_t total_sectors; 71 69 uint16_t root_ent_max; 72 uint32_t addt_res_sectors; 73 uint8_t sectors_per_cluster; 74 70 uint16_t addt_res_sectors; 71 } fat_cfg_t; 72 73 /** Derived file-system parameters */ 74 typedef struct fat_params { 75 struct fat_cfg cfg; 75 76 uint16_t reserved_sectors; 76 uint 32_t rootdir_sectors;77 uint16_t rootdir_sectors; 77 78 uint32_t fat_sectors; 78 uint32_t total_clusters; 79 uint8_t fat_count; 80 } fat_cfg_t; 79 uint16_t total_clusters; 80 } fat_params_t; 81 81 82 82 static void syntax_print(void); 83 83 84 static int fat_params_compute(struct fat_cfg *cfg); 85 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id); 86 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs); 84 static int fat_params_compute(struct fat_cfg const *cfg, 85 struct fat_params *par); 86 static int fat_blocks_write(struct fat_params const *par, 87 service_id_t service_id); 88 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs); 87 89 88 90 int main(int argc, char **argv) 89 91 { 92 struct fat_params par; 90 93 struct fat_cfg cfg; 91 94 … … 93 96 char *dev_path; 94 97 service_id_t service_id; 98 size_t block_size; 95 99 char *endptr; 96 100 aoff64_t dev_nblocks; 97 101 98 cfg.sector_size = default_sector_size;99 cfg.sectors_per_cluster = default_sectors_per_cluster;100 cfg.fat_count = default_fat_count;101 102 cfg.total_sectors = 0; 102 103 cfg.addt_res_sectors = 0; 103 104 cfg.root_ent_max = 128; 104 cfg.fat_type = FAT16;105 105 106 106 if (argc < 2) { … … 111 111 112 112 --argc; ++argv; 113 113 114 if (str_cmp(*argv, "--size") == 0) { 114 115 --argc; ++argv; … … 129 130 } 130 131 131 if (str_cmp(*argv, "--type") == 0) {132 --argc; ++argv;133 if (*argv == NULL) {134 printf(NAME ": Error, argument missing.\n");135 syntax_print();136 return 1;137 }138 139 cfg.fat_type = strtol(*argv, &endptr, 10);140 if (*endptr != '\0') {141 printf(NAME ": Error, invalid argument.\n");142 syntax_print();143 return 1;144 }145 146 --argc; ++argv;147 }148 149 132 if (argc != 1) { 150 133 printf(NAME ": Error, unexpected argument.\n"); … … 154 137 155 138 dev_path = *argv; 156 printf("Device: %s\n", dev_path);157 139 158 140 rc = loc_service_get_id(dev_path, &service_id, 0); … … 168 150 } 169 151 170 rc = block_get_bsize(service_id, & cfg.sector_size);152 rc = block_get_bsize(service_id, &block_size); 171 153 if (rc != EOK) { 172 154 printf(NAME ": Error determining device block size.\n"); … … 183 165 } 184 166 185 if ( cfg.fat_type == FAT12 && cfg.sector_size != 512) {186 printf(NAME ": Error. Device block size is not 512 bytes for FAT12 file system.\n");167 if (block_size != 512) { 168 printf(NAME ": Error. Device block size is not 512 bytes.\n"); 187 169 return 2; 188 170 } … … 193 175 } 194 176 195 printf(NAME ": Creating FAT %d filesystem on device %s.\n", cfg.fat_type, dev_path);196 197 rc = fat_params_compute(&cfg );177 printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path); 178 179 rc = fat_params_compute(&cfg, &par); 198 180 if (rc != EOK) { 199 181 printf(NAME ": Invalid file-system parameters.\n"); … … 201 183 } 202 184 203 rc = fat_blocks_write(& cfg, service_id);185 rc = fat_blocks_write(&par, service_id); 204 186 if (rc != EOK) { 205 187 printf(NAME ": Error writing device.\n"); … … 215 197 static void syntax_print(void) 216 198 { 217 printf("syntax: mkfat 32 [--size <sectors>] [--type 12|16|32] <device_name>\n");199 printf("syntax: mkfat [--size <num_blocks>] <device_name>\n"); 218 200 } 219 201 … … 223 205 * file system params. 224 206 */ 225 static int fat_params_compute(struct fat_cfg *cfg)207 static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par) 226 208 { 227 209 uint32_t fat_bytes; … … 229 211 230 212 /* 231 * Make a conservative guess on the FAT size needed for the file 232 * system. The optimum could be potentially smaller since we 233 * do not subtract size of the FAT itself when computing the 234 * size of the data region. 235 */ 236 237 if (cfg->fat_type == FAT12) 238 cfg->sectors_per_cluster = 1; 239 240 cfg->reserved_sectors = 1 + cfg->addt_res_sectors; 241 if (cfg->fat_type != FAT32) { 242 cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE, 243 cfg->sector_size); 244 } 245 else 246 cfg->rootdir_sectors = 0; 247 non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors; 248 249 cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb, 250 cfg->sectors_per_cluster); 251 252 if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) || 253 (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX || 254 cfg->total_clusters > FAT16_CLST_MAX)) || 255 (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX)) 256 return ENOSPC; 257 258 fat_bytes = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type); 259 cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size); 213 * Make a conservative guess on the FAT size needed for the file 214 * system. The optimum could be potentially smaller since we 215 * do not subtract size of the FAT itself when computing the 216 * size of the data region. 217 */ 218 219 par->reserved_sectors = 1 + cfg->addt_res_sectors; 220 par->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE, 221 sector_size); 222 non_data_sectors_lb = par->reserved_sectors + par->rootdir_sectors; 223 224 par->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb, 225 sectors_per_cluster); 226 227 fat_bytes = (par->total_clusters + 2) * 2; 228 par->fat_sectors = div_round_up(fat_bytes, sector_size); 229 230 par->cfg = *cfg; 260 231 261 232 return EOK; … … 263 234 264 235 /** Create file system with the given parameters. */ 265 static int fat_blocks_write(struct fat_ cfg const *cfg, service_id_t service_id)236 static int fat_blocks_write(struct fat_params const *par, service_id_t service_id) 266 237 { 267 238 aoff64_t addr; … … 272 243 struct fat_bs bs; 273 244 274 fat_bootsec_create( cfg, &bs);245 fat_bootsec_create(par, &bs); 275 246 276 247 rc = block_write_direct(service_id, BS_BLOCK, 1, &bs); … … 280 251 addr = BS_BLOCK + 1; 281 252 282 buffer = calloc( cfg->sector_size, 1);253 buffer = calloc(sector_size, 1); 283 254 if (buffer == NULL) 284 255 return ENOMEM; 285 memset(buffer, 0, cfg->sector_size);286 256 287 257 /* Reserved sectors */ 288 for (i = 0; i < cfg->reserved_sectors - 1; ++i) {258 for (i = 0; i < par->reserved_sectors - 1; ++i) { 289 259 rc = block_write_direct(service_id, addr, 1, buffer); 290 260 if (rc != EOK) … … 295 265 296 266 /* File allocation tables */ 297 for (i = 0; i < cfg->fat_count; ++i) {267 for (i = 0; i < fat_count; ++i) { 298 268 printf("Writing allocation table %d.\n", i + 1); 299 269 300 for (j = 0; j < cfg->fat_sectors; ++j) {301 memset(buffer, 0, cfg->sector_size);270 for (j = 0; j < par->fat_sectors; ++j) { 271 memset(buffer, 0, sector_size); 302 272 if (j == 0) { 303 buffer[0] = default_media_descriptor;273 buffer[0] = media_descriptor; 304 274 buffer[1] = 0xFF; 305 275 buffer[2] = 0xFF; 306 if (cfg->fat_type == FAT16) { 307 buffer[3] = 0xFF; 308 } else if (cfg->fat_type == FAT32) { 309 buffer[3] = 0x0F; 310 buffer[4] = 0xFF; 311 buffer[5] = 0xFF; 312 buffer[6] = 0xFF; 313 buffer[7] = 0x0F; 314 buffer[8] = 0xF8; 315 buffer[9] = 0xFF; 316 buffer[10] = 0xFF; 317 buffer[11] = 0x0F; 318 } 276 buffer[3] = 0xFF; 319 277 } 320 278 … … 327 285 } 328 286 287 printf("Writing root directory.\n"); 288 289 memset(buffer, 0, sector_size); 290 329 291 /* Root directory */ 330 printf("Writing root directory.\n"); 331 memset(buffer, 0, cfg->sector_size); 332 if (cfg->fat_type != FAT32) { 333 size_t idx; 334 for (idx = 0; idx < cfg->rootdir_sectors; ++idx) { 335 rc = block_write_direct(service_id, addr, 1, buffer); 336 if (rc != EOK) 337 return EIO; 338 339 ++addr; 340 } 341 } else { 342 for (i=0; i<cfg->sectors_per_cluster; i++) { 343 rc = block_write_direct(service_id, addr, 1, buffer); 344 if (rc != EOK) 345 return EIO; 346 347 ++addr; 348 } 292 for (i = 0; i < par->rootdir_sectors; ++i) { 293 rc = block_write_direct(service_id, addr, 1, buffer); 294 if (rc != EOK) 295 return EIO; 296 297 ++addr; 349 298 } 350 299 … … 355 304 356 305 /** Construct boot sector with the given parameters. */ 357 static void fat_bootsec_create(struct fat_ cfg const *cfg, struct fat_bs *bs)306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs) 358 307 { 359 308 memset(bs, 0, sizeof(*bs)); … … 366 315 367 316 /* BIOS Parameter Block */ 368 bs->bps = host2uint16_t_le(cfg->sector_size); 369 bs->spc = cfg->sectors_per_cluster; 370 bs->rscnt = host2uint16_t_le(cfg->reserved_sectors); 371 bs->fatcnt = cfg->fat_count; 372 bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max); 373 374 if (cfg->total_sectors < 0x10000) { 375 bs->totsec16 = host2uint16_t_le(cfg->total_sectors); 376 bs->totsec32 = 0; 377 } else { 378 bs->totsec16 = 0; 379 bs->totsec32 = host2uint32_t_le(cfg->total_sectors); 380 } 381 382 bs->mdesc = default_media_descriptor; 317 bs->bps = host2uint16_t_le(sector_size); 318 bs->spc = sectors_per_cluster; 319 bs->rscnt = host2uint16_t_le(par->reserved_sectors); 320 bs->fatcnt = fat_count; 321 bs->root_ent_max = host2uint16_t_le(par->cfg.root_ent_max); 322 323 if (par->cfg.total_sectors < 0x10000) 324 bs->totsec16 = host2uint16_t_le(par->cfg.total_sectors); 325 else 326 bs->totsec16 = host2uint16_t_le(0); 327 328 bs->mdesc = media_descriptor; 329 bs->sec_per_fat = host2uint16_t_le(par->fat_sectors); 383 330 bs->sec_per_track = host2uint16_t_le(63); 384 bs->signature = host2uint16_t_be(0x55AA);385 331 bs->headcnt = host2uint16_t_le(6); 386 332 bs->hidden_sec = host2uint32_t_le(0); 387 333 388 if (cfg->fat_type == FAT32) { 389 bs->sec_per_fat = 0; 390 bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors); 391 392 bs->fat32.pdn = 0x80; 393 bs->fat32.ebs = 0x29; 394 bs->fat32.id = host2uint32_t_be(0x12345678); 395 bs->fat32.root_cluster = 2; 396 397 memcpy(bs->fat32.label, "HELENOS_NEW", 11); 398 memcpy(bs->fat32.type, "FAT32 ", 8); 399 } else { 400 bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors); 401 bs->pdn = 0x80; 402 bs->ebs = 0x29; 403 bs->id = host2uint32_t_be(0x12345678); 404 405 memcpy(bs->label, "HELENOS_NEW", 11); 406 memcpy(bs->type, "FAT ", 8); 407 } 334 if (par->cfg.total_sectors >= 0x10000) 335 bs->totsec32 = host2uint32_t_le(par->cfg.total_sectors); 336 else 337 bs->totsec32 = host2uint32_t_le(0); 338 339 /* Extended BPB */ 340 bs->pdn = 0x80; 341 bs->ebs = 0x29; 342 bs->id = host2uint32_t_be(0x12345678); 343 344 memcpy(bs->label, "HELENOS_NEW", 11); 345 memcpy(bs->type, "FAT16 ", 8); 346 bs->signature = host2uint16_t_be(0x55AA); 408 347 } 409 348 -
uspace/lib/c/generic/str.c
r375ab5e r7fadb65 3 3 * Copyright (c) 2008 Jiri Svoboda 4 4 * Copyright (c) 2011 Martin Sucha 5 * Copyright (c) 2011 Oleg Romanenko6 5 * All rights reserved. 7 6 * … … 368 367 } 369 368 370 /** Check whether wide string is plain ASCII.371 *372 * @return True if wide string is plain ASCII.373 *374 */375 bool wstr_is_ascii(const wchar_t *wstr)376 {377 while (*wstr && ascii_check(*wstr))378 wstr++;379 return *wstr == 0;380 }381 382 369 /** Check whether character is valid 383 370 * … … 632 619 * @param size Size of the destination buffer. 633 620 * @param src Source wide string. 634 * 635 * @return EOK, if success, negative otherwise. 636 */ 637 int wstr_to_str(char *dest, size_t size, const wchar_t *src) 638 { 639 int rc; 621 */ 622 void wstr_to_str(char *dest, size_t size, const wchar_t *src) 623 { 640 624 wchar_t ch; 641 625 size_t src_idx; … … 649 633 650 634 while ((ch = src[src_idx++]) != 0) { 651 rc = chr_encode(ch, dest, &dest_off, size - 1); 652 if (rc != EOK) 635 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 653 636 break; 654 637 } 655 638 656 639 dest[dest_off] = '\0'; 657 return rc; 658 } 659 660 /** Convert UTF16 string to string. 661 * 662 * Convert utf16 string @a src to string. The output is written to the buffer 663 * specified by @a dest and @a size. @a size must be non-zero and the string 664 * written will always be well-formed. Surrogate pairs also supported. 665 * 666 * @param dest Destination buffer. 667 * @param size Size of the destination buffer. 668 * @param src Source utf16 string. 669 * 670 * @return EOK, if success, negative otherwise. 671 */ 672 int utf16_to_str(char *dest, size_t size, const uint16_t *src) 673 { 674 size_t idx=0, dest_off=0; 675 wchar_t ch; 676 int rc = EOK; 677 678 /* There must be space for a null terminator in the buffer. */ 679 assert(size > 0); 680 681 while (src[idx]) { 682 if ((src[idx] & 0xfc00) == 0xd800) { 683 if (src[idx+1] && (src[idx+1] & 0xfc00) == 0xdc00) { 684 ch = 0x10000; 685 ch += (src[idx] & 0x03FF) << 10; 686 ch += (src[idx+1] & 0x03FF); 687 idx += 2; 688 } 689 else 690 break; 691 } else { 692 ch = src[idx]; 693 idx++; 694 } 695 rc = chr_encode(ch, dest, &dest_off, size-1); 696 if (rc != EOK) 697 break; 698 } 699 dest[dest_off] = '\0'; 700 return rc; 701 } 702 703 int str_to_utf16(uint16_t *dest, size_t size, const char *src) 704 { 705 int rc=EOK; 706 size_t offset=0; 707 size_t idx=0; 708 wchar_t c; 709 710 assert(size > 0); 711 712 while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) { 713 if (c > 0x10000) { 714 if (idx+2 >= size-1) { 715 rc=EOVERFLOW; 716 break; 717 } 718 c = (c - 0x10000); 719 dest[idx] = 0xD800 | (c >> 10); 720 dest[idx+1] = 0xDC00 | (c & 0x3FF); 721 idx++; 722 } else { 723 dest[idx] = c; 724 } 725 726 idx++; 727 if (idx >= size-1) { 728 rc=EOVERFLOW; 729 break; 730 } 731 } 732 733 dest[idx] = '\0'; 734 return rc; 735 } 736 640 } 737 641 738 642 /** Convert wide string to new string. … … 794 698 * @param dlen Length of destination buffer (number of wchars). 795 699 * @param src Source string. 796 * 797 * @return EOK, if success, negative otherwise. 798 */ 799 int str_to_wstr(wchar_t *dest, size_t dlen, const char *src) 800 { 801 int rc=EOK; 700 */ 701 void str_to_wstr(wchar_t *dest, size_t dlen, const char *src) 702 { 802 703 size_t offset; 803 704 size_t di; … … 810 711 811 712 do { 812 if (di >= dlen - 1) { 813 rc = EOVERFLOW; 713 if (di >= dlen - 1) 814 714 break; 815 }816 715 817 716 c = str_decode(src, &offset, STR_NO_LIMIT); … … 820 719 821 720 dest[dlen - 1] = '\0'; 822 return rc;823 721 } 824 722 … … 885 783 886 784 return (char *) res; 887 }888 889 /** Find first occurence of character in wide string.890 *891 * @param wstr String to search.892 * @param ch Character to look for.893 *894 * @return Pointer to character in @a wstr or NULL if not found.895 */896 wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch)897 {898 while (*wstr && *wstr != ch)899 wstr++;900 if (*wstr)901 return (wchar_t *) wstr;902 else903 return NULL;904 }905 906 /** Find last occurence of character in wide string.907 *908 * @param wstr String to search.909 * @param ch Character to look for.910 *911 * @return Pointer to character in @a wstr or NULL if not found.912 */913 wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch)914 {915 const wchar_t *res = NULL;916 while (*wstr) {917 if (*wstr == ch)918 res = wstr;919 wstr++;920 }921 return (wchar_t *) res;922 785 } 923 786 … … 1174 1037 } 1175 1038 1176 void str_reverse(char* begin, char* end)1177 {1178 char aux;1179 while(end>begin)1180 aux=*end, *end--=*begin, *begin++=aux;1181 }1182 1183 int size_t_str(size_t value, int base, char* str, size_t size)1184 {1185 static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz";1186 char* wstr=str;1187 1188 if (size == 0)1189 return EINVAL;1190 if (base<2 || base>35) {1191 *str='\0';1192 return EINVAL;1193 }1194 1195 do {1196 *wstr++ = num[value % base];1197 if (--size == 0)1198 return EOVERFLOW;1199 } while(value /= base);1200 *wstr='\0';1201 1202 // Reverse string1203 str_reverse(str,wstr-1);1204 return EOK;1205 }1206 1039 1207 1040 /** Convert initial part of string to unsigned long according to given base. -
uspace/lib/c/include/str.h
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2005 Martin Decky 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 72 71 extern bool ascii_check(wchar_t ch); 73 72 extern bool chr_check(wchar_t ch); 74 extern bool wstr_is_ascii(const wchar_t *wstr);75 73 76 74 extern int str_cmp(const char *s1, const char *s2); … … 81 79 extern void str_append(char *dest, size_t size, const char *src); 82 80 83 extern int wstr_to_str(char *dest, size_t size, const wchar_t *src);84 81 extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n); 82 extern void wstr_to_str(char *dest, size_t size, const wchar_t *src); 85 83 extern char *wstr_to_astr(const wchar_t *src); 84 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src); 86 85 extern wchar_t *str_to_awstr(const char *src); 87 extern int str_to_wstr(wchar_t *dest, size_t dlen, const char *src);88 extern int utf16_to_str(char *dest, size_t size, const uint16_t *src);89 extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);90 86 91 87 extern char *str_chr(const char *str, wchar_t ch); 92 88 extern char *str_rchr(const char *str, wchar_t ch); 93 extern wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch);94 extern wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch);95 89 96 90 extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); … … 99 93 extern char *str_dup(const char *); 100 94 extern char *str_ndup(const char *, size_t max_size); 101 102 extern void str_reverse(char* begin, char* end);103 extern int size_t_str(size_t value, int base, char* str, size_t size);104 95 105 96 extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *); -
uspace/srv/fs/fat/Makefile
r375ab5e r7fadb65 39 39 fat_idx.c \ 40 40 fat_dentry.c \ 41 fat_directory.c \42 41 fat_fat.c 43 42 -
uspace/srv/fs/fat/fat.c
r375ab5e r7fadb65 2 2 * Copyright (c) 2006 Martin Decky 3 3 * Copyright (c) 2008 Jakub Jermar 4 * Copyright (c) 2011 Oleg Romanenko5 4 * All rights reserved. 6 5 * -
uspace/srv/fs/fat/fat.h
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 56 55 #define RSCNT(bs) uint16_t_le2host((bs)->rscnt) 57 56 #define FATCNT(bs) (bs)->fatcnt 58 #define SF(bs) (uint16_t_le2host((bs)->sec_per_fat) !=0 ? \ 59 uint16_t_le2host((bs)->sec_per_fat) : \ 60 uint32_t_le2host(bs->fat32.sectors_per_fat)) 57 #define SF(bs) uint16_t_le2host((bs)->sec_per_fat) 61 58 #define RDE(bs) uint16_t_le2host((bs)->root_ent_max) 62 59 #define TS(bs) (uint16_t_le2host((bs)->totsec16) != 0 ? \ -
uspace/srv/fs/fat/fat_dentry.c
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 40 39 #include <ctype.h> 41 40 #include <str.h> 42 #include <errno.h> 43 #include <byteorder.h> 44 #include <assert.h> 41 42 static bool is_d_char(const char ch) 43 { 44 if (isalnum(ch) || ch == '_') 45 return true; 46 else 47 return false; 48 } 45 49 46 50 /** Compare path component with the name read from the dentry. … … 76 80 } 77 81 78 void fat_dentry_name_get(const fat_dentry_t *d, char *buf) 79 { 80 unsigned int i; 81 82 for (i = 0; i < FAT_NAME_LEN; i++) { 83 if (d->name[i] == FAT_PAD) 84 break; 85 86 if (d->name[i] == FAT_DENTRY_E5_ESC) 87 *buf++ = 0xe5; 88 else { 89 if (d->lcase & FAT_LCASE_LOWER_NAME) 90 *buf++ = tolower(d->name[i]); 91 else 92 *buf++ = d->name[i]; 93 } 94 } 95 96 if (d->ext[0] != FAT_PAD) 97 *buf++ = '.'; 98 99 for (i = 0; i < FAT_EXT_LEN; i++) { 100 if (d->ext[i] == FAT_PAD) { 101 *buf = '\0'; 102 return; 103 } 104 105 if (d->ext[i] == FAT_DENTRY_E5_ESC) 106 *buf++ = 0xe5; 107 else { 108 if (d->lcase & FAT_LCASE_LOWER_EXT) 109 *buf++ = tolower(d->ext[i]); 110 else 111 *buf++ = d->ext[i]; 112 } 113 } 114 115 *buf = '\0'; 116 } 117 118 void fat_dentry_name_set(fat_dentry_t *d, const char *name) 119 { 120 unsigned int i; 121 const char fake_ext[] = " "; 122 bool lower_name = true; 123 bool lower_ext = true; 124 125 for (i = 0; i < FAT_NAME_LEN; i++) { 126 switch ((uint8_t) *name) { 127 case 0xe5: 128 d->name[i] = FAT_DENTRY_E5_ESC; 129 name++; 130 break; 131 case '\0': 132 case '.': 133 d->name[i] = FAT_PAD; 134 break; 135 default: 136 if (isalpha(*name)) { 137 if (!islower(*name)) 138 lower_name = false; 139 } 140 141 d->name[i] = toupper(*name++); 142 break; 143 } 144 } 145 146 if (*name++ != '.') 147 name = fake_ext; 148 149 for (i = 0; i < FAT_EXT_LEN; i++) { 150 switch ((uint8_t) *name) { 151 case 0xe5: 152 d->ext[i] = FAT_DENTRY_E5_ESC; 153 name++; 154 break; 155 case '\0': 156 d->ext[i] = FAT_PAD; 157 break; 158 default: 159 if (isalpha(*name)) { 160 if (!islower(*name)) 161 lower_ext = false; 162 } 163 164 d->ext[i] = toupper(*name++); 165 break; 166 } 167 } 168 169 if (lower_name) 170 d->lcase |= FAT_LCASE_LOWER_NAME; 171 else 172 d->lcase &= ~FAT_LCASE_LOWER_NAME; 173 174 if (lower_ext) 175 d->lcase |= FAT_LCASE_LOWER_EXT; 176 else 177 d->lcase &= ~FAT_LCASE_LOWER_EXT; 178 } 179 180 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) 181 { 182 if (d->attr == FAT_ATTR_LFN) { 183 /* long name entry */ 184 if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED) 185 return FAT_DENTRY_FREE; 186 else 187 return FAT_DENTRY_LFN; 188 } 189 if (d->attr & FAT_ATTR_VOLLABEL) { 190 /* volume label entry */ 191 return FAT_DENTRY_SKIP; 192 } 193 if (d->name[0] == FAT_DENTRY_ERASED) { 194 /* not-currently-used entry */ 195 return FAT_DENTRY_FREE; 196 } 197 if (d->name[0] == FAT_DENTRY_UNUSED) { 198 /* never used entry */ 199 return FAT_DENTRY_LAST; 200 } 201 if (d->name[0] == FAT_DENTRY_DOT) { 202 /* 203 * Most likely '.' or '..'. 204 * It cannot occur in a regular file name. 205 */ 206 return FAT_DENTRY_SKIP; 207 } 208 return FAT_DENTRY_VALID; 209 } 210 211 /** Compute checksum of Node name. 212 * 213 * Returns an unsigned byte checksum computed on an unsigned byte 214 * array. The array must be 11 bytes long and is assumed to contain 215 * a name stored in the format of a MS-DOS directory entry. 216 * 217 * @param name Node name read from the dentry. 218 * 219 * @return An 8-bit unsigned checksum of the name. 220 */ 221 uint8_t fat_dentry_chksum(uint8_t *name) 222 { 223 uint8_t i, sum=0; 224 for (i=0; i<(FAT_NAME_LEN+FAT_EXT_LEN); i++) { 225 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i]; 226 } 227 return sum; 228 } 229 230 /** Get number of bytes in a string with size limit. 231 * 232 * @param str NULL-terminated (or not) string. 233 * @param size Maximum number of bytes to consider. 234 * 235 * @return Number of bytes in string (without 0 and ff). 236 * 237 */ 238 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size) 239 { 240 size_t offset = 0; 241 242 while (offset < size) { 243 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD) 244 break; 245 offset++; 246 } 247 return offset; 248 } 249 250 /** Get number of bytes in a FAT long entry occuped by characters. 251 * 252 * @param d FAT long entry. 253 * 254 * @return Number of bytes. 255 * 256 */ 257 size_t fat_lfn_size(const fat_dentry_t *d) 258 { 259 size_t size = 0; 260 261 size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE); 262 size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE); 263 size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE); 264 265 return size; 266 } 267 268 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset) 269 { 270 int i; 271 for (i=FAT_LFN_PART3_SIZE-1; i>=0 && *offset>0; i--) { 272 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD) 273 continue; 274 (*offset)--; 275 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]); 276 } 277 for (i=FAT_LFN_PART2_SIZE-1; i>=0 && *offset>0; i--) { 278 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD) 279 continue; 280 (*offset)--; 281 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]); 282 } 283 for (i=FAT_LFN_PART1_SIZE-1; i>=0 && *offset>0; i--) { 284 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD) 285 continue; 286 (*offset)--; 287 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]); 288 } 289 return *offset; 290 } 291 292 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, fat_dentry_t *d) 293 { 294 size_t idx; 295 for (idx=0; idx < FAT_LFN_PART1_SIZE; idx++) { 296 if (*offset < size) { 297 d->lfn.part1[idx] = host2uint16_t_le(src[*offset]); 298 (*offset)++; 299 } 300 else 301 d->lfn.part1[idx] = FAT_LFN_PAD; 302 } 303 for (idx=0; idx < FAT_LFN_PART2_SIZE; idx++) { 304 if (*offset < size) { 305 d->lfn.part2[idx] = host2uint16_t_le(src[*offset]); 306 (*offset)++; 307 } 308 else 309 d->lfn.part2[idx] = FAT_LFN_PAD; 310 } 311 for (idx=0; idx < FAT_LFN_PART3_SIZE; idx++) { 312 if (*offset < size) { 313 d->lfn.part3[idx] = host2uint16_t_le(src[*offset]); 314 (*offset)++; 315 } 316 else 317 d->lfn.part3[idx] = FAT_LFN_PAD; 318 } 319 320 if (src[*offset] == 0) 321 offset++; 322 FAT_LFN_ATTR(d) = FAT_ATTR_LFN; 323 d->lfn.type = 0; 324 d->lfn.firstc_lo = 0; 325 326 return *offset; 327 } 328 329 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad) 330 { 331 wchar_t ch; 332 size_t off = 0; 333 size_t i = 0; 334 335 while (i < count) { 336 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) { 337 if (ascii_check(ch) & IS_D_CHAR(ch)) 338 *dst = toupper(ch); 339 else 340 *dst = pad; 341 } 342 else 343 break; 344 345 dst++; 346 i++; 347 } 348 *dst = '\0'; 349 } 350 351 bool fat_valid_name(const char *name) 352 { 353 wchar_t ch; 354 size_t offset=0; 355 bool result = true; 356 357 while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) { 358 if (wstr_chr(FAT_STOP_CHARS, ch) != NULL) { 359 result = false; 360 break; 361 } 362 } 363 return result; 364 } 365 366 bool fat_valid_short_name(const char *name) 82 bool fat_dentry_name_verify(const char *name) 367 83 { 368 84 unsigned int i; 369 85 unsigned int dot = 0; 370 86 bool dot_found = false; 87 371 88 372 89 for (i = 0; name[i]; i++) { … … 379 96 } 380 97 } else { 381 if (! IS_D_CHAR(name[i]))98 if (!is_d_char(name[i])) 382 99 return false; 383 100 } … … 397 114 } 398 115 399 size_t utf16_length(const uint16_t *wstr) 400 { 401 size_t len = 0; 402 403 while (*wstr++ != 0) 404 len++; 405 406 return len; 116 void fat_dentry_name_get(const fat_dentry_t *d, char *buf) 117 { 118 unsigned int i; 119 120 for (i = 0; i < FAT_NAME_LEN; i++) { 121 if (d->name[i] == FAT_PAD) 122 break; 123 124 if (d->name[i] == FAT_DENTRY_E5_ESC) 125 *buf++ = 0xe5; 126 else { 127 if (d->lcase & FAT_LCASE_LOWER_NAME) 128 *buf++ = tolower(d->name[i]); 129 else 130 *buf++ = d->name[i]; 131 } 132 } 133 134 if (d->ext[0] != FAT_PAD) 135 *buf++ = '.'; 136 137 for (i = 0; i < FAT_EXT_LEN; i++) { 138 if (d->ext[i] == FAT_PAD) { 139 *buf = '\0'; 140 return; 141 } 142 143 if (d->ext[i] == FAT_DENTRY_E5_ESC) 144 *buf++ = 0xe5; 145 else { 146 if (d->lcase & FAT_LCASE_LOWER_EXT) 147 *buf++ = tolower(d->ext[i]); 148 else 149 *buf++ = d->ext[i]; 150 } 151 } 152 153 *buf = '\0'; 154 } 155 156 void fat_dentry_name_set(fat_dentry_t *d, const char *name) 157 { 158 unsigned int i; 159 const char fake_ext[] = " "; 160 bool lower_name = true; 161 bool lower_ext = true; 162 163 for (i = 0; i < FAT_NAME_LEN; i++) { 164 switch ((uint8_t) *name) { 165 case 0xe5: 166 d->name[i] = FAT_DENTRY_E5_ESC; 167 name++; 168 break; 169 case '\0': 170 case '.': 171 d->name[i] = FAT_PAD; 172 break; 173 default: 174 if (isalpha(*name)) { 175 if (!islower(*name)) 176 lower_name = false; 177 } 178 179 d->name[i] = toupper(*name++); 180 break; 181 } 182 } 183 184 if (*name++ != '.') 185 name = fake_ext; 186 187 for (i = 0; i < FAT_EXT_LEN; i++) { 188 switch ((uint8_t) *name) { 189 case 0xe5: 190 d->ext[i] = FAT_DENTRY_E5_ESC; 191 name++; 192 break; 193 case '\0': 194 d->ext[i] = FAT_PAD; 195 break; 196 default: 197 if (isalpha(*name)) { 198 if (!islower(*name)) 199 lower_ext = false; 200 } 201 202 d->ext[i] = toupper(*name++); 203 break; 204 } 205 } 206 207 if (lower_name) 208 d->lcase |= FAT_LCASE_LOWER_NAME; 209 else 210 d->lcase &= ~FAT_LCASE_LOWER_NAME; 211 212 if (lower_ext) 213 d->lcase |= FAT_LCASE_LOWER_EXT; 214 else 215 d->lcase &= ~FAT_LCASE_LOWER_EXT; 216 } 217 218 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) 219 { 220 if (d->attr & FAT_ATTR_VOLLABEL) { 221 /* volume label entry */ 222 return FAT_DENTRY_SKIP; 223 } 224 if (d->name[0] == FAT_DENTRY_ERASED) { 225 /* not-currently-used entry */ 226 return FAT_DENTRY_FREE; 227 } 228 if (d->name[0] == FAT_DENTRY_UNUSED) { 229 /* never used entry */ 230 return FAT_DENTRY_LAST; 231 } 232 if (d->name[0] == FAT_DENTRY_DOT) { 233 /* 234 * Most likely '.' or '..'. 235 * It cannot occur in a regular file name. 236 */ 237 return FAT_DENTRY_SKIP; 238 } 239 return FAT_DENTRY_VALID; 407 240 } 408 241 -
uspace/srv/fs/fat/fat_dentry.h
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 38 37 #include <bool.h> 39 38 40 #define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')41 #define FAT_STOP_CHARS L"*?/\\\n\t|'"42 43 39 #define FAT_NAME_LEN 8 44 40 #define FAT_EXT_LEN 3 … … 48 44 #define FAT_EXT_PAD " " 49 45 50 #define FAT_ATTR_RDONLY 0x01 51 #define FAT_ATTR_HIDDEN 0x02 52 #define FAT_ATTR_SYSTEM 0x04 53 #define FAT_ATTR_VOLLABEL 0x08 54 #define FAT_ATTR_SUBDIR 0x10 55 #define FAT_ATTR_ARCHIVE 0x20 56 #define FAT_ATTR_LFN \ 57 (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL) 58 46 #define FAT_ATTR_RDONLY (1 << 0) 47 #define FAT_ATTR_VOLLABEL (1 << 3) 48 #define FAT_ATTR_SUBDIR (1 << 4) 49 59 50 #define FAT_LCASE_LOWER_NAME 0x08 60 51 #define FAT_LCASE_LOWER_EXT 0x10 61 52 62 #define FAT_PAD ' ' 63 #define FAT_LFN_PAD 0xffff 64 #define FAT_SFN_CHAR '_' 53 #define FAT_PAD ' ' 65 54 66 55 #define FAT_DENTRY_UNUSED 0x00 … … 68 57 #define FAT_DENTRY_DOT 0x2e 69 58 #define FAT_DENTRY_ERASED 0xe5 70 #define FAT_LFN_LAST 0x4071 #define FAT_LFN_ERASED 0x8072 73 #define FAT_LFN_ORDER(d) (d->lfn.order)74 #define FAT_IS_LFN(d) \75 ((FAT_LFN_ORDER(d) & FAT_LFN_LAST) == FAT_LFN_LAST)76 #define FAT_LFN_COUNT(d) \77 (FAT_LFN_ORDER(d) ^ FAT_LFN_LAST)78 #define FAT_LFN_PART1(d) (d->lfn.part1)79 #define FAT_LFN_PART2(d) (d->lfn.part2)80 #define FAT_LFN_PART3(d) (d->lfn.part3)81 #define FAT_LFN_ATTR(d) (d->lfn.attr)82 #define FAT_LFN_CHKSUM(d) (d->lfn.check_sum)83 84 #define FAT_LFN_NAME_SIZE 26085 #define FAT_LFN_MAX_COUNT 2086 #define FAT_LFN_PART1_SIZE 587 #define FAT_LFN_PART2_SIZE 688 #define FAT_LFN_PART3_SIZE 289 #define FAT_LFN_ENTRY_SIZE \90 (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)91 59 92 60 typedef enum { … … 94 62 FAT_DENTRY_LAST, 95 63 FAT_DENTRY_FREE, 96 FAT_DENTRY_VALID, 97 FAT_DENTRY_LFN 64 FAT_DENTRY_VALID 98 65 } fat_dentry_clsf_t; 99 66 100 67 typedef struct { 68 uint8_t name[8]; 69 uint8_t ext[3]; 70 uint8_t attr; 71 uint8_t lcase; 72 uint8_t ctime_fine; 73 uint16_t ctime; 74 uint16_t cdate; 75 uint16_t adate; 101 76 union { 102 struct { 103 uint8_t name[8]; 104 uint8_t ext[3]; 105 uint8_t attr; 106 uint8_t lcase; 107 uint8_t ctime_fine; 108 uint16_t ctime; 109 uint16_t cdate; 110 uint16_t adate; 111 union { 112 uint16_t eaidx; /* FAT12/FAT16 */ 113 uint16_t firstc_hi; /* FAT32 */ 114 } __attribute__ ((packed)); 115 uint16_t mtime; 116 uint16_t mdate; 117 union { 118 uint16_t firstc; /* FAT12/FAT16 */ 119 uint16_t firstc_lo; /* FAT32 */ 120 } __attribute__ ((packed)); 121 uint32_t size; 122 } __attribute__ ((packed)); 123 struct { 124 uint8_t order; 125 uint16_t part1[FAT_LFN_PART1_SIZE]; 126 uint8_t attr; 127 uint8_t type; 128 uint8_t check_sum; 129 uint16_t part2[FAT_LFN_PART2_SIZE]; 130 uint16_t firstc_lo; /* MUST be 0 */ 131 uint16_t part3[FAT_LFN_PART3_SIZE]; 132 } __attribute__ ((packed)) lfn; 133 }; 77 uint16_t eaidx; /* FAT12/FAT16 */ 78 uint16_t firstc_hi; /* FAT32 */ 79 } __attribute__ ((packed)); 80 uint16_t mtime; 81 uint16_t mdate; 82 union { 83 uint16_t firstc; /* FAT12/FAT16 */ 84 uint16_t firstc_lo; /* FAT32 */ 85 } __attribute__ ((packed)); 86 uint32_t size; 134 87 } __attribute__ ((packed)) fat_dentry_t; 135 88 136 137 89 extern int fat_dentry_namecmp(char *, const char *); 90 extern bool fat_dentry_name_verify(const char *); 138 91 extern void fat_dentry_name_get(const fat_dentry_t *, char *); 139 92 extern void fat_dentry_name_set(fat_dentry_t *, const char *); 140 93 extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *); 141 extern uint8_t fat_dentry_chksum(uint8_t *);142 143 extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);144 extern size_t fat_lfn_size(const fat_dentry_t *);145 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);146 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, fat_dentry_t *);147 148 extern void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad);149 extern size_t utf16_length(const uint16_t *wstr);150 151 extern bool fat_valid_name(const char *name);152 extern bool fat_valid_short_name(const char *name);153 154 94 155 95 #endif -
uspace/srv/fs/fat/fat_fat.c
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 30 29 /** @addtogroup fs 31 30 * @{ 32 */ 31 */ 33 32 34 33 /** … … 55 54 * primitive boot sector members. 56 55 */ 56 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \ 57 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0) 58 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs)) 59 57 60 #define CLBN2PBN(bs, cl, bn) \ 58 61 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 59 60 #define IS_ODD(number) (number & 0x1)61 62 62 63 /** … … 64 65 * during allocation of clusters. The lock does not have to be held durring 65 66 * deallocation of clusters. 66 */ 67 */ 67 68 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 68 69 … … 76 77 * @param numc If non-NULL, output argument holding the number of 77 78 * clusters seen during the walk. 78 * @param max_clusters Maximum number of clusters to visit. 79 * @param max_clusters Maximum number of clusters to visit. 79 80 * 80 81 * @return EOK on success or a negative error code. 81 82 */ 82 int 83 int 83 84 fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc, 84 fat_cluster_t *lastc, uint 32_t *numc, uint32_t max_clusters)85 { 86 uint32_t clusters = 0;87 fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);88 fat_cluster_t clst _bad = FAT_CLST_BAD(bs);85 fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters) 86 { 87 block_t *b; 88 uint16_t clusters = 0; 89 fat_cluster_t clst = firstc; 89 90 int rc; 90 91 … … 98 99 } 99 100 100 while (clst < clst_last1 && clusters < max_clusters) { 101 while (clst < FAT_CLST_LAST1 && clusters < max_clusters) { 102 aoff64_t fsec; /* sector offset relative to FAT1 */ 103 unsigned fidx; /* FAT1 entry index */ 104 101 105 assert(clst >= FAT_CLST_FIRST); 102 106 if (lastc) 103 107 *lastc = clst; /* remember the last cluster number */ 104 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 105 110 /* read FAT1 */ 106 rc = fat_get_cluster(bs, service_id, FAT1, clst, &clst); 107 if (rc != EOK) 108 return rc; 109 110 assert(clst != clst_bad); 111 rc = block_get(&b, service_id, RSCNT(bs) + fsec, 112 BLOCK_FLAGS_NONE); 113 if (rc != EOK) 114 return rc; 115 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 116 assert(clst != FAT_CLST_BAD); 117 rc = block_put(b); 118 if (rc != EOK) 119 return rc; 111 120 clusters++; 112 121 } 113 122 114 if (lastc && clst < clst_last1)123 if (lastc && clst < FAT_CLST_LAST1) 115 124 *lastc = clst; 116 125 if (numc) … … 142 151 return ELIMIT; 143 152 144 if ( !FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)153 if (nodep->firstc == FAT_CLST_ROOT) 145 154 goto fall_through; 146 155 … … 169 178 if (rc != EOK) 170 179 return rc; 171 180 172 181 /* 173 182 * Update the "current" cluster cache. … … 189 198 * @param clp If not NULL, address where the cluster containing bn 190 199 * will be stored. 191 * stored 200 * stored 192 201 * @param bn Block number. 193 202 * @param flags Flags passed to libblock. … … 199 208 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 200 209 { 201 uint 32_t clusters;202 u int32_tmax_clusters;210 uint16_t clusters; 211 unsigned max_clusters; 203 212 fat_cluster_t c; 204 213 int rc; … … 210 219 return ELIMIT; 211 220 212 if ( !FAT_IS_FAT32(bs) &&fcl == FAT_CLST_ROOT) {221 if (fcl == FAT_CLST_ROOT) { 213 222 /* root directory special case */ 214 223 assert(bn < RDS(bs)); … … 266 275 return rc; 267 276 } 268 277 269 278 if (o >= pos) 270 279 return EOK; 271 280 272 281 /* zero out the initial part of the new cluster chain */ 273 282 for (o = boundary; o < pos; o += BPS(bs)) { … … 286 295 } 287 296 288 /** Get cluster from the first FAT. FAT12 version297 /** Get cluster from the first FAT. 289 298 * 290 299 * @param bs Buffer holding the boot sector for the file system. … … 296 305 */ 297 306 int 298 fat_get_cluster _fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,307 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno, 299 308 fat_cluster_t clst, fat_cluster_t *value) 300 309 { 301 block_t *b, *b1; 302 uint16_t byte1, byte2; 303 aoff64_t offset; 304 int rc; 305 306 offset = (clst + clst/2); 307 if (offset / BPS(bs) >= SF(bs)) 308 return ERANGE; 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 309 313 310 314 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 311 offset/ BPS(bs), BLOCK_FLAGS_NONE);315 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 312 316 if (rc != EOK) 313 317 return rc; 314 315 byte1 = ((uint8_t*) b->data)[offset % BPS(bs)]; 316 /* This cluster access spans a sector boundary. Check only for FAT12 */ 317 if ((offset % BPS(bs)) + 1 == BPS(bs)) { 318 /* Is it last sector of FAT? */ 319 if (offset / BPS(bs) < SF(bs)) { 320 /* No. Reading next sector */ 321 rc = block_get(&b1, service_id, 1 + RSCNT(bs) + 322 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE); 323 if (rc != EOK) { 324 block_put(b); 325 return rc; 326 } 327 /* 328 * Combining value with last byte of current sector and 329 * first byte of next sector 330 */ 331 byte2 = ((uint8_t*) b1->data)[0]; 332 333 rc = block_put(b1); 334 if (rc != EOK) { 335 block_put(b); 336 return rc; 337 } 338 } 339 else { 340 /* Yes. It is last sector of FAT */ 341 block_put(b); 342 return ERANGE; 343 } 344 } 345 else 346 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1]; 347 348 *value = uint16_t_le2host(byte1 | (byte2 << 8)); 349 if (IS_ODD(clst)) 350 *value = (*value) >> 4; 351 else 352 *value = (*value) & FAT12_MASK; 318 cp = (fat_cluster_t *)b->data + 319 clst % (BPS(bs) / sizeof(fat_cluster_t)); 320 *value = uint16_t_le2host(*cp); 321 rc = block_put(b); 353 322 354 rc = block_put(b);355 return rc;356 }357 358 /** Get cluster from the first FAT. FAT16 version359 *360 * @param bs Buffer holding the boot sector for the file system.361 * @param service_id Service ID for the file system.362 * @param clst Cluster which to get.363 * @param value Output argument holding the value of the cluster.364 *365 * @return EOK or a negative error code.366 */367 int368 fat_get_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,369 fat_cluster_t clst, fat_cluster_t *value)370 {371 block_t *b;372 aoff64_t offset;373 int rc;374 375 offset = (clst * FAT16_CLST_SIZE);376 377 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +378 offset / BPS(bs), BLOCK_FLAGS_NONE);379 if (rc != EOK)380 return rc;381 382 *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));383 384 rc = block_put(b);385 386 return rc;387 }388 389 /** Get cluster from the first FAT. FAT32 version390 *391 * @param bs Buffer holding the boot sector for the file system.392 * @param service_id Service ID for the file system.393 * @param clst Cluster which to get.394 * @param value Output argument holding the value of the cluster.395 *396 * @return EOK or a negative error code.397 */398 int399 fat_get_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,400 fat_cluster_t clst, fat_cluster_t *value)401 {402 block_t *b;403 aoff64_t offset;404 int rc;405 406 offset = (clst * FAT32_CLST_SIZE);407 408 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +409 offset / BPS(bs), BLOCK_FLAGS_NONE);410 if (rc != EOK)411 return rc;412 413 *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & FAT32_MASK;414 415 rc = block_put(b);416 417 return rc;418 }419 420 421 /** Get cluster from the first FAT.422 *423 * @param bs Buffer holding the boot sector for the file system.424 * @param service_id Service ID for the file system.425 * @param clst Cluster which to get.426 * @param value Output argument holding the value of the cluster.427 *428 * @return EOK or a negative error code.429 */430 int431 fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,432 fat_cluster_t clst, fat_cluster_t *value)433 {434 int rc;435 436 assert(fatno < FATCNT(bs));437 438 if (FAT_IS_FAT12(bs)) {439 rc = fat_get_cluster_fat12(bs, service_id, fatno, clst, value);440 }441 else {442 if (FAT_IS_FAT32(bs))443 rc = fat_get_cluster_fat32(bs, service_id, fatno, clst, value);444 else445 rc = fat_get_cluster_fat16(bs, service_id, fatno, clst, value);446 }447 448 return rc;449 }450 451 /** Set cluster in one instance of FAT. FAT12 version.452 *453 * @param bs Buffer holding the boot sector for the file system.454 * @param service_id Service ID for the file system.455 * @param fatno Number of the FAT instance where to make the change.456 * @param clst Cluster which is to be set.457 * @param value Value to set the cluster with.458 *459 * @return EOK on success or a negative error code.460 */461 int462 fat_set_cluster_fat12(fat_bs_t *bs, service_id_t service_id, unsigned fatno,463 fat_cluster_t clst, fat_cluster_t value)464 {465 block_t *b, *b1=NULL;466 aoff64_t offset;467 uint16_t byte1, byte2;468 int rc;469 470 offset = (clst + clst/2);471 if (offset / BPS(bs) >= SF(bs))472 return ERANGE;473 474 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +475 offset / BPS(bs), BLOCK_FLAGS_NONE);476 if (rc != EOK)477 return rc;478 479 byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];480 bool border = false;481 /* This cluster access spans a sector boundary. Check only for FAT12 */482 if ((offset % BPS(bs))+1 == BPS(bs)) {483 /* Is it last sector of FAT? */484 if (offset / BPS(bs) < SF(bs)) {485 /* No. Reading next sector */486 rc = block_get(&b1, service_id, 1 + RSCNT(bs) +487 SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);488 if (rc != EOK) {489 block_put(b);490 return rc;491 }492 /*493 * Combining value with last byte of current sector and494 * first byte of next sector495 */496 byte2 = ((uint8_t*) b1->data)[0];497 border = true;498 }499 else {500 /* Yes. It is last sector of fat */501 block_put(b);502 return ERANGE;503 }504 }505 else506 byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];507 508 if (IS_ODD(clst)) {509 byte1 &= 0x0f;510 byte2 = 0;511 value = (value << 4);512 } else {513 byte1 = 0;514 byte2 &= 0xf0;515 value &= FAT12_MASK;516 }517 518 byte1 = byte1 | (value & 0xff);519 byte2 = byte2 | (value >> 8);520 521 ((uint8_t*) b->data)[(offset % BPS(bs))] = byte1;522 if (border) {523 ((uint8_t*) b1->data)[0] = byte2;524 525 b1->dirty = true;526 rc = block_put(b1);527 if (rc != EOK) {528 block_put(b);529 return rc;530 }531 } else532 ((uint8_t*) b->data)[(offset % BPS(bs))+1] = byte2;533 534 b->dirty = true; /* need to sync block */535 rc = block_put(b);536 return rc;537 }538 539 /** Set cluster in one instance of FAT. FAT16 version.540 *541 * @param bs Buffer holding the boot sector for the file system.542 * @param service_id Service ID for the file system.543 * @param fatno Number of the FAT instance where to make the change.544 * @param clst Cluster which is to be set.545 * @param value Value to set the cluster with.546 *547 * @return EOK on success or a negative error code.548 */549 int550 fat_set_cluster_fat16(fat_bs_t *bs, service_id_t service_id, unsigned fatno,551 fat_cluster_t clst, fat_cluster_t value)552 {553 block_t *b;554 aoff64_t offset;555 int rc;556 557 offset = (clst * FAT16_CLST_SIZE);558 559 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +560 offset / BPS(bs), BLOCK_FLAGS_NONE);561 if (rc != EOK)562 return rc;563 564 *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);565 566 b->dirty = true; /* need to sync block */567 rc = block_put(b);568 return rc;569 }570 571 /** Set cluster in one instance of FAT. FAT32 version.572 *573 * @param bs Buffer holding the boot sector for the file system.574 * @param service_id Service ID for the file system.575 * @param fatno Number of the FAT instance where to make the change.576 * @param clst Cluster which is to be set.577 * @param value Value to set the cluster with.578 *579 * @return EOK on success or a negative error code.580 */581 int582 fat_set_cluster_fat32(fat_bs_t *bs, service_id_t service_id, unsigned fatno,583 fat_cluster_t clst, fat_cluster_t value)584 {585 block_t *b;586 aoff64_t offset;587 int rc;588 fat_cluster_t temp;589 590 offset = (clst * FAT32_CLST_SIZE);591 592 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +593 offset / BPS(bs), BLOCK_FLAGS_NONE);594 if (rc != EOK)595 return rc;596 597 temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));598 temp &= 0xf0000000;599 temp |= (value & FAT32_MASK);600 *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);601 602 b->dirty = true; /* need to sync block */603 rc = block_put(b);604 323 return rc; 605 324 } … … 619 338 fat_cluster_t clst, fat_cluster_t value) 620 339 { 340 block_t *b; 341 fat_cluster_t *cp; 621 342 int rc; 622 343 623 344 assert(fatno < FATCNT(bs)); 624 625 if (FAT_IS_FAT12(bs)) 626 rc = fat_set_cluster_fat12(bs, service_id, fatno, clst, value); 627 else if (FAT_IS_FAT32(bs)) 628 rc = fat_set_cluster_fat32(bs, service_id, fatno, clst, value); 629 else 630 rc = fat_set_cluster_fat16(bs, service_id, fatno, clst, value); 631 345 rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno + 346 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 347 if (rc != EOK) 348 return rc; 349 cp = (fat_cluster_t *)b->data + 350 clst % (BPS(bs) / sizeof(fat_cluster_t)); 351 *cp = host2uint16_t_le(value); 352 b->dirty = true; /* need to sync block */ 353 rc = block_put(b); 632 354 return rc; 633 355 } … … 647 369 uint8_t fatno; 648 370 unsigned c; 649 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 650 int rc; 651 652 for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) { 371 int rc; 372 373 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 653 374 for (c = 0; c < nclsts; c++) { 654 375 rc = fat_set_cluster(bs, service_id, fatno, lifo[c], 655 c == 0 ? clst_last1 : lifo[c - 1]);376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]); 656 377 if (rc != EOK) 657 378 return rc; … … 683 404 fat_cluster_t *mcl, fat_cluster_t *lcl) 684 405 { 685 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 686 unsigned found = 0; /* top of the free cluster number stack */ 687 fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs); 688 int rc = EOK; 406 block_t *blk; 407 fat_cluster_t *lifo; /* stack for storing free cluster numbers */ 408 unsigned found = 0; /* top of the free cluster number stack */ 409 unsigned b, c, cl; 410 int rc; 689 411 690 412 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 691 413 if (!lifo) 692 414 return ENOMEM; 415 693 416 /* 694 417 * Search FAT1 for unused clusters. 695 418 */ 696 419 fibril_mutex_lock(&fat_alloc_lock); 697 for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) { 698 rc = fat_get_cluster(bs, service_id, FAT1, clst, &value); 699 if (rc != EOK) 700 break; 701 702 if (value == FAT_CLST_RES0) { 703 /* 704 * The cluster is free. Put it into our stack 705 * of found clusters and mark it as non-free. 706 */ 707 lifo[found] = clst; 708 rc = fat_set_cluster(bs, service_id, FAT1, clst, 709 (found == 0) ? clst_last1 : lifo[found - 1]); 710 if (rc != EOK) 711 break; 712 713 found++; 420 for (b = 0, cl = 0; b < SF(bs); b++) { 421 rc = block_get(&blk, service_id, RSCNT(bs) + b, 422 BLOCK_FLAGS_NONE); 423 if (rc != EOK) 424 goto error; 425 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) { 426 /* 427 * Check if the entire cluster is physically there. 428 * This check becomes necessary when the file system is 429 * created with fewer total sectors than how many is 430 * inferred from the size of the file allocation table 431 * or when the last cluster ends beyond the end of the 432 * device. 433 */ 434 if ((cl >= FAT_CLST_FIRST) && 435 CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) { 436 rc = block_put(blk); 437 if (rc != EOK) 438 goto error; 439 goto out; 440 } 441 442 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; 443 if (uint16_t_le2host(*clst) == FAT_CLST_RES0) { 444 /* 445 * The cluster is free. Put it into our stack 446 * of found clusters and mark it as non-free. 447 */ 448 lifo[found] = cl; 449 *clst = (found == 0) ? 450 host2uint16_t_le(FAT_CLST_LAST1) : 451 host2uint16_t_le(lifo[found - 1]); 452 blk->dirty = true; /* need to sync block */ 453 if (++found == nclsts) { 454 /* we are almost done */ 455 rc = block_put(blk); 456 if (rc != EOK) 457 goto error; 458 /* update the shadow copies of FAT */ 459 rc = fat_alloc_shadow_clusters(bs, 460 service_id, lifo, nclsts); 461 if (rc != EOK) 462 goto error; 463 *mcl = lifo[found - 1]; 464 *lcl = lifo[0]; 465 free(lifo); 466 fibril_mutex_unlock(&fat_alloc_lock); 467 return EOK; 468 } 469 } 714 470 } 715 } 716 717 if (rc == EOK && found == nclsts) { 718 rc = fat_alloc_shadow_clusters(bs, service_id, lifo, nclsts); 719 if (rc == EOK) { 720 *mcl = lifo[found - 1]; 721 *lcl = lifo[0]; 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 474 fibril_mutex_unlock(&fat_alloc_lock); 722 475 free(lifo); 723 fibril_mutex_unlock(&fat_alloc_lock); 724 return EOK; 476 return rc; 725 477 } 726 478 } 727 728 /* If something wrong - free the clusters */ 729 if (found > 0) { 730 while (found--) { 479 out: 480 fibril_mutex_unlock(&fat_alloc_lock); 481 482 /* 483 * We could not find enough clusters. Now we need to free the clusters 484 * we have allocated so far. 485 */ 486 while (found--) { 731 487 rc = fat_set_cluster(bs, service_id, FAT1, lifo[found], 732 488 FAT_CLST_RES0); 489 if (rc != EOK) { 490 free(lifo); 491 return rc; 733 492 } 734 493 } 735 494 736 495 free(lifo); 737 fibril_mutex_unlock(&fat_alloc_lock);738 496 return ENOSPC; 739 497 } … … 751 509 { 752 510 unsigned fatno; 753 fat_cluster_t nextc , clst_bad = FAT_CLST_BAD(bs);511 fat_cluster_t nextc; 754 512 int rc; 755 513 756 514 /* Mark all clusters in the chain as free in all copies of FAT. */ 757 while (firstc < FAT_CLST_LAST1 (bs)) {758 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);515 while (firstc < FAT_CLST_LAST1) { 516 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD); 759 517 rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc); 760 518 if (rc != EOK) 761 519 return rc; 762 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 763 521 rc = fat_set_cluster(bs, service_id, fatno, firstc, 764 522 FAT_CLST_RES0); … … 806 564 } 807 565 808 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {809 rc = fat_set_cluster(bs, nodep->idx->service_id, 810 fatno,lastc, mcl);566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 567 rc = fat_set_cluster(bs, nodep->idx->service_id, fatno, 568 lastc, mcl); 811 569 if (rc != EOK) 812 570 return rc; … … 832 590 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 833 591 { 834 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);835 592 int rc; 836 593 service_id_t service_id = nodep->idx->service_id; … … 859 616 860 617 /* Terminate the cluster chain in all copies of FAT. */ 861 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) { 862 619 rc = fat_set_cluster(bs, service_id, fatno, lcl, 863 clst_last1);620 FAT_CLST_LAST1); 864 621 if (rc != EOK) 865 622 return rc; … … 916 673 917 674 /* Check number of FATs. */ 918 if ( FATCNT(bs)== 0)675 if (bs->fatcnt == 0) 919 676 return ENOTSUP; 920 677 921 678 /* Check total number of sectors. */ 922 if (TS(bs) == 0) 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 923 681 return ENOTSUP; 924 682 925 683 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 926 bs->totsec16 != bs->totsec32) 684 bs->totsec16 != bs->totsec32) 927 685 return ENOTSUP; 928 686 … … 932 690 933 691 /* Check number of sectors per FAT. */ 934 if ( SF(bs)== 0)692 if (bs->sec_per_fat == 0) 935 693 return ENOTSUP; 936 694 … … 942 700 * sanitized to support file systems with this property. 943 701 */ 944 if (!FAT_IS_FAT32(bs) && (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0) 702 if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) % 703 uint16_t_le2host(bs->bps) != 0) 945 704 return ENOTSUP; 946 705 947 706 /* Check signature of each FAT. */ 948 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 707 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 949 709 rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0); 950 710 if (rc != EOK) … … 963 723 * set to one. 964 724 */ 965 if (!FAT_IS_FAT12(bs) && 966 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 967 726 return ENOTSUP; 968 727 } … … 973 732 /** 974 733 * @} 975 */ 734 */ -
uspace/srv/fs/fat/fat_fat.h
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 30 29 /** @addtogroup fs 31 30 * @{ 32 */ 31 */ 33 32 34 33 #ifndef FAT_FAT_FAT_H_ … … 41 40 #define FAT1 0 42 41 43 #define FAT_CLST_RES0 0 44 #define FAT_CLST_RES1 1 45 #define FAT_CLST_FIRST 2 46 47 #define FAT32_CLST_BAD 0x0ffffff7 48 #define FAT32_CLST_LAST1 0x0ffffff8 49 #define FAT32_CLST_LAST8 0x0fffffff 50 51 #define FAT12_MASK 0x0fff 52 #define FAT16_MASK 0xffff 53 #define FAT32_MASK 0x0fffffff 54 55 #define FAT12_CLST_MAX 4085 56 #define FAT16_CLST_MAX 65525 57 58 /* Size in bytes for cluster value of FAT */ 59 #define FAT12_CLST_SIZE 2 60 #define FAT16_CLST_SIZE 2 61 #define FAT32_CLST_SIZE 4 42 #define FAT_CLST_RES0 0x0000 43 #define FAT_CLST_RES1 0x0001 44 #define FAT_CLST_FIRST 0x0002 45 #define FAT_CLST_BAD 0xfff7 46 #define FAT_CLST_LAST1 0xfff8 47 #define FAT_CLST_LAST8 0xffff 62 48 63 49 /* internally used to mark root directory's parent */ … … 66 52 #define FAT_CLST_ROOT FAT_CLST_RES1 67 53 68 /*69 * Convenience macros for computing some frequently used values from the70 * primitive boot sector members.71 */72 #define RDS(bs) ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \73 (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)74 #define SSA(bs) (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))75 #define DS(bs) (TS(bs) - SSA(bs))76 #define CC(bs) (DS(bs) / SPC(bs))77 78 #define FAT_IS_FAT12(bs) (CC(bs) < FAT12_CLST_MAX)79 #define FAT_IS_FAT16(bs) \80 ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))81 #define FAT_IS_FAT32(bs) (CC(bs) >= FAT16_CLST_MAX)82 83 #define FAT_CLST_SIZE(bs) \84 (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)85 86 #define FAT_MASK(bs) \87 (FAT_IS_FAT12(bs) ? FAT12_MASK : \88 (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))89 90 #define FAT_CLST_LAST1(bs) (FAT32_CLST_LAST1 & FAT_MASK((bs)))91 #define FAT_CLST_LAST8(bs) (FAT32_CLST_LAST8 & FAT_MASK((bs)))92 #define FAT_CLST_BAD(bs) (FAT32_CLST_BAD & FAT_MASK((bs)))93 94 #define FAT_ROOT_CLST(bs) \95 (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \96 FAT_CLST_ROOT)97 98 54 /* forward declarations */ 99 55 struct block; … … 101 57 struct fat_bs; 102 58 103 typedef uint 32_t fat_cluster_t;59 typedef uint16_t fat_cluster_t; 104 60 105 #define fat_clusters_get(numc, bs, sid, fc) \106 fat_cluster_walk((bs), ( sid), (fc), NULL, (numc), (uint32_t) -1)61 #define fat_clusters_get(numc, bs, dh, fc) \ 62 fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1) 107 63 extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t, 108 fat_cluster_t *, uint 32_t *, uint32_t);64 fat_cluster_t *, uint16_t *, uint16_t); 109 65 110 66 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *, … … 122 78 extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t, 123 79 fat_cluster_t *, unsigned); 124 extern int fat_get_cluster_fat12(struct fat_bs *, service_id_t, unsigned,125 fat_cluster_t, fat_cluster_t *);126 extern int fat_get_cluster_fat16(struct fat_bs *, service_id_t, unsigned,127 fat_cluster_t, fat_cluster_t *);128 extern int fat_get_cluster_fat32(struct fat_bs *, service_id_t, unsigned,129 fat_cluster_t, fat_cluster_t *);130 80 extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned, 131 81 fat_cluster_t, fat_cluster_t *); 132 extern int fat_set_cluster_fat12(struct fat_bs *, service_id_t, unsigned,133 fat_cluster_t, fat_cluster_t);134 extern int fat_set_cluster_fat16(struct fat_bs *, service_id_t, unsigned,135 fat_cluster_t, fat_cluster_t);136 extern int fat_set_cluster_fat32(struct fat_bs *, service_id_t, unsigned,137 fat_cluster_t, fat_cluster_t);138 82 extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned, 139 83 fat_cluster_t, fat_cluster_t); -
uspace/srv/fs/fat/fat_ops.c
r375ab5e r7fadb65 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko4 3 * All rights reserved. 5 4 * … … 30 29 /** @addtogroup fs 31 30 * @{ 32 */ 31 */ 33 32 34 33 /** … … 40 39 #include "fat_dentry.h" 41 40 #include "fat_fat.h" 42 #include "fat_directory.h"43 41 #include "../../vfs/vfs.h" 44 42 #include <libfs.h> … … 58 56 #include <align.h> 59 57 #include <malloc.h> 60 #include <str.h>61 58 62 59 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 107 104 node->dirty = false; 108 105 node->lastc_cached_valid = false; 109 node->lastc_cached_value = 0;106 node->lastc_cached_value = FAT_CLST_LAST1; 110 107 node->currc_cached_valid = false; 111 108 node->currc_cached_bn = 0; 112 node->currc_cached_value = 0;109 node->currc_cached_value = FAT_CLST_LAST1; 113 110 } 114 111 … … 119 116 fat_dentry_t *d; 120 117 int rc; 121 118 122 119 assert(node->dirty); 123 120 124 121 bs = block_bb_get(node->idx->service_id); 125 122 126 123 /* Read the block that contains the dentry of interest. */ 127 124 rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc, … … 139 136 d->attr = FAT_ATTR_SUBDIR; 140 137 } 141 138 142 139 /* TODO: update other fields? (e.g time fields) */ 143 140 144 141 b->dirty = true; /* need to sync block */ 145 142 rc = block_put(b); … … 258 255 fn->data = nodep; 259 256 nodep->bp = fn; 260 257 261 258 *nodepp = nodep; 262 259 return EOK; … … 294 291 * We must instantiate the node from the file system. 295 292 */ 296 293 297 294 assert(idxp->pfc); 298 295 … … 312 309 313 310 d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs)); 314 if (FAT_IS_FAT32(bs)) {315 nodep->firstc = uint16_t_le2host(d->firstc_lo) |316 (uint16_t_le2host(d->firstc_hi) << 16);317 }318 else319 nodep->firstc = uint16_t_le2host(d->firstc);320 321 311 if (d->attr & FAT_ATTR_SUBDIR) { 322 /* 312 /* 323 313 * The only directory which does not have this bit set is the 324 314 * root directory itself. The root directory node is handled … … 326 316 */ 327 317 nodep->type = FAT_DIRECTORY; 328 329 318 /* 330 319 * Unfortunately, the 'size' field of the FAT dentry is not … … 332 321 * size of the directory by walking the FAT. 333 322 */ 334 uint32_t clusters; 335 rc = fat_clusters_get(&clusters, bs, idxp->service_id, nodep->firstc); 323 uint16_t clusters; 324 rc = fat_clusters_get(&clusters, bs, idxp->service_id, 325 uint16_t_le2host(d->firstc)); 336 326 if (rc != EOK) { 337 327 (void) block_put(b); … … 344 334 nodep->size = uint32_t_le2host(d->size); 345 335 } 346 336 nodep->firstc = uint16_t_le2host(d->firstc); 347 337 nodep->lnkcnt = 1; 348 338 nodep->refcnt = 1; … … 373 363 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 374 364 { 365 fat_bs_t *bs; 375 366 fat_node_t *parentp = FAT_NODE(pfn); 376 char name[FAT_LFN_NAME_SIZE]; 367 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 368 unsigned i, j; 369 unsigned blocks; 377 370 fat_dentry_t *d; 378 371 service_id_t service_id; 372 block_t *b; 379 373 int rc; 380 374 … … 382 376 service_id = parentp->idx->service_id; 383 377 fibril_mutex_unlock(&parentp->idx->lock); 384 385 fat_directory_t di; 386 rc = fat_directory_open(parentp, &di); 387 if (rc != EOK) 388 return rc; 389 390 while (fat_directory_read(&di, name, &d) == EOK) { 391 if (fat_dentry_namecmp(name, component) == 0) { 392 /* hit */ 393 fat_node_t *nodep; 394 aoff64_t o = di.pos % (BPS(di.bs) / sizeof(fat_dentry_t)); 395 fat_idx_t *idx = fat_idx_get_by_pos(service_id, 396 parentp->firstc, di.bnum * DPS(di.bs) + o); 397 if (!idx) { 398 /* 399 * Can happen if memory is low or if we 400 * run out of 32-bit indices. 401 */ 402 rc = fat_directory_close(&di); 403 return (rc == EOK) ? ENOMEM : rc; 378 379 bs = block_bb_get(service_id); 380 blocks = parentp->size / BPS(bs); 381 for (i = 0; i < blocks; i++) { 382 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 383 if (rc != EOK) 384 return rc; 385 for (j = 0; j < DPS(bs); j++) { 386 d = ((fat_dentry_t *)b->data) + j; 387 switch (fat_classify_dentry(d)) { 388 case FAT_DENTRY_SKIP: 389 case FAT_DENTRY_FREE: 390 continue; 391 case FAT_DENTRY_LAST: 392 /* miss */ 393 rc = block_put(b); 394 *rfn = NULL; 395 return rc; 396 default: 397 case FAT_DENTRY_VALID: 398 fat_dentry_name_get(d, name); 399 break; 404 400 } 405 rc = fat_node_get_core(&nodep, idx); 406 fibril_mutex_unlock(&idx->lock); 407 if (rc != EOK) { 408 (void) fat_directory_close(&di); 401 if (fat_dentry_namecmp(name, component) == 0) { 402 /* hit */ 403 fat_node_t *nodep; 404 fat_idx_t *idx = fat_idx_get_by_pos(service_id, 405 parentp->firstc, i * DPS(bs) + j); 406 if (!idx) { 407 /* 408 * Can happen if memory is low or if we 409 * run out of 32-bit indices. 410 */ 411 rc = block_put(b); 412 return (rc == EOK) ? ENOMEM : rc; 413 } 414 rc = fat_node_get_core(&nodep, idx); 415 fibril_mutex_unlock(&idx->lock); 416 if (rc != EOK) { 417 (void) block_put(b); 418 return rc; 419 } 420 *rfn = FS_NODE(nodep); 421 rc = block_put(b); 422 if (rc != EOK) 423 (void) fat_node_put(*rfn); 409 424 return rc; 410 425 } 411 *rfn = FS_NODE(nodep); 412 rc = fat_directory_close(&di); 413 if (rc != EOK) 414 (void) fat_node_put(*rfn); 415 return rc; 416 } else { 417 rc = fat_directory_next(&di); 418 if (rc != EOK) 419 break; 420 } 421 } 422 (void) fat_directory_close(&di); 426 } 427 rc = block_put(b); 428 if (rc != EOK) 429 return rc; 430 } 431 423 432 *rfn = NULL; 424 433 return EOK; … … 582 591 fat_bs_t *bs; 583 592 block_t *b; 584 fat_directory_t di; 585 fat_dentry_t de; 593 unsigned i, j; 594 unsigned blocks; 595 fat_cluster_t mcl, lcl; 586 596 int rc; 587 597 … … 597 607 fibril_mutex_unlock(&childp->lock); 598 608 599 if (!fat_valid_name(name)) 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 600 613 return ENOTSUP; 601 614 } 615 616 /* 617 * Get us an unused parent node's dentry or grow the parent and allocate 618 * a new one. 619 */ 620 602 621 fibril_mutex_lock(&parentp->idx->lock); 603 622 bs = block_bb_get(parentp->idx->service_id); 604 rc = fat_directory_open(parentp, &di); 605 if (rc != EOK) 606 return rc; 607 623 624 blocks = parentp->size / BPS(bs); 625 626 for (i = 0; i < blocks; i++) { 627 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 628 if (rc != EOK) { 629 fibril_mutex_unlock(&parentp->idx->lock); 630 return rc; 631 } 632 for (j = 0; j < DPS(bs); j++) { 633 d = ((fat_dentry_t *)b->data) + j; 634 switch (fat_classify_dentry(d)) { 635 case FAT_DENTRY_SKIP: 636 case FAT_DENTRY_VALID: 637 /* skipping used and meta entries */ 638 continue; 639 case FAT_DENTRY_FREE: 640 case FAT_DENTRY_LAST: 641 /* found an empty slot */ 642 goto hit; 643 } 644 } 645 rc = block_put(b); 646 if (rc != EOK) { 647 fibril_mutex_unlock(&parentp->idx->lock); 648 return rc; 649 } 650 } 651 j = 0; 652 653 /* 654 * We need to grow the parent in order to create a new unused dentry. 655 */ 656 if (parentp->firstc == FAT_CLST_ROOT) { 657 /* Can't grow the root directory. */ 658 fibril_mutex_unlock(&parentp->idx->lock); 659 return ENOSPC; 660 } 661 rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl); 662 if (rc != EOK) { 663 fibril_mutex_unlock(&parentp->idx->lock); 664 return rc; 665 } 666 rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl); 667 if (rc != EOK) { 668 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl); 669 fibril_mutex_unlock(&parentp->idx->lock); 670 return rc; 671 } 672 rc = fat_append_clusters(bs, parentp, mcl, lcl); 673 if (rc != EOK) { 674 (void) fat_free_clusters(bs, parentp->idx->service_id, mcl); 675 fibril_mutex_unlock(&parentp->idx->lock); 676 return rc; 677 } 678 parentp->size += BPS(bs) * SPC(bs); 679 parentp->dirty = true; /* need to sync node */ 680 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 681 if (rc != EOK) { 682 fibril_mutex_unlock(&parentp->idx->lock); 683 return rc; 684 } 685 d = (fat_dentry_t *)b->data; 686 687 hit: 608 688 /* 609 689 * At this point we only establish the link between the parent and the … … 612 692 * dentry data is kept in the child node structure. 613 693 */ 614 memset(&de, 0, sizeof(fat_dentry_t)); 615 616 rc = fat_directory_write(&di, name, &de); 617 if (rc!=EOK) 618 return rc; 619 rc = fat_directory_close(&di); 620 if (rc!=EOK) 621 return rc; 622 694 memset(d, 0, sizeof(fat_dentry_t)); 695 fat_dentry_name_set(d, name); 696 b->dirty = true; /* need to sync block */ 697 rc = block_put(b); 623 698 fibril_mutex_unlock(&parentp->idx->lock); 624 if (rc != EOK) 699 if (rc != EOK) 625 700 return rc; 626 701 627 702 fibril_mutex_lock(&childp->idx->lock); 628 703 629 704 if (childp->type == FAT_DIRECTORY) { 630 705 /* … … 645 720 d = (fat_dentry_t *) b->data; 646 721 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 647 ( bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {722 (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) { 648 723 memset(d, 0, sizeof(fat_dentry_t)); 649 724 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 655 730 d++; 656 731 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 657 ( bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {732 (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) { 658 733 memset(d, 0, sizeof(fat_dentry_t)); 659 734 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 660 735 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 661 736 d->attr = FAT_ATTR_SUBDIR; 662 d->firstc = (parentp->firstc == FAT_ ROOT_CLST(bs)) ?663 host2uint16_t_le(FAT_CLST_R OOTPAR) :737 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 738 host2uint16_t_le(FAT_CLST_RES0) : 664 739 host2uint16_t_le(parentp->firstc); 665 740 /* TODO: initialize also the date/time members. */ … … 675 750 676 751 childp->idx->pfc = parentp->firstc; 677 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */752 childp->idx->pdi = i * DPS(bs) + j; 678 753 fibril_mutex_unlock(&childp->idx->lock); 679 754 … … 695 770 fat_node_t *parentp = FAT_NODE(pfn); 696 771 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs; 773 fat_dentry_t *d; 774 block_t *b; 697 775 bool has_children; 698 776 int rc; … … 700 778 if (!parentp) 701 779 return EBUSY; 702 780 703 781 rc = fat_has_children(&has_children, cfn); 704 782 if (rc != EOK) … … 711 789 assert(childp->lnkcnt == 1); 712 790 fibril_mutex_lock(&childp->idx->lock); 713 714 fat_directory_t di; 715 rc = fat_directory_open(parentp,&di); 716 if (rc != EOK) 791 bs = block_bb_get(childp->idx->service_id); 792 793 rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc, 794 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 795 BLOCK_FLAGS_NONE); 796 if (rc != EOK) 717 797 goto error; 718 rc = fat_directory_seek(&di, childp->idx->pdi); 719 if (rc != EOK) 720 goto error; 721 rc = fat_directory_erase(&di); 722 if (rc != EOK) 723 goto error; 724 rc = fat_directory_close(&di); 798 d = (fat_dentry_t *)b->data + 799 (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t))); 800 /* mark the dentry as not-currently-used */ 801 d->name[0] = FAT_DENTRY_ERASED; 802 b->dirty = true; /* need to sync block */ 803 rc = block_put(b); 725 804 if (rc != EOK) 726 805 goto error; … … 741 820 742 821 error: 743 (void) fat_directory_close(&di); 822 fibril_mutex_unlock(&parentp->idx->lock); 823 fibril_mutex_unlock(&childp->lock); 744 824 fibril_mutex_unlock(&childp->idx->lock); 745 fibril_mutex_unlock(&childp->lock);746 fibril_mutex_unlock(&parentp->lock);747 825 return rc; 748 826 } … … 761 839 return EOK; 762 840 } 763 841 764 842 fibril_mutex_lock(&nodep->idx->lock); 765 843 bs = block_bb_get(nodep->idx->service_id); … … 769 847 for (i = 0; i < blocks; i++) { 770 848 fat_dentry_t *d; 771 849 772 850 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 773 851 if (rc != EOK) { … … 797 875 if (rc != EOK) { 798 876 fibril_mutex_unlock(&nodep->idx->lock); 799 return rc; 877 return rc; 800 878 } 801 879 } … … 868 946 fat_bs_t *bs; 869 947 int rc; 870 948 871 949 /* Check for option enabling write through. */ 872 950 if (str_cmp(opts, "wtcache") == 0) … … 925 1003 return ENOMEM; 926 1004 } 927 928 1005 fs_node_initialize(rfn); 929 1006 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); … … 950 1027 951 1028 rootp->type = FAT_DIRECTORY; 952 rootp->firstc = FAT_ ROOT_CLST(bs);1029 rootp->firstc = FAT_CLST_ROOT; 953 1030 rootp->refcnt = 1; 954 1031 rootp->lnkcnt = 0; /* FS root is not linked */ 955 956 if (FAT_IS_FAT32(bs)) { 957 uint32_t clusters; 958 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc); 959 if (rc != EOK) { 960 free(rfn); 961 free(rootp); 962 (void) block_cache_fini(service_id); 963 block_fini(service_id); 964 fat_idx_fini_by_service_id(service_id); 965 return ENOTSUP; 966 } 967 rootp->size = BPS(bs) * SPC(bs) * clusters; 968 } else 969 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 970 1032 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 971 1033 rootp->idx = ridxp; 972 1034 ridxp->nodep = rootp; 973 1035 rootp->bp = rfn; 974 1036 rfn->data = rootp; 975 1037 976 1038 fibril_mutex_unlock(&ridxp->lock); 977 1039 … … 1002 1064 return EBUSY; 1003 1065 } 1004 1066 1005 1067 /* 1006 1068 * Put the root node and force it to the FAT free node list. … … 1079 1141 } 1080 1142 } else { 1143 unsigned bnum; 1081 1144 aoff64_t spos = pos; 1082 char name[FAT_ LFN_NAME_SIZE];1145 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 1083 1146 fat_dentry_t *d; 1084 1147 … … 1087 1150 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1088 1151 1089 fat_directory_t di; 1090 rc = fat_directory_open(nodep, &di); 1091 if (rc != EOK) goto err; 1092 rc = fat_directory_seek(&di, pos); 1093 if (rc != EOK) { 1094 (void) fat_directory_close(&di); 1095 goto err; 1096 } 1097 1098 rc = fat_directory_read(&di, name, &d); 1099 if (rc == EOK) goto hit; 1100 if (rc == ENOENT) goto miss; 1101 1102 err: 1103 (void) fat_node_put(fn); 1104 async_answer_0(callid, rc); 1105 return rc; 1106 1152 /* 1153 * Our strategy for readdir() is to use the position pointer as 1154 * an index into the array of all dentries. On entry, it points 1155 * to the first unread dentry. If we skip any dentries, we bump 1156 * the position pointer accordingly. 1157 */ 1158 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs); 1159 while (bnum < nodep->size / BPS(bs)) { 1160 aoff64_t o; 1161 1162 rc = fat_block_get(&b, bs, nodep, bnum, 1163 BLOCK_FLAGS_NONE); 1164 if (rc != EOK) 1165 goto err; 1166 for (o = pos % (BPS(bs) / sizeof(fat_dentry_t)); 1167 o < BPS(bs) / sizeof(fat_dentry_t); 1168 o++, pos++) { 1169 d = ((fat_dentry_t *)b->data) + o; 1170 switch (fat_classify_dentry(d)) { 1171 case FAT_DENTRY_SKIP: 1172 case FAT_DENTRY_FREE: 1173 continue; 1174 case FAT_DENTRY_LAST: 1175 rc = block_put(b); 1176 if (rc != EOK) 1177 goto err; 1178 goto miss; 1179 default: 1180 case FAT_DENTRY_VALID: 1181 fat_dentry_name_get(d, name); 1182 rc = block_put(b); 1183 if (rc != EOK) 1184 goto err; 1185 goto hit; 1186 } 1187 } 1188 rc = block_put(b); 1189 if (rc != EOK) 1190 goto err; 1191 bnum++; 1192 } 1107 1193 miss: 1108 rc = fat_directory_close(&di);1109 if (rc!=EOK)1110 goto err;1111 1194 rc = fat_node_put(fn); 1112 1195 async_answer_0(callid, rc != EOK ? rc : ENOENT); … … 1114 1197 return rc != EOK ? rc : ENOENT; 1115 1198 1199 err: 1200 (void) fat_node_put(fn); 1201 async_answer_0(callid, rc); 1202 return rc; 1203 1116 1204 hit: 1117 pos = di.pos;1118 rc = fat_directory_close(&di);1119 if (rc!=EOK)1120 goto err;1121 1205 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1122 bytes = (pos - spos) +1;1206 bytes = (pos - spos) + 1; 1123 1207 } 1124 1208 … … 1147 1231 return ENOENT; 1148 1232 nodep = FAT_NODE(fn); 1149 1233 1150 1234 ipc_callid_t callid; 1151 1235 size_t len; … … 1163 1247 * but this one greatly simplifies fat_write(). Note that we can afford 1164 1248 * to do this because the client must be ready to handle the return 1165 * value signalizing a smaller number of bytes written. 1166 */ 1249 * value signalizing a smaller number of bytes written. 1250 */ 1167 1251 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1168 1252 if (bytes == BPS(bs)) 1169 1253 flags |= BLOCK_FLAGS_NOREAD; 1170 1254 1171 1255 boundary = ROUND_UP(nodep->size, BPC(bs)); 1172 1256 if (pos < boundary) { … … 1211 1295 */ 1212 1296 unsigned nclsts; 1213 fat_cluster_t mcl, lcl; 1214 1297 fat_cluster_t mcl, lcl; 1298 1215 1299 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1216 1300 /* create an independent chain of nclsts clusters in all FATs */ … … 1296 1380 nodep->size = size; 1297 1381 nodep->dirty = true; /* need to sync node */ 1298 rc = EOK; 1382 rc = EOK; 1299 1383 } else { 1300 1384 /* … … 1317 1401 nodep->size = size; 1318 1402 nodep->dirty = true; /* need to sync node */ 1319 rc = EOK; 1403 rc = EOK; 1320 1404 } 1321 1405 out: … … 1360 1444 if (!fn) 1361 1445 return ENOENT; 1362 1446 1363 1447 fat_node_t *nodep = FAT_NODE(fn); 1364 1448 1365 1449 nodep->dirty = true; 1366 1450 rc = fat_node_sync(nodep); 1367 1451 1368 1452 fat_node_put(fn); 1369 1453 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.