Changes in uspace/srv/fs/fat/fat_dentry.c [2c22f1f7:842a2d2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_dentry.c
r2c22f1f7 r842a2d2 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 == '_' || 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_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) 83 367 { 84 368 unsigned int i; 85 369 unsigned int dot = 0; 86 370 bool dot_found = false; 87 88 371 89 372 for (i = 0; name[i]; i++) { … … 96 379 } 97 380 } else { 98 if (! is_d_char(name[i]))381 if (!IS_D_CHAR(name[i])) 99 382 return false; 100 383 } … … 114 397 } 115 398 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; 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; 240 407 } 241 408
Note:
See TracChangeset
for help on using the changeset viewer.