Changes in uspace/srv/fs/fat/fat_dentry.c [411e9ca:2c22f1f7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_dentry.c
r411e9ca r2c22f1f7 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 == '_' || 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_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) 82 bool fat_dentry_name_verify(const char *name) 356 83 { 357 84 unsigned int i; 358 85 unsigned int dot = 0; 359 86 bool dot_found = false; 87 360 88 361 89 for (i = 0; name[i]; i++) { … … 368 96 } 369 97 } else { 370 if (! IS_D_CHAR(name[i]))98 if (!is_d_char(name[i])) 371 99 return false; 372 100 } … … 386 114 } 387 115 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; 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; 396 240 } 397 241
Note:
See TracChangeset
for help on using the changeset viewer.