[comp.sys.sgi] problem with scandir

markov@cs.ruu.nl (Mark Overmars) (03/26/91)

I have a problem with the routine scandir. After some stripping I came up with
the following program:

#include <sys/types.h>
#include <sys/dir.h>

main()
{
  struct direct **namelist;
  scandir("/bin", &namelist, NULL, NULL);
}

It dumps core. It does not do so for any other directory than /bin.
(Same behaviour on two unrelated machines.) Any reason why and any suggestions
how to solve it?

Mark Overmars

jwag@moose.asd.sgi.com (Chris Wagner) (03/28/91)

In article <1991Mar25.191630.939@cs.ruu.nl>, markov@cs.ruu.nl (Mark
Overmars) writes:
> I have a problem with the routine scandir. After some stripping I came
up with
> the following program:
> 
> #include <sys/types.h>
> #include <sys/dir.h>
> 
> main()
> {
>   struct direct **namelist;
>   scandir("/bin", &namelist, NULL, NULL);
> }
> 
> It dumps core. It does not do so for any other directory than /bin.
> (Same behaviour on two unrelated machines.) Any reason why and any
suggestions
> how to solve it?
> 
> Mark Overmars


THis is a bug in scandir in 3.3 - having to do with how much memory
scandir will allocate to hold the directory entries. It gueses based on the
stat size of the directory using a heuristic designed for BSD FFS which
doesn't always work on EFS. If you simply add another entry to /bin it
will probably start working.

It has been fixed in 4.0

Chris Wagner

brendan@illyria.wpd.sgi.com (Brendan Eich) (03/28/91)

In article <1991Mar27.163133.19962@odin.corp.sgi.com>, jwag@moose.asd.sgi.com (Chris Wagner) writes:
> In article <1991Mar25.191630.939@cs.ruu.nl>, markov@cs.ruu.nl (Mark
> Overmars) writes:
> > I have a problem with the routine scandir. After some stripping I came
> up with
> > the following program: [...]
> > It dumps core. It does not do so for any other directory than /bin.
> > (Same behaviour on two unrelated machines.) Any reason why and any
> suggestions
> > how to solve it?
> 
> THis is a bug in scandir in 3.3 - having to do with how much memory
> scandir will allocate to hold the directory entries. It gueses based on the
> stat size of the directory using a heuristic designed for BSD FFS which
> doesn't always work on EFS. If you simply add another entry to /bin it
> will probably start working.
> 
> It has been fixed in 4.0

In the mean time, if you #include <sys/dir.h> instead of <dirent.h>, you'll
get the BSD-compatible directory(3B) interface.  Calling scandir after you
include <sys/dir.h> compiles a call to BSDscandir, which (because it uses
those pesky BSD FFS directory entry structures) guesses the right size for
the array of entries that it allocates.  If there's a bug with BSDscandir,
please let us know.  But it *should* work just like on a 4.3 system.

The System V and Berkeley directory(3) interfaces are so similar, the only
differences among structs dirent (SysV) and direct (BSD), other than the
struct tag names, are the meaning of d_reclen, the absence of d_namlen in
System V's dirent (a botch), and the absence of the next entry's "offset"
cookie, d_off, in the BSD struct direct (another botch).

/be

marks@AIVAX.RADC.AF.MIL (David Marks) (04/05/91)

[ Mail to originator bounced... How can info-iris always get the mail through..]
Mark,
  First, I'm sure its a typo, but the structure name is "dirent" not "direct".
Secondly, you have to provide a place for the directory information to go,
not just a place for a pointer to a pointer of the information.
This should do the trick:

  struct dirent namelist;   /* this is where the info will really go */
                            /* it says to allocate space for a dirent */
  struct dirent *namelist_p; /* this declares space for a ptr to a dirent */
  struct dirent **namelist_p_p; /* and this a ptr to a ptr to a dirent */

/* the relationship amongst these is: */
/*      namelist_p_p  -> namelist_p ->  namelist  */


/* make the declared pointers really point to where we want */
  namelist_p = &namelist; /* point to namelist */
  namelist_p_p = &namelist_p;  /* point to namelist_p */

/* the call would then look like: */
    scandir("/bin", namelist_p_p, NULL, NULL);

OR possibly,

    scandir("/bin", &namelist_p, NULL, NULL);

OR MAYBE, but I don't think so,

    scandir("/bin", &&namelist, NULL, NULL);

--------------------------------------------

I guess you get the idea from the above verbose example.  I got trapped by
this problem several times, and still do now and again.  The trick is
to always know what the pointers are pointing to and that you have
allocated space for the data to actually reside.

I hope this helps.

Dave Marks
Rome Laboratory
marks@aivax.radc.af.mil