#include <afs/stds.h>
#include <windows.h>
+#pragma warning(push)
+#pragma warning(disable: 4005)
#include <ntstatus.h>
#define SECURITY_WIN32
#include <security.h>
#include <lmaccess.h>
+#pragma warning(pop)
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
/* protected by the smb_globalLock */
smb_tran2Packet_t *smb_tran2AssemblyQueuep;
+const char **smb_ExecutableExtensions = NULL;
+
/* retrieve a held reference to a user structure corresponding to an incoming
* request */
cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
return up;
}
+/*
+ * Return boolean specifying if the path name is thought to be an
+ * executable file. For now .exe or .dll.
+ */
+afs_uint32 smb_IsExecutableFileName(const char *name)
+{
+ int i, j, len;
+
+ if ( smb_ExecutableExtensions == NULL || name == NULL)
+ return 0;
+
+ len = (int)strlen(name);
+
+ for ( i=0; smb_ExecutableExtensions[i]; i++) {
+ j = len - (int)strlen(smb_ExecutableExtensions[i]);
+ if (_stricmp(smb_ExecutableExtensions[i], &name[j]) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Return extended attributes.
* Right now, we aren't using any of the "new" bits, so this looks exactly
}
void OutputDebugHexDump(unsigned char * buffer, int len) {
- int i,j,k,pcts=0;
+ int i,j,k;
char buf[256];
static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
for (i=0;i<len;i++) {
if(!(i%16)) {
if(i) {
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
+ osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
strcat(buf,"\r\n");
OutputDebugString(buf);
}
buf[j] = tr[k / 16]; buf[j+1] = tr[k % 16];
j = (i%16);
- j = j + 56 + ((j>7)?1:0) + pcts;
+ j = j + 56 + ((j>7)?1:0);
buf[j] = (k>32 && k<127)?k:'.';
- if (k == '%') {
- buf[++j] = k;
- pcts++;
- }
}
if(i) {
- osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
+ osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
strcat(buf,"\r\n");
OutputDebugString(buf);
}
smb_tid_t *tidp;
smb_user_t *uidp = NULL;
unsigned short newTid;
- char shareName[256];
+ char shareName[AFSPATHMAX];
char *sharePath;
int shareFound;
char *tp;
if (!shareFound) {
if (uidp)
smb_ReleaseUID(uidp);
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
return CM_ERROR_BADSHARENAME;
}
if (vcp->flags & SMB_VCFLAG_USENT)
{
int policy = smb_FindShareCSCPolicy(shareName);
+ HKEY parmKey;
+ DWORD code;
+ DWORD dwAdvertiseDFS = 0, dwSize = sizeof(DWORD);
+
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ code = RegQueryValueEx(parmKey, "AdvertiseDFS", NULL, NULL,
+ (BYTE *)&dwAdvertiseDFS, &dwSize);
+ if (code != ERROR_SUCCESS)
+ dwAdvertiseDFS = 0;
+ RegCloseKey (parmKey);
+ }
smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS |
-#ifdef DFS_SUPPORT
- SMB_SHARE_IS_IN_DFS |
-#endif
+ (dwAdvertiseDFS ? SMB_SHARE_IS_IN_DFS : 0) |
(policy << 2));
}
} else {
if (ipc)
tidp->flags |= SMB_TIDFLAG_IPC;
lock_ReleaseMutex(&tidp->mx);
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
((smb_t *)outp)->tid = newTid;
((smb_t *)inp)->tid = newTid;
} smb_rap_share_info_1_t;
typedef struct smb_rap_share_info_2 {
- char shi2_netname[13];
- char shi2_pad;
+ char shi2_netname[13];
+ char shi2_pad;
unsigned short shi2_type;
- DWORD shi2_remark; /* char *shi2_remark; data offset */
+ DWORD shi2_remark; /* char *shi2_remark; data offset */
unsigned short shi2_permissions;
unsigned short shi2_max_uses;
unsigned short shi2_current_uses;
- DWORD shi2_path; /* char *shi2_path; data offset */
+ DWORD shi2_path; /* char *shi2_path; data offset */
unsigned short shi2_passwd[9];
unsigned short shi2_pad2;
} smb_rap_share_info_2_t;
smb_rap_share_info_1_t * shares;
USHORT cshare = 0;
char * cstrp;
- char thisShare[256];
+ char thisShare[AFSPATHMAX];
int i,j;
DWORD dw;
int nonrootShares;
DWORD allSubmount;
LONG rv;
long code = 0;
+ cm_scache_t *scp = NULL;
+ cm_user_t *userp;
+ cm_req_t req;
+
+ cm_InitReq(&req);
tp = p->parmsp + 1; /* skip over function number (always 1) */
(void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */
else
return CM_ERROR_INVAL;
- outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
-
if(!stricmp(shareName,"all") || !strcmp(shareName,"*.")) {
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
KEY_QUERY_VALUE, &hkParam);
shareFound = TRUE;
} else {
- rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY "\\Submounts", 0,
- KEY_QUERY_VALUE, &hkSubmount);
- if (rv == ERROR_SUCCESS) {
- rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
+ userp = smb_GetTran2User(vcp, p);
+ if (!userp) {
+ osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ return CM_ERROR_BADSMB;
+ }
+ code = cm_NameI(cm_data.rootSCachep, shareName,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+ userp, NULL, &req, &scp);
+ if (code == 0) {
+ cm_ReleaseSCache(scp);
+ shareFound = TRUE;
+ } else {
+ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY "\\Submounts", 0,
+ KEY_QUERY_VALUE, &hkSubmount);
if (rv == ERROR_SUCCESS) {
- shareFound = TRUE;
+ rv = RegQueryValueEx(hkSubmount, shareName, NULL, NULL, NULL, NULL);
+ if (rv == ERROR_SUCCESS) {
+ shareFound = TRUE;
+ }
+ RegCloseKey(hkSubmount);
}
- RegCloseKey(hkSubmount);
}
}
- if (!shareFound) {
- smb_FreeTran2Packet(outp);
+ if (!shareFound)
return CM_ERROR_BADSHARENAME;
- }
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
memset(outp->datap, 0, totalData);
outp->parmsp[0] = 0;
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+ if (lastNamep &&
+ (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+ stricmp(lastNamep, "\\srvsvc") == 0 ||
+ stricmp(lastNamep, "\\wkssvc") == 0 ||
+ stricmp(lastNamep, "\\ipc$") == 0)) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
- if ( WANTS_DFS_PATHNAMES(p) )
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
} else {
#ifdef DFS_SUPPORT
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
- if ( WANTS_DFS_PATHNAMES(p) )
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
/* don't create if not found */
if (dscp)
cm_ReleaseSCache(dscp);
- osi_assert(scp == NULL);
+ osi_assertx(scp == NULL, "null cm_scache_t");
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
return CM_ERROR_NOSUCHFILE;
}
else {
- osi_assert(dscp != NULL && scp == NULL);
+ 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);
/* now all we have to do is open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- osi_assert(fidp);
+ osi_assertx(fidp, "null smb_fid_t");
cm_HoldUser(userp);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
osi_Log2(smb_logp,"smb_ReceiveTran2Open fidp 0x%p scp 0x%p", fidp, scp);
fidp->scp = scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
/* and the user */
fidp->userp = userp;
/* copy out remainder of the parms */
parmSlot = 0;
outp->parmsp[parmSlot++] = fidp->fid;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
if (extraInfo) {
outp->parmsp[parmSlot++] = smb_Attributes(scp);
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
outp->parmsp[parmSlot++] = 0;
outp->parmsp[parmSlot++] = 0;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
outp->totalData = 0; /* total # of data bytes */
outp->totalParms = parmSlot * 2; /* shorts are two bytes */
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
+ DebugBreak();
return CM_ERROR_PATH_NOT_COVERED;
}
#endif /* DFS_SUPPORT */
if (code == 0) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
- if ( WANTS_DFS_PATHNAMES(p) )
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
code = CM_ERROR_BADSHARENAME;
code = CM_ERROR_NOSUCHFILE;
else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
cm_buf_t *bp = buf_Find(dscp, &hzero);
- if (bp)
+ if (bp) {
buf_Release(bp);
+ bp = NULL;
+ }
else
code = CM_ERROR_NOSUCHFILE;
}
#ifdef DFS_SUPPORT
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- if ( WANTS_DFS_PATHNAMES(p) )
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
code = CM_ERROR_BADSHARENAME;
}
#endif /* DFS_SUPPORT */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp_mx_held = 1;
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ConvertWToR(&scp->rw);
+
/* now we have the status in the cache entry, and everything is locked.
* Marshall the output data.
*/
goto done;
}
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
- len = strlen(lastComp);
+ len = (unsigned int)strlen(lastComp);
qpi.u.QPfileNameInfo.fileNameLength = (len + 1) * 2;
mbstowcs((unsigned short *)qpi.u.QPfileNameInfo.fileName, lastComp, len + 1);
qpi.u.QPfileStandardInfo.reserved = 0;
if (fidp) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
scp_mx_held = 0;
lock_ObtainMutex(&fidp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0;
qpi.u.QPfileAllInfo.mode = 0;
qpi.u.QPfileAllInfo.alignmentRequirement = 0;
- len = strlen(lastComp);
+ len = (unsigned int)strlen(lastComp);
qpi.u.QPfileAllInfo.fileNameLength = (len + 1) * 2;
mbstowcs((unsigned short *)qpi.u.QPfileAllInfo.fileName, lastComp, len + 1);
}
/* send and free the packets */
done:
if (scp_mx_held)
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (code == 0) {
infoLevel != SMB_INFO_QUERY_ALL_EAS) {
osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
p->opcode, infoLevel);
- smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
+ smb_SendTran2Error(vcp, p, opx,
+ infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
return 0;
}
if (code == 0) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
- if ( WANTS_DFS_PATHNAMES(p) )
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
code = CM_ERROR_BADSHARENAME;
code = CM_ERROR_NOSUCHFILE;
else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
cm_buf_t *bp = buf_Find(dscp, &hzero);
- if (bp)
+ if (bp) {
buf_Release(bp);
+ bp = NULL;
+ }
else
code = CM_ERROR_NOSUCHFILE;
}
/* lock the vnode with a callback; we need the current status
* to determine what the new status is, in some cases.
*/
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS
| CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
goto done;
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
/* prepare for setattr call */
attr.mask = CM_ATTRMASK_LENGTH;
attr.unixModeBits = scp->unixModeBits | 0222;
}
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
lock_ReleaseMutex(&fidp->mx);
/* call setattr */
}
else if (infoLevel == SMB_INFO_QUERY_ALL_EAS) {
/* we don't support EAs */
- code = CM_ERROR_INVAL;
+ code = CM_ERROR_EAS_NOT_SUPPORTED;
}
done:
cm_scache_t *scp;
smb_tran2QFileInfo_t qfi;
long code = 0;
+ int readlock = 0;
cm_req_t req;
cm_InitReq(&req);
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];
if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
responseSize = sizeof(qfi.u.QFbasicInfo);
osi_Log2(smb_logp,"smb_ReleaseTran2QFileInfo fidp 0x%p scp 0x%p", fidp, scp);
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code)
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ConvertWToR(&scp->rw);
+ readlock = 1;
+
/* now we have the status in the cache entry, and everything is locked.
* Marshall the output data.
*/
unsigned long len;
char *name;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
lock_ObtainMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
if (fidp->NTopen_wholepathp)
name = fidp->NTopen_wholepathp;
else
/* send and free the packets */
done:
- lock_ReleaseMutex(&scp->mx);
+ if (readlock)
+ lock_ReleaseRead(&scp->rw);
+ else
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
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) {
/* lock the vnode with a callback; we need the current status
* to determine what the new status is, in some cases.
*/
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS
| CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
goto done;
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
/* prepare for setattr call */
attr.mask = 0;
attr.unixModeBits = scp->unixModeBits | 0222;
}
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
lock_ReleaseMutex(&fidp->mx);
/* call setattr */
long code = 0;
int maxReferralLevel = 0;
char requestFileName[1024] = "";
+ char referralPath[1024] = "";
smb_tran2Packet_t *outp = 0;
cm_user_t *userp = 0;
+ cm_scache_t *scp = 0;
+ cm_scache_t *dscp = 0;
cm_req_t req;
CPINFO CodePageInfo;
- int i, nbnLen, reqLen;
+ int i, nbnLen, reqLen, refLen;
int idx;
cm_InitReq(&req);
osi_Log2(smb_logp,"ReceiveTran2GetDfsReferral [%d][%s]",
maxReferralLevel, osi_LogSaveString(smb_logp, requestFileName));
- nbnLen = strlen(cm_NetbiosName);
- reqLen = strlen(requestFileName);
+ nbnLen = (int)strlen(cm_NetbiosName);
+ reqLen = (int)strlen(requestFileName);
- if (reqLen == nbnLen + 5 &&
- requestFileName[0] == '\\' &&
+ if (reqLen > nbnLen + 2 && requestFileName[0] == '\\' &&
!_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
- requestFileName[nbnLen+1] == '\\' &&
- (!_strnicmp("all",&requestFileName[nbnLen+2],3) ||
- !_strnicmp("*.",&requestFileName[nbnLen+2],2)))
+ requestFileName[nbnLen+1] == '\\')
{
- USHORT * sp;
- struct smb_v2_referral * v2ref;
- outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (reqLen + 8));
-
- sp = (USHORT *)outp->datap;
- idx = 0;
- sp[idx++] = reqLen; /* path consumed */
- sp[idx++] = 1; /* number of referrals */
- sp[idx++] = 0x03; /* flags */
+ int found = 0;
+
+ if (!_strnicmp("all",&requestFileName[nbnLen+2],3) ||
+ !_strnicmp("*.",&requestFileName[nbnLen+2],2))
+ {
+ found = 1;
+ strcpy(referralPath, requestFileName);
+ refLen = reqLen;
+ } else {
+ userp = smb_GetTran2User(vcp, p);
+ if (!userp) {
+ osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
+
+ /*
+ * 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
+ */
+ 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) {
+ /* Yes it is. */
+ found = 1;
+ strcpy(referralPath, requestFileName);
+ refLen = reqLen;
+ } else if (code == CM_ERROR_PATH_NOT_COVERED ) {
+ char temp[1024];
+ char pathName[1024];
+ char *lastComponent;
+ /*
+ * we have a msdfs link somewhere in the path
+ * we should figure out where in the path the link is.
+ * and return it.
+ */
+ osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral PATH_NOT_COVERED [%s]", requestFileName);
+
+ strcpy(temp, &requestFileName[nbnLen+2]);
+
+ do {
+ if (dscp) {
+ cm_ReleaseSCache(dscp);
+ dscp = 0;
+ }
+ if (scp) {
+ cm_ReleaseSCache(scp);
+ scp = 0;
+ }
+ smb_StripLastComponent(pathName, &lastComponent, temp);
+
+ code = cm_NameI(cm_data.rootSCachep, pathName,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, NULL, &req, &dscp);
+ if (code == 0) {
+ code = cm_NameI(dscp, ++lastComponent,
+ CM_FLAG_CASEFOLD,
+ userp, NULL, &req, &scp);
+ if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK)
+ break;
+ }
+ } while (code == CM_ERROR_PATH_NOT_COVERED);
+
+ /* scp should now be the DfsLink we are looking for */
+ if (scp) {
+ /* figure out how much of the input path was used */
+ reqLen = (int)(nbnLen+2 + strlen(pathName) + 1 + strlen(lastComponent));
+
+ strcpy(referralPath, &scp->mountPointStringp[strlen("msdfs:")]);
+ refLen = (int)strlen(referralPath);
+ found = 1;
+ }
+ } else {
+ char shareName[MAX_PATH + 1];
+ char *p, *q;
+ /* we may have a sharename that is a volume reference */
+
+ for (p = &requestFileName[nbnLen+2], q = shareName; *p && *p != '\\'; p++, q++)
+ {
+ *q = *p;
+ }
+ *q = '\0';
+
+ if (smb_FindShare(vcp, vcp->usersp, shareName, &p)) {
+ code = cm_NameI(cm_data.rootSCachep, "",
+ CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+ userp, p, &req, &scp);
+ free(p);
+
+ if (code == 0) {
+ found = 1;
+ strcpy(referralPath, requestFileName);
+ refLen = reqLen;
+ }
+ }
+ }
+ }
+
+ if (found)
+ {
+ USHORT * sp;
+ struct smb_v2_referral * v2ref;
+ outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 2 * (refLen + 8));
+
+ sp = (USHORT *)outp->datap;
+ idx = 0;
+ sp[idx++] = reqLen; /* path consumed */
+ sp[idx++] = 1; /* number of referrals */
+ sp[idx++] = 0x03; /* flags */
#ifdef DFS_VERSION_1
- sp[idx++] = 1; /* Version Number */
- sp[idx++] = reqLen + 4; /* Referral Size */
- sp[idx++] = 1; /* Type = SMB Server */
- sp[idx++] = 0; /* Do not strip path consumed */
- for ( i=0;i<=reqLen; i++ )
- sp[i+idx] = requestFileName[i];
+ sp[idx++] = 1; /* Version Number */
+ sp[idx++] = refLen + 4; /* Referral Size */
+ sp[idx++] = 1; /* Type = SMB Server */
+ sp[idx++] = 0; /* Do not strip path consumed */
+ for ( i=0;i<=refLen; i++ )
+ sp[i+idx] = referralPath[i];
#else /* DFS_VERSION_2 */
- sp[idx++] = 2; /* Version Number */
- sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */
- idx += (sizeof(struct smb_v2_referral) / 2);
- v2ref = (struct smb_v2_referral *) &sp[5];
- v2ref->ServerType = 1; /* SMB Server */
- v2ref->ReferralFlags = 0x03;
- v2ref->Proximity = 0; /* closest */
- v2ref->TimeToLive = 3600; /* seconds */
- v2ref->DfsPathOffset = idx * 2;
- v2ref->DfsAlternativePathOffset = idx * 2;
- v2ref->NetworkAddressOffset = 0;
- for ( i=0;i<=reqLen; i++ )
- sp[i+idx] = requestFileName[i];
+ sp[idx++] = 2; /* Version Number */
+ sp[idx++] = sizeof(struct smb_v2_referral); /* Referral Size */
+ idx += (sizeof(struct smb_v2_referral) / 2);
+ v2ref = (struct smb_v2_referral *) &sp[5];
+ v2ref->ServerType = 1; /* SMB Server */
+ v2ref->ReferralFlags = 0x03;
+ v2ref->Proximity = 0; /* closest */
+ v2ref->TimeToLive = 3600; /* seconds */
+ v2ref->DfsPathOffset = idx * 2;
+ v2ref->DfsAlternativePathOffset = idx * 2;
+ v2ref->NetworkAddressOffset = 0;
+ for ( i=0;i<=refLen; i++ )
+ sp[i+idx] = referralPath[i];
#endif
+ }
} else {
- userp = smb_GetTran2User(vcp, p);
- if (!userp) {
- osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
- code = CM_ERROR_BADSMB;
- goto done;
- }
-
- /* not done yet */
code = CM_ERROR_NOSUCHPATH;
}
-
+
done:
+ if (dscp)
+ cm_ReleaseSCache(dscp);
+ if (scp)
+ cm_ReleaseSCache(scp);
if (userp)
cm_ReleaseUser(userp);
if (code == 0)
return 0;
#else /* DFS_SUPPORT */
osi_Log0(smb_logp,"ReceiveTran2GetDfsReferral - NOT_SUPPORTED");
- return CM_ERROR_BADOP;
+ return CM_ERROR_NOSUCHDEVICE;
#endif /* DFS_SUPPORT */
}
return CM_ERROR_BADOP;
}
-long
-smb_ApplyV3DirListPatches(cm_scache_t *dscp,
- smb_dirListPatch_t **dirPatchespp, int infoLevel, cm_user_t *userp,
- cm_req_t *reqp)
+static long
+smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
+ char * tidPathp, char * relPathp,
+ int infoLevel, cm_user_t *userp,
+ cm_req_t *reqp)
{
long code = 0;
cm_scache_t *scp;
smb_dirListPatch_t *npatchp;
afs_uint32 rights;
afs_int32 mustFake = 0;
+ char path[AFSPATHMAX];
code = cm_FindACLCache(dscp, userp, &rights);
if (code == 0 && !(rights & PRSFS_READ))
mustFake = 1;
else if (code == -1) {
- lock_ObtainMutex(&dscp->mx);
+ lock_ObtainWrite(&dscp->rw);
code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseMutex(&dscp->mx);
+ lock_ReleaseWrite(&dscp->rw);
if (code == CM_ERROR_NOACCESS) {
mustFake = 1;
code = 0;
for(patchp = *dirPatchespp; patchp; patchp =
(smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", 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_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (mustFake == 0)
code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (mustFake || code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
dptr = patchp->dptr;
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
+ snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
+ reqp->relPathp = path;
+ reqp->tidPathp = tidPathp;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, reqp);
+ reqp->relPathp = reqp->tidPathp = NULL;
if (code == 0) {
/* we have a more accurate file to use (the
* target of the symbolic link). Otherwise,
cm_ReleaseSCache(scp);
scp = targetScp;
}
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
}
+ lock_ConvertWToR(&scp->rw);
+
dptr = patchp->dptr;
if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
/* 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 ||
+ code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
if (lattr == SMB_ATTR_NORMAL)
lattr = SMB_ATTR_DIRECTORY;
else
*dptr++ = (attr >> 8) & 0xff;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
cm_ReleaseSCache(scp);
}
return code;
}
-#ifndef USE_OLD_MATCHING
// char table for case insensitive comparison
char mapCaseTable[256];
return retval;
}
-#else /* USE_OLD_MATCHING */
-/* do a case-folding search of the star name mask with the name in namep.
- * Return 1 if we match, otherwise 0.
- */
-int smb_V3MatchMask(char *namep, char *maskp, int flags)
-{
- unsigned char tcp1, tcp2; /* Pattern characters */
- unsigned char tcn1; /* Name characters */
- int sawDot = 0, sawStar = 0, req8dot3 = 0;
- char *starNamep, *starMaskp;
- static char nullCharp[] = {0};
- int casefold = flags & CM_FLAG_CASEFOLD;
-
- /* make sure we only match 8.3 names, if requested */
- req8dot3 = (flags & CM_FLAG_8DOT3);
- if (req8dot3 && !cm_Is8Dot3(namep))
- return 0;
-
- /* loop */
- while (1) {
- /* Next pattern character */
- tcp1 = *maskp++;
-
- /* Next name character */
- tcn1 = *namep;
-
- if (tcp1 == 0) {
- /* 0 - end of pattern */
- if (tcn1 == 0)
- return 1;
- else
- return 0;
- }
- else if (tcp1 == '.' || tcp1 == '"') {
- if (sawDot) {
- if (tcn1 == '.') {
- namep++;
- continue;
- } else
- return 0;
- }
- else {
- /*
- * first dot in pattern;
- * must match dot or end of name
- */
- sawDot = 1;
- if (tcn1 == 0)
- continue;
- else if (tcn1 == '.') {
- sawStar = 0;
- namep++;
- continue;
- }
- else
- return 0;
- }
- }
- else if (tcp1 == '?') {
- if (tcn1 == 0 || tcn1 == '.')
- return 0;
- namep++;
- continue;
- }
- else if (tcp1 == '>') {
- if (tcn1 != 0 && tcn1 != '.')
- namep++;
- continue;
- }
- else if (tcp1 == '*' || tcp1 == '<') {
- tcp2 = *maskp++;
- if (tcp2 == 0)
- return 1;
- else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
- while (req8dot3 && tcn1 != '.' && tcn1 != 0)
- tcn1 = *++namep;
- if (tcn1 == 0) {
- if (sawDot)
- return 0;
- else
- continue;
- }
- else {
- namep++;
- continue;
- }
- }
- else {
- /*
- * pattern character after '*' is not null or
- * period. If it is '?' or '>', we are not
- * going to understand it. If it is '*' or
- * '<', we are going to skip over it. None of
- * these are likely, I hope.
- */
- /* skip over '*' and '<' */
- while (tcp2 == '*' || tcp2 == '<')
- tcp2 = *maskp++;
-
- /* skip over characters that don't match tcp2 */
- while (req8dot3 && tcn1 != '.' && tcn1 != 0 &&
- ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) ||
- (!casefold && tcn1 != tcp2)))
- tcn1 = *++namep;
-
- /* No match */
- if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
- return 0;
-
- /* Remember where we are */
- sawStar = 1;
- starMaskp = maskp;
- starNamep = namep;
-
- namep++;
- continue;
- }
- }
- else {
- /* tcp1 is not a wildcard */
- if ((casefold && cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) ||
- (!casefold && tcn1 == tcp1)) {
- /* they match */
- namep++;
- continue;
- }
- /* if trying to match a star pattern, go back */
- if (sawStar) {
- maskp = starMaskp - 2;
- namep = starNamep + 1;
- sawStar = 0;
- continue;
- }
- /* that's all */
- return 0;
- }
- }
-}
-#endif /* USE_OLD_MATCHING */
/* smb_ReceiveTran2SearchDir implements both
* Tran2_Find_First and Tran2_Find_Next
int attribute;
long nextCookie;
long code = 0, code2 = 0;
- char *pathp;
+ char *pathp = 0;
int maxCount;
smb_dirListPatch_t *dirListPatchesp;
smb_dirListPatch_t *curPatchp;
int searchFlags;
int eos;
smb_tran2Packet_t *outp; /* response packet */
- char *tidPathp;
+ char *tidPathp = 0;
int align;
char shortName[13]; /* 8.3 name if needed */
int NeedShortName;
char *shortNameEnd;
+ cm_dirEntry_t * dep = NULL;
cm_req_t req;
char * s;
cm_InitReq(&req);
eos = 0;
- osi_assert(p->opcode == 1);
+ osi_assertx(p->opcode == 1, "invalid opcode");
/* find first; obtain basic parameters from request */
#ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- if ( WANTS_DFS_PATHNAMES(p) )
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
code = CM_ERROR_BADSHARENAME;
ohbytes += 4; /* EASIZE */
/* add header to name & term. null */
- onbytes = strlen(maskp);
+ onbytes = (int)strlen(maskp);
orbytes = ohbytes + onbytes + 1;
/* now, we round up the record to a 4 byte alignment, and we make
curPatchp->flags = 0;
}
- curPatchp->fid.cell = targetscp->fid.cell;
- curPatchp->fid.volume = targetscp->fid.volume;
- curPatchp->fid.vnode = targetscp->fid.vnode;
- curPatchp->fid.unique = targetscp->fid.unique;
+ cm_SetFid(&curPatchp->fid, targetscp->fid.cell, targetscp->fid.volume, targetscp->fid.vnode, targetscp->fid.unique);
/* temp */
- curPatchp->dep = NULL;
+ dep = (cm_dirEntry_t *)malloc(sizeof(cm_dirEntry_t)+strlen(maskp));
+ strcpy(dep->name, maskp);
+ dep->fid.vnode = targetscp->fid.vnode;
+ dep->fid.unique = targetscp->fid.unique;
+ curPatchp->dep = dep;
}
if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) {
}
/* apply the patches */
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp, &req);
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, tidPathp, spacep->data, infoLevel, userp, &req);
outp->parmsp[0] = 0;
outp->parmsp[1] = 1; /* number of names returned */
skip_file:
smb_FreeTran2Packet(outp);
+ if (dep)
+ free(dep);
+ if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseSCache(targetscp);
cm_ReleaseUser(userp);
char *tp;
long code = 0, code2 = 0;
char *pathp;
- cm_dirEntry_t *dep;
+ cm_dirEntry_t *dep = 0;
int maxCount;
- smb_dirListPatch_t *dirListPatchesp;
- smb_dirListPatch_t *curPatchp;
+ smb_dirListPatch_t *dirListPatchesp = 0;
+ smb_dirListPatch_t *curPatchp = 0;
cm_buf_t *bufferp;
long temp;
long orbytes; /* # of bytes in this output record */
/* we only failover if we see a CM_ERROR_NOSUCHFILE */
if (code != CM_ERROR_NOSUCHFILE) {
#ifdef USE_BPLUS
+ /* unless we are using the BPlusTree */
if (code == CM_ERROR_BPLUS_NOMATCH)
code = CM_ERROR_NOSUCHFILE;
-#endif
+#endif /* USE_BPLUS */
return code;
}
}
strcpy(dsp->mask, maskp); /* and save mask */
}
else {
- osi_assert(p->opcode == 2);
+ osi_assertx(p->opcode == 2, "invalid opcode");
/* find next; obtain basic parameters from request or open dir file */
dsp = smb_FindDirSearch(p->parmsp[0]);
maxCount = p->parmsp[1];
smb_ReleaseDirSearch(dsp);
return 0;
}
+
+ strcpy(dsp->tidPath, tidPathp ? tidPathp : "/");
+ strcpy(dsp->relPath, spacep->data);
+
code = cm_NameI(cm_data.rootSCachep, spacep->data,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
if (code == 0) {
#ifdef DFS_SUPPORT_BUT_NOT_FIND_FIRST
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- if ( WANTS_DFS_PATHNAMES(p) )
+ if ( WANTS_DFS_PATHNAMES(p) || pnc )
code = CM_ERROR_PATH_NOT_COVERED;
else
code = CM_ERROR_BADSHARENAME;
* and so we do another hold now.
*/
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
+ 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_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
}
}
lock_ReleaseMutex(&dsp->mx);
}
/* get the directory size */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code) {
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_FreeTran2Packet(outp);
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
- lock_ObtainRead(&scp->bufCreateLock);
+ lock_ReleaseWrite(&scp->rw);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
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) {
- smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
- infoLevel, userp,
- &req);
- lock_ObtainMutex(&scp->mx);
+ 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 */
code = cm_TryBulkStat(scp, &thyper, userp, &req);
}
} else {
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
if (code) {
/* compute offset of cookie representing next entry */
nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
+ if (dep->fid.vnode == 0)
+ goto nextEntry; /* This entry is not in use */
+
/* Need 8.3 name? */
NeedShortName = 0;
- if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO
- && dep->fid.vnode != 0
- && !cm_Is8Dot3(dep->name)) {
+ if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO &&
+ !cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
NeedShortName = 1;
}
osi_Log4(smb_logp, "T2 search dir vn %u uniq %u name %s (%s)",
dep->fid.vnode, dep->fid.unique,
- osi_LogSaveString(smb_logp, dep->name),
+ osi_LogSaveString(smb_logp, dep->name),
NeedShortName ? osi_LogSaveString(smb_logp, shortName) : "");
/* When matching, we are using doing a case fold if we have a wildcard mask.
* If we get a non-wildcard match, it's a lookup for a specific file.
*/
- if (dep->fid.vnode != 0 &&
- (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
- (NeedShortName &&
- smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
-
+ if (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0)) ||
+ (NeedShortName && smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))
+ {
/* Eliminate entries that don't match requested attributes */
if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
smb_IsDotFile(dep->name)) {
osi_Log0(smb_logp, "T2 search dir skipping hidden");
goto nextEntry; /* no hidden files */
}
+
if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* no directories */
{
/* We have already done the cm_TryBulkStat above */
- fid.cell = scp->fid.cell;
- fid.volume = scp->fid.volume;
- fid.vnode = ntohl(dep->fid.vnode);
- fid.unique = ntohl(dep->fid.unique);
+ cm_SetFid(&fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
fileType = cm_FindFileType(&fid);
- /*osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
- "has filetype %d", dep->name,
- fileType);*/
- if (fileType == CM_SCACHETYPE_DIRECTORY ||
- fileType == CM_SCACHETYPE_MOUNTPOINT ||
- fileType == CM_SCACHETYPE_DFSLINK ||
- fileType == CM_SCACHETYPE_INVALID)
+ /* osi_Log2(smb_logp, "smb_ReceiveTran2SearchDir: file %s "
+ * "has filetype %d", dep->name, fileType);
+ */
+ if ( fileType == CM_SCACHETYPE_DIRECTORY ||
+ fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ fileType == CM_SCACHETYPE_DFSLINK ||
+ fileType == CM_SCACHETYPE_INVALID)
osi_Log0(smb_logp, "T2 search dir skipping directory or bad link");
- goto nextEntry;
+ goto nextEntry;
}
/* finally check if this name will fit */
ohbytes += 4; /* if resume key required */
}
- if (infoLevel != SMB_INFO_STANDARD
- && infoLevel != SMB_FIND_FILE_DIRECTORY_INFO
- && infoLevel != SMB_FIND_FILE_NAMES_INFO)
+ if ( infoLevel != SMB_INFO_STANDARD &&
+ infoLevel != SMB_FIND_FILE_DIRECTORY_INFO &&
+ infoLevel != SMB_FIND_FILE_NAMES_INFO)
ohbytes += 4; /* EASIZE */
/* add header to name & term. null */
/* now, we round up the record to a 4 byte alignment,
* and we make sure that we have enough room here for
* even the aligned version (so we don't have to worry
- * about an * overflow when we pad things out below).
+ * about an overflow when we pad things out below).
* That's the reason for the alignment arithmetic below.
*/
if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO)
if (orbytes + bytesInBuffer + align > maxReturnData) {
osi_Log1(smb_logp, "T2 dir search exceed max return data %d",
maxReturnData);
- break;
- }
+ break;
+ }
/* this is one of the entries to use: it is not deleted
* and it matches the star pattern we're looking for.
*/
if (infoLevel != SMB_FIND_FILE_NAMES_INFO) {
curPatchp = malloc(sizeof(*curPatchp));
- osi_QAdd((osi_queue_t **) &dirListPatchesp,
- &curPatchp->q);
+ osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
curPatchp->dptr = op;
if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO)
curPatchp->dptr += 8;
else
curPatchp->flags = 0;
- curPatchp->fid.cell = scp->fid.cell;
- curPatchp->fid.volume = scp->fid.volume;
- curPatchp->fid.vnode = ntohl(dep->fid.vnode);
- curPatchp->fid.unique = ntohl(dep->fid.unique);
+ cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
/* temp */
curPatchp->dep = dep;
}
} /* if we're including this name */
else if (!starPattern &&
- !foundInexact &&
- dep->fid.vnode != 0 &&
- smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
+ !foundInexact &&
+ smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
/* We were looking for exact matches, but here's an inexact one*/
foundInexact = 1;
}
-
+
nextEntry:
/* and adjust curOffset to be where the new cookie is */
thyper.HighPart = 0;
}
/* release the mutex */
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp) {
buf_Release(bufferp);
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.
*/
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, infoLevel, userp,
- &req);
-
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
+ dsp->relPath, infoLevel, userp, &req);
+
/* now put out the final parameters */
if (returnedNames == 0)
eos = 1;
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+ if (lastNamep &&
+ (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+ stricmp(lastNamep, "\\srvsvc") == 0 ||
+ stricmp(lastNamep, "\\wkssvc") == 0 ||
+ stricmp(lastNamep, "ipc$") == 0)) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
#ifdef DFS_SUPPORT
if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, pathp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
return CM_ERROR_NOSUCHFILE;
}
else {
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp, "smb_ReceiveV3OpenX creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
openAction = 2; /* created file */
/* now all we have to do is open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- osi_assert(fidp);
+ osi_assertx(fidp, "null smb_fid_t");
cm_HoldUser(userp);
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
osi_Log2(smb_logp,"smb_ReceiveV3OpenX fidp 0x%p scp 0x%p", fidp, scp);
/* also the user */
fidp->userp = userp;
/* copy out remainder of the parms */
parmSlot = 2;
smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
if (extraInfo) {
smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
smb_SetSMBDataLength(outp, 0);
osi_Log1(smb_logp, "SMB OpenX opening fid %d", fidp->fid);
cm_scache_t *scp;
unsigned char LockType;
unsigned short NumberOfUnlocks, NumberOfLocks;
- long Timeout;
+ afs_uint32 Timeout;
char *op;
char *op_locks;
LARGE_INTEGER LOffset, LLength;
if (!fidp)
return CM_ERROR_BADFD;
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ 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");
userp = smb_GetUserFromVCP(vcp, inp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_GETSTATUS
LockType |= LOCKING_ANDX_SHARED_LOCK;
}
- if ((LockType & LOCKING_ANDX_CANCEL_LOCK) ||
- (LockType & LOCKING_ANDX_CHANGE_LOCKTYPE)) {
-
- /* We don't support these requests. Apparently, we can safely
- not deal with them too. */
- osi_Log1(smb_logp, "smb_ReceiveV3Locking received unsupported request [%s]",
- ((LockType & LOCKING_ANDX_CANCEL_LOCK)?
- "LOCKING_ANDX_CANCEL_LOCK":
- "LOCKING_ANDX_CHANGE_LOCKTYPE"));
- /* No need to call osi_LogSaveString since these are string
- constants.*/
-
+ if (LockType & LOCKING_ANDX_CHANGE_LOCKTYPE) {
+ /* AFS does not support atomic changes of lock types from read or write and vice-versa */
+ osi_Log0(smb_logp, "smb_ReceiveV3Locking received unsupported request [LOCKING_ANDX_CHANGE_LOCKTYPE]");
code = CM_ERROR_BADOP;
goto done;
op = smb_GetSMBData(inp, NULL);
+ if (LockType & LOCKING_ANDX_CANCEL_LOCK) {
+ /* Cancel outstanding lock requests */
+ smb_waitingLock_t * wl;
+
+ for (i=0; i<NumberOfLocks; i++) {
+ smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
+
+ key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
+
+ lock_ObtainWrite(&smb_globalLock);
+ 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) &&
+ LargeIntegerEqualTo(wl->LLength, LLength)) {
+ wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
+ goto found_lock_request;
+ }
+ }
+ }
+ found_lock_request:
+ lock_ReleaseWrite(&smb_globalLock);
+ }
+ code = 0;
+ smb_SetSMBDataLength(outp, 0);
+ goto done;
+ }
+
+
for (i=0; i<NumberOfUnlocks; i++) {
smb_GetLockParams(LockType, &op, &pid, &LOffset, &LLength);
wlRequest = malloc(sizeof(smb_waitingLockRequest_t));
- osi_assert(wlRequest != NULL);
+ osi_assertx(wlRequest != NULL, "null wlRequest");
wlRequest->vcp = vcp;
smb_HoldVC(vcp);
wlRequest->inp = smb_CopyPacket(inp);
wlRequest->outp = smb_CopyPacket(outp);
wlRequest->lockType = LockType;
- wlRequest->timeRemaining = Timeout;
+ wlRequest->msTimeout = Timeout;
+ wlRequest->start_t = osi_Time();
wlRequest->locks = NULL;
/* The waiting lock request needs to have enough
wLock = malloc(sizeof(smb_waitingLock_t));
- osi_assert(wLock != NULL);
+ osi_assertx(wLock != NULL, "null smb_waitingLock_t");
wLock->key = tkey;
wLock->LOffset = tOffset;
wLock = malloc(sizeof(smb_waitingLock_t));
- osi_assert(wLock != NULL);
+ osi_assertx(wLock != NULL, "null smb_waitingLock_t");
wLock->key = key;
wLock->LOffset = LOffset;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
doneSync:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
afs_uint32 searchTime;
cm_user_t *userp;
cm_req_t req;
+ int readlock = 0;
cm_InitReq(&req);
if (!fidp)
return CM_ERROR_BADFD;
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ 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);
/* otherwise, stat the file */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code)
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ConvertWToR(&scp->rw);
+
/* 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.
code = 0;
done:
- lock_ReleaseMutex(&scp->mx);
+ if (readlock)
+ lock_ReleaseRead(&scp->rw);
+ else
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
smb_ReleaseFID(fidp);
if (!fidp)
return CM_ERROR_BADFD;
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ 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);
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
char *op;
if (!fidp)
return CM_ERROR_BADFD;
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ 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);
LARGE_INTEGER LLength;
cm_scache_t * scp;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = offset.HighPart;
LLength.LowPart = count;
scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_LockCheckWrite(scp, LOffset, LLength, key);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (code)
goto done;
written = 0;
}
- done_writing:
-
/* slots 0 and 1 are reserved for request chaining and will be
filled in when we return. */
smb_SetSMBParm(outp, 2, total_written);
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
cm_key_t key;
return CM_ERROR_BADFD;
}
- pid = ((smb_t *) inp)->pid;
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
{
LARGE_INTEGER LOffset, LLength;
LLength.LowPart = count;
scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_LockCheckRead(scp, LOffset, LLength, key);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
}
if (code) {
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_LogSaveString(smb_logp,(lastNamep?lastNamep:"null")));
- if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+ if (lastNamep &&
+ (stricmp(lastNamep, SMB_IOCTL_FILENAME) == 0 ||
+ stricmp(lastNamep, "\\srvsvc") == 0 ||
+ stricmp(lastNamep, "\\wkssvc") == 0 ||
+ stricmp(lastNamep, "ipc$") == 0)) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
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);
+ return CM_ERROR_NOSUCHPATH;
+ }
+
baseDirp = baseFidp->scp;
tidPathp = NULL;
}
fidflags = 0;
if (desiredAccess & DELETE)
fidflags |= SMB_FID_OPENDELETE;
- if (desiredAccess & AFS_ACCESS_READ)
+ if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
fidflags |= SMB_FID_OPENREAD_LISTDIR;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (smb_IsExecutableFileName(lastNamep))
+ fidflags |= SMB_FID_EXECUTABLE;
/* and the share mode */
if (shareAccess & FILE_SHARE_READ)
if (code == 0) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
userp, tidPathp, &req, &scp);
#ifdef DFS_SUPPORT
if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
#ifdef DFS_SUPPORT
if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseSCache(dscp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
targetScp = 0;
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
free(realPathp);
return CM_ERROR_NOSUCHFILE;
} else if (realDirFlag == 0 || realDirFlag == -1) {
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
openAction = 2; /* created file */
/* create directory */
if ( !treeCreate )
treeStartp = lastNamep;
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
osi_LogSaveString(smb_logp, treeStartp));
openAction = 2; /* created directory */
/* open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- osi_assert(fidp);
+ osi_assertx(fidp, "null smb_fid_t");
/* save a reference to the user */
cm_HoldUser(userp);
LLength.LowPart = SMB_FID_QLOCK_LENGTH;
/* If we are not opening the file for writing, then we don't
- try to get an exclusive lock. Noone else should be able to
+ try to get an exclusive lock. No one else should be able to
get an exclusive lock on the file anyway, although someone
else can get a shared lock. */
if ((fidflags & SMB_FID_SHARE_READ) ||
key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (code) {
if (ldp)
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp; /* Hold transfered to fidp->scp and no longer needed */
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
osi_Log2(smb_logp,"smb_ReceiveNTCreateX fidp 0x%p scp 0x%p", fidp, scp);
fidp->flags = fidflags;
/* out parms */
parmSlot = 2;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
(scp->fileType == CM_SCACHETYPE_DIRECTORY ||
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
- lock_ReleaseMutex(&scp->mx);
smb_SetSMBDataLength(outp, 0);
+ if ((fidp->flags & SMB_FID_EXECUTABLE) &&
+ LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+ cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
+ fidp->scp->length.LowPart, fidp->scp->length.HighPart,
+ userp);
+ }
+ lock_ReleaseRead(&scp->rw);
+
osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid,
osi_LogSaveString(smb_logp, realPathp));
osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
free(realPathp);
cm_ReleaseUser(userp);
- return CM_ERROR_INVAL;
+ return CM_ERROR_BADFD;
}
+
+ if (baseFidp->scp && (baseFidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ free(realPathp);
+ cm_ReleaseUser(userp);
+ smb_CloseFID(vcp, baseFidp, NULL, 0);
+ smb_ReleaseFID(baseFidp);
+ return CM_ERROR_NOSUCHPATH;
+ }
+
baseDirp = baseFidp->scp;
tidPathp = NULL;
}
fidflags = 0;
if (desiredAccess & DELETE)
fidflags |= SMB_FID_OPENDELETE;
- if (desiredAccess & AFS_ACCESS_READ)
+ if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
fidflags |= SMB_FID_OPENREAD_LISTDIR;
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (smb_IsExecutableFileName(lastNamep))
+ fidflags |= SMB_FID_EXECUTABLE;
/* And the share mode */
if (shareAccess & FILE_SHARE_READ)
if (code == 0) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
userp, tidPathp, &req, &scp);
#ifdef DFS_SUPPORT
if (code == 0 && scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, realPathp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
userp, tidPathp, &req, &dscp);
#ifdef DFS_SUPPORT
if (code == 0 && dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
if (baseFidp)
smb_ReleaseFID(baseFidp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
return CM_ERROR_NOSUCHFILE;
}
else if (realDirFlag == 0 || realDirFlag == -1) {
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp, "smb_ReceiveNTTranCreate creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
openAction = 2; /* created file */
}
} else {
/* create directory */
- osi_assert(dscp != NULL);
+ osi_assertx(dscp != NULL, "null cm_scache_t");
osi_Log1(smb_logp,
"smb_ReceiveNTTranCreate creating directory %s",
osi_LogSaveString(smb_logp, lastNamep));
/* open the file itself */
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
- osi_assert(fidp);
+ osi_assertx(fidp, "null smb_fid_t");
/* save a reference to the user */
cm_HoldUser(userp);
key = cm_GenerateKey(vcp->vcID, SMB_FID_QLOCK_PID, fidp->fid);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (code) {
if (ldp)
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
fidp->scp = scp;
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
scp->flags |= CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
osi_Log2(smb_logp,"smb_ReceiveNTTranCreate fidp 0x%p scp 0x%p", fidp, scp);
fidp->flags = fidflags;
smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
smb_SetSMBDataLength(outp, 70);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
outData = smb_GetSMBData(outp, NULL);
outData++; /* round to get to parmOffset */
*outData = 0; outData++; /* oplock */
scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
outData += 2; /* is a dir? */
- lock_ReleaseMutex(&scp->mx);
} else {
/* out parms */
parmOffset = 8*4 + 39;
smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
smb_SetSMBDataLength(outp, 105);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
outData = smb_GetSMBData(outp, NULL);
outData++; /* round to get to parmOffset */
*outData = 0; outData++; /* oplock */
memset(outData,0,24); outData += 24; /* Volume ID and file ID */
*((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
*((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
- lock_ReleaseMutex(&scp->mx);
}
+ if ((fidp->flags & SMB_FID_EXECUTABLE) &&
+ LargeIntegerGreaterThanZero(fidp->scp->length) &&
+ !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+ cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
+ fidp->scp->length.LowPart, fidp->scp->length.HighPart,
+ userp);
+ }
+ lock_ReleaseRead(&scp->rw);
+
osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
cm_ReleaseUser(userp);
return CM_ERROR_BADFD;
}
+ if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+ smb_CloseFID(vcp, fidp, NULL, 0);
+ smb_ReleaseFID(fidp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
/* Create a copy of the Directory Watch Packet to use when sending the
* notification if in the future a matching change is detected.
*/
if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE)
osi_Log0(smb_logp, " Notify Change Stream Write");
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (watchtree)
scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
else
scp->flags |= CM_SCACHEFLAG_WATCHED;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
smb_ReleaseFID(fidp);
outp->flags |= SMB_PACKETFLAG_NOSEND;
break;
case 6:
return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp);
+ case 7:
+ osi_Log0(smb_logp, "SMB NT Transact Query Quota - not implemented");
+ break;
+ case 8:
+ osi_Log0(smb_logp, "SMB NT Transact Set Quota - not implemented");
+ break;
}
return CM_ERROR_INVAL;
}
lastWatch = watch;
watch = watch->nextp;
continue;
- }
- if (fidp->scp != dscp
- || (filter & notifyFilter) == 0
- || (!isDirectParent && !wtree)) {
+ }
+
+ if (fidp->scp != dscp ||
+ fidp->scp->flags & CM_SCACHEFLAG_DELETED ||
+ (filter & notifyFilter) == 0 ||
+ (!isDirectParent && !wtree))
+ {
osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
smb_ReleaseFID(fidp);
lastWatch = watch;
lastWatch->nextp = nextWatch;
/* Turn off WATCHED flag in dscp */
- lock_ObtainMutex(&dscp->mx);
+ lock_ObtainWrite(&dscp->rw);
if (wtree)
dscp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
else
dscp->flags &= ~CM_SCACHEFLAG_WATCHED;
- lock_ReleaseMutex(&dscp->mx);
+ lock_ReleaseWrite(&dscp->rw);
/* Convert to response packet */
- ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
+ ((smb_t *) watch)->reb = SMB_FLAGS_SERVER_TO_CLIENT;
+#ifdef SEND_CANONICAL_PATHNAMES
+ ((smb_t *) watch)->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
+#endif
((smb_t *) watch)->wct = 0;
/* out parms */
scp = fidp->scp;
osi_Log2(smb_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (watchtree)
scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
else
scp->flags &= ~CM_SCACHEFLAG_WATCHED;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
smb_ReleaseFID(fidp);
} else {
osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);