Esempio n. 1
0
static int floppy_probe_device(const char *filename)
{
    int fd, ret;
    int prio = 0;
    struct floppy_struct fdparam;
    struct stat st;

    if (strstart(filename, "/dev/fd", NULL) &&
        !strstart(filename, "/dev/fdset/", NULL)) {
        prio = 50;
    }

    fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
    if (fd < 0) {
        goto out;
    }
    ret = fstat(fd, &st);
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
        goto outc;
    }

    /* Attempt to detect via a floppy specific ioctl */
    ret = ioctl(fd, FDGETPRM, &fdparam);
    if (ret >= 0)
        prio = 100;

outc:
    qemu_close(fd);
out:
    return prio;
}
Esempio n. 2
0
static void tpm_passthrough_destroy(TPMBackend *tb)
{
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);

    tpm_passthrough_cancel_cmd(tb);

    tpm_backend_thread_end(&tpm_pt->tbt);

    qemu_close(tpm_pt->tpm_fd);
    qemu_close(tpm_pt->cancel_fd);

    g_free(tb->id);
    g_free(tb->path);
    g_free(tb->cancel_path);
    g_free(tpm_pt->tpm_dev);
}
Esempio n. 3
0
static int raw_create(const char *filename, QEMUOptionParameter *options)
{
    int fd;
    int result = 0;
    int64_t total_size = 0;

    /* Read out options */
    while (options && options->name) {
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
            total_size = options->value.n / BDRV_SECTOR_SIZE;
        }
        options++;
    }

    fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                   0644);
    if (fd < 0) {
        result = -errno;
    } else {
        if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
            result = -errno;
        }
        if (qemu_close(fd) != 0) {
            result = -errno;
        }
    }
    return result;
}
Esempio n. 4
0
static int cdrom_probe_device(const char *filename)
{
    int fd, ret;
    int prio = 0;
    struct stat st;

    fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
    if (fd < 0) {
        goto out;
    }
    ret = fstat(fd, &st);
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
        goto outc;
    }

    /* Attempt to detect via a CDROM specific ioctl */
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
    if (ret >= 0)
        prio = 100;

outc:
    qemu_close(fd);
out:
    return prio;
}
Esempio n. 5
0
static int hdev_create(const char *filename, QEMUOptionParameter *options)
{
    int fd;
    int ret = 0;
    struct stat stat_buf;
    int64_t total_size = 0;

    /* Read out options */
    while (options && options->name) {
        if (!strcmp(options->name, "size")) {
            total_size = options->value.n / BDRV_SECTOR_SIZE;
        }
        options++;
    }

    fd = qemu_open(filename, O_WRONLY | O_BINARY);
    if (fd < 0)
        return -errno;

    if (fstat(fd, &stat_buf) < 0)
        ret = -errno;
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
        ret = -ENODEV;
    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
        ret = -ENOSPC;

    qemu_close(fd);
    return ret;
}
Esempio n. 6
0
static void floppy_eject(BlockDriverState *bs, bool eject_flag)
{
    BDRVRawState *s = bs->opaque;
    int fd;

    if (s->fd >= 0) {
        qemu_close(s->fd);
        s->fd = -1;
    }
    fd = qemu_open(bs->filename, s->open_flags | O_NONBLOCK);
    if (fd >= 0) {
        if (ioctl(fd, FDEJECT, 0) < 0)
            perror("FDEJECT");
        qemu_close(fd);
    }
}
Esempio n. 7
0
static int raw_open_common(BlockDriverState *bs, QDict *options,
                           int bdrv_flags, int open_flags)
{
    BDRVRawState *s = bs->opaque;
    QemuOpts *opts;
    Error *local_err = NULL;
    const char *filename;
    int fd, ret;

    opts = qemu_opts_create_nofail(&raw_runtime_opts);
    qemu_opts_absorb_qdict(opts, options, &local_err);
    if (error_is_set(&local_err)) {
        qerror_report_err(local_err);
        error_free(local_err);
        ret = -EINVAL;
        goto fail;
    }

    filename = qemu_opt_get(opts, "filename");

    ret = raw_normalize_devicepath(&filename);
    if (ret != 0) {
        goto fail;
    }

    s->open_flags = open_flags;
    raw_parse_flags(bdrv_flags, &s->open_flags);

    s->fd = -1;
    fd = qemu_open(filename, s->open_flags, 0644);
    if (fd < 0) {
        ret = -errno;
        if (ret == -EROFS) {
            ret = -EACCES;
        }
        goto fail;
    }
    s->fd = fd;

#ifdef CONFIG_LINUX_AIO
    if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
        qemu_close(fd);
        ret = -errno;
        goto fail;
    }
