public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] UTC timestamp option for FAT filesystems
@ 2008-06-25  5:24 Joe Peterson
  2008-06-25 22:33 ` Andi Kleen
  0 siblings, 1 reply; 27+ messages in thread
From: Joe Peterson @ 2008-06-25  5:24 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1449 bytes --]

(This patch is based on one submitted last year by Paul Collins, but it
is updated to work with current source, and it uses a different option
name.)

Attached is a patch to provide a new mount option ("utc") for DOS
(vfat/msdos) filesystems, allowing timestamps to be in universal
coordinated time (UTC) rather than local time in applications where
doing this is advantageous.

Since DOS filesystems do not contain time zone information, and
timestamps are typically in local time, a file written in one time
zone will be wrong when read in a different time zone.  When interacting
with filesystems written or read in Windows, using local time is
often necessary, but there are other situations in which the
problems with using local time can be avoided.

Many digital cameras and other portable devices use vfat, and when
traveling across time zones it is inconvenient and confusing to
change the clock setting, but downloading files to a computer in
a different time zone will result in erroneous timestamps.  Also,
it is often necessary to remember to manually change the clock at
daylight saving time changes.  Forgetting to do this also results
in incorrect timestamps.

Setting the clock to UTC is an obvious solution, eliminating
these issues, but Linux is currently hard-coded to always offset the
timestamps by sys_tz.tz_minuteswest in order to interpret them as
local time only.  The new mount option removed this limitation.

						-Joe

[-- Attachment #2: utc-timestamp-option-for-fat-filesystems.patch --]
[-- Type: text/x-patch, Size: 7510 bytes --]

New mount option ("utc") for DOS (vfat/msdos) filesystems allowing
timestamps to be in universal coordinated time (UTC) rather than
local time in applications where doing this is advantageous (like
digital cameras, etc.)

Signed-off-by: Joe Peterson <joe@skyrush.com>
---

diff -ur linux-2.6.26-rc7-git1.old/fs/fat/dir.c linux-2.6.26-rc7-git1/fs/fat/dir.c
--- linux-2.6.26-rc7-git1.old/fs/fat/dir.c	2008-06-24 13:46:02.000000000 -0600
+++ linux-2.6.26-rc7-git1/fs/fat/dir.c	2008-06-24 14:12:56.000000000 -0600
@@ -1082,7 +1082,7 @@
 		goto error_free;
 	}
 
-	fat_date_unix2dos(ts->tv_sec, &time, &date);
+	fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.utc);
 
 	de = (struct msdos_dir_entry *)bhs[0]->b_data;
 	/* filling the new directory slots ("." and ".." entries) */
diff -ur linux-2.6.26-rc7-git1.old/fs/fat/inode.c linux-2.6.26-rc7-git1/fs/fat/inode.c
--- linux-2.6.26-rc7-git1.old/fs/fat/inode.c	2008-06-24 13:46:02.000000000 -0600
+++ linux-2.6.26-rc7-git1/fs/fat/inode.c	2008-06-24 14:40:52.000000000 -0600
@@ -382,17 +382,20 @@
 	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
 			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
 	inode->i_mtime.tv_sec =
-		date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
+		date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
+			      sbi->options.utc);
 	inode->i_mtime.tv_nsec = 0;
 	if (sbi->options.isvfat) {
 		int secs = de->ctime_cs / 100;
 		int csecs = de->ctime_cs % 100;
 		inode->i_ctime.tv_sec  =
 			date_dos2unix(le16_to_cpu(de->ctime),
-				      le16_to_cpu(de->cdate)) + secs;
+				      le16_to_cpu(de->cdate),
+				      sbi->options.utc) + secs;
 		inode->i_ctime.tv_nsec = csecs * 10000000;
 		inode->i_atime.tv_sec =
-			date_dos2unix(0, le16_to_cpu(de->adate));
+			date_dos2unix(0, le16_to_cpu(de->adate),
+				      sbi->options.utc);
 		inode->i_atime.tv_nsec = 0;
 	} else
 		inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -592,11 +595,11 @@
 	raw_entry->attr = fat_attr(inode);
 	raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
-	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
+	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date, sbi->options.utc);
 	if (sbi->options.isvfat) {
 		__le16 atime;
-		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
-		fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate);
+		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate, sbi->options.utc);
+		fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate, sbi->options.utc);
 		raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
 			inode->i_ctime.tv_nsec / 10000000;
 	}
@@ -848,7 +851,7 @@
 	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
-	Opt_obsolate, Opt_flush, Opt_err,
+	Opt_obsolate, Opt_flush, Opt_utc, Opt_err,
 };
 
 static match_table_t fat_tokens = {
@@ -883,6 +886,7 @@
 	{Opt_obsolate, "cvf_options=%100s"},
 	{Opt_obsolate, "posix"},
 	{Opt_flush, "flush"},
+	{Opt_utc, "utc"},
 	{Opt_err, NULL},
 };
 static match_table_t msdos_tokens = {
@@ -947,6 +951,7 @@
 	opts->utf8 = opts->unicode_xlate = 0;
 	opts->numtail = 1;
 	opts->usefree = opts->nocase = 0;
+	opts->utc = 0;
 	*debug = 0;
 
 	if (!options)
@@ -1036,6 +1041,9 @@
 		case Opt_flush:
 			opts->flush = 1;
 			break;
+		case Opt_utc:
+			opts->utc = 1;
+			break;
 
 		/* msdos specific */
 		case Opt_dots:
diff -ur linux-2.6.26-rc7-git1.old/fs/fat/misc.c linux-2.6.26-rc7-git1/fs/fat/misc.c
--- linux-2.6.26-rc7-git1.old/fs/fat/misc.c	2008-04-16 20:49:44.000000000 -0600
+++ linux-2.6.26-rc7-git1/fs/fat/misc.c	2008-06-24 14:44:05.000000000 -0600
@@ -142,7 +142,7 @@
 };
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-int date_dos2unix(unsigned short time, unsigned short date)
+int date_dos2unix(unsigned short time, unsigned short date, int utc)
 {
 	int month, year, secs;
 
@@ -156,16 +156,18 @@
 	    ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
 	    month < 2 ? 1 : 0)+3653);
 			/* days since 1.1.70 plus 80's leap day */
-	secs += sys_tz.tz_minuteswest*60;
+	if (!utc)
+		secs += sys_tz.tz_minuteswest*60;
 	return secs;
 }
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
-void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
+void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int utc)
 {
 	int day, year, nl_day, month;
 
-	unix_date -= sys_tz.tz_minuteswest*60;
+	if (!utc)
+		unix_date -= sys_tz.tz_minuteswest*60;
 
 	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
 	if (unix_date < 315532800)
diff -ur linux-2.6.26-rc7-git1.old/fs/msdos/namei.c linux-2.6.26-rc7-git1/fs/msdos/namei.c
--- linux-2.6.26-rc7-git1.old/fs/msdos/namei.c	2008-06-24 13:46:02.000000000 -0600
+++ linux-2.6.26-rc7-git1/fs/msdos/namei.c	2008-06-24 16:32:19.000000000 -0600
@@ -243,6 +243,7 @@
 			   int is_dir, int is_hid, int cluster,
 			   struct timespec *ts, struct fat_slot_info *sinfo)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
 	struct msdos_dir_entry de;
 	__le16 time, date;
 	int err;
@@ -252,7 +253,7 @@
 	if (is_hid)
 		de.attr |= ATTR_HIDDEN;
 	de.lcase = 0;
-	fat_date_unix2dos(ts->tv_sec, &time, &date);
+	fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.utc);
 	de.cdate = de.adate = 0;
 	de.ctime = 0;
 	de.ctime_cs = 0;
diff -ur linux-2.6.26-rc7-git1.old/fs/vfat/namei.c linux-2.6.26-rc7-git1/fs/vfat/namei.c
--- linux-2.6.26-rc7-git1.old/fs/vfat/namei.c	2008-06-24 13:46:03.000000000 -0600
+++ linux-2.6.26-rc7-git1/fs/vfat/namei.c	2008-06-24 14:39:34.000000000 -0600
@@ -621,7 +621,7 @@
 	memcpy(de->name, msdos_name, MSDOS_NAME);
 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 	de->lcase = lcase;
-	fat_date_unix2dos(ts->tv_sec, &time, &date);
+	fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.utc);
 	de->time = de->ctime = time;
 	de->date = de->cdate = de->adate = date;
 	de->ctime_cs = 0;
diff -ur linux-2.6.26-rc7-git1.old/include/linux/msdos_fs.h linux-2.6.26-rc7-git1/include/linux/msdos_fs.h
--- linux-2.6.26-rc7-git1.old/include/linux/msdos_fs.h	2008-06-24 13:46:04.000000000 -0600
+++ linux-2.6.26-rc7-git1/include/linux/msdos_fs.h	2008-06-24 15:03:58.000000000 -0600
@@ -205,7 +205,8 @@
 		 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
 		 flush:1,	  /* write things quickly */
 		 nocase:1,	  /* Does this need case conversion? 0=need case conversion*/
-		 usefree:1;	  /* Use free_clusters for FAT32 */
+		 usefree:1,	  /* Use free_clusters for FAT32 */
+		 utc:1;		  /* Filesystem timestamps are in UTC */
 };
 
 #define FAT_HASH_BITS	8
@@ -428,8 +429,8 @@
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
 extern void fat_clusters_flush(struct super_block *sb);
 extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
+extern int date_dos2unix(unsigned short time, unsigned short date, int utc);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int utc);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
 int fat_cache_init(void);

^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: [PATCH] UTC timestamp option for FAT filesystems
@ 2008-06-25 13:31 barry bouwsma
  2008-06-25 14:42 ` Joe Peterson
  0 siblings, 1 reply; 27+ messages in thread
