diff options
author | Steve French <sfrench@us.ibm.com> | 2006-09-27 23:35:57 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-09-27 23:35:57 -0400 |
commit | 1bd5bbcb6531776a8f73e2cc6287fc4dd542e1c7 (patch) | |
tree | 7c41514f13224d6292a1bb90636f44c3c027b2e8 | |
parent | 0889a9441d98af7951c5377647413d79c84c9efa (diff) |
[CIFS] Legacy time handling for Win9x and OS/2 part 1
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 10 | ||||
-rw-r--r-- | fs/cifs/inode.c | 7 | ||||
-rw-r--r-- | fs/cifs/link.c | 6 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 51 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 7 |
6 files changed, 80 insertions, 4 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b35c55c3c8bb..2fbc982aa13d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -80,6 +80,9 @@ extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, | |||
80 | extern void DeleteOplockQEntry(struct oplock_q_entry *); | 80 | extern void DeleteOplockQEntry(struct oplock_q_entry *); |
81 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); | 81 | extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); |
82 | extern u64 cifs_UnixTimeToNT(struct timespec); | 82 | extern u64 cifs_UnixTimeToNT(struct timespec); |
83 | extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time); | ||
84 | extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time); | ||
85 | |||
83 | extern int cifs_get_inode_info(struct inode **pinode, | 86 | extern int cifs_get_inode_info(struct inode **pinode, |
84 | const unsigned char *search_path, | 87 | const unsigned char *search_path, |
85 | FILE_ALL_INFO * pfile_info, | 88 | FILE_ALL_INFO * pfile_info, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 075d8fb3d376..2851d6e0d823 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2856,7 +2856,6 @@ qsec_out: | |||
2856 | return rc; | 2856 | return rc; |
2857 | } | 2857 | } |
2858 | 2858 | ||
2859 | |||
2860 | /* Legacy Query Path Information call for lookup to old servers such | 2859 | /* Legacy Query Path Information call for lookup to old servers such |
2861 | as Win9x/WinME */ | 2860 | as Win9x/WinME */ |
2862 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, | 2861 | int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, |
@@ -2898,7 +2897,16 @@ QInfRetry: | |||
2898 | if (rc) { | 2897 | if (rc) { |
2899 | cFYI(1, ("Send error in QueryInfo = %d", rc)); | 2898 | cFYI(1, ("Send error in QueryInfo = %d", rc)); |
2900 | } else if (pFinfo) { /* decode response */ | 2899 | } else if (pFinfo) { /* decode response */ |
2900 | struct timespec ts; | ||
2901 | __u32 time = le32_to_cpu(pSMBr->last_write_time); | ||
2902 | /* BB FIXME - add time zone adjustment BB */ | ||
2901 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); | 2903 | memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); |
2904 | ts.tv_nsec = 0; | ||
2905 | ts.tv_sec = time; | ||
2906 | /* decode time fields */ | ||
2907 | pFinfo->ChangeTime = cifs_UnixTimeToNT(ts); | ||
2908 | pFinfo->LastWriteTime = pFinfo->ChangeTime; | ||
2909 | pFinfo->LastAccessTime = 0; | ||
2902 | pFinfo->AllocationSize = | 2910 | pFinfo->AllocationSize = |
2903 | cpu_to_le64(le32_to_cpu(pSMBr->size)); | 2911 | cpu_to_le64(le32_to_cpu(pSMBr->size)); |
2904 | pFinfo->EndOfFile = pFinfo->AllocationSize; | 2912 | pFinfo->EndOfFile = pFinfo->AllocationSize; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b88147c1dc27..06dbce3a1815 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -432,8 +432,11 @@ int cifs_get_inode_info(struct inode **pinode, | |||
432 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | 432 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ |
433 | 433 | ||
434 | /* Linux can not store file creation time so ignore it */ | 434 | /* Linux can not store file creation time so ignore it */ |
435 | inode->i_atime = | 435 | if(pfindData->LastAccessTime) |
436 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); | 436 | inode->i_atime = cifs_NTtimeToUnix |
437 | (le64_to_cpu(pfindData->LastAccessTime)); | ||
438 | else /* do not need to use current_fs_time - time not stored */ | ||
439 | inode->i_atime = CURRENT_TIME; | ||
437 | inode->i_mtime = | 440 | inode->i_mtime = |
438 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); | 441 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); |
439 | inode->i_ctime = | 442 | inode->i_ctime = |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index a57f5d6e6213..0bee8b7e521a 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -254,7 +254,11 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) | |||
254 | tmpbuffer, | 254 | tmpbuffer, |
255 | len - 1, | 255 | len - 1, |
256 | cifs_sb->local_nls); | 256 | cifs_sb->local_nls); |
257 | else { | 257 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
258 | cERROR(1,("SFU style symlinks not implemented yet")); | ||
259 | /* add open and read as in fs/cifs/inode.c */ | ||
260 | |||
261 | } else { | ||
258 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, | 262 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, |
259 | OPEN_REPARSE_POINT,&fid, &oplock, NULL, | 263 | OPEN_REPARSE_POINT,&fid, &oplock, NULL, |
260 | cifs_sb->local_nls, | 264 | cifs_sb->local_nls, |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index ce87550e918f..fa5124d9af19 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -909,3 +909,54 @@ cifs_UnixTimeToNT(struct timespec t) | |||
909 | /* Convert to 100ns intervals and then add the NTFS time offset. */ | 909 | /* Convert to 100ns intervals and then add the NTFS time offset. */ |
910 | return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; | 910 | return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET; |
911 | } | 911 | } |
912 | |||
913 | static int total_days_of_prev_months[] = | ||
914 | {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; | ||
915 | |||
916 | |||
917 | __le64 cnvrtDosCifsTm(__u16 date, __u16 time) | ||
918 | { | ||
919 | return cpu_to_le64(cifs_UnixTimeToNT(cnvrtDosUnixTm(date, time))); | ||
920 | } | ||
921 | struct timespec cnvrtDosUnixTm(__u16 date, __u16 time) | ||
922 | { | ||
923 | __u8 dt[2]; | ||
924 | __u8 tm[2]; | ||
925 | struct timespec ts; | ||
926 | int sec,min, days, month, year; | ||
927 | struct timespec removeme; /* BB removeme BB */ | ||
928 | /* SMB_TIME * st = (SMB_TIME *)&time;*/ | ||
929 | |||
930 | cFYI(1,("date %d time %d",date, time)); | ||
931 | |||
932 | dt[0] = date & 0xFF; | ||
933 | dt[1] = (date & 0xFF00) >> 8; | ||
934 | tm[0] = time & 0xFF; | ||
935 | tm[1] = (time & 0xFF00) >> 8; | ||
936 | |||
937 | sec = tm[0] & 0x1F; | ||
938 | sec = 2 * sec; | ||
939 | min = ((tm[0] >>5)&0xFF) + ((tm[1] & 0x7)<<3); | ||
940 | |||
941 | sec += (min * 60); | ||
942 | sec += 60 * 60 * ((tm[1] >> 3) &0xFF) /* hours */; | ||
943 | days = (dt[0] & 0x1F) - 1; | ||
944 | month = ((dt[0] >> 5) & 0xFF) + ((dt[1] & 0x1) <<3); | ||
945 | if(month > 12) | ||
946 | cERROR(1,("illegal month %d in date", month)); | ||
947 | month -= 1; | ||
948 | days += total_days_of_prev_months[month]; | ||
949 | days += 3653; /* account for difference in days between 1980 and 1970 */ | ||
950 | year = (dt[1]>>1) & 0xFF; | ||
951 | days += year * 365; | ||
952 | days += (year/4); /* leap year */ | ||
953 | /* adjust for leap year where we are still before leap day */ | ||
954 | days -= ((year & 0x03) == 0) && (month < 2 ? 1 : 0); | ||
955 | sec += 24 * 60 * 60 * days; | ||
956 | |||
957 | removeme = CURRENT_TIME; /* BB removeme BB */ | ||
958 | ts.tv_sec = sec; | ||
959 | |||
960 | ts.tv_nsec = 0; | ||
961 | return ts; | ||
962 | } | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 9aeb58a7d369..71e86c38e632 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -135,12 +135,19 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
135 | tmp_inode->i_ctime = | 135 | tmp_inode->i_ctime = |
136 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); | 136 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); |
137 | } else { /* legacy, OS2 and DOS style */ | 137 | } else { /* legacy, OS2 and DOS style */ |
138 | /* struct timespec ts;*/ | ||
138 | FIND_FILE_STANDARD_INFO * pfindData = | 139 | FIND_FILE_STANDARD_INFO * pfindData = |
139 | (FIND_FILE_STANDARD_INFO *)buf; | 140 | (FIND_FILE_STANDARD_INFO *)buf; |
140 | 141 | ||
142 | /* ts = cnvrtDosUnixTm( | ||
143 | le16_to_cpu(pfindData->LastWriteDate), | ||
144 | le16_to_cpu(pfindData->LastWriteTime));*/ | ||
141 | attr = le16_to_cpu(pfindData->Attributes); | 145 | attr = le16_to_cpu(pfindData->Attributes); |
142 | allocation_size = le32_to_cpu(pfindData->AllocationSize); | 146 | allocation_size = le32_to_cpu(pfindData->AllocationSize); |
143 | end_of_file = le32_to_cpu(pfindData->DataSize); | 147 | end_of_file = le32_to_cpu(pfindData->DataSize); |
148 | /* do not need to use current_fs_time helper function since | ||
149 | time not stored for this case so atime can not "go backwards" | ||
150 | by pulling newer older from disk when inode refrenshed */ | ||
144 | tmp_inode->i_atime = CURRENT_TIME; | 151 | tmp_inode->i_atime = CURRENT_TIME; |
145 | /* tmp_inode->i_mtime = BB FIXME - add dos time handling | 152 | /* tmp_inode->i_mtime = BB FIXME - add dos time handling |
146 | tmp_inode->i_ctime = 0; BB FIXME */ | 153 | tmp_inode->i_ctime = 0; BB FIXME */ |