#endif

    s->has_discard = 1;
#ifdef CONFIG_XFS
    if (platform_test_xfs_fd(s->fd)) {
        s->is_xfs = 1;
    }
#endif

    ret = 0;
fail:
    qemu_opts_del(opts);
    return ret;
}
Esempio n. 8
0
static void raw_close(BlockDriverState *bs)
{
    BDRVRawState *s = bs->opaque;
    if (s->fd >= 0) {
        qemu_close(s->fd);
        s->fd = -1;
    }
}
Esempio n. 9
0
static void rng_random_finalize(Object *obj)
{
    RndRandom *s = RNG_RANDOM(obj);

    if (s->fd != -1) {
        qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
        qemu_close(s->fd);
    }

    g_free(s->filename);
}
Esempio n. 10
0
static void raw_reopen_abort(BDRVReopenState *state)
{
    BDRVRawReopenState *raw_s = state->opaque;

     /* nothing to do if NULL, we didn't get far enough */
    if (raw_s == NULL) {
        return;
    }

    if (raw_s->fd >= 0) {
        qemu_close(raw_s->fd);
        raw_s->fd = -1;
    }
    g_free(state->opaque);
    state->opaque = NULL;
}
Esempio n. 11
0
static void raw_reopen_commit(BDRVReopenState *state)
{
    BDRVRawReopenState *raw_s = state->opaque;
    BDRVRawState *s = state->bs->opaque;

    s->open_flags = raw_s->open_flags;

    qemu_close(s->fd);
    s->fd = raw_s->fd;
#ifdef CONFIG_LINUX_AIO
    s->use_aio = raw_s->use_aio;
#endif

    g_free(state->opaque);
    state->opaque = NULL;
}
Esempio n. 12
0
static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
{
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
    const char *value;

    value = qemu_opt_get(opts, "cancel-path");
    if (value) {
        tb->cancel_path = g_strdup(value);
    }

    value = qemu_opt_get(opts, "path");
    if (!value) {
        value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
    }

    tpm_pt->tpm_dev = g_strdup(value);

    tb->path = g_strdup(tpm_pt->tpm_dev);

    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
    if (tpm_pt->tpm_fd < 0) {
        error_report("Cannot access TPM device using '%s': %s\n",
                     tpm_pt->tpm_dev, strerror(errno));
        goto err_free_parameters;
    }

    if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
        error_report("'%s' is not a TPM device.\n",
                     tpm_pt->tpm_dev);
        goto err_close_tpmdev;
    }

    return 0;

 err_close_tpmdev:
    qemu_close(tpm_pt->tpm_fd);
    tpm_pt->tpm_fd = -1;

 err_free_parameters:
    g_free(tb->path);
    tb->path = NULL;

    g_free(tpm_pt->tpm_dev);
    tpm_pt->tpm_dev = NULL;

    return 1;
}
Esempio n. 13
0
/* Note: we do not have a reliable method to detect if the floppy is
   present. The current method is to try to open the floppy at every
   I/O and to keep it opened during a few hundreds of ms. */
