Tcl Source Code

View Ticket
Login
Ticket UUID: e5c21e566ff31a51f85bf12e0b5031993a3c4b4a
Title: inconsistent handling of glob -nocomplain
Type: Bug Version: any
Submitter: sebres Created on: 2025-08-13 17:02:18
Subsystem: 37. File System Assigned To: nobody
Priority: 5 Medium Severity: Severe
Status: Open Last Modified: 2025-08-16 05:42:45
Resolution: None Closed By: nobody
    Closed on:
Description:

It looks that on certain circumstances glob -nocomplain may complain about "no such file or directory". Still worse for Tcl 9, because since TIP#637 -glob always works as "nocomplain" now.

Normally, following code would return an empty list if the directory doesn't exist:

% glob -nocomplain -directory {/path/that/does/not/exist} *.ext
~empty~

However sometimes (depending on file-system/platform/whatever) it may fail... for instance this happens by some of my customer on some SMB-share on Windows:

% glob -nocomplain -directory {//server/smb-share/no-such-path} *.ext
couldn't read directory "//server/smb-share/no-such-path/*.ext": no such file or directory

I cannot reproduce it directly in this constellation on my boxes, but I guess I found it in source code, and was able to reproduce another similar "inconsistence" (e. g. if there is no access to directory):

% glob -nocomplain -directory {/path-without-permissions} *.ext
couldn't read directory "/path-without-permissions/*.ext": permission denied
% glob -nocomplain -directory {/path-without-permissions/.} *.ext
~empty~
% glob -nocomplain -directory {/path-without-permissions/other} *.ext
~empty~
The reason seems to be that neither DoGlob nor Tcl_FSMatchInDirectory know TCL_GLOBMODE_NO_COMPLAIN flag, or rather trying to distinguish the error codes internally, so by the error they'd simply set it to the interpreter and return with TCL_ERROR.

I'm pretty sure that from point of view of not complaining glob, both codes, ENOENT and EACCES, shall be considered as no hits, and glob has to return empty list without to complain the error, no matter how deep exactly it was caused.

User Comments: apnadkarni added on 2025-08-16 05:42:45:
I think what is really needed is another switch (when all else fails, add another switch!). Fundamentally, only the application can decide whether errors such as access denied should be catastrophic or not. Based on the behaviour of my Windows backup programs, I would imagine backup programs for example to skip inaccessible files as opposed to aborting. An installer copying files might treat errors reading source directories as catastrophic. Since glob can't tell the difference, it needs a switch, `-skiponerror` or similar. Which would of course require a TIP.

sebres added on 2025-08-13 19:24:18:

I know that all, but... again, I only spoke about ENOENT and EACCES and inconsistences. I agree that nocomplain is indeed "ambiguous" option in that context, however throwed error ENOENT is completely unexpected here, isn't it?

If you mean that it shall be considered orthogonal to -nocomplain option, I'm agree. I just wanted emphasize that even with -nocomplain it behaves strange (complains with both mentioned errors).

As for inconsistence by EACCESS, I think "./private/some/.../child" is simply considered as not found (because otherwise you have to check permissions of every parent). And I just wanted illustrate, that in this case throwing of EACCESS by `glob` on "./private" may be a nonsense, even because `glob` on "./private/some/.../child" just handles it as no such entry (not found). And I tend to say it is correct and logical.

Also note that "inconsistence" with EACCESS is showing across platforms. Here is the linux world:

% cd ./private
couldn't change working directory to "./private": permission denied
% glob -nocomplain -directory ./private *
couldn't read directory "./private/": permission denied
% glob -nocomplain -directory ./private/. *
~empty~

But I never saw ENOENT on linux, and even if it can be some circumstances (e. g. file system type, etc), I cannot imagine why `glob` shall ever throw it (if, normally, it never does that in regular case).


dgp added on 2025-08-13 17:57:09:
[glob -nocomplain] was always a terrible name.  We have to live with that.

[glob -nocomplain] does not mean
[glob -SuppressAllReportingOfAllErrors]

[glob -nocomplain] means
[glob -DontRaiseAnErrorForNoOtherReasonThanTheResultIsEmpty-NoThinkingPersonBelievesAnEmptyResultIsAnErrorCondition]

If [glob] encounters an error in its operations, the error
should be reported.

If [glob] does not encounter an error, an empty result should not
prompt the creation of an error as if an empty result is an error condition.

It's a good thing to track down inconsistencies in
[glob -directory $permissionDenied].  It surprises me that such an
error would not be reported.  The programmer should want to know
they've coded a directory name that is inaccessible.

In any event, please don't change the meaning of [glob -nocomplain]
while fixing the bugs in [glob -directory].

sebres added on 2025-08-13 17:16:26:

I didn't speak about TIP#637 particularly... It was about that glob -nocomplain (even on 8.5 or 8.6) may behave different by certain circumstances, and I guess the ticket description explains it good, at least for the case with "error" ENOENT (no such file or directory), what shall normally never occur in case of non complaining glob (and doesn't do that normally, but sometimes).


dgp added on 2025-08-13 17:08:03:
The purpose of TIP 637 is to stop incorrectly treating an empty
result as an error.

The purpose of TIP 637 is not to stop reporting actual errors
just because they happen to occur at the same time an empty result
is generated.