DEVEL15-windows-largefile-support-20060623
authorAsanka Herath <asanka@secure-endpoints.com>
Sat, 24 Jun 2006 21:41:54 +0000 (21:41 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Sat, 24 Jun 2006 21:41:54 +0000 (21:41 +0000)
This patch adds large file support (> 2GB) to the CIFS server and
the cache manager.

It also corrects a significant oversight where the definition of
struct rx_call was inconsistent due to a failure to define AFS_PTHREAD_ENV
prior to including rx.h in all source files.  This prevented all errors
during rx_Read and rx_Write to be ignored.

(cherry picked from commit 015f9ce287c22df7a0b967ee0357d0816b4e0e54)

24 files changed:
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_conn.h
src/WINNT/afsd/cm_daemon.c
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_dir.c
src/WINNT/afsd/cm_freelance.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h
src/WINNT/afsd/cm_user.c
src/WINNT/afsd/cm_utils.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/smb.c
src/WINNT/afsd/smb.h
src/WINNT/afsd/smb3.c
src/WINNT/afsd/smb3.h
src/WINNT/afsd/smb_ioctl.c
src/WINNT/afsd/smb_ioctl.h
src/libafsrpc/afsrpc.def

index 198f970..07ac222 100644 (file)
@@ -404,6 +404,7 @@ AFSD_EXELIBS =\
        $(DESTDIR)\lib\libafsconf.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
        $(DESTDIR)\lib\afs\afsutil.lib \
+       $(DESTDIR)\lib\afspthread.lib \
         $(LANAHELPERLIB)
 
 $(AFSD_EXEFILE): $(OUT)\afsd.obj $(AFSDOBJS) $(OUT)\afsd.res  $(RXOBJS) $(AFSD_EXELIBS)
index ca52252..cbdd169 100644 (file)
@@ -10,6 +10,9 @@
 #ifndef __CM_H_ENV__
 #define __CM_H_ENV__ 1
 
+#ifndef AFS_PTHREAD_ENV
+#define AFS_PTHREAD_ENV 1
+#endif
 #include <rx/rx.h>
 #ifdef DJGPP      /* we need these for vldbentry decl., etc. */
 #include <afs/vldbint.h>
index b282aaa..1cf6494 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
+#include "afsd.h"
 #include <osi.h>
 #include <rx_pthread.h>
 
-#include "afsd.h"
 #include <WINNT/syscfg.h>
 #include <WINNT/afsreg.h>
 #include <../afsrdr/kif.h>
@@ -475,6 +475,9 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
        
        lock_ReleaseWrite(&cm_scacheLock);
        
+       /* reset the No 64-bit flag on the server */
+       cm_SetServerNo64Bit(tsp, 0);
+
        /* we're done with the server structure */
        if (tsp) 
             cm_PutServer(tsp);
@@ -829,7 +832,7 @@ SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry64 *cep)
     cep->Length.high = scp->length.HighPart;
     cep->Length.low = scp->length.LowPart;
 #else
-    cep->Length = ((afs_int64)scp->length.HighPart)<<32 | scp->length.LowPart;
+    cep->Length = (afs_int64) scp->length.QuadPart;
 #endif
     cep->DataVersion = scp->dataVersion;
     cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
index e52d0b5..57563e8 100644 (file)
 #include <string.h>
 #include <malloc.h>
 #include <osi.h>
+#include "afsd.h"
 #include <rx/rx.h>
 #include <rx/rxkad.h>
 #include <afs/unified_afs.h>
-#include "afsd.h"
 
 osi_rwlock_t cm_connLock;
 
index bf97f82..9d65a69 100644 (file)
@@ -91,6 +91,9 @@ typedef struct cm_req {
                                   cache managers treat it as "server is down"*/
 
 #include "cm_server.h"
+#ifndef AFS_PTHREAD_ENV
+#define AFS_PTHREAD_ENV 1
+#endif
 #include "rx.h"
 
 extern void cm_InitConn(void);
index ac210e1..7c8d47e 100644 (file)
 #include <malloc.h>
 #include <string.h>
 
+#include "afsd.h"
+
 #include <rx/rx.h>
 #include <rx/rx_prototypes.h>
 #include <WINNT/afsreg.h>
 
-#include "afsd.h"
 #include "afsicf.h"
 
 /* in seconds */
index c1221fb..cc548fd 100644 (file)
@@ -33,6 +33,16 @@ osi_mutex_t cm_bufGetMutex;
 extern osi_mutex_t cm_Freelance_Lock;
 #endif
 
+#ifdef AFS_LARGEFILES
+/* we can access connp->serverp without holding a lock because that
+   never changes since the connection is made. */
+#define SERVERHAS64BIT(connp) (!((connp)->serverp->flags & CM_SERVERFLAG_NO64BIT))
+#define SET_SERVERHASNO64BIT(connp) (cm_SetServerNo64Bit((connp)->serverp, TRUE))
+#else
+#define SERVERHAS64BIT(connp) (FALSE)
+#define SET_SERVERHASNO64BIT(connp) (FALSE)
+#endif
+
 /* functions called back from the buffer package when reading or writing data,
  * or when holding or releasing a vnode pointer.
  */
@@ -62,8 +72,9 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
     long wbytes;
     char *bufferp;
     cm_conn_t *connp;
-    long truncPos;
+    osi_hyper_t truncPos;
     cm_bulkIO_t biod;          /* bulk IO descriptor */
+    int require_64bit_ops = 0;
 
     osi_assert(userp != NULL);
 
@@ -78,7 +89,7 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
     cm_AFSFidFromFid(&tfid, fidp);
 
     lock_ObtainMutex(&scp->mx);
-        
+
     code = cm_SetupStoreBIOD(scp, offsetp, length, &biod, userp, reqp);
     if (code) {
         osi_Log1(afsd_logp, "cm_SetupStoreBIOD code %x", code);
@@ -93,7 +104,7 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
         cm_ReleaseBIOD(&biod, 1);      /* should be a NOOP */
         cm_ReleaseSCache(scp);
         return 0;
-    }   
+    }
 
     /* Serialize StoreData RPC's; for rationale see cm_scache.c */
     (void) cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA_EXCL);
