From 6a9324ad733385d39594c770227809333248251b Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 23 Jun 2011 17:51:22 -0400 Subject: [PATCH] Windows: TRANS2_FIND_FIRST2 for _._AFS_IOCTL_._ smb_T2SearchDirSingle() must not fail directory search requests for the _._AFS_IOCTL_._ file. Although this file does not actually exist, it is successfully processed by CreateFile operations. Therefore, an explicit search for it should return a valid answer. Reviewed-on: http://gerrit.openafs.org/4884 Tested-by: BuildBot Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman (cherry-picked from 9f77a2d6b3d571a928261563763913c8c6ee2938) Change-Id: Iab58557350fa099c903b0c2b555e5cc2027daafc Reviewed-on: http://gerrit.openafs.org/4894 Tested-by: BuildBot Reviewed-by: Derrick Brashear Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/smb.h | 5 +- src/WINNT/afsd/smb3.c | 148 ++++++++++++++++++++++++++---------- src/WINNT/afsd/smb_iocons.h | 2 + 3 files changed, 112 insertions(+), 43 deletions(-) diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 0bd48dbd7..f44e0da2b 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -488,17 +488,18 @@ typedef struct smb_dirSearch { /* type for patching directory listings */ typedef struct smb_dirListPatch { osi_queue_t q; - char *dptr; /* ptr to attr, time, data, sizel, sizeh */ + char *dptr; /* ptr to attr, time, data, sizel, sizeh */ long flags; /* flags. See below */ cm_fid_t fid; cm_dirEntry_t *dep; /* temp */ } smb_dirListPatch_t; /* dirListPatch Flags */ -#define SMB_DIRLISTPATCH_DOTFILE 1 +#define SMB_DIRLISTPATCH_DOTFILE 1 /* the file referenced is a dot file * Note: will not be set if smb_hideDotFiles is false */ +#define SMB_DIRLISTPATCH_IOCTL 2 /* individual lock on a waiting lock request */ typedef struct smb_waitingLock { diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index dc3c39854..0d6e5841c 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -1,3 +1,4 @@ + /* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. @@ -4578,6 +4579,10 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp, cm_scache_t *tscp = NULL; int i; + /* Do not look for a cm_scache_t or bulkstat an ioctl entry */ + if (patchp->flags & SMB_DIRLISTPATCH_IOCTL) + continue; + code = cm_GetSCache(&patchp->fid, &tscp, userp, reqp); if (code == 0) { if (lock_TryWrite(&tscp->rw)) { @@ -4633,6 +4638,36 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp, reqp->relPathp = path; reqp->tidPathp = tidPathp; + if (patchp->flags & SMB_DIRLISTPATCH_IOCTL) { + /* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter' + errors in the client. */ + if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) { + smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr; + + /* 1969-12-31 23:59:59 +00 */ + ft.dwHighDateTime = 0x19DB200; + ft.dwLowDateTime = 0x5BB78980; + + /* copy to Creation Time */ + fa->creationTime = ft; + fa->lastAccessTime = ft; + fa->lastWriteTime = ft; + fa->lastChangeTime = ft; + fa->extFileAttributes = SMB_ATTR_SYSTEM | SMB_ATTR_HIDDEN; + } else { + smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr; + + /* 1969-12-31 23:59:58 +00*/ + dosTime = 0xEBBFBF7D; + + fa->creationDateTime = MAKELONG(HIWORD(dosTime),LOWORD(dosTime)); + fa->lastAccessDateTime = fa->creationDateTime; + fa->lastWriteDateTime = fa->creationDateTime; + fa->attributes = SMB_ATTR_SYSTEM|SMB_ATTR_HIDDEN; + } + continue; + } + code = cm_GetSCache(&patchp->fid, &scp, userp, reqp); reqp->relPathp = reqp->tidPathp = NULL; if (code) @@ -4871,7 +4906,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op size_t ohbytes; /* # of bytes, except file name */ size_t onbytes; /* # of bytes in name, incl. term. null */ cm_scache_t *scp = NULL; - cm_scache_t *targetscp = NULL; + cm_scache_t *targetScp = NULL; cm_user_t *userp = NULL; char *op; /* output data ptr */ char *origOp; /* original value of op */ @@ -4886,7 +4921,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op smb_tran2Packet_t *outp; /* response packet */ clientchar_t *tidPathp = 0; int align; - clientchar_t shortName[13]; /* 8.3 name if needed */ + clientchar_t shortName[13]; /* 8.3 name if needed */ int NeedShortName; clientchar_t *shortNameEnd; cm_dirEntry_t * dep = NULL; @@ -4894,6 +4929,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op char * s; void * attrp = NULL; smb_tran2Find_t * fp; + int afs_ioctl = 0; /* is this query for _._AFS_IOCTL_._? */ + cm_dirFid_t dfid; smb_InitReq(&req); @@ -5045,32 +5082,43 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op #endif /* DFS_SUPPORT */ osi_Log1(smb_logp,"T2SDSingle scp 0x%p", scp); - /* now do a single case sensitive lookup for the file in question */ - code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetscp); + afs_ioctl = (cm_ClientStrCmpI(maskp, CM_IOCTL_FILENAME_NOSLASH_W) == 0); - /* if a case sensitive match failed, we try a case insensitive one - next. */ - if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) { - code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE | CM_FLAG_CASEFOLD, userp, &req, &targetscp); - } + /* + * If we are not searching for _._AFS_IOCTL_._, then we need to obtain + * the target scp. + */ + if (!afs_ioctl) { + /* now do a single case sensitive lookup for the file in question */ + code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE, userp, &req, &targetScp); - if (code == 0 && targetscp->fid.vnode == 0) { - cm_ReleaseSCache(targetscp); - code = CM_ERROR_NOSUCHFILE; - } + /* + * if a case sensitive match failed, we try a case insensitive + * one next. + */ + if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) + code = cm_Lookup(scp, maskp, CM_FLAG_NOMOUNTCHASE | CM_FLAG_CASEFOLD, userp, &req, &targetScp); - if (code) { - /* if we can't find the directory entry, this block will - return CM_ERROR_NOSUCHFILE, which we will pass on to - smb_ReceiveTran2SearchDir(). */ - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { - smb_SendTran2Error(vcp, p, opx, code); - code = 0; - } - smb_FreeTran2Packet(outp); - return code; + if (code == 0 && targetScp->fid.vnode == 0) { + cm_ReleaseSCache(targetScp); + code = CM_ERROR_NOSUCHFILE; + } + + if (code) { + /* + * if we can't find the directory entry, this block will + * return CM_ERROR_NOSUCHFILE, which we will pass on to + * smb_ReceiveTran2SearchDir(). + */ + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + if (code != CM_ERROR_NOSUCHFILE && code != CM_ERROR_BPLUS_NOMATCH) { + smb_SendTran2Error(vcp, p, opx, code); + code = 0; + } + smb_FreeTran2Packet(outp); + return code; + } } /* now that we have the target in sight, we proceed with filling @@ -5087,12 +5135,20 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op fp = (smb_tran2Find_t *) op; if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO - && targetscp->fid.vnode != 0 && !cm_Is8Dot3(maskp)) { - cm_dirFid_t dfid; - dfid.vnode = htonl(targetscp->fid.vnode); - dfid.unique = htonl(targetscp->fid.unique); + /* + * Since the _._AFS_IOCTL_._ file does not actually exist + * we will make up a per directory FID equivalent to the + * directory vnode and the uniqifier 0. + */ + if (afs_ioctl) { + dfid.vnode = htonl(scp->fid.vnode); + dfid.unique = htonl(0); + } else { + dfid.vnode = htonl(targetScp->fid.vnode); + dfid.unique = htonl(targetScp->fid.unique); + } cm_Gen8Dot3NameIntW(maskp, &dfid, shortName, &shortNameEnd); NeedShortName = 1; @@ -5101,8 +5157,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op } osi_Log4(smb_logp, "T2SDSingle dir vn %u uniq %u name %S (%S)", - htonl(targetscp->fid.vnode), - htonl(targetscp->fid.unique), + ntohl(dfid.vnode), + ntohl(dfid.unique), osi_LogSaveClientString(smb_logp, pathp), (NeedShortName)? osi_LogSaveClientString(smb_logp, shortName) : _C("")); @@ -5117,10 +5173,11 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op } if (!(attribute & SMB_ATTR_DIRECTORY) && - (targetscp->fileType == CM_SCACHETYPE_DIRECTORY || - targetscp->fileType == CM_SCACHETYPE_MOUNTPOINT || - targetscp->fileType == CM_SCACHETYPE_DFSLINK || - targetscp->fileType == CM_SCACHETYPE_INVALID)) { + !afs_ioctl && + (targetScp->fileType == CM_SCACHETYPE_DIRECTORY || + targetScp->fileType == CM_SCACHETYPE_MOUNTPOINT || + targetScp->fileType == CM_SCACHETYPE_DFSLINK || + targetScp->fileType == CM_SCACHETYPE_INVALID)) { code = CM_ERROR_NOSUCHFILE; osi_Log0(smb_logp, "T2SDSingle skipping directory or bad link"); @@ -5239,16 +5296,24 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op curPatchp->flags = 0; } - cm_SetFid(&curPatchp->fid, targetscp->fid.cell, targetscp->fid.volume, targetscp->fid.vnode, targetscp->fid.unique); - /* temp */ { int namelen = cm_ClientStringToFsString(maskp, -1, NULL, 0); dep = (cm_dirEntry_t *)malloc(sizeof(cm_dirEntry_t)+namelen); cm_ClientStringToFsString(maskp, -1, dep->name, namelen); } - dep->fid.vnode = targetscp->fid.vnode; - dep->fid.unique = targetscp->fid.unique; + + if (afs_ioctl) { + cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, scp->fid.vnode, 0); + dep->fid.vnode = scp->fid.vnode; + dep->fid.unique = 0; + curPatchp->flags |= SMB_DIRLISTPATCH_IOCTL; + } else { + cm_SetFid(&curPatchp->fid, targetScp->fid.cell, targetScp->fid.volume, targetScp->fid.vnode, targetScp->fid.unique); + dep->fid.vnode = targetScp->fid.vnode; + dep->fid.unique = targetScp->fid.unique; + } + curPatchp->dep = dep; } @@ -5295,8 +5360,9 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op if (dep) free(dep); if (scp) - cm_ReleaseSCache(scp); - cm_ReleaseSCache(targetscp); + cm_ReleaseSCache(scp); + if (targetScp) + cm_ReleaseSCache(targetScp); cm_ReleaseUser(userp); return code; diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index 0fb54ae88..3015aa695 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -110,7 +110,9 @@ struct sbstruct { /* magic file name for ioctl opens */ #define CM_IOCTL_FILENAME "\\_._AFS_IOCTL_._" /* double backslashes for C compiler */ +#define CM_IOCTL_FILENAME_W L"\\_._AFS_IOCTL_._" /* double backslashes for C compiler */ #define CM_IOCTL_FILENAME_NOSLASH "_._AFS_IOCTL_._" +#define CM_IOCTL_FILENAME_NOSLASH_W L"_._AFS_IOCTL_._" /* max parms for ioctl, in either direction */ #define CM_IOCTL_MAXDATA 8192*2 -- 2.39.5