$(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)
#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>
#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>
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);
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);
#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;
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);
#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 */
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.
*/
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);
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);
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);
/* 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 */
/* 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 */
} /* 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
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
* 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)
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,
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);
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);
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);
}
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;
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
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);
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);
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;
}
}
- 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));
#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.
#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"
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);
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;
}
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;
* include locks which have
* CM_FILELOCK_FLAG_CLIENTONLY set.
*/
-
+
afs_uint32 clientLocks; /* number of locks on ::fileLocks that
have CM_FILELOCK_FLAG_CLIENTONLY
set. */
#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
#include <malloc.h>
#include <string.h>
+#include "afsd.h"
#include <osi.h>
#include <rx/rx.h>
-#include "afsd.h"
osi_rwlock_t cm_serverLock;
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 */
#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 */
extern void cm_ForceNewConnectionsAllServers(void);
+extern void cm_SetServerNo64Bit(cm_server_t * serverp, int no64bit);
+
#endif /* __CM_SERVER_H_ENV__ */
#include <malloc.h>
#include <string.h>
+#include "afsd.h"
#include <osi.h>
#include <rx/rx.h>
-#include "afsd.h"
osi_rwlock_t cm_userLock;
#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;
}
} 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
}
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
/* am I sane? */
osi_assert(newLock == LockRead);
-
+
code = cm_IntSetLock(scp, userp, newLock, reqp);
}
/* 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;
}
if (IS_LOCK_ACCEPTED(fileLock) &&
- INTERSECT_RANGE(oldFileLock->range, fileLock->range)) {
+ INTERSECT_RANGE(oldFileLock->range, fileLock->range)) {
if (oldFileLock->lockType != LockRead ||
fileLock->lockType != LockRead) {
#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
#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"
return "(2d)ReceiveV3OpenX";
case 0x2e:
return "(2e)ReceiveV3ReadX";
+ case 0x2f:
+ return "(2f)ReceiveV3WriteX";
case 0x32:
return "(32)ReceiveV3Tran2A";
case 0x33:
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)
key = cm_GenerateKey(vcp->vcID, pid, fd);
- LOffset.HighPart = 0;
+ LOffset.HighPart = offset.HighPart;
LOffset.LowPart = offset.LowPart;
LLength.HighPart = 0;
LLength.LowPart = count;
caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
+#endif
+#ifdef AFS_LARGEFILES
+ NTNEGOTIATE_CAPABILITY_LARGEFILES |
#endif
NTNEGOTIATE_CAPABILITY_NTFIND |
NTNEGOTIATE_CAPABILITY_RAWMODE |
cm_ReleaseUser(userp);
return code;
}
-
+
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
cm_ReleaseSCache(newScp);
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
count -= written;
total_written += written;
written = 0;
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);
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);
if (code == 0 && written == 0)
code = CM_ERROR_PARTIALWRITE;
- offset.LowPart += written;
+ offset = LargeIntegerAdd(offset,
+ ConvertLongToLargeInteger(written));
+
count -= written;
total_written += written;
written = 0;
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;
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;
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);
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;
#include <ntsecapi.h>
+/* Support largefiles by default */
+#define AFS_LARGEFILES
+
/* basic core protocol SMB structure */
typedef struct smb {
unsigned char id[4];
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
#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
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.
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)
{
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) {
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);
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)
{
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
rx_DebugOnOff @223
rx_InitHost @224
rx_NewServiceHost @225
-
-
+ osi_AssertFailU @226