@@ -101,10 +112,10 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
     /* prepare the output status for the store */
     scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
     cm_StatusFromAttr(&inStatus, scp, NULL);
-    truncPos = scp->length.LowPart;
+    truncPos = scp->length;
     if ((scp->mask & CM_SCACHEMASK_TRUNCPOS)
-         && scp->truncPos.LowPart < (unsigned long) truncPos)
-        truncPos = scp->truncPos.LowPart;
+        && LargeIntegerLessThan(scp->truncPos, truncPos))
+        truncPos = scp->truncPos;
        scp->mask &= ~CM_SCACHEMASK_TRUNCPOS;
                 
     /* compute how many bytes to write from this buffer */
@@ -117,28 +128,66 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
         /* otherwise write out part of buffer before EOF, but not
          * more than bufferSize bytes.
          */
-        nbytes = thyper.LowPart;
-        if (nbytes > biod.length) 
+        if (LargeIntegerGreaterThan(thyper,
+                                    ConvertLongToLargeInteger(biod.length))) {
             nbytes = biod.length;
+        } else {
+            /* if thyper is less than or equal to biod.length, then we
+               can safely assume that the value fits in a long. */
+            nbytes = thyper.LowPart;
+        }
     }
 
-    lock_ReleaseMutex(&scp->mx);
+    if (LargeIntegerGreaterThan(LargeIntegerAdd(biod.offset,
+                                                 ConvertLongToLargeInteger(nbytes)),
+                                 ConvertLongToLargeInteger(LONG_MAX)) ||
+         LargeIntegerGreaterThan(truncPos,
+                                 ConvertLongToLargeInteger(LONG_MAX))) {
+        require_64bit_ops = 1;
+    }
         
+    lock_ReleaseMutex(&scp->mx);
+
     /* now we're ready to do the store operation */
     do {
         code = cm_Conn(&scp->fid, userp, reqp, &connp);
         if (code) 
             continue;
-               
+
+    retry:
         rxconnp = cm_GetRxConn(connp);
         callp = rx_NewCall(rxconnp);
         rx_PutConnection(rxconnp);
 
+#ifdef AFS_LARGEFILES
+        if (SERVERHAS64BIT(connp)) {
+            osi_Log4(afsd_logp, "CALL StoreData64 scp 0x%p, offset 0x%x:%08x, length 0x%x",
+                     scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
+
+            code = StartRXAFS_StoreData64(callp, &tfid, &inStatus,
+                                          biod.offset.QuadPart,
+                                          nbytes,
+                                          truncPos.QuadPart);
+        } else {
+
+            if (require_64bit_ops) {
+                osi_Log0(afsd_logp, "Skipping StoreData.  The operation requires StoreData64");
+                code = CM_ERROR_TOOBIG;
+            } else {
+                osi_Log4(afsd_logp, "CALL StoreData scp 0x%p, offset 0x%x:%08x, length 0x%x",
+                         scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
+
+                code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
+                                            biod.offset.LowPart, nbytes, truncPos.LowPart);
+            }
+        }
+#else
         osi_Log4(afsd_logp, "CALL StoreData scp 0x%p, offset 0x%x:%08x, length 0x%x",
                  scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
 
         code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
-                                    biod.offset.LowPart, nbytes, truncPos);
+                                    biod.offset.LowPart, nbytes, truncPos.LowPart);
+#endif
 
         if (code == 0) {
             /* write the data from the the list of buffers */
@@ -168,18 +217,34 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
             }  /* while more bytes to write */
         }              /* if RPC started successfully */
         else {
-            osi_Log2(afsd_logp, "StartRXAFS_StoreData scp 0x%p failed (%lX)",scp,code);
+            osi_Log2(afsd_logp, "StartRXAFS_StoreData?? scp 0x%p failed (%lX)",scp,code);
         }
+
         if (code == 0) {
-            code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
-            if (code)
-                osi_Log2(afsd_logp, "EndRXAFS_StoreData scp 0x%p failed (%lX)",scp,code);
+            if (SERVERHAS64BIT(connp)) {
+                code = EndRXAFS_StoreData64(callp, &outStatus, &volSync);
+                if (code)
+                    osi_Log2(afsd_logp, "EndRXAFS_StoreData64 scp 0x%p failed (%lX)", scp, code);
+            } else {
+                code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+                if (code)
+                    osi_Log2(afsd_logp, "EndRXAFS_StoreData scp 0x%p failed (%lX)",scp,code);
+            }
         }
+
         code = rx_EndCall(callp, code);
+
+#ifdef AFS_LARGEFILES
+        if (code == RXGEN_OPCODE && SERVERHAS64BIT(connp)) {
+            SET_SERVERHASNO64BIT(connp);
+            goto retry;
+        }
+#endif
                 
     } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
+
     code = cm_MapRPCError(code, reqp);
-        
+
     if (code)
         osi_Log2(afsd_logp, "CALL StoreData FAILURE scp 0x%p, code 0x%x", scp, code);
     else
