示例#1
0
文件: char.c 项目: mdroth/qemu
static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
                           bool *be_opened, Error **errp)
{
    ChardevClass *cc = CHARDEV_GET_CLASS(chr);
    /* Any ChardevCommon member would work */
    ChardevCommon *common = backend ? backend->u.null.data : NULL;

    if (common && common->has_logfile) {
        int flags = O_WRONLY | O_CREAT;
        if (common->has_logappend &&
            common->logappend) {
            flags |= O_APPEND;
        } else {
            flags |= O_TRUNC;
        }
        chr->logfd = qemu_open(common->logfile, flags, 0666);
        if (chr->logfd < 0) {
            error_setg_errno(errp, errno,
                             "Unable to open logfile %s",
                             common->logfile);
            return;
        }
    }

    if (cc->open) {
        cc->open(chr, backend, be_opened, errp);
    }
}
示例#2
0
static void write_pidfile(void)
{
    int pidfd;
    char pidstr[32];

    pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
    if (pidfd == -1) {
        error_report("Cannot open pid file, %s", strerror(errno));
        exit(EXIT_FAILURE);
    }

    if (lockf(pidfd, F_TLOCK, 0)) {
        error_report("Cannot lock pid file, %s", strerror(errno));
        goto fail;
    }
    if (ftruncate(pidfd, 0)) {
        error_report("Failed to truncate pid file");
        goto fail;
    }

    snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
    if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
        error_report("Failed to write pid file");
        goto fail;
    }
    return;

fail:
    unlink(pidfile);
    close(pidfd);
    exit(EXIT_FAILURE);
}
示例#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;
}
示例#4
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;
}
示例#5
0
static int rtc_start_timer(struct qemu_alarm_timer *t)
{
    int rtc_fd;
    unsigned long current_rtc_freq = 0;

    TFR(rtc_fd = qemu_open("/dev/rtc", O_RDONLY));
    if (rtc_fd < 0)
        return -1;
    ioctl(rtc_fd, RTC_IRQP_READ, &current_rtc_freq);
    if (current_rtc_freq != RTC_FREQ &&
        ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) {
        fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n"
                "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n"
                "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n");
        goto fail;
    }
    if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
    fail:
        close(rtc_fd);
        return -1;
    }

    enable_sigio_timer(rtc_fd);

    t->priv = (void *)(long)rtc_fd;

    return 0;
}
示例#6
0
文件: main.c 项目: JunaidLoonat/qemu
static bool ga_open_pidfile(const char *pidfile)
{
    int pidfd;
    char pidstr[32];

    pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
    if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
        g_critical("Cannot lock pid file, %s", strerror(errno));
        if (pidfd != -1) {
            close(pidfd);
        }
        return false;
    }

    if (ftruncate(pidfd, 0)) {
        g_critical("Failed to truncate pid file");
        goto fail;
    }
    snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
    if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
        g_critical("Failed to write pid file");
        goto fail;
    }

    /* keep pidfile open & locked forever */
    return true;

fail:
    unlink(pidfile);
    close(pidfd);
    return false;
}
示例#7
0
文件: os-posix.c 项目: limboemu/limbo
int qemu_create_pidfile(const char *filename)
{
    char buffer[128];
    int len;
    int fd;

    fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
    if (fd == -1) {
        return -1;
    }
#ifndef __ANDROID__
    if (lockf(fd, F_TLOCK, 0) == -1) {
        close(fd);
        return -1;
    }
    len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid());
    if (write(fd, buffer, len) != len) {
        close(fd);
        return -1;
    }
