esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.08k stars 13.33k forks source link

ESP8266 LittleFS.mkdir timestamp is always 1-1-1970 (?) #9120

Closed arjenv closed 5 months ago

arjenv commented 7 months ago

Running a webserver with javascript on an ESP8266. The ESP is not connected to the WWW, however the client is and returns an epoch upon request from the ESP.

I then set the time with setTime(new_epoch), in which new_epoch is the nr of seconds from 1-1-1970 returned by the client. Client runs from cellphone or PC with a WWW connection.

I check the set time via Serial.print. It is correct.

When I then try and save a new file to LittleFS the timestamp is wrong, it is equal to the 'on' time as returned by milis().

When I add a settimecallback just before the open to write:

File file = LittleFS.open(fullpath, "w");

the timestamp is correct.

Sofar so good.

I then try and create a new directory with LittleFS.mkdir(path). The directory is created but the timestamp is always 1-1-1970 at 0:0:0 time. Calling the settimecallback() does not solve this.

When settimecallback is called before I open a new file with a directory in front of it, the directory is created and the file is created. The file has the correct timestamp, the directory, however, has again timestamp 1-1-1970

File file = LittleFS.open("newdir/foo.bar, "w");

foor.bar has the correct timestamp. /newdir/ (directory) has timestamp 1-1-1970.

Is this an issue or did I do something wrong here?

Is bugging me for three days now...

Your input is welcomed. Thanks for your great work.

mcspr commented 7 months ago

Looking at the code, we manually add 'c' and 't' littlefs attributes for creation and modification times respectively. This is not the case for directories leading to the file, though. You'd have to manually add those, should you need them? (edit: or littlefs can, for example, walk file list and get 'latest' time from directory contents. would not work for empty dirs, though)

Check out these lines in lfs lib https://github.com/esp8266/Arduino/blob/685f2c97ff4b3c76b437a43be86d1dfdf6cb33e3/libraries/LittleFS/src/LittleFS.h#L484-L505

Specifically https://github.com/esp8266/Arduino/blob/685f2c97ff4b3c76b437a43be86d1dfdf6cb33e3/libraries/LittleFS/src/LittleFS.h#L492-L495

arjenv commented 7 months ago

Thank you for your reply. You're obviously much more into this code than I am since you are probably one of the writers. Could you make it simpler for me?

Am I to understand that it is possible to set the time attribute of the LittleFS files and directories separately? If so could you post an example on how to do that?

I further searched - and I am aware that this is more of a forum question but could not find the answer- how to invoke the debug statements (DEBUGV) so I have some more debug statements while I try stuff within the LittleFS library? I guess a simple '#define DEBUGV' will not do.

I (still) use the arduino IDE thus far. Thanks.

mcspr commented 7 months ago

The example is above, I would suggest to read up the LittleFS.{cpp,h} code first. The way you can handle it is by modifying your own private copy of Core and LittleFS library and then do lfs_setattr on directories leading to the file itself in file ::close() method. Like it already does for the file itself, but use directory path(s) instead.

I have tried to write a small example, but I turns out while we have pretty nice API for internal use, there does not seem to be a way to easily substitute LittleFS File class with a custom one :/ Since it is explicitly named in multiple places, and sometimes requires protected member access, it becomes pretty overwhelming very fast (unless I am really missing some obvious way to replace target file impl without doing it... have to think about it a bit)

arjenv commented 7 months ago

Thanks again. This is, however, way beyond my capability. I'd rather not fiddle with the library itself. Can I not just set the attributes with some function setAttributes(dir, time). or so? My programming skills are not that sophisticated....

mcspr commented 7 months ago

Depends on what the problem is. The way our littlefs wrapper works, creation and write times are bound to files. Without changing anything, directories are never going to show the attribute as it is simply not there. As far as I can tell, arbitrary binary attributes are currently specific to littlefs and there is no generic way to access them from the outside.

If the goal is to simply get this timestamp value in the app , simply iterating files and finding the 'max' value based on common root should do it?

#include <Arduino.h>
#include <LittleFS.h>

#include <array>
#include <algorithm>
#include <vector>

#include <inttypes.h>

void setup() {
    Serial.begin(115200);
    LittleFS.begin();

    const std::array paths{
        "/common/1.txt",
        "/common/2.txt",
        "/common/3.txt",
    };

    for (auto& path : paths) {
        auto file = LittleFS.open(path, "w");
        delay(1000);
        file.write("123456789");
    }

    std::vector<time_t> times;
    for (auto& path : paths) {
        auto file = LittleFS.open(path, "r");

        auto last = file.getLastWrite();
        Serial.printf("%s last write -> %" PRId64 "\n",
            file.name(), last);

        times.push_back(last);
    }

    Serial.printf("\nlast write time for /common/ -> %" PRId64 "\n",
            *std::max_element(times.begin(), times.end()));
}

void loop() {
}

Running the app

1.txt last write -> 1712926053
2.txt last write -> 1712926054
3.txt last write -> 1712926055

last write time for /common/ -> 1712936855
arjenv commented 7 months ago

It's the 'dirt n nasty' solution (I like that BTW :-) ).

arjenv commented 7 months ago

Now when I upload the 'data' next to my sketch, the directory timestamp is actually there. It copies the timestamp from the PC. So how can that be when there is no timestamp for directories?.

I would still like to pose the question to implement a sort of 'set attribute' functionality to this library. I think it would be an extra asset. So not an issue, but a kind request.