@@ -191,6 +256,7 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_STOREDATA_EXCL);
 
     if (code == 0) {
+        osi_hyper_t t;
         /* now, here's something a little tricky: in AFS 3, a dirty
          * length can't be directly stored, instead, a dirty chunk is
          * stored that sets the file's size (by writing and by using
@@ -209,8 +275,17 @@ long cm_BufWrite(void *vfidp, osi_hyper_t *offsetp, long length, long flags,
          * We have to turn off the length dirty bit as soon as we can,
          * so that we see updates made by other machines.
          */
-        if (outStatus.Length >= scp->length.LowPart)
+
+        if (SERVERHAS64BIT(connp)) {
+            t.LowPart = outStatus.Length;
+            t.HighPart = outStatus.Length_hi;
+        } else {
+            t = ConvertLongToLargeInteger(outStatus.Length);
+        }
+
+        if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
             scp->mask &= ~CM_SCACHEMASK_LENGTH;
+
         cm_MergeStatus(scp, &outStatus, &volSync, userp, 0);
     } else {
         if (code == CM_ERROR_SPACE)
@@ -237,10 +312,11 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
     AFSVolSync volSync;
     AFSFid tfid;
     long code;
-    long truncPos;
+    osi_hyper_t truncPos;
     cm_conn_t *connp;
     struct rx_call *callp;
     struct rx_connection *rxconnp;
+    int require_64bit_ops = 0;
 
     /* Serialize StoreData RPC's; for rationale see cm_scache.c */
     (void) cm_SyncOp(scp, NULL, userp, reqp, 0,
@@ -252,12 +328,18 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
     scp->mask &= ~CM_SCACHEMASK_CLIENTMODTIME;
 
     /* calculate truncation position */
-    truncPos = scp->length.LowPart;
+    truncPos = scp->length;
     if ((scp->mask & CM_SCACHEMASK_TRUNCPOS)
-         && scp->truncPos.LowPart < (unsigned long) truncPos)
-        truncPos = scp->truncPos.LowPart;
+        && LargeIntegerLessThan(scp->truncPos, truncPos))
+        truncPos = scp->truncPos;
     scp->mask &= ~CM_SCACHEMASK_TRUNCPOS;
 
+    if (LargeIntegerGreaterThan(truncPos,
+                                ConvertLongToLargeInteger(LONG_MAX))) {
+
+        require_64bit_ops = 1;
+    }
+
     lock_ReleaseMutex(&scp->mx);
 
     cm_AFSFidFromFid(&tfid, &scp->fid);
@@ -267,18 +349,44 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
         code = cm_Conn(&scp->fid, userp, reqp, &connp);
         if (code) 
             continue;
-               
+
+    retry:     
         rxconnp = cm_GetRxConn(connp);
         callp = rx_NewCall(rxconnp);
         rx_PutConnection(rxconnp);
 
+#ifdef AFS_LARGEFILES
+        if (SERVERHAS64BIT(connp)) {
+            code = StartRXAFS_StoreData64(callp, &tfid, &inStatus,
+                                          0, 0, truncPos.QuadPart);
+        } else {
+            if (require_64bit_ops) {
+                code = CM_ERROR_TOOBIG;
+            } else {
+                code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
+                                            0, 0, truncPos.LowPart);
+            }
+        }
+#else
         code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
-                                    0, 0, truncPos);
+                                    0, 0, truncPos.LowPart);
+#endif
 
-        if (code == 0)
-            code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+        if (code == 0) {
+            if (SERVERHAS64BIT(connp))
+                code = EndRXAFS_StoreData64(callp, &outStatus, &volSync);
+            else
+                code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+        }
         code = rx_EndCall(callp, code);
 
+#ifdef AFS_LARGEFILES
+        if (code == RXGEN_OPCODE && SERVERHAS64BIT(connp)) {
+            SET_SERVERHASNO64BIT(connp);
+            goto retry;
+        }
+#endif
+
     } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
     code = cm_MapRPCError(code, reqp);
         
@@ -288,11 +396,19 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_STOREDATA_EXCL);
 
     if (code == 0) {
+        osi_hyper_t t;
         /*
          * For explanation of handling of CM_SCACHEMASK_LENGTH,
          * see cm_BufWrite().
          */
-        if (outStatus.Length >= scp->length.LowPart)
+        if (SERVERHAS64BIT(connp)) {
+            t.HighPart = outStatus.Length_hi;
+            t.LowPart = outStatus.Length;
+        } else {
+            t = ConvertLongToLargeInteger(outStatus.Length);
+        }
+
+        if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
             scp->mask &= ~CM_SCACHEMASK_LENGTH;
         cm_MergeStatus(scp, &outStatus, &volSync, userp, 0);
     }
