#include "smb.h"
#include "lanahelper.h"
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
+
/* These characters are illegal in Windows filenames */
-static char *illegalChars = "\\/:*?\"<>|";
+static clientchar_t *illegalChars = _C("\\/:*?\"<>|");
static int smbShutdownFlag = 0;
static int smb_ListenerState = SMB_LISTENER_UNINITIALIZED;
osi_rwlock_t smb_globalLock;
osi_rwlock_t smb_rctLock;
osi_mutex_t smb_ListenerLock;
-
-char smb_LANadapter;
+osi_mutex_t smb_StartedLock;
+
+unsigned char smb_LANadapter = LANA_INVALID;
unsigned char smb_sharename[NCBNAMSZ+1] = {0};
+int smb_LanAdapterChangeDetected = 0;
+afs_uint32 smb_AsyncStore = 1;
+afs_uint32 smb_AsyncStoreSize = CM_CONFIGDEFAULT_ASYNCSTORESIZE;
BOOL isGateway = FALSE;
smb_packet_t *smb_packetFreeListp;
smb_ncb_t *smb_ncbFreeListp;
-int smb_NumServerThreads;
+afs_uint32 smb_NumServerThreads;
-int numNCBs, numSessions, numVCs;
+afs_uint32 numNCBs, numSessions, numVCs;
int smb_maxVCPerServer;
int smb_maxMpxRequests;
EVENT_HANDLE **NCBreturns;
EVENT_HANDLE **NCBShutdown;
EVENT_HANDLE *smb_ServerShutdown;
+EVENT_HANDLE ListenerShutdown[256];
DWORD NCBsessions[NCB_MAX];
NCB *NCBs[NCB_MAX];
struct smb_packet *bufs[NCB_MAX];
int lanas[SESSION_MAX];
BOOL dead_sessions[SESSION_MAX];
LANA_ENUM lana_list;
-
/* for raw I/O */
osi_mutex_t smb_RawBufLock;
char *smb_RawBufs;
/* for raw write */
typedef struct raw_write_cont {
- long code;
- osi_hyper_t offset;
- long count;
- char *buf;
- int writeMode;
- long alreadyWritten;
+ long code;
+ osi_hyper_t offset;
+ long count;
+ char *buf;
+ int writeMode;
+ long alreadyWritten;
} raw_write_cont_t;
/* dir search stuff */
/* hide dot files? */
int smb_hideDotFiles;
+/* Negotiate Unicode support? */
+LONG smb_UseUnicode;
+
/* global state about V3 protocols */
int smb_useV3; /* try to negotiate V3 */
-static showErrors = 0;
+static int showErrors = 0;
/* MessageBox or something like it */
-int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT)
+= NULL;
/* GMT time info:
* Time in Unix format of midnight, 1/1/1970 local time.
/* forward decl */
void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
NCB *ncbp, raw_write_cont_t *rwcp);
-int smb_NetbiosInit(void);
+int smb_NetbiosInit(int);
#ifdef LOG_PACKET
void smb_LogPacket(smb_packet_t *packet);
#endif /* LOG_PACKET */
-
-char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
+
+clientchar_t smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = _C(""); /* domain name */
int smb_ServerDomainNameLength = 0;
-char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
-int smb_ServerOSLength = sizeof(smb_ServerOS);
-char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
-int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
+clientchar_t smb_ServerOS[] = _C("Windows 5.0"); /* Faux OS String */
+int smb_ServerOSLength = lengthof(smb_ServerOS);
+clientchar_t smb_ServerLanManager[] = _C("Windows 2000 LAN Manager"); /* Faux LAN Manager string */
+int smb_ServerLanManagerLength = lengthof(smb_ServerLanManager);
/* Faux server GUID. This is never checked. */
GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+void smb_InitReq(cm_req_t *reqp)
+{
+ cm_InitReq(reqp);
+ reqp->flags |= CM_REQ_SOURCE_SMB;
+}
+
void smb_ResetServerPriority()
{
void * p = TlsGetValue(smb_TlsRequestSlot);
time_t now = osi_Time();
/* Give one priority boost for each 15 seconds */
- SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
+ SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
}
}
{
const char * s;
switch ( code ) {
- case 0x01: s = "llegal buffer length"; break;
- case 0x03: s = "illegal command"; break;
- case 0x05: s = "command timed out"; break;
- case 0x06: s = "message incomplete, issue another command"; break;
- case 0x07: s = "illegal buffer address"; break;
- case 0x08: s = "session number out of range"; break;
- case 0x09: s = "no resource available"; break;
- case 0x0a: s = "session closed"; break;
- case 0x0b: s = "command cancelled"; break;
- case 0x0d: s = "duplicate name"; break;
- case 0x0e: s = "name table full"; break;
- case 0x0f: s = "no deletions, name has active sessions"; break;
- case 0x11: s = "local session table full"; break;
- case 0x12: s = "remote session table full"; break;
- case 0x13: s = "illegal name number"; break;
- case 0x14: s = "no callname"; break;
- case 0x15: s = "cannot put * in NCB_NAME"; break;
- case 0x16: s = "name in use on remote adapter"; break;
- case 0x17: s = "name deleted"; break;
- case 0x18: s = "session ended abnormally"; break;
- case 0x19: s = "name conflict detected"; break;
- case 0x21: s = "interface busy, IRET before retrying"; break;
- case 0x22: s = "too many commands outstanding, retry later";break;
- case 0x23: s = "ncb_lana_num field invalid"; break;
- case 0x24: s = "command completed while cancel occurring "; break;
- case 0x26: s = "command not valid to cancel"; break;
- case 0x30: s = "name defined by anther local process"; break;
- case 0x34: s = "environment undefined. RESET required"; break;
- case 0x35: s = "required OS resources exhausted"; break;
- case 0x36: s = "max number of applications exceeded"; break;
- case 0x37: s = "no saps available for netbios"; break;
- case 0x38: s = "requested resources are not available"; break;
- case 0x39: s = "invalid ncb address or length > segment"; break;
- case 0x3B: s = "invalid NCB DDID"; break;
- case 0x3C: s = "lock of user area failed"; break;
- case 0x3f: s = "NETBIOS not loaded"; break;
- case 0x40: s = "system error"; break;
+ case 0x01: s = "NRC_BUFLEN llegal buffer length"; break;
+ case 0x03: s = "NRC_ILLCMD illegal command"; break;
+ case 0x05: s = "NRC_CMDTMO command timed out"; break;
+ case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break;
+ case 0x07: s = "NRC_BADDR illegal buffer address"; break;
+ case 0x08: s = "NRC_SNUMOUT session number out of range"; break;
+ case 0x09: s = "NRC_NORES no resource available"; break;
+ case 0x0a: s = "NRC_SCLOSED asession closed"; break;
+ case 0x0b: s = "NRC_CMDCAN command cancelled"; break;
+ case 0x0d: s = "NRC_DUPNAME duplicate name"; break;
+ case 0x0e: s = "NRC_NAMTFUL name table full"; break;
+ case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break;
+ case 0x11: s = "NRC_LOCTFUL local session table full"; break;
+ case 0x12: s = "NRC_REMTFUL remote session table full"; break;
+ case 0x13: s = "NRC_ILLNN illegal name number"; break;
+ case 0x14: s = "NRC_NOCALL no callname"; break;
+ case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME"; break;
+ case 0x16: s = "NRC_INUSE name in use on remote adapter"; break;
+ case 0x17: s = "NRC_NAMERR name deleted"; break;
+ case 0x18: s = "NRC_SABORT session ended abnormally"; break;
+ case 0x19: s = "NRC_NAMCONF name conflict detected"; break;
+ case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying"; break;
+ case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
+ case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid"; break;
+ case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break;
+ case 0x26: s = "NRC_CANCEL command not valid to cancel"; break;
+ case 0x30: s = "NRC_DUPENV name defined by anther local process"; break;
+ case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required"; break;
+ case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted"; break;
+ case 0x36: s = "NRC_MAXAPPS max number of applications exceeded"; break;
+ case 0x37: s = "NRC_NOSAPS no saps available for netbios"; break;
+ case 0x38: s = "NRC_NORESOURCES requested resources are not available"; break;
+ case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment"; break;
+ case 0x3B: s = "NRC_INVDDID invalid NCB DDID"; break;
+ case 0x3C: s = "NRC_LOCKFAILlock of user area failed"; break;
+ case 0x3f: s = "NRC_OPENERR NETBIOS not loaded"; break;
+ case 0x40: s = "NRC_SYSTEM system error"; break;
default: s = "unknown error";
}
return s;
/* Check if the named file/dir is a dotfile/dotdir */
/* String pointed to by lastComp can have leading slashes, but otherwise should have
no other patch components */
-unsigned int smb_IsDotFile(char *lastComp) {
- char *s;
+unsigned int smb_IsDotFile(clientchar_t *lastComp) {
+ clientchar_t *s;
+
if(lastComp) {
/* skip over slashes */
for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
return 0;
/* nulls, curdir and parent dir doesn't count */
- if (!*s)
+ if (!*s)
return 0;
- if (*s == '.') {
+ if (*s == _C('.')) {
if (!*(s + 1))
return 0;
- if(*(s+1) == '.' && !*(s + 2))
+ if(*(s+1) == _C('.') && !*(s + 2))
return 0;
return 1;
}
*unixTimep = dosTime + smb_localZero;
}
+#ifdef DEBUG_SMB_REFCOUNT
+smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line)
+#else
smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
+#endif
{
smb_vc_t *vcp;
- lock_ObtainWrite(&smb_globalLock); /* for numVCs */
+ lock_ObtainWrite(&smb_globalLock); /* for numVCs */
lock_ObtainWrite(&smb_rctLock);
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
if (vcp->magic != SMB_VC_MAGIC)
vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
vcp->nextp = smb_allVCsp;
smb_allVCsp = vcp;
- lock_InitializeMutex(&vcp->mx, "vc_t mutex");
+ lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
vcp->lsn = lsn;
vcp->lana = lana;
vcp->secCtx = NULL;
*/
NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
- PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
+ PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp = NULL;
ULONG lsaRespSize = 0;
lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
&lsaResp,
&lsaRespSize,
&ntsEx);
- if (nts != STATUS_SUCCESS)
+ if (nts != STATUS_SUCCESS || ntsEx != STATUS_SUCCESS) {
osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
nts, ntsEx, sizeof(lsaReq), lsaRespSize);
+ afsi_log("MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize %u",
+ nts, ntsEx, lsaRespSize);
+ }
osi_assertx(nts == STATUS_SUCCESS, "LsaCallAuthenticationPackage failed"); /* this had better work! */
- memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
- LsaFreeReturnBuffer(lsaResp);
+ if (ntsEx == STATUS_SUCCESS) {
+ memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
+ } else {
+ /*
+ * This will cause the subsequent authentication to fail but
+ * that is better than us dereferencing a NULL pointer and
+ * crashing.
+ */
+ memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
+ }
+ if (lsaResp)
+ LsaFreeReturnBuffer(lsaResp);
}
else
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
}
}
+#ifdef DEBUG_SMB_REFCOUNT
+ if (vcp) {
+ afsi_log("%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+ }
+#endif
lock_ReleaseWrite(&smb_rctLock);
- lock_ReleaseWrite(&smb_globalLock);
+ lock_ReleaseWrite(&smb_globalLock);
return vcp;
}
-int smb_IsStarMask(char *maskp)
+int smb_IsStarMask(clientchar_t *maskp)
{
int i;
- char tc;
+ clientchar_t tc;
for(i=0; i<11; i++) {
tc = *maskp++;
- if (tc == '?' || tc == '*' || tc == '>')
+ if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
return 1;
- }
+ }
return 0;
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
+#define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
+#else
void smb_ReleaseVCInternal(smb_vc_t *vcp)
+#endif
{
smb_vc_t **vcpp;
smb_vc_t * avcp;
+ lock_AssertWrite(&smb_rctLock);
vcp->refCount--;
if (vcp->refCount == 0) {
- if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
- /* remove VCP from smb_deadVCsp */
- for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
- if (*vcpp == vcp) {
- *vcpp = vcp->nextp;
- break;
- }
- }
- lock_FinalizeMutex(&vcp->mx);
- memset(vcp,0,sizeof(smb_vc_t));
- free(vcp);
- } else {
- for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
- if (avcp == vcp)
- break;
- }
- osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
- avcp?"not ":"",vcp, vcp->refCount);
-#ifdef DEBUG
- GenerateMiniDump(NULL);
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+#endif
+ /* remove VCP from smb_deadVCsp */
+ for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+ if (*vcpp == vcp) {
+ *vcpp = vcp->nextp;
+ break;
+ }
+ }
+ lock_FinalizeMutex(&vcp->mx);
+ memset(vcp,0,sizeof(smb_vc_t));
+ free(vcp);
+ } else {
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is alive ref %d", file, line, vcp, vcp->refCount);
+#endif
+ for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
+ if (avcp == vcp)
+ break;
+ }
+ osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
+ avcp?"":"not ",vcp, vcp->refCount);
+
+ /* This is a wrong. However, I suspect that there is an undercount
+ * and I don't want to release 1.4.1 in a state that will allow
+ * smb_vc_t objects to be deallocated while still in the
+ * smb_allVCsp list. The list is supposed to keep a reference
+ * to the smb_vc_t. Put it back.
+ */
+ if (avcp) {
+ vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+#endif
+ }
+ }
+ } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ /* The reference count is non-zero but the VC is dead.
+ * This implies that some FIDs, TIDs, etc on the VC have yet to
+ * be cleaned up. If we were not called by smb_CleanupDeadVC(),
+ * add a reference that will be dropped by
+ * smb_CleanupDeadVC() and try to cleanup the VC again.
+ * Eventually the refCount will drop to zero when all of the
+ * active threads working with the VC end their task.
+ */
+ if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) {
+ vcp->refCount++; /* put the refCount back */
+ lock_ReleaseWrite(&smb_rctLock);
+ smb_CleanupDeadVC(vcp);
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+#endif
+ lock_ObtainWrite(&smb_rctLock);
+ }
+ } else {
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
#endif
- /* This is a wrong. However, I suspect that there is an undercount
- * and I don't want to release 1.4.1 in a state that will allow
- * smb_vc_t objects to be deallocated while still in the
- * smb_allVCsp list. The list is supposed to keep a reference
- * to the smb_vc_t. Put it back.
- */
- vcp->refCount++;
- }
}
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+#endif
{
+ lock_AssertWrite(&smb_rctLock);
osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
smb_ReleaseVCInternal(vcp);
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
void smb_ReleaseVC(smb_vc_t *vcp)
+#endif
{
lock_ObtainWrite(&smb_rctLock);
osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
lock_ReleaseWrite(&smb_rctLock);
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
void smb_HoldVCNoLock(smb_vc_t *vcp)
+#endif
{
+ lock_AssertWrite(&smb_rctLock);
vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+#endif
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
void smb_HoldVC(smb_vc_t *vcp)
+#endif
{
lock_ObtainWrite(&smb_rctLock);
vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_HoldVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
+#endif
lock_ReleaseWrite(&smb_rctLock);
}
smb_user_t *uidpIter;
smb_user_t *uidpNext;
smb_vc_t **vcpp;
-
+ afs_uint32 refCount = 0;
lock_ObtainMutex(&vcp->mx);
if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
- if (fidpIter->delete)
+ if (fidpIter->deleteOk)
continue;
fid = fidpIter->fid;
for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
tidpNext = tidpIter->nextp;
- if (tidpIter->delete)
+ if (tidpIter->deleteOk)
continue;
- tidpIter->delete = 1;
+ tidpIter->deleteOk = 1;
tid = tidpIter->tid;
osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
smb_HoldTIDNoLock(tidpIter);
- lock_ReleaseWrite(&smb_rctLock);
-
- smb_ReleaseTID(tidpIter);
-
- lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseTID(tidpIter, TRUE);
tidpNext = vcp->tidsp;
}
for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
uidpNext = uidpIter->nextp;
- if (uidpIter->delete)
+ if (uidpIter->deleteOk)
continue;
- uidpIter->delete = 1;
+ uidpIter->deleteOk = 1;
/* do not add an additional reference count for the smb_user_t
* as the smb_vc_t already is holding a reference */
}
/* The vcp is now on the deadVCsp list. We intentionally drop the
- * reference so that the refcount can reach 0 and we can delete it */
+ * reference so that the refcount can reach 0 and we can delete it
+ *
+ * If the refCount == 1 going into the ReleaseVCNoLock call
+ * the object will be freed and it won't be safe to clear
+ * the flag.
+ */
+ refCount = vcp->refCount;
smb_ReleaseVCNoLock(vcp);
-
+ if (refCount > 1) {
+ lock_ObtainMutex(&vcp->mx);
+ vcp->flags &= ~SMB_VCFLAG_CLEAN_IN_PROGRESS;
+ lock_ReleaseMutex(&vcp->mx);
+ }
+
lock_ReleaseWrite(&smb_rctLock);
osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
}
+#ifdef DEBUG_SMB_REFCOUNT
+smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char * file, long line)
+#else
smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
+#endif
{
smb_tid_t *tidp;
lock_ObtainWrite(&smb_rctLock);
retry:
for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
- if (tidp->refCount == 0 && tidp->delete) {
+ if (tidp->refCount == 0 && tidp->deleteOk) {
tidp->refCount++;
- lock_ReleaseWrite(&smb_rctLock);
- smb_ReleaseTID(tidp);
- lock_ObtainWrite(&smb_rctLock);
+ smb_ReleaseTID(tidp, TRUE);
goto retry;
}
if (tid == tidp->tid) {
tidp->refCount++;
break;
- }
+ }
}
if (!tidp && (flags & SMB_FLAG_CREATE)) {
tidp = malloc(sizeof(*tidp));
tidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
vcp->tidsp = tidp;
- lock_InitializeMutex(&tidp->mx, "tid_t mutex");
+ lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
tidp->tid = tid;
}
+#ifdef DEBUG_SMB_REFCOUNT
+ if (tidp) {
+ afsi_log("%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+ }
+#endif
lock_ReleaseWrite(&smb_rctLock);
return tidp;
-}
+}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldTIDNoLockDbg(smb_tid_t *tidp, char * file, long line)
+#else
void smb_HoldTIDNoLock(smb_tid_t *tidp)
+#endif
{
+ lock_AssertWrite(&smb_rctLock);
tidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+#endif
}
-void smb_ReleaseTID(smb_tid_t *tidp)
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseTIDDbg(smb_tid_t *tidp, afs_uint32 locked, char *file, long line)
+#else
+void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
+#endif
{
smb_tid_t *tp;
smb_tid_t **ltpp;
- cm_user_t *userp;
+ cm_user_t *userp = NULL;
+ smb_vc_t *vcp = NULL;
+
+ if (!locked)
+ lock_ObtainWrite(&smb_rctLock);
+ else
+ lock_AssertWrite(&smb_rctLock);
- userp = NULL;
- lock_ObtainWrite(&smb_rctLock);
osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
- if (tidp->refCount == 0 && (tidp->delete)) {
- ltpp = &tidp->vcp->tidsp;
- for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
- if (tp == tidp)
- break;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+ osi_Log5(smb_logp,"%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+#endif
+ if (tidp->refCount == 0) {
+ if (tidp->deleteOk) {
+ ltpp = &tidp->vcp->tidsp;
+ for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
+ if (tp == tidp)
+ break;
+ }
+ osi_assertx(tp != NULL, "null smb_tid_t");
+ *ltpp = tp->nextp;
+ lock_FinalizeMutex(&tidp->mx);
+ userp = tidp->userp; /* remember to drop ref later */
+ tidp->userp = NULL;
+ vcp = tidp->vcp;
+ tidp->vcp = NULL;
+ free(tidp);
}
- osi_assertx(tp != NULL, "null smb_tid_t");
- *ltpp = tp->nextp;
- lock_FinalizeMutex(&tidp->mx);
- userp = tidp->userp; /* remember to drop ref later */
- tidp->userp = NULL;
- smb_ReleaseVCNoLock(tidp->vcp);
- tidp->vcp = NULL;
}
- lock_ReleaseWrite(&smb_rctLock);
+ if (!locked)
+ lock_ReleaseWrite(&smb_rctLock);
if (userp)
cm_ReleaseUser(userp);
+ if (vcp)
+ smb_ReleaseVCNoLock(vcp);
}
smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
if (uid == uidp->userID) {
uidp->refCount++;
- osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
+ osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%S]",
vcp, uidp->userID,
- osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
+ ((uidp->unp)? osi_LogSaveClientString(smb_logp, uidp->unp->name):_C("")));
break;
}
}
uidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
vcp->usersp = uidp;
- lock_InitializeMutex(&uidp->mx, "user_t mutex");
+ lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
uidp->userID = uid;
- osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
- vcp, uidp->userID,
- osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
+ osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
+ vcp, uidp->userID,
+ ((uidp->unp)?osi_LogSaveClientString(smb_logp,uidp->unp->name):_C("")));
}
lock_ReleaseWrite(&smb_rctLock);
return uidp;
}
-smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
+smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
+ afs_uint32 flags)
{
smb_username_t *unp= NULL;
lock_ObtainWrite(&smb_rctLock);
for(unp = usernamesp; unp; unp = unp->nextp) {
- if (stricmp(unp->name, usern) == 0 &&
- stricmp(unp->machine, machine) == 0) {
+ if (cm_ClientStrCmpI(unp->name, usern) == 0 &&
+ cm_ClientStrCmpI(unp->machine, machine) == 0) {
unp->refCount++;
break;
}
memset(unp, 0, sizeof(*unp));
unp->refCount = 1;
unp->nextp = usernamesp;
- unp->name = strdup(usern);
- unp->machine = strdup(machine);
+ unp->name = cm_ClientStrDup(usern);
+ unp->machine = cm_ClientStrDup(machine);
usernamesp = unp;
- lock_InitializeMutex(&unp->mx, "username_t mutex");
+ lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
if (flags & SMB_FLAG_AFSLOGON)
unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
}
return unp;
}
-smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
+smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, clientchar_t *usern)
{
smb_user_t *uidp= NULL;
for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
if (!uidp->unp)
continue;
- if (stricmp(uidp->unp->name, usern) == 0) {
+ if (cm_stricmp_utf16(uidp->unp->name, usern) == 0) {
uidp->refCount++;
- osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
- vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
+ osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%S]",
+ vcp,uidp->userID,osi_LogSaveClientString(smb_logp,usern));
break;
} else
continue;
free(unp->name);
free(unp->machine);
free(unp);
- }
+ }
lock_ReleaseWrite(&smb_rctLock);
-
- if (userp) {
+ if (userp)
cm_ReleaseUser(userp);
- }
}
void smb_HoldUIDNoLock(smb_user_t *uidp)
{
+ lock_AssertWrite(&smb_rctLock);
uidp->refCount++;
}
* Return a pointer to a pathname extracted from a TID structure. The
* TID structure is not held; assume it won't go away.
*/
-long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
+long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, clientchar_t ** treepath)
{
smb_tid_t *tidp;
long code = 0;
/* tidp->pathname would be NULL, but that's fine */
}
*treepath = tidp->pathname;
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
}
return code;
}
* If the SMB_FLAG_CREATE flag is set, we allocate a new
* smb_fid_t data structure if desired File ID cannot be found.
*/
+#ifdef DEBUG_SMB_REFCOUNT
+smb_fid_t *smb_FindFIDDbg(smb_vc_t *vcp, unsigned short fid, int flags, char *file, long line)
+#else
smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
+#endif
{
smb_fid_t *fidp;
int newFid = 0;
retry:
for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
- if (fidp->refCount == 0 && fidp->delete) {
+ if (fidp->refCount == 0 && fidp->deleteOk) {
fidp->refCount++;
lock_ReleaseWrite(&smb_rctLock);
smb_ReleaseFID(fidp);
fidp->refCount = 1;
fidp->vcp = vcp;
smb_HoldVCNoLock(vcp);
- lock_InitializeMutex(&fidp->mx, "fid_t mutex");
+ lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
fidp->fid = fid;
fidp->curr_chunk = fidp->prev_chunk = -2;
fidp->raw_write_event = event;
}
}
+#ifdef DEBUG_SMB_REFCOUNT
+ if (fidp) {
+ afsi_log("%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+ }
+#endif
lock_ReleaseWrite(&smb_rctLock);
return fidp;
}
+#ifdef DEBUG_SMB_REFCOUNT
+smb_fid_t *smb_FindFIDByScacheDbg(smb_vc_t *vcp, cm_scache_t * scp, char *file, long line)
+#else
smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
+#endif
{
smb_fid_t *fidp = NULL;
int newFid = 0;
break;
}
}
+#ifdef DEBUG_SMB_REFCOUNT
+ if (fidp) {
+ afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+ }
+#endif
lock_ReleaseWrite(&smb_rctLock);
return fidp;
}
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldFIDNoLockDbg(smb_fid_t *fidp, char *file, long line)
+#else
void smb_HoldFIDNoLock(smb_fid_t *fidp)
+#endif
{
+ lock_AssertWrite(&smb_rctLock);
fidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+ osi_Log4(smb_logp,"%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+#endif
}
/* smb_ReleaseFID cannot be called while an cm_scache_t mutex lock is held */
/* the sm_fid_t->mx and smb_rctLock must not be held */
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
+#else
void smb_ReleaseFID(smb_fid_t *fidp)
+#endif
{
cm_scache_t *scp = NULL;
cm_user_t *userp = NULL;
lock_ObtainMutex(&fidp->mx);
lock_ObtainWrite(&smb_rctLock);
osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
- if (fidp->refCount == 0 && (fidp->delete)) {
- vcp = fidp->vcp;
- fidp->vcp = NULL;
- scp = fidp->scp; /* release after lock is released */
- if (scp) {
- lock_ObtainMutex(&scp->mx);
- scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
- osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
- fidp->scp = NULL;
- }
- userp = fidp->userp;
- fidp->userp = NULL;
+#ifdef DEBUG_SMB_REFCOUNT
+ afsi_log("%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+ osi_Log5(smb_logp,"%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+#endif
+ if (fidp->refCount == 0) {
+ if (fidp->deleteOk) {
+ vcp = fidp->vcp;
+ fidp->vcp = NULL;
+ scp = fidp->scp; /* release after lock is released */
+ if (scp) {
+ lock_ObtainWrite(&scp->rw);
+ scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+ lock_ReleaseWrite(&scp->rw);
+ osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
+ fidp->scp = NULL;
+ }
+ userp = fidp->userp;
+ fidp->userp = NULL;
- if (vcp->fidsp)
- osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
- thrd_CloseHandle(fidp->raw_write_event);
+ if (vcp->fidsp)
+ osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
+ thrd_CloseHandle(fidp->raw_write_event);
- /* and see if there is ioctl stuff to free */
- ioctlp = fidp->ioctlp;
- if (ioctlp) {
- if (ioctlp->prefix)
+ /* and see if there is ioctl stuff to free */
+ ioctlp = fidp->ioctlp;
+ if (ioctlp) {
+ if (ioctlp->prefix)
cm_FreeSpace(ioctlp->prefix);
- if (ioctlp->inAllocp)
- free(ioctlp->inAllocp);
- if (ioctlp->outAllocp)
- free(ioctlp->outAllocp);
- free(ioctlp);
- }
- lock_ReleaseMutex(&fidp->mx);
- lock_FinalizeMutex(&fidp->mx);
- free(fidp);
-
- if (vcp)
- smb_ReleaseVCNoLock(vcp);
- } else {
- lock_ReleaseMutex(&fidp->mx);
+ if (ioctlp->ioctl.inAllocp)
+ free(ioctlp->ioctl.inAllocp);
+ if (ioctlp->ioctl.outAllocp)
+ free(ioctlp->ioctl.outAllocp);
+ free(ioctlp);
+ }
+ lock_ReleaseMutex(&fidp->mx);
+ lock_FinalizeMutex(&fidp->mx);
+ free(fidp);
+ fidp = NULL;
+
+ if (vcp)
+ smb_ReleaseVCNoLock(vcp);
+ }
}
+ if (fidp)
+ lock_ReleaseMutex(&fidp->mx);
+
lock_ReleaseWrite(&smb_rctLock);
/* now release the scache structure */
* Case-insensitive search for one string in another;
* used to find variable names in submount pathnames.
*/
-static char *smb_stristr(char *str1, char *str2)
+static clientchar_t *smb_stristr(clientchar_t *str1, clientchar_t *str2)
{
- char *cursor;
+ clientchar_t *cursor;
for (cursor = str1; *cursor; cursor++)
- if (stricmp(cursor, str2) == 0)
+ if (cm_ClientStrCmpI(cursor, str2) == 0)
return cursor;
return NULL;
* name has been identified by smb_stristr() and is in substr. Variable name
* length (plus one) is in substr_size. Variable value is in newstr.
*/
-static void smb_subst(char *str1, char *substr, unsigned int substr_size,
- char *newstr)
+static void smb_subst(clientchar_t *str1, int cchstr1, clientchar_t *substr,
+ unsigned int substr_size, clientchar_t *newstr)
{
- char temp[1024];
-
- strcpy(temp, substr + substr_size - 1);
- strcpy(substr, newstr);
- strcat(str1, temp);
-}
+ clientchar_t temp[1024];
-char VNUserName[] = "%USERNAME%";
-char VNLCUserName[] = "%LCUSERNAME%";
-char VNComputerName[] = "%COMPUTERNAME%";
-char VNLCComputerName[] = "%LCCOMPUTERNAME%";
+ cm_ClientStrCpy(temp, lengthof(temp), substr + substr_size - 1);
+ cm_ClientStrCpy(substr, cchstr1 - (substr - str1), newstr);
+ cm_ClientStrCat(str1, cchstr1, temp);
+}
+clientchar_t VNUserName[] = _C("%USERNAME%");
+clientchar_t VNLCUserName[] = _C("%LCUSERNAME%");
+clientchar_t VNComputerName[] = _C("%COMPUTERNAME%");
+clientchar_t VNLCComputerName[] = _C("%LCCOMPUTERNAME%");
typedef struct smb_findShare_rock {
- char * shareName;
- char * match;
+ clientchar_t * shareName;
+ clientchar_t * match;
int matchType;
} smb_findShare_rock_t;
{
int matchType = 0;
smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
- if (!strnicmp(dep->name, vrock->shareName, 12)) {
- if(!stricmp(dep->name, vrock->shareName))
+ normchar_t normName[MAX_PATH];
+
+ cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0]));
+
+ if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
+ if(!cm_ClientStrCmpI(normName, vrock->shareName))
matchType = SMB_FINDSHARE_EXACT_MATCH;
else
matchType = SMB_FINDSHARE_PARTIAL_MATCH;
if(vrock->match) free(vrock->match);
- vrock->match = strdup(dep->name);
+ vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
vrock->matchType = matchType;
if(matchType == SMB_FINDSHARE_EXACT_MATCH)
/* find a shareName in the table of submounts */
-int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
- char **pathNamep)
-{
- DWORD len;
- char pathName[1024];
- char *var;
- char temp[1024];
+int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
+ clientchar_t *shareName,
+ clientchar_t **pathNamep)
+{
+ DWORD cblen;
+ DWORD cchlen;
+ clientchar_t pathName[1024];
+ clientchar_t *var;
DWORD sizeTemp;
- char *p, *q;
+ clientchar_t *p, *q;
+ fschar_t *cellname = NULL;
HKEY parmKey;
DWORD code;
DWORD allSubmount = 1;
* world to do so.
*/
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
- 0, KEY_QUERY_VALUE, &parmKey);
+ 0, KEY_QUERY_VALUE, &parmKey);
if (code == ERROR_SUCCESS) {
- len = sizeof(allSubmount);
+ cblen = sizeof(allSubmount);
code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
- (BYTE *) &allSubmount, &len);
+ (BYTE *) &allSubmount, &cblen);
if (code != ERROR_SUCCESS) {
allSubmount = 1;
}
RegCloseKey (parmKey);
}
- if (allSubmount && _stricmp(shareName, "all") == 0) {
+ if (allSubmount && cm_ClientStrCmpI(shareName, _C("all")) == 0) {
*pathNamep = NULL;
return 1;
}
/* In case, the all share is disabled we need to still be able
* to handle ioctl requests
*/
- if (_stricmp(shareName, "ioctl$") == 0) {
- *pathNamep = strdup("/.__ioctl__");
+ if (cm_ClientStrCmpI(shareName, _C("ioctl$")) == 0) {
+ *pathNamep = cm_ClientStrDup(_C("/.__ioctl__"));
return 1;
}
- if (_stricmp(shareName, "IPC$") == 0 ||
- _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
- _stricmp(shareName, "DESKTOP.INI") == 0
- ) {
+ if (cm_ClientStrCmpIA(shareName, _C("IPC$")) == 0 ||
+ cm_ClientStrCmpIA(shareName, _C("srvsvc")) == 0 ||
+ cm_ClientStrCmpIA(shareName, _C("wkssvc")) == 0 ||
+ cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
+ cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
+ ) {
*pathNamep = NULL;
return 0;
}
*
* They look like <cell>{%,#}<volume>
*/
- if (strchr(shareName, '%') != NULL ||
- strchr(shareName, '#') != NULL) {
- char pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
- /* make room for '/@vol:' + mountchar + NULL terminator*/
+ if (cm_ClientStrChr(shareName, '%') != NULL ||
+ cm_ClientStrChr(shareName, '#') != NULL) {
+ clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
+ /* make room for '/@vol:' + mountchar + NULL terminator*/
- osi_Log1(smb_logp, "smb_FindShare found volume reference [%s]",
- osi_LogSaveString(smb_logp, shareName));
+ osi_Log1(smb_logp, "smb_FindShare found volume reference [%S]",
+ osi_LogSaveClientString(smb_logp, shareName));
- snprintf(pathstr, sizeof(pathstr)/sizeof(char),
- "/" CM_PREFIX_VOL "%s", shareName);
- pathstr[sizeof(pathstr)/sizeof(char) - 1] = '\0';
- len = strlen(pathstr) + 1;
+ cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
+ _C("/") _C(CM_PREFIX_VOL) _C("%s"), shareName);
+ cchlen = (DWORD)(cm_ClientStrLen(pathstr) + 1);
- *pathNamep = malloc(len);
+ *pathNamep = malloc(cchlen * sizeof(clientchar_t));
if (*pathNamep) {
- strcpy(*pathNamep, pathstr);
- strlwr(*pathNamep);
- osi_Log1(smb_logp, " returning pathname [%s]",
- osi_LogSaveString(smb_logp, *pathNamep));
+ cm_ClientStrCpy(*pathNamep, cchlen, pathstr);
+ cm_ClientStrLwr(*pathNamep);
+ osi_Log1(smb_logp, " returning pathname [%S]",
+ osi_LogSaveClientString(smb_logp, *pathNamep));
return 1;
} else {
}
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
- 0, KEY_QUERY_VALUE, &parmKey);
+ 0, KEY_QUERY_VALUE, &parmKey);
if (code == ERROR_SUCCESS) {
- len = sizeof(pathName);
- code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
- (BYTE *) pathName, &len);
+ cblen = sizeof(pathName);
+ code = RegQueryValueExW(parmKey, shareName, NULL, NULL,
+ (BYTE *) pathName, &cblen);
if (code != ERROR_SUCCESS)
- len = 0;
+ cblen = 0;
RegCloseKey (parmKey);
} else {
- len = 0;
- }
- if (len != 0 && len != sizeof(pathName) - 1) {
+ cblen = 0;
+ }
+ cchlen = cblen / sizeof(clientchar_t);
+ if (cchlen != 0 && cchlen != lengthof(pathName) - 1) {
/* We can accept either unix or PC style AFS pathnames. Convert
* Unix-style to PC style here for internal use.
*/
p = pathName;
- if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) == 0)
- p += strlen(cm_mountRoot); /* skip mount path */
+ cchlen = lengthof(pathName);
+
+ /* within this code block, we maintain, cchlen = writeable
+ buffer length of p */
+
+ if (cm_ClientStrCmpN(p, cm_mountRootC, cm_mountRootCLen) == 0) {
+ p += cm_mountRootCLen; /* skip mount path */
+ cchlen -= (DWORD)(p - pathName);
+ }
+
q = p;
while (*q) {
- if (*q == '/') *q = '\\'; /* change to \ */
+ if (*q == _C('/')) *q = _C('\\'); /* change to \ */
q++;
}
while (1)
{
+ clientchar_t temp[1024];
+
if (var = smb_stristr(p, VNUserName)) {
if (uidp && uidp->unp)
- smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
+ smb_subst(p, cchlen, var, lengthof(VNUserName),uidp->unp->name);
else
- smb_subst(p, var, sizeof(VNUserName)," ");
+ smb_subst(p, cchlen, var, lengthof(VNUserName), _C(" "));
}
else if (var = smb_stristr(p, VNLCUserName))
{
if (uidp && uidp->unp)
- strcpy(temp, uidp->unp->name);
+ cm_ClientStrCpy(temp, lengthof(temp), uidp->unp->name);
else
- strcpy(temp, " ");
- _strlwr(temp);
- smb_subst(p, var, sizeof(VNLCUserName), temp);
+ cm_ClientStrCpy(temp, lengthof(temp), _C(" "));
+ cm_ClientStrLwr(temp);
+ smb_subst(p, cchlen, var, lengthof(VNLCUserName), temp);
}
else if (var = smb_stristr(p, VNComputerName))
{
- sizeTemp = sizeof(temp);
- GetComputerName((LPTSTR)temp, &sizeTemp);
- smb_subst(p, var, sizeof(VNComputerName), temp);
+ sizeTemp = lengthof(temp);
+ GetComputerNameW(temp, &sizeTemp);
+ smb_subst(p, cchlen, var, lengthof(VNComputerName), temp);
}
else if (var = smb_stristr(p, VNLCComputerName))
{
- sizeTemp = sizeof(temp);
+ sizeTemp = lengthof(temp);
GetComputerName((LPTSTR)temp, &sizeTemp);
- _strlwr(temp);
- smb_subst(p, var, sizeof(VNLCComputerName), temp);
+ cm_ClientStrLwr(temp);
+ smb_subst(p, cchlen, var, lengthof(VNLCComputerName), temp);
}
else
break;
}
- *pathNamep = strdup(p);
+ *pathNamep = cm_ClientStrDup(p);
return 1;
}
else
cm_req_t req;
smb_findShare_rock_t vrock;
osi_hyper_t thyper;
- char * p = shareName;
+ fschar_t ftemp[1024];
+ clientchar_t * p = shareName;
int rw = 0;
/* attempt to locate a partial match in root.afs. This is because
when using the ANSI RAP calls, the share name is limited to 13 chars
and hence is truncated. Of course we prefer exact matches. */
- cm_InitReq(&req);
+ smb_InitReq(&req);
thyper.HighPart = 0;
thyper.LowPart = 0;
- vrock.shareName = shareName;
+ vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
vrock.match = NULL;
vrock.matchType = 0;
cm_HoldSCache(cm_data.rootSCachep);
code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
- (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
+ (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
cm_ReleaseSCache(cm_data.rootSCachep);
+ free(vrock.shareName);
+ vrock.shareName = NULL;
+
if (vrock.matchType) {
- sprintf(pathName,"/%s/",vrock.match);
- *pathNamep = strdup(strlwr(pathName));
+ cm_ClientStrPrintfN(pathName, lengthof(pathName), _C("/%s/"), vrock.match);
+ *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
free(vrock.match);
return 1;
}
rw = 1;
}
/* Get the full name for this cell */
- code = cm_SearchCellFile(p, temp, 0, 0);
+ cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
+ code = cm_SearchCellFile(cellname, ftemp, 0, 0);
#ifdef AFS_AFSDB_ENV
if (code && cm_dnsEnabled) {
int ttl;
- code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
+ code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
}
#endif
+ if (cellname)
+ free(cellname);
+
/* construct the path */
- if (code == 0) {
- sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
- *pathNamep = strdup(strlwr(pathName));
+ if (code == 0) {
+ clientchar_t temp[1024];
+
+ cm_FsStringToClientString(ftemp, -1, temp, 1024);
+ cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
+ rw ? _C("/.%S/") : _C("/%S/"), temp);
+ *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
return 1;
}
}
#define CSC_POLICY_PROGRAMS 2
#define CSC_POLICY_DISABLE 3
-int smb_FindShareCSCPolicy(char *shareName)
+int smb_FindShareCSCPolicy(clientchar_t *shareName)
{
DWORD len;
- char policy[1024];
+ clientchar_t policy[1024];
DWORD dwType;
HKEY hkCSCPolicy;
int retval = CSC_POLICY_MANUAL;
NULL );
len = sizeof(policy);
- if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
+ if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
len == 0) {
- retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
+ retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
}
- else if (stricmp(policy, "documents") == 0)
+ else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
{
retval = CSC_POLICY_DOCUMENTS;
}
- else if (stricmp(policy, "programs") == 0)
+ else if (cm_ClientStrCmpIA(policy, _C("programs")) == 0)
{
retval = CSC_POLICY_PROGRAMS;
}
- else if (stricmp(policy, "disable") == 0)
+ else if (cm_ClientStrCmpIA(policy, _C("disable")) == 0)
{
retval = CSC_POLICY_DISABLE;
}
if (!smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
}
- lock_ObtainMutex(&dsp->mx);
dsp->refCount++;
- lock_ReleaseMutex(&dsp->mx);
break;
}
}
void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
{
- lock_ObtainWrite(&smb_globalLock);
lock_ObtainMutex(&dsp->mx);
osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p",
dsp->cookie, dsp, dsp->scp);
dsp->flags |= SMB_DIRSEARCH_DELETE;
if (dsp->scp != NULL) {
- lock_ObtainMutex(&dsp->scp->mx);
+ lock_ObtainWrite(&dsp->scp->rw);
if (dsp->flags & SMB_DIRSEARCH_BULKST) {
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
dsp->scp->bulkStatProgress = hzero;
}
- lock_ReleaseMutex(&dsp->scp->mx);
+ lock_ReleaseWrite(&dsp->scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
- lock_ReleaseWrite(&smb_globalLock);
}
/* Must be called with the smb_globalLock held */
{
cm_scache_t *scp = NULL;
- lock_ObtainMutex(&dsp->mx);
osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
- if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
- if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
- smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
- osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
- lock_ReleaseMutex(&dsp->mx);
- lock_FinalizeMutex(&dsp->mx);
- scp = dsp->scp;
- osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
- dsp->cookie, dsp, scp);
- free(dsp);
- } else {
- lock_ReleaseMutex(&dsp->mx);
+ if (dsp->refCount == 0) {
+ lock_ObtainMutex(&dsp->mx);
+ if (dsp->flags & SMB_DIRSEARCH_DELETE) {
+ if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
+ smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
+ osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ lock_ReleaseMutex(&dsp->mx);
+ lock_FinalizeMutex(&dsp->mx);
+ scp = dsp->scp;
+ osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
+ dsp->cookie, dsp, scp);
+ free(dsp);
+ } else {
+ lock_ReleaseMutex(&dsp->mx);
+ }
}
/* do this now to avoid spurious locking hierarchy creation */
if (scp)
void smb_GCDirSearches(int isV3)
{
smb_dirSearch_t *prevp;
- smb_dirSearch_t *tp;
+ smb_dirSearch_t *dsp;
smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
int victimCount;
int i;
victimCount = 0; /* how many have we got so far */
- for (tp = smb_lastDirSearchp; tp; tp=prevp) {
+ for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
/* we'll move tp from queue, so
* do this early.
*/
- prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);
+ prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
/* if no one is using this guy, and we're either in the new protocol,
* or we're in the old one and this is a small enough ID to be useful
* to the old protocol, GC this guy.
*/
- if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
+ if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
/* hold and delete */
- lock_ObtainMutex(&tp->mx);
- tp->flags |= SMB_DIRSEARCH_DELETE;
- lock_ReleaseMutex(&tp->mx);
- victimsp[victimCount++] = tp;
- tp->refCount++;
+ lock_ObtainMutex(&dsp->mx);
+ dsp->flags |= SMB_DIRSEARCH_DELETE;
+ lock_ReleaseMutex(&dsp->mx);
+ victimsp[victimCount++] = dsp;
+ dsp->refCount++;
}
/* don't do more than this */
/* don't need to watch for refcount zero and deleted, since
* we haven't dropped the global lock.
*/
- lock_ObtainMutex(&dsp->mx);
dsp->refCount--;
- lock_ReleaseMutex(&dsp->mx);
++smb_dirSearchCounter;
continue;
}
dsp->cookie = smb_dirSearchCounter;
++smb_dirSearchCounter;
dsp->refCount = 1;
- lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
+ lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
dsp->lastTime = osi_Time();
osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
if (!smb_lastDirSearchp)
return dsp;
}
-static smb_packet_t *GetPacket(void)
+static smb_packet_t *smb_GetPacket(void)
{
smb_packet_t *tbp;
smb_packetFreeListp = tbp->nextp;
lock_ReleaseWrite(&smb_globalLock);
if (!tbp) {
- tbp = calloc(65540,1);
+ tbp = calloc(sizeof(*tbp),1);
tbp->magic = SMB_PACKETMAGIC;
tbp->ncbp = NULL;
tbp->vcp = NULL;
tbp->ncb_length = 0;
tbp->flags = 0;
tbp->spacep = NULL;
-
+ tbp->stringsp = NULL;
}
osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
{
smb_packet_t *tbp;
- tbp = GetPacket();
+ tbp = smb_GetPacket();
memcpy(tbp, pkt, sizeof(smb_packet_t));
tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+ tbp->stringsp = NULL;
if (tbp->vcp)
smb_HoldVC(tbp->vcp);
return tbp;
}
-static NCB *GetNCB(void)
+static NCB *smb_GetNCB(void)
{
smb_ncb_t *tbp;
NCB *ncbp;
return ncbp;
}
+static void FreeSMBStrings(smb_packet_t * pkt)
+{
+ cm_space_t * s;
+ cm_space_t * ns;
+
+ for (s = pkt->stringsp; s; s = ns) {
+ ns = s->nextp;
+ cm_FreeSpace(s);
+ }
+ pkt->stringsp = NULL;
+}
+
void smb_FreePacket(smb_packet_t *tbp)
{
smb_vc_t * vcp = NULL;
tbp->oddByte = 0;
tbp->ncb_length = 0;
tbp->flags = 0;
+ FreeSMBStrings(tbp);
lock_ReleaseWrite(&smb_globalLock);
if (vcp)
smb_ReleaseVC(vcp);
}
-static void FreeNCB(NCB *bufferp)
+static void smb_FreeNCB(NCB *bufferp)
{
smb_ncb_t *tbp;
void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
{
- char *parmDatap;
+ unsigned char *parmDatap;
/* make sure we have enough slots */
if (*smbp->wctp <= slot)
void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
{
- char *parmDatap;
+ unsigned char *parmDatap;
/* make sure we have enough slots */
if (*smbp->wctp <= slot)
void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
{
- char *parmDatap;
+ unsigned char *parmDatap;
int i;
/* make sure we have enough slots */
void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
{
- char *parmDatap;
+ unsigned char *parmDatap;
/* make sure we have enough slots */
if (*smbp->wctp <= slot) {
*parmDatap++ = parmValue & 0xff;
}
-void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp)
+
+
+void smb_StripLastComponent(clientchar_t *outPathp, clientchar_t **lastComponentp,
+ clientchar_t *inPathp)
{
- char *lastSlashp;
+ clientchar_t *lastSlashp;
- lastSlashp = strrchr(inPathp, '\\');
+ lastSlashp = cm_ClientStrRChr(inPathp, '\\');
if (lastComponentp)
*lastComponentp = lastSlashp;
if (lastSlashp) {
}
}
-unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
+clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
+ char **chainpp, int flags)
{
+ size_t cb;
+
if (*inp++ != 0x4)
return NULL;
- if (chainpp) {
- *chainpp = inp + strlen(inp) + 1; /* skip over null-terminated string */
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ cb = sizeof(pktp->data) - (inp - pktp->data);
+ if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ cb = sizeof(pktp->data);
+ }
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+clientchar_t *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
+ char ** chainpp, int flags)
+{
+ size_t cb;
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ cb = sizeof(pktp->data) - (inp - pktp->data);
+ if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ cb = sizeof(pktp->data);
+ }
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
+ flags | SMB_STRF_SRCNULTERM);
+}
+
+clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
+ size_t cb, char ** chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+#endif
+
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+clientchar_t *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp,
+ size_t cch, char ** chainpp, int flags)
+{
+ size_t cb = cch;
+
+#ifdef SMB_UNICODE
+ if (!WANTS_UNICODE(pktp))
+ flags |= SMB_STRF_FORCEASCII;
+ else
+ cb = cch * sizeof(wchar_t);
+#endif
+
+ return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+clientchar_t *
+smb_ParseStringBuf(const unsigned char * bufbase,
+ cm_space_t ** stringspp,
+ unsigned char *inp, size_t *pcb_max,
+ char **chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+ if (!(flags & SMB_STRF_FORCEASCII)) {
+ size_t cch_src;
+ cm_space_t * spacep;
+ int null_terms = 0;
+
+ if (bufbase && ((inp - bufbase) % 2) != 0) {
+ inp++; /* unicode strings are always word aligned */
+ }
+
+ if (*pcb_max > 0) {
+ if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t),
+ &cch_src))) {
+ cch_src = *pcb_max / sizeof(wchar_t);
+ *pcb_max = 0;
+ null_terms = 0;
+ } else {
+ *pcb_max -= (cch_src + 1) * sizeof(wchar_t);
+ null_terms = 1;
+ }
+ } else {
+ cch_src = 0;
+ }
+
+ spacep = cm_GetSpace();
+ spacep->nextp = *stringspp;
+ *stringspp = spacep;
+
+ if (cch_src == 0) {
+ if (chainpp) {
+ *chainpp = inp + sizeof(wchar_t);
+ }
+
+ *(spacep->wdata) = 0;
+ return spacep->wdata;
+ }
+
+ StringCchCopyNW(spacep->wdata,
+ lengthof(spacep->wdata),
+ (const clientchar_t *) inp, cch_src);
+
+ if (chainpp)
+ *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t);
+
+ return spacep->wdata;
+
+ } else {
+#endif
+ cm_space_t * spacep;
+ int cchdest;
+
+ /* Not using Unicode */
+ if (chainpp) {
+ *chainpp = inp + strlen(inp) + 1;
+ }
+
+ spacep = cm_GetSpace();
+ spacep->nextp = *stringspp;
+ *stringspp = spacep;
+
+ cchdest = lengthof(spacep->wdata);
+ cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
+ spacep->wdata, cchdest);
+
+ return spacep->wdata;
+#ifdef SMB_UNICODE
+ }
+#endif
+}
+
+unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
+ clientchar_t * str,
+ size_t * plen, int flags)
+{
+ size_t buffersize;
+ int align = 0;
+
+ if (outp == NULL) {
+ /* we are only calculating the required size */
+
+ if (plen == NULL)
+ return NULL;
+
+#ifdef SMB_UNICODE
+
+ if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+
+ StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
+ if (!(flags & SMB_STRF_IGNORENUL))
+ *plen += sizeof(wchar_t);
+
+ return (unsigned char *) 1; /* return TRUE if we are using unicode */
+ }
+ else
+#endif
+ {
+ /* Storing ANSI */
+
+ size_t cch_str;
+ size_t cch_dest;
+
+ cch_str = cm_ClientStrLen(str);
+ cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
+
+ if (plen)
+ *plen = ((flags & SMB_STRF_IGNORENUL)? cch_dest: cch_dest+1);
+
+ return NULL;
+ }
+
+ /* Not reached. */
+ }
+
+ /* if outp != NULL ... */
+
+ /* Number of bytes left in the buffer.
+
+ If outp lies inside the packet data buffer, we assume that the
+ buffer is the packet data buffer. Otherwise we assume that the
+ buffer is sizeof(packet->data).
+
+ */
+ if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
+ align = (int)((outp - pktp->data) % 2);
+ buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
+ } else {
+ align = (int)(((size_t) outp) % 2);
+ buffersize = (int)sizeof(pktp->data);
+ }
+
+#ifdef SMB_UNICODE
+
+ if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+ int nchars;
+
+ if (align)
+ *outp++ = '\0';
+
+ if (*str == _C('\0')) {
+
+ if (buffersize < sizeof(wchar_t))
+ return NULL;
+
+ *((wchar_t *) outp) = L'\0';
+ if (plen && !(flags & SMB_STRF_IGNORENUL))
+ *plen += sizeof(wchar_t);
+ return outp + sizeof(wchar_t);
+ }
+
+ nchars = cm_ClientStringToUtf16(str, -1, (wchar_t *) outp, (int)(buffersize / sizeof(wchar_t)));
+ if (nchars == 0) {
+ osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
+ osi_LogSaveClientString(smb_logp, str),
+ GetLastError());
+ return NULL;
+ }
+
+ if (plen)
+ *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENUL)? nchars - 1: nchars);
+
+ return outp + sizeof(wchar_t) * nchars;
+ }
+ else
+#endif
+ {
+ /* Storing ANSI */
+ size_t cch_dest;
+
+ cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
+
+ if (plen)
+ *plen += ((flags & SMB_STRF_IGNORENUL)? cch_dest - 1: cch_dest);
+
+ return outp + cch_dest;
}
- return inp;
}
unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
return inp;
}
+unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
+{
+ int tlen;
+
+ if (*inp++ != 0x1) return NULL;
+ tlen = inp[0] + (inp[1]<<8);
+ inp += 2; /* skip length field */
+
+ if (chainpp) {
+ *chainpp = inp + tlen;
+ }
+
+ if (lengthp) *lengthp = tlen;
+
+ return inp;
+}
+
/* format a packet as a response */
void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
{
outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
#endif
outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
+#ifdef SMB_UNICODE
+ if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
+ outp->flg2 |= SMB_FLAGS2_UNICODE;
+#endif
/* copy fields in generic packet area */
op->wctp = &outp->wct;
ncbp = inp->ncbp;
if (ncbp == NULL) {
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
localNCB = 1;
}
}
if (localNCB)
- FreeNCB(ncbp);
+ smb_FreeNCB(ncbp);
}
void smb_MapNTError(long code, unsigned long *NTStatusp)
NTStatus = 0xC09820FBL; /* SMB use standard */
}
else if (code == CM_ERROR_QUOTA) {
-#ifdef COMMENT
NTStatus = 0xC0000044L; /* Quota exceeded */
-#else
- NTStatus = 0xC000007FL; /* Disk full */
-#endif
}
else if (code == CM_ERROR_SPACE) {
NTStatus = 0xC000007FL; /* Disk full */
else if (code == CM_ERROR_PATH_NOT_COVERED) {
NTStatus = 0xC0000257L; /* Path Not Covered */
}
-#ifdef COMMENT
else if (code == CM_ERROR_ALLBUSY) {
- NTStatus = 0xC00000BFL; /* Network Busy */
+ NTStatus = 0xC000022DL; /* Retry */
}
else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
- NTStatus = 0xC0000350L; /* Remote Host Down */
- }
-#else
- /* we do not want to be telling the SMB/CIFS client that
- * the AFS Client Service is busy or down.
- */
- else if (code == CM_ERROR_ALLBUSY ||
- code == CM_ERROR_ALLOFFLINE ||
- code == CM_ERROR_ALLDOWN) {
NTStatus = 0xC00000BEL; /* Bad Network Path */
- }
-#endif
- else if (code == RXKADUNKNOWNKEY) {
- NTStatus = 0xC0000322L; /* Bad Kerberos key */
+ }
+ else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+ NTStatus = 0xC0000322L; /* No Kerberos key */
}
else if (code == CM_ERROR_BAD_LEVEL) {
NTStatus = 0xC0000148L; /* Invalid Level */
+ }
+ else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+ NTStatus = 0xC000007EL; /* Range Not Locked */
+ }
+ else if (code == CM_ERROR_NOSUCHDEVICE) {
+ NTStatus = 0xC000000EL; /* No Such Device */
+ }
+ else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+ NTStatus = 0xC0000055L; /* Lock Not Granted */
} else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
return CM_ERROR_BADOP;
}
+/* SMB_COM_ECHO */
long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short EchoCount, i;
return 0;
}
+/* SMB_COM_READ_RAW */
long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
osi_hyper_t offset;
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp = NULL;
NCB *ncbp;
}
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
{
LARGE_INTEGER LOffset, LLength;
cm_key_t key;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
if (code) {
goto send1a;
lock_ReleaseMutex(&smb_RawBufLock);
}
+ lock_ReleaseMutex(&fidp->mx);
smb_ReleaseFID(fidp);
return rc;
}
return 0;
}
+/* SMB_COM_NEGOTIATE */
long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *namep;
* and NT Find *
* and NT SMB's *
* and raw mode
- * and DFS */
+ * and DFS
+ * and Unicode */
caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
#ifdef DFS_SUPPORT
NTNEGOTIATE_CAPABILITY_DFS |
if ( smb_authType == SMB_AUTH_EXTENDED )
caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
+#ifdef SMB_UNICODE
+ if ( smb_UseUnicode ) {
+ caps |= NTNEGOTIATE_CAPABILITY_UNICODE;
+ }
+#endif
+
smb_SetSMBParmLong(outp, 9, caps);
time(&unixTime);
smb_SearchTimeFromUnixTime(&dosTime, unixTime);
datap = smb_GetSMBData(outp, NULL);
memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
/* and the faux domain name */
- strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
+ cm_ClientStringToUtf8(smb_ServerDomainName, -1,
+ datap + MSV1_0_CHALLENGE_LENGTH,
+ (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
} else if ( smb_authType == SMB_AUTH_EXTENDED ) {
void * secBlob;
int secBlobLength;
/* paste in a new encryption key */
memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
/* and the faux domain name */
- strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
+ cm_ClientStringToUtf8(smb_ServerDomainName, -1,
+ datap + MSV1_0_CHALLENGE_LENGTH,
+ (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
} else {
smb_SetSMBParm(outp, 11, 0); /* encryption key length */
smb_SetSMBParm(outp, 12, 0); /* resvd */
void smb_CheckVCs(void)
{
smb_vc_t * vcp, *nextp;
- smb_packet_t * outp = GetPacket();
+ smb_packet_t * outp = smb_GetPacket();
smb_t *smbp;
lock_ObtainWrite(&smb_rctLock);
osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
__FILE__, __LINE__);
+ /* on the first pass hold 'vcp' which was not held as 'nextp' */
+ if (vcp != nextp)
+ smb_HoldVCNoLock(vcp);
+
+ /*
+ * obtain a reference to 'nextp' now because we drop the
+ * smb_rctLock later and the list contents could change
+ * or 'vcp' could be destroyed when released.
+ */
nextp = vcp->nextp;
+ if (nextp)
+ smb_HoldVCNoLock(nextp);
- if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ smb_ReleaseVCNoLock(vcp);
continue;
+ }
- smb_HoldVCNoLock(vcp);
- if (nextp)
- smb_HoldVCNoLock(nextp);
smb_FormatResponsePacket(vcp, NULL, outp);
smbp = (smb_t *)outp;
outp->inCom = smbp->com = 0x2b /* Echo */;
lock_ObtainWrite(&smb_rctLock);
smb_ReleaseVCNoLock(vcp);
- if (nextp)
- smb_ReleaseVCNoLock(nextp);
}
lock_ReleaseWrite(&smb_rctLock);
smb_FreePacket(outp);
now = osi_Time();
lock_ObtainWrite(&smb_rctLock);
for ( unpp=&usernamesp; *unpp; ) {
- int delete = 0;
+ int deleteOk = 0;
smb_username_t *unp;
lock_ObtainMutex(&(*unpp)->mx);
;
else if (!smb_LogoffTokenTransfer ||
((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
- delete = 1;
+ deleteOk = 1;
lock_ReleaseMutex(&(*unpp)->mx);
- if (delete) {
+ if (deleteOk) {
cm_user_t * userp;
unp = *unpp;
free(unp->name);
free(unp->machine);
free(unp);
- if (userp) {
- lock_ReleaseWrite(&smb_rctLock);
+ if (userp)
cm_ReleaseUser(userp);
- lock_ObtainWrite(&smb_rctLock);
- }
} else {
unpp = &(*unpp)->nextp;
}
if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
continue;
+ if (wl->state == SMB_WAITINGLOCKSTATE_CANCELLED) {
+ code = CM_ERROR_LOCK_NOT_GRANTED;
+ break;
+ }
+
osi_assertx(wl->state != SMB_WAITINGLOCKSTATE_ERROR, "!SMB_WAITINGLOCKSTATE_ERROR");
/* wl->state is either _DONE or _WAITING. _ERROR
if (code == CM_ERROR_WOULDBLOCK) {
/* no progress */
- if (wlRequest->timeRemaining != 0xffffffff
- && (wlRequest->timeRemaining -= 1000) < 0)
+ if (wlRequest->msTimeout != 0xffffffff
+ && ((osi_Time() - wlRequest->start_t) * 1000 > wlRequest->msTimeout))
goto endWait;
continue;
scp = wlRequest->scp;
osi_Log2(smb_logp,"smb_WaitingLocksDaemon wlRequest 0x%p scp 0x%p", wlRequest, scp);
- cm_InitReq(&req);
+ smb_InitReq(&req);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
for (wl = wlRequest->locks; wl; wl = wlNext) {
wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
-
- cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
- wl->LLength, wl->key, NULL, &req);
+
+ if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
+ cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
+ wl->LLength, wl->key, NULL, &req);
osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
free(wl);
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
} else {
vcp = wlRequest->vcp;
inp = wlRequest->inp;
outp = wlRequest->outp;
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
ncbp->ncb_length = inp->ncb_length;
inp->spacep = cm_GetSpace();
smb_FreePacket(outp);
smb_ReleaseVC(vcp);
cm_ReleaseSCache(wlRequest->scp);
- FreeNCB(ncbp);
+ smb_FreeNCB(ncbp);
free(wlRequest);
} while (nwlRequest && smbShutdownFlag == 0);
thrd_Sleep(1000);
return 0;
}
+/* SMB_COM_TREE_CONNECT */
long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
{
smb_tid_t *tidp;
smb_user_t *uidp;
unsigned short newTid;
- char shareName[AFSPATHMAX];
- char *sharePath;
+ clientchar_t shareName[AFSPATHMAX];
+ clientchar_t *sharePath;
int shareFound;
- char *tp;
- char *pathp;
- char *passwordp;
+ clientchar_t *tp;
+ clientchar_t *pathp;
cm_user_t *userp;
osi_Log0(smb_logp, "SMB receive tree connect");
/* parse input parameters */
- tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
- passwordp = smb_ParseASCIIBlock(tp, &tp);
- tp = strrchr(pathp, '\\');
+ {
+ char *tbp;
+ tbp = smb_GetSMBData(inp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, tbp, &tbp, SMB_STRF_ANSIPATH);
+ }
+ tp = cm_ClientStrRChr(pathp, '\\');
if (!tp)
return CM_ERROR_BADSMB;
- strcpy(shareName, tp+1);
+ cm_ClientStrCpy(shareName, lengthof(shareName), tp+1);
lock_ObtainMutex(&vcp->mx);
newTid = vcp->tidCounter++;
if (uidp)
smb_ReleaseUID(uidp);
if (!shareFound) {
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
return CM_ERROR_BADSHARENAME;
}
lock_ObtainMutex(&tidp->mx);
tidp->userp = userp;
tidp->pathname = sharePath;
lock_ReleaseMutex(&tidp->mx);
- smb_ReleaseTID(tidp);
+ smb_ReleaseTID(tidp, FALSE);
smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
smb_SetSMBParm(rsp, 1, newTid);
return 0;
}
-unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
-{
- int tlen;
-
- if (*inp++ != 0x1) return NULL;
- tlen = inp[0] + (inp[1]<<8);
- inp += 2; /* skip length field */
-
- if (chainpp) {
- *chainpp = inp + tlen;
- }
-
- if (lengthp) *lengthp = tlen;
-
- return inp;
-}
-
/* set maskp to the mask part of the incoming path.
* Mask is 11 bytes long (8.3 with the dot elided).
* Returns true if succeeds with a valid name, otherwise it does
* its best, but returns false.
*/
-int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
+int smb_Get8Dot3MaskFromPath(clientchar_t *maskp, clientchar_t *pathp)
{
- char *tp;
- char *up;
+ clientchar_t *tp;
+ clientchar_t *up;
int i;
int tc;
int valid8Dot3;
/* mask starts out all blanks */
memset(maskp, ' ', 11);
+ maskp[11] = '\0';
/* find last backslash, or use whole thing if there is none */
- tp = strrchr(pathp, '\\');
- if (!tp) tp = pathp;
- else tp++; /* skip slash */
+ tp = cm_ClientStrRChr(pathp, '\\');
+ if (!tp)
+ tp = pathp;
+ else
+ tp++; /* skip slash */
up = maskp;
/* names starting with a dot are illegal */
- if (*tp == '.') valid8Dot3 = 0;
+ if (*tp == '.')
+ valid8Dot3 = 0;
for(i=0;; i++) {
tc = *tp++;
- if (tc == 0) return valid8Dot3;
- if (tc == '.' || tc == '"') break;
- if (i < 8) *up++ = tc;
- else valid8Dot3 = 0;
+ if (tc == 0)
+ return valid8Dot3;
+ if (tc == '.' || tc == '"')
+ break;
+ if (i < 8)
+ *up++ = tc;
+ else
+ valid8Dot3 = 0;
}
/* if we get here, tp point after the dot */
/* unreachable */
}
-int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
+int smb_Match8Dot3Mask(clientchar_t *unixNamep, clientchar_t *maskp)
{
- char umask[11];
+ clientchar_t umask[11];
int valid;
int i;
- char tc1;
- char tc2;
- char *tp1;
- char *tp2;
+ clientchar_t tc1;
+ clientchar_t tc2;
+ clientchar_t *tp1;
+ clientchar_t *tp2;
- /* XXX redo this, calling smb_V3MatchMask with a converted mask */
+ /* XXX redo this, calling cm_MatchMask with a converted mask */
valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
if (!valid)
tp1 = umask; /* real name, in mask format */
tp2 = maskp; /* mask, in mask format */
for(i=0; i<11; i++) {
- tc1 = *tp1++; /* char from real name */
- tc2 = *tp2++; /* char from mask */
- tc1 = (char) cm_foldUpper[(unsigned char)tc1];
- tc2 = (char) cm_foldUpper[(unsigned char)tc2];
+ tc1 = *tp1++; /* clientchar_t from real name */
+ tc2 = *tp2++; /* clientchar_t from mask */
+ tc1 = (clientchar_t) cm_foldUpper[(clientchar_t)tc1];
+ tc2 = (clientchar_t) cm_foldUpper[(clientchar_t)tc2];
if (tc1 == tc2)
continue;
if (tc2 == '?' && tc1 != ' ')
return 1;
}
-char *smb_FindMask(char *pathp)
+clientchar_t *smb_FindMask(clientchar_t *pathp)
{
- char *tp;
+ clientchar_t *tp;
- tp = strrchr(pathp, '\\'); /* find last slash */
+ tp = cm_ClientStrRChr(pathp, '\\'); /* find last slash */
if (tp)
return tp+1; /* skip the slash */
return pathp; /* no slash, return the entire path */
}
+/* SMB_COM_SEARCH for a volume label
+
+ (This is called from smb_ReceiveCoreSearchDir() and not an actual
+ dispatch function.) */
long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- unsigned char *pathp;
+ clientchar_t *pathp;
unsigned char *tp;
- unsigned char mask[11];
+ clientchar_t mask[12];
unsigned char *statBlockp;
unsigned char initStatBlock[21];
int statLen;
/* pull pathname and stat block out of request */
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp,
+ SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
osi_assertx(pathp != NULL, "null path");
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
- statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
+ statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
osi_assertx(statBlockp != NULL, "null statBlock");
if (statLen == 0) {
statBlockp = initStatBlock;
*tp++ = 0;
*tp++ = 0;
+ /* The filename is a UCHAR buffer that is ASCII even if Unicode
+ was negotiated. */
+
/* finally, null-terminated 8.3 pathname, which we set to AFS */
memset(tp, ' ', 13);
strcpy(tp, "AFS");
return 0;
}
-long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
- cm_user_t *userp, cm_req_t *reqp)
+static long
+smb_ApplyDirListPatches(cm_scache_t * dscp, smb_dirListPatch_t **dirPatchespp,
+ clientchar_t * tidPathp, clientchar_t * relPathp,
+ cm_user_t *userp, cm_req_t *reqp)
{
long code = 0;
cm_scache_t *scp;
char attr;
smb_dirListPatch_t *patchp;
smb_dirListPatch_t *npatchp;
+ clientchar_t path[AFSPATHMAX];
+ afs_uint32 rights;
+ afs_int32 mustFake = 0;
+
+ code = cm_FindACLCache(dscp, userp, &rights);
+ if (code == -1) {
+ lock_ObtainWrite(&dscp->rw);
+ code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&dscp->rw);
+ if (code == CM_ERROR_NOACCESS) {
+ mustFake = 1;
+ code = 0;
+ }
+ }
+ if (code)
+ goto cleanup;
+
+ if (!mustFake) { /* Bulk Stat */
+ afs_uint32 count;
+ cm_bulkStat_t *bsp = malloc(sizeof(cm_bulkStat_t));
+
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
+
+ for (patchp = *dirPatchespp, count=0;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ cm_scache_t *tscp = cm_FindSCache(&patchp->fid);
+ int i;
+
+ if (tscp) {
+ if (lock_TryWrite(&tscp->rw)) {
+ /* we have an entry that we can look at */
+ 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)) {
dptr = patchp->dptr;
+ cm_ClientStrPrintfN(path, AFSPATHMAX, _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) {
if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
*dptr++ = SMB_ATTR_HIDDEN;
continue;
}
- lock_ObtainMutex(&scp->mx);
- code = cm_SyncOp(scp, NULL, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) {
- lock_ReleaseMutex(&scp->mx);
- cm_ReleaseSCache(scp);
- if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
- *dptr++ = SMB_ATTR_HIDDEN;
- continue;
- }
+ lock_ObtainWrite(&scp->rw);
+ if (mustFake || (scp->flags & CM_SCACHEFLAG_EACCESS) || !cm_HaveCallback(scp)) {
+ lock_ReleaseWrite(&scp->rw);
+
+ /* set the attribute */
+ switch (scp->fileType) {
+ case CM_SCACHETYPE_DIRECTORY:
+ case CM_SCACHETYPE_MOUNTPOINT:
+ case CM_SCACHETYPE_INVALID:
+ attr = SMB_ATTR_DIRECTORY;
+ break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ attr = SMB_ATTR_DIRECTORY;
+ else
+ attr = 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.
+ * 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))
+ attr = SMB_ATTR_DIRECTORY;
+ else
+ attr = SMB_ATTR_NORMAL;
+ }
+ *dptr++ = attr;
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ /* 1969-12-31 23:59:58 +00*/
+ dosTime = 0xEBBFBF7D;
- attr = smb_Attributes(scp);
- /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
- if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
- attr |= SMB_ATTR_HIDDEN;
- *dptr++ = attr;
+ /* copy out time */
+ shortTemp = (unsigned short) (dosTime & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* get dos time */
- smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+ /* and copy out date */
+ shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
- /* copy out time */
- shortTemp = (unsigned short) (dosTime & 0xffff);
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
-
- /* and copy out date */
- shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
- *((u_short *)dptr) = shortTemp;
- dptr += 2;
+ /* copy out file length */
+ *((u_long *)dptr) = 0;
+ dptr += 4;
+ } else {
+ lock_ConvertWToR(&scp->rw);
+ attr = smb_Attributes(scp);
+ /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
+ if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
+ attr |= SMB_ATTR_HIDDEN;
+ *dptr++ = attr;
+
+ /* get dos time */
+ smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
- /* copy out file length */
- *((u_long *)dptr) = scp->length.LowPart;
- dptr += 4;
- lock_ReleaseMutex(&scp->mx);
+ /* copy out time */
+ shortTemp = (unsigned short) (dosTime & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* and copy out date */
+ shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+ *((u_short *)dptr) = shortTemp;
+ dptr += 2;
+
+ /* copy out file length */
+ *((u_long *)dptr) = scp->length.LowPart;
+ dptr += 4;
+ lock_ReleaseRead(&scp->rw);
+ }
cm_ReleaseSCache(scp);
}
/* and mark the list as empty */
*dirPatchespp = NULL;
+ cleanup:
return code;
}
+/* SMB_COM_SEARCH */
long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
int attribute;
long nextCookie;
- char *tp;
+ unsigned char *tp;
long code = 0;
- char *pathp;
- cm_dirEntry_t *dep;
+ clientchar_t *pathp;
+ cm_dirEntry_t *dep = 0;
int maxCount;
smb_dirListPatch_t *dirListPatchesp;
smb_dirListPatch_t *curPatchp;
cm_pageHeader_t *pageHeaderp;
cm_user_t *userp = NULL;
int slotInPage;
- char shortName[13];
- char *actualName;
- char *shortNameEnd;
- char mask[11];
+ clientchar_t mask[12];
int returnedNames;
long nextEntryCookie;
int numDirChunks; /* # of 32 byte dir chunks in this entry */
int starPattern;
int rootPath = 0;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp = 0;
cm_req_t req;
cm_fid_t fid;
int fileType;
- cm_InitReq(&req);
+ smb_InitReq(&req);
maxCount = smb_GetSMBParm(inp, 0);
caseFold = CM_FLAG_CASEFOLD;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp,
+ SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
/* bail out if request looks bad */
if (attribute & 0x8)
return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
- osi_Log2(smb_logp, "SMB receive search dir count %d [%s]",
- maxCount, osi_LogSaveString(smb_logp, pathp));
+ osi_Log2(smb_logp, "SMB receive search dir count %d [%S]",
+ maxCount, osi_LogSaveClientString(smb_logp, pathp));
if (*pathp == 0) { /* null pathp, treat as root dir */
if (!(attribute & SMB_ATTR_DIRECTORY)) /* exclude dirs */
dsp = smb_NewDirSearch(0);
dsp->attribute = attribute;
smb_Get8Dot3MaskFromPath(mask, pathp);
- memcpy(dsp->mask, mask, 11);
+ memcpy(dsp->mask, mask, 12);
/* track if this is likely to match a lot of entries */
if (smb_IsStarMask(mask))
dsp = smb_FindDirSearch(inCookiep[12]);
if (!dsp) {
/* can't find dir search status; fatal error */
- osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%s]",
- inCookiep[12], nextCookie, osi_LogSaveString(smb_logp, pathp));
+ osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%S]",
+ inCookiep[12], nextCookie, osi_LogSaveClientString(smb_logp, pathp));
return CM_ERROR_BADFD;
}
attribute = dsp->attribute;
*/
memcpy(&clientCookie, &inCookiep[17], 4);
- memcpy(mask, dsp->mask, 11);
+ memcpy(mask, dsp->mask, 12);
/* assume we're doing a star match if it has continued for more
* than one call.
code = 0;
} else {
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, NULL, pathp);
+ smb_StripLastComponent(spacep->wdata, NULL, pathp);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
lock_ReleaseMutex(&dsp->mx);
smb_ReleaseDirSearch(dsp);
return CM_ERROR_NOFILES;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->data,
+ cm_ClientStrCpy(dsp->tidPath, lengthof(dsp->tidPath), tidPathp ? tidPathp : _C("/"));
+ cm_ClientStrCpy(dsp->relPath, lengthof(dsp->relPath), spacep->wdata);
+
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
if (code == 0) {
#ifdef DFS_SUPPORT
if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc;
+
+ pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->wdata);
cm_ReleaseSCache(scp);
lock_ReleaseMutex(&dsp->mx);
cm_ReleaseUser(userp);
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
- if ( WANTS_DFS_PATHNAMES(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
* now.
*/
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
- if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
- && LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
- scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags |= SMB_DIRSEARCH_BULKST;
- dsp->scp->bulkStatProgress = hzero;
- }
- lock_ReleaseMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
+ dsp->flags |= SMB_DIRSEARCH_BULKST;
+ lock_ReleaseWrite(&scp->rw);
}
}
lock_ReleaseMutex(&dsp->mx);
smb_SetSMBParm(outp, 0, 0);
/* 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_DeleteDirSearch(dsp);
code = 0;
returnedNames = 0;
while (1) {
+ clientchar_t *actualName;
+ clientchar_t shortName[13];
+ clientchar_t *shortNameEnd;
+
/* make sure that curOffset.LowPart doesn't point to the first
* 32 bytes in the 2nd through last dir page, and that it doesn't
* point at the first 13 32-byte chunks in the first dir page,
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_ApplyDirListPatches(&dirListPatchesp, userp, &req);
- lock_ObtainMutex(&scp->mx);
- if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
- LargeIntegerGreaterThanOrEqualTo(thyper,
- scp->bulkStatProgress)) {
- /* Don't bulk stat if risking timeout */
- int now = GetTickCount();
- if (now - req.startTime > RDRtimeout * 1000) {
- scp->bulkStatProgress = thyper;
- scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags &= ~SMB_DIRSEARCH_BULKST;
- dsp->scp->bulkStatProgress = hzero;
- } else
- code = cm_TryBulkStat(scp, &thyper, userp, &req);
- }
- } else {
- lock_ObtainMutex(&scp->mx);
- }
+ if (starPattern)
+ smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
+
+ lock_ObtainWrite(&scp->rw);
lock_ReleaseMutex(&dsp->mx);
if (code) {
osi_Log2(smb_logp, "SMB search dir buf_Get scp %x failed %d", scp, code);
nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
/* Compute 8.3 name if necessary */
- actualName = dep->name;
+ actualName = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
if (dep->fid.vnode != 0 && !cm_Is8Dot3(actualName)) {
- cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
+ free(actualName);
+ cm_Gen8Dot3NameInt(dep->name, &dep->fid, shortName, &shortNameEnd);
actualName = shortName;
}
- osi_Log3(smb_logp, "SMB search dir vn %d name %s (%s)",
- dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
- osi_LogSaveString(smb_logp, actualName));
+ osi_Log3(smb_logp, "SMB search dir vn %d name %s (%S)",
+ dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+ osi_LogSaveClientString(smb_logp, actualName));
if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
/* this is one of the entries to use: it is not deleted
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_ReceiveCoreSearchDir: file %s "
"has filetype %d", osi_LogSaveString(smb_logp, dep->name),
*op++ = resByte;
memcpy(op, mask, 11); op += 11;
- *op++ = (char) dsp->cookie; /* they say it must be non-zero */
- *op++ = (char)(nextEntryCookie & 0xff);
- *op++ = (char)((nextEntryCookie>>8) & 0xff);
- *op++ = (char)((nextEntryCookie>>16) & 0xff);
- *op++ = (char)((nextEntryCookie>>24) & 0xff);
+ *op++ = (unsigned char) dsp->cookie; /* they say it must be non-zero */
+ *op++ = (unsigned char)(nextEntryCookie & 0xff);
+ *op++ = (unsigned char)((nextEntryCookie>>8) & 0xff);
+ *op++ = (unsigned char)((nextEntryCookie>>16) & 0xff);
+ *op++ = (unsigned char)((nextEntryCookie>>24) & 0xff);
memcpy(op, &clientCookie, 4); op += 4;
/* now we emit the attribute. This is sort of tricky,
curPatchp = malloc(sizeof(*curPatchp));
osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
curPatchp->dptr = op;
- 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));
/* do hidden attribute here since name won't be around when applying
* dir list patches
* it fits in 8.3 or the pattern wouldn't match, but it
* never hurts to be sure.
*/
- strncpy(op, actualName, 13);
+ cm_ClientStringToUtf8(actualName, -1, op, 13);
if (smb_StoreAnsiFilenames)
CharToOem(op, op);
+ /* This is a UCHAR field, which is ASCII even if Unicode
+ is negotiated. */
/* Uppercase if requested by client */
if (!KNOWS_LONG_NAMES(inp))
} /* while copying data for dir listing */
/* 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.
*/
- smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+ smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
/* special return code for unsuccessful search */
if (code == 0 && dataLength < 21 && returnedNames == 0)
*/
temp -= 3; /* deduct vbl block info */
osi_assertx(temp == (43 * returnedNames), "unexpected data length");
- origOp[1] = (char)(temp & 0xff);
- origOp[2] = (char)((temp>>8) & 0xff);
+ origOp[1] = (unsigned char)(temp & 0xff);
+ origOp[2] = (unsigned char)((temp>>8) & 0xff);
if (returnedNames == 0)
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
return code;
}
+
/* verify that this is a valid path to a directory. I don't know why they
* don't use the get file attributes call.
+ *
+ * SMB_COM_CHECK_DIRECTORY
*/
long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ clientchar_t *pathp;
long code = 0;
cm_scache_t *rootScp;
cm_scache_t *newScp;
cm_user_t *userp;
unsigned int attrs;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_req_t req;
+ char * pdata;
- cm_InitReq(&req);
+ smb_InitReq(&req);
- pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ pdata = smb_GetSMBData(inp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, pdata, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADFD;
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
- osi_Log1(smb_logp, "SMB receive check path %s",
- osi_LogSaveString(smb_logp, pathp));
+ osi_Log1(smb_logp, "SMB receive check path %S",
+ osi_LogSaveClientString(smb_logp, pathp));
rootScp = cm_data.rootSCachep;
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
cm_ReleaseSCache(newScp);
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;
#endif /* DFS_SUPPORT */
/* now lock the vnode with a callback; returns with newScp locked */
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
if (code != CM_ERROR_NOACCESS) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
if (!(attrs & SMB_ATTR_DIRECTORY))
code = CM_ERROR_NOTDIR;
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
}
+/* SMB_COM_SET_INFORMATION */
long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ clientchar_t *pathp;
long code = 0;
cm_scache_t *rootScp;
unsigned short attribute;
afs_uint32 dosTime;
cm_user_t *userp;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
+ char * datap;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
/* decode basic attributes we're passed */
attribute = smb_GetSMBParm(inp, 0);
dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
- pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ datap = smb_GetSMBData(inp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADSMB;
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
dosTime, attribute);
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
cm_ReleaseSCache(newScp);
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;
* need the current status to determine what the new status is, in some
* cases.
*/
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
/* Check for RO volume */
if (newScp->flags & CM_SCACHEFLAG_RO) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return CM_ERROR_READONLY;
attr.unixModeBits = newScp->unixModeBits | 0222;
attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
}
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
/* now call setattr */
if (attr.mask)
return code;
}
+
long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ clientchar_t *pathp;
long code = 0;
cm_scache_t *rootScp;
cm_scache_t *newScp, *dscp;
int attrs;
cm_user_t *userp;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_space_t *spacep;
- char *lastComp;
+ clientchar_t *lastComp;
+ char * datap;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
- pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
+ datap = smb_GetSMBData(inp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
return CM_ERROR_BADSMB;
if (*pathp == 0) /* null path */
- pathp = "\\";
- else
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = _C("\\");
- osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
- osi_LogSaveString(smb_logp, pathp));
+ osi_Log1(smb_logp, "SMB receive getfile attributes path %S",
+ osi_LogSaveClientString(smb_logp, pathp));
rootScp = cm_data.rootSCachep;
* http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_extending/custom.asp
*/
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastComp, pathp);
+ smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
#ifndef SPECIAL_FOLDERS
- if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
- code = cm_NameI(rootScp, spacep->data,
+ if (lastComp && cm_ClientStrCmpIA(lastComp, _C("\\desktop.ini")) == 0) {
+ code = cm_NameI(rootScp, spacep->wdata,
caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code == 0) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
- if ( WANTS_DFS_PATHNAMES(inp) )
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,
+ spacep->wdata);
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
#ifdef DFS_SUPPORT
if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(newScp, tidPathp, pathp);
cm_ReleaseSCache(newScp);
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;
#endif /* DFS_SUPPORT */
/* now lock the vnode with a callback; returns with newScp locked */
- lock_ObtainMutex(&newScp->mx);
+ lock_ObtainWrite(&newScp->rw);
code = cm_SyncOp(newScp, NULL, userp, &req, 0,
CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
if (code) {
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return code;
cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-#ifdef undef
- /* use smb_Attributes instead. Also the fact that a file is
- * in a readonly volume doesn't mean it shojuld be marked as RO
- */
- if (newScp->fileType == CM_SCACHETYPE_DIRECTORY ||
- newScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
- newScp->fileType == CM_SCACHETYPE_INVALID)
- attrs = SMB_ATTR_DIRECTORY;
- else
- attrs = 0;
- if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
- attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
-#else
attrs = smb_Attributes(newScp);
-#endif
smb_SetSMBParm(outp, 0, attrs);
smb_SetSMBParm(outp, 8, 0);
smb_SetSMBParm(outp, 9, 0);
smb_SetSMBDataLength(outp, 0);
- lock_ReleaseMutex(&newScp->mx);
+ lock_ReleaseWrite(&newScp->rw);
cm_ReleaseSCache(newScp);
cm_ReleaseUser(userp);
return 0;
}
+/* SMB_COM_TREE_DISCONNECT */
long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
smb_tid_t *tidp;
tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
if (tidp) {
lock_ObtainWrite(&smb_rctLock);
- tidp->delete = 1;
+ tidp->deleteOk = 1;
+ smb_ReleaseTID(tidp, TRUE);
lock_ReleaseWrite(&smb_rctLock);
- smb_ReleaseTID(tidp);
}
return 0;
}
+/* SMB_COM_0PEN */
long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
smb_fid_t *fidp;
- char *pathp;
- char *lastNamep;
+ clientchar_t *pathp;
+ clientchar_t *lastNamep;
int share;
int attribute;
long code = 0;
afs_uint32 dosTime;
int caseFold;
cm_space_t *spacep;
- char *tidPathp;
+ clientchar_t *tidPathp;
+ char * datap;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
- pathp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(pathp, NULL);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
-
- osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
+ datap = smb_GetSMBData(inp, NULL);
+ pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
+
+ osi_Log1(smb_logp, "SMB receive open file [%S]", osi_LogSaveClientString(smb_logp, pathp));
#ifdef DEBUG_VERBOSE
{
attribute = smb_GetSMBParm(inp, 1);
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastNamep, pathp);
- if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+ smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ if (lastNamep && cm_ClientStrCmp(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
*/
#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(inp) )
+ if ( WANTS_DFS_PATHNAMES(inp) || pnc )
return CM_ERROR_PATH_NOT_COVERED;
else
return CM_ERROR_BADSHARENAME;
/* save a pointer to the vnode */
fidp->scp = scp;
osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, 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 */
cm_HoldUser(userp);
fidp->flags |= (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainRead(&scp->rw);
smb_SetSMBParm(outp, 0, fidp->fid);
smb_SetSMBParm(outp, 1, smb_Attributes(scp));
smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
/* pass the open mode back; XXXX add access checks */
smb_SetSMBParm(outp, 6, (share & 0xf));
smb_SetSMBDataLength(outp, 0);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseRead(&scp->rw);
/* notify open */
cm_Open(scp, 0, userp);
cm_user_t *userp;
cm_req_t *reqp;
smb_vc_t *vcp;
- char *maskp; /* pointer to the star pattern */
+ clientchar_t *maskp; /* pointer to the star pattern */
int flags;
int any;
cm_dirEntryList_t * matches;
smb_unlinkRock_t *rockp;
int caseFold;
int match;
- char shortName[13];
- char *matchName;
+ normchar_t matchName[MAX_PATH];
rockp = vrockp;
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- matchName = dep->name;
- match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+ cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ match = cm_MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
- (rockp->flags & SMB_MASKFLAG_TILDE) &&
- !cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- matchName = shortName;
+ (rockp->flags & SMB_MASKFLAG_TILDE) &&
+ !cm_Is8Dot3(matchName)) {
+ cm_Gen8Dot3Name(dep, matchName, NULL);
/* 8.3 matches are always case insensitive */
- match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
+ match = cm_MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
}
if (match) {
- osi_Log1(smb_logp, "Found match %s",
- osi_LogSaveString(smb_logp, matchName));
+ osi_Log1(smb_logp, "Found match %S",
+ osi_LogSaveClientString(smb_logp, matchName));
cm_DirEntryListAdd(dep->name, &rockp->matches);
- rockp->any = 1;
+ rockp->any = 1;
- /* If we made a case sensitive exact match, we might as well quit now. */
- if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
- code = CM_ERROR_STOPNOW;
+ /* If we made a case sensitive exact match, we might as well quit now. */
+ if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !cm_ClientStrCmp(matchName, rockp->maskp))
+ code = CM_ERROR_STOPNOW;
else
code = 0;
}
return code;
}
+/* SMB_COM_DELETE */
long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
int attribute;
long code = 0;
- char *pathp;
- char *tp;
+ clientchar_t *pathp;
+ unsigned char *tp;
cm_space_t *spacep;
cm_scache_t *dscp;
- char *lastNamep;
+ clientchar_t *lastNamep;
smb_unlinkRock_t rock;
cm_user_t *userp;
osi_hyper_t thyper;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
attribute = smb_GetSMBParm(inp, 0);
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
- osi_Log1(smb_logp, "SMB receive unlink %s",
- osi_LogSaveString(smb_logp, pathp));
+ osi_Log1(smb_logp, "SMB receive unlink %S",
+ osi_LogSaveClientString(smb_logp, pathp));
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+ smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
userp = smb_GetUserFromVCP(vcp, inp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold, userp, tidPathp,
&req, &dscp);
if (code) {
cm_ReleaseUser(userp);
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
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;
lastNamep++;
rock.any = 0;
- rock.maskp = smb_FindMask(pathp);
- rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+ rock.maskp = cm_ClientStringToNormStringAlloc(smb_FindMask(pathp), -1, NULL);
+ rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
thyper.HighPart = 0;
cm_dirEntryList_t * entry;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+ normchar_t normalizedName[MAX_PATH];
+
+ /* Note: entry->name is a non-normalized name */
osi_Log1(smb_logp, "Unlinking %s",
osi_LogSaveString(smb_logp, entry->name));
- code = cm_Unlink(dscp, entry->name, userp, &req);
+
+ cm_FsStringToNormString(entry->name, -1,
+ normalizedName, lengthof(normalizedName));
+
+ code = cm_Unlink(dscp, entry->name, normalizedName, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
- dscp, entry->name, NULL, TRUE);
+ dscp, normalizedName, NULL, TRUE);
}
}
cm_ReleaseSCache(dscp);
+ free(rock.maskp);
+
if (code == 0 && !rock.any)
code = CM_ERROR_NOSUCHFILE;
return code;
}
typedef struct smb_renameRock {
- cm_scache_t *odscp; /* old dir */
- cm_scache_t *ndscp; /* new dir */
- cm_user_t *userp; /* user */
- cm_req_t *reqp; /* request struct */
- smb_vc_t *vcp; /* virtual circuit */
- char *maskp; /* pointer to star pattern of old file name */
- int flags; /* tilde, casefold, etc */
- char *newNamep; /* ptr to the new file's name */
- char oldName[MAX_PATH];
+ cm_scache_t *odscp; /* old dir */
+ cm_scache_t *ndscp; /* new dir */
+ cm_user_t *userp; /* user */
+ cm_req_t *reqp; /* request struct */
+ smb_vc_t *vcp; /* virtual circuit */
+ normchar_t *maskp; /* pointer to star pattern of old file name */
+ int flags; /* tilde, casefold, etc */
+ clientchar_t *newNamep; /* ptr to the new file's name */
+ fschar_t fsOldName[MAX_PATH]; /* raw FS name */
+ clientchar_t clOldName[MAX_PATH]; /* client name */
int any;
} smb_renameRock_t;
smb_renameRock_t *rockp;
int caseFold;
int match;
- char shortName[13]="";
+ normchar_t matchName[MAX_PATH];
rockp = (smb_renameRock_t *) vrockp;
+ cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
+ match = cm_MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
- !cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
+ !cm_Is8Dot3(matchName)) {
+ cm_Gen8Dot3Name(dep, matchName, NULL);
+ match = cm_MatchMask(matchName, rockp->maskp, caseFold);
}
if (match) {
rockp->any = 1;
- strncpy(rockp->oldName, dep->name, sizeof(rockp->oldName)/sizeof(char) - 1);
- rockp->oldName[sizeof(rockp->oldName)/sizeof(char) - 1] = '\0';
- code = CM_ERROR_STOPNOW;
+ StringCbCopyA(rockp->fsOldName, sizeof(rockp->fsOldName), dep->name);
+ cm_ClientStrCpy(rockp->clOldName, lengthof(rockp->clOldName),
+ matchName);
+ code = CM_ERROR_STOPNOW;
} else {
code = 0;
}
long
-smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, int attrs)
+smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t * newPathp, int attrs)
{
long code = 0;
cm_space_t *spacep = NULL;
cm_scache_t *newDscp = NULL;
cm_scache_t *tmpscp= NULL;
cm_scache_t *tmpscp2 = NULL;
- char *oldLastNamep;
- char *newLastNamep;
+ clientchar_t *oldLastNamep;
+ clientchar_t *newLastNamep;
osi_hyper_t thyper;
cm_user_t *userp;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
DWORD filter;
cm_req_t req;
return CM_ERROR_NOSUCHPATH;
}
- cm_InitReq(&req);
+ smb_InitReq(&req);
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
+ smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
userp, tidPathp, &req, &oldDscp);
if (code) {
cm_ReleaseUser(userp);
#ifdef DFS_SUPPORT
if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->wdata);
cm_ReleaseSCache(oldDscp);
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;
}
#endif /* DFS_SUPPORT */
- smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+ smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
#ifdef DFS_SUPPORT
if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->wdata);
cm_ReleaseSCache(oldDscp);
cm_ReleaseSCache(newDscp);
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;
rock.userp = userp;
rock.reqp = &req;
rock.vcp = vcp;
- rock.maskp = oldLastNamep;
- rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+ rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
+ rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
rock.newNamep = newLastNamep;
- rock.oldName[0] = '\0';
+ rock.fsOldName[0] = '\0';
+ rock.clOldName[0] = '\0';
rock.any = 0;
/* Check if the file already exists; if so return error */
if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) &&
(code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) )
{
- osi_Log2(smb_logp, " lookup returns %ld for [%s]", code,
- osi_LogSaveString(smb_logp, newLastNamep));
+ osi_Log2(smb_logp, " lookup returns %ld for [%S]", code,
+ osi_LogSaveClientString(smb_logp, newLastNamep));
/* Check if the old and the new names differ only in case. If so return
* success, else return CM_ERROR_EXISTS
*/
- if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+ if (!code && oldDscp == newDscp && !cm_ClientStrCmpI(oldLastNamep, newLastNamep)) {
/* This would be a success only if the old file is *as same as* the new file */
code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
cm_ReleaseSCache(newDscp);
cm_ReleaseSCache(oldDscp);
cm_ReleaseUser(userp);
+
+ free(rock.maskp);
+ rock.maskp = NULL;
return code;
}
}
osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
- if (code == CM_ERROR_STOPNOW && rock.oldName[0] != '\0') {
- code = cm_Rename(rock.odscp, rock.oldName,
+ if (code == CM_ERROR_STOPNOW && rock.fsOldName[0] != '\0') {
+ code = cm_Rename(rock.odscp, rock.fsOldName, rock.clOldName,
rock.ndscp, rock.newNamep, rock.userp,
- rock.reqp);
+ rock.reqp);
/* if the call worked, stop doing the search now, since we
* really only want to rename one file.
*/
+ if (code)
+ osi_Log0(smb_logp, "cm_Rename failure");
osi_Log1(smb_logp, "cm_Rename returns %ld", code);
} else if (code == 0) {
code = CM_ERROR_NOSUCHFILE;
if (oldDscp == newDscp) {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
- filter, oldDscp, oldLastNamep,
- newLastNamep, TRUE);
+ filter, oldDscp, rock.clOldName,
+ newLastNamep, TRUE);
} else {
if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
- filter, oldDscp, oldLastNamep,
+ filter, oldDscp, rock.clOldName,
NULL, TRUE);
if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME,
- filter, newDscp, newLastNamep,
- NULL, TRUE);
+ filter, newDscp, newLastNamep,
+ NULL, TRUE);
}
}
cm_ReleaseUser(userp);
cm_ReleaseSCache(oldDscp);
cm_ReleaseSCache(newDscp);
+
+ free(rock.maskp);
+ rock.maskp = NULL;
+
return code;
}
long
-smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
+smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t * newPathp)
{
long code = 0;
cm_space_t *spacep = NULL;
cm_scache_t *tmpscp= NULL;
cm_scache_t *tmpscp2 = NULL;
cm_scache_t *sscp = NULL;
- char *oldLastNamep;
- char *newLastNamep;
+ clientchar_t *oldLastNamep;
+ clientchar_t *newLastNamep;
cm_user_t *userp;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
DWORD filter;
cm_req_t req;
return CM_ERROR_NOSUCHPATH;
}
- cm_InitReq(&req);
+ smb_InitReq(&req);
caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
+ smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
userp, tidPathp, &req, &oldDscp);
if (code) {
cm_ReleaseUser(userp);
#ifdef DFS_SUPPORT
if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->wdata);
cm_ReleaseSCache(oldDscp);
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;
}
#endif /* DFS_SUPPORT */
- smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+ smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
userp, tidPathp, &req, &newDscp);
if (code) {
cm_ReleaseSCache(oldDscp);
#ifdef DFS_SUPPORT
if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->wdata);
cm_ReleaseSCache(newDscp);
cm_ReleaseSCache(oldDscp);
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;
newLastNamep++;
/* now lookup the old name */
- osi_Log1(smb_logp," looking up [%s]", osi_LogSaveString(smb_logp,oldLastNamep));
+ osi_Log1(smb_logp," looking up [%S]", osi_LogSaveClientString(smb_logp,oldLastNamep));
code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH | CM_FLAG_CASEFOLD, userp, &req, &sscp);
if (code) {
cm_ReleaseSCache(oldDscp);
if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) &&
(code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) )
{
- osi_Log2(smb_logp, " lookup returns %ld for [%s]", code,
- osi_LogSaveString(smb_logp, newLastNamep));
+ osi_Log2(smb_logp, " lookup returns %ld for [%S]", code,
+ osi_LogSaveClientString(smb_logp, newLastNamep));
/* if the existing link is to the same file, then we return success */
if (!code) {
}
/* now create the hardlink */
- osi_Log1(smb_logp," Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep));
+ osi_Log1(smb_logp," Attempting to create new link [%S]", osi_LogSaveClientString(smb_logp, newLastNamep));
code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req);
osi_Log1(smb_logp," Link returns 0x%x", code);
return code;
}
+/* SMB_COM_RENAME */
long
smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *oldPathp;
- char *newPathp;
- char *tp;
+ clientchar_t *oldPathp;
+ clientchar_t *newPathp;
+ unsigned char *tp;
long code;
tp = smb_GetSMBData(inp, NULL);
- oldPathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(oldPathp,oldPathp);
- newPathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(newPathp,newPathp);
+ oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
- osi_Log2(smb_logp, "smb rename [%s] to [%s]",
- osi_LogSaveString(smb_logp, oldPathp),
- osi_LogSaveString(smb_logp, newPathp));
+ osi_Log2(smb_logp, "smb rename [%S] to [%S]",
+ osi_LogSaveClientString(smb_logp, oldPathp),
+ osi_LogSaveClientString(smb_logp, newPathp));
code = smb_Rename(vcp,inp,oldPathp,newPathp,0);
cm_scache_t *dscp;
cm_user_t *userp;
cm_req_t *reqp;
- char *maskp; /* pointer to the star pattern */
+ normchar_t *maskp; /* pointer to the star pattern */
int flags;
int any;
cm_dirEntryList_t * matches;
long code = 0;
smb_rmdirRock_t *rockp;
int match;
- char shortName[13];
- char *matchName;
+ normchar_t matchName[MAX_PATH];
rockp = (smb_rmdirRock_t *) vrockp;
- matchName = dep->name;
+ cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
- match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
else
- match = (strcmp(matchName, rockp->maskp) == 0);
+ match = (cm_ClientStrCmp(matchName, rockp->maskp) == 0);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
- !cm_Is8Dot3(dep->name)) {
- cm_Gen8Dot3Name(dep, shortName, NULL);
- matchName = shortName;
- match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ !cm_Is8Dot3(matchName)) {
+ cm_Gen8Dot3Name(dep, matchName, NULL);
+ match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
}
if (match) {
- rockp->any = 1;
+ rockp->any = 1;
cm_DirEntryListAdd(dep->name, &rockp->matches);
}
return 0;
}
+
long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
- char *pathp;
- char *tp;
+ clientchar_t *pathp;
+ unsigned char *tp;
cm_space_t *spacep;
cm_scache_t *dscp;
- char *lastNamep;
+ clientchar_t *lastNamep;
smb_rmdirRock_t rock;
cm_user_t *userp;
osi_hyper_t thyper;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+ smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
userp = smb_GetUserFromVCP(vcp, inp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
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;
lastNamep++;
rock.any = 0;
- rock.maskp = lastNamep;
- rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+ rock.maskp = cm_ClientStringToNormStringAlloc(lastNamep, -1, NULL);
+ rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
thyper.HighPart = 0;
cm_dirEntryList_t * entry;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+ clientchar_t clientName[MAX_PATH];
+
+ cm_FsStringToClientString(entry->name, -1, clientName, lengthof(clientName));
+
osi_Log1(smb_logp, "Removing directory %s",
osi_LogSaveString(smb_logp, entry->name));
- code = cm_RemoveDir(dscp, entry->name, userp, &req);
+ code = cm_RemoveDir(dscp, entry->name, clientName, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
- dscp, entry->name, NULL, TRUE);
+ dscp, clientName, NULL, TRUE);
}
}
if (code == 0 && !rock.any)
code = CM_ERROR_NOSUCHFILE;
+
+ free(rock.maskp);
+ rock.maskp = NULL;
+
return code;
}
+/* SMB_COM_FLUSH */
long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fid;
long code = 0;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = smb_GetSMBParm(inp, 0);
userp = smb_GetUserFromVCP(vcp, inp);
lock_ObtainMutex(&fidp->mx);
- if (fidp->flags & SMB_FID_OPENWRITE) {
+ if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
cm_scache_t * scp = fidp->scp;
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
}
struct smb_FullNameRock {
- char *name;
- cm_scache_t *vnode;
- char *fullName;
+ clientchar_t *name;
+ cm_scache_t *vnode;
+ clientchar_t *fullName;
+ fschar_t *originalName;
};
int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
osi_hyper_t *offp)
{
- char shortName[13];
+ normchar_t matchName[MAX_PATH];
struct smb_FullNameRock *vrockp;
vrockp = (struct smb_FullNameRock *)rockp;
- if (!cm_Is8Dot3(dep->name)) {
+ cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+
+ if (!cm_Is8Dot3(matchName)) {
+ clientchar_t shortName[13];
+
cm_Gen8Dot3Name(dep, shortName, NULL);
- if (cm_stricmp(shortName, vrockp->name) == 0) {
- vrockp->fullName = strdup(dep->name);
+ if (cm_ClientStrCmpIA(shortName, vrockp->name) == 0) {
+ vrockp->fullName = cm_ClientStrDup(matchName);
+ vrockp->originalName = cm_FsStrDup(dep->name);
return CM_ERROR_STOPNOW;
}
}
- if (cm_stricmp(dep->name, vrockp->name) == 0 &&
+ if (cm_ClientStrCmpI(matchName, vrockp->name) == 0 &&
ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode &&
ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
- vrockp->fullName = strdup(dep->name);
+ vrockp->fullName = cm_ClientStrDup(matchName);
+ vrockp->originalName = cm_FsStrDup(dep->name);
return CM_ERROR_STOPNOW;
}
return 0;
}
-void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
- char **newPathp, cm_user_t *userp, cm_req_t *reqp)
+void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, clientchar_t *pathp,
+ clientchar_t **newPathp, fschar_t ** originalPathp,
+ cm_user_t *userp, cm_req_t *reqp)
{
struct smb_FullNameRock rock;
long code = 0;
+ memset(&rock, 0, sizeof(rock));
rock.name = pathp;
rock.vnode = scp;
code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL);
- if (code == CM_ERROR_STOPNOW)
+ if (code == CM_ERROR_STOPNOW) {
*newPathp = rock.fullName;
- else
- *newPathp = strdup(pathp);
+ *originalPathp = rock.originalName;
+ } else {
+ *newPathp = cm_ClientStrDup(pathp);
+ *originalPathp = cm_ClientStringToFsStringAlloc(pathp, -1, NULL);
+ }
}
long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
long code = 0;
cm_req_t req;
cm_scache_t *dscp = NULL;
- char *pathp = NULL;
+ clientchar_t *pathp = NULL;
cm_scache_t * scp = NULL;
cm_scache_t *delscp = NULL;
- int deleted = 0;
int nullcreator = 0;
osi_Log4(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d scp=0x%x vcp=0x%x)",
lock_ReleaseMutex(&fidp->mx);
}
- cm_InitReq(&req);
+ smb_InitReq(&req);
lock_ObtainWrite(&smb_rctLock);
- if (fidp->delete) {
+ if (fidp->deleteOk) {
osi_Log0(smb_logp, " Fid already closed.");
lock_ReleaseWrite(&smb_rctLock);
return CM_ERROR_BADFD;
}
- fidp->delete = 1;
+ fidp->deleteOk = 1;
lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
}
if (fidp->NTopen_pathp) {
- pathp = strdup(fidp->NTopen_pathp);
+ pathp = cm_ClientStrDup(fidp->NTopen_pathp);
}
if (fidp->scp) {
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
}
- lock_ReleaseMutex(&fidp->mx);
- code = cm_FSync(scp, userp, &req);
- lock_ObtainMutex(&fidp->mx);
+ if (smb_AsyncStore != 2) {
+ lock_ReleaseMutex(&fidp->mx);
+ code = cm_FSync(scp, userp, &req);
+ lock_ObtainMutex(&fidp->mx);
+ }
}
else
code = 0;
/* CM_UNLOCK_BY_FID doesn't look at the process ID. We pass
in zero. */
key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
post_syncopdone:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&fidp->mx);
}
if (fidp->flags & SMB_FID_DELONCLOSE) {
- char *fullPathp;
+ clientchar_t *fullPathp = NULL;
+ fschar_t *originalNamep = NULL;
lock_ReleaseMutex(&fidp->mx);
cm_HoldSCache(scp);
delscp = scp;
}
- smb_FullName(dscp, delscp, pathp, &fullPathp, userp, &req);
+ smb_FullName(dscp, delscp, pathp, &fullPathp, &originalNamep, userp, &req);
if (delscp->fileType == CM_SCACHETYPE_DIRECTORY) {
- code = cm_RemoveDir(dscp, fullPathp, userp, &req);
+ code = cm_RemoveDir(dscp, originalNamep, fullPathp, userp, &req);
if (code == 0) {
- deleted = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
dscp, fullPathp, NULL, TRUE);
}
} else {
- code = cm_Unlink(dscp, fullPathp, userp, &req);
+ code = cm_Unlink(dscp, originalNamep, fullPathp, userp, &req);
if (code == 0) {
- deleted = 1;
if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
dscp, fullPathp, NULL, TRUE);
}
}
- free(fullPathp);
+
+ if (fullPathp)
+ free(fullPathp);
+ if (originalNamep)
+ free(originalNamep);
+
lock_ObtainMutex(&fidp->mx);
fidp->flags &= ~SMB_FID_DELONCLOSE;
}
cm_ReleaseSCache(dscp);
if (delscp) {
- if (deleted) {
- lock_ObtainMutex(&delscp->mx);
- if (deleted)
- delscp->flags |= CM_SCACHEFLAG_DELETED;
- lock_ReleaseMutex(&delscp->mx);
- }
cm_ReleaseSCache(delscp);
}
if (scp) {
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (nullcreator && scp->creator == userp)
scp->creator = NULL;
scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
}
return code;
}
+/* SMB_COM_CLOSE */
long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fid;
/*
* smb_ReadData -- common code for Read, Read And X, and Raw Read
*/
-long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
cm_user_t *userp, long *readp)
{
osi_hyper_t offset;
osi_hyper_t thyper;
osi_hyper_t lastByte;
osi_hyper_t bufferOffset;
- long bufIndex, nbytes;
+ long bufIndex;
+ afs_uint32 nbytes;
int chunk;
int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
cm_req_t req;
- cm_InitReq(&req);
+ osi_Log3(smb_logp, "smb_ReadData fid %d, off 0x%x, size 0x%x",
+ fidp->fid, offsetp->LowPart, count);
+
+ *readp = 0;
+
+ lock_ObtainMutex(&fidp->mx);
+ /* make sure we have a readable FD */
+ if (!(fidp->flags & SMB_FID_OPENREAD_LISTDIR)) {
+ osi_Log2(smb_logp, "smb_ReadData fid %d not OPENREAD_LISTDIR flags 0x%x",
+ fidp->fid, fidp->flags);
+ lock_ReleaseMutex(&fidp->mx);
+ code = CM_ERROR_BADFDOP;
+ goto done2;
+ }
+
+ smb_InitReq(&req);
bufferp = NULL;
offset = *offsetp;
- lock_ObtainMutex(&fidp->mx);
scp = fidp->scp;
cm_HoldSCache(scp);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (offset.HighPart == 0) {
chunk = offset.LowPart >> cm_logChunkSize;
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) goto done;
bufferOffset = thyper;
} /* while 1 */
done:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp)
buf_Release(bufferp);
if (code == 0 && sequential)
- cm_ConsiderPrefetch(scp, &lastByte, userp, &req);
+ cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req);
cm_ReleaseSCache(scp);
+ done2:
+ osi_Log3(smb_logp, "smb_ReadData fid %d returns 0x%x read %d bytes",
+ fidp->fid, code, *readp);
return code;
}
/*
* smb_WriteData -- common code for Write and Raw Write
*/
-long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
cm_user_t *userp, long *writtenp)
{
- osi_hyper_t offset;
+ osi_hyper_t offset = *offsetp;
long code = 0;
long written = 0;
- cm_scache_t *scp;
+ cm_scache_t *scp = NULL;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
afs_uint32 nbytes; /* # of bytes to transfer this iteration */
- cm_buf_t *bufferp;
+ cm_buf_t *bufferp = NULL;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
afs_uint32 bufIndex; /* index in buffer where our data is */
- int doWriteBack;
- osi_hyper_t writeBackOffset;/* offset of region to write back when
- * I/O is done */
+ int doWriteBack = 0;
+ osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
DWORD filter = 0;
cm_req_t req;
*writtenp = 0;
- cm_InitReq(&req);
-
- bufferp = NULL;
- doWriteBack = 0;
- offset = *offsetp;
-
lock_ObtainMutex(&fidp->mx);
/* make sure we have a writable FD */
if (!(fidp->flags & SMB_FID_OPENWRITE)) {
fidp->fid, fidp->flags);
lock_ReleaseMutex(&fidp->mx);
code = CM_ERROR_BADFDOP;
- goto done;
+ goto done2;
}
+ smb_InitReq(&req);
+
scp = fidp->scp;
cm_HoldSCache(scp);
lock_ReleaseMutex(&fidp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK
/* now, if the new position (thyper) and the old (offset) are in
* different storeback windows, remember to store back the previous
* storeback window when we're done with the write.
+ *
+ * the purpose of this logic is to slow down the CIFS client
+ * in order to avoid the client disconnecting during the CLOSE
+ * operation if there are too many dirty buffers left to write
+ * than can be accomplished during 45 seconds. This used to be
+ * based upon cm_chunkSize but we desire cm_chunkSize to be large
+ * so that we can read larger amounts of data at a time.
*/
- if ((thyper.LowPart & (-cm_chunkSize)) !=
- (offset.LowPart & (-cm_chunkSize))) {
+ if (smb_AsyncStore == 1 &&
+ (thyper.LowPart & ~(smb_AsyncStoreSize-1)) !=
+ (offset.LowPart & ~(smb_AsyncStoreSize-1))) {
/* they're different */
doWriteBack = 1;
writeBackOffset.HighPart = offset.HighPart;
- writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
+ writeBackOffset.LowPart = offset.LowPart & ~(smb_AsyncStoreSize-1);
}
-
+
*writtenp = count;
/* now, copy the data one buffer at a time, until we've filled the
buf_Release(bufferp);
bufferp = NULL;
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
- lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ReleaseRead(&scp->bufCreateLock);
lock_ObtainMutex(&bufferp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) goto done;
bufferOffset = thyper;
ConvertLongToLargeInteger(count)),
minLength))) {
if (count < cm_data.buf_blockSize
- && bufferp->dataVersion == -1)
+ && bufferp->dataVersion == CM_BUF_VERSION_BAD)
memset(bufferp->datap, 0,
cm_data.buf_blockSize);
bufferp->dataVersion = scp->dataVersion;
lock_ReleaseMutex(&bufferp->mx);
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
lock_ObtainMutex(&bufferp->mx);
- lock_ObtainMutex(&scp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) break;
}
if (code) {
/* now copy the data */
memcpy(bufferp->datap + bufIndex, op, nbytes);
- buf_SetDirty(bufferp, bufIndex, nbytes);
-
- /* and record the last writer */
- if (bufferp->userp != userp) {
- cm_HoldUser(userp);
- if (bufferp->userp)
- cm_ReleaseUser(bufferp->userp);
- bufferp->userp = userp;
- }
+ buf_SetDirty(bufferp, bufIndex, nbytes, userp);
/* adjust counters, pointers, etc. */
op += nbytes;
} /* while 1 */
done:
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
if (bufferp) {
lock_ReleaseMutex(&bufferp->mx);
lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
- && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
+ && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ {
+ lock_ReleaseMutex(&fidp->mx);
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
fidp->NTopen_dscp, fidp->NTopen_pathp,
NULL, TRUE);
- }
- lock_ReleaseMutex(&fidp->mx);
+ } else {
+ lock_ReleaseMutex(&fidp->mx);
+ }
- if (code == 0 && doWriteBack) {
- long code2;
- lock_ObtainMutex(&scp->mx);
- osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
- fidp->fid);
- code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
- osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
- fidp->fid, code2);
- lock_ReleaseMutex(&scp->mx);
- cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
- writeBackOffset.HighPart, cm_chunkSize, 0, userp);
- /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+ if (code == 0) {
+ if (smb_AsyncStore > 0) {
+ if (doWriteBack) {
+ long code2;
+
+ lock_ObtainWrite(&scp->rw);
+ osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
+ fidp->fid);
+ code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
+ osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
+ fidp->fid, code2);
+ lock_ReleaseWrite(&scp->rw);
+ cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
+ writeBackOffset.HighPart,
+ smb_AsyncStoreSize, 0, userp);
+ /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+ }
+ } else {
+ cm_BufWrite(scp, offsetp, *writtenp, 0, userp, &req);
+ }
}
cm_ReleaseSCache(scp);
+ done2:
osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
fidp->fid, code, *writtenp);
return code;
}
+/* SMB_COM_WRITE */
long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
unsigned short fd;
long written = 0, total_written = 0;
unsigned pid;
smb_fid_t *fidp;
+ smb_t* smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
cm_attr_t truncAttr; /* attribute struct used for truncating file */
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = offset.HighPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
if (code) {
osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
osi_Log1(smb_logp, "smb_ReceiveCoreWrite truncation to length 0x%x", offset.LowPart);
- cm_InitReq(&req);
+ smb_InitReq(&req);
truncAttr.mask = CM_ATTRMASK_LENGTH;
truncAttr.length.LowPart = offset.LowPart;
return 0;
}
+/* SMB_COM_WRITE_RAW */
long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, raw_write_cont_t *rwcp)
{
osi_hyper_t offset;
long totalCount;
unsigned short fd;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
char *op;
LARGE_INTEGER LOffset;
LARGE_INTEGER LLength;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = offset.HighPart;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
if (code) {
smb_ReleaseFID(fidp);
return 0;
}
+/* SMB_COM_READ */
long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
osi_hyper_t offset;
unsigned short fd;
unsigned pid;
smb_fid_t *fidp;
+ smb_t *smbp = (smb_t*) inp;
long code = 0;
cm_user_t *userp;
char *op;
LARGE_INTEGER LOffset, LLength;
cm_key_t key;
- pid = ((smb_t *) inp)->pid;
+ pid = smbp->pid;
key = cm_GenerateKey(vcp->vcID, pid, fd);
LOffset.HighPart = 0;
LLength.HighPart = 0;
LLength.LowPart = count;
- lock_ObtainMutex(&fidp->scp->mx);
+ lock_ObtainWrite(&fidp->scp->rw);
code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
- lock_ReleaseMutex(&fidp->scp->mx);
+ lock_ReleaseWrite(&fidp->scp->rw);
}
if (code) {
smb_ReleaseFID(fidp);
return code;
}
+/* SMB_COM_CREATE_DIRECTORY */
long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ clientchar_t *pathp;
long code = 0;
cm_space_t *spacep;
- char *tp;
+ unsigned char *tp;
cm_user_t *userp;
cm_scache_t *dscp; /* dir we're dealing with */
cm_scache_t *scp; /* file we're creating */
cm_attr_t setAttr;
int initialModeBits;
- char *lastNamep;
+ clientchar_t *lastNamep;
int caseFold;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
scp = NULL;
initialModeBits = 0777;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
- if (strcmp(pathp, "\\") == 0)
+ if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
return CM_ERROR_EXISTS;
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+ smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
userp = smb_GetUserFromVCP(vcp, inp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->data,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
userp, tidPathp, &req, &dscp);
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
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;
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
- code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
+ code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_DIR_NAME,
return 0;
}
-BOOL smb_IsLegalFilename(char *filename)
+BOOL smb_IsLegalFilename(clientchar_t *filename)
{
/*
* Find the longest substring of filename that does not contain
* than the length of the whole string, then one or more of the
* illegal chars is in filename.
*/
- if (strcspn(filename, illegalChars) < strlen(filename))
+ if (cm_ClientStrCSpn(filename, illegalChars) < cm_ClientStrLen(filename))
return FALSE;
return TRUE;
-}
+}
+/* SMB_COM_CREATE and SMB_COM_CREATE_NEW */
long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
- char *pathp;
+ clientchar_t *pathp;
long code = 0;
cm_space_t *spacep;
- char *tp;
+ unsigned char *tp;
int excl;
cm_user_t *userp;
cm_scache_t *dscp; /* dir we're dealing with */
int initialModeBits;
smb_fid_t *fidp;
int attributes;
- char *lastNamep;
+ clientchar_t *lastNamep;
int caseFold;
afs_uint32 dosTime;
- char *tidPathp;
+ clientchar_t *tidPathp;
cm_req_t req;
int created = 0; /* the file was new */
- cm_InitReq(&req);
+ smb_InitReq(&req);
scp = NULL;
excl = (inp->inCom == 0x03)? 0 : 1;
initialModeBits &= ~0222;
tp = smb_GetSMBData(inp, NULL);
- pathp = smb_ParseASCIIBlock(tp, &tp);
- if (smb_StoreAnsiFilenames)
- OemToChar(pathp,pathp);
+ pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
spacep = inp->spacep;
- smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+ smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
userp = smb_GetUserFromVCP(vcp, inp);
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
- code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+ code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
userp, tidPathp, &req, &dscp);
if (code) {
#ifdef DFS_SUPPORT
if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+ int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
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;
if (!smb_IsLegalFilename(lastNamep))
return CM_ERROR_BADNTFILENAME;
- osi_Log1(smb_logp, "SMB receive create [%s]", osi_LogSaveString( smb_logp, pathp ));
+ osi_Log1(smb_logp, "SMB receive create [%S]", osi_LogSaveClientString( smb_logp, pathp ));
#ifdef DEBUG_VERBOSE
{
char *hexp;
/* 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);
/* and the user */
fidp->userp = userp;
return 0;
}
+/* SMB_COM_SEEK */
long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
long code = 0;
cm_user_t *userp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fd = smb_GetSMBParm(inp, 0);
whence = smb_GetSMBParm(inp, 1);
scp = 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 == 0) {
smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
smb_SetSMBDataLength(outp, 0);
}
- lock_ReleaseMutex(&scp->mx);
+ lock_ReleaseWrite(&scp->rw);
smb_ReleaseFID(fidp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (dp->procp) {
/* we have a recognized operation */
+ char * opName = myCrt_Dispatch(inp->inCom);
if (inp->inCom == 0x1d)
/* Raw Write */
code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
else {
- osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",
+ opName,vcp,vcp->lana,vcp->lsn);
code = (*(dp->procp)) (vcp, inp, outp);
- osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d",code,vcp,vcp->lana,vcp->lsn);
+ osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d",
+ code,vcp,vcp->lana,vcp->lsn);
#ifdef LOG_PACKET
if ( code == CM_ERROR_BADSMB ||
code == CM_ERROR_BADOP )
- smb_LogPacket(inp);
+ smb_LogPacket(inp);
#endif /* LOG_PACKET */
}
+ newTime = GetTickCount();
+ osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+
if (oldGen != sessionGen) {
- newTime = GetTickCount();
LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION,
newTime - oldTime, ncbp->ncb_length);
- osi_Log2(smb_logp, "Pkt straddled session startup, "
- "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
+ osi_Log3(smb_logp, "Request %s straddled session startup, "
+ "took %d ms, ncb length %d", opName, newTime - oldTime, ncbp->ncb_length);
}
- }
- else {
+
+ FreeSMBStrings(inp);
+ } else {
/* bad opcode, fail the request, after displaying it */
osi_Log1(smb_logp, "Received bad SMB req 0x%X", inp->inCom);
#ifdef LOG_PACKET
UCHAR rc;
smb_vc_t *vcp = NULL;
smb_t *smbp;
+ extern void rx_StartClientThread(void);
rx_StartClientThread();
- outncbp = GetNCB();
- outbufp = GetPacket();
+ outncbp = smb_GetNCB();
+ outbufp = smb_GetPacket();
outbufp->ncbp = outncbp;
while (1) {
lock_ObtainWrite(&smb_globalLock);
dead_sessions[vcp->session] = TRUE;
lock_ReleaseWrite(&smb_globalLock);
- smb_CleanupDeadVC(vcp);
- smb_ReleaseVC(vcp);
- vcp = NULL;
} else {
lock_ReleaseMutex(&vcp->mx);
}
+ smb_CleanupDeadVC(vcp);
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
}
goto doneWithNCB;
default:
/* A weird error code. Log it, sleep, and continue. */
vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
- if (vcp)
+ if (vcp) {
lock_ObtainMutex(&vcp->mx);
- if (vcp && vcp->errorCount++ > 3) {
- osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
- if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
- osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
- vcp, vcp->usersp);
- vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
- lock_ReleaseMutex(&vcp->mx);
- lock_ObtainWrite(&smb_globalLock);
- dead_sessions[vcp->session] = TRUE;
- lock_ReleaseWrite(&smb_globalLock);
- smb_CleanupDeadVC(vcp);
- smb_ReleaseVC(vcp);
- vcp = NULL;
- } else {
- lock_ReleaseMutex(&vcp->mx);
- }
- goto doneWithNCB;
- }
- else {
- if (vcp)
+ if (vcp->errorCount++ > 3) {
+ osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
+ if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+ osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+ vcp, vcp->usersp);
+ vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+ lock_ReleaseMutex(&vcp->mx);
+ lock_ObtainWrite(&smb_globalLock);
+ dead_sessions[vcp->session] = TRUE;
+ lock_ReleaseWrite(&smb_globalLock);
+ } else {
+ lock_ReleaseMutex(&vcp->mx);
+ }
+ smb_CleanupDeadVC(vcp);
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
+ goto doneWithNCB;
+ }
+ else {
lock_ReleaseMutex(&vcp->mx);
- thrd_Sleep(1000);
- thrd_SetEvent(SessionEvents[idx_session]);
+ smb_ReleaseVC(vcp);
+ vcp = NULL;
+ Sleep(10);
+ thrd_SetEvent(SessionEvents[idx_session]);
+ }
}
continue;
}
smbp = (smb_t *)bufp->data;
outbufp->flags = 0;
+#ifndef NOTRACE
__try
{
+#endif
if (smbp->com == 0x1d) {
/* Special handling for Write Raw */
raw_write_cont_t rwc;
/* TODO: what else needs to be serialized? */
smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
}
+#ifndef NOTRACE
}
__except( smb_ServerExceptionFilter() ) {
}
+#endif
smb_concurrentCalls--;
}
if (vcp)
smb_ReleaseVC(vcp);
+ if (outbufp)
+ smb_FreePacket(outbufp);
+ if (outncbp)
+ smb_FreeNCB(outncbp);
}
/*
{
struct smb_packet *bufp;
EVENT_HANDLE retHandle;
- int i;
+ afs_uint32 i;
char eventName[MAX_PATH];
osi_assertx( idx < (sizeof(NCBs) / sizeof(NCBs[0])), "invalid index" );
- NCBs[idx] = GetNCB();
+ NCBs[idx] = smb_GetNCB();
sprintf(eventName,"NCBavails[%d]", idx);
NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
for (i=0; i<smb_NumServerThreads; i++)
NCBreturns[i][idx] = retHandle;
- bufp = GetPacket();
+ bufp = smb_GetPacket();
bufp->spacep = cm_GetSpace();
bufs[idx] = bufp;
}
long code = 0;
long len;
long i;
- int session, thread;
+ afs_uint32 session, thread;
smb_vc_t *vcp = NULL;
int flags = 0;
char rname[NCBNAMSZ+1];
char cname[MAX_COMPUTERNAME_LENGTH+1];
int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
INT_PTR lana = (INT_PTR) parmp;
+ char eventName[MAX_PATH];
+ int bridgeCount = 0;
+ int nowildCount = 0;
+
+ sprintf(eventName,"smb_Listener_lana_%d", (unsigned char)lana);
+ ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ thrd_ResetEvent(ListenerShutdown[lana]);
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
/* retrieve computer name */
GetComputerName(cname, &cnamelen);
code = Netbios(ncbp);
- if (code == NRC_BRIDGE) {
- int lanaRemaining = 0;
+ if (code == NRC_NAMERR) {
+ /* An smb shutdown or Vista resume must have taken place */
+ osi_Log1(smb_logp,
+ "NCBLISTEN lana=%d failed with NRC_NAMERR.",
+ ncbp->ncb_lana_num);
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NAMERR.", ncbp->ncb_lana_num);
- if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
- ExitThread(1);
+ if (lock_TryMutex(&smb_StartedLock)) {
+ lana_list.lana[i] = LANA_INVALID;
+ lock_ReleaseMutex(&smb_StartedLock);
}
+ break;
+ } else if (code == NRC_BRIDGE || code != 0) {
+ int lanaRemaining = 0;
+
+ if (code == NRC_BRIDGE) {
+ if (++bridgeCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_BRIDGE, retrying ...", ncbp->ncb_lana_num);
+ continue;
+ }
+ } else if (code == NRC_NOWILD) {
+ if (++nowildCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NOWILD, retrying ...", ncbp->ncb_lana_num);
+
+ if (bridgeCount > 0) {
+ memset(ncbp, 0, sizeof(*ncbp));
+ ncbp->ncb_command = NCBADDNAME;
+ ncbp->ncb_lana_num = (UCHAR)lana;
+ /* pad out with spaces instead of null termination */
+ len = (long)strlen(smb_localNamep);
+ strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
+ for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+ code = Netbios(ncbp);
+ }
+ continue;
+ }
+ }
- osi_Log2(smb_logp,
- "NCBLISTEN lana=%d failed with NRC_BRIDGE. Listener thread exiting.",
- ncbp->ncb_lana_num, code);
+ while (!lock_TryMutex(&smb_StartedLock)) {
+ if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
+ goto exit_thread;
+ Sleep(50);
+ }
+
+ osi_Log2(smb_logp,
+ "NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
+ ncbp->ncb_lana_num, ncb_error_string(code));
+ afsi_log("NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
+ ncbp->ncb_lana_num, ncb_error_string(code));
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == ncbp->ncb_lana_num) {
- smb_StopListener(ncbp, lana_list.lana[i]);
- lana_list.lana[i] = 255;
+ if (lana_list.lana[i] == lana) {
+ smb_StopListener(ncbp, lana_list.lana[i], FALSE);
+ lana_list.lana[i] = LANA_INVALID;
}
- if (lana_list.lana[i] != 255)
+ if (lana_list.lana[i] != LANA_INVALID)
lanaRemaining++;
}
#endif
);
smb_ListenerState = SMB_LISTENER_STOPPED;
- smb_LANadapter = -1;
+ smb_LANadapter = LANA_INVALID;
lana_list.length = 0;
}
- FreeNCB(ncbp);
- return;
- } else if (code != 0) {
+ lock_ReleaseMutex(&smb_StartedLock);
+ break;
+ }
+#if 0
+ else if (code != 0) {
char tbuffer[AFSPATHMAX];
/* terminate silently if shutdown flag is set */
- if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1) {
- ExitThread(1);
+ while (!lock_TryMutex(&smb_StartedLock)) {
+ if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
+ goto exit_thread;
+ Sleep(50);
}
- osi_Log2(smb_logp,
- "NCBLISTEN lana=%d failed with code %d",
- ncbp->ncb_lana_num, code);
+ osi_Log3(smb_logp,
+ "NCBLISTEN lana=%d failed with code %d [%s]",
+ ncbp->ncb_lana_num, code, ncb_error_string(code));
osi_Log0(smb_logp,
"Client exiting due to network failure. Please restart client.\n");
sprintf(tbuffer,
"Client exiting due to network failure. Please restart client.\n"
- "NCBLISTEN lana=%d failed with code %d",
- ncbp->ncb_lana_num, code);
+ "NCBLISTEN lana=%d failed with code %d [%s]",
+ ncbp->ncb_lana_num, code, ncb_error_string(code));
if (showErrors)
code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
MB_OK|MB_SERVICE_NOTIFICATION);
osi_panic(tbuffer, __FILE__, __LINE__);
+
+ lock_ReleaseMutex(&smb_StartedLock);
+ break;
}
+#endif /* 0 */
+
+ /* a successful packet received. clear bridge error count */
+ bridgeCount = 0;
+ nowildCount = 0;
/* check for remote conns */
/* first get remote name and insert null terminator */
}
lock_ObtainMutex(&vcp->mx);
- strcpy(vcp->rname, rname);
+ cm_Utf8ToUtf16(rname, -1, vcp->rname, lengthof(vcp->rname));
vcp->flags |= flags;
lock_ReleaseMutex(&vcp->mx);
if (session >= SESSION_MAX - 1 || numNCBs >= NCB_MAX - 1) {
unsigned long code = CM_ERROR_ALLBUSY;
- smb_packet_t * outp = GetPacket();
+ smb_packet_t * outp = smb_GetPacket();
unsigned char *outWctp;
smb_t *smbp;
smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
smbp->rcls = errClass;
}
+
smb_SendPacket(vcp, outp);
smb_FreePacket(outp);
lock_ReleaseMutex(&smb_ListenerLock);
} /* dispatch while loop */
- FreeNCB(ncbp);
+exit_thread:
+ smb_FreeNCB(ncbp);
+ thrd_SetEvent(ListenerShutdown[lana]);
+ return;
+}
+
+static void
+smb_LanAdapterChangeThread(void *param)
+{
+ /*
+ * Give the IPAddrDaemon thread a chance
+ * to block before we trigger.
+ */
+ Sleep(30000);
+ smb_LanAdapterChange(0);
+}
+
+void smb_SetLanAdapterChangeDetected(void)
+{
+ int lpid;
+ thread_t phandle;
+
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (!powerStateSuspended) {
+ phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_LanAdapterChangeThread,
+ NULL, 0, &lpid, "smb_LanAdapterChange");
+ osi_assertx(phandle != NULL, "smb_LanAdapterChangeThread thread creation failure");
+ thrd_CloseHandle(phandle);
+ }
+
+ smb_LanAdapterChangeDetected = 1;
+ lock_ReleaseMutex(&smb_StartedLock);
+}
+
+void smb_LanAdapterChange(int locked) {
+ lana_number_t lanaNum;
+ BOOL bGateway;
+ char NetbiosName[MAX_NB_NAME_LENGTH] = "";
+ int change = 0;
+ LANA_ENUM temp_list;
+ long code;
+ int i;
+
+
+ afsi_log("smb_LanAdapterChange");
+
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ smb_LanAdapterChangeDetected = 0;
+
+ if (!powerStateSuspended &&
+ SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway,
+ LANA_NETBIOS_NAME_FULL)) &&
+ lanaNum != LANA_INVALID && smb_LANadapter != lanaNum) {
+ if ( isGateway != bGateway ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): gateway %d != %d",
+ smb_LANadapter, lanaNum, isGateway, bGateway);
+ change = 1;
+ } else if (strcmp(cm_NetbiosName, NetbiosName) ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): name %s != %s",
+ smb_LANadapter, lanaNum, cm_NetbiosName, NetbiosName);
+ change = 1;
+ } else {
+ NCB *ncbp = smb_GetNCB();
+ ncbp->ncb_command = NCBENUM;
+ ncbp->ncb_buffer = (PUCHAR)&temp_list;
+ ncbp->ncb_length = sizeof(temp_list);
+ code = Netbios(ncbp);
+ if (code == 0) {
+ if (temp_list.length != lana_list.length) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lan list length changed %d != %d",
+ smb_LANadapter, lanaNum, temp_list.length, lana_list.length);
+ change = 1;
+ } else {
+ for (i=0; i<lana_list.length; i++) {
+ if ( temp_list.lana[i] != lana_list.lana[i] ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lana[%d] %d != %d",
+ smb_LANadapter, lanaNum, i, temp_list.lana[i], lana_list.lana[i]);
+ change = 1;
+ break;
+ }
+ }
+ }
+ }
+ smb_FreeNCB(ncbp);
+ }
+ }
+
+ if (change) {
+ smb_StopListeners(1);
+ smb_RestartListeners(1);
+ }
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
/* initialize Netbios */
-int smb_NetbiosInit(void)
+int smb_NetbiosInit(int locked)
{
NCB *ncbp;
int i, lana, code, l;
int lana_found = 0;
lana_number_t lanaNum;
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState != SMB_LISTENER_UNINITIALIZED &&
+ smb_ListenerState != SMB_LISTENER_STOPPED) {
+
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
+ return 0;
+ }
/* setup the NCB system */
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
/* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
smb_LANadapter = (lanaNum == LANA_INVALID)? -1: lanaNum;
- if (smb_LANadapter != -1)
+ if (smb_LANadapter != LANA_INVALID)
afsi_log("LAN adapter number %d", smb_LANadapter);
else
afsi_log("LAN adapter number not determined");
strcpy(smb_localNamep, cm_NetbiosName);
afsi_log("smb_localNamep is >%s<", smb_localNamep);
+ /* Also copy the value to the client character encoded string */
+ cm_Utf8ToClientString(cm_NetbiosName, -1, cm_NetbiosNameC, MAX_NB_NAME_LENGTH);
- if (smb_LANadapter == -1) {
+ if (smb_LANadapter == LANA_INVALID) {
ncbp->ncb_command = NCBENUM;
ncbp->ncb_buffer = (PUCHAR)&lana_list;
ncbp->ncb_length = sizeof(lana_list);
code = ncbp->ncb_retcode;
if (code != 0) {
afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
- lana_list.lana[i] = 255; /* invalid lana */
+ lana_list.lana[i] = LANA_INVALID; /* invalid lana */
} else {
afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
}
else {
afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
if (code == NRC_BRIDGE) { /* invalid LANA num */
- lana_list.lana[l] = 255;
+ lana_list.lana[l] = LANA_INVALID;
continue;
}
else if (code == NRC_DUPNAME) {
afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code);
}
if (code != 0 || delname_tried) {
- lana_list.lana[l] = 255;
+ lana_list.lana[l] = LANA_INVALID;
}
else if (code == 0) {
if (!delname_tried) {
}
else {
afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
- lana_list.lana[l] = 255; /* invalid lana */
+ lana_list.lana[l] = LANA_INVALID; /* invalid lana */
}
}
if (code == 0) {
+ smb_LANadapter = lana;
lana_found = 1; /* at least one worked */
}
}
if (!lana_found) {
afsi_log("No valid LANA numbers found!");
lana_list.length = 0;
- smb_LANadapter = -1;
+ smb_LANadapter = LANA_INVALID;
smb_ListenerState = SMB_LISTENER_STOPPED;
cm_VolStatus_Network_Stopped(cm_NetbiosName
#ifdef _WIN64
}
/* we're done with the NCB now */
- FreeNCB(ncbp);
+ smb_FreeNCB(ncbp);
+
+ afsi_log("smb_NetbiosInit smb_LANadapter=%d",smb_LANadapter);
+ if (lana_list.length > 0)
+ osi_assert(smb_LANadapter != LANA_INVALID);
+
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
return (lana_list.length > 0 ? 1 : 0);
}
-void smb_StartListeners()
+void smb_StartListeners(int locked)
{
int i;
int lpid;
thread_t phandle;
- if (smb_ListenerState == SMB_LISTENER_STARTED)
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState == SMB_LISTENER_STARTED) {
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
return;
-
+ }
+
+ afsi_log("smb_StartListeners");
smb_ListenerState = SMB_LISTENER_STARTED;
cm_VolStatus_Network_Started(cm_NetbiosName
#ifdef _WIN64
);
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == 255)
+ if (lana_list.lana[i] == LANA_INVALID)
continue;
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
(void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
osi_assertx(phandle != NULL, "smb_Listener thread creation failure");
thrd_CloseHandle(phandle);
}
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
-void smb_RestartListeners()
+void smb_RestartListeners(int locked)
{
- if (!powerStateSuspended && smb_ListenerState == SMB_LISTENER_STOPPED) {
- if (smb_NetbiosInit())
- smb_StartListeners();
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (powerStateSuspended)
+ afsi_log("smb_RestartListeners called while suspended");
+
+ if (!powerStateSuspended && smb_ListenerState != SMB_LISTENER_UNINITIALIZED) {
+ if (smb_ListenerState == SMB_LISTENER_STOPPED) {
+ if (smb_NetbiosInit(1))
+ smb_StartListeners(1);
+ } else if (smb_LanAdapterChangeDetected) {
+ smb_LanAdapterChange(1);
+ }
}
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
-void smb_StopListener(NCB *ncbp, int lana)
+void smb_StopListener(NCB *ncbp, int lana, int wait)
{
long code;
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
code = Netbios(ncbp);
- afsi_log("Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
+ afsi_log("StopListener: Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
/* and then reset the LANA; this will cause the listener threads to exit */
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- afsi_log("Netbios NCBRESET lana %d error code %d", lana, code);
+ afsi_log("StopListener: Netbios NCBRESET lana %d error code %d", lana, code);
} else {
- afsi_log("Netbios NCBRESET lana %d succeeded", lana);
+ afsi_log("StopListener: Netbios NCBRESET lana %d succeeded", lana);
}
+
+ if (wait)
+ thrd_WaitForSingleObject_Event(ListenerShutdown[lana], INFINITE);
}
-void smb_StopListeners(void)
+void smb_StopListeners(int locked)
{
NCB *ncbp;
int lana, l;
- if (smb_ListenerState == SMB_LISTENER_STOPPED)
+ if (!locked)
+ lock_ObtainMutex(&smb_StartedLock);
+
+ if (smb_ListenerState == SMB_LISTENER_STOPPED) {
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
return;
+ }
+ afsi_log("smb_StopListeners");
smb_ListenerState = SMB_LISTENER_STOPPED;
cm_VolStatus_Network_Stopped(cm_NetbiosName
#ifdef _WIN64
#endif
);
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
/* Unregister the SMB name */
for (l = 0; l < lana_list.length; l++) {
lana = lana_list.lana[l];
- if (lana != 255) {
- smb_StopListener(ncbp, lana);
+ if (lana != LANA_INVALID) {
+ smb_StopListener(ncbp, lana, TRUE);
/* mark the adapter invalid */
- lana_list.lana[l] = 255; /* invalid lana */
+ lana_list.lana[l] = LANA_INVALID; /* invalid lana */
}
}
/* force a re-evaluation of the network adapters */
lana_list.length = 0;
- smb_LANadapter = -1;
- FreeNCB(ncbp);
- Sleep(1000); /* give the listener threads a chance to exit */
+ smb_LANadapter = LANA_INVALID;
+ smb_FreeNCB(ncbp);
+ if (!locked)
+ lock_ReleaseMutex(&smb_StartedLock);
}
void smb_Init(osi_log_t *logp, int useV3,
struct tm myTime;
EVENT_HANDLE retHandle;
char eventName[MAX_PATH];
+ int startListeners = 0;
smb_TlsRequestSlot = TlsAlloc();
smb_logp = logp;
/* and the global lock */
- lock_InitializeRWLock(&smb_globalLock, "smb global lock");
- lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
+ lock_InitializeRWLock(&smb_globalLock, "smb global lock", LOCK_HIERARCHY_SMB_GLOBAL);
+ lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock", LOCK_HIERARCHY_SMB_RCT_GLOBAL);
/* Raw I/O data structures */
- lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
+ lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock", LOCK_HIERARCHY_SMB_RAWBUF);
- lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
+ lock_InitializeMutex(&smb_ListenerLock, "smb listener lock", LOCK_HIERARCHY_SMB_LISTENER);
+ lock_InitializeMutex(&smb_StartedLock, "smb started lock", LOCK_HIERARCHY_SMB_STARTED);
/* 4 Raw I/O buffers */
smb_RawBufs = calloc(65536,1);
smb_ncbFreeListp = NULL;
smb_packetFreeListp = NULL;
- smb_NetbiosInit();
+ lock_ObtainMutex(&smb_StartedLock);
+ startListeners = smb_NetbiosInit(1);
/* Initialize listener and server structures */
numVCs = 0;
* It is actually the domain for local logins, and we are acting as
* a local SMB server.
*/
- bufsize = sizeof(smb_ServerDomainName) - 1;
- GetComputerName(smb_ServerDomainName, &bufsize);
+ bufsize = lengthof(smb_ServerDomainName) - 1;
+ GetComputerNameW(smb_ServerDomainName, &bufsize);
smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */
- afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName);
+ afsi_log("Setting SMB server domain name to [%S]", smb_ServerDomainName);
}
/* Start listeners, waiters, servers, and daemons */
-
- smb_StartListeners();
+ if (startListeners)
+ smb_StartListeners(1);
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
NULL, 0, &lpid, "smb_ClientWaiter");
- osi_assertx(phandle != NULL, , "smb_ClientWaiter thread creation failure");
+ osi_assertx(phandle != NULL, "smb_ClientWaiter thread creation failure");
thrd_CloseHandle(phandle);
phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
osi_assertx(phandle != NULL, "smb_WaitingLocksDaemon thread creation failure");
thrd_CloseHandle(phandle);
+ lock_ReleaseMutex(&smb_StartedLock);
return;
}
{
NCB *ncbp;
long code = 0;
- int i;
+ afs_uint32 i;
smb_vc_t *vcp;
/*fprintf(stderr, "Entering smb_Shutdown\n");*/
/* setup the NCB system */
- ncbp = GetNCB();
+ ncbp = smb_GetNCB();
/* Block new sessions by setting shutdown flag */
smbShutdownFlag = 1;
/* Delete Netbios name */
memset((char *)ncbp, 0, sizeof(NCB));
for (i = 0; i < lana_list.length; i++) {
- if (lana_list.lana[i] == 255) continue;
+ if (lana_list.lana[i] == LANA_INVALID) continue;
ncbp->ncb_command = NCBDELNAME;
ncbp->ncb_lana_num = lana_list.lana[i];
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
+ fprintf(stderr, "Shutdown: Netbios NCBDELNAME lana %d error code %d",
ncbp->ncb_lana_num, code);
}
fflush(stderr);
if (fidp->scp != NULL) {
cm_scache_t * scp;
+ lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
if (fidp->scp != NULL) {
scp = fidp->scp;
fidp->scp = NULL;
- 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_Shutdown fidp 0x%p scp 0x%p", fidp, scp);
cm_ReleaseSCache(scp);
}
lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
}
}
if (tidp->userp) {
cm_user_t *userp = tidp->userp;
tidp->userp = NULL;
- lock_ReleaseWrite(&smb_rctLock);
cm_ReleaseUser(userp);
- lock_ObtainWrite(&smb_rctLock);
}
}
}
lock_ReleaseWrite(&smb_rctLock);
- FreeNCB(ncbp);
+ smb_FreeNCB(ncbp);
TlsFree(smb_TlsRequestSlot);
}
char *smb_GetSharename()
{
char *name;
+ size_t len;
/* Make sure we have been properly initialized. */
if (smb_localNamep == NULL)
/* Allocate space for \\<servername>\<sharename>, plus the
* terminator.
*/
- name = malloc(strlen(smb_localNamep) + strlen("ALL") + 4);
- sprintf(name, "\\\\%s\\%s", smb_localNamep, "ALL");
+ len = (strlen(smb_localNamep) + strlen("ALL") + 4) * sizeof(char);
+ name = malloc(len);
+ snprintf(name, len, "\\\\%s\\%s", smb_localNamep, "ALL");
return name;
-}
+}
#ifdef LOG_PACKET
void smb_LogPacket(smb_packet_t *packet)
{
BYTE *vp, *cp;
+ smb_t * smbp;
unsigned length, paramlen, datalen, i, j;
char buf[81];
char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
osi_Log0(smb_logp, "*** SMB packet dump ***");
+ smbp = (smb_t *) packet->data;
vp = (BYTE *) packet->data;
- datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1)));
- length = paramlen + 2 + datalen;
-
+ paramlen = smbp->wct * 2;
+ datalen = *((WORD *) (smbp->vdata + paramlen));
+ length = sizeof(*smbp) + paramlen + 1 + datalen;
for (i=0;i < length; i+=16)
{
int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
{
int zilch;
- char output[1024];
+ char output[4196];
smb_vc_t *vcp;
-
+ smb_username_t *unp;
+ smb_waitingLockRequest_t *wlrp;
+
if (lock)
lock_ObtainRead(&smb_rctLock);
+ sprintf(output, "begin dumping smb_username_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (unp = usernamesp; unp; unp=unp->nextp)
+ {
+ cm_ucell_t *ucellp;
+
+ sprintf(output, "%s -- smb_unp=0x%p, refCount=%d, cm_userp=0x%p, flags=0x%x, logoff=%u, name=%S, machine=%S\r\n",
+ cookie, unp, unp->refCount, unp->userp, unp->flags, unp->last_logoff_t,
+ unp->name ? unp->name : _C("NULL"),
+ unp->machine ? unp->machine : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping cm_ucell_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ for ( ucellp = unp->userp->cellInfop; ucellp; ucellp = ucellp->nextp ) {
+ sprintf(output, " %s -- ucellp=0x%p, cellp=0x%p, flags=0x%x, tktLen=%04u, kvno=%03u, expires=%I64u, gen=%d, name=%s, cellname=%s\r\n",
+ cookie, ucellp, ucellp->cellp, ucellp->flags, ucellp->ticketLen, ucellp->kvno,
+ ucellp->expirationTime, ucellp->gen,
+ ucellp->userName,
+ ucellp->cellp->name);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, " done dumping cm_ucell_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ }
+ sprintf(output, "done dumping smb_username_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+ sprintf(output, "begin dumping smb_waitingLockRequest_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+ for ( wlrp = smb_allWaitingLocks; wlrp; wlrp = (smb_waitingLockRequest_t *) osi_QNext(&wlrp->q)) {
+ smb_waitingLock_t *lockp;
+
+ sprintf(output, "%s wlrp=0x%p vcp=0x%p, scp=0x%p, type=0x%x, start_t=0x%I64u msTimeout=0x%x\r\n",
+ cookie, wlrp, wlrp->vcp, wlrp->scp, wlrp->lockType, wlrp->start_t, wlrp->msTimeout);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_waitingLock_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (lockp = wlrp->locks; lockp; lockp = (smb_waitingLock_t *) osi_QNext(&lockp->q)) {
+ sprintf(output, " %s -- waitlockp=0x%p lockp=0x%p key=0x%I64x offset=0x%I64x length=0x%I64x state=0x%x\r\n",
+ cookie, lockp, lockp->lockp, lockp->key, lockp->LOffset.QuadPart, lockp->LLength.QuadPart, lockp->state);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_waitingLock_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+
+ sprintf(output, "done dumping smb_waitingLockRequest_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
sprintf(output, "begin dumping smb_vc_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
+ smb_tid_t *tidp;
+ smb_user_t *userp;
- sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
+ sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping smb_fid_t\r\n");
+ sprintf(output, " begin dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (userp = vcp->usersp; userp; userp = userp->nextp) {
+ sprintf(output, " %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n",
+ cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ sprintf(output, " %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n",
+ cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+ tidp->pathname ? tidp->pathname : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
{
- sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\r\n",
- cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
- fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL",
- fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+ sprintf(output, " %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
+ fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"),
+ fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping smb_fid_t\r\n");
+ sprintf(output, " done dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp)
{
smb_fid_t *fidp;
-
- sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
- cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+ smb_tid_t *tidp;
+ smb_user_t *userp;
+
+ sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
+ cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
- sprintf(output, "begin dumping smb_fid_t\r\n");
+ sprintf(output, " begin dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (userp = vcp->usersp; userp; userp = userp->nextp) {
+ sprintf(output, " %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n",
+ cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_user_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+ sprintf(output, " %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n",
+ cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+ tidp->pathname ? tidp->pathname : _C("NULL"));
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+ }
+ sprintf(output, " done dumping smb_tid_t\r\n");
+ WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+ sprintf(output, " begin dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
{
- sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\r\n",
- cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp,
- fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL",
- fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+ sprintf(output, " %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n",
+ cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
+ fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"),
+ fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
- sprintf(output, "done dumping smb_fid_t\r\n");
+ sprintf(output, " done dumping smb_fid_t\r\n");
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
long smb_IsNetworkStarted(void)
{
- return (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0);
+ long rc;
+ lock_ObtainWrite(&smb_globalLock);
+ rc = (smb_ListenerState == SMB_LISTENER_STARTED && smbShutdownFlag == 0);
+ lock_ReleaseWrite(&smb_globalLock);
+ return rc;
}