windows-smb_vc_t-refcounts-20050117

Rework the reference counting of the smb_vc_t objects to use
smb_ReleaseVC and smb_HoldVC.  Add missing counts for references
from waiting locks.

Fix cm_ioctl.c to allow it to compile once again.
This commit is contained in:
Jeffrey Altman 2005-01-18 07:36:25 +00:00
parent cadc5b46e1
commit eabe2b6f77
4 changed files with 327 additions and 266 deletions

View File

@ -89,8 +89,8 @@ void cm_ResetACLCache(cm_user_t *userp)
int hash;
lock_ObtainWrite(&cm_scacheLock);
for (hash=0; hash < cm_data.hashTableSize; hash++) {
for (scp=cm_data.hashTablep[hash]; scp; scp=scp->nextp) {
for (hash=0; hash < cm_hashTableSize; hash++) {
for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
cm_HoldSCacheNoLock(scp);
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainMutex(&scp->mx);
@ -179,7 +179,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
if ( shareFound ) {
/* we found a sharename, therefore use the resulting path */
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, sharePath, reqp, &substRootp);
free(sharePath);
@ -208,7 +208,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
shareName[i] = 0; /* terminate string */
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, shareName, reqp, &substRootp);
if (code)
@ -220,7 +220,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
return code;
}
} else {
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, ioctlp->tidPathp, reqp, &substRootp);
if (code)
@ -347,7 +347,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
shareFound = smb_FindShare(ioctlp->fidp->vcp, ioctlp->uidp, shareName, &sharePath);
if ( shareFound ) {
/* we found a sharename, therefore use the resulting path */
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, sharePath, reqp, &substRootp);
free(sharePath);
@ -373,7 +373,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
shareName[i++] = '/'; /* add trailing slash */
shareName[i] = 0; /* terminate string */
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, shareName, reqp, &substRootp);
if (code) return code;
@ -383,7 +383,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
if (code) return code;
}
} else {
code = cm_NameI(cm_data.rootSCachep, ioctlp->prefix->data,
code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
userp, ioctlp->tidPathp, reqp, &substRootp);
if (code) return code;
@ -472,7 +472,7 @@ long cm_IoctlGetFileCellName(struct smb_ioctl *ioctlp, struct cm_user *userp)
{
cellp = cm_FindCellByID(scp->fid.cell);
if (cellp) {
StringCbCopyA(ioctlp->outDatap, 999999, cellp->name);
StringCbCopyA(ioctlp->outDatap, 999999, cellp->namep);
ioctlp->outDatap += strlen(ioctlp->outDatap) + 1;
code = 0;
}
@ -545,8 +545,8 @@ long cm_IoctlFlushVolume(struct smb_ioctl *ioctlp, struct cm_user *userp)
cm_ReleaseSCache(scp);
lock_ObtainWrite(&cm_scacheLock);
for (i=0; i<cm_data.hashTableSize; i++) {
for (scp = cm_data.hashTablep[i]; scp; scp = scp->nextp) {
for (i=0; i<cm_hashTableSize; i++) {
for (scp = cm_hashTablep[i]; scp; scp = scp->nextp) {
if (scp->fid.volume == volume) {
cm_HoldSCacheNoLock(scp);
lock_ReleaseWrite(&cm_scacheLock);
@ -974,10 +974,10 @@ long cm_IoctlSetCacheSize(struct smb_ioctl *ioctlp, struct cm_user *userp)
memcpy(&temp, ioctlp->inDatap, sizeof(temp));
if (temp == 0)
temp = cm_data.buf_nOrigBuffers;
temp = buf_nOrigBuffers;
else {
/* temp is in 1K units, convert to # of buffers */
temp = temp / (cm_data.buf_blockSize / 1024);
temp = temp / (buf_bufferSize / 1024);
}
/* now adjust the cache size */
@ -1031,12 +1031,12 @@ long cm_IoctlGetCacheParms(struct smb_ioctl *ioctlp, struct cm_user *userp)
memset(&parms, 0, sizeof(parms));
/* first we get, in 1K units, the cache size */
parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
parms.parms[0] = buf_nbuffers * (buf_bufferSize / 1024);
/* and then the actual # of buffers in use (not in the free list, I guess,
* will be what we do).
*/
parms.parms[1] = (cm_data.buf_nbuffers - buf_CountFreeList()) * (cm_data.buf_blockSize / 1024);
parms.parms[1] = (buf_nbuffers - buf_CountFreeList()) * (buf_bufferSize / 1024);
memcpy(ioctlp->outDatap, &parms, sizeof(parms));
ioctlp->outDatap += sizeof(parms);
@ -1069,7 +1069,7 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
}
lock_ObtainRead(&cm_cellLock);
for (tcellp = cm_data.allCellsp; tcellp; tcellp = tcellp->nextp) {
for (tcellp = cm_allCellsp; tcellp; tcellp = tcellp->nextp) {
if (whichCell == 0) break;
whichCell--;
}
@ -1097,8 +1097,8 @@ long cm_IoctlGetCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
}
lock_ReleaseRead(&cm_serverLock);
cp = basep + max * sizeof(afs_int32);
StringCbCopyA(cp, 999999, tcellp->name);
cp += strlen(tcellp->name)+1;
StringCbCopyA(cp, 999999, tcellp->namep);
cp += strlen(tcellp->namep)+1;
ioctlp->outDatap = cp;
}
@ -1126,18 +1126,18 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
cm_SkipIoctlPath(ioctlp);
lock_ObtainWrite(&cm_cellLock);
for (cp = cm_data.allCellsp; cp; cp=cp->nextp)
for (cp = cm_allCellsp; cp; cp=cp->nextp)
{
long code;
/* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
cm_FreeServerList(&cp->vlServersp);
cp->vlServersp = NULL;
code = cm_SearchCellFile(cp->name, cp->name, cm_AddCellProc, cp);
code = cm_SearchCellFile(cp->namep, cp->namep, cm_AddCellProc, cp);
#ifdef AFS_AFSDB_ENV
if (code) {
if (cm_dnsEnabled) {
int ttl;
code = cm_SearchCellByDNS(cp->name, cp->name, &ttl, cm_AddCellProc, cp);
code = cm_SearchCellByDNS(cp->namep, cp->namep, &ttl, cm_AddCellProc, cp);
if ( code == 0 ) { /* got cell from DNS */
cp->flags |= CM_CELLFLAG_DNS;
cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
@ -1169,9 +1169,9 @@ long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp)
if (cm_freelanceEnabled) {
StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root");
ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
} else if (cm_data.rootCellp) {
} else if (cm_rootCellp) {
/* return the default cellname to the caller */
StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name);
StringCbCopyA(ioctlp->outDatap, 999999, cm_rootCellp->namep);
ioctlp->outDatap += strlen(ioctlp->outDatap) +1;
} else {
/* if we don't know our default cell, return failure */
@ -1481,7 +1481,7 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
}
#ifdef AFS_FREELANCE_CLIENT
if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
/* we are adding the mount point to the root dir., so call
* the freelance code to do the add. */
osi_Log0(afsd_logp,"IoctlCreateMountPoint within Freelance root dir");
@ -1530,7 +1530,7 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
cp = ioctlp->inDatap; /* contents of link */
#ifdef AFS_FREELANCE_CLIENT
if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
/* we are adding the symlink to the root dir., so call
* the freelance code to do the add. */
if (cp[0] == cp[1] && cp[1] == '\\' &&
@ -1595,7 +1595,7 @@ long cm_IoctlListlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
code = cm_AssembleLink(scp, "", &newRootScp, &spacep, userp, &req);
cm_ReleaseSCache(scp);
if (code == 0 || code == CM_ERROR_PATH_NOT_COVERED) {
if (code == 0) {
cp = ioctlp->outDatap;
if (newRootScp != NULL) {
StringCbCopyA(cp, 999999, cm_mountRoot);
@ -1657,7 +1657,7 @@ long cm_IoctlDeletelink(struct smb_ioctl *ioctlp, struct cm_user *userp)
cp = ioctlp->inDatap;
#ifdef AFS_FREELANCE_CLIENT
if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) {
if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
/* we are adding the mount point to the root dir., so call
* the freelance code to do the add. */
osi_Log0(afsd_logp,"IoctlDeletelink from Freelance root dir");
@ -1785,7 +1785,7 @@ long cm_IoctlSetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
return CM_ERROR_INVAL;
#endif /* !DJGPP */
} else {
cellp = cm_data.rootCellp;
cellp = cm_rootCellp;
osi_Log0(smb_logp,"cm_IoctlSetToken - no name specified");
}
@ -1904,7 +1904,7 @@ long cm_IoctlGetTokenIter(struct smb_ioctl *ioctlp, struct cm_user *userp)
cp += sizeof(temp);
/* cell name */
StringCbCopyA(cp, 999999, ucellp->cellp->name);
StringCbCopyA(cp, 999999, ucellp->cellp->namep);
cp += strlen(cp) + 1;
/* user name */
@ -1993,7 +1993,7 @@ long cm_IoctlGetToken(struct smb_ioctl *ioctlp, struct cm_user *userp)
cp += sizeof(temp);
/* cell name */
StringCbCopyA(cp, 999999, ucellp->cellp->name);
StringCbCopyA(cp, 999999, ucellp->cellp->namep);
cp += strlen(cp) + 1;
/* user name */

View File

@ -779,9 +779,9 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
smb_vc_t *vcp;
lock_ObtainWrite(&smb_rctLock);
for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
if (lsn == vcp->lsn && lana == vcp->lana) {
vcp->refCount++;
smb_HoldVCNoLock(vcp);
break;
}
}
@ -842,6 +842,11 @@ int smb_IsStarMask(char *maskp)
return 0;
}
void smb_ReleaseVCNoLock(smb_vc_t *vcp)
{
osi_assert(vcp->refCount-- > 0);
}
void smb_ReleaseVC(smb_vc_t *vcp)
{
lock_ObtainWrite(&smb_rctLock);
@ -849,6 +854,11 @@ void smb_ReleaseVC(smb_vc_t *vcp)
lock_ReleaseWrite(&smb_rctLock);
}
void smb_HoldVCNoLock(smb_vc_t *vcp)
{
vcp->refCount++;
}
void smb_HoldVC(smb_vc_t *vcp)
{
lock_ObtainWrite(&smb_rctLock);
@ -873,7 +883,7 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
tidp->nextp = vcp->tidsp;
tidp->refCount = 1;
tidp->vcp = vcp;
vcp->refCount++;
smb_HoldVCNoLock(vcp);
vcp->tidsp = tidp;
lock_InitializeMutex(&tidp->mx, "tid_t mutex");
tidp->tid = tid;
@ -887,30 +897,27 @@ void smb_ReleaseTID(smb_tid_t *tidp)
smb_tid_t *tp;
smb_tid_t **ltpp;
cm_user_t *userp;
smb_vc_t *vcp;
userp = NULL;
vcp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(tidp->refCount-- > 0);
if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
ltpp = &tidp->vcp->tidsp;
for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
if (tp == tidp) break;
for (tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
if (tp == tidp)
break;
}
osi_assert(tp != NULL);
*ltpp = tp->nextp;
lock_FinalizeMutex(&tidp->mx);
userp = tidp->userp; /* remember to drop ref later */
vcp = tidp->vcp;
tidp->userp = NULL;
smb_ReleaseVCNoLock(tidp->vcp);
tidp->vcp = NULL;
}
lock_ReleaseWrite(&smb_rctLock);
if (userp) {
if (userp)
cm_ReleaseUser(userp);
}
if (vcp) {
smb_ReleaseVC(vcp);
}
}
smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
@ -933,7 +940,7 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
uidp->nextp = vcp->usersp;
uidp->refCount = 1;
uidp->vcp = vcp;
vcp->refCount++;
smb_HoldVCNoLock(vcp);
vcp->usersp = uidp;
lock_InitializeMutex(&uidp->mx, "user_t mutex");
uidp->userID = uid;
@ -992,10 +999,8 @@ void smb_ReleaseUID(smb_user_t *uidp)
smb_user_t *up;
smb_user_t **lupp;
cm_user_t *userp;
smb_vc_t *vcp;
userp = NULL;
vcp = NULL;
lock_ObtainWrite(&smb_rctLock);
osi_assert(uidp->refCount-- > 0);
if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
@ -1007,10 +1012,10 @@ void smb_ReleaseUID(smb_user_t *uidp)
*lupp = up->nextp;
lock_FinalizeMutex(&uidp->mx);
if (uidp->unp) {
userp = uidp->unp->userp; /* remember to drop ref later */
uidp->unp->userp = NULL;
userp = uidp->unp->userp; /* avoid deadlock by releasing */
uidp->unp->userp = NULL; /* after releasing the lock */
}
vcp = uidp->vcp;
smb_ReleaseVCNoLock(uidp->vcp);
uidp->vcp = NULL;
}
lock_ReleaseWrite(&smb_rctLock);
@ -1018,9 +1023,6 @@ void smb_ReleaseUID(smb_user_t *uidp)
cm_ReleaseUserVCRef(userp);
cm_ReleaseUser(userp);
}
if (vcp) {
smb_ReleaseVC(vcp);
}
}
/* retrieve a held reference to a user structure corresponding to an incoming
@ -1110,7 +1112,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
}
retry:
for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
if (fid == fidp->fid) {
if (newFid) {
fid++;
@ -1141,7 +1143,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
fidp->refCount = 1;
fidp->vcp = vcp;
vcp->refCount++;
smb_HoldVCNoLock(vcp);
lock_InitializeMutex(&fidp->mx, "fid_t mutex");
fidp->fid = fid;
fidp->curr_chunk = fidp->prev_chunk = -2;
@ -1170,24 +1172,30 @@ void smb_ReleaseFID(smb_fid_t *fidp)
osi_assert(fidp->refCount-- > 0);
if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
vcp = fidp->vcp;
if (!(fidp->flags & SMB_FID_IOCTL))
fidp->vcp = NULL;
if (!(fidp->flags & SMB_FID_IOCTL)) {
scp = fidp->scp;
fidp->scp = NULL;
}
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) cm_FreeSpace(ioctlp->prefix);
if (ioctlp->inAllocp) free(ioctlp->inAllocp);
if (ioctlp->outAllocp) free(ioctlp->outAllocp);
if (ioctlp->prefix)
cm_FreeSpace(ioctlp->prefix);
if (ioctlp->inAllocp)
free(ioctlp->inAllocp);
if (ioctlp->outAllocp)
free(ioctlp->outAllocp);
free(ioctlp);
}
free(fidp);
/* do not call smb_ReleaseVC() because we already have the lock */
vcp->refCount--;
smb_ReleaseVCNoLock(vcp);
}
lock_ReleaseWrite(&smb_rctLock);
@ -1854,6 +1862,8 @@ static NCB *GetNCB(void)
void smb_FreePacket(smb_packet_t *tbp)
{
smb_vc_t * vcp = NULL;
osi_assert(tbp->magic == SMB_PACKETMAGIC);
lock_ObtainWrite(&smb_globalLock);
@ -1861,6 +1871,7 @@ void smb_FreePacket(smb_packet_t *tbp)
smb_packetFreeListp = tbp;
tbp->magic = SMB_PACKETMAGIC;
tbp->ncbp = NULL;
vcp = tbp->vcp;
tbp->vcp = NULL;
tbp->resumeCode = 0;
tbp->inCount = 0;
@ -1871,6 +1882,9 @@ void smb_FreePacket(smb_packet_t *tbp)
tbp->ncb_length = 0;
tbp->flags = 0;
lock_ReleaseWrite(&smb_globalLock);
if (vcp)
smb_ReleaseVC(vcp);
}
static void FreeNCB(NCB *bufferp)
@ -2966,6 +2980,8 @@ void smb_WaitingLocksDaemon()
cm_FreeSpace(inp->spacep);
smb_FreePacket(inp);
smb_FreePacket(outp);
if (vcp)
smb_ReleaseVC(vcp);
FreeNCB(ncbp);
free(wL);
} while (nwL);
@ -3404,10 +3420,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
memcpy(dsp->mask, mask, 11);
/* track if this is likely to match a lot of entries */
if (smb_IsStarMask(mask)) starPattern = 1;
else starPattern = 0;
}
else {
if (smb_IsStarMask(mask))
starPattern = 1;
else
starPattern = 0;
} else {
/* pull the next cookie value out of the search status block */
nextCookie = inCookiep[13] + (inCookiep[14]<<8) + (inCookiep[15]<<16)
+ (inCookiep[16]<<24);
@ -3837,7 +3854,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
caseFold = CM_FLAG_CASEFOLD;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if(code) {
if (code) {
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}

View File

@ -436,6 +436,8 @@ extern smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana);
extern void smb_ReleaseVC(smb_vc_t *vcp);
extern void smb_ReleaseVCNoLock(smb_vc_t *vcp);
extern smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags);
extern void smb_ReleaseTID(smb_tid_t *tidp);
@ -513,6 +515,8 @@ extern void smb_MapNTError(long code, unsigned long *NTStatusp);
extern void smb_HoldVC(smb_vc_t *vcp);
extern void smb_HoldVCNoLock(smb_vc_t *vcp);
/* some globals, too */
extern char *smb_localNamep;
extern int loggedOut;

