Re: Bug in fat-fs code: file date/time wrong

Joe Zbiciak (jzbiciak@dal.asp.ti.com)
Mon, 15 Nov 1999 02:19:04 -0600


Peter Samuelson [peter@wire.cadcamlab.org] wrote:
| Check it yourself.

I don't have the Win9x box handy at the moment.

| But what seems to be happening, according to my
| limited perusal, is that if you created a file in NT4 at 3:00 AM in
| Central Daylight Time (GMT-0500) and put it on a FAT floppy, the time
| stored on the floppy is 3:00 AM, no particular timezone. Then if you
| do a `dir' on that floppy a couple months later in Central Standard
| Time (GMT-0600), it will still say 3:00 AM. FAT does not care about
| time changes and it assumes everyone who will ever have access to a
| particular file will be in the same time zone.

Ok, that's what I _thought_ they did. It's the only behavior which
makes any sense to me. Your proposal would have the time reported
for the file change to 4:00AM during CST if it was written at 3:00AM
during CDT.

| On an ext2 filesystem in Linux, on the other hand, the timestamp stored
| would have been 8:00 AM, i.e. UTC; `ls' converts this to 3:00 AM
| because it knows about DST conversions and when to do them and when not
| to, thanks to libc functions specializing in this. If you set TZ to
| something else, then do the `ls', it will convert the UTC value to
| whatever else you wanted.

Correct. This illustrates the power of a GMT-based system. What's
even neater is that different users can have TZ set differently
for themselves, allowing each to see the times reported according
to their timezone. This is the Right Way, IMHO. :-)

| So the thing to do for Linux FAT, in order to show the same timestamps
| as NT4 does (AFAICT), is to convert from UTC to local when writing and

This isn't a huge issue, it's solved by a constant offset that's
modified as we enter/leave DST as you note, since we are always at
'now' now. There is a small race for files created near the
DST/non-DST boundary, though, if the change is made from user-space.
Also, it doesn't handle touching files with dates other than "now".

| from local to UTC when reading.

This is not handled by a constant offset. The offset in effect
right now may be different than the offset that was in effect when
I wrote the file. If I apply the current offset to the file when
converting from local to UTC, I will get the wrong time, because
'ls' or whatever will convert it back to local with the correct
offset, which is different from the current offset.

| Yes, that's
| *contant* offset -- do not attempt to correct for DST or non-DST *when
| the file was written*. The only time to change that offset is when DST
| *itself* comes or goes.

This works for updating timestamps. It does not work for reading
timestamps that were updated when the time offset was different than
it currently is now.

For instance, suppose I'm at GMT -0500, so my offset is -5 hours, and
DST is in effect. I write a file at noon local time. When I write the
file, I report the current time as 17:00 GMT, it subtracts 5, and
records the time in the filesystem as 12:00.

Now, a few months later, daylight savings time is no longer in effect.
That means I'm now at GMT -0600, so my offset is -6 hours. I go back
to read the file. The kernel sees "12:00" and adds 6, and reports that
the file was written at 19:00 GMT on the date a few months back. The
userspace program sees the date, knows DST was in effect at the time,
and it tells me I wrote the file at 1:00PM. Ooops, we broke.

What I'm saying is this: The conversions that the kernel performs must
mirror exactly the conversions that user-space performs so that the
intermediate jump to GMT cancels out for all dates in the past and
present.

| I do not know whether FAT already has this behavior on Linux. My
| system's FAT seems to report times in UTC but I don't know if there's a
| way to add the "local" offset I describe above.

>From what I understand, FAT stores dates in local time. If you do
not set a timezone at boot, then local time is GMT/UTC.

| > For instance, if I create a file while DST is active, and then I look
| > at it when DST is inactive, I should see the same time-stamp as I did
| > back when DST was active, not an hour different.
|
| With my scheme, you won't (which is why I noted that it would break
| normal Unix semantics), but at least the file will have been stored the
| same way on disk as it would have been in your legacy system.

Essentially, one-way interoperability: I can send data to the
legacy systems that the legacy systems interpret correctly, but
the data I see is not quite 100% correct.

| If you
| want complete interoperability, you will need to define a non-DST-able
| time zone and manually change it twice a year.

Ick. That'll break all the native Unix stuff. Now the file I
created during DST on the ext2 partition will show a different time
when I'm not in DST.

| [...] It comes back to: if we don't bother with
| compatibility with the legacy systems, there are a lot of ways to make
| up for some of the deficiencies in FAT. But then again, if we don't
| bother with compatibility with the legacy systems, we don't *need* FAT.

The easiest way to make up for the deficiencies in FAT is to not
use it at all (as you note). :-)

Regards,

--Joe

-- 
-- Joseph Zbiciak             |  "Never worry about the theory        --
-- j-zbiciak1@ti.com          |   as long as the machinery            --
-- #include <std_disc.h>      |   does what it is supposed to do."    --
-- Texas Instruments, Dallas  |                        -- Heinlein    --

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/