# Accidental Dir.glob behavior change in 1.8.6

**URL:** <https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295>\
**Category:** Ruby\
**Created:** [April 17, 2007, 11:45pm UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295 "2007-04-17T23:45:39Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Elliott\_Hughes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/cab0a1/32.png) [@Elliott\_Hughes](https://www.ruby-forum.com/u/Elliott_Hughes)\
**Post date:** [April 17, 2007, 11:45pm UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295/1 "2007-04-17T23:45:39Z")

</div>

## expected/1.8.4 behavior

download ruby-1.8.4, extract, cd into the source root. (alternatively,  
use Ubuntu 6.10’s ruby package.)

./configure && make && ./ruby -w -e ‘puts(Dir.glob(“v\*/config.h”))’

produces (after the build output) this output:

vms/config.h

## actual 1.8.6 behavior

download ruby-1.8.6, extract, cd into the source root. (alternatively,  
use Debian testing/unstable’s ruby package.)

./configure && make && ./ruby -w -e ‘puts(Dir.glob(“v\*/config.h”))’

produces (after the build output) this output:

-e:1: warning: variable.o/config.h: Not a directory  
-e:1: warning: variable.c/config.h: Not a directory  
-e:1: warning: version.c/config.h: Not a directory  
-e:1: warning: version.o/config.h: Not a directory  
-e:1: warning: version.h/config.h: Not a directory  
vms/config.h

## responsible code

in “dir.c”:

static int  
do\_stat(const char \*path, struct stat \*pst, int flags)

{  
int ret = stat(path, pst);  
if (ret \< 0 && errno != ENOENT)  
sys\_warning(path);

```
return ret;

```

}

static int  
do\_lstat(const char \*path, struct stat \*pst, int flags)  
{  
int ret = lstat(path, pst);  
if (ret \< 0 && errno != ENOENT)  
sys\_warning(path);

```
return ret;

```

}

static DIR \*  
do\_opendir(const char \*path, int flags)  
{  
DIR \*dirp = opendir(path);  
if (dirp == NULL && errno != ENOENT && errno != ENOTDIR)  
sys\_warning(path);

```
return dirp;

```

}

## evaluation

stat(2)/lstat(2) can return ENOTDIR if a non-leaf element of the path  
they’re given is not a directory.  
this is a fairly common case when people are using globbing as a cheap  
way of finding files at a fixed depth below a given directory.

## suggested fix

make do\_stat and do\_lstat more like do\_opendir:

- 

```
if (ret < 0 && errno != ENOENT)

```

- 

```
if (ret < 0 && errno != ENOENT && errno != ENOTDIR)

```

it might also be worth a code comment, since it’s not likely to be  
immediately obvious to most readers that stat(2)/lstat(2) can return  
ENOTDIR.

thanks!

–  
Elliott Hughes, BlueArc Engineering

---

<div class="post-metadata">

**Author:** ![Elliott\_Hughes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/cab0a1/32.png) [@Elliott\_Hughes](https://www.ruby-forum.com/u/Elliott_Hughes)\
**Post date:** [April 18, 2007, 4:42am UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295/2 "2007-04-18T04:42:55Z")

</div>

Hi,

At Wed, 18 Apr 2007 06:44:30 +0900,  
Elliott Hughes wrote in [ruby-talk:248288]:

> ## evaluation
> 
> stat(2)/lstat(2) can return ENOTDIR if a non-leaf element of  
> the path they’re given is not a directory.  
> this is a fairly common case when people are using globbing  
> as a cheap way of finding files at a fixed depth below a  
> given directory.

Thank you.

> it might also be worth a code comment, since it’s not likely  
> to be immediately obvious to most readers that  
> stat(2)/lstat(2) can return ENOTDIR.

What about this? The comment was borrowed from your post.

# Index: dir.c

— dir.c (revision 12191)  
+++ dir.c (working copy)  
@@ -929,4 +929,10 @@ sys\_warning\_1(const char\* mesg)  
#define GLOB\_JUMP\_TAG(status) ((status == -1) ? rb\_memerror() :  
rb\_jump\_tag(status))

+/\*

- 
  - ENOTDIR can return even if a non-leaf element of the path is not a

- 
  - directory.

- \*/  
+#define to\_be\_ignored(e) ((e) == ENOENT || (e) == ENOTDIR)
- 

/\* System call with warning \*/  
static int  
@@ -935,5 +941,5 @@ do\_stat(const char \*path, struct stat \*p  
{  
int ret = stat(path, pst);

- if (ret \< 0 && errno != ENOENT)

- if (ret \< 0 && !to\_be\_ignored(errno))  
sys\_warning(path);

@@ -945,5 +951,5 @@ do\_lstat(const char \*path, struct stat \*  
{  
int ret = lstat(path, pst);

- if (ret \< 0 && errno != ENOENT)

- if (ret \< 0 && !to\_be\_ignored(errno))  
sys\_warning(path);

@@ -955,5 +961,5 @@ do\_opendir(const char \*path, int flags)  
{  
DIR \*dirp = opendir(path);

- if (dirp == NULL && errno != ENOENT && errno != ENOTDIR)

- if (dirp == NULL && !to\_be\_ignored(errno))  
sys\_warning(path);

---

<div class="post-metadata">

**Author:** ![Elliott\_Hughes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/cab0a1/32.png) [@Elliott\_Hughes](https://www.ruby-forum.com/u/Elliott_Hughes)\
**Post date:** [April 18, 2007, 4:48am UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295/3 "2007-04-18T04:48:55Z")

</div>

looks good. i like the idea of factoring out the repeated test, too.  
that’s nicer than what i did.

actually i think you missed a couple of words in the comment. maybe  
something like this?

+/\*

- 
  - ENOTDIR can be returned by stat(2) if a non-leaf element of the path

- 
  - is not a directory.

- \*/

btw, was this the right place to report a bug? there was no obvious link  
on [Ruby Programming Language](http://www.ruby-lang.org/en/) and searching that site for “bug  
database” came back with 0 matches.

–  
Elliott Hughes, BlueArc Engineering

---

<div class="post-metadata">

**Author:** ![Elliott\_Hughes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/cab0a1/32.png) [@Elliott\_Hughes](https://www.ruby-forum.com/u/Elliott_Hughes)\
**Post date:** [April 19, 2007, 5:55am UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295/4 "2007-04-19T05:55:31Z")

</div>

Hi,

At Wed, 18 Apr 2007 11:47:12 +0900,  
Elliott Hughes wrote in [ruby-talk:248309]:

> actually i think you missed a couple of words in the comment. maybe something like this?
> 
> +/\*
> 
> - 
> - ENOTDIR can be returned by stat(2) if a non-leaf element of the path
> 
> - 
> - is not a directory.
> 
> - \*/

Thank you. I’ll commit it if knu admits it.

> btw, was this the right place to report a bug? there was no  
> obvious link on [Ruby Programming Language](http://www.ruby-lang.org/en/) and searching  
> that site for “bug database” came back with 0 matches.

Not wrong place, but ruby-core ML is better.

---

<div class="post-metadata">

**Author:** ![Elliott\_Hughes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/cab0a1/32.png) [@Elliott\_Hughes](https://www.ruby-forum.com/u/Elliott_Hughes)\
**Post date:** [April 26, 2007, 4:02am UTC](https://www.ruby-forum.com/t/accidental-dir-glob-behavior-change-in-1-8-6/92295/5 "2007-04-26T04:02:49Z")

</div>

i just noticed that you committed the change. i’ve checked out and  
tested revision 12220 of ruby\_1\_8 and it’s working perfectly. thank-you!

–  
Elliott Hughes, BlueArc Engineering