#endif // __ANDROID__

    /* keep pidfile open & locked forever */
    return 0;
}
示例#8
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;
}
示例#9
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;
}
示例#10
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;
}
示例#11
0
文件: char-fd.c 项目: mdroth/qemu
int qmp_chardev_open_file_source(char *src, int flags, Error **errp)
{
    int fd = -1;

    TFR(fd = qemu_open(src, flags, 0666));
    if (fd == -1) {
        error_setg_file_open(errp, errno, src);
    }
    return fd;
}
示例#12
0
文件: rng-random.c 项目: Aakriti/qemu
static void rng_random_opened(RngBackend *b, Error **errp)
{
    RndRandom *s = RNG_RANDOM(b);

    if (s->filename == NULL) {
        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
                  "filename", "a valid filename");
    } else {
        s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
        if (s->fd == -1) {
            error_setg_file_open(errp, errno, s->filename);
        }
    }
}
示例#13
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;
}
示例#14
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);
    }
}
示例#15
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;
}
示例#16
0
文件: osdep.c 项目: joshsyu/PQEMU
int qemu_create_pidfile(const char *filename)
{
    char buffer[128];
    int len;
#ifndef _WIN32
    int fd;

    fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
    if (fd == -1)
        return -1;

    if (lockf(fd, F_TLOCK, 0) == -1)
        return -1;

    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
    if (write(fd, buffer, len) != len)
        return -1;
#else
    HANDLE file;
    DWORD flags;
    OVERLAPPED overlap;
    BOOL ret;

    /* Open for writing with no sharing. */
    file = CreateFile(filename, GENERIC_WRITE, 0, NULL,
		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (file == INVALID_HANDLE_VALUE)
      return -1;

    flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
    overlap.hEvent = 0;
    /* Lock 1 byte. */
    ret = LockFileEx(file, flags, 0, 0, 1, &overlap);
    if (ret == 0)
      return -1;

    /* Write PID to file. */
    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
    ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
		      &overlap, NULL);
    if (ret == 0)
      return -1;
#endif
    return 0;
}
示例#17
0
文件: raw-posix.c 项目: Jokymon/qemu
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);
}
示例#18
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;
}
int qemu_create_pidfile(const char *filename)
{
    char buffer[128];
    int len;
    int fd;

    fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
    if (fd == -1) {
        return -1;
    }
    if (lockf(fd, F_TLOCK, 0) == -1) {
        return -1;
    }
    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
    if (write(fd, buffer, len) != len) {
        return -1;
    }

    return 0;
}
示例#20
0
static int hpet_start_timer(struct qemu_alarm_timer *t)
{
    struct hpet_info info;
    int r, fd;

    fd = qemu_open("/dev/hpet", O_RDONLY);
    if (fd < 0)
        return -1;

    /* Set frequency */
    r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ);
    if (r < 0) {
        fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n"
                "error, but for better emulation accuracy type:\n"
                "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n");
        goto fail;
    }

    /* Check capabilities */
    r = ioctl(fd, HPET_INFO, &info);
    if (r < 0)
        goto fail;

    /* Enable periodic mode */
    r = ioctl(fd, HPET_EPI, 0);
    if (info.hi_flags && (r < 0))
        goto fail;

    /* Enable interrupt */
    r = ioctl(fd, HPET_IE_ON, 0);
    if (r < 0)
        goto fail;

    enable_sigio_timer(fd);
    t->priv = (void *)(long)fd;

    return 0;
fail:
    close(fd);
    return -1;
}
示例#21
0
文件: raw-posix.c 项目: Jokymon/qemu
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;
}
示例#22
0
文件: os-posix.c 项目: CTU-IIG/qemu
void os_setup_post(void)
{
    int fd = 0;

    if (daemonize) {
        if (chdir("/")) {
            error_report("not able to chdir to /: %s", strerror(errno));
            exit(1);
        }
        TFR(fd = qemu_open("/dev/null", O_RDWR));
        if (fd == -1) {
            exit(1);
        }
    }

    change_root();
    change_process_uid();

    if (daemonize) {
        uint8_t status = 0;
        ssize_t len;

        dup2(fd, 0);
        dup2(fd, 1);
        /* In case -D is given do not redirect stderr to /dev/null */
        if (!qemu_logfile) {
            dup2(fd, 2);
        }

        close(fd);

        do {        
            len = write(daemon_pipe, &status, 1);
        } while (len < 0 && errno == EINTR);
        if (len != 1) {
            exit(1);
        }
    }
}
示例#23
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;
}
示例#24
0
static int kvm_vm_clone(KVMState *s)
{
    struct stat stat;
    int fd;

    if (fstat(s->fd, &stat) != 0) {
        return -errno;
    }

    fd = qemu_open("/dev/kvm", O_RDWR);

    if (fd == -1) {
        return -errno;
    }

    if (ioctl(fd, KVM_CLONE, stat.st_rdev) == -1) {
        close(fd);
        return -errno;
    }

    return fd;
}
示例#25
0
void os_setup_post(void)
{
    int fd = 0;

    if (daemonize) {
	uint8_t status = 0;
	ssize_t len;

    again1:
	len = write(fds[1], &status, 1);
	LOGV("%s:%s=%d, write(), len = %d", __FILE__, __func__, status, len);
	if (len == -1 && (errno == EINTR))
	    goto again1;

	if (len != 1)
	    exit(1);

        if (chdir("/")) {
            perror("not able to chdir to /");
            exit(1);
        }
	TFR(fd = qemu_open("/dev/null", O_RDWR));
	if (fd == -1)
	    exit(1);
    }

    change_root();
    change_process_uid();

    if (daemonize) {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);

        close(fd);
    }
}
示例#26
0
文件: osdep.c 项目: mozyg/qemu
int qemu_create_pidfile(const char *filename)
{
    char buffer[128];
    int len;
#ifndef _WIN32
    int fd;

    fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
    if (fd == -1)
        return -1;

    if (lockf(fd, F_TLOCK, 0) == -1)
        return -1;

    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
    if (write(fd, buffer, len) != len)
        return -1;
#else
    HANDLE file;
    OVERLAPPED overlap;
    BOOL ret;
    memset(&overlap, 0, sizeof(overlap));

    file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
		      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (file == INVALID_HANDLE_VALUE)
      return -1;

    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
    ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
		      &overlap, NULL);
    if (ret == 0)
      return -1;
