<commit_before>#include <linux/kvm.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

#include <sys/select.h>

/* for net */
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <err.h>

#include "ukvm-private.h"
#include "ukvm-modules.h"
#include "ukvm.h"

static char *netiface;
static int netfd;
static struct ukvm_netinfo netinfo;

/*
 * Attach to an existing TAP interface named 'dev'.
 *
 * This function abstracts away the horrible implementation details of the
 * Linux tun API by ensuring (as much as is possible) success if and only if
 * the TAP device named 'dev' already exists.
 *
 * Returns -1 and an appropriate errno on failure (ENODEV if the device does
 * not exist), and the tap device file descriptor on success.
 */
static int tap_attach(const char *dev)
{
    struct ifreq ifr;
    int fd, err;

    fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
    if (fd == -1)
        return -1;

    /*
     * Initialise ifr for TAP interface.
     */
    memset(&ifr, 0, sizeof(ifr));
    /*
     * TODO: IFF_NO_PI may silently truncate packets on read().
     */
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    if (strlen(dev) > IFNAMSIZ) {
        errno = EINVAL;
        return -1;
    }
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);

    /*
     * Try to create OR attach to an existing device. The Linux API has no way
     * to differentiate between the two, but see below.
     */
    if (ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
        err = errno;
        close(fd);
        /*
         * If we got back EPERM then the device would have been created but we
         * don't have permission to do that. Translate that to ENODEV since
         * that's what it means for our purposes.
         */
        if (err == EPERM)
            errno = ENODEV;
        else
            errno = err;
        return -1;
    }
    /*
     * If we got back a different device than the one requested, e.g. because
     * the caller mistakenly passed in '%d' (yes, that's really in the Linux API)
     * then fail.
     */
    if (strncmp(ifr.ifr_name, dev, IFNAMSIZ) != 0) {
        close(fd);
        errno = ENODEV;
        return -1;
    }

    /*
     * Attempt a zero-sized write to the device. If the device was freshly
     * created (as opposed to attached to an existing one) this will fail with
     * EIO. Ignore any other error return since that may indicate the device
     * is up.
     *
     * If this check produces a false positive then caller's later writes to fd
     * will fail with EIO, which is not great but at least we tried.
     */
    char buf[1] = { 0 };
    if (write(fd, buf, 0) == -1 && errno == EIO) {<commit_msg>ukvm: Don't mask EPERM in tap_attach()<commit_after>#include <linux/kvm.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>

#include <sys/select.h>

/* for net */
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <err.h>

#include "ukvm-private.h"
#include "ukvm-modules.h"
#include "ukvm.h"

static char *netiface;
static int netfd;
static struct ukvm_netinfo netinfo;

/*
 * Attach to an existing TAP interface named 'dev'.
 *
 * This function abstracts away the horrible implementation details of the
 * Linux tun API by ensuring (as much as is possible) success if and only if
 * the TAP device named 'dev' already exists.
 *
 * Returns -1 and an appropriate errno on failure (ENODEV if the device does
 * not exist), and the tap device file descriptor on success.
 */
static int tap_attach(const char *dev)
{
    struct ifreq ifr;
    int fd, err;

    fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
    if (fd == -1)
        return -1;

    /*
     * Initialise ifr for TAP interface.
     */
    memset(&ifr, 0, sizeof(ifr));
    /*
     * TODO: IFF_NO_PI may silently truncate packets on read().
     */
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
    if (strlen(dev) > IFNAMSIZ) {
        errno = EINVAL;
        return -1;
    }
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);

    /*
     * Try to create OR attach to an existing device. The Linux API has no way
     * to differentiate between the two, but see below.
     */
    if (ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
        err = errno;
        close(fd);
        errno = err;
        return -1;
    }
    /*
     * If we got back a different device than the one requested, e.g. because
     * the caller mistakenly passed in '%d' (yes, that's really in the Linux API)
     * then fail.
     */
    if (strncmp(ifr.ifr_name, dev, IFNAMSIZ) != 0) {
        close(fd);
        errno = ENODEV;
        return -1;
    }

    /*
     * Attempt a zero-sized write to the device. If the device was freshly
     * created (as opposed to attached to an existing one) this will fail with
     * EIO. Ignore any other error return since that may indicate the device
     * is up.
     *
     * If this check produces a false positive then caller's later writes to fd
     * will fail with EIO, which is not great but at least we tried.
     */
    char buf[1] = { 0 };
    if (write(fd, buf, 0) == -1 && errno == EIO) {
{'fraction_non_alphanumeric': 0.11387434554973822, 'fraction_numerical': 0.0048616305160807775, 'mean_word_length': 2.439871382636656, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '59132', 'n_tokens_mistral': 1817, 'n_tokens_neox': 1786, 'n_words': 661}