2024-03-29 07:28 AEDT

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000265mercuryBugpublic2012-12-07 05:44
Reportergloomdemon 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusnewResolutionopen 
PlatformwindowsOSwindows 32/64OS Versionany
Product Version 
Target VersionFixed in Version 
Summary0000265: long path handling in io module
Description"io.file_type" uses "_wstat" in C grade, but *stat didn't support long names on Windows OS (> 260)
http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/3c093ea9-f0aa-446d-b648-2dabe8480430
It may be fixed by using "FindFirstFileW" with "\\?\" file name prefix instead of "_wstat".

Also, other functions in io module (open_input -> mercury_open -> _wfopen) may be can't handle long path.
Steps To Reproduceunpack test_dir.tar, change path to unpacked directory in bugl program, compile and run
Additional Information:- module bugl.
:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- implementation.

:- import_module require, dir, list, bool.

main(!IO) :-
    Ps = (
        pred(DN::in, BN::in, FT::in, C::out, Di::in, Do::out, !.IO::di, !:IO::uo) is det :-
            C = yes,
            io.write_strings([DN, " ", BN, "\n"], !IO),
            Do = Di
    ),
    dir.recursive_foldl2(Ps, "C:\\5", no, [], MaybeResult, !IO),
    (
        MaybeResult = error(_, Err),
        error(io.error_message(Err)) % exception
    ;
        MaybeResult = ok(_)
    ).
