#2578 unix glob has inconsistent behavior

obsolete: 8.5a0
closed-fixed
Vince Darley
5
2004-01-23
2004-01-19
Colin McCormack
No

Assuming a directory htdocs as the current directory
containing a file .tml, the following occurs:

% puts $tcl_version
8.5
% puts $tcl_patchLevel
8.5a0
% glob .tml
.tml
% glob ./.tml
no files matched glob pattern "./.tml"
% glob [pwd]/.tml
/home/colin/.gnome-desktop/tclhttpd-cvs/htdocs/.tml
% glob ../htdocs/.tml
no files matched glob pattern "../htdocs/.tml"

This behavior is confusing and inconsistent, and
doesn't seem to accord with the documentation (because
it seems to be triggered by relative paths and not
absolute paths.)

Discussion

  • Vince Darley
    Vince Darley
    2004-01-19

    Logged In: YES
    user_id=32170

    All of these work for me on Windows:

    % pwd
    C:/Documents and Settings/VinceD
    (VinceD) 2 % glob *
    .eclipse-platform .tkchatrc Alpha-v8 {Bluetooth Software}
    Cookies Desktop Favorites gsview32.ini {My Documents}
    PUTTY.RND {Start Menu} tmp UserData WINDOWS
    (VinceD) 3 % glob .tkchatrc
    .tkchatrc
    (VinceD) 4 % glob ./.tkchatrc
    ./.tkchatrc
    (VinceD) 5 % glob [pwd]/.tkchatrc
    {C:/Documents and Settings/VinceD/.tkchatrc}
    (VinceD) 6 % glob ../VinceD/.tkchatrc
    ../VinceD/.tkchatrc
    (VinceD) 7 %

    So it must be something in the unix-specific code. Note
    that the code path used here will be 'pattern == NULL' path,
    I think.

    This means the bug (or at least some very good information
    about the bug) should be in these few lines:

    if (pattern == NULL || (*pattern == '\0')) {
    /* Match a file directly */
    native = (CONST char*) Tcl_FSGetNativePath(pathPtr);
    if (NativeMatchType(native, types)) {
    Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
    }
    Tcl_DecrRefCount(fileNamePtr);
    return TCL_OK;

    in tclUnixFile.c/TclpMatchInDirectory.

    Since I'm not on unix, can I ask you to debug what is going
    on there? In particular, what is 'native' in these cases?

     
  • Logged In: YES
    user_id=19214

    Ok, Vince, I'm happy to debug it. I'll get back to you in a
    few days with what I found - thanks for the localisation of
    the problem.

     
  • Logged In: YES
    user_id=19214

    The problem is in tclPathObj.c TclFSNormalizeAbsolutePath.
    Given a pathPtr argument containing the string
    "/home/colin/.gnome-desktop/tclhttpd-cvs/htdocs/./.tml" it
    returns a value
    "/home/colin/.gnome-desktop/tclhttpd-cvs/htdocs/htdocs/./.tml"

    The problem seems to be in the replacement of substrings
    like /./, where oldDirSep is not being advanced to account
    for the elision.

    Is the problem's solution immediately obvious, or should I
    go digging for one? I don't feel I can suggest a solution
    off the top of my head, but I will certainly find one if needed.

     
  • Vince Darley
    Vince Darley
    2004-01-22

    Logged In: YES
    user_id=32170

    I believe the fix is to insert 'oldDirSep = dirSep' as follows:

    again:
    if (IsSeparatorOrNull(dirSep[2])) {
    /* Need to skip '.' in the path */
    if (retVal == NULL) {
    CONST char *path = Tcl_GetString(pathPtr);
    retVal = Tcl_NewStringObj(path, dirSep - path);
    Tcl_IncrRefCount(retVal);
    }
    dirSep += 2;
    oldDirSep = dirSep;
    if (dirSep[0] != 0 && dirSep[1] == '.') {
    goto again;
    }
    continue;
    }

    thanks for tracking this down, and please do test the above....

     
  • Vince Darley
    Vince Darley
    2004-01-23

    • status: open --> closed-fixed
     
  • Vince Darley
    Vince Darley
    2004-01-23

    Logged In: YES
    user_id=32170

    I believe I fixed this now. Please try cvs head, which also
    has several new tests.