#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;
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
#endif
+#ifdef AFS_LARGEFILES
+ NTNEGOTIATE_CAPABILITY_LARGEFILES |
+#endif
NTNEGOTIATE_CAPABILITY_NTFIND |
NTNEGOTIATE_CAPABILITY_RAWMODE |
NTNEGOTIATE_CAPABILITY_NTSMB;
cm_ReleaseUser(userp);
return code;
}
-
+
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
cm_ReleaseSCache(newScp);
* in a readonly volume doesn't mean it shojuld be marked as RO
*/
if (newScp->fileType == CM_SCACHETYPE_DIRECTORY ||
- newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ newScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ newScp->fileType == CM_SCACHETYPE_INVALID)
attrs = SMB_ATTR_DIRECTORY;
else
attrs = 0;
userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_OPENWRITE)
- code = cm_FSync(fidp->scp, userp, &req);
- else
+ if (fidp->flags & SMB_FID_OPENWRITE) {
+ cm_scache_t * scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ cm_ReleaseSCache(scp);
+ } else {
code = 0;
- lock_ReleaseMutex(&fidp->mx);
+ lock_ReleaseMutex(&fidp->mx);
+ }
smb_ReleaseFID(fidp);
cm_req_t req;
cm_scache_t *dscp = fidp->NTopen_dscp;
char *pathp = fidp->NTopen_pathp;
+ cm_scache_t * scp;
osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
fidp, fidp->fid, vcp);
lock_ObtainMutex(&fidp->mx);
}
+ scp = fidp->scp;
+ if (scp)
+ cm_HoldSCache(scp);
+
/* watch for ioctl closes, and read-only opens */
- if (fidp->scp != NULL &&
+ if (scp != NULL &&
(fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
== SMB_FID_OPENWRITE) {
if (dosTime != 0 && dosTime != -1) {
- fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+ scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
/* This fixes defect 10958 */
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
}
- code = cm_FSync(fidp->scp, userp, &req);
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ lock_ObtainMutex(&fidp->mx);
}
else
code = 0;
/* unlock any pending locks */
- if (!(fidp->flags & SMB_FID_IOCTL) && fidp->scp &&
- fidp->scp->fileType == CM_SCACHETYPE_FILE) {
+ if (!(fidp->flags & SMB_FID_IOCTL) && scp &&
+ scp->fileType == CM_SCACHETYPE_FILE) {
cm_key_t key;
- cm_scache_t * scp;
long tcode;
- /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
+ lock_ReleaseMutex(&fidp->mx);
+
+ /* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
in zero. */
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
- scp = fidp->scp;
- cm_HoldSCache(scp);
lock_ObtainMutex(&scp->mx);
tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
post_syncopdone:
lock_ReleaseMutex(&scp->mx);
- cm_ReleaseSCache(scp);
+ lock_ObtainMutex(&fidp->mx);
}
if (fidp->flags & SMB_FID_DELONCLOSE) {
char *fullPathp;
- smb_FullName(dscp, fidp->scp, pathp, &fullPathp, userp, &req);
- if (fidp->scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_FullName(dscp, scp, pathp, &fullPathp, userp, &req);
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
code = cm_RemoveDir(dscp, fullPathp, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
dscp, fullPathp, NULL, TRUE);
}
free(fullPathp);
+ lock_ObtainMutex(&fidp->mx);
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
/* if this was a newly created file, then clear the creator
* in the stat cache entry. */
if (fidp->flags & SMB_FID_CREATED) {
- lock_ObtainMutex(&fidp->scp->mx);
- if (fidp->scp->creator == userp)
- fidp->scp->creator = NULL;
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ObtainMutex(&scp->mx);
+ if (scp->creator == userp)
+ scp->creator = NULL;
+ lock_ReleaseMutex(&scp->mx);
fidp->flags &= ~SMB_FID_CREATED;
}
if (dscp)
cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
+
if (pathp)
free(pathp);
if (fidp->curr_chunk == fidp->prev_chunk + 1)
sequential = 1;
}
+ lock_ReleaseMutex(&fidp->mx);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
done:
lock_ReleaseMutex(&scp->mx);
- lock_ReleaseMutex(&fidp->mx);
if (bufferp)
buf_Release(bufferp);
offset = *offsetp;
lock_ObtainMutex(&fidp->mx);
+ /* make sure we have a writable FD */
+ if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+ osi_Log2(smb_logp, "smb_WriteData fid %d not OPENWRITE flags 0x%x",
+ fidp->fid, fidp->flags);
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFDOP;
+ goto done;
+ }
+
scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainMutex(&scp->mx);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
if (code)
goto done;
- /* make sure we have a writable FD */
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- osi_Log2(smb_logp, "smb_WriteData fid %d not OPENWRITE flags 0x%x",
- fidp->fid, fidp->flags);
- code = CM_ERROR_BADFDOP;
- goto done;
- }
-
/* now we have the entry locked, look up the length */
fileLength = scp->length;
minLength = fileLength;
buf_Release(bufferp);
}
+ lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
&& (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
writeBackOffset.HighPart, cm_chunkSize, 0, userp);
}
+ cm_ReleaseSCache(scp);
+
osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
fidp->fid, code, *writtenp);
return code;
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;
lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
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);
- lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
}
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;