View File

@ -1145,7 +1145,8 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
/* free a tran2 packet; must be called with smb_globalLock held */
void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
{
if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
if (t2p->vcp)
smb_ReleaseVC(t2p->vcp);
if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
if (t2p->parmsp)
free(t2p->parmsp);
@ -3742,10 +3743,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
smb_StripLastComponent(spacep->data, NULL, pathp);
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
lock_ReleaseMutex(&dsp->mx);
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES);
smb_FreeTran2Packet(outp);
lock_ReleaseMutex(&dsp->mx);
smb_DeleteDirSearch(dsp);
smb_ReleaseDirSearch(dsp);
return 0;
@ -4371,8 +4372,10 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
* and truncate the file if we find it, otherwise we create the
* file.
*/
if (!lastNamep) lastNamep = pathp;
else lastNamep++;
if (!lastNamep)
lastNamep = pathp;
else
lastNamep++;
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
&req, &scp);
if (code && code != CM_ERROR_NOSUCHFILE) {
@ -4390,7 +4393,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (code == 0) {
code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
if (code) {
if (dscp) cm_ReleaseSCache(dscp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return code;
@ -4398,7 +4402,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (excl) {
/* oops, file shouldn't be there */
if (dscp) cm_ReleaseSCache(dscp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
return CM_ERROR_EXISTS;
@ -4557,7 +4562,8 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_GETSTATUS
| CM_SCACHESYNC_LOCK);
if (code) goto doneSync;
if (code)
goto doneSync;
LockType = smb_GetSMBParm(inp, 3) & 0xff;
Timeout = (smb_GetSMBParm(inp, 5) << 16) + smb_GetSMBParm(inp, 4);
@ -4619,6 +4625,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* Put on waiting list */
waitingLock = malloc(sizeof(smb_waitingLock_t));
waitingLock->vcp = vcp;
smb_HoldVC(vcp);
waitingLock->inp = smb_CopyPacket(inp);
waitingLock->outp = smb_CopyPacket(outp);
waitingLock->timeRemaining = Timeout;
@ -4631,7 +4638,8 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* don't send reply immediately */
outp->flags |= SMB_PACKETFLAG_NOSEND;
}
if (code) break;
if (code)
break;
}
if (code) {
@ -4886,9 +4894,14 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
cm_InitReq(&req);
/* This code is very long and has a lot of if-then-else clauses
* scp and dscp get reused frequently and we need to ensure that
* we don't lose a reference. Start by ensuring that they are NULL.
*/
scp = NULL;
dscp = NULL;
treeCreate = FALSE;
foundscp = FALSE;
scp = NULL;
nameLength = smb_GetSMBOffsetParm(inp, 2, 1);
flags = smb_GetSMBOffsetParm(inp, 3, 1)
@ -5035,8 +5048,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (desiredAccess & AFS_ACCESS_WRITE)
fidflags |= SMB_FID_OPENWRITE;
dscp = NULL;
code = 0;
/* For an exclusive create, we want to do a case sensitive match for the last component. */
if ( createDisp == FILE_CREATE ||
createDisp == FILE_OVERWRITE ||
@ -5057,15 +5070,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
return CM_ERROR_EXISTS;
}
}
} else
dscp = NULL;
}
/* we have both scp and dscp */
} else {
code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, tidPathp, &req, &scp);
/* we might have scp but not dscp */
}
if (code == 0)
foundscp = TRUE;
if (scp)
foundscp = TRUE;
if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
/* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
@ -5073,8 +5088,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
* recognize.
*/
if ( !dscp ) {
while (1) {
/* we might or might not have scp */
if (dscp == NULL) {
do {
char *tp;
code = cm_NameI(baseDirp, spacep->data,
@ -5094,20 +5111,27 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_ReleaseFID(baseFidp);
cm_ReleaseUser(userp);
free(realPathp);
if (scp)
cm_ReleaseSCache(scp);
return CM_ERROR_BADNTFILENAME;
}
code = 0;
}
else
break;
}
} while (dscp == NULL && code == 0);
} else
code = 0;
code = 0;
/* we might have scp and we might have dscp */
if (baseFid != 0)
smb_ReleaseFID(baseFidp);
if (code) {
osi_Log0(smb_logp,"NTCreateX parent not found");
if (scp)
cm_ReleaseSCache(scp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
@ -5115,6 +5139,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
/* A file exists where we want a directory. */
if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
@ -5127,6 +5153,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
lastNamep++;
if (!smb_IsLegalFilename(lastNamep)) {
if (scp)
cm_ReleaseSCache(scp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
@ -5152,196 +5181,206 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
return code;
}
}
}
else {
/* we have scp and dscp */
} else {
/* we have scp but not dscp */
if (baseFid != 0)
smb_ReleaseFID(baseFidp);
}
}
/* if we get here, if code is 0, the file exists and is represented by
* scp. Otherwise, we have to create it. The dir may be represented
* by dscp, or we may have found the file directly. If code is non-zero,
* scp is NULL.
*/
if (code == 0 && !treeCreate) {
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_EXISTS;
}
if ( createDisp == FILE_OVERWRITE ||
createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
targetScp = 0;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
code = cm_SetAttr(scp, &setAttr, userp, &req);
openAction = 3; /* truncated existing file */
}
else
openAction = 1; /* found existing file */
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
&req);
if (code) {
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
}
}
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
/* if we get here, if code is 0, the file exists and is represented by
* scp. Otherwise, we have to create it. The dir may be represented
* by dscp, or we may have found the file directly. If code is non-zero,
* scp is NULL.
*/
if (code == 0 && !treeCreate) {
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOSUCHFILE;
}
else if (realDirFlag == 0 || realDirFlag == -1) {
osi_assert(dscp != NULL);
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
&req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
return CM_ERROR_EXISTS;
}
if ( createDisp == FILE_OVERWRITE ||
createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
targetScp = 0;
osi_assert(dscp != NULL);
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
code = cm_SetAttr(scp, &setAttr, userp, &req);
openAction = 3; /* truncated existing file */
}
else
openAction = 1; /* found existing file */
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
if (code) {
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
}
} else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOSUCHFILE;
} else if (realDirFlag == 0 || realDirFlag == -1) {
osi_assert(dscp != NULL);
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s",
osi_LogSaveString(smb_logp, lastNamep));
openAction = 2; /* created file */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, &req);
if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
* fails, that means that the file was deleted after we
* started this call.
*/
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
if (code == 0) {
if (createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
targetScp = 0;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
code = cm_SetAttr(scp, &setAttr, userp, &req);
}
} /* lookup succeeded */
}
} else {
char *tp, *pp;
char *cp; /* This component */
int clen = 0; /* length of component */
cm_scache_t *tscp1, *tscp2;
int isLast = 0;
/* create directory */
if ( !treeCreate )
treeStartp = lastNamep;
osi_assert(dscp != NULL);
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
osi_LogSaveString(smb_logp, treeStartp));
openAction = 2; /* created directory */
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
pp = treeStartp;
cp = spacep->data;
tscp1 = dscp;
cm_HoldSCache(tscp1);
tscp2 = NULL;
while (pp && *pp) {
tp = strchr(pp, '\\');
if (!tp) {
strcpy(cp,pp);
clen = strlen(cp);
isLast = 1; /* indicate last component. the supplied path never ends in a slash */
} else {
clen = tp - pp;
strncpy(cp,pp,clen);
*(cp + clen) = 0;
tp++;
}
pp = tp;
if (clen == 0)
continue; /* the supplied path can't have consecutive slashes either , but */
/* cp is the next component to be created. */
code = cm_MakeDir(tscp1, cp, 0, &setAttr, userp, &req);
if (code == 0 && (tscp1->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
FILE_NOTIFY_CHANGE_DIR_NAME,
tscp1, cp, NULL, TRUE);
if (code == 0 ||
(code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
* fails, that means that the file was deleted after we
* started this call.
*/
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
if (code == 0) {
if (createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
code = cm_Lookup(tscp1, cp, CM_FLAG_CASEFOLD,
userp, &req, &tscp2);
}
if (code)
break;
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
targetScp = 0;
code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req);
if (code == 0) {
/* we have a more accurate file to use (the
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
code = cm_SetAttr(scp, &setAttr, userp, &req);
}
} /* lookup succeeded */
if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
cm_ReleaseSCache(tscp1);
tscp1 = tscp2; /* Newly created directory will be next parent */
/* the hold is transfered to tscp1 from tscp2 */
}
}
else {
char *tp, *pp;
char *cp; /* This component */
int clen = 0; /* length of component */
cm_scache_t *tscp;
int isLast = 0;
/* create directory */
if ( !treeCreate )
treeStartp = lastNamep;
osi_assert(dscp != NULL);
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
osi_LogSaveString(smb_logp, treeStartp));
openAction = 2; /* created directory */
}
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
pp = treeStartp;
cp = spacep->data;
tscp = dscp;
while (pp && *pp) {
tp = strchr(pp, '\\');
if (!tp) {
strcpy(cp,pp);
clen = strlen(cp);
isLast = 1; /* indicate last component. the supplied path never ends in a slash */
}
else {
clen = tp - pp;
strncpy(cp,pp,clen);
*(cp + clen) = 0;
tp++;
}
pp = tp;
if (clen == 0)
continue; /* the supplied path can't have consecutive slashes either , but */
/* cp is the next component to be created. */
code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_DIR_NAME,
tscp, cp, NULL, TRUE);
if (code == 0 ||
(code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) {
/* Not an exclusive create, and someone else tried
* creating it already, then we open it anyway. We
* don't bother retrying after this, since if this next
* fails, that means that the file was deleted after we
* started this call.
*/
code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
userp, &req, &scp);
}
if (code) break;
if (!isLast) { /* for anything other than dscp, release it unless it's the last one */
cm_ReleaseSCache(tscp);
tscp = scp; /* Newly created directory will be next parent */
}
}
/*
* if we get here and code == 0, then scp is the last directory created, and tscp is the
* parent of scp. dscp got released if dscp != tscp. both tscp and scp are held.
*/
dscp = tscp;
}
cm_ReleaseSCache(dscp);
dscp = tscp1;
cm_ReleaseSCache(scp);
scp = tscp2;
/*
* if we get here and code == 0, then scp is the last directory created, and dscp is the
* parent of scp.
*/
}
if (code) {
/* something went wrong creating or truncating the file */
if (scp) cm_ReleaseSCache(scp);
if (dscp) cm_ReleaseSCache(dscp);
if (scp)
cm_ReleaseSCache(scp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
@ -5359,14 +5398,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
* target of the symbolic link). Otherwise,
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
free(realPathp);
@ -5377,7 +5417,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* (only applies to single component case) */
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
cm_ReleaseSCache(scp);
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOTDIR;
@ -5387,7 +5427,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
osi_assert(fidp);
/* save a pointer to the vnode */
fidp->scp = scp;
fidp->scp = scp; /* Hold transfered to fidp->scp and no longer needed */
fidp->flags = fidflags;
@ -5401,7 +5441,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
fidp->NTopen_wholepathp = realPathp;
/* we don't need this any longer */
if (dscp) cm_ReleaseSCache(dscp);
if (dscp) {
cm_ReleaseSCache(dscp);
dscp = NULL;
}
cm_Open(scp, 0, userp);
/* set inp->fid so that later read calls in same msg can find fid */
@ -5442,6 +5485,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
return 0;
}
/*
* A lot of stuff copied verbatim from NT Create&X to NT Tran Create.
* Instead, ultimately, would like to use a subroutine for common code.
@ -6352,7 +6396,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
}
smb_SendPacket(vcp, watch);
smb_ReleaseVC(vcp);
smb_FreePacket(watch);
watch = nextWatch;
}
@ -6419,8 +6462,6 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
((smb_t *)watch)->errHigh = 0xC0;
((smb_t *)watch)->flg2 |= SMB_FLAGS2_ERR_STATUS;
smb_SendPacket(vcp, watch);
if (watch->vcp)
smb_ReleaseVC(watch->vcp);
smb_FreePacket(watch);
return 0;
}
@ -6445,7 +6486,6 @@ long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
{
char *oldPathp, *newPathp;
long code = 0;
cm_user_t *userp;
char * tp;
int attrs;
int rename_type;