c++data-conversionfusetimevaltimespec

How to correctly convert timespec to timeval?


I have a struct timespec object I need to convert to struct timeval for use with lutimes(...).

I've attempted the following, but lutimes() complains.

const struct timespec ts; // originally provided as function parameter from FUSE
struct timeval tv;
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
lutimes(path, tv); // returns -1; errno=EINVAL

Now EINVAL from lutimes means the usec component was outside of 0 <= tv_usec < 1000000, meaning the conversion from timespec went wrong. [source]

How do I properly convert from timespec to timeval?


More thorough debugging with the touch command, reveals that timespec contains tv_sec = 0 and tv_nsec > 1000000000, when no specific date was specified and the current time should be used.

Why is this? What's the proper way to handle this?


Solution

  • First I'll clarify what was not clear to me at first from the question: This is implementation of the utimens operation in fuse filesystem and the problem is that sometimes the tv_nsec field has value bigger or equal to 1,000,000,000.

    My guess is that it is one of the two special values: UTIME_NOW or UTIME_OMIT.

    The fuse documentation points to the utimensat manual page, which has explanation for those special values: http://man7.org/linux/man-pages/man2/utimensat.2.html


    Also check the nsec_valid function in linux kernel:

    https://elixir.free-electrons.com/linux/v4.15.2/source/fs/utimes.c#L40