From: barry bouwsma @ 2008-06-25 13:31 UTC (permalink / raw)
  To: linux-kernel; +Cc: Joe Peterson

Moin moin!

May I just add a resounding YES-YES-YES to the message which was
posted earlier today as
Message-ID: <>
oh b*gger, that doesn't help when snarfing from a web archive
(voluntary use as a non-subscirber of a webmail interface prevents
me from including a References: header without more effort than I
care to do now, not that this would help)


I was actually just about to post an almost identical message today
to clean out my repository of hacks, with almost the same justifications.

In addition, may I request that not only the option `-o utc,...' be
accepted, but also as an alternate, the string `gmt', not because it's
more accurate (it isn't) but because it seems to be tradition to use
GMT+/-xxxx in lots of places.

Another justification which wasn't mentioned, but which I would put
forth, is that last time I checked, the BSDen were using UTC as their
MSDOS timestamp base, so such an option would make it easier to
exchange data between BSD and Linux machines with a normal USB stick
or flash card.  And I was doing that a year or three ago when I hacked
my hack.


I'll have to do a line-by-line comparison with my hacked code (last
applied to 2.6.24-ish) to make sure I don't have any differences, but
in order to allow users the option to specify the seeped-in-tradition-
especially-for-us-old-f*rts `gmt', here's the trivial-to-correct
section of code -- may well be different than in the patch since I
didn't save it before being kicked offline:

in  fs/fat/inode.c
    880         {Opt_debug, "debug"},
    881         {Opt_immutable, "sys_immutable"},
    882 /* XXX HACK */
    883         {Opt_utc, "utc"},
    884         {Opt_utc, "gmt"},
    885         {Opt_obsolate, "conv=binary"},
    886         {Opt_obsolate, "conv=text"},

(I use `-o utc' myself but would prefer to be flexible to alternate uses)
I notice this most when I fail to include the needed patches when
updating kernel