#endif
    return 0;
}
示例#27
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;
}

/*
 * Check whether the given base path, e.g.,  /sys/class/misc/tpm0/device,
 * is the sysfs directory of a TPM. A TPM sysfs directory should be uniquely
 * recognizable by the file entries 'pcrs' and 'cancel'.
 * Upon success 'true' is returned and the basebath buffer has '/cancel'
 * appended.
 */
static bool tpm_passthrough_check_sysfs_cancel(char *basepath, size_t bufsz)
{
    char path[PATH_MAX];
    struct stat statbuf;

    snprintf(path, sizeof(path), "%s/pcrs", basepath);
    if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
        return false;
    }

    snprintf(path, sizeof(path), "%s/cancel", basepath);
    if (stat(path, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
        return false;
    }

    strncpy(basepath, path, bufsz);

    return true;
}

/*
 * 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.
 */
static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
{
    int fd = -1;
    unsigned int idx;
    DIR *pnp_dir;
    char path[PATH_MAX];
    struct dirent entry, *result;
    int len;

    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;
    }

    snprintf(path, sizeof(path), "/sys/class/misc");
    pnp_dir = opendir(path);
    if (pnp_dir != NULL) {
        while (readdir_r(pnp_dir, &entry, &result) == 0 &&
               result != NULL) {
            /*
             * only allow /sys/class/misc/tpm%u type of paths
             */
            if (sscanf(entry.d_name, "tpm%u%n", &idx, &len) < 1 ||
                len <= strlen("tpm") ||
                len != strlen(entry.d_name)) {
                continue;
            }

            snprintf(path, sizeof(path), "/sys/class/misc/%s/device",
                     entry.d_name);
            if (!tpm_passthrough_check_sysfs_cancel(path, sizeof(path))) {
                continue;
            }

            fd = qemu_open(path, O_WRONLY);
            break;
        }
        closedir(pnp_dir);
    }

    if (fd >= 0) {
        tb->cancel_path = g_strdup(path);
    }

    return fd;
}
示例#28
0
static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod method)
{
    int ret;
    c->method = method;

    switch (c->method) {
    case GA_CHANNEL_VIRTIO_SERIAL: {
        int fd = qemu_open(path, O_RDWR | O_NONBLOCK
#ifndef CONFIG_SOLARIS
                           | O_ASYNC
#endif
                           );
        if (fd == -1) {
            g_critical("error opening channel: %s", strerror(errno));
            return false;
        }
#ifdef CONFIG_SOLARIS
        ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI);
        if (ret == -1) {
            g_critical("error setting event mask for channel: %s",
                       strerror(errno));
            close(fd);
            return false;
        }
#endif
        ret = ga_channel_client_add(c, fd);
        if (ret) {
            g_critical("error adding channel to main loop");
            close(fd);
            return false;
        }
        break;
    }
    case GA_CHANNEL_ISA_SERIAL: {
        struct termios tio;
        int fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd == -1) {
            g_critical("error opening channel: %s", strerror(errno));
            return false;
        }
        tcgetattr(fd, &tio);
        /* set up serial port for non-canonical, dumb byte streaming */
        tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
                         INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY |
                         IMAXBEL);
        tio.c_oflag = 0;
        tio.c_lflag = 0;
        tio.c_cflag |= GA_CHANNEL_BAUDRATE_DEFAULT;
        /* 1 available byte min or reads will block (we'll set non-blocking
         * elsewhere, else we have to deal with read()=0 instead)
         */
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 0;
        /* flush everything waiting for read/xmit, it's garbage at this point */
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd, TCSANOW, &tio);
        ret = ga_channel_client_add(c, fd);
        if (ret) {
            g_critical("error adding channel to main loop");
            close(fd);
            return false;
        }
        break;
    }
    case GA_CHANNEL_UNIX_LISTEN: {
        Error *local_err = NULL;
        int fd = unix_listen(path, NULL, strlen(path), &local_err);
        if (local_err != NULL) {
            g_critical("%s", error_get_pretty(local_err));
            error_free(local_err);
            return false;
        }
        ga_channel_listen_add(c, fd, true);
        break;
    }
    default:
        g_critical("error binding/listening to specified socket");
        return false;
    }

    return true;
}
示例#29
0
/**
 * \ingroup imglib
 * Opens one or more disk image files so that they can be read.  If a file format
 * type is specified, this function will call the specific routine to open the file.
 * Otherwise, it will detect the type (it will default to raw if no specific type can
 * be detected).   This function must be called before a disk image can be read from. 
 * Note that the data type used to store the image paths is a TSK_TCHAR, which changes
 * depending on a Unix or Windows build.  If you will always have UTF8, then consider
 * using tsk_img_open_utf8(). 
 *
 * @param num_img The number of images to open (will be > 1 for split images).
 * @param images The path to the image files (the number of files must
 * be equal to num_img and they must be in a sorted order)
 * @param type The disk image type (can be autodetection)
 * @param a_ssize Size of device sector in bytes (or 0 for default)
 *
 * @return Pointer to TSK_IMG_INFO or NULL on error
 */