static int fd_open(BlockDriverState *bs)
{
    BDRVRawState *s = bs->opaque;
    int last_media_present;

    if (s->type != FTYPE_FD)
        return 0;
    last_media_present = (s->fd >= 0);
    if (s->fd >= 0 &&
        (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
        qemu_close(s->fd);
        s->fd = -1;
#ifdef DEBUG_FLOPPY
        printf("Floppy closed\n");
#endif
    }
    if (s->fd < 0) {
        if (s->fd_got_error &&
            (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
#ifdef DEBUG_FLOPPY
            printf("No floppy (open delayed)\n");
#endif
            return -EIO;
        }
        s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK);
        if (s->fd < 0) {
            s->fd_error_time = get_clock();
            s->fd_got_error = 1;
            if (last_media_present)
                s->fd_media_changed = 1;
#ifdef DEBUG_FLOPPY
            printf("No floppy\n");
#endif
            return -EIO;
        }
#ifdef DEBUG_FLOPPY
        printf("Floppy opened\n");
#endif
    }
    if (!last_media_present)
        s->fd_media_changed = 1;
    s->fd_open_time = get_clock();
    s->fd_got_error = 0;
    return 0;
}
Esempio n. 14
0
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
{
    BDRVRawState *s = bs->opaque;

#if defined(__APPLE__) && defined(__MACH__)
    if (strstart(filename, "/dev/cdrom", NULL)) {
        kern_return_t kernResult;
        io_iterator_t mediaIterator;
        char bsdPath[ MAXPATHLEN ];
        int fd;

        kernResult = FindEjectableCDMedia( &mediaIterator );
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );

        if ( bsdPath[ 0 ] != '\0' ) {
            strcat(bsdPath,"s0");
            /* some CDs don't have a partition 0 */
            fd = qemu_open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
            if (fd < 0) {
                bsdPath[strlen(bsdPath)-1] = '1';
            } else {
                qemu_close(fd);
            }
            filename = bsdPath;
        }

        if ( mediaIterator )
            IOObjectRelease( mediaIterator );
    }
#endif

    s->type = FTYPE_FILE;
#if defined(__linux__)
    {
        char resolved_path[ MAXPATHLEN ], *temp;

        temp = realpath(filename, resolved_path);
        if (temp && strstart(temp, "/dev/sg", NULL)) {
            bs->sg = 1;
        }
    }
#endif

    return raw_open_common(bs, filename, flags, 0);
}
Esempio n. 15
0
static int floppy_open(BlockDriverState *bs, QDict *options, int flags)
{
    BDRVRawState *s = bs->opaque;
    int ret;

    s->type = FTYPE_FD;

    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
    ret = raw_open_common(bs, options, flags, O_NONBLOCK);
    if (ret)
        return ret;

    /* close fd so that we can reopen it as needed */
    qemu_close(s->fd);
    s->fd = -1;
    s->fd_media_changed = 1;

    return 0;
}
Esempio n. 16
0
static int raw_open_common(BlockDriverState *bs, const char *filename,
                           int bdrv_flags, int open_flags)
{
    BDRVRawState *s = bs->opaque;
    int fd, ret;

    ret = raw_normalize_devicepath(&filename);
    if (ret != 0) {
        return ret;
    }

    s->open_flags = open_flags;
    raw_parse_flags(bdrv_flags, &s->open_flags);

    s->fd = -1;
    fd = qemu_open(filename, s->open_flags, 0644);
    if (fd < 0) {
        ret = -errno;
        if (ret == -EROFS)
            ret = -EACCES;
        return ret;
    }
    s->fd = fd;

#ifdef CONFIG_LINUX_AIO
    if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
        qemu_close(fd);
        return -errno;
    }
#endif

    s->has_discard = 1;
#ifdef CONFIG_XFS
    if (platform_test_xfs_fd(s->fd)) {
        s->is_xfs = 1;
    }
#endif

    return 0;
}
Esempio n. 17
0
static int cdrom_reopen(BlockDriverState *bs)
{
    BDRVRawState *s = bs->opaque;
    int fd;

    /*
     * Force reread of possibly changed/newly loaded disc,
     * FreeBSD seems to not notice sometimes...
     */
    if (s->fd >= 0)
        qemu_close(s->fd);
    fd = qemu_open(bs->filename, s->open_flags, 0644);
    if (fd < 0) {
        s->fd = -1;
        return -EIO;
    }
    s->fd = fd;

    /* make sure the door isn't locked at this time */
    ioctl(s->fd, CDIOCALLOW);
    return 0;
}
Esempio n. 18
0
static int raw_reopen_prepare(BDRVReopenState *state,
                              BlockReopenQueue *queue, Error **errp)
{
    BDRVRawState *s;
    BDRVRawReopenState *raw_s;
    int ret = 0;

    assert(state != NULL);
    assert(state->bs != NULL);

    s = state->bs->opaque;

    state->opaque = g_malloc0(sizeof(BDRVRawReopenState));
    raw_s = state->opaque;

#ifdef CONFIG_LINUX_AIO
    raw_s->use_aio = s->use_aio;

    /* we can use s->aio_ctx instead of a copy, because the use_aio flag is
     * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio()
     * won't override aio_ctx if aio_ctx is non-NULL */
    if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) {
        return -1;
    }
