greiman / SdFat

Arduino FAT16/FAT32 exFAT Library
MIT License
1.08k stars 509 forks source link

error: 'class FsFile' has no member named 'readDir' (or how to imlement detailed file list with v2.x?) #254

Open stevstrong opened 3 years ago

stevstrong commented 3 years ago

Hi, after updating to v.2.x I have said error message when trying to compile the code which was ok for v1.x. I can see that readDir() is member of FatFile, but not in FsFile: https://github.com/greiman/SdFat/blob/cb5a7d2afb4eb94f2563044645fc816f0ea4c2c8/src/FatLib/FatFile.cpp#L834 I was implementing a directory listing with detailed information based on the lsPrintNext function from the old SdFile.cpp:

    // This code is just copied from SdFile.cpp (lsPrintNext) of the SDFat library
    while ( file.readDir(&dir) > 0 )
    {
        // done if past last used entry
        if (dir.name[0] == DIR_NAME_FREE) break;
        // skip deleted entry and entries for . and  ..
        if (dir.name[0] == DIR_NAME_DELETED || dir.name[0] == '.') continue;
        // only list subdirectories and files
        if (!DIR_IS_FILE_OR_SUBDIR(&dir)) continue;

        f_ind = 0;
        // print any indent spaces
        File_BufAdd_P(PSTR("<tr><td style='text-align:left'><a href='"));
        for (byte i = 0; i < 11; i++) {
            if (dir.name[i] == ' ') continue;
            if (i == 8)     f_buf[f_ind++] = '.';
            f_buf[f_ind++] = (char)dir.name[i];
        }
        if ( DIR_IS_SUBDIR(&dir) )  f_buf[f_ind++] = '/';
        f_buf[f_ind++] = '\''; f_buf[f_ind++] = '>';
        // print file name with possible blank fill
        for (byte i = 0; i < 11; i++) {
            if (dir.name[i] == ' ') continue;
            if (i == 8)  f_buf[f_ind++] = '.';
            f_buf[f_ind++] = (char)dir.name[i];
        }
        if ( DIR_IS_SUBDIR(&dir) )  f_buf[f_ind++] = '/';
        File_BufAdd_P(PSTR("</a></td><td>"));
        // next cell is the file size
        if ( DIR_IS_SUBDIR(&dir) ) {
            File_BufAdd_P(PSTR(" - "));
        } else { //if ( flags & LS_SIZE ) // print size if requested
            sprintf_P(f_buf+f_ind, PSTR("%6lu"), (long int)dir.fileSize); f_ind += 6;
        }
        //client.print(F("</td><td>"));
        File_BufAdd_P(PSTR("</td><td>"));
        // write next cell: print modify date/time
        sprintf(f_buf+f_ind, PSTR("%4u-%02u-%02u %02u:%02u:%02u"),
            int(FAT_YEAR(dir.lastWriteDate)), FAT_MONTH(dir.lastWriteDate), FAT_DAY(dir.lastWriteDate),
            FAT_HOUR(dir.lastWriteTime), FAT_MINUTE(dir.lastWriteTime), FAT_SECOND(dir.lastWriteTime));
        f_ind += 19;  // the length of date and time
        //client.println(F("</td></tr>"));
        File_BufAdd_P(PSTR("</td></tr>\n"));
        // send here the table line string to ethernet client
        cl.print(f_buf);
    }

There are several other related error messages as well, like: error: 'DIR_NAME_FREE' was not declared in this scope error: 'DIR_NAME_DELETED' was not declared in this scope error: 'DIR_IS_SUBDIR' was not declared in this scope - found alternative: isDir() error: 'DIR_IS_FILE_OR_SUBDIR' was not declared in this scope - found alternative: isFileOrSubdir(dir) error: 'struct DirFat_t' has no member named 'lastWriteDate' error: 'struct DirFat_t' has no member named 'lastWriteTime' error: 'FAT_MINUTE' was not declared in this scope error: 'FAT_YEAR' was not declared in this scope error: 'FAT_DAY' was not declared in this scope error: 'FAT_SECOND' was not declared in this scope

Can you please suggest alternatives for these expressions? Or eventually an alternative way how can I implement the same functionality with v2.x? The old method yield the following result: image I appreciate any advice, thank you in advance.

greiman commented 3 years ago

I lifted new definitions for file system structures from various places since exFAT has a totally different structures than FAT, I needed unique symbols for both and I wanted to allow for future use on processors with various endian and alignment requirements.

The new symbols are here. Notice that all definitions are in terms of uint8_t bytes, not packed structs.

There can be no function like readDir() for FsFile with both FAT16/FAT32 and exFAT.

I am trying to add functions to get more properties of files to FsFile. More new functions are in SdFat-beta in FsFile.h.

uint64_t fileSize();
bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime);
bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime);
bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime)
bool isContiguous();
bool isDir();
bool isFile();
bool isHidden();
bool isReadOnly();

I am still changing date/time functions. The definitions are in FsDateTime.h these formatting functions will change.

stevstrong commented 3 years ago

Thanks a lot for the reply, I will have a look on those functions. I want to use readDir() so I changed FsFileinstance to FatFile and it worked. I will come back after I finished the replacement of all other functions/symbols, so please keep this open till then.

stevstrong commented 3 years ago

While looking for a replacement for isDir(&dir) I have found isFileDir(&dir) in FsStructs.h. Is that the correct replacement? I am not sure because the name isFileDir(&dir) could mean (isFile or isDir)(dir). Or this name was selected just to differentiate from file.isDir().

greiman commented 3 years ago

Don't know where isFileDir came from, I don't use it. I copied the stuff in FsStructs.h from various sources that reverse engineered FAT, exFAT and other file systems.

I should warn you that anything you use in FsStructs.h to interpret a directory entry may go away or change at any time. It is not in the documentation for supported functions/symbols.

You can use the Microsoft spec for FAT to define your own symbols:

https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc

I will probably mark readDir(DirFat_t* dir) as deprecated since it is specific to FAT and I don't use it. It was a mistake I made 10 years ago before I added functions for file attributes.

Just open a directory and call read but don't expect support. read(dir, sizeof(DirFat_t));

I provided openNext() as the supported way to open all files in a directory and get their properties.

Here are the supported attribute functions for an open FAT16/FAT32 file.

  /** \return True if this is a directory. */
  bool isDir() const
  /** \return True if this is a normal file. */
  bool isFile() const
  /** \return True if this is a hidden file. */
  bool isHidden() const
  /** \return true if this file has a Long File Name. */
  bool isLFN() const
  /** \return True if this is an open file/directory. */
  bool isOpen() const 
  /** \return True file is readable. */
  bool isReadable() const
  /** \return True if file is read-only */
  bool isReadOnly() const
  /** \return True if this is the root directory. */
  bool isRoot() const
  /** \return True if this is the FAT32 root directory. */
  bool isRoot32() const 
  /** \return True if this is the FAT12 of FAT16 root directory. */
  bool isRootFixed() const
  /** \return True if this is a subdirectory. */
  bool isSubDir() const
  /** \return True if this is a system file. */
  bool isSystem() const
  /** \return True file is writable. */
  bool isWritable() const

Eventually attributes common to FAT and exFAT will be supported for FsFile.