Changes in / [3fab770:a33f0a6] in mainline
- Files:
-
- 26 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r3fab770 ra33f0a6 102 102 $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \ 103 103 $(USPACE_PATH)/srv/fs/fat/fat \ 104 $(USPACE_PATH)/srv/fs/exfat/exfat \ 104 105 $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \ 105 106 $(USPACE_PATH)/srv/taskmon/taskmon \ … … 147 148 $(USPACE_PATH)/app/dload/dload \ 148 149 $(USPACE_PATH)/app/edit/edit \ 150 $(USPACE_PATH)/app/filecrc/filecrc \ 151 $(USPACE_PATH)/app/filegen/filegen \ 149 152 $(USPACE_PATH)/app/ext2info/ext2info \ 150 153 $(USPACE_PATH)/app/kill/kill \ -
uspace/Makefile
r3fab770 ra33f0a6 38 38 app/bnchmark \ 39 39 app/edit \ 40 app/filecrc \ 41 app/filegen \ 40 42 app/ext2info \ 41 43 app/getterm \ … … 77 79 srv/bd/part/guid_part \ 78 80 srv/bd/part/mbr_part \ 81 srv/fs/exfat \ 79 82 srv/fs/fat \ 80 83 srv/fs/tmpfs \ -
uspace/lib/c/generic/str.c
r3fab770 ra33f0a6 2 2 * Copyright (c) 2005 Martin Decky 3 3 * Copyright (c) 2008 Jiri Svoboda 4 * Copyright (c) 2011 Oleg Romanenko 4 5 * All rights reserved. 5 6 * … … 366 367 } 367 368 369 /** Check whether wide string is plain ASCII. 370 * 371 * @return True if wide string is plain ASCII. 372 * 373 */ 374 bool wstr_is_ascii(const wchar_t *wstr) 375 { 376 while (*wstr && ascii_check(*wstr)) 377 wstr++; 378 return *wstr == 0; 379 } 380 368 381 /** Check whether character is valid 369 382 * … … 618 631 * @param size Size of the destination buffer. 619 632 * @param src Source wide string. 620 */ 621 void wstr_to_str(char *dest, size_t size, const wchar_t *src) 622 { 633 * 634 * @return EOK, if success, negative otherwise. 635 */ 636 int wstr_to_str(char *dest, size_t size, const wchar_t *src) 637 { 638 int rc; 623 639 wchar_t ch; 624 640 size_t src_idx; … … 632 648 633 649 while ((ch = src[src_idx++]) != 0) { 634 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 650 rc = chr_encode(ch, dest, &dest_off, size - 1); 651 if (rc != EOK) 635 652 break; 636 653 } 637 654 638 655 dest[dest_off] = '\0'; 639 } 656 return rc; 657 } 658 659 /** Convert UTF16 string to string. 660 * 661 * Convert utf16 string @a src to string. The output is written to the buffer 662 * specified by @a dest and @a size. @a size must be non-zero and the string 663 * written will always be well-formed. Surrogate pairs also supported. 664 * 665 * @param dest Destination buffer. 666 * @param size Size of the destination buffer. 667 * @param src Source utf16 string. 668 * 669 * @return EOK, if success, negative otherwise. 670 */ 671 int utf16_to_str(char *dest, size_t size, const uint16_t *src) 672 { 673 size_t idx=0, dest_off=0; 674 wchar_t ch; 675 int rc = EOK; 676 677 /* There must be space for a null terminator in the buffer. */ 678 assert(size > 0); 679 680 while (src[idx]) { 681 if ((src[idx] & 0xfc00) == 0xd800) { 682 if (src[idx+1] && (src[idx+1] & 0xfc00) == 0xdc00) { 683 ch = 0x10000; 684 ch += (src[idx] & 0x03FF) << 10; 685 ch += (src[idx+1] & 0x03FF); 686 idx += 2; 687 } 688 else 689 break; 690 } else { 691 ch = src[idx]; 692 idx++; 693 } 694 rc = chr_encode(ch, dest, &dest_off, size-1); 695 if (rc != EOK) 696 break; 697 } 698 dest[dest_off] = '\0'; 699 return rc; 700 } 701 702 int str_to_utf16(uint16_t *dest, size_t size, const char *src) 703 { 704 int rc=EOK; 705 size_t offset=0; 706 size_t idx=0; 707 wchar_t c; 708 709 assert(size > 0); 710 711 while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) { 712 if (c > 0x10000) { 713 if (idx+2 >= size-1) { 714 rc=EOVERFLOW; 715 break; 716 } 717 c = (c - 0x10000); 718 dest[idx] = 0xD800 | (c >> 10); 719 dest[idx+1] = 0xDC00 | (c & 0x3FF); 720 idx++; 721 } else { 722 dest[idx] = c; 723 } 724 725 idx++; 726 if (idx >= size-1) { 727 rc=EOVERFLOW; 728 break; 729 } 730 } 731 732 dest[idx] = '\0'; 733 return rc; 734 } 735 640 736 641 737 /** Convert wide string to new string. … … 697 793 * @param dlen Length of destination buffer (number of wchars). 698 794 * @param src Source string. 699 */ 700 void str_to_wstr(wchar_t *dest, size_t dlen, const char *src) 701 { 795 * 796 * @return EOK, if success, negative otherwise. 797 */ 798 int str_to_wstr(wchar_t *dest, size_t dlen, const char *src) 799 { 800 int rc=EOK; 702 801 size_t offset; 703 802 size_t di; … … 710 809 711 810 do { 712 if (di >= dlen - 1) 811 if (di >= dlen - 1) { 812 rc = EOVERFLOW; 713 813 break; 814 } 714 815 715 816 c = str_decode(src, &offset, STR_NO_LIMIT); … … 718 819 719 820 dest[dlen - 1] = '\0'; 821 return rc; 720 822 } 721 823 … … 763 865 764 866 return (char *) res; 867 } 868 869 /** Find first occurence of character in wide string. 870 * 871 * @param wstr String to search. 872 * @param ch Character to look for. 873 * 874 * @return Pointer to character in @a wstr or NULL if not found. 875 */ 876 wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch) 877 { 878 while (*wstr && *wstr != ch) 879 wstr++; 880 if (*wstr) 881 return (wchar_t *) wstr; 882 else 883 return NULL; 884 } 885 886 /** Find last occurence of character in wide string. 887 * 888 * @param wstr String to search. 889 * @param ch Character to look for. 890 * 891 * @return Pointer to character in @a wstr or NULL if not found. 892 */ 893 wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch) 894 { 895 const wchar_t *res = NULL; 896 while (*wstr) { 897 if (*wstr == ch) 898 res = wstr; 899 wstr++; 900 } 901 return (wchar_t *) res; 765 902 } 766 903 … … 1017 1154 } 1018 1155 1156 void str_reverse(char* begin, char* end) 1157 { 1158 char aux; 1159 while(end>begin) 1160 aux=*end, *end--=*begin, *begin++=aux; 1161 } 1162 1163 int size_t_str(size_t value, int base, char* str, size_t size) 1164 { 1165 static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1166 char* wstr=str; 1167 1168 if (size == 0) 1169 return EINVAL; 1170 if (base<2 || base>35) { 1171 *str='\0'; 1172 return EINVAL; 1173 } 1174 1175 do { 1176 *wstr++ = num[value % base]; 1177 if (--size == 0) 1178 return EOVERFLOW; 1179 } while(value /= base); 1180 *wstr='\0'; 1181 1182 // Reverse string 1183 str_reverse(str,wstr-1); 1184 return EOK; 1185 } 1019 1186 1020 1187 /** Convert initial part of string to unsigned long according to given base. -
uspace/lib/c/include/str.h
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2005 Martin Decky 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 71 72 extern bool ascii_check(wchar_t ch); 72 73 extern bool chr_check(wchar_t ch); 74 extern bool wstr_is_ascii(const wchar_t *wstr); 73 75 74 76 extern int str_cmp(const char *s1, const char *s2); … … 79 81 extern void str_append(char *dest, size_t size, const char *src); 80 82 83 extern int wstr_to_str(char *dest, size_t size, const wchar_t *src); 81 84 extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n); 82 85 extern void wstr_to_str(char *dest, size_t size, const wchar_t *src); 83 86 extern char *wstr_to_astr(const wchar_t *src); 84 extern void str_to_wstr(wchar_t *dest, size_t dlen, 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); 85 90 86 91 extern char *str_chr(const char *str, wchar_t ch); 87 92 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); 88 95 89 96 extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos); … … 92 99 extern char *str_dup(const char *); 93 100 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); 94 104 95 105 extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *); -
uspace/srv/fs/fat/Makefile
r3fab770 ra33f0a6 39 39 fat_idx.c \ 40 40 fat_dentry.c \ 41 fat_directory.c \ 41 42 fat_fat.c 42 43 -
uspace/srv/fs/fat/fat.c
r3fab770 ra33f0a6 2 2 * Copyright (c) 2006 Martin Decky 3 3 * Copyright (c) 2008 Jakub Jermar 4 * Copyright (c) 2011 Oleg Romanenko 4 5 * All rights reserved. 5 6 * -
uspace/srv/fs/fat/fat.h
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 55 56 #define RSCNT(bs) uint16_t_le2host((bs)->rscnt) 56 57 #define FATCNT(bs) (bs)->fatcnt 57 #define SF(bs) uint16_t_le2host((bs)->sec_per_fat) 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)) 58 61 #define RDE(bs) uint16_t_le2host((bs)->root_ent_max) 59 62 #define TS(bs) (uint16_t_le2host((bs)->totsec16) != 0 ? \ -
uspace/srv/fs/fat/fat_dentry.c
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 39 40 #include <ctype.h> 40 41 #include <str.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 } 42 #include <errno.h> 43 #include <byteorder.h> 44 #include <assert.h> 49 45 50 46 /** Compare path component with the name read from the dentry. … … 80 76 } 81 77 82 bool fat_dentry_name_verify(const char *name) 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_part(const uint16_t *src, size_t src_size, uint16_t *dst, size_t *offset) 269 { 270 while (src_size!=0 && (*offset)!=0) { 271 src_size--; 272 if (src[src_size] == 0 || src[src_size] == FAT_LFN_PAD) 273 continue; 274 275 (*offset)--; 276 dst[(*offset)] = uint16_t_le2host(src[src_size]); 277 } 278 return (*offset); 279 } 280 281 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset) 282 { 283 fat_lfn_get_part(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE, dst, offset); 284 fat_lfn_get_part(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE, dst, offset); 285 fat_lfn_get_part(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE, dst, offset); 286 287 return *offset; 288 } 289 290 size_t fat_lfn_set_part(const uint16_t *src, size_t *offset, size_t src_size, uint16_t *dst, size_t dst_size) 291 { 292 size_t idx; 293 for (idx=0; idx < dst_size; idx++) { 294 if (*offset < src_size) { 295 dst[idx] = uint16_t_le2host(src[*offset]); 296 (*offset)++; 297 } 298 else 299 dst[idx] = FAT_LFN_PAD; 300 } 301 return *offset; 302 } 303 304 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, fat_dentry_t *d) 305 { 306 fat_lfn_set_part(src, offset, size, FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE); 307 fat_lfn_set_part(src, offset, size, FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE); 308 fat_lfn_set_part(src, offset, size, FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE); 309 if (src[*offset] == 0) 310 offset++; 311 FAT_LFN_ATTR(d) = FAT_ATTR_LFN; 312 d->lfn.type = 0; 313 d->lfn.firstc_lo = 0; 314 315 return *offset; 316 } 317 318 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad) 319 { 320 wchar_t ch; 321 size_t off = 0; 322 size_t i = 0; 323 324 while (i < count) { 325 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) { 326 if (ascii_check(ch) & IS_D_CHAR(ch)) 327 *dst = toupper(ch); 328 else 329 *dst = pad; 330 } 331 else 332 break; 333 334 dst++; 335 i++; 336 } 337 *dst = '\0'; 338 } 339 340 bool fat_valid_name(const char *name) 341 { 342 wchar_t ch; 343 size_t offset=0; 344 bool result = true; 345 346 while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) { 347 if (wstr_chr(FAT_STOP_CHARS, ch) != NULL) { 348 result = false; 349 break; 350 } 351 } 352 return result; 353 } 354 355 bool fat_valid_short_name(const char *name) 83 356 { 84 357 unsigned int i; 85 358 unsigned int dot = 0; 86 359 bool dot_found = false; 87 88 360 89 361 for (i = 0; name[i]; i++) { … … 96 368 } 97 369 } else { 98 if (! is_d_char(name[i]))370 if (!IS_D_CHAR(name[i])) 99 371 return false; 100 372 } … … 114 386 } 115 387 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; 388 size_t utf16_length(const uint16_t *wstr) 389 { 390 size_t len = 0; 391 392 while (*wstr++ != 0) 393 len++; 394 395 return len; 240 396 } 241 397 -
uspace/srv/fs/fat/fat_dentry.h
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 37 38 #include <bool.h> 38 39 40 #define IS_D_CHAR(ch) (isalnum(ch) || ch == '_') 41 #define FAT_STOP_CHARS L"*?/\\\n\t|'" 42 39 43 #define FAT_NAME_LEN 8 40 44 #define FAT_EXT_LEN 3 … … 44 48 #define FAT_EXT_PAD " " 45 49 46 #define FAT_ATTR_RDONLY (1 << 0) 47 #define FAT_ATTR_VOLLABEL (1 << 3) 48 #define FAT_ATTR_SUBDIR (1 << 4) 49 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 50 59 #define FAT_LCASE_LOWER_NAME 0x08 51 60 #define FAT_LCASE_LOWER_EXT 0x10 52 61 53 #define FAT_PAD ' ' 62 #define FAT_PAD ' ' 63 #define FAT_LFN_PAD 0xffff 64 #define FAT_SFN_CHAR '_' 54 65 55 66 #define FAT_DENTRY_UNUSED 0x00 … … 57 68 #define FAT_DENTRY_DOT 0x2e 58 69 #define FAT_DENTRY_ERASED 0xe5 70 #define FAT_LFN_LAST 0x40 71 #define FAT_LFN_ERASED 0x80 72 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 260 85 #define FAT_LFN_MAX_COUNT 20 86 #define FAT_LFN_PART1_SIZE 5 87 #define FAT_LFN_PART2_SIZE 6 88 #define FAT_LFN_PART3_SIZE 2 89 #define FAT_LFN_ENTRY_SIZE \ 90 (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE) 59 91 60 92 typedef enum { … … 62 94 FAT_DENTRY_LAST, 63 95 FAT_DENTRY_FREE, 64 FAT_DENTRY_VALID 96 FAT_DENTRY_VALID, 97 FAT_DENTRY_LFN 65 98 } fat_dentry_clsf_t; 66 99 67 100 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;76 101 union { 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; 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 }; 87 134 } __attribute__ ((packed)) fat_dentry_t; 88 135 136 89 137 extern int fat_dentry_namecmp(char *, const char *); 90 extern bool fat_dentry_name_verify(const char *);91 138 extern void fat_dentry_name_get(const fat_dentry_t *, char *); 92 139 extern void fat_dentry_name_set(fat_dentry_t *, const char *); 93 140 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_part(const uint16_t *, size_t, uint16_t *, size_t *); 146 extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *); 147 extern size_t fat_lfn_set_part(const uint16_t *, size_t *, size_t, uint16_t *, size_t); 148 extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, fat_dentry_t *); 149 150 extern void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad); 151 extern size_t utf16_length(const uint16_t *wstr); 152 153 extern bool fat_valid_name(const char *name); 154 extern bool fat_valid_short_name(const char *name); 155 94 156 95 157 #endif -
uspace/srv/fs/fat/fat_fat.c
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 54 55 * primitive boot sector members. 55 56 */ 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 60 57 #define CLBN2PBN(bs, cl, bn) \ 61 58 (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs))) 59 60 #define IS_ODD(number) (number & 0x1) 62 61 63 62 /** … … 65 64 * during allocation of clusters. The lock does not have to be held durring 66 65 * deallocation of clusters. 67 */ 66 */ 68 67 static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock); 69 68 … … 77 76 * @param numc If non-NULL, output argument holding the number of 78 77 * clusters seen during the walk. 79 * @param max_clusters Maximum number of clusters to visit. 78 * @param max_clusters Maximum number of clusters to visit. 80 79 * 81 80 * @return EOK on success or a negative error code. 82 81 */ 83 int 82 int 84 83 fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc, 85 fat_cluster_t *lastc, uint 16_t *numc, uint16_t max_clusters)86 { 87 block_t *b;88 uint16_t clusters = 0;89 fat_cluster_t clst = firstc;84 fat_cluster_t *lastc, uint32_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); 90 89 int rc; 91 90 … … 99 98 } 100 99 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 100 while (clst < clst_last1 && clusters < max_clusters) { 105 101 assert(clst >= FAT_CLST_FIRST); 106 102 if (lastc) 107 103 *lastc = clst; /* remember the last cluster number */ 108 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs); 109 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t)); 104 110 105 /* read FAT1 */ 111 rc = block_get(&b, devmap_handle, 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; 106 rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst); 107 if (rc != EOK) 108 return rc; 109 110 assert(clst != clst_bad); 120 111 clusters++; 121 112 } 122 113 123 if (lastc && clst < FAT_CLST_LAST1)114 if (lastc && clst < clst_last1) 124 115 *lastc = clst; 125 116 if (numc) … … 151 142 return ELIMIT; 152 143 153 if ( nodep->firstc == FAT_CLST_ROOT)144 if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT) 154 145 goto fall_through; 155 146 … … 178 169 if (rc != EOK) 179 170 return rc; 180 171 181 172 /* 182 173 * Update the "current" cluster cache. … … 198 189 * @param clp If not NULL, address where the cluster containing bn 199 190 * will be stored. 200 * stored 191 * stored 201 192 * @param bn Block number. 202 193 * @param flags Flags passed to libblock. … … 208 199 fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags) 209 200 { 210 uint 16_t clusters;211 u nsignedmax_clusters;201 uint32_t clusters; 202 uint32_t max_clusters; 212 203 fat_cluster_t c; 213 204 int rc; … … 219 210 return ELIMIT; 220 211 221 if ( fcl == FAT_CLST_ROOT) {212 if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) { 222 213 /* root directory special case */ 223 214 assert(bn < RDS(bs)); … … 275 266 return rc; 276 267 } 277 268 278 269 if (o >= pos) 279 270 return EOK; 280 271 281 272 /* zero out the initial part of the new cluster chain */ 282 273 for (o = boundary; o < pos; o += BPS(bs)) { … … 295 286 } 296 287 297 /** Get cluster from the first FAT. 288 /** Get cluster from the first FAT. FAT12 version 298 289 * 299 290 * @param bs Buffer holding the boot sector for the file system. … … 305 296 */ 306 297 int 298 fat_get_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 299 fat_cluster_t clst, fat_cluster_t *value) 300 { 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; 309 310 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 311 offset / BPS(bs), BLOCK_FLAGS_NONE); 312 if (rc != EOK) 313 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, devmap_handle, 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; 353 354 rc = block_put(b); 355 return rc; 356 } 357 358 /** Get cluster from the first FAT. FAT16 version 359 * 360 * @param bs Buffer holding the boot sector for the file system. 361 * @param devmap_handle Device handle 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 int 368 fat_get_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, 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, devmap_handle, 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 version 390 * 391 * @param bs Buffer holding the boot sector for the file system. 392 * @param devmap_handle Device handle 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 int 399 fat_get_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, 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, devmap_handle, 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 devmap_handle Device handle 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 int 307 431 fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 308 432 fat_cluster_t clst, fat_cluster_t *value) 309 433 { 310 block_t *b; 311 fat_cluster_t *cp; 312 int rc; 313 314 rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno + 315 (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE); 316 if (rc != EOK) 317 return rc; 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); 322 434 int rc; 435 436 assert(fatno < FATCNT(bs)); 437 438 if (FAT_IS_FAT12(bs)) { 439 rc = fat_get_cluster_fat12(bs, devmap_handle, fatno, clst, value); 440 } 441 else { 442 if (FAT_IS_FAT32(bs)) 443 rc = fat_get_cluster_fat32(bs, devmap_handle, fatno, clst, value); 444 else 445 rc = fat_get_cluster_fat16(bs, devmap_handle, fatno, clst, value); 446 } 447 323 448 return rc; 324 449 } 325 450 326 /** Set cluster in one instance of FAT. 451 /** Set cluster in one instance of FAT. FAT12 version. 327 452 * 328 453 * @param bs Buffer holding the boot sector for the file system. … … 335 460 */ 336 461 int 462 fat_set_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, 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, devmap_handle, 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, devmap_handle, 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 and 494 * first byte of next sector 495 */ 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 else 506 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 } else 532 ((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 devmap_handle Device handle 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 int 550 fat_set_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, 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, devmap_handle, 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 devmap_handle Device handle 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 int 582 fat_set_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, 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, devmap_handle, 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 return rc; 605 } 606 607 /** Set cluster in one instance of FAT. 608 * 609 * @param bs Buffer holding the boot sector for the file system. 610 * @param devmap_handle Device handle for the file system. 611 * @param fatno Number of the FAT instance where to make the change. 612 * @param clst Cluster which is to be set. 613 * @param value Value to set the cluster with. 614 * 615 * @return EOK on success or a negative error code. 616 */ 617 int 337 618 fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno, 338 619 fat_cluster_t clst, fat_cluster_t value) 339 620 { 340 block_t *b;341 fat_cluster_t *cp;342 621 int rc; 343 622 344 623 assert(fatno < FATCNT(bs)); 345 rc = block_get(&b, devmap_handle, 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); 624 625 if (FAT_IS_FAT12(bs)) 626 rc = fat_set_cluster_fat12(bs, devmap_handle, fatno, clst, value); 627 else if (FAT_IS_FAT32(bs)) 628 rc = fat_set_cluster_fat32(bs, devmap_handle, fatno, clst, value); 629 else 630 rc = fat_set_cluster_fat16(bs, devmap_handle, fatno, clst, value); 631 354 632 return rc; 355 633 } … … 369 647 uint8_t fatno; 370 648 unsigned c; 371 int rc; 372 373 for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) { 649 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 650 int rc; 651 652 for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) { 374 653 for (c = 0; c < nclsts; c++) { 375 654 rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c], 376 c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);655 c == 0 ? clst_last1 : lifo[c - 1]); 377 656 if (rc != EOK) 378 657 return rc; … … 404 683 fat_cluster_t *mcl, fat_cluster_t *lcl) 405 684 { 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; 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; 411 689 412 690 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); 413 691 if (!lifo) 414 692 return ENOMEM; 415 416 693 /* 417 694 * Search FAT1 for unused clusters. 418 695 */ 419 696 fibril_mutex_lock(&fat_alloc_lock); 420 for (b = 0, cl = 0; b < SF(bs); b++) { 421 rc = block_get(&blk, devmap_handle, 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 devmap_handle, 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 } 470 } 471 rc = block_put(blk); 472 if (rc != EOK) { 473 error: 697 for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) { 698 rc = fat_get_cluster(bs, devmap_handle, 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, devmap_handle, FAT1, clst, 709 (found == 0) ? clst_last1 : lifo[found - 1]); 710 if (rc != EOK) 711 break; 712 713 found++; 714 } 715 } 716 717 if (rc == EOK && found == nclsts) { 718 rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts); 719 if (rc == EOK) { 720 *mcl = lifo[found - 1]; 721 *lcl = lifo[0]; 722 free(lifo); 474 723 fibril_mutex_unlock(&fat_alloc_lock); 475 free(lifo); 476 return rc; 477 } 478 } 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--) { 724 return EOK; 725 } 726 } 727 728 /* If something wrong - free the clusters */ 729 if (found > 0) { 730 while (found--) { 487 731 rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found], 488 732 FAT_CLST_RES0); 489 if (rc != EOK) { 490 free(lifo); 491 return rc; 492 } 493 } 494 733 } 734 } 735 495 736 free(lifo); 737 fibril_mutex_unlock(&fat_alloc_lock); 496 738 return ENOSPC; 497 739 } … … 509 751 { 510 752 unsigned fatno; 511 fat_cluster_t nextc ;753 fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs); 512 754 int rc; 513 755 514 756 /* Mark all clusters in the chain as free in all copies of FAT. */ 515 while (firstc < FAT_CLST_LAST1 ) {516 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);757 while (firstc < FAT_CLST_LAST1(bs)) { 758 assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad); 517 759 rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc); 518 760 if (rc != EOK) 519 761 return rc; 520 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {762 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 521 763 rc = fat_set_cluster(bs, devmap_handle, fatno, firstc, 522 764 FAT_CLST_RES0); … … 564 806 } 565 807 566 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {567 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,568 lastc, mcl);808 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 809 rc = fat_set_cluster(bs, nodep->idx->devmap_handle, 810 fatno, lastc, mcl); 569 811 if (rc != EOK) 570 812 return rc; … … 590 832 int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl) 591 833 { 834 fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs); 592 835 int rc; 593 836 devmap_handle_t devmap_handle = nodep->idx->devmap_handle; … … 616 859 617 860 /* Terminate the cluster chain in all copies of FAT. */ 618 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {861 for (fatno = FAT1; fatno < FATCNT(bs); fatno++) { 619 862 rc = fat_set_cluster(bs, devmap_handle, fatno, lcl, 620 FAT_CLST_LAST1);863 clst_last1); 621 864 if (rc != EOK) 622 865 return rc; … … 673 916 674 917 /* Check number of FATs. */ 675 if ( bs->fatcnt== 0)918 if (FATCNT(bs) == 0) 676 919 return ENOTSUP; 677 920 678 921 /* Check total number of sectors. */ 679 680 if (bs->totsec16 == 0 && bs->totsec32 == 0) 922 if (TS(bs) == 0) 681 923 return ENOTSUP; 682 924 683 925 if (bs->totsec16 != 0 && bs->totsec32 != 0 && 684 bs->totsec16 != bs->totsec32) 926 bs->totsec16 != bs->totsec32) 685 927 return ENOTSUP; 686 928 … … 690 932 691 933 /* Check number of sectors per FAT. */ 692 if ( bs->sec_per_fat== 0)934 if (SF(bs) == 0) 693 935 return ENOTSUP; 694 936 … … 700 942 * sanitized to support file systems with this property. 701 943 */ 702 if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) % 703 uint16_t_le2host(bs->bps) != 0) 944 if (!FAT_IS_FAT32(bs) && (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0) 704 945 return ENOTSUP; 705 946 706 947 /* Check signature of each FAT. */ 707 708 for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) { 948 for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) { 709 949 rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0); 710 950 if (rc != EOK) … … 723 963 * set to one. 724 964 */ 725 if ((e0 >> 8) != 0xff || e1 != 0xffff) 965 if (!FAT_IS_FAT12(bs) && 966 ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs))) 726 967 return ENOTSUP; 727 968 } … … 732 973 /** 733 974 * @} 734 */ 975 */ -
uspace/srv/fs/fat/fat_fat.h
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 #ifndef FAT_FAT_FAT_H_ … … 40 41 #define FAT1 0 41 42 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 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 48 62 49 63 /* internally used to mark root directory's parent */ … … 52 66 #define FAT_CLST_ROOT FAT_CLST_RES1 53 67 68 /* 69 * Convenience macros for computing some frequently used values from the 70 * 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 54 98 /* forward declarations */ 55 99 struct block; … … 57 101 struct fat_bs; 58 102 59 typedef uint 16_t fat_cluster_t;103 typedef uint32_t fat_cluster_t; 60 104 61 105 #define fat_clusters_get(numc, bs, dh, fc) \ 62 fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint 16_t) -1)106 fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint32_t) -1) 63 107 extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t, 64 fat_cluster_t *, uint 16_t *, uint16_t);108 fat_cluster_t *, uint32_t *, uint32_t); 65 109 66 110 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *, … … 78 122 extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t, 79 123 fat_cluster_t *, unsigned); 124 extern int fat_get_cluster_fat12(struct fat_bs *, devmap_handle_t, unsigned, 125 fat_cluster_t, fat_cluster_t *); 126 extern int fat_get_cluster_fat16(struct fat_bs *, devmap_handle_t, unsigned, 127 fat_cluster_t, fat_cluster_t *); 128 extern int fat_get_cluster_fat32(struct fat_bs *, devmap_handle_t, unsigned, 129 fat_cluster_t, fat_cluster_t *); 80 130 extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned, 81 131 fat_cluster_t, fat_cluster_t *); 132 extern int fat_set_cluster_fat12(struct fat_bs *, devmap_handle_t, unsigned, 133 fat_cluster_t, fat_cluster_t); 134 extern int fat_set_cluster_fat16(struct fat_bs *, devmap_handle_t, unsigned, 135 fat_cluster_t, fat_cluster_t); 136 extern int fat_set_cluster_fat32(struct fat_bs *, devmap_handle_t, unsigned, 137 fat_cluster_t, fat_cluster_t); 82 138 extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned, 83 139 fat_cluster_t, fat_cluster_t); -
uspace/srv/fs/fat/fat_ops.c
r3fab770 ra33f0a6 1 1 /* 2 2 * Copyright (c) 2008 Jakub Jermar 3 * Copyright (c) 2011 Oleg Romanenko 3 4 * All rights reserved. 4 5 * … … 29 30 /** @addtogroup fs 30 31 * @{ 31 */ 32 */ 32 33 33 34 /** … … 39 40 #include "fat_dentry.h" 40 41 #include "fat_fat.h" 42 #include "fat_directory.h" 41 43 #include "../../vfs/vfs.h" 42 44 #include <libfs.h> … … 56 58 #include <align.h> 57 59 #include <malloc.h> 60 #include <str.h> 58 61 59 62 #define FAT_NODE(node) ((node) ? (fat_node_t *) (node)->data : NULL) … … 104 107 node->dirty = false; 105 108 node->lastc_cached_valid = false; 106 node->lastc_cached_value = FAT_CLST_LAST1;109 node->lastc_cached_value = 0; 107 110 node->currc_cached_valid = false; 108 111 node->currc_cached_bn = 0; 109 node->currc_cached_value = FAT_CLST_LAST1;112 node->currc_cached_value = 0; 110 113 } 111 114 … … 116 119 fat_dentry_t *d; 117 120 int rc; 118 121 119 122 assert(node->dirty); 120 123 121 124 bs = block_bb_get(node->idx->devmap_handle); 122 125 123 126 /* Read the block that contains the dentry of interest. */ 124 127 rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc, … … 136 139 d->attr = FAT_ATTR_SUBDIR; 137 140 } 138 141 139 142 /* TODO: update other fields? (e.g time fields) */ 140 143 141 144 b->dirty = true; /* need to sync block */ 142 145 rc = block_put(b); … … 255 258 fn->data = nodep; 256 259 nodep->bp = fn; 257 260 258 261 *nodepp = nodep; 259 262 return EOK; … … 291 294 * We must instantiate the node from the file system. 292 295 */ 293 296 294 297 assert(idxp->pfc); 295 298 … … 309 312 310 313 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 else 319 nodep->firstc = uint16_t_le2host(d->firstc); 320 311 321 if (d->attr & FAT_ATTR_SUBDIR) { 312 /* 322 /* 313 323 * The only directory which does not have this bit set is the 314 324 * root directory itself. The root directory node is handled … … 316 326 */ 317 327 nodep->type = FAT_DIRECTORY; 328 318 329 /* 319 330 * Unfortunately, the 'size' field of the FAT dentry is not … … 321 332 * size of the directory by walking the FAT. 322 333 */ 323 uint16_t clusters; 324 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, 325 uint16_t_le2host(d->firstc)); 334 uint32_t clusters; 335 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, nodep->firstc); 326 336 if (rc != EOK) { 327 337 (void) block_put(b); … … 334 344 nodep->size = uint32_t_le2host(d->size); 335 345 } 336 nodep->firstc = uint16_t_le2host(d->firstc); 346 337 347 nodep->lnkcnt = 1; 338 348 nodep->refcnt = 1; … … 363 373 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 364 374 { 365 fat_bs_t *bs;366 375 fat_node_t *parentp = FAT_NODE(pfn); 367 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; 368 unsigned i, j; 369 unsigned blocks; 376 char name[FAT_LFN_NAME_SIZE]; 370 377 fat_dentry_t *d; 371 378 devmap_handle_t devmap_handle; 372 block_t *b;373 379 int rc; 374 380 … … 376 382 devmap_handle = parentp->idx->devmap_handle; 377 383 fibril_mutex_unlock(&parentp->idx->lock); 378 379 bs = block_bb_get(devmap_handle); 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; 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(devmap_handle, 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; 400 404 } 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(devmap_handle, 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); 405 rc = fat_node_get_core(&nodep, idx); 406 fibril_mutex_unlock(&idx->lock); 407 if (rc != EOK) { 408 (void) fat_directory_close(&di); 424 409 return rc; 425 410 } 426 } 427 rc = block_put(b); 428 if (rc != EOK) 411 *rfn = FS_NODE(nodep); 412 rc = fat_directory_close(&di); 413 if (rc != EOK) 414 (void) fat_node_put(*rfn); 429 415 return rc; 430 } 431 416 } else { 417 rc = fat_directory_next(&di); 418 if (rc != EOK) 419 break; 420 } 421 } 422 (void) fat_directory_close(&di); 432 423 *rfn = NULL; 433 424 return EOK; … … 521 512 rc = fat_idx_get_new(&idxp, devmap_handle); 522 513 if (rc != EOK) { 523 (void) fat_free_clusters(bs, devmap_handle, mcl); 514 (void) fat_free_clusters(bs, devmap_handle, mcl); 524 515 (void) fat_node_put(FS_NODE(nodep)); 525 516 return rc; … … 591 582 fat_bs_t *bs; 592 583 block_t *b; 593 unsigned i, j; 594 unsigned blocks; 595 fat_cluster_t mcl, lcl; 584 fat_directory_t di; 585 fat_dentry_t de; 596 586 int rc; 597 587 … … 607 597 fibril_mutex_unlock(&childp->lock); 608 598 609 if (!fat_dentry_name_verify(name)) { 610 /* 611 * Attempt to create unsupported name. 612 */ 599 if (!fat_valid_name(name)) 613 600 return ENOTSUP; 614 } 615 616 /* 617 * Get us an unused parent node's dentry or grow the parent and allocate 618 * a new one. 619 */ 620 601 621 602 fibril_mutex_lock(&parentp->idx->lock); 622 603 bs = block_bb_get(parentp->idx->devmap_handle); 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->devmap_handle, 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->devmap_handle, mcl); 667 if (rc != EOK) { 668 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, 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->devmap_handle, 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: 604 rc = fat_directory_open(parentp, &di); 605 if (rc != EOK) 606 return rc; 607 688 608 /* 689 609 * At this point we only establish the link between the parent and the … … 692 612 * dentry data is kept in the child node structure. 693 613 */ 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); 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 698 623 fibril_mutex_unlock(&parentp->idx->lock); 699 if (rc != EOK) 624 if (rc != EOK) 700 625 return rc; 701 626 702 627 fibril_mutex_lock(&childp->idx->lock); 703 628 704 629 if (childp->type == FAT_DIRECTORY) { 705 630 /* … … 720 645 d = (fat_dentry_t *) b->data; 721 646 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 722 ( str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {647 (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) { 723 648 memset(d, 0, sizeof(fat_dentry_t)); 724 649 memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN); … … 730 655 d++; 731 656 if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) || 732 ( str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {657 (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) { 733 658 memset(d, 0, sizeof(fat_dentry_t)); 734 659 memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN); 735 660 memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN); 736 661 d->attr = FAT_ATTR_SUBDIR; 737 d->firstc = (parentp->firstc == FAT_ CLST_ROOT) ?738 host2uint16_t_le(FAT_CLST_R ES0) :662 d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ? 663 host2uint16_t_le(FAT_CLST_ROOTPAR) : 739 664 host2uint16_t_le(parentp->firstc); 740 665 /* TODO: initialize also the date/time members. */ … … 750 675 751 676 childp->idx->pfc = parentp->firstc; 752 childp->idx->pdi = i * DPS(bs) + j;677 childp->idx->pdi = di.pos; /* di.pos holds absolute position of SFN entry */ 753 678 fibril_mutex_unlock(&childp->idx->lock); 754 679 … … 770 695 fat_node_t *parentp = FAT_NODE(pfn); 771 696 fat_node_t *childp = FAT_NODE(cfn); 772 fat_bs_t *bs;773 fat_dentry_t *d;774 block_t *b;775 697 bool has_children; 776 698 int rc; … … 778 700 if (!parentp) 779 701 return EBUSY; 780 702 781 703 rc = fat_has_children(&has_children, cfn); 782 704 if (rc != EOK) … … 789 711 assert(childp->lnkcnt == 1); 790 712 fibril_mutex_lock(&childp->idx->lock); 791 bs = block_bb_get(childp->idx->devmap_handle); 792 793 rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc, 794 NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs), 795 BLOCK_FLAGS_NONE); 796 if (rc != EOK) 713 714 fat_directory_t di; 715 rc = fat_directory_open(parentp,&di); 716 if (rc != EOK) 797 717 goto error; 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); 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); 804 725 if (rc != EOK) 805 726 goto error; … … 820 741 821 742 error: 822 fibril_mutex_unlock(&parentp->idx->lock); 743 (void) fat_directory_close(&di); 744 fibril_mutex_unlock(&childp->idx->lock); 823 745 fibril_mutex_unlock(&childp->lock); 824 fibril_mutex_unlock(& childp->idx->lock);746 fibril_mutex_unlock(&parentp->lock); 825 747 return rc; 826 748 } … … 839 761 return EOK; 840 762 } 841 763 842 764 fibril_mutex_lock(&nodep->idx->lock); 843 765 bs = block_bb_get(nodep->idx->devmap_handle); … … 847 769 for (i = 0; i < blocks; i++) { 848 770 fat_dentry_t *d; 849 771 850 772 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 851 773 if (rc != EOK) { … … 875 797 if (rc != EOK) { 876 798 fibril_mutex_unlock(&nodep->idx->lock); 877 return rc; 799 return rc; 878 800 } 879 801 } … … 946 868 fat_bs_t *bs; 947 869 int rc; 948 870 949 871 /* Check for option enabling write through. */ 950 872 if (str_cmp(opts, "wtcache") == 0) … … 967 889 /* get the buffer with the boot sector */ 968 890 bs = block_bb_get(devmap_handle); 969 891 970 892 if (BPS(bs) != BS_SIZE) { 971 893 block_fini(devmap_handle); … … 1003 925 return ENOMEM; 1004 926 } 927 1005 928 fs_node_initialize(rfn); 1006 929 fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t)); … … 1027 950 1028 951 rootp->type = FAT_DIRECTORY; 1029 rootp->firstc = FAT_ CLST_ROOT;952 rootp->firstc = FAT_ROOT_CLST(bs); 1030 953 rootp->refcnt = 1; 1031 954 rootp->lnkcnt = 0; /* FS root is not linked */ 1032 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 955 956 if (FAT_IS_FAT32(bs)) { 957 uint32_t clusters; 958 rc = fat_clusters_get(&clusters, bs, devmap_handle, rootp->firstc); 959 if (rc != EOK) { 960 free(rfn); 961 free(rootp); 962 free(ridxp); /* TODO: Is it right way to free ridxp? */ 963 (void) block_cache_fini(devmap_handle); 964 block_fini(devmap_handle); 965 fat_idx_fini_by_devmap_handle(devmap_handle); 966 async_answer_0(rid, ENOTSUP); 967 return; 968 } 969 rootp->size = BPS(bs) * SPC(bs) * clusters; 970 } else 971 rootp->size = RDE(bs) * sizeof(fat_dentry_t); 972 1033 973 rootp->idx = ridxp; 1034 974 ridxp->nodep = rootp; 1035 975 rootp->bp = rfn; 1036 976 rfn->data = rootp; 1037 977 1038 978 fibril_mutex_unlock(&ridxp->lock); 1039 979 … … 1064 1004 return EBUSY; 1065 1005 } 1066 1006 1067 1007 /* 1068 1008 * Put the root node and force it to the FAT free node list. … … 1141 1081 } 1142 1082 } else { 1143 unsigned bnum;1144 1083 aoff64_t spos = pos; 1145 char name[FAT_ NAME_LEN + 1 + FAT_EXT_LEN + 1];1084 char name[FAT_LFN_NAME_SIZE]; 1146 1085 fat_dentry_t *d; 1147 1086 … … 1150 1089 assert(BPS(bs) % sizeof(fat_dentry_t) == 0); 1151 1090 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 } 1091 fat_directory_t di; 1092 rc = fat_directory_open(nodep, &di); 1093 if (rc != EOK) goto err; 1094 rc = fat_directory_seek(&di, pos); 1095 if (rc != EOK) { 1096 (void) fat_directory_close(&di); 1097 goto err; 1098 } 1099 1100 rc = fat_directory_read(&di, name, &d); 1101 if (rc == EOK) goto hit; 1102 if (rc == ENOENT) goto miss; 1103 1104 err: 1105 (void) fat_node_put(fn); 1106 async_answer_0(callid, rc); 1107 return rc; 1108 1193 1109 miss: 1110 rc = fat_directory_close(&di); 1111 if (rc!=EOK) 1112 goto err; 1194 1113 rc = fat_node_put(fn); 1195 1114 async_answer_0(callid, rc != EOK ? rc : ENOENT); … … 1197 1116 return rc != EOK ? rc : ENOENT; 1198 1117 1199 err:1200 (void) fat_node_put(fn);1201 async_answer_0(callid, rc);1202 return rc;1203 1204 1118 hit: 1119 pos = di.pos; 1120 rc = fat_directory_close(&di); 1121 if (rc!=EOK) 1122 goto err; 1205 1123 (void) async_data_read_finalize(callid, name, str_size(name) + 1); 1206 bytes = (pos - spos) +1;1124 bytes = (pos - spos)+1; 1207 1125 } 1208 1126 … … 1224 1142 int flags = BLOCK_FLAGS_NONE; 1225 1143 int rc; 1226 1144 1227 1145 rc = fat_node_get(&fn, devmap_handle, index); 1228 1146 if (rc != EOK) … … 1231 1149 return ENOENT; 1232 1150 nodep = FAT_NODE(fn); 1233 1151 1234 1152 ipc_callid_t callid; 1235 1153 size_t len; … … 1247 1165 * but this one greatly simplifies fat_write(). Note that we can afford 1248 1166 * to do this because the client must be ready to handle the return 1249 * value signalizing a smaller number of bytes written. 1250 */ 1167 * value signalizing a smaller number of bytes written. 1168 */ 1251 1169 bytes = min(len, BPS(bs) - pos % BPS(bs)); 1252 1170 if (bytes == BPS(bs)) 1253 1171 flags |= BLOCK_FLAGS_NOREAD; 1254 1172 1255 1173 boundary = ROUND_UP(nodep->size, BPC(bs)); 1256 1174 if (pos < boundary) { … … 1295 1213 */ 1296 1214 unsigned nclsts; 1297 fat_cluster_t mcl, lcl; 1298 1215 fat_cluster_t mcl, lcl; 1216 1299 1217 nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs); 1300 1218 /* create an independent chain of nclsts clusters in all FATs */ … … 1380 1298 nodep->size = size; 1381 1299 nodep->dirty = true; /* need to sync node */ 1382 rc = EOK; 1300 rc = EOK; 1383 1301 } else { 1384 1302 /* … … 1401 1319 nodep->size = size; 1402 1320 nodep->dirty = true; /* need to sync node */ 1403 rc = EOK; 1321 rc = EOK; 1404 1322 } 1405 1323 out: … … 1444 1362 if (!fn) 1445 1363 return ENOENT; 1446 1364 1447 1365 fat_node_t *nodep = FAT_NODE(fn); 1448 1366 1449 1367 nodep->dirty = true; 1450 1368 rc = fat_node_sync(nodep); 1451 1369 1452 1370 fat_node_put(fn); 1453 1371 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.