@@ -1117,7 +1233,9 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                   cm_req_t *reqp)
 {
     long code;
-    long nbytes;                       /* bytes in transfer */
+    afs_int32 nbytes;                  /* bytes in transfer */
+    afs_int32 nbytes_hi = 0;            /* high-order 32 bits of bytes in transfer */
+    afs_int64 length_found = 0;
     long rbytes;                       /* bytes in rx_Read call */
     long temp;
     AFSFetchStatus afsStatus;
@@ -1133,6 +1251,7 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
     cm_conn_t *connp;
     int getroot;
     long t1, t2;
+    int require_64bit_ops = 0;
 
     /* now, the buffer may or may not be filled with good data (buf_GetNew
      * drops lots of locks, and may indeed return a properly initialized
@@ -1182,9 +1301,15 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
         lock_ObtainMutex(&scp->mx);
         return 0;
     }
-        
+
     lock_ReleaseMutex(&scp->mx);
 
+    if (LargeIntegerGreaterThan(LargeIntegerAdd(biod.offset,
+                                                ConvertLongToLargeInteger(biod.length)),
+                                ConvertLongToLargeInteger(LONG_MAX))) {
+        require_64bit_ops = 1;
+    }
+
 #ifdef DISKCACHE95
     DPRINTF("cm_GetBuffer: fetching data scpDV=%d bufDV=%d scp=%x bp=%x dcp=%x\n",
             scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
@@ -1259,11 +1384,68 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
         code = cm_Conn(&scp->fid, up, reqp, &connp);
         if (code) 
             continue;
-       
+
         rxconnp = cm_GetRxConn(connp);
         callp = rx_NewCall(rxconnp);
         rx_PutConnection(rxconnp);
 
+#ifdef AFS_LARGEFILES
+        nbytes = nbytes_hi = 0;
+
+        if (SERVERHAS64BIT(connp)) {
+            osi_Log4(afsd_logp, "CALL FetchData64 scp 0x%p, off 0x%x:%08x, size 0x%x",
+                     scp, biod.offset.HighPart, biod.offset.LowPart, biod.length);
+
+            code = StartRXAFS_FetchData64(callp, &tfid, biod.offset.QuadPart, biod.length);
+
+            if (code == 0) {
+                temp = rx_Read(callp, (char *) &nbytes_hi, sizeof(afs_int32));
+                if (temp == sizeof(afs_int32)) {
+                    nbytes_hi = ntohl(nbytes_hi);
+                } else {
+                    nbytes_hi = 0;
+                                       code = callp->error;
+                    rx_EndCall(callp, code);
+                    callp = NULL;
+                }
+            }
+        }
+
+        if (code == RXGEN_OPCODE || !SERVERHAS64BIT(connp)) {
+            if (require_64bit_ops) {
+                osi_Log0(afsd_logp, "Skipping FetchData.  Operation requires FetchData64");
+                code = CM_ERROR_TOOBIG;
+            } else {
+                if (!callp) {
+                    rxconnp = cm_GetRxConn(connp);
+                    callp = rx_NewCall(rxconnp);
+                    rx_PutConnection(rxconnp);
+                }
+
+                osi_Log3(afsd_logp, "CALL FetchData scp 0x%p, off 0x%x, size 0x%x",
+                         scp, biod.offset.LowPart, biod.length);
+
+                code = StartRXAFS_FetchData(callp, &tfid, biod.offset.LowPart,
+                                            biod.length);
+
+                SET_SERVERHASNO64BIT(connp);
+            }
+        }
+
+        if (code == 0) {
+            temp  = rx_Read(callp, (char *)&nbytes, sizeof(afs_int32));
+            if (temp == sizeof(afs_int32)) {
+                nbytes = ntohl(nbytes);
+                FillInt64(length_found, nbytes_hi, nbytes);
+                if (length_found > biod.length) 
+                    code = (callp->error < 0) ? callp->error : -1;
+            } else {
+                code = (callp->error < 0) ? callp->error : -1;
+            }
+        }
+        /* for the moment, nbytes_hi will always be 0 if code == 0
+           because biod.length is a 32-bit quantity. */
+#else
         osi_Log3(afsd_logp, "CALL FetchData scp 0x%p, off 0x%x, size 0x%x",
                  scp, biod.offset.LowPart, biod.length);
 
@@ -1271,14 +1453,17 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
                                     biod.length);
 
         /* now copy the data out of the pipe and put it in the buffer */
-        temp  = rx_Read(callp, (char *)&nbytes, 4);
-        if (temp == 4) {
-            nbytes = ntohl(nbytes);
-            if (nbytes > biod.length) 
+        if (code == 0) {
+            temp  = rx_Read(callp, (char *)&nbytes, sizeof(afs_int32));
+            if (temp == sizeof(afs_int32)) {
+                nbytes = ntohl(nbytes);
+                if (nbytes > biod.length) 
+                    code = (callp->error < 0) ? callp->error : -1;
+            }
+            else 
                 code = (callp->error < 0) ? callp->error : -1;
         }
-        else 
-            code = (callp->error < 0) ? callp->error : -1;
+#endif
 
         if (code == 0) {
             qdp = biod.bufListEndp;
@@ -1368,13 +1553,24 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *up,
             }   
         }
 
-        if (code == 0)
-            code = EndRXAFS_FetchData(callp, &afsStatus, &callback, &volSync);
-        else
-            osi_Log1(afsd_logp, "CALL EndRXAFS_FetchData skipped due to error %d", code);
-        code = rx_EndCall(callp, code);
+        if (code == 0) {
+            if (SERVERHAS64BIT(connp))
+                code = EndRXAFS_FetchData64(callp, &afsStatus, &callback, &volSync);
+            else
+                code = EndRXAFS_FetchData(callp, &afsStatus, &callback, &volSync);
+        } else {
+            if (SERVERHAS64BIT(connp))
+                osi_Log1(afsd_logp, "CALL EndRXAFS_FetchData64 skipped due to error %d", code);
+            else
+                osi_Log1(afsd_logp, "CALL EndRXAFS_FetchData skipped due to error %d", code);
+        }
+
+        if (callp)
+            code = rx_EndCall(callp, code);
+
         if (code == RXKADUNKNOWNKEY)
             osi_Log0(afsd_logp, "CALL EndCall returns RXKADUNKNOWNKEY");
+
         osi_Log0(afsd_logp, "CALL FetchData DONE");
 
     } while (cm_Analyze(connp, up, reqp, &scp->fid, &volSync, NULL, NULL, code));
