Пример #1
0
static void
ioctl_emulate_open(int fd, const char *dev_path)
{
    libc_func(fclose, int, FILE *);
    FILE *f;
    static char ioctl_path[PATH_MAX];
    struct ioctl_fd_info *fdinfo;

    if (strncmp(dev_path, "/dev/", 5) != 0)
	return;

    fdinfo = malloc(sizeof(struct ioctl_fd_info));
    fdinfo->tree = NULL;
    fdinfo->last = NULL;
    fd_map_add(&ioctl_wrapped_fds, fd, fdinfo);

    /* check if we have an ioctl tree for this */
    snprintf(ioctl_path, sizeof(ioctl_path), "%s/ioctl/%s", getenv("UMOCKDEV_DIR"), dev_path);

    f = fopen(ioctl_path, "r");
    if (f == NULL)
	return;

    fdinfo->tree = ioctl_tree_read(f);
    _fclose(f);
    if (fdinfo->tree == NULL) {
	fprintf(stderr, "ERROR: libumockdev-preload: failed to load ioctl record file for %s: empty or invalid format?",
		dev_path);
	exit(1);
    }
    DBG(DBG_IOCTL, "ioctl_emulate_open fd %i (%s): loaded ioctl tree\n", fd, dev_path);
}
Пример #2
0
static void
ioctl_record_open(int fd)
{
    static dev_t record_rdev = (dev_t) - 1;

    if (fd < 0)
	return;

    /* lazily initialize record_rdev */
    if (record_rdev == (dev_t) - 1) {
	const char *dev = getenv("UMOCKDEV_IOCTL_RECORD_DEV");

	if (dev != NULL)
	    record_rdev = parse_dev_t(dev, "$UMOCKDEV_IOCTL_RECORD_DEV", 1);
	else {
	    /* not recording */
	    record_rdev = 0;
	}
    }

    if (record_rdev == 0)
	return;

    /* check if the opened device is the one we want to record */
    if (dev_of_fd(fd) != record_rdev)
	return;

    /* recording is already in progress? */
    if (ioctl_record_fd >= 0) {
	/* libmtp opens the device multiple times, we can't do that */
	/*
       fprintf(stderr, "umockdev: recording for this device is already ongoing, stopping recording of previous open()\n");
       ioctl_record_close();
       */
       fprintf(stderr, "umockdev: WARNING: ioctl recording for this device is already ongoing on fd %i, but application opened it a second time on fd %i without closing\n", ioctl_record_fd, fd);
    }

    ioctl_record_fd = fd;

    /* lazily open the record file */
    if (ioctl_record_log == NULL) {
	const char *path = getenv("UMOCKDEV_IOCTL_RECORD_FILE");
	const char *device_path = getenv("UMOCKDEV_IOCTL_RECORD_DEVICE_PATH");
	struct sigaction act_int;

	if (path == NULL) {
	    fprintf(stderr, "umockdev: $UMOCKDEV_IOCTL_RECORD_FILE not set\n");
	    exit(1);
	}
	if (device_path == NULL) {
	    fprintf(stderr, "umockdev: $UMOCKDEV_IOCTL_RECORD_DEVICE_PATH not set\n");
	    exit(1);
	}
	if (getenv("UMOCKDEV_DIR") != NULL) {
	    fprintf(stderr, "umockdev: $UMOCKDEV_DIR cannot be used while recording\n");
	    exit(1);
	}
	ioctl_record_log = fopen(path, "a+");
	if (ioctl_record_log == NULL) {
	    perror("umockdev: failed to open ioctl record file");
	    exit(1);
	}
	/* We record the device node for later loading without specifying
	 * the devpath in umockdev_testbed_load_ioctl.
	 */
	fseek(ioctl_record_log, 0, SEEK_END);
	if (ftell(ioctl_record_log) > 0) {
	    /* We're updating a previous log; don't write the devnode header again,
	     * but check that we're recording the same device as the previous log.
	     */
	    char *existing_device_path;
	    char c;
	    DBG(DBG_IOCTL, "ioctl_record_open: Updating existing record for path %s\n", path);
	    fseek(ioctl_record_log, 0, SEEK_SET);

	    /* Start by skipping any leading comments */
	    while ((c = fgetc(ioctl_record_log)) == '#')
		while (fgetc(ioctl_record_log) != '\n')
		    ;
	    ungetc(c, ioctl_record_log);

	    if (fscanf(ioctl_record_log, "@DEV %ms\n", &existing_device_path) == 1)
	    {
		/* We have an existing "@DEV /dev/something" directive, check it matches */
		DBG(DBG_IOCTL, "ioctl_record_open: recording %s, existing device spec in record %s\n", device_path, existing_device_path);
		if (strcmp(device_path, existing_device_path) != 0) {
		    fprintf(stderr, "umockdev: attempt to record two different devices to the same ioctl recording\n");
		    exit(1);
		}
		free(existing_device_path);
	    }

	    /* load an already existing log */
	    fseek(ioctl_record_log, 0, SEEK_SET);
	    ioctl_record = ioctl_tree_read(ioctl_record_log);
	} else {
	    /* New log, add devnode header */
	    DBG(DBG_IOCTL, "ioctl_record_open: Starting new record %s\n", path);
	    fprintf(ioctl_record_log, "@DEV %s\n", device_path);
	}

	/* ensure that we write the file also on Control-C */
	act_int.sa_handler = ioctl_record_sigint_handler;
	assert(sigemptyset(&act_int.sa_mask) == 0);
	act_int.sa_flags = 0;
	assert(sigaction(SIGINT, &act_int, &orig_actint) == 0);

	DBG(DBG_IOCTL, "ioctl_record_open: starting ioctl recording of fd %i into %s\n", fd, path);
    } else {
	DBG(DBG_IOCTL, "ioctl_record_open: ioctl recording is already ongoing, continuing on new fd %i\n", fd);
    }
}
Пример #3
0
static void
ioctl_record_open(int fd)
{
    static dev_t record_rdev = (dev_t) - 1;

    if (fd < 0)
	return;

    /* lazily initialize record_rdev */
    if (record_rdev == (dev_t) - 1) {
	const char *dev = getenv("UMOCKDEV_IOCTL_RECORD_DEV");

	if (dev != NULL) {
	    record_rdev = (dev_t) atoi(dev);
	} else {
	    /* not recording */
	    record_rdev = 0;
	}
    }

    if (record_rdev == 0)
	return;

    /* check if the opened device is the one we want to record */
    if (dev_of_fd(fd) != record_rdev)
	return;

    /* recording is already in progress? */
    if (ioctl_record_fd >= 0) {
	/* libmtp opens the device multiple times, we can't do that */
	/*
       fprintf(stderr, "umockdev: recording for this device is already ongoing, stopping recording of previous open()\n");
       ioctl_record_close();
       */
       fprintf(stderr, "umockdev: WARNING: ioctl recording for this device is already ongoing on fd %i, but application opened it a second time on fd %i without closing\n", ioctl_record_fd, fd);
    }

    ioctl_record_fd = fd;

    /* lazily open the record file */
    if (ioctl_record_log == NULL) {
	const char *path = getenv("UMOCKDEV_IOCTL_RECORD_FILE");
	struct sigaction act_int;

	if (path == NULL) {
	    fprintf(stderr, "umockdev: $UMOCKDEV_IOCTL_RECORD_FILE not set\n");
	    exit(1);
	}
	if (getenv("UMOCKDEV_DIR") != NULL) {
	    fprintf(stderr, "umockdev: $UMOCKDEV_DIR cannot be used while recording\n");
	    exit(1);
	}
	ioctl_record_log = fopen(path, "a+");
	if (ioctl_record_log == NULL) {
	    perror("umockdev: failed to open ioctl record file");
	    exit(1);
	}

	/* load an already existing log */
	ioctl_record = ioctl_tree_read(ioctl_record_log);

	/* ensure that we write the file also on Control-C */
	act_int.sa_handler = ioctl_record_sigint_handler;
	assert(sigemptyset(&act_int.sa_mask) == 0);
	act_int.sa_flags = 0;
	assert(sigaction(SIGINT, &act_int, &orig_actint) == 0);

	DBG("ioctl_record_open: starting ioctl recording of fd %i into %s\n", fd, path);
    } else {
	DBG("ioctl_record_open: ioctl recording is already ongoing, continuing on new fd %i\n", fd);
    }
}