#endif

    if (s->type == FTYPE_FD || s->type == FTYPE_CD) {
        raw_s->open_flags |= O_NONBLOCK;
    }

    raw_parse_flags(state->flags, &raw_s->open_flags);

    raw_s->fd = -1;

    int fcntl_flags = O_APPEND | O_NONBLOCK;
#ifdef O_NOATIME
    fcntl_flags |= O_NOATIME;
#endif

#ifdef O_ASYNC
    /* Not all operating systems have O_ASYNC, and those that don't
     * will not let us track the state into raw_s->open_flags (typically
     * you achieve the same effect with an ioctl, for example I_SETSIG
     * on Solaris). But we do not use O_ASYNC, so that's fine.
     */
    assert((s->open_flags & O_ASYNC) == 0);
#endif

    if ((raw_s->open_flags & ~fcntl_flags) == (s->open_flags & ~fcntl_flags)) {
        /* dup the original fd */
        /* TODO: use qemu fcntl wrapper */
#ifdef F_DUPFD_CLOEXEC
        raw_s->fd = fcntl(s->fd, F_DUPFD_CLOEXEC, 0);
#else
        raw_s->fd = dup(s->fd);
        if (raw_s->fd != -1) {
            qemu_set_cloexec(raw_s->fd);
        }
#endif
        if (raw_s->fd >= 0) {
            ret = fcntl_setfl(raw_s->fd, raw_s->open_flags);
            if (ret) {
                qemu_close(raw_s->fd);
                raw_s->fd = -1;
            }
        }
    }

    /* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
    if (raw_s->fd == -1) {
        assert(!(raw_s->open_flags & O_CREAT));
        raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags);
        if (raw_s->fd == -1) {
            ret = -1;
        }
    }
    return ret;
}
Esempio n. 19
0
/*
 * A basic test of a TPM device. We expect a well formatted response header
 * (error response is fine) within one second.
 */
static int tpm_passthrough_test_tpmdev(int fd)
{
    struct tpm_req_hdr req = {
        .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
        .len = cpu_to_be32(sizeof(req)),
        .ordinal = cpu_to_be32(TPM_ORD_GetTicks),
    };
    struct tpm_resp_hdr *resp;
    fd_set readfds;
    int n;
    struct timeval tv = {
        .tv_sec = 1,
        .tv_usec = 0,
    };
    unsigned char buf[1024];

    n = write(fd, &req, sizeof(req));
    if (n < 0) {
        return errno;
    }
    if (n != sizeof(req)) {
        return EFAULT;
    }

    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);

    /* wait for a second */
    n = select(fd + 1, &readfds, NULL, NULL, &tv);
    if (n != 1) {
        return errno;
    }

    n = read(fd, &buf, sizeof(buf));
    if (n < sizeof(struct tpm_resp_hdr)) {
        return EFAULT;
    }

    resp = (struct tpm_resp_hdr *)buf;
    /* check the header */
    if (be16_to_cpu(resp->tag) != TPM_TAG_RSP_COMMAND ||
        be32_to_cpu(resp->len) != n) {
        return EBADMSG;
    }

    return 0;
}

/*
 * Unless path or file descriptor set has been provided by user,
 * determine the sysfs cancel file following kernel documentation
 * in Documentation/ABI/stable/sysfs-class-tpm.
 * From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
 */
static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
{
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
    int fd = -1;
    char *dev;
    char path[PATH_MAX];

    if (tb->cancel_path) {
        fd = qemu_open(tb->cancel_path, O_WRONLY);
        if (fd < 0) {
            error_report("Could not open TPM cancel path : %s",
                         strerror(errno));
        }
        return fd;
    }

    dev = strrchr(tpm_pt->tpm_dev, '/');
    if (dev) {
        dev++;
        if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
                     dev) < sizeof(path)) {
            fd = qemu_open(path, O_WRONLY);
            if (fd >= 0) {
                tb->cancel_path = g_strdup(path);
            } else {
                error_report("tpm_passthrough: Could not open TPM cancel "
                             "path %s : %s", path, strerror(errno));
            }
        }
    } else {
       error_report("tpm_passthrough: Bad TPM device path %s",
                    tpm_pt->tpm_dev);
    }

    return fd;
}

