[CIFS] Legacy time handling for Win9x and OS/2 part 1
authorSteve French <sfrench@us.ibm.com>
Thu, 28 Sep 2006 03:35:57 +0000 (03:35 +0000)
committerSteve French <sfrench@us.ibm.com>
Thu, 28 Sep 2006 03:35:57 +0000 (03:35 +0000)
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/netmisc.c
fs/cifs/readdir.c

index b35c55c3c8bb9d76b1afc8ae9e13189d2f3f6071..2fbc982aa13d4babc460e338b219734cdff10ad4 100644 (file)
@@ -80,6 +80,9 @@ extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
 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,
index 075d8fb3d37608a96d0610c519794388351d1173..2851d6e0d82365d858ed63dbfe282a4249019ee6 100644 (file)
@@ -2856,7 +2856,6 @@ qsec_out:
        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 @@ QInfRetry:
        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;
index b88147c1dc27f0df435b6251376a73b7dfc531cb..06dbce3a1815267fb9660d91992e19c6bf2631c3 100644 (file)
@@ -432,8 +432,11 @@ int cifs_get_inode_info(struct inode **pinode,
                (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 =
index a57f5d6e6213d6f23e693c88a98c3d539eb4ae6a..0bee8b7e521a2a153fa50e03bde68ec69865a364 100644 (file)
@@ -254,7 +254,11 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
                                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, 
index ce87550e918f8d33d87573677287e24d2da234e9..fa5124d9af197b5c2f2ea82ae3556869e660be06 100644 (file)
@@ -909,3 +909,54 @@ cifs_UnixTimeToNT(struct timespec t)
        /* 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;
+} 
index 9aeb58a7d369380d3f81a5f63569c66405af2463..71e86c38e632d007ccd63f3eb71c7dfbfee8930e 100644 (file)
@@ -135,12 +135,19 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
                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 */