| 709 | } |
| 710 | |
| 711 | int FileSystem::readdir(DirHandle dir, Stat& stat) |
| 712 | { |
| 713 | GET_FILEDIR() |
| 714 | |
| 715 | SPIFFS_clearerr(handle()); |
| 716 | spiffs_dirent e; |
| 717 | for(;;) { |
| 718 | if(SPIFFS_readdir(&d->d, &e) == nullptr) { |
| 719 | int err = SPIFFS_errno(handle()); |
| 720 | if(err == SPIFFS_OK) { |
| 721 | return Error::NoMoreFiles; |
| 722 | } |
| 723 | |
| 724 | return translateSpiffsError(err); |
| 725 | } |
| 726 | |
| 727 | /* The volume doesn't contain directory objects, so at each level we need |
| 728 | * to identify sub-folders and insert a virtual 'directory' object. |
| 729 | */ |
| 730 | |
| 731 | auto name = (char*)e.name; |
| 732 | |
| 733 | // For sub-directories, match the parsing path |
| 734 | auto len = strlen(name); |
| 735 | if(d->pathlen != 0) { |
| 736 | if(len <= d->pathlen) { |
| 737 | // debug_i("Ignoring '%s' - too short for '%s'", name, d->path); |
| 738 | continue; |
| 739 | } |
| 740 | |
| 741 | if(name[d->pathlen] != '/') { |
| 742 | // debug_i("Ignoring '%s' - no '/' in expected position to match '%s'", name, d->path); |
| 743 | continue; |
| 744 | } |
| 745 | |
| 746 | if(memcmp(d->path, name, d->pathlen) != 0) { |
| 747 | // debug_i("Ignoring '%s' - doesn't match '%s'", name, d->path); |
| 748 | continue; |
| 749 | } |
| 750 | |
| 751 | name += d->pathlen + 1; |
| 752 | } |
| 753 | |
| 754 | // This is a child directory |
| 755 | char* nextSep = strchr(name, '/'); |
| 756 | if(nextSep != nullptr) { |
| 757 | *nextSep = '\0'; |
| 758 | auto len = 1 + nextSep - name; // Include NUL terminator |
| 759 | // Emit directory names only once |
| 760 | auto dirEmitted = [&]() { |
| 761 | unsigned i = 0; |
| 762 | while(i < d->directories.length()) { |
| 763 | auto p = &d->directories[i]; |
| 764 | auto len = strlen(p); |
| 765 | if(strcmp(p, name) == 0) { |
| 766 | return true; |
| 767 | } |
| 768 | i += len + 1; |