static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
{
    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
    const char *value;

    value = qemu_opt_get(opts, "cancel-path");
    tb->cancel_path = g_strdup(value);

    value = qemu_opt_get(opts, "path");
    if (!value) {
        value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
    }

    tpm_pt->tpm_dev = g_strdup(value);

    tb->path = g_strdup(tpm_pt->tpm_dev);

    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
    if (tpm_pt->tpm_fd < 0) {
        error_report("Cannot access TPM device using '%s': %s",
                     tpm_pt->tpm_dev, strerror(errno));
        goto err_free_parameters;
    }

    if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
        error_report("'%s' is not a TPM device.",
                     tpm_pt->tpm_dev);
        goto err_close_tpmdev;
    }

    return 0;

 err_close_tpmdev:
    qemu_close(tpm_pt->tpm_fd);
    tpm_pt->tpm_fd = -1;

 err_free_parameters:
    g_free(tb->path);
    tb->path = NULL;

    g_free(tpm_pt->tpm_dev);
    tpm_pt->tpm_dev = NULL;

    return 1;
}
Esempio n. 20
0
File: qapi.c Progetto: AlexHai/qemu
/**
 * bdrv_query_image_info:
 * @bs: block device to examine
 * @p_info: location to store image information
 * @errp: location to store error information
 *
 * Store "flat" image information in @p_info.
 *
 * "Flat" means it does *not* query backing image information,
 * i.e. (*pinfo)->has_backing_image will be set to false and
 * (*pinfo)->backing_image to NULL even when the image does in fact have
 * a backing image.
 *
 * @p_info will be set only on success. On error, store error in @errp.
 */
void bdrv_query_image_info(BlockDriverState *bs,
                           ImageInfo **p_info,
                           Error **errp)
{
    int64_t size;
    const char *backing_filename;
    char backing_filename2[1024];
    BlockDriverInfo bdi;
    int ret;
    Error *err = NULL;
    ImageInfo *info;
#ifdef __linux__
    int fd, attr;
#endif

    size = bdrv_getlength(bs);
    if (size < 0) {
        error_setg_errno(errp, -size, "Can't get size of device '%s'",
                         bdrv_get_device_name(bs));
        return;
    }

    info = g_new0(ImageInfo, 1);
    info->filename        = g_strdup(bs->filename);
    info->format          = g_strdup(bdrv_get_format_name(bs));
    info->virtual_size    = size;
    info->actual_size     = bdrv_get_allocated_file_size(bs);
    info->has_actual_size = info->actual_size >= 0;
    if (bdrv_is_encrypted(bs)) {
        info->encrypted = true;
        info->has_encrypted = true;
    }
    if (bdrv_get_info(bs, &bdi) >= 0) {
        if (bdi.cluster_size != 0) {
            info->cluster_size = bdi.cluster_size;
            info->has_cluster_size = true;
        }
        info->dirty_flag = bdi.is_dirty;
        info->has_dirty_flag = true;
    }
    info->format_specific     = bdrv_get_specific_info(bs);
    info->has_format_specific = info->format_specific != NULL;

#ifdef __linux__
    /* get NOCOW info */
    fd = qemu_open(bs->filename, O_RDONLY | O_NONBLOCK);
    if (fd >= 0) {
        if (ioctl(fd, FS_IOC_GETFLAGS, &attr) == 0 && (attr & FS_NOCOW_FL)) {
            info->has_nocow = true;
            info->nocow = true;
        }
        qemu_close(fd);
    }
#endif

    backing_filename = bs->backing_file;
    if (backing_filename[0] != '\0') {
        info->backing_filename = g_strdup(backing_filename);
        info->has_backing_filename = true;
        bdrv_get_full_backing_filename(bs, backing_filename2,
                                       sizeof(backing_filename2));

        if (strcmp(backing_filename, backing_filename2) != 0) {
            info->full_backing_filename =
                        g_strdup(backing_filename2);
            info->has_full_backing_filename = true;
        }

        if (bs->backing_format[0]) {
            info->backing_filename_format = g_strdup(bs->backing_format);
            info->has_backing_filename_format = true;
        }
    }

    ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err);
    switch (ret) {
    case 0:
        if (info->snapshots) {
            info->has_snapshots = true;
        }
        break;
    /* recoverable error */
    case -ENOMEDIUM:
    case -ENOTSUP:
        error_free(err);
        break;
    default:
        error_propagate(errp, err);
        qapi_free_ImageInfo(info);
        return;
    }

    *p_info = info;
}