Menu

FSFIRST/FSNEXT fail to detect subdirectories in Windows 10 1903 32-bit

2019-07-22
2019-07-26
  • Yet Another Troll

    They also appear to throw error -33 on every call but still return something if the error is caught or ignored.

    > ver
    X11-BASIC Version: 1.27 Jul  8 2019 12:44:26
    > load "\users\trollollio\onedrive\bas\0_dirwalk 1.bas"
    > run
    0       'd /'
    Oopsie -33 * File %s not found
    Calling FSNEXT - $Recycle.Bin
    Calling FSNEXT - autoexec.bat
    Calling FSNEXT - bootmgr
    Calling FSNEXT - BOOTNXT
    Calling FSNEXT - bootTel.dat
    Calling FSNEXT - config.sys
    Calling FSNEXT - Documents and Settings
    Calling FSNEXT - hiberfil.sys
    Calling FSNEXT - Intel
    Calling FSNEXT - Logs
    Calling FSNEXT - MSOCache
    Calling FSNEXT - OneDriveTemp
    Calling FSNEXT - pagefile.sys
    Calling FSNEXT - PerfLogs
    Calling FSNEXT - Program Files
    Calling FSNEXT - ProgramData
    Calling FSNEXT - Recovery
    Calling FSNEXT - swapfile.sys
    Calling FSNEXT - System Volume Information
    Calling FSNEXT - TEST_TOOL
    Calling FSNEXT - Users
    Calling FSNEXT - Windows
    Calling FSNEXT - Windows.old
    Calling FSNEXT - Windows10Upgrade
    Calling FSNEXT
    1       1       0
    0       'B0rk'
    0 match(es) found.
    OK
    >
    

    The code,

    #!/usr/bin/xbasic
    
    Program DirWalkOnTheWildSide
    
     ' Can match all symbolic links with "s *" etc.
     ' TODO Convert this nasty NFA to an optimized DFA at run time
     Patterns$() = [ "*temp", "*tmp", "*sql*-v*", "*.mgr" ]
     Patterns$() = [ "*.wav", "*.mp3", "*.ogg", "*.amr", "*.fla", "*.flac" ]
     Patterns$() = [ "*.bas", "*.b", "*.cgi" ]
     PMFlags% = 16 ! Case insensitive GLOB() matching
    
     AllDirs$() = [ "d /" ]  ! Looking for adventure
     Matches$() = [ "B0rk" ] ! In whatever comes our way
     DirCount% = 1
     MatCount% = 0
     CurDir% = 0
    
     While CurDir% < DirCount%
    
      Clr P$, F$, S%
      P$ = AllDirs$(CurDir%)
      Print CurDir%, "'"; P$; "'"
      S% = InStr(P$, " ")
      ' Print "FindFirst '"; Mid$(P$, S% + 1, Len(P$) - S%); ; "'"
      ' Pause 0.1
    
      Clr F$
      ' Compiled code apparently doesn't like error handlers?
      ' On Error Cont
      On Error GoSub Mulligan ! We get one Mulligan per directory
      F$ = FSFirst$(Mid$(P$, S% + 1, Len(P$) - S%), "*", "dfa")
      ' If Len(F$) Then
      '  ' Use up our Mulligan if it's still unused
      '  Print 0xDEADBEEF / 0; Chr$(13);
      ' EndIf
    
      If Len(F$) = 0 Then
       ! No-op
      Else If Left$(P$, 2) = "d " Then
       ! No-op
      Else If Left$(P$, 2) = "s " Then
       ! No-op
      Else
       Print "Weird dir '"; P$; "' contains files like '"; F$; "'"
       Pause 5
      EndIf
    
      ' Discard the path's "d " or "s " prefix
      P$ = Mid$(P$, S% + 1, Len(P$) - S%)
    
      While Len(F$)
       S% = InStr(F$, " ")
       F$ = Left$(F$, S%) + P$ + Mid$(F$, S% + 1, Len(F$) - S%)
       ' Print "'"; F$; "'"
       ' Pause 0.1
    
       Clr WeHaveAContendah%, i%
       For i% = 0 To (UBound(Patterns$()) - 1)
        If Glob(F$, Patterns$(i%), PMFlags%) Then
         WeHaveAContendah% = True
         ' Is early exit just GOTO in drag?
         ' Would Dijkstra not like this?
         ' Break
         ' Exit For
        EndIf
        ' Exit If WeHaveAContendah%
       Next i%
       If WeHaveAContendah% Then
        Dim Matches$(MatCount% + 1)
        Matches$(MatCount%) = F$
        Inc MatCount%
        Print "Match "; MatCount%; " found '"; F$; "'"
        ' Pause 0.2
       EndIf
    
       If (Left$(F$, 2) = "d ") ! Or (Left$(F$, 2) = "s ") Then ! DO NOT FOLLOW SYMLINKS
        ' Directory, or symbolic link to maybe a directory?
        ' Could following symlinks cause an infinite loop? How to detect?
        If DirCount% = UBound(AllDirs$()) Then
         ' Hundreds of thousands of subdirectories!!!1!
         Print "REDIM PRESERVE AllDirs$("; DirCount% + (DirCount% Div 8) + 4; ")"
         Dim AllDirs$(DirCount% + (DirCount% Div 8) + 4)
        EndIf
        AllDirs$(DirCount%) = F$ + "/"
        Inc DirCount%
       Else If (Left$(F$, 2) = "- ") Then
        ' Ordinary file
        ! No-op
       Else If (Left$(F$, 2) = "s ") Then
        ' Symbolic link, can we find out what it points to?
        ! No-op
       Else
        ' We found something new!
        Dim Matches$(MatCount% + 1)
        Matches$(MatCount%) = F$
        Inc MatCount%
        Print "Weird "; MatCount%; '" found "; F$; "'"
        Pause 5
       EndIf
    
       Clr F$
       ' Is FSNEXT also prone to throwing exceptions? YES IT IS!
       Print "Calling FSNEXT ";
       F$ = "! UNKNOWN"
       On Error Cont ! GoSub Mulligan
       F$ = FSNext$()
       Print F$
      Wend
      Inc CurDir%
     Wend
    
     Print UBound(AllDirs$()), DirCount%, MatCount%
     For i% = 0 To (MatCount% - 1) ! Needs parens or it's a syntax error
      Print i%, "'"; Matches$(i%); "'"
     Next i%
     Print MatCount%; " match(es) found."
    
     Print "OK"
    End
    
    DefFn SubStr$(S$, First%, Last%) = Mid$(S$, First%, Last% - First% + 1)
    
    Procedure Mulligan()
     Print "Oopsie ";
     E% = Err
     Print E%; " "; Err$(E%)
     Select E%
      Case 0   ! Divide by zero, not "all is well"
       ! No-op
      Case -13 ! Permission denied
       ! No-op
      Case -33 ! File not found (symlink to missing file/dir?)
       ! No-op
      Case -20 ! Not a directory (symlink to ordinary file?)
       ! No-op
      Default
       Stop
     EndSelect
     ' Pause 0.5
     ' Resume Next
    Return
    
     
  • Yet Another Troll

    ...but the stepdir.bas sample does sometimes recognize subdirectories if root$ = "C:\"

    I'll do more testing.

     
  • Yet Another Troll

    I also see it in Windows 8.1 64-bit 6.3.9600 with the July Important patches installed but not the optional 2019-07 Preview of Monthly Quality Rollup for Windows 8.1 for x64-based Systems (KB4507463)

    It could be the bug is in my code somehow, or FSFIRST/FSNEXT don't like "/" or "\" in Windows, or perhaps they need "C://" in order to indicate directories properly in the returned string instead of just "C:/"

     

    Last edit: Yet Another Troll 2019-07-23
  • Markus Hoffmann

    Markus Hoffmann - 2019-07-25

    I think, on WINDOWS, the root path "/" does not exist. So "d /" will cause that error.
    However it probably defaults to something (like "C:/" or the current directory).
    Have you tried to use "d C:/" on windows?

    IF WIN32?
      AllDirs$() = [ "d C:/" ]  ! Looking for adventure
    else 
    AllDirs$() = [ "d /" ]  ! Looking for adventure
    endif
    
     

    Last edit: Markus Hoffmann 2019-07-25
    • Yet Another Troll

      The first call to FSFIRST sort of succeeds, and the names of the files and directories in the root of the current drive, in this case C:, are found. It's just whatever is checking for -, d, or s that fails. I'll keep playing with it and/or finally dig into the sources. Thanks for looking at it.

       
    • Yet Another Troll

      In a cmd window, DIR \ will list the root directory of the current drive. VB/VBA's Dir$ works similarly, so I expected FSFIRST/FSNEXT to also work like that,

      Microsoft Windows [Version 10.0.18362.239]
      (c) 2019 Microsoft Corporation. All rights reserved.
      
      C:\Users\trollollio>dir \
       Volume in drive C has no label.
       Volume Serial Number is F696-BB0C
      
       Directory of C:\
      
      10/29/2015  10:47 PM                24 autoexec.bat
      10/29/2015  10:47 PM                10 config.sys
      04/25/2016  01:33 PM    <DIR>          Intel
      02/13/2016  05:19 AM    <DIR>          Logs
      03/18/2019  07:46 PM    <DIR>          PerfLogs
      07/18/2019  10:29 AM    <DIR>          Program Files
      06/13/2016  01:08 AM    <DIR>          TEST_TOOL
      07/18/2019  10:02 AM    <DIR>          Users
      07/26/2019  06:40 AM    <DIR>          Windows
      01/17/2018  03:55 PM    <DIR>          Windows10Upgrade
                     2 File(s)             34 bytes
                     8 Dir(s)  12,868,653,056 bytes free
      
      C:\Users\trollollio>
      

      Still, I may be better off inspecting environment variables like SystemRoot, ProgramData, ProgramFiles, and UserProfile to derive a list of drives to search, in case of a customized Windows installation spread amongst multiple drives or partitions. Such things were possible in the NT days and maybe still are.

       

      Last edit: Yet Another Troll 2019-07-26

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.