index a570479..3e0dbfe 100644 (file)
@@ -16,9 +16,9 @@
 #include <string.h>
 #include <malloc.h>
 #include <osi.h>
+#include "afsd.h"
 #include <rx/rx.h>
 
-#include "afsd.h"
 
 /* compute how many 32 byte entries an AFS 3 dir requires for storing
  * the specified name.
index df775f6..a875e57 100644 (file)
 #include <malloc.h>
 #include <string.h>
 
-#include <rx/rx.h>
-
 #include <WINNT/afsreg.h>
 #include "afsd.h"
+#include <rx/rx.h>
+
 #ifdef AFS_FREELANCE_CLIENT
 #include "cm_freelance.h"
 #include "stdio.h"
index 309f972..1d772c1 100644 (file)
@@ -551,6 +551,7 @@ long cm_GetSCache(cm_fid_t *fidp, cm_scache_t **outScpp, cm_user_t *userp,
 
         lock_ObtainMutex(&cm_Freelance_Lock);
         scp->length.LowPart = (DWORD)strlen(mp)+4;
+        scp->length.HighPart = 0;
         strncpy(scp->mountPointStringp,mp,MOUNTPOINTLEN);
         scp->mountPointStringp[MOUNTPOINTLEN-1] = '\0';
         lock_ReleaseMutex(&cm_Freelance_Lock);
@@ -1148,6 +1149,7 @@ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp,
         statusp->FileType = CM_SCACHETYPE_DIRECTORY;
         statusp->LinkCount = scp->linkCount;
         statusp->Length = cm_fakeDirSize;
+        statusp->Length_hi = 0;
         statusp->DataVersion = cm_data.fakeDirVersion;
         statusp->Author = 0x1;
         statusp->Owner = 0x0;
@@ -1220,11 +1222,11 @@ void cm_MergeStatus(cm_scache_t *scp, AFSFetchStatus *statusp, AFSVolSync *volp,
     }
     if (!(scp->mask & CM_SCACHEMASK_LENGTH)) {
         scp->length.LowPart = statusp->Length;
-        scp->length.HighPart = 0;
+        scp->length.HighPart = statusp->Length_hi;
     }
 
     scp->serverLength.LowPart = statusp->Length;
-    scp->serverLength.HighPart = 0;
+    scp->serverLength.HighPart = statusp->Length_hi;
 
     scp->linkCount = statusp->LinkCount;
     scp->dataVersion = statusp->DataVersion;
index b8abbaf..78c942e 100644 (file)
@@ -181,7 +181,7 @@ typedef struct cm_scache {
                                   * include locks which have
                                   * CM_FILELOCK_FLAG_CLIENTONLY set.
                                   */
-       
+
     afs_uint32   clientLocks;   /* number of locks on ::fileLocks that
                                    have CM_FILELOCK_FLAG_CLIENTONLY
                                    set. */
@@ -245,6 +245,10 @@ typedef struct cm_scache {
 #define CM_SCACHEFLAG_ANYWATCH \
                        (CM_SCACHEFLAG_WATCHED | CM_SCACHEFLAG_WATCHEDSUBTREE)
 
+#define CM_SCACHEFLAG_NO64BITOPS        0x200000 /* only supports
+                                                    32-bit fetch/store
+                                                    operations */
+
 /* sync flags for calls to the server.  The CM_SCACHEFLAG_FETCHING,
  * CM_SCACHEFLAG_STORING and CM_SCACHEFLAG_SIZESTORING flags correspond to the
  * below, except for FETCHDATA and STOREDATA, which correspond to non-null
index 3d29d27..84a69af 100644 (file)
@@ -21,9 +21,9 @@
 #include <malloc.h>
 #include <string.h>
 
+#include "afsd.h"
 #include <osi.h>
 #include <rx/rx.h>
-#include "afsd.h"
 
 osi_rwlock_t cm_serverLock;
 
@@ -226,6 +226,16 @@ void cm_PutServerNoLock(cm_server_t *serverp)
     osi_assert(serverp->refCount-- > 0);
 }
 
+void cm_SetServerNo64Bit(cm_server_t * serverp, int no64bit)
+{
+    lock_ObtainMutex(&serverp->mx);
+    if (no64bit)
+        serverp->flags |= CM_SERVERFLAG_NO64BIT;
+    else
+        serverp->flags &= ~CM_SERVERFLAG_NO64BIT;
+    lock_ReleaseMutex(&serverp->mx);
+}
+
 void cm_SetServerPrefs(cm_server_t * serverp)
 {
     unsigned long      serverAddr;     /* in host byte order */
index 9182a2a..ba672ba 100644 (file)
@@ -51,6 +51,8 @@ typedef struct cm_serverRef {
 #define CM_SERVERFLAG_DOWN     1       /* server is down */
 #define CM_SERVERFLAG_PREF_SET 2       /* server preference set by user */
 #define CM_SERVERFLAG_PINGING  4       /* a ping against this server in progress */
+#define CM_SERVERFLAG_NO64BIT   8       /* server has no support for
+                                           64-bit operations. */
 
 /* flags for procedures */
 #define CM_FLAG_CHECKUPSERVERS         1       /* check working servers */
@@ -105,4 +107,6 @@ extern void cm_FreeServerList(cm_serverRef_t** list);
 
 extern void cm_ForceNewConnectionsAllServers(void);
 
+extern void cm_SetServerNo64Bit(cm_server_t * serverp, int no64bit);
+
 #endif /*  __CM_SERVER_H_ENV__ */
index 54d3c25..0f53e05 100644 (file)
 #include <malloc.h>
 #include <string.h>
 
+#include "afsd.h"
 #include <osi.h>
 #include <rx/rx.h>
 
-#include "afsd.h"
 
 osi_rwlock_t cm_userLock;
 
index 8d73014..d764a65 100644 (file)
 
 #include <string.h>
 #include <malloc.h>
+#include "afsd.h"
 #include <osi.h>
 #include <rx/rx.h>
 
-#include "afsd.h"
 
 static osi_once_t cm_utilsOnce;
 
index 1626e51..ce7c606 100644 (file)
@@ -3573,7 +3573,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
             }
 
         } else if ((scp->exclusiveLocks > 0) ||
-                (scp->sharedLocks > 0 && scp->serverLock != LockRead)) {
+                   (scp->sharedLocks > 0 && scp->serverLock != LockRead)) {
 
             /* We are already waiting for some other lock.  We should
                wait for the daemon to catch up instead of generating a
@@ -3609,7 +3609,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
             }
 
             if (scp->serverLock == LockRead && Which == LockWrite) {
-            
+
                 /* We want to escalate the lock to a LockWrite.
                    Unfortunately that's not really possible without
                    letting go of the current lock.  But for now we do
@@ -3651,7 +3651,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType,
 
                 /* am I sane? */
                 osi_assert(newLock == LockRead);
-                
+
                 code = cm_IntSetLock(scp, userp, newLock, reqp);
             }
 
