| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | /* |
| 2 | * dirent.c |
| 3 | * |
| 4 | * Include functions implementing directory entry. |
| 5 | * implementation file. |
| 6 | * |
| 7 | * Copyright (C) knightray@gmail.com |
| 8 | * |
| 9 | * SPDX-License-Identifier: GPL-2.0+ |
| 10 | */ |
| 11 | #include "dirent.h" |
| 12 | #include "debug.h" |
| 13 | #include "fat.h" |
| 14 | #include "common.h" |
| 15 | #include "dir.h" |
| 16 | |
| 17 | #ifndef DBG_DIRENT |
| 18 | #undef DBG |
| 19 | #define DBG nulldbg |
| 20 | #endif |
| 21 | |
| 22 | /* Private routins declaration. */ |
| 23 | |
| 24 | static int32 |
| 25 | _get_dirent( |
| 26 | IN tdir_t * pdir, |
| 27 | OUT dir_entry_t * pdirent |
| 28 | ); |
| 29 | |
| 30 | static void |
| 31 | _parse_file_name( |
| 32 | IN tdir_t * pdir, |
| 33 | IN dir_entry_t * pdirent, |
| 34 | OUT tdir_entry_t * pdir_entry |
| 35 | ); |
| 36 | |
| 37 | static BOOL |
| 38 | _get_long_file_name( |
| 39 | IN dir_entry_t * pdirent, |
| 40 | OUT byte * long_name |
| 41 | ); |
| 42 | |
| 43 | static BOOL |
| 44 | _convert_short_fname( |
| 45 | IN ubyte * dir_name, |
| 46 | OUT byte * d_name |
| 47 | ); |
| 48 | |
| 49 | static BOOL |
| 50 | _convert_to_short_fname( |
| 51 | IN byte * fname, |
| 52 | OUT ubyte * short_fname |
| 53 | ); |
| 54 | |
| 55 | static ubyte |
| 56 | _get_check_sum( |
| 57 | IN ubyte * fname |
| 58 | ); |
| 59 | |
| 60 | /*----------------------------------------------------------------------------------------------------*/ |
| 61 | |
| 62 | int32 |
| 63 | dirent_find( |
| 64 | IN tdir_t * pdir, |
| 65 | IN byte * dirname, |
| 66 | OUT tdir_entry_t * pdir_entry) |
| 67 | { |
| 68 | int32 ret; |
| 69 | |
| 70 | pdir->cur_clus = pdir->start_clus; |
| 71 | pdir->cur_sec = 0; |
| 72 | pdir->cur_dir_entry = 0; |
| 73 | if (dir_read_sector(pdir) != DIR_OK) |
| 74 | return ERR_DIRENTRY_NOT_FOUND; |
| 75 | |
| 76 | ASSERT(pdir_entry->pdirent == NULL); |
| 77 | ret = DIRENTRY_OK; |
| 78 | |
| 79 | while(1) { |
| 80 | dir_entry_t dirent; |
| 81 | |
| 82 | if ((ret = _get_dirent(pdir, &dirent)) == DIRENTRY_OK) { |
| 83 | |
| 84 | if (dirent.dir_name[0] == 0x00) { |
| 85 | ret = ERR_DIRENTRY_NOT_FOUND; |
| 86 | break; |
| 87 | } |
| 88 | else if (dirent.dir_name[0] == 0xE5) { |
| 89 | //FixMe do with 0x5 |
| 90 | continue; |
| 91 | } |
| 92 | |
| 93 | Memset(pdir_entry->long_name, 0, LONG_NAME_LEN); |
| 94 | Memset(pdir_entry->short_name, 0, SHORT_NAME_LEN); |
| 95 | _parse_file_name(pdir, &dirent, pdir_entry); |
| 96 | |
| 97 | if (!Strcmp(pdir_entry->long_name, dirname)) { |
| 98 | break; |
| 99 | } |
| 100 | } |
| 101 | else if (ret == ERR_DIRENTRY_NOMORE_ENTRY){ |
| 102 | ret = ERR_DIRENTRY_NOT_FOUND; |
| 103 | break; |
| 104 | } |
| 105 | else { |
| 106 | ret = ERR_DIRENTRY_DEVICE_FAIL; |
| 107 | break; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | return ret; |
| 112 | } |
| 113 | |
| 114 | BOOL |
| 115 | dirent_is_empty( |
| 116 | IN tdir_t * pdir) |
| 117 | { |
| 118 | BOOL ret; |
| 119 | tdir_entry_t * pdir_entry; |
| 120 | |
| 121 | pdir->cur_clus = pdir->start_clus; |
| 122 | pdir->cur_sec = 0; |
| 123 | pdir->cur_dir_entry = 0; |
| 124 | if (dir_read_sector(pdir) != DIR_OK) |
| 125 | return ERR_DIRENTRY_NOT_FOUND; |
| 126 | |
| 127 | pdir_entry = dirent_malloc(); |
| 128 | ASSERT(pdir_entry->pdirent == NULL); |
| 129 | ret = TRUE; |
| 130 | |
| 131 | while(1) { |
| 132 | dir_entry_t dirent; |
| 133 | |
| 134 | if ((ret = _get_dirent(pdir, &dirent)) == DIRENTRY_OK) { |
| 135 | |
| 136 | if (dirent.dir_name[0] == 0x00) { |
| 137 | break; |
| 138 | } |
| 139 | else if (dirent.dir_name[0] == 0xE5) { |
| 140 | //FixMe do with 0x5 |
| 141 | continue; |
| 142 | } |
| 143 | |
| 144 | Memset(pdir_entry->long_name, 0, LONG_NAME_LEN); |
| 145 | Memset(pdir_entry->short_name, 0, SHORT_NAME_LEN); |
| 146 | _parse_file_name(pdir, &dirent, pdir_entry); |
| 147 | |
| 148 | if (!Strcmp(pdir_entry->long_name, ".") || !Strcmp(pdir_entry->long_name, "..")) { |
| 149 | continue; |
| 150 | } |
| 151 | else { |
| 152 | ret = FALSE; |
| 153 | break; |
| 154 | } |
| 155 | } |
| 156 | else if (ret == ERR_DIRENTRY_NOMORE_ENTRY){ |
| 157 | break; |
| 158 | } |
| 159 | else { |
| 160 | ERR("%s(): get next direntry failed. ret = %d\n", __FUNCTION__, ret); |
| 161 | ret = FALSE; |
| 162 | break; |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | dirent_release(pdir_entry); |
| 167 | return ret; |
| 168 | } |
| 169 | |
| 170 | /* Marvell fixed: when a new cluster is being allocated to a directory |
| 171 | the contents of all dirent's should be 0 */ |
| 172 | static void |
| 173 | dirent_clear_new_cluster(tdir_t *pdir) |
| 174 | { |
| 175 | Memset(pdir->secbuf, 0, pdir->ptffs->pbs->byts_per_sec); |
| 176 | for (pdir->cur_sec = 0; |
| 177 | pdir->cur_sec < pdir->ptffs->pbs->sec_per_clus; |
| 178 | pdir->cur_sec++) |
| 179 | if (dir_write_sector(pdir) != DIR_OK) |
| 180 | break; |
| 181 | pdir->cur_sec = 0; |
| 182 | pdir->cur_dir_entry = 0; |
| 183 | /* Leave secbuf as is, so no need to read it again */ |
| 184 | } |
| 185 | |
| 186 | /* Marvell fixed: when a new entry is appended at the end of a directory, |
| 187 | all the entries should be allocated in the same sector, as they are later |
| 188 | accessed in the sector buffer. This function: |
| 189 | - checks if the required number of entries (dirent_num) is available; |
| 190 | - otherwise, pads the current sector with E5 (deleted) entries, |
| 191 | and lets the search continue into the following sector. */ |
| 192 | static int32 dirent_space_check_extend(tdir_t *pdir, int32 dirent_num) |
| 193 | { |
| 194 | int32 nent = pdir->ptffs->pbs->byts_per_sec / sizeof(dir_entry_t); |
| 195 | dir_entry_t *pde = (dir_entry_t *)pdir->secbuf; |
| 196 | int32 i, n0, ne5; |
| 197 | for (i = n0 = ne5 = 0; i < nent; i++) { |
| 198 | unsigned char c = pde[i].dir_name[0]; |
| 199 | if (n0) |
| 200 | ASSERT(c == 0); |
| 201 | if (c == 0) |
| 202 | n0++; |
| 203 | else if (c == 0xE5) |
| 204 | ne5++; |
| 205 | else |
| 206 | n0 = ne5 = 0; |
| 207 | if ((n0 + ne5) == dirent_num) { |
| 208 | pdir->cur_dir_entry = i + 1 - dirent_num; |
| 209 | return DIRENTRY_OK; |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | /* not found the free entry sequence in this sector */ |
| 214 | if (n0) { |
| 215 | /* replace 0 entries with E5 as dir continues to next sector */ |
| 216 | for (i = nent - n0; i < nent; i++) |
| 217 | pde[i].dir_name[0] = 0xE5; |
| 218 | if (dir_write_sector(pdir) != DIR_OK) |
| 219 | return ERR_DIRENTRY_DEVICE_FAIL; |
| 220 | } |
| 221 | pdir->cur_dir_entry = nent; /* sector ended */ |
| 222 | return ERR_DIRENTRY_NOMORE_ENTRY; |
| 223 | } |
| 224 | |
| 225 | int32 |
| 226 | dirent_find_free_entry( |
| 227 | IN tdir_t * pdir, |
| 228 | IN tdir_entry_t * pdir_entry) |
| 229 | { |
| 230 | int32 ret; |
| 231 | tffs_t * ptffs = pdir->ptffs; |
| 232 | |
| 233 | ret = DIRENTRY_OK; |
| 234 | |
| 235 | while(1) { |
| 236 | dir_entry_t dirent; |
| 237 | |
| 238 | if ((ret = _get_dirent(pdir, &dirent)) == DIRENTRY_OK) { |
| 239 | /* Marvell fixed: revised search for free entries */ |
| 240 | if (dirent_space_check_extend(pdir, pdir_entry->dirent_num) == DIRENTRY_OK) |
| 241 | break; /* enough free entries in this sector */ |
| 242 | } |
| 243 | else if (ret == ERR_DIRENTRY_NOMORE_ENTRY) { |
| 244 | uint32 new_clus; |
| 245 | |
| 246 | if (dir_write_sector(pdir) != DIR_OK) { |
| 247 | ret = ERR_DIRENTRY_DEVICE_FAIL; |
| 248 | break; |
| 249 | } |
| 250 | if ((ret = fat_malloc_clus(ptffs->pfat, pdir->cur_clus, &new_clus)) == FAT_OK) { |
| 251 | pdir->cur_clus = new_clus; |
| 252 | pdir->cur_sec = 0; |
| 253 | pdir->cur_dir_entry = 0; |
| 254 | /* Marvell fixed: zero the new cluster */ |
| 255 | dirent_clear_new_cluster(pdir); |
| 256 | } |
| 257 | else { |
| 258 | ret = ERR_DIRENTRY_NOMORE_ENTRY; |
| 259 | break; |
| 260 | } |
| 261 | } |
| 262 | else { |
| 263 | break; |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | return ret; |
| 268 | } |
| 269 | |
| 270 | int32 |
| 271 | dirent_get_next( |
| 272 | IN tdir_t * pdir, |
| 273 | OUT tdir_entry_t * pdir_entry) |
| 274 | { |
| 275 | int32 ret; |
| 276 | |
| 277 | ret = DIRENTRY_OK; |
| 278 | |
| 279 | while(1) { |
| 280 | dir_entry_t dirent; |
| 281 | |
| 282 | //print_sector(pdir->secbuf, 1); |
| 283 | DBG("%s():pdir->cur_clus = %d, pdir->cur_dir_entry = %d\n", __FUNCTION__, pdir->cur_clus, pdir->cur_dir_entry); |
| 284 | if ((ret = _get_dirent(pdir, &dirent)) == DIRENTRY_OK) { |
| 285 | |
| 286 | if (dirent.dir_name[0] == 0x00) { |
| 287 | ret = ERR_DIRENTRY_NOMORE_ENTRY; |
| 288 | break; |
| 289 | } |
| 290 | else if (dirent.dir_name[0] == 0xE5) { |
| 291 | //FixMe do with 0x5 |
| 292 | continue; |
| 293 | } |
| 294 | |
| 295 | Memset(pdir_entry->long_name, 0, LONG_NAME_LEN); |
| 296 | Memset(pdir_entry->short_name, 0, SHORT_NAME_LEN); |
| 297 | _parse_file_name(pdir, &dirent, pdir_entry); |
| 298 | |
| 299 | break; |
| 300 | } |
| 301 | else { |
| 302 | break; |
| 303 | } |
| 304 | } |
| 305 | return ret; |
| 306 | } |
| 307 | |
| 308 | void |
| 309 | dirent_release( |
| 310 | IN tdir_entry_t * pdir_entry) |
| 311 | { |
| 312 | Free(pdir_entry->pdirent); |
| 313 | Free(pdir_entry); |
| 314 | } |
| 315 | |
| 316 | tdir_entry_t * |
| 317 | dirent_malloc() |
| 318 | { |
| 319 | tdir_entry_t * pdir_entry; |
| 320 | |
| 321 | pdir_entry = (tdir_entry_t *)Malloc(sizeof(tdir_entry_t)); |
| 322 | Memset(pdir_entry, 0, sizeof(tdir_entry_t)); |
| 323 | return pdir_entry; |
| 324 | } |
| 325 | |
| 326 | BOOL |
| 327 | dirent_init( |
| 328 | IN byte * fname, |
| 329 | IN ubyte dir_attr, |
| 330 | IN byte use_long_name, |
| 331 | OUT tdir_entry_t * pdir_entry) |
| 332 | { |
| 333 | long_dir_entry_t * plfent; |
| 334 | dir_entry_t * pdirent; |
| 335 | uint32 lfent_num; |
| 336 | int32 lfent_i; |
| 337 | byte * pfname; |
| 338 | |
| 339 | if (Strlen(fname) > LONG_NAME_LEN || |
| 340 | (!use_long_name && Strlen(fname) > SHORT_NAME_LEN)) |
| 341 | return FALSE; |
| 342 | |
| 343 | if (use_long_name) { |
| 344 | lfent_num = Strlen(fname) / 13 + 2; |
| 345 | } |
| 346 | else { |
| 347 | lfent_num = 1; |
| 348 | } |
| 349 | |
| 350 | pfname = fname; |
| 351 | |
| 352 | plfent = (long_dir_entry_t *)Malloc(sizeof(long_dir_entry_t) * lfent_num); |
| 353 | Memset(plfent, 0, sizeof(long_dir_entry_t) * lfent_num); |
| 354 | pdirent = (dir_entry_t *)(&plfent[lfent_num - 1]); |
| 355 | |
| 356 | _convert_to_short_fname(fname, pdirent->dir_name); |
| 357 | DBG("%s(): %s=>%s\n", __FUNCTION__, fname, pdirent->dir_name); |
| 358 | pdirent->dir_attr = dir_attr; |
| 359 | pdirent->dir_ntres = 0; |
| 360 | pdirent->dir_crt_time_tenth = dirent_get_cur_time_tenth(); |
| 361 | pdirent->dir_crt_time = dirent_get_cur_time(); |
| 362 | pdirent->dir_crt_date = dirent_get_cur_date(); |
| 363 | pdirent->dir_lst_acc_date = pdirent->dir_crt_date; |
| 364 | pdirent->dir_wrt_time = pdirent->dir_crt_time; |
| 365 | pdirent->dir_wrt_date = pdirent->dir_crt_date; |
| 366 | pdirent->dir_fst_clus_hi = 0; |
| 367 | pdirent->dir_fst_clus_lo = 0; |
| 368 | pdirent->dir_file_size = 0; |
| 369 | |
| 370 | if (use_long_name) { |
| 371 | for (lfent_i = lfent_num - 2; lfent_i >= 0; lfent_i--) { |
| 372 | ubyte fname_line[13]; |
| 373 | |
| 374 | Memset(fname_line, 0xFF, 13); |
| 375 | Memcpy(fname_line, pfname, min(fname + Strlen(fname) - pfname + 1, 13)); |
| 376 | |
| 377 | if (lfent_i == 0) { |
| 378 | plfent[lfent_i].ldir_ord = (lfent_num - 1 - lfent_i) | LAST_LONG_ENTRY; |
| 379 | } |
| 380 | else { |
| 381 | plfent[lfent_i].ldir_ord = lfent_num - 1 - lfent_i; |
| 382 | } |
| 383 | copy_to_unicode(fname_line, 5, plfent[lfent_i].ldir_name1); |
| 384 | copy_to_unicode(fname_line + 5, 6, plfent[lfent_i].ldir_name2); |
| 385 | copy_to_unicode(fname_line + 11, 2, plfent[lfent_i].ldir_name3); |
| 386 | pfname += 13; |
| 387 | |
| 388 | plfent[lfent_i].ldir_attr = ATTR_LONG_NAME; |
| 389 | plfent[lfent_i].ldir_type = 0; |
| 390 | plfent[lfent_i].ldir_chksum = _get_check_sum(pdirent->dir_name); |
| 391 | plfent[lfent_i].ldir_fst_clus_lo = 0; |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | pdir_entry->pdirent = (dir_entry_t *)plfent; |
| 396 | pdir_entry->dirent_num = lfent_num; |
| 397 | Strcpy(pdir_entry->long_name, fname); |
| 398 | _convert_short_fname(pdirent->dir_name, pdir_entry->short_name); |
| 399 | |
| 400 | return TRUE; |
| 401 | } |
| 402 | |
| 403 | uint16 |
| 404 | dirent_get_cur_time() |
| 405 | { |
| 406 | tffs_sys_time_t curtm; |
| 407 | uint16 ret; |
| 408 | |
| 409 | Getcurtime(&curtm); |
| 410 | |
| 411 | ret = 0; |
| 412 | ret |= (curtm.tm_sec >> 2) & 0x1F; |
| 413 | ret |= (curtm.tm_min << 5) & 0x7E0; |
| 414 | ret |= (curtm.tm_hour << 11) & 0xF800; |
| 415 | |
| 416 | return ret; |
| 417 | } |
| 418 | |
| 419 | uint16 |
| 420 | dirent_get_cur_date() |
| 421 | { |
| 422 | tffs_sys_time_t curtm; |
| 423 | uint16 ret; |
| 424 | |
| 425 | Getcurtime(&curtm); |
| 426 | |
| 427 | ret = 0; |
| 428 | ret |= (curtm.tm_mday) & 0x1F; |
| 429 | ret |= ((curtm.tm_mon + 1) << 5) & 0x1E0; |
| 430 | ret |= ((curtm.tm_year - 80) << 9) & 0xFE00; |
| 431 | |
| 432 | return ret; |
| 433 | } |
| 434 | |
| 435 | ubyte |
| 436 | dirent_get_cur_time_tenth() |
| 437 | { |
| 438 | tffs_sys_time_t curtm; |
| 439 | uint16 ret; |
| 440 | |
| 441 | Getcurtime(&curtm); |
| 442 | |
| 443 | ret = (curtm.tm_sec & 1) == 0 ? 0 : 100; |
| 444 | return ret; |
| 445 | } |
| 446 | |
| 447 | /*----------------------------------------------------------------------------------------------------*/ |
| 448 | |
| 449 | static int32 |
| 450 | _get_dirent( |
| 451 | IN tdir_t * pdir, |
| 452 | OUT dir_entry_t * pdirent) |
| 453 | { |
| 454 | int32 ret; |
| 455 | |
| 456 | ret = DIRENTRY_OK; |
| 457 | |
| 458 | if (pdir->cur_dir_entry < |
| 459 | (pdir->ptffs->pbs->byts_per_sec / sizeof(dir_entry_t))) { |
| 460 | Memcpy(pdirent, (dir_entry_t *)pdir->secbuf + pdir->cur_dir_entry, sizeof(dir_entry_t)); |
| 461 | pdir->cur_dir_entry++; |
| 462 | } |
| 463 | else { |
| 464 | if (fat_get_next_sec(pdir->ptffs->pfat, &pdir->cur_clus, &pdir->cur_sec)) { |
| 465 | pdir->cur_dir_entry = 0; |
| 466 | if ((ret = dir_read_sector(pdir)) == DIR_OK) { |
| 467 | Memcpy(pdirent, (dir_entry_t *)pdir->secbuf + pdir->cur_dir_entry, sizeof(dir_entry_t)); |
| 468 | pdir->cur_dir_entry++; |
| 469 | } |
| 470 | else { |
| 471 | ret = ERR_DIRENTRY_DEVICE_FAIL; |
| 472 | } |
| 473 | } |
| 474 | else { |
| 475 | ret = ERR_DIRENTRY_NOMORE_ENTRY; |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | return ret; |
| 480 | } |
| 481 | |
| 482 | static void |
| 483 | _parse_file_name( |
| 484 | IN tdir_t * pdir, |
| 485 | IN dir_entry_t * pdirent, |
| 486 | OUT tdir_entry_t * pdir_entry) |
| 487 | { |
| 488 | int32 lf_entry_num; |
| 489 | |
| 490 | /* |
| 491 | * Marvell fixed: pdir_entry->pdirent is allocated below, while |
| 492 | * the function is called in a loop, e.g. in dirent_find(), so |
| 493 | * the previously allocated memory should be released to prevent |
| 494 | * a memory leak: with a lot of files in the working dir, searches |
| 495 | * exhausted the heap and following allocations failed. |
| 496 | */ |
| 497 | if (pdir_entry->pdirent) { |
| 498 | /* This is 0 after dirent_init() unless object re-used */ |
| 499 | Free(pdir_entry->pdirent); |
| 500 | pdir_entry->pdirent = NULL; |
| 501 | } |
| 502 | lf_entry_num = 0; |
| 503 | /* Marvell fixed: was "& ATTR_LONG_NAME", however one of the bits |
| 504 | is ATTR_VOLUME_ID, which alone indicates a volume id, short */ |
| 505 | if (pdirent->dir_attr == ATTR_LONG_NAME) { |
| 506 | uint32 lf_i; |
| 507 | dir_entry_t dirent; |
| 508 | |
| 509 | lf_entry_num = pdirent->dir_name[0] & ~(LAST_LONG_ENTRY); |
| 510 | pdir_entry->pdirent = (dir_entry_t *)Malloc((lf_entry_num + 1) * sizeof(dir_entry_t)); |
| 511 | |
| 512 | _get_long_file_name(pdirent, pdir_entry->long_name + (lf_entry_num - 1) * 13); |
| 513 | Memcpy(pdir_entry->pdirent, pdirent, sizeof(dir_entry_t)); |
| 514 | |
| 515 | for (lf_i = 1; lf_i < lf_entry_num; lf_i++) { |
| 516 | _get_dirent(pdir, &dirent); |
| 517 | Memcpy(pdir_entry->pdirent + lf_i, &dirent, sizeof(dir_entry_t)); |
| 518 | _get_long_file_name(&dirent, pdir_entry->long_name + (lf_entry_num - lf_i - 1) * 13); |
| 519 | } |
| 520 | |
| 521 | _get_dirent(pdir, &dirent); |
| 522 | Memcpy(pdir_entry->pdirent + lf_i, &dirent, sizeof(dir_entry_t)); |
| 523 | } |
| 524 | else { |
| 525 | pdir_entry->pdirent = (dir_entry_t *)Malloc(sizeof(dir_entry_t)); |
| 526 | |
| 527 | _convert_short_fname(pdirent->dir_name, pdir_entry->long_name); |
| 528 | Memcpy(pdir_entry->pdirent, pdirent, sizeof(dir_entry_t)); |
| 529 | } |
| 530 | |
| 531 | _convert_short_fname(pdirent->dir_name, pdir_entry->short_name); |
| 532 | pdir_entry->dirent_num = lf_entry_num + 1; |
| 533 | } |
| 534 | |
| 535 | static ubyte |
| 536 | _get_check_sum( |
| 537 | IN ubyte * fname) |
| 538 | { |
| 539 | int16 fname_len; |
| 540 | ubyte sum; |
| 541 | |
| 542 | sum = 0; |
| 543 | for (fname_len = 11; fname_len != 0; fname_len--) { |
| 544 | sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + *fname++; |
| 545 | } |
| 546 | return sum; |
| 547 | } |
| 548 | |
| 549 | static BOOL |
| 550 | _convert_to_short_fname( |
| 551 | IN byte * fname, |
| 552 | OUT ubyte * short_fname) |
| 553 | { |
| 554 | byte * pfname; |
| 555 | byte * pcur; |
| 556 | uint16 sf_i; |
| 557 | static uint16 num_tail = 0; |
| 558 | |
| 559 | for (sf_i = 0; sf_i < 11; sf_i++) |
| 560 | short_fname[sf_i] = ' '; |
| 561 | |
| 562 | if (!Strcmp(fname, ".") || !Strcmp(fname, "..")) { |
| 563 | /* Marvell fixed: names should not be 0-terminated */ |
| 564 | Memcpy((byte *)short_fname, fname, Strlen(fname)); |
| 565 | return TRUE; |
| 566 | } |
| 567 | |
| 568 | pfname = dup_string(fname); |
| 569 | pcur = pfname; |
| 570 | sf_i = 0; |
| 571 | |
| 572 | trip_blanks(pfname); |
| 573 | |
| 574 | while (sf_i < 8) { |
| 575 | if (*pcur == '\0' || *pcur == '.') { |
| 576 | break; |
| 577 | } |
| 578 | short_fname[sf_i++] = Toupper(*pcur++); |
| 579 | } |
| 580 | |
| 581 | if (*pcur == '.') { |
| 582 | pcur++; |
| 583 | } |
| 584 | else { |
| 585 | if (*pcur != '\0') { |
| 586 | byte str_tail[8]; |
| 587 | |
| 588 | while(*pcur && *pcur != '.') |
| 589 | pcur++; |
| 590 | |
| 591 | if (*pcur == '.') |
| 592 | pcur++; |
| 593 | |
| 594 | Sprintf(str_tail, "~%d", num_tail++); |
| 595 | Memcpy(short_fname + (8 - Strlen(str_tail)), str_tail, Strlen(str_tail)); |
| 596 | |
| 597 | if (*pcur == '\0') |
| 598 | goto _release; |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | sf_i = 8; |
| 603 | |
| 604 | while (sf_i < 11) { |
| 605 | if (*pcur == '\0') |
| 606 | break; |
| 607 | short_fname[sf_i++] = Toupper(*pcur++); |
| 608 | } |
| 609 | |
| 610 | _release: |
| 611 | Free(pfname); |
| 612 | return TRUE; |
| 613 | } |
| 614 | |
| 615 | static BOOL |
| 616 | _get_long_file_name( |
| 617 | IN dir_entry_t * pdirent, |
| 618 | OUT byte * long_name) |
| 619 | { |
| 620 | long_dir_entry_t * pldirent; |
| 621 | |
| 622 | pldirent = (long_dir_entry_t *)pdirent; |
| 623 | |
| 624 | copy_from_unicode(pldirent->ldir_name1, 5, long_name); |
| 625 | copy_from_unicode(pldirent->ldir_name2, 6, long_name + 5); |
| 626 | copy_from_unicode(pldirent->ldir_name3, 2, long_name + 11); |
| 627 | return TRUE; |
| 628 | } |
| 629 | |
| 630 | static BOOL |
| 631 | _convert_short_fname( |
| 632 | IN ubyte * dir_name, |
| 633 | OUT byte * d_name) |
| 634 | { |
| 635 | uint32 i; |
| 636 | |
| 637 | Memset(d_name, 0, 11); |
| 638 | for (i = 0; i < 8; i++) { |
| 639 | if (dir_name[i] == ' ') |
| 640 | break; |
| 641 | d_name[i] = dir_name[i]; |
| 642 | } |
| 643 | |
| 644 | if (dir_name[8] != ' ') { |
| 645 | uint32 j; |
| 646 | |
| 647 | d_name[i++] = '.'; |
| 648 | for (j = 0; j < 3; j++) { |
| 649 | if (dir_name[8 + j] == ' ') |
| 650 | break; |
| 651 | d_name[i + j] = dir_name[8 + j]; |
| 652 | } |
| 653 | } |
| 654 | return TRUE; |
| 655 | } |
| 656 | |