diff mbox

[v2,CIFS] Fix setting time before epoch (negative time values)

Message ID CAH2r5mtLFMqkyoJKVzxUBLfSVwo+3i+XVB6S-_ahQ8ZkpFsD0g@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Steve French Sept. 16, 2014, 5:51 a.m. UTC
Resending as attachment to avoid mailer issues

On Mon, Sep 15, 2014 at 12:14 PM, Christoph Hellwig <hch@infradead.org> wrote:
>>      /* Subtract the NTFS time offset, then convert to 1s intervals. */
>> -    u64 t;
>> +    s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
>> +
>> +    /*
>
> The patch looks whitespace damaged.
>
diff mbox

Patch

From 2ae83bf93882d1ec0cd775c489bd1bee611f792e Mon Sep 17 00:00:00 2001
From: Steve French <smfrench@gmail.com>
Date: Sun, 14 Sep 2014 17:06:36 -0500
Subject: [PATCH 1/4] [CIFS] Fix setting time before epoch (negative time
 values)

xfstest generic/258 sets the time on a file to a negative value
(before 1970) which fails since do_div can not handle negative
numbers.  In addition 'normal' division of 64 bit values does
not build on 32 bit arch so have to workaround this by special
casing negative values in cifs_NTtimeToUnix

Samba server also has a bug with this (see samba bugzilla 7771)
but it works to Windows server.

Signed-off-by: Steve French <smfrench@gmail.com>
---
 fs/cifs/netmisc.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 6834b9c..b333ff6 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -925,11 +925,23 @@  cifs_NTtimeToUnix(__le64 ntutc)
 	/* BB what about the timezone? BB */
 
 	/* Subtract the NTFS time offset, then convert to 1s intervals. */
-	u64 t;
+	s64 t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
+
+	/*
+	 * Unfortunately can not use normal 64 bit division on 32 bit arch, but
+	 * the alternative, do_div, does not work with negative numbers so have
+	 * to special case them
+	 */
+	if (t < 0) {
+		t = -t;
+		ts.tv_nsec = (long)(do_div(t, 10000000) * 100);
+		ts.tv_nsec = -ts.tv_nsec;
+		ts.tv_sec = -t;
+	} else {
+		ts.tv_nsec = (long)do_div(t, 10000000) * 100;
+		ts.tv_sec = t;
+	}
 
-	t = le64_to_cpu(ntutc) - NTFS_TIME_OFFSET;
-	ts.tv_nsec = do_div(t, 10000000) * 100;
-	ts.tv_sec = t;
 	return ts;
 }
 
-- 
1.9.1