@@ -4462,9 +4462,9 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
     /* Check if we already have a sufficient server lock to allow this
        lock to go through. */
     if (IS_LOCK_WAITLOCK(oldFileLock) &&
-       (!SERVERLOCKS_ENABLED(scp) ||
-        scp->serverLock == oldFileLock->lockType ||
-        scp->serverLock == LockWrite)) {
+        (!SERVERLOCKS_ENABLED(scp) ||
+         scp->serverLock == oldFileLock->lockType ||
+         scp->serverLock == LockWrite)) {
 
         oldFileLock->flags &= ~CM_FILELOCK_FLAG_WAITLOCK;
 
@@ -4505,7 +4505,7 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int client_is_dead)
             }
 
             if (IS_LOCK_ACCEPTED(fileLock) &&
-               INTERSECT_RANGE(oldFileLock->range, fileLock->range)) {
+                INTERSECT_RANGE(oldFileLock->range, fileLock->range)) {
 
                 if (oldFileLock->lockType != LockRead ||
                    fileLock->lockType != LockRead) {
index 04e5553..83bd7a5 100644 (file)
 #endif /* !DJGPP */
 #include <string.h>
 #include <malloc.h>
+#include "afsd.h"
 #include <osi.h>
 #include <rx/rx.h>
 
-#include "afsd.h"
-
 osi_rwlock_t cm_volumeLock;
 
 long 
index 968a621..3af0993 100644 (file)
 #include <stdio.h>
 #include <time.h>
 
+#include "afsd.h"
 #include <osi.h>
 #include <rx\rx.h>
 #include <rx/rx_prototypes.h>
-
-#include "afsd.h"
 #include <WINNT\afsreg.h>
 
 #include "smb.h"
@@ -351,6 +350,8 @@ char * myCrt_Dispatch(int i)
         return "(2d)ReceiveV3OpenX";
     case 0x2e:
         return "(2e)ReceiveV3ReadX";
+    case 0x2f:
+        return "(2f)ReceiveV3WriteX";
     case 0x32:
         return "(32)ReceiveV3Tran2A";
     case 0x33:
@@ -2965,11 +2966,32 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     fd = smb_GetSMBParm(inp, 0);
     count = smb_GetSMBParm(inp, 3);
     minCount = smb_GetSMBParm(inp, 4);
-    offset.HighPart = 0;       /* too bad */
     offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-    osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
-             fd, offset.LowPart, count);
+    if (*inp->wctp == 10) {
+        /* we were sent a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
+            goto send1;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
+            osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset.  Dropping request.");
+            goto send1;
+        } else {
+            offset.HighPart = 0;
+        }
+#endif
+    } else {
+        /* we were sent a request with 32-bit file offsets */
+        offset.HighPart = 0;
+    }
+
+    osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
 
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp)
@@ -2982,7 +3004,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
 
         key = cm_GenerateKey(vcp->vcID, pid, fd);
 
-        LOffset.HighPart = 0;
+        LOffset.HighPart = offset.HighPart;
         LOffset.LowPart = offset.LowPart;
         LLength.HighPart = 0;
         LLength.LowPart = count;
@@ -3219,6 +3241,9 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #ifdef DFS_SUPPORT
                NTNEGOTIATE_CAPABILITY_DFS |
 #endif
+#ifdef AFS_LARGEFILES
+               NTNEGOTIATE_CAPABILITY_LARGEFILES |
+#endif
                NTNEGOTIATE_CAPABILITY_NTFIND |
                NTNEGOTIATE_CAPABILITY_RAWMODE |
                NTNEGOTIATE_CAPABILITY_NTSMB;
@@ -4580,7 +4605,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         cm_ReleaseUser(userp);
         return code;
     }
-       
+
 #ifdef DFS_SUPPORT
     if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
         cm_ReleaseSCache(newScp);
@@ -6456,7 +6481,8 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (code == 0 && written == 0)
             code = CM_ERROR_PARTIALWRITE;
 
-        offset.LowPart += written;
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
         count -= written;
         total_written += written;
         written = 0;
@@ -6492,8 +6518,8 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     fd = smb_GetSMBParm(inp, 0);
     fidp = smb_FindFID(vcp, fd, 0);
 
-    osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
-             rwcp->offset.LowPart, rwcp->count);
+    osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
+             rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -6566,16 +6592,44 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fd = smb_GetSMBParm(inp, 0);
     totalCount = smb_GetSMBParm(inp, 1);
     count = smb_GetSMBParm(inp, 10);
