#include <WINNT\afsreg.h>
#include "smb.h"
+#include "msrpc.h"
#include <strsafe.h>
extern osi_hyper_t hzero;
* turns out to be impolitic in NT. See defect 10007.
*/
#ifdef notdef
- if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+ if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
attrs |= SMB_ATTR_READONLY; /* Read-only */
#else
- if ((scp->unixModeBits & 0222) == 0)
+ if ((scp->unixModeBits & 0200) == 0)
attrs |= SMB_ATTR_READONLY; /* Read-only */
#endif
va_start( args, format );
cm_ClientStrPrintfV(vbuffer, lengthof(vbuffer), format, args);
osi_Log1(smb_logp, "%S", osi_LogSaveClientString(smb_logp, vbuffer));
- cm_ClientStrCat(vbuffer, lengthof(vbuffer), _C("\n"));
- OutputDebugStringW(vbuffer);
}
void OutputDebugHexDump(unsigned char * buffer, int len) {
if(!(i%16)) {
if(i) {
osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
- StringCchCatA(buf, lengthof(buf), "\r\n");
- OutputDebugString(buf);
}
StringCchPrintfA(buf, lengthof(buf), "%5x", i);
memset(buf+5,' ',80);
}
if(i) {
osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
- StringCchCatA(buf, lengthof(buf), "\r\n");
- OutputDebugString(buf);
}
}
clientchar_t usern[SMB_MAX_USERNAME_LENGTH];
char *secBlobOut = NULL;
int secBlobOutLength = 0;
+ int maxBufferSize = 0;
+ int maxMpxCount = 0;
+ int vcNumber = 0;
/* Check for bad conns */
if (vcp->flags & SMB_VCFLAG_REMOTECONN)
return CM_ERROR_REMOTECONN;
+ /* maxBufferSize */
+ maxBufferSize = smb_GetSMBParm(inp, 2);
+ maxMpxCount = smb_GetSMBParm(inp, 3);
+ vcNumber = smb_GetSMBParm(inp, 4);
+
+ osi_Log3(smb_logp, "SESSION_SETUP_ANDX with MaxBufferSize=%d, MaxMpxCount=%d, VCNumber=%d",
+ maxBufferSize, maxMpxCount, vcNumber);
+
+ if (maxMpxCount > smb_maxMpxRequests) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_MPX_COUNT, maxMpxCount, smb_maxMpxRequests);
+ osi_Log2(smb_logp, "MaxMpxCount for client is too large (Client=%d, Server=%d)",
+ maxMpxCount, smb_maxMpxRequests);
+ }
+
+ if (maxBufferSize < SMB_PACKETSIZE) {
+ LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_BUFFER_SIZE, maxBufferSize, SMB_PACKETSIZE);
+ osi_Log2(smb_logp, "MaxBufferSize for client is too small (Client=%d, Server=%d)",
+ maxBufferSize, SMB_PACKETSIZE);
+ }
+
+ if (vcNumber == 0) {
+ osi_Log0(smb_logp, "Resetting all VCs");
+ smb_MarkAllVCsDead(vcp);
+ }
+
if (vcp->flags & SMB_VCFLAG_USENT) {
if (smb_authType == SMB_AUTH_EXTENDED) {
/* extended authentication */
free(t2p->parmsp);
if (t2p->datap)
free(t2p->datap);
- }
+ }
+ if (t2p->name) {
+ free(t2p->name);
+ t2p->name = NULL;
+ }
while (t2p->stringsp) {
cm_space_t * ns;
smbp->uid = t2p->uid;
smbp->res[0] = t2p->res[0];
+ if (t2p->error_code) {
+ if (vcp->flags & SMB_VCFLAG_STATUS32) {
+ unsigned long NTStatus;
+
+ smb_MapNTError(t2p->error_code, &NTStatus);
+
+ smbp->rcls = (unsigned char) (NTStatus & 0xff);
+ smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+ smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+ smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+ smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+ }
+ else {
+ unsigned short errCode;
+ unsigned char errClass;
+
+ smb_MapCoreError(t2p->error_code, vcp, &errCode, &errClass);
+
+ smbp->rcls = errClass;
+ smbp->errLow = (unsigned char) (errCode & 0xff);
+ smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+ }
+ }
+
totalLength = 1 + t2p->totalData + t2p->totalParms;
/* now add the core parameters (tran2 info) to the packet */
/* next, send the datagram */
smb_SendPacket(vcp, tp);
-}
+}
+
+/* TRANS_SET_NMPIPE_STATE */
+long smb_nmpipeSetState(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int pipeState = 0x0100; /* default */
+ smb_tran2Packet_t *outp = NULL;
+
+ fd = p->pipeParam;
+ if (p->totalParms > 0)
+ pipeState = p->parmsp[0];
+
+ osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_nmpipeSetState Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
+ return CM_ERROR_BADFD;
+ }
+ lock_ObtainMutex(&fidp->mx);
+ if (pipeState & 0x8000)
+ fidp->flags |= SMB_FID_BLOCKINGPIPE;
+ if (pipeState & 0x0100)
+ fidp->flags |= SMB_FID_MESSAGEMODEPIPE;
+ lock_ReleaseMutex(&fidp->mx);
+
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 0);
+ smb_SendTran2Packet(vcp, outp, op);
+ smb_FreeTran2Packet(outp);
+
+ smb_ReleaseFID(fidp);
+
+ return 0;
+}
+
+long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+ smb_fid_t *fidp;
+ int fd;
+ int is_rpc = 0;
+
+ long code = 0;
+
+ fd = p->pipeParam;
+
+ osi_Log3(smb_logp, "smb_nmpipeTransact for fd[%d] %d bytes in, %d max bytes out",
+ fd, p->totalData, p->maxReturnData);
+
+ fidp = smb_FindFID(vcp, fd, 0);
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_nmpipeTransact Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
+ return CM_ERROR_BADFD;
+ }
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_RPC) {
+ is_rpc = 1;
+ }
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (is_rpc) {
+ code = smb_RPCNmpipeTransact(fidp, vcp, p, op);
+ smb_ReleaseFID(fidp);
+ } else {
+ /* We only deal with RPC pipes */
+ osi_Log2(smb_logp, "smb_nmpipeTransact Not a RPC vcp 0x%p fid %d",
+ vcp, fd);
+ code = CM_ERROR_BADFD;
+ }
+
+ return code;
+}
/* SMB_COM_TRANSACTION and SMB_COM_TRANSACTION_SECONDARY */
dataOffset = smb_GetSMBParm(inp, 12);
parmCount = smb_GetSMBParm(inp, 9);
dataCount = smb_GetSMBParm(inp, 11);
+ asp->setupCount = smb_GetSMBParmByte(inp, 13);
asp->maxReturnParms = smb_GetSMBParm(inp, 2);
asp->maxReturnData = smb_GetSMBParm(inp, 3);
osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
totalData, dataCount, asp->maxReturnData);
+
+ if (asp->setupCount == 2) {
+ clientchar_t * pname;
+
+ asp->pipeCommand = smb_GetSMBParm(inp, 14);
+ asp->pipeParam = smb_GetSMBParm(inp, 15);
+ pname = smb_ParseString(inp, inp->wctp + 35, NULL, 0);
+ if (pname) {
+ asp->name = cm_ClientStrDup(pname);
+ }
+
+ osi_Log2(smb_logp, " Named Pipe command id [%d] with name [%S]",
+ asp->pipeCommand, osi_LogSaveClientString(smb_logp, asp->name));
+ }
}
else {
parmDisp = smb_GetSMBParm(inp, 4);
osi_Log2(smb_logp, "SMB3 received Trans aux packet parms %d, data %d",
parmCount, dataCount);
- }
+ }
/* now copy the parms and data */
if ( asp->totalParms > 0 && parmCount != 0 )
asp->curParms += parmCount;
/* finally, if we're done, remove the packet from the queue and dispatch it */
- if (asp->totalParms > 0 &&
- asp->curParms > 0 &&
+ if (((asp->totalParms > 0 && asp->curParms > 0)
+ || asp->setupCount == 2) &&
asp->totalData <= asp->curData &&
asp->totalParms <= asp->curParms) {
+
/* we've received it all */
lock_ObtainWrite(&smb_globalLock);
osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
- /* now dispatch it */
- rapOp = asp->parmsp[0];
+ switch(asp->setupCount) {
+ case 0:
+ { /* RAP */
+ rapOp = asp->parmsp[0];
- if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
- code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",code,vcp,vcp->lana,vcp->lsn);
- }
- else {
- osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
- code = CM_ERROR_BADOP;
- }
+ if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES &&
+ smb_rapDispatchTable[rapOp].procp) {
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",
+ myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+
+ code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return code 0x%x vcp[%x] lana[%d] lsn[%d]",
+ code,vcp,vcp->lana,vcp->lsn);
+ }
+ else {
+ osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]",
+ rapOp, vcp, vcp->lana, vcp->lsn);
+
+ code = CM_ERROR_BADOP;
+ }
+ }
+ break;
+
+ case 2:
+ { /* Named pipe operation */
+ osi_Log2(smb_logp, "Named Pipe: %s with name [%S]",
+ myCrt_NmpipeDispatch(asp->pipeCommand),
+ osi_LogSaveClientString(smb_logp, asp->name));
+
+ code = CM_ERROR_BADOP;
+
+ switch (asp->pipeCommand) {
+ case SMB_TRANS_SET_NMPIPE_STATE:
+ code = smb_nmpipeSetState(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_STATE:
+ break;
+
+ case SMB_TRANS_QUERY_NMPIPE_INFO:
+ break;
+
+ case SMB_TRANS_PEEK_NMPIPE:
+ break;
+
+ case SMB_TRANS_TRANSACT_NMPIPE:
+ code = smb_nmpipeTransact(vcp, asp, outp);
+ break;
+
+ case SMB_TRANS_RAW_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_READ_NMPIPE:
+ break;
+
+ case SMB_TRANS_WRITE_NMPIPE:
+ break;
+
+ case SMB_TRANS_WAIT_NMPIPE:
+ break;
+
+ case SMB_TRANS_CALL_NMPIPE:
+ break;
+ }
+ }
+ break;
+
+ default:
+ code = CM_ERROR_BADOP;
+ }
/* if an error is returned, we're supposed to send an error packet,
* otherwise the dispatched function already did the data sending.
} else {
userp = smb_GetTran2User(vcp, p);
if (!userp) {
- osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ osi_Log1(smb_logp,"ReceiveRAPNetShareGetInfo unable to resolve user [%d]", p->uid);
return CM_ERROR_BADSMB;
}
code = cm_NameI(cm_data.rootSCachep, shareName,
int dataCount;
int firstPacket;
long code = 0;
+ DWORD oldTime, newTime;
/* We sometimes see 0 word count. What to do? */
if (*inp->wctp == 0) {
osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
+ oldTime = GetTickCount();
+
/* now dispatch it */
if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
osi_Log4(smb_logp,"AFS Server - Dispatch-2 %s vcp[%p] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
smb_SendTran2Error(vcp, asp, outp, code);
}
+ newTime = GetTickCount();
+ if (newTime - oldTime > 45000) {
+ smb_user_t *uidp;
+ smb_fid_t *fidp;
+ clientchar_t *treepath = NULL; /* do not free */
+ clientchar_t *pathname = NULL;
+ cm_fid_t afid = {0,0,0,0,0};
+
+ uidp = smb_FindUID(vcp, asp->uid, 0);
+ smb_LookupTIDPath(vcp, asp->tid, &treepath);
+ fidp = smb_FindFID(vcp, inp->fid, 0);
+
+ if (fidp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->NTopen_pathp)
+ pathname = fidp->NTopen_pathp;
+ if (fidp->scp)
+ afid = fidp->scp->fid;
+ } else {
+ if (inp->stringsp->wdata)
+ pathname = inp->stringsp->wdata;
+ }
+
+ afsi_log("Request %s duration %d ms user 0x%x \"%S\" pid 0x%x mid 0x%x tid 0x%x \"%S\" path? \"%S\" afid (%d.%d.%d.%d)",
+ myCrt_2Dispatch(asp->opcode), newTime - oldTime,
+ asp->uid, uidp ? uidp->unp->name : NULL,
+ asp->pid, asp->mid, asp->tid,
+ treepath,
+ pathname,
+ afid.cell, afid.volume, afid.vnode, afid.unique);
+
+ if (fidp)
+ lock_ReleaseMutex(&fidp->mx);
+
+ if (uidp)
+ smb_ReleaseUID(uidp);
+ if (fidp)
+ smb_ReleaseFID(fidp);
+ }
+
/* free the input tran 2 packet */
smb_FreeTran2Packet(asp);
}
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
+ code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+ if (code == CM_ERROR_TIDIPC) {
+ is_ipc = TRUE;
+ osi_Log0(smb_logp, "Tran2Open received IPC TID");
+ }
+
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
- if (lastNamep &&
- (cm_ClientStrCmpI(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpI(lastNamep, _C("\\ipc$")) == 0)) {
+ if (lastNamep &&
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
+ (cm_ClientStrCmpI(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+ /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional)*/
+ (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log2(smb_logp, "smb_ReceiveTran2Open Creating RPC Fid [%d] code [%d]",
+ fidp->fid, code);
+ if (code) {
+ smb_ReleaseFID(fidp);
+ smb_FreeTran2Packet(outp);
+ osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "smb_ReceiveTran2Open Creating IOCTL Fid [%d]", fidp->fid);
+ }
/* copy out remainder of the parms */
parmSlot = 0;
outp->parmsp[parmSlot++] = 0; /* len */
outp->parmsp[parmSlot++] = 0x7fff;
outp->parmsp[parmSlot++] = openMode;
- outp->parmsp[parmSlot++] = 0; /* file type 0 ==> normal file or dir */
- outp->parmsp[parmSlot++] = 0; /* IPC junk */
+ outp->parmsp[parmSlot++] = file_type;
+ outp->parmsp[parmSlot++] = device_state;
}
/* and the final "always present" stuff */
outp->parmsp[parmSlot++] = 1; /* openAction found existing file */
return 0;
}
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log1(smb_logp, "Tran2Open rejecting IPC TID vcp %p", vcp);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADFD;
+ }
+#endif
+
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "Tran2Open rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "Tran2Open rejecting invalid name");
+#endif
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADNTFILENAME;
+ }
+
#ifdef DEBUG_VERBOSE
{
char *hexp, *asciip;
return CM_ERROR_BADSMB;
}
- code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
- if (code == CM_ERROR_TIDIPC) {
- /* Attempt to use a TID allocated for IPC. The client
- * is probably looking for DCE RPC end points which we
- * don't support OR it could be looking to make a DFS
- * referral request.
- */
- osi_Log0(smb_logp, "Tran2Open received IPC TID");
-#ifndef DFS_SUPPORT
- cm_ReleaseUser(userp);
- smb_FreeTran2Packet(outp);
- return CM_ERROR_NOSUCHPATH;
-#endif
- }
-
dscp = NULL;
code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
return code;
}
} else {
+ /* macintosh is expensive to program for it */
+ cm_FreeSpace(spacep);
+
#ifdef DFS_SUPPORT
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep);
if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
-
- /* macintosh is expensive to program for it */
- cm_FreeSpace(spacep);
}
/* if we get here, if code is 0, the file exists and is represented by
osi_assertx(dscp != NULL && scp == NULL, "null dsc || non-null sc");
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+ cm_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0) {
lock_ObtainRead(&scp->rw);
if (extraInfo) {
outp->parmsp[parmSlot++] = smb_Attributes(scp);
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
outp->parmsp[parmSlot++] = (unsigned short)(dosTime & 0xffff);
outp->parmsp[parmSlot++] = (unsigned short)((dosTime>>16) & 0xffff);
outp->parmsp[parmSlot++] = (unsigned short) (scp->length.LowPart & 0xffff);
case SMB_INFO_VOLUME:
/* volume info */
qi.u.volumeInfo.vsn = 1234; /* Volume serial number */
- qi.u.volumeInfo.vnCount = 4; /* Number of characters in label (AFS\0)*/
+ qi.u.volumeInfo.vnCount = 3; /* Number of characters in label (AFS\0)*/
/* we're supposed to pad it out with zeroes to the end */
memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
}
qi.u.FSvolumeInfo.vsn = 1234;
- qi.u.FSvolumeInfo.vnCount = 8; /* This is always in Unicode */
+ qi.u.FSvolumeInfo.vnCount = 6; /* This is always in Unicode */
+ memset(&qi.u.FSvolumeInfo.label, 0, sizeof(qi.u.FSvolumeInfo.label));
memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
break;
/* attributes, defined in WINNT.H:
* FILE_CASE_SENSITIVE_SEARCH 0x1
* FILE_CASE_PRESERVED_NAMES 0x2
+ * FILE_UNICODE_ON_DISK 0x4
* FILE_VOLUME_QUOTAS 0x10
* <no name defined> 0x4000
* If bit 0x4000 is not set, Windows 95 thinks
qi.u.FSattributeInfo.attributes = 0x4003;
/* The maxCompLength is supposed to be in bytes */
#ifdef SMB_UNICODE
- if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
- qi.u.FSattributeInfo.maxCompLength = MAX_PATH * sizeof(wchar_t);
- else {
-#endif
- qi.u.FSattributeInfo.maxCompLength = MAX_PATH;
-#ifdef SMB_UNICODE
- }
+ qi.u.FSattributeInfo.attributes |= 0x04;
#endif
- smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, 0);
+ qi.u.FSattributeInfo.maxCompLength = 255;
+ smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, SMB_STRF_IGNORENUL);
qi.u.FSattributeInfo.FSnameLength = sz;
responseSize =
rockp = vrockp;
- cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(clientchar_t));
+ if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(clientchar_t)) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
/* compare both names and vnodes, though probably just comparing vnodes
* would be safe enough.
osi_hyper_t thyper;
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
cm_user_t *userp;
cm_space_t *spacep;
cm_scache_t *scp, *dscp;
- int scp_mx_held = 0;
+ int scp_rw_held = 0;
int delonclose = 0;
long code = 0;
clientchar_t *pathp;
responseSize = sizeof(qpi.u.QPfileAllInfo);
else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO)
responseSize = sizeof(qpi.u.QPfileAltNameInfo);
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+ responseSize = sizeof(qpi.u.QPfileStreamInfo);
else {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2QPathInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
return 0;
}
+ memset(&qpi, 0, sizeof(qpi));
pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH);
- osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %S", infoLevel,
+ osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path \"%S\"", infoLevel,
osi_LogSaveClientString(smb_logp, pathp));
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
outp->totalParms = 2;
else
outp->totalParms = 0;
- outp->totalData = responseSize;
/* now, if we're at infoLevel 6, we're only being asked to check
* the syntax, so we just OK things now. In particular, we're *not*
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if(code) {
+ osi_Log1(smb_logp, "ReceiveTran2QPathInfo tid path lookup failure 0x%x", code);
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH);
smb_FreeTran2Packet(outp);
return 0;
}
+ osi_Log1(smb_logp, "T2 QPathInfo tidPathp \"%S\"",
+ osi_LogSaveClientString(smb_logp, tidPathp));
+
/*
* XXX Strange hack XXX
*
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
/* Make sure that lastComp is not NULL */
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
} else
#endif /* DFS_SUPPORT */
if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
return 0;
#endif /* DFS_SUPPORT */
lock_ObtainWrite(&scp->rw);
- scp_mx_held = 1;
+ scp_rw_held = 2;
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) goto done;
+ if (code)
+ goto done;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ConvertWToR(&scp->rw);
+ scp_rw_held = 1;
len = 0;
goto done;
}
- smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAltNameInfo.fileNameLength = len;
-
- goto done;
+ responseSize = sizeof(unsigned long) + len;
}
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
- smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileNameInfo.fileNameLength = len;
-
- goto done;
+ responseSize = sizeof(unsigned long) + len;
}
else if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
qpi.u.QPstandardInfo.creationDateTime = dosTime;
qpi.u.QPstandardInfo.lastAccessDateTime = dosTime;
qpi.u.QPstandardInfo.lastWriteDateTime = dosTime;
qpi.u.QPstandardInfo.eaSize = 0;
}
else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qpi.u.QPfileBasicInfo.creationTime = ft;
qpi.u.QPfileBasicInfo.lastAccessTime = ft;
qpi.u.QPfileBasicInfo.lastWriteTime = ft;
qpi.u.QPfileBasicInfo.reserved = 0;
}
else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
- smb_fid_t *fidp = smb_FindFIDByScache(vcp, scp);
+ smb_fid_t * fidp;
+
+ lock_ReleaseRead(&scp->rw);
+ scp_rw_held = 0;
+ fidp = smb_FindFIDByScache(vcp, scp);
qpi.u.QPfileStandardInfo.allocationSize = scp->length;
qpi.u.QPfileStandardInfo.endOfFile = scp->length;
qpi.u.QPfileStandardInfo.reserved = 0;
if (fidp) {
- lock_ReleaseRead(&scp->rw);
- scp_mx_held = 0;
lock_ObtainMutex(&fidp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
lock_ReleaseMutex(&fidp->mx);
qpi.u.QPfileEaInfo.eaSize = 0;
}
else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ smb_fid_t * fidp;
+
+ lock_ReleaseRead(&scp->rw);
+ scp_rw_held = 0;
+ fidp = smb_FindFIDByScache(vcp, scp);
+
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qpi.u.QPfileAllInfo.creationTime = ft;
qpi.u.QPfileAllInfo.lastAccessTime = ft;
qpi.u.QPfileAllInfo.lastWriteTime = ft;
((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
- qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.cell;
- qpi.u.QPfileAllInfo.indexNumber.LowPart = scp->fid.volume;
+ qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.vnode;
+ qpi.u.QPfileAllInfo.indexNumber.LowPart = scp->fid.unique;
qpi.u.QPfileAllInfo.eaSize = 0;
- qpi.u.QPfileAllInfo.accessFlags = 0;
- qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.vnode;
- qpi.u.QPfileAllInfo.indexNumber2.LowPart = scp->fid.unique;
+ qpi.u.QPfileAllInfo.accessFlags = 0;
+ if (fidp) {
+ lock_ObtainMutex(&fidp->mx);
+ if (fidp->flags & SMB_FID_OPENDELETE)
+ qpi.u.QPfileAllInfo.accessFlags |= DELETE;
+ if (fidp->flags & SMB_FID_OPENREAD_LISTDIR)
+ qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_READ|AFS_ACCESS_EXECUTE;
+ if (fidp->flags & SMB_FID_OPENWRITE)
+ qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_WRITE;
+ if (fidp->flags & SMB_FID_DELONCLOSE)
+ qpi.u.QPfileAllInfo.deletePending = 1;
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ }
+ qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.cell;
+ qpi.u.QPfileAllInfo.indexNumber2.LowPart = scp->fid.volume;
qpi.u.QPfileAllInfo.currentByteOffset.HighPart = 0;
qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0;
qpi.u.QPfileAllInfo.mode = 0;
qpi.u.QPfileAllInfo.alignmentRequirement = 0;
- smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAllInfo.fileNameLength = len;
+ responseSize -= (sizeof(qpi.u.QPfileAllInfo.fileName) - len);
+ }
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+ size_t len = 0;
+ /* For now we have no streams */
+ qpi.u.QPfileStreamInfo.nextEntryOffset = 0;
+ if (scp->fileType == CM_SCACHETYPE_FILE) {
+ qpi.u.QPfileStreamInfo.streamSize = scp->length;
+ qpi.u.QPfileStreamInfo.streamAllocationSize = scp->length;
+ smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+ qpi.u.QPfileStreamInfo.streamNameLength = len;
+ responseSize -= (sizeof(qpi.u.QPfileStreamInfo.fileName) - len);
+ } else {
+ qpi.u.QPfileStreamInfo.streamSize.QuadPart = 0;
+ qpi.u.QPfileStreamInfo.streamAllocationSize.QuadPart = 0;
+ smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"", &len, SMB_STRF_IGNORENUL);
+ qpi.u.QPfileStreamInfo.streamNameLength = 0;
+ responseSize = 0;
+ }
}
+ outp->totalData = responseSize;
/* send and free the packets */
done:
- if (scp_mx_held)
+ switch (scp_rw_held) {
+ case 1:
lock_ReleaseRead(&scp->rw);
+ break;
+ case 2:
+ lock_ReleaseWrite(&scp->rw);
+ break;
+ }
+ scp_rw_held = 0;
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (code == 0) {
return CM_ERROR_BADOP;
#else
long code = 0;
- smb_fid_t *fidp;
unsigned short infoLevel;
clientchar_t * pathp;
smb_tran2Packet_t *outp;
if (infoLevel != SMB_INFO_STANDARD &&
infoLevel != SMB_INFO_QUERY_EA_SIZE &&
infoLevel != SMB_INFO_QUERY_ALL_EAS) {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2SetPathInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx,
infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
/* Make sure that lastComp is not NULL */
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
} else
#endif /* DFS_SUPPORT */
if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
return 0;
}
- fidp = smb_FindFIDByScache(vcp, scp);
- if (!fidp) {
- cm_ReleaseSCache(scp);
- cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, code);
- return 0;
- }
-
- lock_ObtainMutex(&fidp->mx);
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- lock_ReleaseMutex(&fidp->mx);
- cm_ReleaseSCache(scp);
- smb_ReleaseFID(fidp);
- cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
- return 0;
- }
- lock_ReleaseMutex(&fidp->mx);
-
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0);
outp->totalParms = 2;
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseWrite(&scp->rw);
- lock_ObtainMutex(&fidp->mx);
- lock_ObtainRead(&scp->rw);
-
/* prepare for setattr call */
attr.mask = CM_ATTRMASK_LENGTH;
attr.length.LowPart = spi->u.QPstandardInfo.dataSize;
attr.length.HighPart = 0;
if (spi->u.QPstandardInfo.lastWriteDateTime != 0) {
- smb_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
+ cm_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- fidp->flags |= SMB_FID_MTIMESETDONE;
}
if (spi->u.QPstandardInfo.attributes != 0) {
- if ((scp->unixModeBits & 0222)
+ if ((scp->unixModeBits & 0200)
&& (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) != 0) {
/* make a writable file read-only */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
attr.unixModeBits = scp->unixModeBits & ~0222;
}
- else if ((scp->unixModeBits & 0222) == 0
+ else if ((scp->unixModeBits & 0200) == 0
&& (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) == 0) {
/* make a read-only file writable */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
}
}
lock_ReleaseRead(&scp->rw);
- lock_ReleaseMutex(&fidp->mx);
/* call setattr */
if (attr.mask)
done:
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- smb_ReleaseFID(fidp);
if (code == 0)
smb_SendTran2Packet(vcp, outp, opx);
else
fidp = smb_FindFID(vcp, fid, 0);
if (fidp == NULL) {
+ osi_Log2(smb_logp, "Tran2QFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
return 0;
}
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return 0;
}
+ lock_ReleaseMutex(&fidp->mx);
infoLevel = p->parmsp[1];
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
responseSize = sizeof(qfi.u.QFeaInfo);
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
responseSize = sizeof(qfi.u.QFfileNameInfo);
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+ responseSize = sizeof(qfi.u.QFfileStreamInfo);
else {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2QFileInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
smb_ReleaseFID(fidp);
return 0;
}
osi_Log2(smb_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
+ memset(&qfi, 0, sizeof(qfi));
outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
outp->totalParms = 2;
else
outp->totalParms = 0;
- outp->totalData = responseSize;
userp = smb_GetTran2User(vcp, p);
if (!userp) {
* Marshall the output data.
*/
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
qfi.u.QFbasicInfo.creationTime = ft;
qfi.u.QFbasicInfo.lastAccessTime = ft;
qfi.u.QFbasicInfo.lastWriteTime = ft;
name = _C("\\"); /* probably can't happen */
lock_ReleaseMutex(&fidp->mx);
- smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, 0);
- outp->totalData = len + 4; /* this is actually what we want to return */
+ smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, SMB_STRF_IGNORENUL);
+ responseSize = len + 4; /* this is actually what we want to return */
qfi.u.QFfileNameInfo.fileNameLength = len;
}
+ else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+ size_t len = 0;
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) {
+ /* Do not return the alternate streams for directories */
+ responseSize = 0;
+ } else {
+ /* For now we have no alternate streams */
+ qfi.u.QFfileStreamInfo.nextEntryOffset = 0;
+ qfi.u.QFfileStreamInfo.streamSize = scp->length;
+ qfi.u.QFfileStreamInfo.streamAllocationSize = scp->length;
+ smb_UnparseString(opx, qfi.u.QFfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+ qfi.u.QFfileStreamInfo.streamNameLength = len;
+ responseSize -= (sizeof(qfi.u.QFfileStreamInfo.fileName) - len);
+ }
+ }
+ outp->totalData = responseSize;
/* send and free the packets */
done:
fidp = smb_FindFID(vcp, fid, 0);
if (fidp == NULL) {
+ osi_Log2(smb_logp, "Tran2SetFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
return 0;
}
- if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
- smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
- smb_CloseFID(vcp, fidp, NULL, 0);
- smb_ReleaseFID(fidp);
- return 0;
- }
-
infoLevel = p->parmsp[1];
osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type 0x%x fid %d", infoLevel, fid);
if (infoLevel > SMB_SET_FILE_END_OF_FILE_INFO || infoLevel < SMB_SET_FILE_BASIC_INFO) {
- osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+ osi_Log2(smb_logp, "Bad Tran2SetFileInfo op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
smb_ReleaseFID(fidp);
}
lock_ObtainMutex(&fidp->mx);
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return 0;
+ }
+
if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO &&
!(fidp->flags & SMB_FID_OPENDELETE)) {
osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENDELETE fidp 0x%p scp 0x%p fidp->flags 0x%x",
if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) &&
lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
+ cm_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
fidp->flags |= SMB_FID_MTIMESETDONE;
}
attribute = sfi->u.QFbasicInfo.attributes;
if (attribute != 0) {
- if ((scp->unixModeBits & 0222)
+ if ((scp->unixModeBits & 0200)
&& (attribute & SMB_ATTR_READONLY) != 0) {
/* make a writable file read-only */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
attr.unixModeBits = scp->unixModeBits & ~0222;
}
- else if ((scp->unixModeBits & 0222) == 0
+ else if ((scp->unixModeBits & 0200) == 0
&& (attribute & SMB_ATTR_READONLY) == 0) {
/* make a read-only file writable */
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
/*
* We have a requested path. Check to see if it is something
* we know about.
- *
- * But be careful because the name that we might be searching
- * for might be a known name with the final character stripped
- * off. If we
+ *
+ * But be careful because the name that we might be searching
+ * for might be a known name with the final character stripped
+ * off.
*/
code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
userp, NULL, &req, &scp);
- if (code == 0) {
+ if (code == 0 ||
+ code == CM_ERROR_ALLDOWN ||
+ code == CM_ERROR_ALLBUSY ||
+ code == CM_ERROR_ALLOFFLINE ||
+ code == CM_ERROR_NOSUCHCELL ||
+ code == CM_ERROR_NOSUCHVOLUME ||
+ code == CM_ERROR_NOACCESS) {
/* Yes it is. */
found = 1;
cm_ClientStrCpy(referralPath, lengthof(referralPath), requestFileName);
cm_ReleaseSCache(scp);
scp = 0;
}
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(pathName, &lastComponent, temp);
code = cm_NameI(cm_data.rootSCachep, pathName,
for ( i=0;i<=refLen; i++ )
sp[i+idx] = referralPath[i];
#endif
+ } else {
+ code = CM_ERROR_NOSUCHPATH;
}
} else {
code = CM_ERROR_NOSUCHPATH;
}
static long
-smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
+smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
clientchar_t * tidPathp, clientchar_t * relPathp,
- int infoLevel, cm_user_t *userp,
- cm_req_t *reqp)
+ int infoLevel, cm_user_t *userp, cm_req_t *reqp)
{
long code = 0;
cm_scache_t *scp;
clientchar_t path[AFSPATHMAX];
code = cm_FindACLCache(dscp, userp, &rights);
- if (code == 0 && !(rights & PRSFS_READ))
- mustFake = 1;
- else if (code == -1) {
+ if (code == -1) {
lock_ObtainWrite(&dscp->rw);
code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == 0)
+ cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&dscp->rw);
if (code == CM_ERROR_NOACCESS) {
mustFake = 1;
}
}
if (code)
- return code;
+ goto cleanup;
- for(patchp = *dirPatchespp; patchp; patchp =
- (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
- cm_ClientStrPrintfN(path, lengthof(path),_C("%s\\%S"),
- relPathp ? relPathp : _C(""), patchp->dep->name);
- reqp->relPathp = path;
- reqp->tidPathp = tidPathp;
+ if (!mustFake) { /* Bulk Stat */
+ afs_uint32 count;
+ cm_bulkStat_t *bsp = malloc(sizeof(cm_bulkStat_t));
- code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
- reqp->relPathp = reqp->tidPathp = NULL;
- if (code)
- continue;
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
- lock_ObtainWrite(&scp->rw);
- if (mustFake == 0)
- code = cm_SyncOp(scp, NULL, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (mustFake || code) {
+ for (patchp = *dirPatchespp, count=0;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ cm_scache_t *tscp = NULL;
+ int i;
+
+ code = cm_GetSCache(&patchp->fid, &tscp, userp, reqp);
+ if (code == 0) {
+ if (lock_TryWrite(&tscp->rw)) {
+ /* we have an entry that we can look at */
+#ifdef AFS_FREELANCE_CLIENT
+ if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
+ code = cm_SyncOp(tscp, NULL, userp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == 0)
+ cm_SyncOpDone(tscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+ lock_ReleaseWrite(&tscp->rw);
+ cm_ReleaseSCache(tscp);
+ continue;
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+ if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
+ /* we have a callback on it. Don't bother
+ * fetching this stat entry, since we're happy
+ * with the info we have.
+ */
+ lock_ReleaseWrite(&tscp->rw);
+ cm_ReleaseSCache(tscp);
+ continue;
+ }
+ lock_ReleaseWrite(&tscp->rw);
+ } /* got lock */
+ cm_ReleaseSCache(tscp);
+ } /* found entry */
+
+ i = bsp->counter++;
+ bsp->fids[i].Volume = patchp->fid.volume;
+ bsp->fids[i].Vnode = patchp->fid.vnode;
+ bsp->fids[i].Unique = patchp->fid.unique;
+
+ if (bsp->counter == AFSCBMAX) {
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
+ }
+ }
+
+ if (bsp->counter > 0)
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+
+ free(bsp);
+ }
+
+ for( patchp = *dirPatchespp;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ cm_ClientStrPrintfN(path, lengthof(path),_C("%s\\%S"),
+ relPathp ? relPathp : _C(""), patchp->dep->name);
+ reqp->relPathp = path;
+ reqp->tidPathp = tidPathp;
+
+ code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
+ reqp->relPathp = reqp->tidPathp = NULL;
+ if (code)
+ continue;
+
+ lock_ObtainWrite(&scp->rw);
+ if (mustFake || (scp->flags & CM_SCACHEFLAG_EACCESS) || !cm_HaveCallback(scp)) {
lock_ReleaseWrite(&scp->rw);
/* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter'
switch (scp->fileType) {
case CM_SCACHETYPE_DIRECTORY:
case CM_SCACHETYPE_MOUNTPOINT:
- case CM_SCACHETYPE_SYMLINK:
case CM_SCACHETYPE_INVALID:
fa->extFileAttributes = SMB_ATTR_DIRECTORY;
break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ fa->extFileAttributes = SMB_ATTR_DIRECTORY;
+ else
+ fa->extFileAttributes = SMB_ATTR_NORMAL;
+ break;
default:
/* if we get here we either have a normal file
* or we have a file for which we have never
* received status info. In this case, we can
* check the even/odd value of the entry's vnode.
- * even means it is to be treated as a directory
- * and odd means it is to be treated as a file.
+ * odd means it is to be treated as a directory
+ * and even means it is to be treated as a file.
*/
if (mustFake && (scp->fid.vnode & 0x1))
fa->extFileAttributes = SMB_ATTR_DIRECTORY;
switch (scp->fileType) {
case CM_SCACHETYPE_DIRECTORY:
case CM_SCACHETYPE_MOUNTPOINT:
- case CM_SCACHETYPE_SYMLINK:
case CM_SCACHETYPE_INVALID:
fa->attributes = SMB_ATTR_DIRECTORY;
break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ fa->attributes = SMB_ATTR_DIRECTORY;
+ else
+ fa->attributes = SMB_ATTR_NORMAL;
+ break;
default:
/* if we get here we either have a normal file
* or we have a file for which we have never
else
fa->attributes = SMB_ATTR_NORMAL;
}
+
/* merge in hidden (dot file) attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
fa->attributes |= SMB_ATTR_HIDDEN;
continue;
}
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr;
/* get filetime */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
fa->creationTime = ft;
fa->lastAccessTime = ft;
/* Copy attributes */
lattr = smb_ExtAttributes(scp);
- if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK ||
+ if ((code == CM_ERROR_NOSUCHPATH &&
+ (scp->fileType == CM_SCACHETYPE_SYMLINK &&
+ cm_TargetPerceivedAsDirectory(scp->mountPointStringp))) ||
code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
if (lattr == SMB_ATTR_NORMAL)
lattr = SMB_ATTR_DIRECTORY;
smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr;
/* get dos time */
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
fa->creationDateTime = MAKELONG(HIWORD(dosTime), LOWORD(dosTime));
fa->lastAccessDateTime = fa->creationDateTime;
/* and mark the list as empty */
*dirPatchespp = NULL;
+ cleanup:
return code;
}
maxReturnParms = 10; /* return params for findfirst, which
is the only one we handle.*/
-#ifndef CM_CONFIG_MULTITRAN2RESPONSES
- if (maxReturnData > 6000)
- maxReturnData = 6000;
-#endif /* CM_CONFIG_MULTITRAN2RESPONSES */
-
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
/* try to get the vnode for the path name next */
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
return 0;
/* add header to name & term. null */
onbytes = 0;
- smb_UnparseString(opx, NULL, maskp, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, NULL, maskp, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
orbytes = ohbytes + onbytes;
/* now, we round up the record to a 4 byte alignment, and we make
memset(origOp, 0, orbytes);
onbytes = 0;
- smb_UnparseString(opx, origOp + ohbytes, maskp, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, origOp + ohbytes, maskp, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
switch (infoLevel) {
case SMB_INFO_STANDARD:
#ifdef SMB_UNICODE
int nchars;
- nchars = cm_ClientStringToUtf16(shortName, -1,
+ nchars = cm_ClientStringToUtf16(shortName, cm_ClientStrLen(shortName),
fp->u.FfileBothDirectoryInfo.shortName,
sizeof(fp->u.FfileBothDirectoryInfo.shortName)/sizeof(wchar_t));
if (nchars > 0)
- fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t);
+ fp->u.FfileBothDirectoryInfo.shortNameLength = nchars*sizeof(wchar_t);
else
fp->u.FfileBothDirectoryInfo.shortNameLength = 0;
fp->u.FfileBothDirectoryInfo.reserved = 0;
else
maxReturnParms = 8; /* bytes */
-#ifndef CM_CONFIG_MULTITRAN2RESPONSES
- if (maxReturnData > 6000)
- maxReturnData = 6000;
-#endif /* CM_CONFIG_MULTITRAN2RESPONSES */
-
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
+ if (maxCount > 500)
+ maxCount = 500;
+
osi_Log2(smb_logp, "T2 receive search dir count %d [%S]",
maxCount, osi_LogSaveClientString(smb_logp, pathp));
code = 0;
} else {
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
- code = CM_ERROR_BADSHARENAME;
+ code = CM_ERROR_NOSUCHPATH;
smb_SendTran2Error(vcp, p, opx, code);
smb_FreeTran2Packet(outp);
lock_ReleaseMutex(&dsp->mx);
* and so we do another hold now.
*/
cm_HoldSCache(scp);
- lock_ObtainWrite(&scp->rw);
- if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
- LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
- scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags |= SMB_DIRSEARCH_BULKST;
- }
- lock_ReleaseWrite(&scp->rw);
+ dsp->flags |= SMB_DIRSEARCH_BULKST;
}
}
lock_ReleaseMutex(&dsp->mx);
break;
}
+ /* when we have obtained as many entries as can be processed in
+ * a single Bulk Status call to the file server, apply the dir listing
+ * patches.
+ */
+ if (returnedNames > 0 && returnedNames % AFSCBMAX == 0) {
+ lock_ReleaseWrite(&scp->rw);
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
+ dsp->relPath, infoLevel, userp, &req);
+ lock_ObtainWrite(&scp->rw);
+ }
+ /* Then check to see if we have time left to process more entries */
+ if (GetTickCount() - req.startTime > (RDRtimeout - 15) * 1000) {
+ osi_Log0(smb_logp, "T2 search dir RDRtimeout exceeded");
+ break;
+ }
+
/* see if we can use the bufferp we have now; compute in which
* page the current offset would be, and check whether that's
* the offset of the buffer we have. If not, get the buffer.
bufferp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &bufferp);
- lock_ObtainMutex(&dsp->mx);
-
- /* now, if we're doing a star match, do bulk fetching
- * of all of the status info for files in the dir.
- */
- if (starPattern) {
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, infoLevel, userp, &req);
-
- lock_ObtainWrite(&scp->rw);
- if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
- LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
- /* Don't bulk stat if risking timeout */
- DWORD now = GetTickCount();
- if (now - req.startTime > RDRtimeout * 1000) {
- scp->bulkStatProgress = thyper;
- scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags &= ~SMB_DIRSEARCH_BULKST;
- } else
- code = cm_TryBulkStat(scp, &thyper, userp, &req);
- }
- } else {
- lock_ObtainWrite(&scp->rw);
- }
- lock_ReleaseMutex(&dsp->mx);
+ code = buf_Get(scp, &thyper, &req, &bufferp);
+ lock_ObtainWrite(&scp->rw);
if (code) {
osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
break;
break;
}
- cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
-
if (cm_HaveBuffer(scp, bufferp, 0)) {
osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+ cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
break;
}
/* otherwise, load the buffer and try again */
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
+ cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
if (code) {
osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
scp, bufferp, code);
if (dep->fid.vnode == 0)
goto nextEntry; /* This entry is not in use */
- cm_FsStringToClientString(dep->name, -1, cfileName, lengthof(cfileName));
- cm_ClientStringToNormString(cfileName, -1, normName, lengthof(normName));
+ if (cm_FsStringToClientString(dep->name, -1, cfileName, lengthof(cfileName)) == 0 ||
+ cm_ClientStringToNormString(cfileName, -1, normName, lengthof(normName)) == 0) {
+
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't convert or normalize FS String",
+ osi_LogSaveString(smb_logp, dep->name));
+ goto nextEntry;
+ }
/* Need 8.3 name? */
NeedShortName = 0;
/* finally check if this name will fit */
onbytes = 0;
- smb_UnparseString(opx, NULL, cfileName, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, NULL, cfileName, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
orbytes = ohbytes + onbytes;
/* now, we round up the record to a 4 byte alignment,
memset(origOp, 0, orbytes);
onbytes = 0;
- smb_UnparseString(opx, origOp + ohbytes, cfileName, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, origOp + ohbytes, cfileName, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
switch (infoLevel) {
case SMB_INFO_STANDARD:
#ifdef SMB_UNICODE
int nchars;
- nchars = cm_ClientStringToUtf16(shortName, -1,
+ nchars = cm_ClientStringToUtf16(shortName, cm_ClientStrLen(shortName),
fp->u.FfileBothDirectoryInfo.shortName,
sizeof(fp->u.FfileBothDirectoryInfo.shortName)/sizeof(wchar_t));
if (nchars > 0)
- fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t);
+ fp->u.FfileBothDirectoryInfo.shortNameLength = nchars*sizeof(wchar_t);
else
fp->u.FfileBothDirectoryInfo.shortNameLength = 0;
fp->u.FfileBothDirectoryInfo.reserved = 0;
bufferp = NULL;
}
- /* apply and free last set of patches; if not doing a star match, this
- * will be empty, but better safe (and freeing everything) than sorry.
+ /*
+ * Finally, process whatever entries we have left.
*/
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
dsp->relPath, infoLevel, userp, &req);
/* now put out the final parameters */
clientchar_t *tidPathp;
cm_req_t req;
int created = 0;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
pathp = smb_ParseASCIIBlock(inp, smb_GetSMBData(inp, NULL), NULL,
SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
+
+ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+ if (code) {
+ if (code == CM_ERROR_TIDIPC) {
+ is_ipc = TRUE;
+ } else {
+ return CM_ERROR_NOSUCHPATH;
+ }
+ }
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
if (lastNamep &&
- (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
+
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
-#ifdef NOTSERVICE
- osi_Log0(smb_logp, "IOCTL Open");
-#endif
+ (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+ /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional) */
+ (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "OpenAndX Setting up RPC on fid[%d]", fidp->fid);
+ if (code) {
+ osi_Log1(smb_logp, "smb_SetupRPCFid failure code [%d]", code);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "OpenAndX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* len */
smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
- }
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++;
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++;
+ }
/* and the final "always present" stuff */
smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
/* next write out the "unique" ID */
return 0;
}
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log0(smb_logp, "NTOpenX rejecting IPC TID");
+ return CM_ERROR_BADFD;
+ }
+#endif
+
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "NTOpenX rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "NTOpenX rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
#ifdef DEBUG_VERBOSE
{
char *hexp, *asciip;
userp = smb_GetUserFromVCP(vcp, inp);
dscp = NULL;
- code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if (code) {
- cm_ReleaseUser(userp);
- return CM_ERROR_NOSUCHPATH;
- }
code = cm_NameI(cm_data.rootSCachep, pathp,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
/* otherwise, scp points to the parent directory. Do a lookup,
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3LockingX Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
lock_ReleaseMutex(&fidp->mx);
userp = smb_GetUserFromVCP(vcp, inp);
-
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
{
for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
- if (wl->key == key && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
+ if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
LargeIntegerEqualTo(wl->LLength, LLength)) {
wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
goto found_lock_request;
key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
- code = cm_Unlock(scp, LockType, LOffset, LLength, key, userp, &req);
+ code = cm_Unlock(scp, LockType, LOffset, LLength, key, 0, userp, &req);
if (code)
goto done;
userp, &req, &lockp);
}
- if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+ if (code == CM_ERROR_LOCK_NOT_GRANTED && Timeout != 0) {
smb_waitingLock_t * wLock;
/* Put on waiting list */
wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
- ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, userp, &req);
+ ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, 0, userp, &req);
if(ul_code != 0) {
osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Unlock returns code %d", ul_code);
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3GetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ConvertWToR(&scp->rw);
+ readlock = 1;
/* decode times. We need a search time, but the response to this
* call provides the date first, not the time, as returned in the
* searchTime variable. So we take the high-order bits first.
*/
- smb_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
+ cm_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff); /* ctime */
smb_SetSMBParm(outp, 1, searchTime & 0xffff);
smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff); /* atime */
fid = smb_ChainFID(fid, inp);
fidp = smb_FindFID(vcp, fid, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "V3SetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
-
+ }
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- lock_ObtainMutex(&fidp->mx);
if (fidp->flags & SMB_FID_IOCTL) {
lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
userp = smb_GetUserFromVCP(vcp, inp);
-
/* now prepare to call cm_setattr. This message only sets various times,
* and AFS only implements mtime, and we'll set the mtime if that's
* requested. The others we'll ignore.
searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
if (searchTime != 0) {
- smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+ cm_UnixTimeFromSearchTime(&unixTime, searchTime);
if ( unixTime != -1 ) {
attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
osi_Log1(smb_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
} else {
- osi_Log1(smb_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+ osi_Log1(smb_logp, "**cm_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
}
}
else
smb_fid_t *fidp;
smb_t *smbp = (smb_t*) inp;
long code = 0;
+ cm_scache_t *scp;
cm_user_t *userp;
char *op;
int inDataBlockCount;
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;
+ return CM_ERROR_INVAL;
}
#endif
}
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
- if (!fidp)
+ if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveV3WriteX Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
-
+ }
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
- 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;
}
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = smb_RPCV3Write(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFDOP;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
+
userp = smb_GetUserFromVCP(vcp, inp);
/* special case: 0 bytes transferred means there is no data
cm_key_t key;
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- cm_scache_t * scp;
pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LLength.HighPart = 0;
LLength.LowPart = count;
- scp = fidp->scp;
lock_ObtainWrite(&scp->rw);
code = cm_LockCheckWrite(scp, LOffset, LLength, key);
lock_ReleaseWrite(&scp->rw);
*/
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_ObtainWrite(&fidp->scp->rw);
+ scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+ scp->clientModTime = time(NULL);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
lock_ReleaseMutex(&fidp->mx);
smb_SetSMBDataLength(outp, 0);
done:
+
+ cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
smb_fid_t *fidp;
smb_t *smbp = (smb_t*) inp;
long code = 0;
+ cm_scache_t *scp;
cm_user_t *userp;
cm_key_t key;
char *op;
- fd = smb_GetSMBParm(inp, 2);
- count = smb_GetSMBParm(inp, 5);
+ fd = smb_GetSMBParm(inp, 2); /* File ID */
+ count = smb_GetSMBParm(inp, 5); /* MaxCount */
offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
if (*inp->wctp == 12) {
fd = smb_ChainFID(fd, inp);
fidp = smb_FindFID(vcp, fd, 0);
if (!fidp) {
+ osi_Log2(smb_logp, "smb_ReceiveV3Read Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fd);
return CM_ERROR_BADFD;
}
+ lock_ObtainMutex(&fidp->mx);
+
+ if (fidp->flags & SMB_FID_IOCTL) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_IoctlV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
+ if (fidp->flags & SMB_FID_RPC) {
+ lock_ReleaseMutex(&fidp->mx);
+ inp->fid = fd;
+ code = smb_RPCV3Read(fidp, vcp, inp, outp);
+ smb_ReleaseFID(fidp);
+ return code;
+ }
+
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
+ if (!fidp->scp) {
+ lock_ReleaseMutex(&fidp->mx);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_BADFDOP;
+ }
+
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+
+ lock_ReleaseMutex(&fidp->mx);
+
pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
{
LARGE_INTEGER LOffset, LLength;
- cm_scache_t *scp;
LOffset.HighPart = offset.HighPart;
LOffset.LowPart = offset.LowPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- scp = fidp->scp;
lock_ObtainWrite(&scp->rw);
code = cm_LockCheckRead(scp, LOffset, LLength, key);
lock_ReleaseWrite(&scp->rw);
}
+ cm_ReleaseSCache(scp);
if (code) {
smb_ReleaseFID(fidp);
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fd;
- lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_IOCTL) {
- lock_ReleaseMutex(&fidp->mx);
- code = smb_IoctlV3Read(fidp, vcp, inp, outp);
- smb_ReleaseFID(fidp);
- return code;
- }
- lock_ReleaseMutex(&fidp->mx);
-
userp = smb_GetUserFromVCP(vcp, inp);
/* 0 and 1 are reserved for request chaining, were setup by our caller,
#define FILE_RANDOM_ACCESS 0x0800
#define FILE_DELETE_ON_CLOSE 0x1000
#define FILE_OPEN_BY_FILE_ID 0x2000
+#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
+#define FILE_NO_COMPRESSION 0x00008000
+#define FILE_RESERVE_OPFILTER 0x00100000
+#define FILE_OPEN_REPARSE_POINT 0x00200000
+#define FILE_OPEN_NO_RECALL 0x00400000
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
/* SMB_COM_NT_CREATE_ANDX */
long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
BOOL foundscp;
cm_req_t req;
int created = 0;
+ int prefetch = 0;
+ int checkDoneRequired = 0;
cm_lock_data_t *ldp = NULL;
+ BOOL is_rpc = FALSE;
+ BOOL is_ipc = FALSE;
smb_InitReq(&req);
realPathp[nameLength/sizeof(clientchar_t)] = 0;
spacep = inp->spacep;
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
osi_Log1(smb_logp,"NTCreateX for [%S]",osi_LogSaveClientString(smb_logp,realPathp));
osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%S]", shareAccess, flags, osi_LogSaveClientString(smb_logp,(lastNamep?lastNamep:_C("null"))));
- if (lastNamep &&
- (cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\srvsvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("\\wkssvc")) == 0 ||
- cm_ClientStrCmpIA(lastNamep, _C("ipc$")) == 0)) {
- /* special case magic file name for receiving IOCTL requests
- * (since IOCTL calls themselves aren't getting through).
- */
+ if (baseFid == 0) {
+ baseFidp = NULL;
+ baseDirp = cm_data.rootSCachep;
+ code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+ if (code == CM_ERROR_TIDIPC) {
+ /* Attempt to use a TID allocated for IPC. The client
+ * is probably looking for DCE RPC end points which we
+ * don't support OR it could be looking to make a DFS
+ * referral request.
+ */
+ osi_Log0(smb_logp, "NTCreateX received IPC TID");
+ is_ipc = TRUE;
+ }
+ }
+
+ osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
+
+ if (lastNamep &&
+
+ ((is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)) ||
+
+ /* special case magic file name for receiving IOCTL requests
+ * (since IOCTL calls themselves aren't getting through).
+ */
+ cm_ClientStrCmpIA(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0)) {
+
+ unsigned short file_type = 0;
+ unsigned short device_state = 0;
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- smb_SetupIoctlFid(fidp, spacep);
- osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid);
+
+ if (is_rpc) {
+ code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+ osi_Log1(smb_logp, "NTCreateX Setting up RPC on fid[%d]", fidp->fid);
+ if (code) {
+ osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+ smb_ReleaseFID(fidp);
+ free(realPathp);
+ return code;
+ }
+ } else {
+ smb_SetupIoctlFid(fidp, spacep);
+ osi_Log1(smb_logp, "NTCreateX Setting up IOCTL on fid[%d]", fidp->fid);
+ }
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
sz.HighPart = 0x7fff; sz.LowPart = 0;
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */
smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
+ smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++; /* dev state */
smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */
smb_SetSMBDataLength(outp, 0);
return 0;
}
-#ifdef DEBUG_VERBOSE
- {
- char *hexp, *asciip;
- asciip = (lastNamep? lastNamep : realPathp);
- hexp = osi_HexifyString( asciip );
- DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
- free(hexp);
+#ifndef DFS_SUPPORT
+ if (is_ipc) {
+ osi_Log0(smb_logp, "NTCreateX rejecting IPC TID");
+ free(realPathp);
+ return CM_ERROR_BADFD;
}
#endif
+ if (!cm_IsValidClientString(realPathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(realPathp, -1);
+ osi_Log1(smb_logp, "NTCreateX rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "NTCreateX rejecting invalid name");
+#endif
+ free(realPathp);
+ return CM_ERROR_BADNTFILENAME;
+ }
+
userp = smb_GetUserFromVCP(vcp, inp);
if (!userp) {
osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
return CM_ERROR_INVAL;
}
- if (baseFid == 0) {
- baseFidp = NULL;
- baseDirp = cm_data.rootSCachep;
- code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
- if (code == CM_ERROR_TIDIPC) {
- /* Attempt to use a TID allocated for IPC. The client
- * is probably looking for DCE RPC end points which we
- * don't support OR it could be looking to make a DFS
- * referral request.
- */
- osi_Log0(smb_logp, "NTCreateX received IPC TID");
-#ifndef DFS_SUPPORT
- free(realPathp);
- cm_ReleaseUser(userp);
- return CM_ERROR_NOSUCHFILE;
-#endif /* DFS_SUPPORT */
- }
- } else {
+ if (baseFidp != 0) {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+ cm_ReleaseUser(userp);
free(realPathp);
- cm_ReleaseUser(userp);
return CM_ERROR_INVAL;
- }
+ }
if (baseFidp->scp && (baseFidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
free(realPathp);
- cm_ReleaseUser(userp);
smb_CloseFID(vcp, baseFidp, NULL, 0);
smb_ReleaseFID(baseFidp);
+ cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
tidPathp = NULL;
}
- osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
-
/* compute open mode */
fidflags = 0;
if (desiredAccess & DELETE)
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (createOptions & FILE_OPEN_REPARSE_POINT)
+ osi_Log0(smb_logp, "NTCreateX Open Reparse Point");
if (smb_IsExecutableFileName(lastNamep))
fidflags |= SMB_FID_EXECUTABLE;
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
/* we might have scp but not dscp */
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
if (code == 0 && !treeCreate) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
free(realPathp);
return code;
}
+ checkDoneRequired = 1;
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
scp = targetScp;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
if (code) {
/* something went wrong creating or truncating the file */
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (scp)
cm_ReleaseSCache(scp);
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
/* (only applies to single component case) */
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
if (dscp)
lock_ReleaseWrite(&scp->rw);
if (code) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
if (dscp)
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
free(realPathp);
- return code;
+ return CM_ERROR_SHARING_VIOLATION;
}
}
/* Now its safe to release the file server lock obtained by cm_CheckNTOpen() */
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
- /* out parms */
- parmSlot = 2;
lock_ObtainRead(&scp->rw);
- smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
- smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
- smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
- smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
- parmSlot += 2;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
- smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
- smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
- smb_SetSMBParmByte(outp, parmSlot,
- (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
- scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
- scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
- smb_SetSMBDataLength(outp, 0);
+
+ /*
+ * Always send the standard response. Sending the extended
+ * response results in the Explorer Shell being unable to
+ * access directories at random times.
+ */
+ if (1 /*!extendedRespRequired */) {
+ /* out parms */
+ parmSlot = 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+ parmSlot += 2;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+ parmSlot++; /* dev state */
+ smb_SetSMBParmByte(outp, parmSlot,
+ (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+ smb_SetSMBDataLength(outp, 0);
+ } else {
+ /* out parms */
+ parmSlot = 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+ smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+ smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+ smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+ parmSlot += 2;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+ smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+ smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+ parmSlot++; /* dev state */
+ smb_SetSMBParmByte(outp, parmSlot,
+ (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+ /* Setting the GUID results in a failure with cygwin */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Maxmimal access rights */
+ smb_SetSMBParmLong(outp, parmSlot, 0x001f01ff); parmSlot += 2;
+ /* Guest access rights */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBDataLength(outp, 0);
+ }
if ((fidp->flags & SMB_FID_EXECUTABLE) &&
- LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ LargeIntegerGreaterThanZero(scp->length) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
- cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
- fidp->scp->length.LowPart, fidp->scp->length.HighPart,
- userp);
+ prefetch = 1;
}
lock_ReleaseRead(&scp->rw);
+ if (prefetch)
+ cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+ scp->length.LowPart, scp->length.HighPart,
+ userp);
+
+
osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %S", fidp->fid,
osi_LogSaveClientString(smb_logp, realPathp));
unsigned int extendedRespRequired;
int realDirFlag;
unsigned int desiredAccess;
-#ifdef DEBUG_VERBOSE
unsigned int allocSize;
-#endif
unsigned int shareAccess;
unsigned int extAttributes;
unsigned int createDisp;
-#ifdef DEBUG_VERBOSE
unsigned int sdLen;
-#endif
+ unsigned int eaLen;
+ unsigned int impLevel;
+ unsigned int secFlags;
unsigned int createOptions;
int initialModeBits;
unsigned short baseFid;
char *outData;
cm_req_t req;
int created = 0;
+ int prefetch = 0;
cm_lock_data_t *ldp = NULL;
+ int checkDoneRequired = 0;
smb_InitReq(&req);
return CM_ERROR_INVAL;
baseFid = (unsigned short)lparmp[1];
desiredAccess = lparmp[2];
-#ifdef DEBUG_VERBOSE
allocSize = lparmp[3];
-#endif /* DEBUG_VERSOSE */
extAttributes = lparmp[5];
shareAccess = lparmp[6];
createDisp = lparmp[7];
createOptions = lparmp[8];
-#ifdef DEBUG_VERBOSE
sdLen = lparmp[9];
-#endif
- nameLength = lparmp[11];
-
-#ifdef DEBUG_VERBOSE
- osi_Log4(smb_logp,"NTTranCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
- osi_Log3(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
- osi_Log1(smb_logp,"... flags[%x]",flags);
-#endif
+ eaLen = lparmp[10];
+ nameLength = lparmp[11]; /* spec says chars but appears to be bytes */
+ impLevel = lparmp[12];
+ secFlags = lparmp[13];
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
if (extAttributes & SMB_ATTR_READONLY)
initialModeBits &= ~0222;
- pathp = smb_ParseStringCch(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
+ pathp = smb_ParseStringCb(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
nameLength, NULL, SMB_STRF_ANSIPATH);
- /* Sometimes path is not null-terminated, so we make a copy. */
- realPathp = malloc((nameLength+1) * sizeof(clientchar_t));
- memcpy(realPathp, pathp, nameLength * sizeof(clientchar_t));
- realPathp[nameLength] = 0;
+ /* Sometimes path is not nul-terminated, so we make a copy. */
+ realPathp = malloc(nameLength+sizeof(clientchar_t));
+ memcpy(realPathp, pathp, nameLength);
+ realPathp[nameLength/sizeof(clientchar_t)] = 0;
spacep = cm_GetSpace();
+ /* smb_StripLastComponent will strip "::$DATA" if present */
smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
+ osi_Log1(smb_logp,"NTTranCreate %S",osi_LogSaveStringW(smb_logp,realPathp));
+ osi_Log4(smb_logp,"... da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+ osi_Log4(smb_logp,"... co[%x],sdl[%x],eal[%x],as[%x],flags[%x]",createOptions,sdLen,eaLen,allocSize);
+ osi_Log3(smb_logp,"... imp[%x],sec[%x],flags[%x]", impLevel, secFlags, flags);
+
/*
* Nothing here to handle SMB_IOCTL_FILENAME.
* Will add it if necessary.
*/
-#ifdef DEBUG_VERBOSE
- {
- char *hexp, *asciip;
- asciip = (lastNamep? lastNamep : realPathp);
- hexp = osi_HexifyString( asciip );
- DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip);
+ if (!cm_IsValidClientString(realPathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(realPathp, -1);
+ osi_Log1(smb_logp, "NTTranCreate rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
free(hexp);
- }
+#else
+ osi_Log0(smb_logp, "NTTranCreate rejecting invalid name.");
#endif
+ free(realPathp);
+ return CM_ERROR_BADNTFILENAME;
+ }
userp = smb_GetUserFromVCP(vcp, inp);
if (!userp) {
} else {
baseFidp = smb_FindFID(vcp, baseFid, 0);
if (!baseFidp) {
- osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+ osi_Log2(smb_logp, "NTTranCreate Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, baseFid);
free(realPathp);
cm_ReleaseUser(userp);
return CM_ERROR_BADFD;
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (createOptions & FILE_OPEN_REPARSE_POINT)
+ osi_Log0(smb_logp, "NTTranCreate Open Reparse Point");
if (smb_IsExecutableFileName(lastNamep))
fidflags |= SMB_FID_EXECUTABLE;
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
}
if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
- return CM_ERROR_BADSHARENAME;
+ return CM_ERROR_NOSUCHPATH;
}
#endif /* DFS_SUPPORT */
} else
if (code == 0) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
free(realPathp);
return code;
}
+ checkDoneRequired = 1;
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
scp = targetScp;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
if (code) {
/* something went wrong creating or truncating the file */
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (scp)
cm_ReleaseSCache(scp);
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
}
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
lock_ReleaseWrite(&scp->rw);
if (code) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
}
/* Now its safe to drop the file server lock obtained by cm_CheckNTOpen() */
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
*((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
*((ULONG *)outData) = openAction; outData += 4;
*((ULONG *)outData) = 0; outData += 4; /* EA error offset */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)outData) = ft; outData += 8; /* creation time */
*((FILETIME *)outData) = ft; outData += 8; /* last access time */
*((FILETIME *)outData) = ft; outData += 8; /* last write time */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
*((USHORT *)outData) = 0; outData += 2; /* filetype */
- *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+ outData += 2; /* dev state */
*((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
*((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
*((ULONG *)outData) = openAction; outData += 4;
*((ULONG *)outData) = 0; outData += 4; /* EA error offset */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
*((FILETIME *)outData) = ft; outData += 8; /* creation time */
*((FILETIME *)outData) = ft; outData += 8; /* last access time */
*((FILETIME *)outData) = ft; outData += 8; /* last write time */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
*((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
*((USHORT *)outData) = 0; outData += 2; /* filetype */
- *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+ outData += 2; /* dev state */
*((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
outData += 1; /* is a dir? */
- memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+ /* Setting the GUID results in failures with cygwin */
+ memset(outData,0,24); outData += 24; /* GUID */
*((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
*((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
}
if ((fidp->flags & SMB_FID_EXECUTABLE) &&
- LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ LargeIntegerGreaterThanZero(scp->length) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
- cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
- fidp->scp->length.LowPart, fidp->scp->length.HighPart,
- userp);
+ prefetch = 1;
}
lock_ReleaseRead(&scp->rw);
+ if (prefetch)
+ cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+ scp->length.LowPart, scp->length.HighPart,
+ userp);
+
osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
cm_ReleaseUser(userp);
fidp = smb_FindFID(vcp, fid, 0);
if (!fidp) {
- osi_Log1(smb_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+ osi_Log2(smb_logp, "NotifyChange Unknown SMB Fid vcp 0x%p fid %d",
+ vcp, fid);
return CM_ERROR_BADFD;
}
+ lock_ObtainMutex(&fidp->mx);
if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ lock_ReleaseMutex(&fidp->mx);
smb_CloseFID(vcp, fidp, NULL, 0);
smb_ReleaseFID(fidp);
return CM_ERROR_NOSUCHFILE;
}
+ scp = fidp->scp;
+ cm_HoldSCache(scp);
+ lock_ReleaseMutex(&fidp->mx);
/* Create a copy of the Directory Watch Packet to use when sending the
* notification if in the future a matching change is detected.
*/
savedPacketp = smb_CopyPacket(inp);
- smb_HoldVC(vcp);
- if (savedPacketp->vcp)
- smb_ReleaseVC(savedPacketp->vcp);
- savedPacketp->vcp = vcp;
+ if (vcp != savedPacketp->vcp) {
+ smb_HoldVC(vcp);
+ if (savedPacketp->vcp)
+ smb_ReleaseVC(savedPacketp->vcp);
+ savedPacketp->vcp = vcp;
+ }
/* Add the watch to the list of events to send notifications for */
lock_ObtainMutex(&smb_Dir_Watch_Lock);
smb_Directory_Watches = savedPacketp;
lock_ReleaseMutex(&smb_Dir_Watch_Lock);
- scp = fidp->scp;
osi_Log3(smb_logp,"smb_ReceiveNTTranNotifyChange fidp 0x%p scp 0x%p file \"%S\"",
fidp, scp, osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp));
osi_Log3(smb_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d",
else
scp->flags |= CM_SCACHEFLAG_WATCHED;
lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
smb_ReleaseFID(fidp);
outp->flags |= SMB_PACKETFLAG_NOSEND;
osi_Log0(smb_logp, "SMB NT Transact Set Quota - not implemented");
break;
}
- return CM_ERROR_INVAL;
+ return CM_ERROR_BADOP;
}
/*
(!isDirectParent && !wtree))
{
osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
- smb_ReleaseFID(fidp);
lastWatch = watch;
watch = watch->nextp;
+ smb_ReleaseFID(fidp);
continue;
}
- smb_ReleaseFID(fidp);
osi_Log4(smb_logp,
"Sending Change Notification for fid %d filter 0x%x wtree %d file %S",
smb_SendPacket(watch->vcp, watch);
smb_FreePacket(watch);
+
+ smb_ReleaseFID(fidp);
watch = nextWatch;
}
lock_ReleaseMutex(&smb_Dir_Watch_Lock);
scp = fidp->scp;
osi_Log2(smb_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
- lock_ObtainWrite(&scp->rw);
- if (watchtree)
- scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
- else
- scp->flags &= ~CM_SCACHEFLAG_WATCHED;
- lock_ReleaseWrite(&scp->rw);
+ if (scp) {
+ lock_ObtainWrite(&scp->rw);
+ if (watchtree)
+ scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+ else
+ scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+ lock_ReleaseWrite(&scp->rw);
+ }
smb_ReleaseFID(fidp);
} else {
osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
tp = smb_GetSMBData(inp, NULL);
oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+ if (!oldPathp)
+ return CM_ERROR_BADSMB;
newPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+ if (!newPathp)
+ return CM_ERROR_BADSMB;
osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
osi_LogSaveClientString(smb_logp, oldPathp),
osi_LogSaveClientString(smb_logp, newPathp),
- ((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink"));
+ ((rename_type==RENAME_FLAG_RENAME)?"rename":(rename_type==RENAME_FLAG_HARD_LINK)?"hardlink":"other"));
if (rename_type == RENAME_FLAG_RENAME) {
code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
- } else { /* RENAME_FLAG_HARD_LINK */
+ } else if (rename_type == RENAME_FLAG_HARD_LINK) { /* RENAME_FLAG_HARD_LINK */
code = smb_Link(vcp,inp,oldPathp,newPathp);
- }
+ } else
+ code = CM_ERROR_BADOP;
return code;
}
void smb3_Init()
{
- lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
+ lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock", LOCK_HIERARCHY_SMB_DIRWATCH);
}
cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)