Changes in uspace/srv/fs/fat/fat_dentry.c [2c22f1f7:5d95f02] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_dentry.c
r2c22f1f7 r5d95f02 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 225 for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++) 226 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i]; 227 228 return sum; 229 } 230 231 /** Get number of bytes in a string with size limit. 232 * 233 * @param str NULL-terminated (or not) string. 234 * @param size Maximum number of bytes to consider. 235 * 236 * @return Number of bytes in string (without 0 and ff). 237 * 238 */ 239 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size) 240 { 241 size_t offset = 0; 242 243 while (offset < size) { 244 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD) 245 break; 246 offset++; 247 } 248 return offset; 249 } 250 251 /** Get number of bytes in a FAT long entry occuped by characters. 252 * 253 * @param d FAT long entry. 254 * 255 * @return Number of bytes. 256 * 257 */ 258 size_t fat_lfn_size(const fat_dentry_t *d) 259 { 260 size_t size = 0; 261 262 size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE); 263 size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE); 264 size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE); 265 266 return size; 267 } 268 269 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset) 270 { 271 int i; 272 for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) { 273 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD) 274 continue; 275 (*offset)--; 276 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]); 277 } 278 for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) { 279 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD) 280 continue; 281 (*offset)--; 282 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]); 283 } 284 for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) { 285 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD) 286 continue; 287 (*offset)--; 288 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]); 289 } 290 return *offset; 291 } 292 293 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, 294 fat_dentry_t *d) 295 { 296 size_t idx; 297 for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) { 298 if (*offset < size) { 299 d->lfn.part1[idx] = host2uint16_t_le(src[*offset]); 300 (*offset)++; 301 } else 302 d->lfn.part1[idx] = FAT_LFN_PAD; 303 } 304 for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) { 305 if (*offset < size) { 306 d->lfn.part2[idx] = host2uint16_t_le(src[*offset]); 307 (*offset)++; 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 } else 316 d->lfn.part3[idx] = FAT_LFN_PAD; 317 } 318 319 if (src[*offset] == 0) 320 offset++; 321 FAT_LFN_ATTR(d) = FAT_ATTR_LFN; 322 d->lfn.type = 0; 323 d->lfn.firstc_lo = 0; 324 325 return *offset; 326 } 327 328 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad) 329 { 330 wchar_t ch; 331 size_t off = 0; 332 size_t i = 0; 333 334 while (i < count) { 335 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) { 336 if (ascii_check(ch) & IS_D_CHAR(ch)) 337 *dst = toupper(ch); 338 else 339 *dst = pad; 340 } else 341 break; 342 343 dst++; 344 i++; 345 } 346 *dst = '\0'; 347 } 348 349 bool fat_valid_name(const char *name) 350 { 351 wchar_t ch; 352 size_t offset=0; 353 bool result = true; 354 355 while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) { 356 if (str_chr(FAT_STOP_CHARS, ch) != NULL) { 357 result = false; 358 break; 359 } 360 } 361 return result; 362 } 363 364 bool fat_valid_short_name(const char *name) 83 365 { 84 366 unsigned int i; 85 367 unsigned int dot = 0; 86 368 bool dot_found = false; 87 88 369 89 370 for (i = 0; name[i]; i++) { … … 96 377 } 97 378 } else { 98 if (! is_d_char(name[i]))379 if (!IS_D_CHAR(name[i])) 99 380 return false; 100 381 } … … 114 395 } 115 396 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; 397 size_t utf16_length(const uint16_t *wstr) 398 { 399 size_t len = 0; 400 401 while (*wstr++ != 0) 402 len++; 403 404 return len; 240 405 } 241 406
Note:
See TracChangeset
for help on using the changeset viewer.