-    offset.HighPart = 0;       /* too bad */
-    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
     writeMode = smb_GetSMBParm(inp, 7);
 
     op = (char *) inp->data;
     op += smb_GetSMBParm(inp, 11);
 
+    offset.HighPart = 0;
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    if (*inp->wctp == 14) {
+        /* we received a 64-bit file offset */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log2(smb_logp,
+                     "smb_ReceiveCoreWriteRaw received negative file offset 0x%x:%08x",
+                     offset.HighPart, offset.LowPart);
+            return CM_ERROR_BADSMB;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+            osi_Log0(smb_logp,
+                     "smb_ReceiveCoreWriteRaw received 64-bit file offset, but we don't support large files");
+            return CM_ERROR_BADSMB;
+        }
+
+        offset.HighPart = 0;
+#endif
+    } else {
+        offset.HighPart = 0;    /* 32-bit file offset */
+    }
+    
     osi_Log4(smb_logp,
-             "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
-             fd, offset.LowPart, count, writeMode);
+             "smb_ReceiveCoreWriteRaw fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+    osi_Log1(smb_logp,
+             "               WriteRaw WriteMode 0x%x",
+             writeMode);
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
@@ -6636,7 +6690,9 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        if (code == 0 && written == 0)
             code = CM_ERROR_PARTIALWRITE;
 
-        offset.LowPart += written;
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
+
         count -= written;
         total_written += written;
         written = 0;
@@ -6680,10 +6736,13 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         return code;
     }
 
+    offset = LargeIntegerAdd(offset,
+                             ConvertLongToLargeInteger(count));
+
     rwcp->code = 0;
     rwcp->buf = rawBuf;
-    rwcp->offset.HighPart = 0;
-    rwcp->offset.LowPart = offset.LowPart + count;
+    rwcp->offset.HighPart = offset.HighPart;
+    rwcp->offset.LowPart = offset.LowPart;
     rwcp->count = totalCount - count;
     rwcp->writeMode = writeMode;
     rwcp->alreadyWritten = total_written;
@@ -7103,6 +7162,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     long code = 0;
+    osi_hyper_t new_offset;
     long offset;
     int whence;
     unsigned short fd;
@@ -7144,15 +7204,20 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (code == 0) {
         if (whence == 1) {
             /* offset from current offset */
-            offset += fidp->offset;
+            new_offset = LargeIntegerAdd(fidp->offset,
+                                         ConvertLongToLargeInteger(offset));
         }
         else if (whence == 2) {
             /* offset from current EOF */
-            offset += scp->length.LowPart;
+            new_offset = LargeIntegerAdd(scp->length,
+                                         ConvertLongToLargeInteger(offset));
+        } else {
+            new_offset = ConvertLongToLargeInteger(offset);
         }
-        fidp->offset = offset;
-        smb_SetSMBParm(outp, 0, offset & 0xffff);
-        smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
+
+        fidp->offset = new_offset;
+        smb_SetSMBParm(outp, 0, new_offset.LowPart & 0xffff);
+        smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
         smb_SetSMBDataLength(outp, 0);
     }
     lock_ReleaseMutex(&scp->mx);
@@ -8607,6 +8672,8 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
     smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
     smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x2f].procp = smb_ReceiveV3WriteX;
+    smb_dispatchTable[0x2f].flags |= SMB_DISPATCHFLAG_CHAINED;
     smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A;       /* both are same */
     smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
     smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
index 8563245..37b1faf 100644 (file)
@@ -16,6 +16,9 @@
 
 #include <ntsecapi.h>
 
