[CIFS] Legacy time handling for Win9x and OS/2 part 1
Signed-off-by: Steve French <sfrench@us.ibm.com>
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b35c55c..2fbc982 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -80,6 +80,9 @@
extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
extern u64 cifs_UnixTimeToNT(struct timespec);
+extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
+extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
+
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO * pfile_info,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 075d8fb..2851d6e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2856,7 +2856,6 @@
return rc;
}
-
/* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */
int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -2898,7 +2897,16 @@
if (rc) {
cFYI(1, ("Send error in QueryInfo = %d", rc));
} else if (pFinfo) { /* decode response */
+ struct timespec ts;
+ __u32 time = le32_to_cpu(pSMBr->last_write_time);
+ /* BB FIXME - add time zone adjustment BB */
memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
+ ts.tv_nsec = 0;
+ ts.tv_sec = time;
+ /* decode time fields */
+ pFinfo->ChangeTime = cifs_UnixTimeToNT(ts);
+ pFinfo->LastWriteTime = pFinfo->ChangeTime;
+ pFinfo->LastAccessTime = 0;
pFinfo->AllocationSize =
cpu_to_le64(le32_to_cpu(pSMBr->size));
pFinfo->EndOfFile = pFinfo->AllocationSize;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b88147c..06dbce3 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -432,8 +432,11 @@
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
/* Linux can not store file creation time so ignore it */
- inode->i_atime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ if(pfindData->LastAccessTime)
+ inode->i_atime = cifs_NTtimeToUnix
+ (le64_to_cpu(pfindData->LastAccessTime));
+ else /* do not need to use current_fs_time - time not stored */
+ inode->i_atime = CURRENT_TIME;
inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime =
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index a57f5d6..0bee8b7 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -254,7 +254,11 @@
tmpbuffer,
len - 1,
cifs_sb->local_nls);
- else {
+ else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+ cERROR(1,("SFU style symlinks not implemented yet"));
+ /* add open and read as in fs/cifs/inode.c */
+
+ } else {
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
OPEN_REPARSE_POINT,&fid, &oplock, NULL,
cifs_sb->local_nls,
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index ce87550..fa5124d 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -909,3 +909,54 @@
/* Convert to 100ns intervals and then add the NTFS time offset. */
return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
}
+
+static int total_days_of_prev_months[] =
+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+
+__le64 cnvrtDosCifsTm(__u16 date, __u16 time)
+{
+ return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time)));
+}
+struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
+{
+ __u8 dt[2];
+ __u8 tm[2];
+ struct timespec ts;
+ int sec,min, days, month, year;
+ struct timespec removeme; /* BB removeme BB */
+/* SMB_TIME * st = (SMB_TIME *)&time;*/
+
+ cFYI(1,("date %d time %d",date, time));
+
+ dt[0] = date & 0xFF;
+ dt[1] = (date & 0xFF00) >> 8;
+ tm[0] = time & 0xFF;
+ tm[1] = (time & 0xFF00) >> 8;
+
+ sec = tm[0] & 0x1F;
+ sec = 2 * sec;
+ min = ((tm[0] >>5)&0xFF) + ((tm[1] & 0x7)<<3);
+
+ sec += (min * 60);
+ sec += 60 * 60 * ((tm[1] >> 3) &0xFF) /* hours */;
+ days = (dt[0] & 0x1F) - 1;
+ month = ((dt[0] >> 5) & 0xFF) + ((dt[1] & 0x1) <<3);
+ if(month > 12)
+ cERROR(1,("illegal month %d in date", month));
+ month -= 1;
+ days += total_days_of_prev_months[month];
+ days += 3653; /* account for difference in days between 1980 and 1970 */
+ year = (dt[1]>>1) & 0xFF;
+ days += year * 365;
+ days += (year/4); /* leap year */
+ /* adjust for leap year where we are still before leap day */
+ days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0);
+ sec += 24 * 60 * 60 * days;
+
+ removeme = CURRENT_TIME; /* BB removeme BB */
+ ts.tv_sec = sec;
+
+ ts.tv_nsec = 0;
+ return ts;
+}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9aeb58a..71e86c3 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -135,12 +135,19 @@
tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
} else { /* legacy, OS2 and DOS style */
+/* struct timespec ts;*/
FIND_FILE_STANDARD_INFO * pfindData =
(FIND_FILE_STANDARD_INFO *)buf;
+/* ts = cnvrtDosUnixTm(
+ le16_to_cpu(pfindData->LastWriteDate),
+ le16_to_cpu(pfindData->LastWriteTime));*/
attr = le16_to_cpu(pfindData->Attributes);
allocation_size = le32_to_cpu(pfindData->AllocationSize);
end_of_file = le32_to_cpu(pfindData->DataSize);
+ /* do not need to use current_fs_time helper function since
+ time not stored for this case so atime can not "go backwards"
+ by pulling newer older from disk when inode refrenshed */
tmp_inode->i_atime = CURRENT_TIME;
/* tmp_inode->i_mtime = BB FIXME - add dos time handling
tmp_inode->i_ctime = 0; BB FIXME */