static void script_record_op(char op, int fd, const void *buf, ssize_t size) { struct script_record_info *srinfo; unsigned long delta; libc_func(fwrite, size_t, const void *, size_t, size_t, FILE *); static char header[100]; const unsigned char *cur; int i; if (!fd_map_get(&script_recorded_fds, fd, (const void **)&srinfo)) return; if (size <= 0) return; DBG("script_record_op %c: got %zi bytes on fd %i\n", op, size, fd); delta = update_msec(&srinfo->time); DBG(" %lu ms since last operation %c\n", delta, srinfo->op); /* for negligible time deltas, append to the previous stanza, otherwise * create a new record */ if (delta >= 10 || srinfo->op != op) { if (srinfo->op != 0) putc('\n', srinfo->log); snprintf(header, sizeof(header), "%c %lu ", op, delta); assert(_fwrite(header, strlen(header), 1, srinfo->log) == 1); } /* escape ASCII control chars */ for (i = 0, cur = buf; i < size; ++i, ++cur) { if (*cur < 32) { putc('^', srinfo->log); putc(*cur + 64, srinfo->log); continue; } if (*cur == '^') { /* we cannot encode ^ as ^^, as we need that for 0x1E already; so * take the next free code which is 0x60 */ putc('^', srinfo->log); putc('`', srinfo->log); continue; } putc(*cur, srinfo->log); } fflush(srinfo->log); srinfo->op = op; }
static void script_record_op(char op, int fd, const void *buf, ssize_t size) { struct script_record_info *srinfo; unsigned long delta; libc_func(fwrite, size_t, const void *, size_t, size_t, FILE *); static char header[100]; const unsigned char *cur; int i; if (!fd_map_get(&script_recorded_fds, fd, (const void **)&srinfo)) return; if (size <= 0) return; DBG(DBG_SCRIPT, "script_record_op %c: got %zi bytes on fd %i (format %i)\n", op, size, fd, srinfo->fmt); switch (srinfo->fmt) { case FMT_DEFAULT: delta = update_msec(&srinfo->time); DBG(DBG_SCRIPT, " %lu ms since last operation %c\n", delta, srinfo->op); /* for negligible time deltas, append to the previous stanza, otherwise * create a new record */ if (delta >= 10 || srinfo->op != op) { if (srinfo->op != 0) putc('\n', srinfo->log); snprintf(header, sizeof(header), "%c %lu ", op, delta); assert(_fwrite(header, strlen(header), 1, srinfo->log) == 1); } /* escape ASCII control chars */ for (i = 0, cur = buf; i < size; ++i, ++cur) { if (*cur < 32) { putc('^', srinfo->log); putc(*cur + 64, srinfo->log); continue; } if (*cur == '^') { /* we cannot encode ^ as ^^, as we need that for 0x1E already; so * take the next free code which is 0x60 */ putc('^', srinfo->log); putc('`', srinfo->log); continue; } putc(*cur, srinfo->log); } break; case FMT_EVEMU: if (op != 'r') { fprintf(stderr, "libumockdev-preload: evemu format only supports reads from the device\n"); abort(); } if (size % sizeof(struct input_event) != 0) { fprintf(stderr, "libumockdev-preload: evemu format only supports reading input_event structs\n"); abort(); } const struct input_event *e = buf; while (size > 0) { fprintf(srinfo->log, "E: %li.%06li %04"PRIX16" %04"PRIX16 " %"PRIi32"\n", (long) e->time.tv_sec, (long) e->time.tv_usec, e->type, e->code, e->value); size -= sizeof(struct input_event); e++; } break; default: fprintf(stderr, "libumockdev-preload script_record_op(): unsupported format %i\n", srinfo->fmt); abort(); } fflush(srinfo->log); srinfo->op = op; }