+/* Support largefiles by default */
+#define AFS_LARGEFILES
+
 /* basic core protocol SMB structure */
 typedef struct smb {
     unsigned char id[4];
@@ -340,7 +343,7 @@ typedef struct smb_fid {
                                            originally (used to close
                                            the file if session is
                                            terminated) */
-    long offset;                       /* our file pointer */
+    osi_hyper_t offset;                        /* our file pointer */
     smb_ioctl_t *ioctlp;               /* ptr to ioctl structure */
                                        /* Under NT, we may need to know the
                                         * parent directory and pathname used
@@ -376,7 +379,7 @@ typedef struct smb_fid {
 #define SMB_FID_SHARE_READ              0x1000
 #define SMB_FID_SHARE_WRITE             0x2000
 
-#define SMB_FID_QLOCK_HIGH              0x0fe00000
+#define SMB_FID_QLOCK_HIGH              0x7f000000
 #define SMB_FID_QLOCK_LOW               0x00000000
 #define SMB_FID_QLOCK_LENGTH            1
 #define SMB_FID_QLOCK_PID               0
index 618cf72..fc2b955 100644 (file)
@@ -4670,7 +4670,6 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 return CM_ERROR_BADSHARENAME;
         }
 #endif /* DFS_SUPPORT */
-
         /* otherwise, scp points to the parent directory.  Do a lookup,
          * and truncate the file if we find it, otherwise we create the
          * file.
@@ -5250,6 +5249,137 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     return code;
 }
 
+long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+    osi_hyper_t offset;
+    long count, written = 0, total_written = 0;
+    unsigned short fd;
+    unsigned pid;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    cm_attr_t truncAttr;       /* attribute struct used for truncating file */
+    char *op;
+    int inDataBlockCount;
+
+    fd = smb_GetSMBParm(inp, 2);
+    count = smb_GetSMBParm(inp, 10);
+
+    offset.HighPart = 0;
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    if (*inp->wctp == 14) {
+        /* we have a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+#else
+        if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+            /* uh oh */
+            osi_Log0(smb_logp, "smb_ReceiveV3WriteX offset requires largefile support");
+            /* we shouldn't have received this op if we didn't specify
+               largefile support */
+            return CM_ERROR_BADOP;
+        }
+#endif
+    }
+
+    op = inp->data + smb_GetSMBParm(inp, 11);
+    inDataBlockCount = count;
+
+    osi_Log4(smb_logp, "smb_ReceiveV3WriteX fid %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+        
+    fd = smb_ChainFID(fd, inp);
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp)
+        return CM_ERROR_BADFD;
+        
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlV3Write(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+    userp = smb_GetUserFromVCP(vcp, inp);
+
+    /* special case: 0 bytes transferred means there is no data
+       transferred.  A slight departure from SMB_COM_WRITE where this
+       means that we are supposed to truncate the file at this
+       position. */
+
+    {
+        cm_key_t key;
+        LARGE_INTEGER LOffset;
+        LARGE_INTEGER LLength;
+
+        pid = ((smb_t *) inp)->pid;
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+
+        if (code)
+            goto done;
+    }
+
+    /*
+     * Work around bug in NT client
+     *
+     * When copying a file, the NT client should first copy the data,
+     * then copy the last write time.  But sometimes the NT client does
+     * these in the wrong order, so the data copies would inadvertently
+     * cause the last write time to be overwritten.  We try to detect this,
+     * and don't set client mod time if we think that would go against the
+     * intention.
+     */
+    lock_ObtainMutex(&fidp->mx);
+    if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+        fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+        fidp->scp->clientModTime = time(NULL);
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    code = 0;
+    while ( code == 0 && count > 0 ) {
+#ifndef DJGPP
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
+       if (code == 0 && written == 0)
+            code = CM_ERROR_PARTIALWRITE;
+
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
+        count -= written;
+        total_written += written;
+        written = 0;
+    }
+
+ done_writing:
+    
+    /* slots 0 and 1 are reserved for request chaining and will be
+       filled in when we return. */
+    smb_SetSMBParm(outp, 2, total_written);
+    smb_SetSMBParm(outp, 3, 0); /* reserved */
+    smb_SetSMBParm(outp, 4, 0); /* reserved */
+    smb_SetSMBParm(outp, 5, 0); /* reserved */
+    smb_SetSMBDataLength(outp, 0);
+
+ done:
+    smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
+
+    return code;
+}
 
 long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -5266,12 +5396,33 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     fd = smb_GetSMBParm(inp, 2);
     count = smb_GetSMBParm(inp, 5);
-    offset.HighPart = 0;       /* too bad */
     offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
 
-    osi_Log3(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
-             fd, offset.LowPart, count);
-        
+    if (*inp->wctp == 12) {
+        /* a request with 64-bit offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log2(smb_logp, "smb_ReceiveV3Read offset too large (0x%x:%08x)",
+                     offset.HighPart, offset.LowPart);
+            return CM_ERROR_BADSMB;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16)) != 0) {
+            osi_Log0(smb_logp, "smb_ReceiveV3Read offset is 64-bit.  Dropping");
+            return CM_ERROR_BADSMB;
+        } else {
+            offset.HighPart = 0;
+        }
+#endif
+    } else {
+        offset.HighPart = 0;
+    }
+
+    osi_Log4(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
index 2167d9f..6a6caa9 100644 (file)
@@ -175,6 +175,8 @@ extern long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pac
 
 extern long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
 
+extern long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
 extern long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
 
 extern long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
index 86d6e51..70f4b28 100644 (file)
@@ -280,6 +280,51 @@ done:
         return code;
 }
 
+/* called from smb_ReceiveV3WriteX when we receive a write call on the IOCTL
+ * file descriptor.
+ */
+long smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+       smb_ioctl_t *iop;
+        long count;
+        long code;
+        char *op;
+        int inDataBlockCount;
+
+       code = 0;
+       count = smb_GetSMBParm(inp, 10);
+        iop = fidp->ioctlp;
+        
+       smb_IoctlPrepareWrite(fidp, iop);
+
+        op = inp->data + smb_GetSMBParm(inp, 11);
+        inDataBlockCount = count;
+       
+        if (count + iop->inCopied > SMB_IOCTL_MAXDATA) {
+               code = CM_ERROR_TOOBIG;
+                goto done;
+        }
+        
+       /* copy data */
+        memcpy(iop->inDatap + iop->inCopied, op, count);
+        
+        /* adjust counts */
+        iop->inCopied += count;
+
+done:
+       /* return # of bytes written */
+       if (code == 0) {
+               smb_SetSMBParm(outp, 2, count);
+                smb_SetSMBParm(outp, 3, 0); /* reserved */
+               smb_SetSMBParm(outp, 4, 0); /* reserved */
+               smb_SetSMBParm(outp, 5, 0); /* reserved */
+               smb_SetSMBDataLength(outp, 0);
+        }
+
+        return code;
+}
+
+
 /* called from V3 read to handle IOCTL descriptor reads */
 long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
index bce9e84..bb5ffb0 100644 (file)
@@ -30,6 +30,8 @@ extern long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb
 
 extern long smb_IoctlWrite(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
 
+extern long smb_IoctlV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
+
 extern long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp);
 
 #ifndef DJGPP
index 15bb847..4d965b9 100644 (file)
@@ -218,5 +218,4 @@ EXPORTS
        rx_DebugOnOff                           @223
        rx_InitHost                             @224
        rx_NewServiceHost                       @225
-        
-
+        osi_AssertFailU                                @226