TagsNo tags attached.
Attached Files
  • tar file icon test_dir.tar (16,896 bytes) 2012-11-15 00:30
  • diff file icon dir.diff (8,095 bytes) 2012-12-07 05:44 -
    --- dir.m.12.08.beta.2012.12.04	2012-01-03 15:04:48.000000000 +0400
    +++ dir.m	2012-12-06 22:34:43.411414500 +0400
    @@ -220,6 +220,15 @@
         string::in, bool::in, T::in, io.maybe_partial_res(T)::out,
         io::di, io::uo) is det.
     
    +    %
    +:- pred dir.foldl2_skip(dir.foldl_pred(T)::in(dir.foldl_pred), string::in,
    +    T::in, io.maybe_partial_res(T)::out, io::di, io::uo) is det.
    +
    +    %
    +:- pred dir.recursive_foldl2_skip(dir.foldl_pred(T)::in(dir.foldl_pred),
    +    string::in, bool::in, T::in, io.maybe_partial_res(T)::out,
    +    io::di, io::uo) is det.
    +
     %-----------------------------------------------------------------------------%
     
         % Implement brace expansion, as in sh: return the sequence of strings
    @@ -1289,11 +1298,19 @@ dir.check_dir_accessibility(DirName, Res
     
     dir.foldl2(P, DirName, T, Res, !IO) :-
         dir.foldl2_process_dir(no, P, fixup_dirname(DirName), [], no,
    -        no, _, T, Res, !IO).
    +        no, no, _, T, Res, !IO).
     
     dir.recursive_foldl2(P, DirName, FollowLinks, T, Res, !IO) :-
         dir.foldl2_process_dir(no, P, fixup_dirname(DirName), [], yes,
    -        FollowLinks, _, T, Res, !IO).
    +        FollowLinks, no, _, T, Res, !IO).
    +
    +dir.foldl2_skip(P, DirName, T, Res, !IO) :-
    +    dir.foldl2_process_dir(no, P, fixup_dirname(DirName), [], no,
    +        no, yes, _, T, Res, !IO).
    +
    +dir.recursive_foldl2_skip(P, DirName, FollowLinks, T, Res, !IO) :-
    +    dir.foldl2_process_dir(no, P, fixup_dirname(DirName), [], yes,
    +        FollowLinks, yes, _, T, Res, !IO).
     
         %
         % Under windows you cannot list the files of a directory if the directory
    @@ -1315,22 +1332,22 @@ fixup_dirname(Dir0) = Dir :-
     
     :- pred dir.foldl2_process_dir(bool::in,
         dir.foldl_pred(T)::in(dir.foldl_pred), string::in,
    -    list(file_id)::in, bool::in, bool::in, bool::out, T::in,
    +    list(file_id)::in, bool::in, bool::in, bool::in, bool::out, T::in,
         io.maybe_partial_res(T)::out, io::di, io::uo) is det.
     
     :- pred dir.foldl2_process_dir2(dir.stream::in, dir.stream::out, bool::in,
         dir.foldl_pred(T)::in(dir.foldl_pred), string::in,
    -    list(file_id)::in, string::in, bool::in, bool::in, T::in,
    +    list(file_id)::in, string::in, bool::in, bool::in, bool::in, T::in,
         {io.maybe_partial_res(T), bool}::out, io::di, io::uo) is det.
     
     dir.foldl2_process_dir2(!Dir, SymLinkParent, P, DirName, ParentIds, FirstEntry,
    -        Recursive, FollowLinks, T0, {Res, Cont}, !IO) :-
    +        Recursive, FollowLinks, SkipInaccessible, T0, {Res, Cont}, !IO) :-
         dir.foldl2_process_entries(!Dir, SymLinkParent, P, DirName,
    -        ok(FirstEntry), ParentIds, Recursive, FollowLinks, Cont,
    -        T0, Res, !IO).
    +        ok(FirstEntry), ParentIds, Recursive, FollowLinks, SkipInaccessible,
    +        Cont, T0, Res, !IO).
     
     dir.foldl2_process_dir(SymLinkParent, P, DirName, ParentIds0, Recursive,
    -        FollowLinks, Continue, T0, Result, !IO) :-
    +        FollowLinks, SkipInaccessible, Continue, T0, Result, !IO) :-
         ( can_implement_dir_foldl ->
             (
                 Recursive = yes,
    @@ -1355,7 +1372,8 @@ dir.foldl2_process_dir(SymLinkParent, P,
                                 IO0::di, IO::uo) is det :-
                             dir.foldl2_process_dir2(Dir0, Dir1, SymLinkParent,
                                 P, DirName, ParentIds, FirstEntry, Recursive,
    -                            FollowLinks, T0, {DirRes1, Continue1}, IO0, IO)
    +                            FollowLinks, SkipInaccessible, T0, {DirRes1, Continue1},
    +                            IO0, IO)
                         ),
                     promise_equivalent_solutions [!:IO, ExcpResult] (
                         exception.try_io(ProcessDir, ExcpResult, !IO)
    @@ -1390,8 +1408,15 @@ dir.foldl2_process_dir(SymLinkParent, P,
                     Result = ok(T0)
                 ;
                     OpenResult = error(Error),
    -                Continue = no,
    -                Result = error(T0, Error)
    +                (
    +                    SkipInaccessible = yes,
    +                    Continue = yes,
    +                    Result = ok(T0)
    +                ;
    +                    SkipInaccessible = no,                    
    +                    Continue = no,
    +                    Result = error(T0, Error)
    +                )
                 )
             ;
                 LoopRes = ok(yes),
    @@ -1413,14 +1438,14 @@ dir.foldl2_process_dir(SymLinkParent, P,
     :- pred dir.foldl2_process_entries(dir.stream::in, dir.stream::out, bool::in,
         dir.foldl_pred(T)::in(dir.foldl_pred), string::in,
         io.result(string)::in, list(file_id)::in, bool::in,
    -    bool::in, bool::out, T::in, io.maybe_partial_res(T)::out,
    +    bool::in, bool::in, bool::out, T::in, io.maybe_partial_res(T)::out,
         io::di, io::uo) is det.
     
    -dir.foldl2_process_entries(!Dir, _, _, _, error(Error), _, _, _, no,
    +dir.foldl2_process_entries(!Dir, _, _, _, error(Error), _, _, _, _, no,
             T0, error(T0, Error), !IO).
    -dir.foldl2_process_entries(!Dir, _, _, _, eof, _, _, _, yes, T0, ok(T0), !IO).
    +dir.foldl2_process_entries(!Dir, _, _, _, eof, _, _, _, _, yes, T0, ok(T0), !IO).
     dir.foldl2_process_entries(!Dir, SymLinkParent, P, DirName, ok(FileName),
    -        ParentIds, Recursive, FollowLinks, Continue, T0, Res, !IO) :-
    +        ParentIds, Recursive, FollowLinks, SkipInaccessible, Continue, T0, Res, !IO) :-
         PathName = DirName/FileName,
         io.file_type(no, PathName, FileTypeRes, !IO),
         (
    @@ -1433,7 +1458,8 @@ dir.foldl2_process_entries(!Dir, SymLink
                     Type = directory
                 ->
                     dir.foldl2_process_dir(SymLinkParent, P, PathName, ParentIds,
    -                    Recursive, FollowLinks, Continue2, T1, Res1, !IO)
    +                    Recursive, FollowLinks, SkipInaccessible, Continue2, T1, Res1,
    +                    !IO)
                 ;
                     Recursive = yes,
                     Type = symbolic_link,
    @@ -1445,7 +1471,8 @@ dir.foldl2_process_entries(!Dir, SymLink
                         (
                             TargetType = directory,
                             dir.foldl2_process_dir(yes, P, PathName, ParentIds,
    -                            Recursive, FollowLinks, Continue2, T1, Res1, !IO)
    +                            Recursive, FollowLinks, SkipInaccessible, Continue2,
    +                            T1, Res1, !IO)
                         ;
     
                             ( TargetType = regular_file
    @@ -1487,8 +1514,8 @@ dir.foldl2_process_entries(!Dir, SymLink
                         EntryResult = error(Error)
                     ),
                     dir.foldl2_process_entries(!Dir, SymLinkParent, P, DirName,
    -                    EntryResult, ParentIds, Recursive, FollowLinks, Continue,
    -                    T, Res, !IO)
    +                    EntryResult, ParentIds, Recursive, FollowLinks, SkipInaccessible,
    +                    Continue, T, Res, !IO)
                 ;
                     Continue = no,
                     Res = Res1
    @@ -1499,9 +1526,28 @@ dir.foldl2_process_entries(!Dir, SymLink
                 Continue = no
             )
         ;
    -        FileTypeRes = error(Error),
    -        Continue = no,
    -        Res = error(T0, Error)
    +        FileTypeRes = error(ErrorFT),
    +        (
    +            SkipInaccessible = yes,
    +            dir.read_entry(!.Dir, EntryResult0, !IO),
    +            (
    +                EntryResult0 = ok({!:Dir, FileName1}),
    +                EntryResult = ok(FileName1)
    +            ;
    +                EntryResult0 = eof,
    +                EntryResult = eof
    +            ;
    +                EntryResult0 = error(Error),
    +                EntryResult = error(Error)
    +            ),
    +            dir.foldl2_process_entries(!Dir, SymLinkParent, P, DirName,
    +                EntryResult, ParentIds, Recursive, FollowLinks, SkipInaccessible,
    +                Continue, T0, Res, !IO)
    +        ;
    +            SkipInaccessible = no,
    +            Continue = no,
    +            Res = error(T0, ErrorFT)
    +        )
         ).
     
         % Check whether we've seen this directory before in this branch of the
    
    diff file icon dir.diff (8,095 bytes) 2012-12-07 05:44 +

-Relationships
+Relationships

-Notes

~0000481

gloomdemon (reporter)

Last edited: 2012-12-07 05:54

View 3 revisions

test_dir.tar can be unpacked without errors with with 7-Zip to disk root directory (c:\, d:\ or other).

Also dir.recursive_foldl2 and dir.foldl2 can fail on inaccessible dir (no rights to read files list). Possible fix is to skip inaccessible file or dir (see dir.diff).

+Notes

-Issue History
Date Modified Username Field Change
2012-11-15 00:30 gloomdemon New Issue
2012-11-15 00:30 gloomdemon File Added: test_dir.tar
2012-12-07 05:44 gloomdemon Note Added: 0000481
2012-12-07 05:44 gloomdemon File Added: dir.diff
2012-12-07 05:45 gloomdemon Note Edited: 0000481 View Revisions
2012-12-07 05:54 gloomdemon Note Edited: 0000481 View Revisions
+Issue History