TSK_IMG_INFO *
tsk_img_open(int num_img,
    const TSK_TCHAR * const images[], TSK_IMG_TYPE_ENUM type,
    unsigned int a_ssize)
{
    TSK_IMG_INFO *img_info = NULL;

    // Get rid of any old error messages laying around
    tsk_error_reset();

    if ((num_img == 0) || (images[0] == NULL)) {
        tsk_error_reset();
        tsk_errno = TSK_ERR_IMG_NOFILE;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "tsk_img_open");
        return NULL;
    }
    
    if ((a_ssize > 0) && (a_ssize < 512)) {
        tsk_error_reset(); 
        tsk_errno = TSK_ERR_IMG_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "sector size is less than 512 bytes (%d)", a_ssize);
        return NULL;
    }
    
    if ((a_ssize % 512) != 0) {
        tsk_error_reset(); 
        tsk_errno = TSK_ERR_IMG_ARG;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "sector size is not a multiple of 512 (%d)", a_ssize);
        return NULL;
    }
    

    if (tsk_verbose)
        TFPRINTF(stderr,
            _TSK_T("tsk_img_open: Type: %d   NumImg: %d  Img1: %s\n"),
            type, num_img, images[0]);

    /* If no type is given, then we use the autodetection methods 
     * In case the image file matches the signatures of multiple formats,
     * we try all of the embedded formats 
     */
    if (type == TSK_IMG_TYPE_DETECT) {
        TSK_IMG_INFO *img_set = NULL;
#if HAVE_LIBAFFLIB || HAVE_LIBEWF
        char *set = NULL;
#endif
        struct STAT_STR stat_buf;

        // we rely on tsk_errno, so make sure it is 0
        tsk_error_reset();

        /* Try the non-raw formats first */
#if HAVE_LIBAFFLIB
        if ((img_info = aff_open(images, a_ssize)) != NULL) {
            /* we don't allow the "ANY" when autodetect is used because
             * we only want to detect the tested formats. */
            if (img_info->itype == TSK_IMG_TYPE_AFF_ANY) {
                img_info->close(img_info);
            }
            else {
                set = "AFF";
                img_set = img_info;
            }
        }
        else {
            // If AFF is otherwise happy except for a password, stop trying to guess
            if (tsk_errno == TSK_ERR_IMG_PASSWD) {
                return NULL;
            }
            tsk_error_reset();
        }
#endif

#if HAVE_LIBEWF
        if ((img_info = ewf_open(num_img, images, a_ssize)) != NULL) {
            if (set == NULL) {
                set = "EWF";
                img_set = img_info;
            }
            else {
                img_set->close(img_set);
                img_info->close(img_info);
                tsk_error_reset();
                tsk_errno = TSK_ERR_IMG_UNKTYPE;
                snprintf(tsk_errstr, TSK_ERRSTR_L, "EWF or %s", set);
                return NULL;
            }
        }
        else {
            tsk_error_reset();
        }
#endif
        // if any of the non-raw formats were detected, then use it. 
        if (img_set != NULL)
            return img_set;

        /* We'll use the raw format */
        if (num_img == 1) {
            if ((img_info = raw_open(images[0], a_ssize)) != NULL) {
                return img_info;
            }
            else if (tsk_errno) {
                return NULL;
            }
        }
        else {
            if ((img_info = split_open(num_img, images, a_ssize)) != NULL) {
                return img_info;
            }
            else if (tsk_errno) {
                return NULL;
            }
        }

        /* To improve the error message, verify the file can be read. */
        if (TSTAT(images[0], &stat_buf) < 0) {
            // special case to handle windows objects
#if defined(TSK_WIN32) || defined(__CYGWIN__)
            if (TSTRNCMP(_TSK_T("\\\\.\\"), images[0], 4) == 0) {
                if (tsk_verbose)
                    TFPRINTF(stderr,
                        _TSK_T
                        ("tsk_img_open: Ignoring stat error because of windows object: %s\n"),
                        images[0]);
            }
            else {
#endif
                tsk_error_reset();
                tsk_errno = TSK_ERR_IMG_STAT;
                snprintf(tsk_errstr, TSK_ERRSTR_L, "%" PRIttocTSK " : %s",
                    images[0], strerror(errno));
                return NULL;
#if defined(TSK_WIN32) || defined(__CYGWIN__)
            }
#endif
        }

        tsk_errno = TSK_ERR_IMG_UNKTYPE;
        tsk_errstr[0] = '\0';
        tsk_errstr2[0] = '\0';
        return NULL;
    }

    /*
     * Type values
     * Make a local copy that we can modify the string as we parse it
     */

    switch (type) {
    case TSK_IMG_TYPE_RAW_SING:

        /* If we have more than one image name, and raw was the only
         * type given, then use split */
        if (num_img > 1)
            img_info = split_open(num_img, images, a_ssize);
        else
            img_info = raw_open(images[0], a_ssize);
        break;

    case TSK_IMG_TYPE_RAW_SPLIT:

        /* If only one image file is given, and only one type was
         * given then use raw */
        if (num_img == 1)
            img_info = raw_open(images[0], a_ssize);
        else
            img_info = split_open(num_img, images, a_ssize);
        break;

#if HAVE_LIBAFFLIB
    case TSK_IMG_TYPE_AFF_AFF:
    case TSK_IMG_TYPE_AFF_AFD:
    case TSK_IMG_TYPE_AFF_AFM:
    case TSK_IMG_TYPE_AFF_ANY:
        img_info = aff_open(images, a_ssize);
        break;
#endif

#if HAVE_LIBEWF
    case TSK_IMG_TYPE_EWF_EWF:
        img_info = ewf_open(num_img, images, a_ssize);
        break;
#endif
    case TSK_IMG_TYPE_QEMU:
        img_info = qemu_open(images[0], a_ssize);
        break;

    default:
        tsk_error_reset();
        tsk_errno = TSK_ERR_IMG_UNSUPTYPE;
        snprintf(tsk_errstr, TSK_ERRSTR_L, "%d", type);
        return NULL;
    }

    return img_info;
}
示例#30
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 | O_BINARY;
    s->open_flags &= ~O_ACCMODE;
    if (bdrv_flags & BDRV_O_RDWR) {
        s->open_flags |= O_RDWR;
    } else {
        s->open_flags |= O_RDONLY;
    }

    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
     * and O_DIRECT for no caching. */
    if ((bdrv_flags & BDRV_O_NOCACHE))
        s->open_flags |= O_DIRECT;
    if (!(bdrv_flags & BDRV_O_CACHE_WB))
        s->open_flags |= O_DSYNC;

    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;
    s->aligned_buf = NULL;

    if ((bdrv_flags & BDRV_O_NOCACHE)) {
        /*
         * Allocate a buffer for read/modify/write cycles.  Chose the size
         * pessimistically as we don't know the block size yet.
         */
        s->aligned_buf_size = 32 * MAX_BLOCKSIZE;
        s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size);
        if (s->aligned_buf == NULL) {
            goto out_close;
        }
    }

#ifdef CONFIG_LINUX_AIO
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {

        /* We're falling back to POSIX AIO in some cases */
        paio_init();

        s->aio_ctx = laio_init();
        if (!s->aio_ctx) {
            goto out_free_buf;
        }
        s->use_aio = 1;
    } else
#endif
    {
        if (paio_init() < 0) {
            goto out_free_buf;
        }
#ifdef CONFIG_LINUX_AIO
        s->use_aio = 0;
#endif
    }

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

    return 0;

out_free_buf:
    qemu_vfree(s->aligned_buf);
out_close:
    close(fd);
    return -errno;
}