@@ -617,10 +617,37 @@ func CopyToChannel(outputCh chan<- []byte, reader io.Reader) error {
617617 }
618618}
619619
620+ const (
621+ winFlagSoftlink = uint32 (0x8000 ) // FILE_ATTRIBUTE_REPARSE_POINT
622+ winFlagJunction = uint32 (0x80 ) // FILE_ATTRIBUTE_JUNCTION
623+ )
624+
625+ func WinSymlinkDir (path string , bits os.FileMode ) bool {
626+ // Windows compatibility layer doesn't expose symlink target type through fileInfo
627+ // so we need to check file attributes and extension patterns
628+ isFileSymlink := func (filepath string ) bool {
629+ if len (filepath ) == 0 {
630+ return false
631+ }
632+ return strings .LastIndex (filepath , "." ) > strings .LastIndex (filepath , "/" )
633+ }
634+
635+ flags := uint32 (bits >> 12 )
636+
637+ if flags == winFlagSoftlink {
638+ return ! isFileSymlink (path )
639+ } else if flags == winFlagJunction {
640+ return true
641+ } else {
642+ return false
643+ }
644+ }
645+
620646// on error just returns ""
621647// does not return "application/octet-stream" as this is considered a detection failure
622648// can pass an existing fileInfo to avoid re-statting the file
623649// falls back to text/plain for 0 byte files
650+
624651func DetectMimeType (path string , fileInfo fs.FileInfo , extended bool ) string {
625652 if fileInfo == nil {
626653 statRtn , err := os .Stat (path )
@@ -629,7 +656,8 @@ func DetectMimeType(path string, fileInfo fs.FileInfo, extended bool) string {
629656 }
630657 fileInfo = statRtn
631658 }
632- if fileInfo .IsDir () {
659+
660+ if fileInfo .IsDir () || WinSymlinkDir (path , fileInfo .Mode ()) {
633661 return "directory"
634662 }
635663 if fileInfo .Mode ()& os .ModeNamedPipe == os .ModeNamedPipe {
0 commit comments