diff options
author | Steve French <sfrench@us.ibm.com> | 2006-10-02 01:53:29 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-10-02 01:53:29 -0400 |
commit | b815f1e559e7cbdf3e561cf0c7cffc4a4a57a013 (patch) | |
tree | 0ff77669363276a97bd4e3cc1b3dcea928c97545 /fs | |
parent | 203cf2fc13a5db1fb202c294948fa9cb43bf69fa (diff) |
[CIFS] Allow for 15 minute TZs (e.g. Nepal) and be more explicit about
not setting time on close
Signed-off-by: Guenter Kukkukk <linux@kukkukk.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifspdu.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 35 |
2 files changed, 25 insertions, 14 deletions
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 50505422dbb4..6df9dadba647 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -409,6 +409,8 @@ typedef struct negotiate_req { | |||
409 | 409 | ||
410 | /* Dialect index is 13 for LANMAN */ | 410 | /* Dialect index is 13 for LANMAN */ |
411 | 411 | ||
412 | #define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */ | ||
413 | |||
412 | typedef struct lanman_neg_rsp { | 414 | typedef struct lanman_neg_rsp { |
413 | struct smb_hdr hdr; /* wct = 13 */ | 415 | struct smb_hdr hdr; /* wct = 13 */ |
414 | __le16 DialectIndex; | 416 | __le16 DialectIndex; |
@@ -678,7 +680,7 @@ typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on | |||
678 | typedef struct smb_com_close_req { | 680 | typedef struct smb_com_close_req { |
679 | struct smb_hdr hdr; /* wct = 3 */ | 681 | struct smb_hdr hdr; /* wct = 3 */ |
680 | __u16 FileID; | 682 | __u16 FileID; |
681 | __u32 LastWriteTime; /* should be zero */ | 683 | __u32 LastWriteTime; /* should be zero or -1 */ |
682 | __u16 ByteCount; /* 0 */ | 684 | __u16 ByteCount; /* 0 */ |
683 | } __attribute__((packed)) CLOSE_REQ; | 685 | } __attribute__((packed)) CLOSE_REQ; |
684 | 686 | ||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 75f060328e29..8d30a5c4f244 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -450,7 +450,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
450 | } else if((pSMBr->hdr.WordCount == 13) | 450 | } else if((pSMBr->hdr.WordCount == 13) |
451 | && ((pSMBr->DialectIndex == LANMAN_PROT) | 451 | && ((pSMBr->DialectIndex == LANMAN_PROT) |
452 | || (pSMBr->DialectIndex == LANMAN2_PROT))) { | 452 | || (pSMBr->DialectIndex == LANMAN2_PROT))) { |
453 | int tmp, adjust; | 453 | __s16 tmp; |
454 | struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; | 454 | struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr; |
455 | 455 | ||
456 | if((secFlags & CIFSSEC_MAY_LANMAN) || | 456 | if((secFlags & CIFSSEC_MAY_LANMAN) || |
@@ -476,14 +476,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
476 | server->maxRw = 0;/* we do not need to use raw anyway */ | 476 | server->maxRw = 0;/* we do not need to use raw anyway */ |
477 | server->capabilities = CAP_MPX_MODE; | 477 | server->capabilities = CAP_MPX_MODE; |
478 | } | 478 | } |
479 | tmp = le16_to_cpu(rsp->ServerTimeZone); | 479 | tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone); |
480 | if (tmp == (int)0xffff) { | 480 | if (tmp == 0xffff) { |
481 | /* OS/2 often does not set timezone therefore | 481 | /* OS/2 often does not set timezone therefore |
482 | * we must use server time to calc time zone. | 482 | * we must use server time to calc time zone. |
483 | * Could deviate slightly from the right zone. Not easy | 483 | * Could deviate slightly from the right zone. |
484 | * to adjust, since timezones are not always a multiple | 484 | * Smallest defined timezone difference is 15 minutes |
485 | * of 60 (sometimes 30 minutes - are there smaller?) | 485 | * (i.e. Nepal). Rounding up/down is done to match |
486 | * this requirement. | ||
486 | */ | 487 | */ |
488 | int val, seconds, remain, result; | ||
487 | struct timespec ts, utc; | 489 | struct timespec ts, utc; |
488 | utc = CURRENT_TIME; | 490 | utc = CURRENT_TIME; |
489 | ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), | 491 | ts = cnvrtDosUnixTm(le16_to_cpu(rsp->SrvTime.Date), |
@@ -491,12 +493,18 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
491 | cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d", | 493 | cFYI(1,("SrvTime: %d sec since 1970 (utc: %d) diff: %d", |
492 | (int)ts.tv_sec, (int)utc.tv_sec, | 494 | (int)ts.tv_sec, (int)utc.tv_sec, |
493 | (int)(utc.tv_sec - ts.tv_sec))); | 495 | (int)(utc.tv_sec - ts.tv_sec))); |
494 | tmp = (int)(utc.tv_sec - ts.tv_sec); | 496 | val = (int)(utc.tv_sec - ts.tv_sec); |
495 | adjust = tmp < 0 ? -29 : 29; | 497 | seconds = val < 0 ? -val : val; |
496 | tmp = ((tmp + adjust) / 60) * 60; | 498 | result = (seconds / IN_TZ_ADJ) * MIN_TZ_ADJ; |
497 | server->timeAdj = tmp; | 499 | remain = seconds % MIN_TZ_ADJ; |
500 | if(remain >= (MIN_TZ_ADJ / 2)) | ||
501 | result += MIN_TZ_ADJ; | ||
502 | if(val < 0) | ||
503 | result = - result; | ||
504 | server->timeAdj = result; | ||
498 | } else { | 505 | } else { |
499 | server->timeAdj = tmp * 60; /* also in seconds */ | 506 | server->timeAdj = (int)tmp; |
507 | server->timeAdj *= 60; /* also in seconds */ | ||
500 | } | 508 | } |
501 | cFYI(1,("server->timeAdj: %d seconds", server->timeAdj)); | 509 | cFYI(1,("server->timeAdj: %d seconds", server->timeAdj)); |
502 | 510 | ||
@@ -559,7 +567,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
559 | cFYI(0, ("Max buf = %d", ses->server->maxBuf)); | 567 | cFYI(0, ("Max buf = %d", ses->server->maxBuf)); |
560 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | 568 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); |
561 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 569 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
562 | server->timeAdj = le16_to_cpu(pSMBr->ServerTimeZone) * 60; | 570 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
571 | server->timeAdj *= 60; | ||
563 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { | 572 | if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { |
564 | memcpy(server->cryptKey, pSMBr->u.EncryptionKey, | 573 | memcpy(server->cryptKey, pSMBr->u.EncryptionKey, |
565 | CIFS_CRYPTO_KEY_SIZE); | 574 | CIFS_CRYPTO_KEY_SIZE); |
@@ -1645,7 +1654,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1645 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | 1654 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ |
1646 | 1655 | ||
1647 | pSMB->FileID = (__u16) smb_file_id; | 1656 | pSMB->FileID = (__u16) smb_file_id; |
1648 | pSMB->LastWriteTime = 0; | 1657 | pSMB->LastWriteTime = 0xFFFFFFFF; |
1649 | pSMB->ByteCount = 0; | 1658 | pSMB->ByteCount = 0; |
1650 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1659 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1651 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1660 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |