Portfile question for 10.6.8

raf macports at raf.org
Thu Jun 8 10:24:02 UTC 2023


On Wed, Jun 07, 2023 at 04:59:11PM +1000, raf <macports at raf.org> wrote:

> On Tue, Jun 06, 2023 at 06:49:35PM -0700, Ken Cunningham <ken.cunningham.webuse at gmail.com> wrote:
> 
> > > On Jun 6, 2023, at 6:28 PM, raf via macports-users <macports-users at lists.macports.org> wrote:
> > > 
> > > On Wed, Jun 07, 2023 at 11:09:13AM +1000, raf via macports-users <macports-users at lists.macports.org> wrote:
> > > 
> > >> Yay! It worked. Many thanks. I'll fix my Makefile for the upcoming version
> > >> of rawhide and create the Portfile for that.
> > > 
> > > I spoke too soon. The compilation worked, but when I ran the
> > > program to list everything in my home directory, there were
> > > many many "Bad file descriptor" errors for fstatat(). It's
> > > happening for everything immediately below the current
> > > directory. Any ideas?
> > > 
> > > cheers,
> > > raf

> And with debugging on, everything looks correct until
> the error:
> 
>   openat(parent_fd=3, path=.git)
>   openat: dir_fd 4
>   fdopendir(dir_fd=4)
>   dir entry ./.git/branches
>   fstatat(parent_fd=4, path=branches)
>   rh: fstatat ./.git/branches: Bad file descriptor
> 
> The "bad" file descriptor is 4 which was returned by openat.
> That's what it looks like on other systems that work. Mysterious.

Looking at the source for legacysupport, I think I can see the
deliberate use of an invalid file descriptor. There must be a reason
for it, but I don't understand what is intended.

In atcalls.c:

  int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
  {
    ERR_ON(EINVAL, flags & ~AT_SYMLINK_NOFOLLOW);
    if (flags & AT_SYMLINK_NOFOLLOW) {
        return ATCALL(dirfd, pathname, lstat(pathname, buf));
    } else {
        return ATCALL(dirfd, pathname, stat(pathname, buf));
    }
  }

In common-priv.h is the _ATCALL macro:

  #define _ATCALL(fd, p, onerr, what)                             \
    ({  typeof(what) __result;                                  \
        int oldCWD = -1;                                        \
        if (fd != AT_FDCWD && p[0] != '/') {                    \
            oldCWD = open(".", O_RDONLY);                       \
            if (best_fchdir(-1) < 0 && oldCWD != -1) {          \
                close(oldCWD); oldCWD = -1;                     \
            }                                                   \
            if (best_fchdir(fd) < 0) {                          \
                PROTECT_ERRNO(best_fchdir(oldCWD));             \
                if (oldCWD != -1) PROTECT_ERRNO(close(oldCWD)); \
                return onerr;                                   \
            }                                                   \
        }                                                       \
        __result = (what);                                      \
        if (fd != AT_FDCWD && p[0] != '/') {                    \
            PROTECT_ERRNO(best_fchdir(oldCWD));                 \
            if (oldCWD != -1) PROTECT_ERRNO(close(oldCWD));     \
        }                                                       \
        __result;                                               \
    })

  #define ATCALL(fd, p, what)  _ATCALL(fd, p, -1, what)

The call to best_fchdir(-1) would presumably set errno to "Bad File Descriptor".
But I don't see why best_fchdir(fd) or the stat() would fail, so that shouldn't
matter.

Maybe I need to failover to stat() when fstatat() fails with EBADF? No. I made
fstatat() failover to stat(), but then openat() resulted in Bad File Descriptor.
So I made openat() failover to open(), but then fdopendir() started saying that
a directory was "Not a directory". This approach isn't working.

I think I should give up on getting it working on 10.6.8.

cheers,
raf



More information about the macports-users mailing list