thanks
barry bouwsma


      


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2008-07-02 14:48 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-25  5:24 [PATCH] UTC timestamp option for FAT filesystems Joe Peterson
2008-06-25 22:33 ` Andi Kleen
2008-06-25 23:56   ` Joe Peterson
2008-06-26  2:44     ` Joe Peterson
2008-06-26  7:32       ` OGAWA Hirofumi
2008-06-26 13:23         ` Joe Peterson
2008-06-26 14:37           ` OGAWA Hirofumi
2008-06-26 15:45             ` Joe Peterson
2008-06-26 16:26               ` OGAWA Hirofumi
2008-06-26 17:06                 ` Joe Peterson
2008-06-28 22:24                   ` James Cloos
2008-06-29  5:03                     ` Joe Peterson
2008-06-29  8:20                       ` Bernd Eckenfels
2008-06-26 17:21                 ` Joe Peterson
2008-06-26 18:15                   ` OGAWA Hirofumi
2008-06-27  5:12                   ` Joe Peterson
2008-07-01 23:25                     ` Andrew Morton
2008-07-02  4:43                       ` Joe Peterson
2008-07-01 23:27                     ` Andrew Morton
2008-07-02 14:47                       ` Joe Peterson
2008-06-26 16:01             ` Joe Peterson
2008-06-26 17:08               ` OGAWA Hirofumi
  -- strict thread matches above, loose matches on Subject: below --
2008-06-25 13:31 barry bouwsma
2008-06-25 14:42 ` Joe Peterson
2008-06-25 19:35   ` barry bouwsma
2008-06-26  4:24     ` Joe Peterson
2008-06-26 19:07       ` barry bouwsma

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox