#endif /* SPECIAL_FOLDERS */
} else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
- } else
+ } else if (scp->fid.vnode & 0x1)
+ attrs = SMB_ATTR_DIRECTORY;
+ else
attrs = 0;
+
/*
* We used to mark a file RO if it was in an RO volume, but that
* turns out to be impolitic in NT. See defect 10007.
rootShares.cShare = 0;
rootShares.shares = malloc( sizeof(smb_rap_share_info_0_t) * SMB_RAP_MAX_SHARES );
- cm_InitReq(&req);
+ smb_InitReq(&req);
userp = smb_GetTran2User(vcp,p);
cm_user_t *userp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
tp = p->parmsp + 1; /* skip over function number (always 1) */
cm_req_t req;
int created = 0;
- cm_InitReq(&req);
+ smb_InitReq(&req);
scp = NULL;
case SMB_INFO_VOLUME:
/* volume info */
qi.u.volumeInfo.vsn = 1234; /* Volume serial number */
- qi.u.volumeInfo.vnCount = 4; /* Number of characters in label (AFS\0)*/
+ qi.u.volumeInfo.vnCount = 3; /* Number of characters in label (AFS\0)*/
/* we're supposed to pad it out with zeroes to the end */
memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
}
qi.u.FSvolumeInfo.vsn = 1234;
- qi.u.FSvolumeInfo.vnCount = 8; /* This is always in Unicode */
+ qi.u.FSvolumeInfo.vnCount = 6; /* This is always in Unicode */
+ memset(&qi.u.FSvolumeInfo.label, 0, sizeof(qi.u.FSvolumeInfo.label));
memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
break;
#ifdef SMB_UNICODE
}
#endif
- smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, 0);
+ smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, SMB_STRF_IGNORENUL);
qi.u.FSattributeInfo.FSnameLength = sz;
responseSize =
cm_user_t *userp;
cm_space_t *spacep;
cm_scache_t *scp, *dscp;
- int scp_mx_held = 0;
+ int scp_rw_held = 0;
int delonclose = 0;
long code = 0;
clientchar_t *pathp;
clientchar_t *lastComp;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
infoLevel = p->parmsp[0];
if (infoLevel == SMB_INFO_IS_NAME_VALID)
#endif /* DFS_SUPPORT */
lock_ObtainWrite(&scp->rw);
- scp_mx_held = 1;
+ scp_rw_held = 2;
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) goto done;
+ if (code)
+ goto done;
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ConvertWToR(&scp->rw);
+ scp_rw_held = 1;
len = 0;
goto done;
}
- smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAltNameInfo.fileNameLength = len;
goto done;
}
else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
- smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileNameInfo.fileNameLength = len;
goto done;
qpi.u.QPfileBasicInfo.reserved = 0;
}
else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
- smb_fid_t *fidp = smb_FindFIDByScache(vcp, scp);
+ smb_fid_t * fidp;
+
+ lock_ReleaseRead(&scp->rw);
+ scp_rw_held = 0;
+ fidp = smb_FindFIDByScache(vcp, scp);
qpi.u.QPfileStandardInfo.allocationSize = scp->length;
qpi.u.QPfileStandardInfo.endOfFile = scp->length;
qpi.u.QPfileStandardInfo.reserved = 0;
if (fidp) {
- lock_ReleaseRead(&scp->rw);
- scp_mx_held = 0;
lock_ObtainMutex(&fidp->mx);
delonclose = fidp->flags & SMB_FID_DELONCLOSE;
lock_ReleaseMutex(&fidp->mx);
qpi.u.QPfileAllInfo.mode = 0;
qpi.u.QPfileAllInfo.alignmentRequirement = 0;
- smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, 0);
+ smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
qpi.u.QPfileAllInfo.fileNameLength = len;
}
/* send and free the packets */
done:
- if (scp_mx_held)
+ switch (scp_rw_held) {
+ case 1:
lock_ReleaseRead(&scp->rw);
+ break;
+ case 2:
+ lock_ReleaseWrite(&scp->rw);
+ break;
+ }
+ scp_rw_held = 0;
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
if (code == 0) {
clientchar_t *tidPathp;
clientchar_t *lastComp;
- cm_InitReq(&req);
+ smb_InitReq(&req);
infoLevel = p->parmsp[0];
osi_Log1(smb_logp,"ReceiveTran2SetPathInfo type 0x%x", infoLevel);
int readlock = 0;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = p->parmsp[0];
fidp = smb_FindFID(vcp, fid, 0);
name = _C("\\"); /* probably can't happen */
lock_ReleaseMutex(&fidp->mx);
- smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, 0);
+ smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, SMB_STRF_IGNORENUL);
outp->totalData = len + 4; /* this is actually what we want to return */
qfi.u.QFfileNameInfo.fileNameLength = len;
}
cm_scache_t *scp = NULL;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = p->parmsp[0];
fidp = smb_FindFID(vcp, fid, 0);
int i, nbnLen, reqLen, refLen;
int idx;
- cm_InitReq(&req);
+ smb_InitReq(&req);
maxReferralLevel = p->parmsp[0];
}
static long
-smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp,
+smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
clientchar_t * tidPathp, clientchar_t * relPathp,
- int infoLevel, cm_user_t *userp,
- cm_req_t *reqp)
+ int infoLevel, cm_user_t *userp, cm_req_t *reqp)
{
long code = 0;
cm_scache_t *scp;
clientchar_t path[AFSPATHMAX];
code = cm_FindACLCache(dscp, userp, &rights);
- if (code == 0 && !(rights & PRSFS_READ))
- mustFake = 1;
- else if (code == -1) {
+ if (code == -1) {
lock_ObtainWrite(&dscp->rw);
code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == 0)
+ cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&dscp->rw);
if (code == CM_ERROR_NOACCESS) {
mustFake = 1;
}
}
if (code)
- return code;
+ goto cleanup;
+
+ 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; patchp; patchp =
- (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ for (patchp = *dirPatchespp, count=0;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+ cm_scache_t *tscp = NULL;
+ int i;
+
+ code = cm_GetSCache(&patchp->fid, &tscp, userp, reqp);
+ if (code == 0) {
+ if (lock_TryWrite(&tscp->rw)) {
+ /* we have an entry that we can look at */
+#ifdef AFS_FREELANCE_CLIENT
+ if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
+ code = cm_SyncOp(tscp, NULL, userp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == 0)
+ cm_SyncOpDone(tscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+ lock_ReleaseWrite(&tscp->rw);
+ cm_ReleaseSCache(tscp);
+ continue;
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+ if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
+ /* we have a callback on it. Don't bother
+ * fetching this stat entry, since we're happy
+ * with the info we have.
+ */
+ lock_ReleaseWrite(&tscp->rw);
+ cm_ReleaseSCache(tscp);
+ continue;
+ }
+ lock_ReleaseWrite(&tscp->rw);
+ } /* got lock */
+ cm_ReleaseSCache(tscp);
+ } /* found entry */
+
+ i = bsp->counter++;
+ bsp->fids[i].Volume = patchp->fid.volume;
+ bsp->fids[i].Vnode = patchp->fid.vnode;
+ bsp->fids[i].Unique = patchp->fid.unique;
+
+ if (bsp->counter == AFSCBMAX) {
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+ memset(bsp, 0, sizeof(cm_bulkStat_t));
+ }
+ }
+
+ if (bsp->counter > 0)
+ code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+
+ free(bsp);
+ }
+
+ for( patchp = *dirPatchespp;
+ patchp;
+ patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
cm_ClientStrPrintfN(path, lengthof(path),_C("%s\\%S"),
relPathp ? relPathp : _C(""), patchp->dep->name);
reqp->relPathp = path;
continue;
lock_ObtainWrite(&scp->rw);
- if (mustFake == 0)
- code = cm_SyncOp(scp, NULL, userp, reqp, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (mustFake || code) {
+ if (mustFake || (scp->flags & CM_SCACHEFLAG_EACCESS) || !cm_HaveCallback(scp)) {
lock_ReleaseWrite(&scp->rw);
/* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter'
switch (scp->fileType) {
case CM_SCACHETYPE_DIRECTORY:
case CM_SCACHETYPE_MOUNTPOINT:
- case CM_SCACHETYPE_SYMLINK:
case CM_SCACHETYPE_INVALID:
fa->extFileAttributes = SMB_ATTR_DIRECTORY;
break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ fa->extFileAttributes = SMB_ATTR_DIRECTORY;
+ else
+ fa->extFileAttributes = SMB_ATTR_NORMAL;
+ break;
default:
/* if we get here we either have a normal file
* or we have a file for which we have never
* received status info. In this case, we can
* check the even/odd value of the entry's vnode.
- * even means it is to be treated as a directory
- * and odd means it is to be treated as a file.
+ * odd means it is to be treated as a directory
+ * and even means it is to be treated as a file.
*/
if (mustFake && (scp->fid.vnode & 0x1))
fa->extFileAttributes = SMB_ATTR_DIRECTORY;
else
fa->extFileAttributes = SMB_ATTR_NORMAL;
-
}
/* merge in hidden attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
switch (scp->fileType) {
case CM_SCACHETYPE_DIRECTORY:
case CM_SCACHETYPE_MOUNTPOINT:
- case CM_SCACHETYPE_SYMLINK:
case CM_SCACHETYPE_INVALID:
fa->attributes = SMB_ATTR_DIRECTORY;
+ break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ fa->attributes = SMB_ATTR_DIRECTORY;
+ else
+ fa->attributes = SMB_ATTR_NORMAL;
+ break;
default:
- fa->attributes = SMB_ATTR_NORMAL;
+ /* if we get here we either have a normal file
+ * or we have a file for which we have never
+ * received status info. In this case, we can
+ * check the even/odd value of the entry's vnode.
+ * even means it is to be treated as a directory
+ * and odd means it is to be treated as a file.
+ */
+ if (mustFake && (scp->fid.vnode & 0x1))
+ fa->attributes = SMB_ATTR_DIRECTORY;
+ else
+ fa->attributes = SMB_ATTR_NORMAL;
}
+
/* merge in hidden (dot file) attribute */
if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) {
fa->attributes |= SMB_ATTR_HIDDEN;
continue;
}
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-
/* now watch for a symlink */
code = 0;
while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
/* Copy attributes */
lattr = smb_ExtAttributes(scp);
- if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK ||
+ if ((code == CM_ERROR_NOSUCHPATH &&
+ (scp->fileType == CM_SCACHETYPE_SYMLINK &&
+ cm_TargetPerceivedAsDirectory(scp->mountPointStringp))) ||
code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
if (lattr == SMB_ATTR_NORMAL)
lattr = SMB_ATTR_DIRECTORY;
/* and mark the list as empty */
*dirPatchespp = NULL;
+ cleanup:
return code;
}
void * attrp = NULL;
smb_tran2Find_t * fp;
- cm_InitReq(&req);
+ smb_InitReq(&req);
eos = 0;
osi_assertx(p->opcode == 1, "invalid opcode");
maxReturnParms = 10; /* return params for findfirst, which
is the only one we handle.*/
-#ifndef CM_CONFIG_MULTITRAN2RESPONSES
- if (maxReturnData > 6000)
- maxReturnData = 6000;
-#endif /* CM_CONFIG_MULTITRAN2RESPONSES */
-
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
/* add header to name & term. null */
onbytes = 0;
- smb_UnparseString(opx, NULL, maskp, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, NULL, maskp, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
orbytes = ohbytes + onbytes;
/* now, we round up the record to a 4 byte alignment, and we make
memset(origOp, 0, orbytes);
onbytes = 0;
- smb_UnparseString(opx, origOp + ohbytes, maskp, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, origOp + ohbytes, maskp, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
switch (infoLevel) {
case SMB_INFO_STANDARD:
#ifdef SMB_UNICODE
int nchars;
- nchars = cm_ClientStringToUtf16(shortName, -1,
+ nchars = cm_ClientStringToUtf16(shortName, cm_ClientStrLen(shortName),
fp->u.FfileBothDirectoryInfo.shortName,
sizeof(fp->u.FfileBothDirectoryInfo.shortName)/sizeof(wchar_t));
if (nchars > 0)
- fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t);
+ fp->u.FfileBothDirectoryInfo.shortNameLength = nchars*sizeof(wchar_t);
else
fp->u.FfileBothDirectoryInfo.shortNameLength = 0;
fp->u.FfileBothDirectoryInfo.reserved = 0;
char * s;
smb_tran2Find_t * fp;
- cm_InitReq(&req);
+ smb_InitReq(&req);
eos = 0;
if (p->opcode == 1) {
else
maxReturnParms = 8; /* bytes */
-#ifndef CM_CONFIG_MULTITRAN2RESPONSES
- if (maxReturnData > 6000)
- maxReturnData = 6000;
-#endif /* CM_CONFIG_MULTITRAN2RESPONSES */
-
outp = smb_GetTran2ResponsePacket(vcp, p, opx, maxReturnParms,
maxReturnData);
+ if (maxCount > 500)
+ maxCount = 500;
+
osi_Log2(smb_logp, "T2 receive search dir count %d [%S]",
maxCount, osi_LogSaveClientString(smb_logp, pathp));
* and so we do another hold now.
*/
cm_HoldSCache(scp);
- lock_ObtainWrite(&scp->rw);
- if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0 &&
- LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
- scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags |= SMB_DIRSEARCH_BULKST;
- }
- lock_ReleaseWrite(&scp->rw);
+ dsp->flags |= SMB_DIRSEARCH_BULKST;
}
}
lock_ReleaseMutex(&dsp->mx);
break;
}
+ /* when we have obtained as many entries as can be processed in
+ * a single Bulk Status call to the file server, apply the dir listing
+ * patches.
+ */
+ if (returnedNames > 0 && returnedNames % AFSCBMAX == 0) {
+ lock_ReleaseWrite(&scp->rw);
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
+ dsp->relPath, infoLevel, userp, &req);
+ lock_ObtainWrite(&scp->rw);
+ }
+ /* Then check to see if we have time left to process more entries */
+ if (GetTickCount() - req.startTime > (RDRtimeout - 15) * 1000) {
+ osi_Log0(smb_logp, "T2 search dir RDRtimeout exceeded");
+ break;
+ }
+
/* see if we can use the bufferp we have now; compute in which
* page the current offset would be, and check whether that's
* the offset of the buffer we have. If not, get the buffer.
}
lock_ReleaseWrite(&scp->rw);
code = buf_Get(scp, &thyper, &bufferp);
- lock_ObtainMutex(&dsp->mx);
-
- /* now, if we're doing a star match, do bulk fetching
- * of all of the status info for files in the dir.
- */
- if (starPattern) {
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, infoLevel, userp, &req);
-
- lock_ObtainWrite(&scp->rw);
- if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
- LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
- /* Don't bulk stat if risking timeout */
- DWORD now = GetTickCount();
- if (now - req.startTime > RDRtimeout * 1000) {
- scp->bulkStatProgress = thyper;
- scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
- dsp->flags &= ~SMB_DIRSEARCH_BULKST;
- } else
- code = cm_TryBulkStat(scp, &thyper, userp, &req);
- }
- } else {
- lock_ObtainWrite(&scp->rw);
- }
- lock_ReleaseMutex(&dsp->mx);
+ lock_ObtainWrite(&scp->rw);
if (code) {
osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
break;
break;
}
- cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
-
if (cm_HaveBuffer(scp, bufferp, 0)) {
osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+ cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
break;
}
/* otherwise, load the buffer and try again */
code = cm_GetBuffer(scp, bufferp, NULL, userp,
&req);
+ cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
if (code) {
osi_Log3(smb_logp, "T2 search dir cm_GetBuffer failed scp %x bufferp %x code %d",
scp, bufferp, code);
/* finally check if this name will fit */
onbytes = 0;
- smb_UnparseString(opx, NULL, cfileName, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, NULL, cfileName, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
orbytes = ohbytes + onbytes;
/* now, we round up the record to a 4 byte alignment,
memset(origOp, 0, orbytes);
onbytes = 0;
- smb_UnparseString(opx, origOp + ohbytes, cfileName, &onbytes, SMB_STRF_ANSIPATH);
+ smb_UnparseString(opx, origOp + ohbytes, cfileName, &onbytes, SMB_STRF_ANSIPATH|SMB_STRF_IGNORENUL);
switch (infoLevel) {
case SMB_INFO_STANDARD:
#ifdef SMB_UNICODE
int nchars;
- nchars = cm_ClientStringToUtf16(shortName, -1,
+ nchars = cm_ClientStringToUtf16(shortName, cm_ClientStrLen(shortName),
fp->u.FfileBothDirectoryInfo.shortName,
sizeof(fp->u.FfileBothDirectoryInfo.shortName)/sizeof(wchar_t));
if (nchars > 0)
- fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t);
+ fp->u.FfileBothDirectoryInfo.shortNameLength = nchars*sizeof(wchar_t);
else
fp->u.FfileBothDirectoryInfo.shortNameLength = 0;
fp->u.FfileBothDirectoryInfo.reserved = 0;
bufferp = NULL;
}
- /* apply and free last set of patches; if not doing a star match, this
- * will be empty, but better safe (and freeing everything) than sorry.
+ /*
+ * Finally, process whatever entries we have left.
*/
- code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
+ code2 = smb_ApplyV3DirListPatches(scp, &dirListPatchesp, dsp->tidPath,
dsp->relPath, infoLevel, userp, &req);
/* now put out the final parameters */
cm_req_t req;
int created = 0;
- cm_InitReq(&req);
+ smb_InitReq(&req);
scp = NULL;
cm_key_t key;
unsigned int pid;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = smb_GetSMBParm(inp, 2);
fid = smb_ChainFID(fid, inp);
for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
{
for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
- if (wl->key == key && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
+ if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) &&
LargeIntegerEqualTo(wl->LLength, LLength)) {
wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
goto found_lock_request;
cm_req_t req;
int readlock = 0;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = smb_GetSMBParm(inp, 0);
fid = smb_ChainFID(fid, inp);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ConvertWToR(&scp->rw);
+ readlock = 1;
/* decode times. We need a search time, but the response to this
* call provides the date first, not the time, as returned in the
cm_attr_t attrs;
cm_req_t req;
- cm_InitReq(&req);
+ smb_InitReq(&req);
fid = smb_GetSMBParm(inp, 0);
fid = smb_ChainFID(fid, inp);
#define FILE_RANDOM_ACCESS 0x0800
#define FILE_DELETE_ON_CLOSE 0x1000
#define FILE_OPEN_BY_FILE_ID 0x2000
+#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
+#define FILE_NO_COMPRESSION 0x00008000
+#define FILE_RESERVE_OPFILTER 0x00100000
+#define FILE_OPEN_REPARSE_POINT 0x00200000
+#define FILE_OPEN_NO_RECALL 0x00400000
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
/* SMB_COM_NT_CREATE_ANDX */
long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
BOOL foundscp;
cm_req_t req;
int created = 0;
+ int prefetch = 0;
+ int checkDoneRequired = 0;
cm_lock_data_t *ldp = NULL;
- cm_InitReq(&req);
+ smb_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
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (createOptions & FILE_OPEN_REPARSE_POINT)
+ osi_Log0(smb_logp, "NTCreateX Open Reparse Point");
if (smb_IsExecutableFileName(lastNamep))
fidflags |= SMB_FID_EXECUTABLE;
if (code == 0 && !treeCreate) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
free(realPathp);
return code;
}
+ checkDoneRequired = 1;
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
scp = targetScp;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
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);
+ code = cm_MakeDir(tscp1, cp, 0, &setAttr, userp, &req, NULL);
if (code == 0 && (tscp1->flags & CM_SCACHEFLAG_ANYWATCH))
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_DIR_NAME,
if (code) {
/* something went wrong creating or truncating the file */
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (scp)
cm_ReleaseSCache(scp);
* we'll just use the symlink anyway.
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
/* (only applies to single component case) */
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
if (dscp)
lock_ReleaseWrite(&scp->rw);
if (code) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
if (dscp)
}
/* Now its safe to release the file server lock obtained by cm_CheckNTOpen() */
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
if ((fidp->flags & SMB_FID_EXECUTABLE) &&
LargeIntegerGreaterThanZero(fidp->scp->length) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+ prefetch = 1;
+ }
+ lock_ReleaseRead(&scp->rw);
+
+ if (prefetch)
cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
fidp->scp->length.LowPart, fidp->scp->length.HighPart,
userp);
- }
- lock_ReleaseRead(&scp->rw);
+
osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %S", fidp->fid,
osi_LogSaveClientString(smb_logp, realPathp));
unsigned int extendedRespRequired;
int realDirFlag;
unsigned int desiredAccess;
-#ifdef DEBUG_VERBOSE
unsigned int allocSize;
-#endif
unsigned int shareAccess;
unsigned int extAttributes;
unsigned int createDisp;
-#ifdef DEBUG_VERBOSE
unsigned int sdLen;
-#endif
+ unsigned int eaLen;
+ unsigned int impLevel;
+ unsigned int secFlags;
unsigned int createOptions;
int initialModeBits;
unsigned short baseFid;
char *outData;
cm_req_t req;
int created = 0;
+ int prefetch = 0;
cm_lock_data_t *ldp = NULL;
+ int checkDoneRequired = 0;
- cm_InitReq(&req);
+ smb_InitReq(&req);
foundscp = FALSE;
scp = NULL;
return CM_ERROR_INVAL;
baseFid = (unsigned short)lparmp[1];
desiredAccess = lparmp[2];
-#ifdef DEBUG_VERBOSE
allocSize = lparmp[3];
-#endif /* DEBUG_VERSOSE */
extAttributes = lparmp[5];
shareAccess = lparmp[6];
createDisp = lparmp[7];
createOptions = lparmp[8];
-#ifdef DEBUG_VERBOSE
sdLen = lparmp[9];
-#endif
- nameLength = lparmp[11];
-
-#ifdef DEBUG_VERBOSE
- osi_Log4(smb_logp,"NTTranCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
- osi_Log3(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
- osi_Log1(smb_logp,"... flags[%x]",flags);
-#endif
+ eaLen = lparmp[10];
+ nameLength = lparmp[11]; /* spec says chars but appears to be bytes */
+ impLevel = lparmp[12];
+ secFlags = lparmp[13];
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
if (extAttributes & SMB_ATTR_READONLY)
initialModeBits &= ~0222;
- pathp = smb_ParseStringCch(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
+ pathp = smb_ParseStringCb(inp, (parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR)),
nameLength, NULL, SMB_STRF_ANSIPATH);
- /* Sometimes path is not null-terminated, so we make a copy. */
- realPathp = malloc((nameLength+1) * sizeof(clientchar_t));
- memcpy(realPathp, pathp, nameLength * sizeof(clientchar_t));
- realPathp[nameLength] = 0;
+ /* Sometimes path is not nul-terminated, so we make a copy. */
+ realPathp = malloc(nameLength+sizeof(clientchar_t));
+ memcpy(realPathp, pathp, nameLength);
+ realPathp[nameLength/sizeof(clientchar_t)] = 0;
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
+ osi_Log1(smb_logp,"NTTranCreate %S",osi_LogSaveStringW(smb_logp,realPathp));
+ osi_Log4(smb_logp,"... da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+ osi_Log4(smb_logp,"... co[%x],sdl[%x],eal[%x],as[%x],flags[%x]",createOptions,sdLen,eaLen,allocSize);
+ osi_Log3(smb_logp,"... imp[%x],sec[%x],flags[%x]", impLevel, secFlags, flags);
+
/*
* Nothing here to handle SMB_IOCTL_FILENAME.
* Will add it if necessary.
fidflags |= SMB_FID_SEQUENTIAL;
if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
fidflags |= SMB_FID_RANDOM;
+ if (createOptions & FILE_OPEN_REPARSE_POINT)
+ osi_Log0(smb_logp, "NTTranCreate Open Reparse Point");
if (smb_IsExecutableFileName(lastNamep))
fidflags |= SMB_FID_EXECUTABLE;
if (code == 0) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
free(realPathp);
return code;
}
+ checkDoneRequired = 1;
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
scp = targetScp;
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
if (code) {
+ cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (dscp)
cm_ReleaseSCache(dscp);
if (scp)
openAction = 2; /* created directory */
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,
if (code) {
/* something went wrong creating or truncating the file */
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
if (scp)
cm_ReleaseSCache(scp);
*/
osi_Log2(smb_logp, "symlink vp %x to vp %x",
scp, targetScp);
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
cm_ReleaseSCache(scp);
scp = targetScp;
}
}
if (scp->fileType != CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
}
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
lock_ReleaseWrite(&scp->rw);
if (code) {
- if (ldp)
+ if (checkDoneRequired)
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
cm_ReleaseSCache(scp);
cm_ReleaseUser(userp);
}
/* Now its safe to drop the file server lock obtained by cm_CheckNTOpen() */
- if (ldp)
+ if (checkDoneRequired) {
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+ checkDoneRequired = 0;
+ }
lock_ObtainMutex(&fidp->mx);
/* save a pointer to the vnode */
if ((fidp->flags & SMB_FID_EXECUTABLE) &&
LargeIntegerGreaterThanZero(fidp->scp->length) &&
!(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
+ prefetch = 1;
+ }
+ lock_ReleaseRead(&scp->rw);
+
+ if (prefetch)
cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
fidp->scp->length.LowPart, fidp->scp->length.HighPart,
userp);
- }
- lock_ReleaseRead(&scp->rw);
osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
* notification if in the future a matching change is detected.
*/
savedPacketp = smb_CopyPacket(inp);
- smb_HoldVC(vcp);
- if (savedPacketp->vcp)
- smb_ReleaseVC(savedPacketp->vcp);
- savedPacketp->vcp = vcp;
+ if (vcp != savedPacketp->vcp) {
+ smb_HoldVC(vcp);
+ if (savedPacketp->vcp)
+ smb_ReleaseVC(savedPacketp->vcp);
+ savedPacketp->vcp = vcp;
+ }
/* Add the watch to the list of events to send notifications for */
lock_ObtainMutex(&smb_Dir_Watch_Lock);
(!isDirectParent && !wtree))
{
osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
- smb_ReleaseFID(fidp);
lastWatch = watch;
watch = watch->nextp;
+ smb_ReleaseFID(fidp);
continue;
}
- smb_ReleaseFID(fidp);
osi_Log4(smb_logp,
"Sending Change Notification for fid %d filter 0x%x wtree %d file %S",
smb_SendPacket(watch->vcp, watch);
smb_FreePacket(watch);
+
+ smb_ReleaseFID(fidp);
watch = nextWatch;
}
lock_ReleaseMutex(&smb_Dir_Watch_Lock);
osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
osi_LogSaveClientString(smb_logp, oldPathp),
osi_LogSaveClientString(smb_logp, newPathp),
- ((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink"));
+ ((rename_type==RENAME_FLAG_RENAME)?"rename":(rename_type==RENAME_FLAG_HARD_LINK)?"hardlink":"other"));
if (rename_type == RENAME_FLAG_RENAME) {
code = smb_Rename(vcp,inp,oldPathp,newPathp,attrs);
- } else { /* RENAME_FLAG_HARD_LINK */
+ } else if (rename_type == RENAME_FLAG_HARD_LINK) { /* RENAME_FLAG_HARD_LINK */
code = smb_Link(vcp,inp,oldPathp,newPathp);
- }
+ } else
+ code = CM_ERROR_BADOP;
return code;
}
void smb3_Init()
{
- lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
+ lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock", LOCK_HIERARCHY_SMB_DIRWATCH);
}
cm_user_t *smb_FindCMUserByName(clientchar_t *usern, clientchar_t *machine, afs_uint32 flags)
lock_ReleaseMutex(&unp->mx);
osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
} else {
- osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
+ osi_Log2(smb_logp,"smb_FindCMUserByName Found name[%S] machine[%S]",osi_LogSaveClientString(smb_logp,usern),osi_LogSaveClientString(smb_logp,machine));
}
userp = unp->userp;
cm_HoldUser(userp);