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 /fs | |
| parent | 0889a9441d98af7951c5377647413d79c84c9efa (diff) | |
[CIFS] Legacy time handling for Win9x and OS/2 part 1
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
| -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 */ |
