Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 6 Jul 2007 08:23:02 -0400
From:      "Ighighi Ighighi" <ighighi@gmail.com>
To:        d@delphij.net
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: add closefrom() call
Message-ID:  <de5dfb5a0707060523w6cda3de9y57d32ad8b1d70ea@mail.gmail.com>
In-Reply-To: <468CD5E9.7060000@delphij.net>
References:  <de5dfb5a0707041727j3e3518f9l5a019717a9f90aa@mail.gmail.com> <468CD5E9.7060000@delphij.net>

next in thread | previous in thread | raw e-mail | index | archive | help
> LI Xin <delphij at delphij.net> wrote:
> Here is my implementation for FreeBSD.  Some difference between my and
> DragonFly's implementation:
>
>  - closefrom(-1) would be no-op on DragonFly, my version would close all
> open files (From my understanding of OpenSolaris's userland
> implementation, this is Solaris's behavior).
>  - my version closefrom(very_big_fd) would result in EBADF.  I am not
> very sure whether this is correct, but it does not hurt for applications
> that thinks closefrom() would return void.

Why not follow current practice and return EBADF for -1 ?
It'd be dangerous to close all open files with -1 (a closefrom(0)
would suffice),
and weird to ignore very_big_fd.

I also agree that using fcntl() would be better.

Here's the code I'm using to emulate this call on FreeBSD >= 5.0 anyway.

int closefrom(int lowfd)
{
    int mib[2] = { CTL_KERN, KERN_FILE };
    struct xfile *files = NULL;
    pid_t pid = getpid();
    int i, nfiles;
    size_t fsize;

    for (;;) {
        if (sysctl(mib, 2, files, &fsize, NULL, 0) == -1) {
            if (errno != ENOMEM)
                goto bad;
            else if (files != NULL) {
                free(files);
                files = NULL;
            }
        }
        else if (files == NULL) {
            files = (struct xfile *) malloc(fsize);
            if (files == NULL)
                return -1;
        }
        else
            break;
    }

    /* XXX This structure may change */
    if (files->xf_size != sizeof(struct xfile) ||
        fsize % sizeof(struct xfile))
    {
        errno = ENOSYS;
        goto bad;
    }

    nfiles = fsize / sizeof(struct xfile);

    for (i = 0; i < nfiles; i++)
        if (files[i].xf_pid == pid && files[i].xf_fd >= lowfd)
            close(files[i].xf_fd);

    free(files);
    return 0;

bad:
    if (files != NULL) {
        int save_errno = errno;
        free(files);
        errno = save_errno;
    }
    return -1;
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?de5dfb5a0707060523w6cda3de9y57d32ad8b1d70ea>