From f9191fdebcf694f1a6afac8c0f4679c35114ce93 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 18 Oct 2008 18:01:07 +0000 Subject: [PATCH] smb-symlink-to-vnovnode-attribute-20081017 LICENSE MIT When reporting the attribute of a directory name which happens to be a symlink object to a file that cannot be accessed or does not exist, use the target name to guess the type of the object. If it has an extension, consider it a file, otherwise report it as a directory. --- src/WINNT/afsd/NTMakefile | 2 +- src/WINNT/afsd/cm_utils.c | 12 ++++++++++++ src/WINNT/afsd/cm_utils.h | 2 ++ src/WINNT/afsd/smb.c | 25 ++++++++----------------- src/WINNT/afsd/smb3.c | 22 +++++++++++++++++----- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/WINNT/afsd/NTMakefile b/src/WINNT/afsd/NTMakefile index 734555695..22c55f968 100644 --- a/src/WINNT/afsd/NTMakefile +++ b/src/WINNT/afsd/NTMakefile @@ -376,7 +376,7 @@ AFSD_SDKLIBS =\ secur32.lib \ ole32.lib \ oleaut32.lib \ - iphlpapi.lib shell32.lib + iphlpapi.lib shell32.lib shlwapi.lib AFSD_EXELIBS =\ $(DESTDIR)\lib\libosi.lib \ diff --git a/src/WINNT/afsd/cm_utils.c b/src/WINNT/afsd/cm_utils.c index 89e8c9b22..f8fbab57a 100644 --- a/src/WINNT/afsd/cm_utils.c +++ b/src/WINNT/afsd/cm_utils.c @@ -12,6 +12,7 @@ #include #include +#include #include #ifndef EWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK @@ -747,3 +748,14 @@ int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags) return retval; } +BOOL +cm_TargetPerceivedAsDirectory(const fschar_t *target) +{ + char * ext; + + ext = PathFindExtension(target); + if (!ext[0]) + return TRUE; + + return FALSE; +} diff --git a/src/WINNT/afsd/cm_utils.h b/src/WINNT/afsd/cm_utils.h index bca414ee8..b852902b1 100644 --- a/src/WINNT/afsd/cm_utils.h +++ b/src/WINNT/afsd/cm_utils.h @@ -81,4 +81,6 @@ extern void cm_Gen8Dot3NameIntW(const clientchar_t* longname, cm_dirFid_t * pfid extern int cm_MatchMask(clientchar_t *namep, clientchar_t *maskp, int flags); +extern BOOL cm_TargetPerceivedAsDirectory(const fschar_t *target); + #endif /* __CM_UTILS_H_ENV__ */ diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 63642e19a..a1fb9f238 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -4380,17 +4380,22 @@ smb_ApplyDirListPatches(cm_scache_t * dscp, smb_dirListPatch_t **dirPatchespp, switch (scp->fileType) { case CM_SCACHETYPE_DIRECTORY: case CM_SCACHETYPE_MOUNTPOINT: - case CM_SCACHETYPE_SYMLINK: case CM_SCACHETYPE_INVALID: attr = SMB_ATTR_DIRECTORY; break; + case CM_SCACHETYPE_SYMLINK: + if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp)) + attr = SMB_ATTR_DIRECTORY; + else + attr = SMB_ATTR_NORMAL; + break; default: /* if we get here we either have a normal file * or we have a file for which we have never * received status info. In this case, we can * check the even/odd value of the entry's vnode. - * 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)) attr = SMB_ATTR_DIRECTORY; @@ -5315,21 +5320,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); -#ifdef undef - /* use smb_Attributes instead. Also the fact that a file is - * in a readonly volume doesn't mean it shojuld be marked as RO - */ - if (newScp->fileType == CM_SCACHETYPE_DIRECTORY || - newScp->fileType == CM_SCACHETYPE_MOUNTPOINT || - newScp->fileType == CM_SCACHETYPE_INVALID) - attrs = SMB_ATTR_DIRECTORY; - else - attrs = 0; - if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO)) - attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */ -#else attrs = smb_Attributes(newScp); -#endif smb_SetSMBParm(outp, 0, attrs); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 7c8a31757..ca9588e11 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -4128,17 +4128,22 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp, 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; @@ -4163,10 +4168,15 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp, 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: /* if we get here we either have a normal file * or we have a file for which we have never @@ -4233,7 +4243,9 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp, /* 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; -- 2.39.5