mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 13:38:01 +00:00
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:
parent
cadc5b46e1
commit
eabe2b6f77
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user