/*
 * Dump RNG output into a string.
 */
void RngDump(NaClSrpcRpc *rpc,
             NaClSrpcArg **in_args,
             NaClSrpcArg **out_args,
             NaClSrpcClosure *done) {
  struct StringBuffer sb;
  NaClSrpcError rpc_result;
  int status;
  int rng;

  StringBufferCtor(&sb);
  rpc_result = NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP,
                                         "SecureRandom", O_RDONLY,
                                         &status, &rng);
  assert(NACL_SRPC_RESULT_OK == rpc_result);
  printf("rpc status %d\n", status);
  assert(NACL_NAME_SERVICE_SUCCESS == status);
  printf("rng descriptor %d\n", rng);

  dump_output(&sb, rng, RNG_OUTPUT_BYTES);
  out_args[0]->arrays.str = strdup(sb.buffer);
  rpc->result = NACL_SRPC_RESULT_OK;
  done->Run(done);
  close(rng);
  StringBufferDtor(&sb);
}
int main(int argc, char** argv) {

  read_ascii_flight_log(IN_FILE);

  imu_init();
  ahrs_init();

  for (int i=0; i<nb_samples; i++) {
    feed_imu(i);
    if (ahrs.status == AHRS_UNINIT) {
      ahrs_aligner_run();
      if (ahrs_aligner.status == AHRS_ALIGNER_LOCKED)
        ahrs_align();
    }
    else {
      ahrs_propagate((1./AHRS_PROPAGATE_FREQUENCY));
#ifdef ENABLE_MAG_UPDATE
      if (MAG_AVAILABLE(samples[i].flag))
        ahrs_update_mag();
#endif
#ifdef ENABLE_ACCEL_UPDATE
      if (IMU_AVAILABLE(samples[i].flag) && (!MAG_AVAILABLE(samples[i].flag)))
        ahrs_update_accel();
#endif
    }
    store_filter_output(i);
  }

  dump_output(OUT_FILE);

}
int main(void) {
  int ns;
  NaClSrpcChannel channel;
  int connected_socket;
  int status;
  int rng;

  if (!NaClSrpcModuleInit()) {
    fprintf(stderr, "srpc module init failed\n");
    return 1;
  }
  printf("Hello world\n");
  ns = -1;
  nacl_nameservice(&ns);
  printf("ns = %d\n", ns);
  assert(-1 != ns);

  connected_socket = imc_connect(ns);
  assert(-1 != connected_socket);
  if (!NaClSrpcClientCtor(&channel, connected_socket)) {
    fprintf(stderr, "Srpc client channel ctor failed\n");
    return 1;
  }
  printf("NaClSrpcClientCtor succeeded\n");
  if (!EnumerateNames(&channel)) {
    fprintf(stderr, "Could not enumerate names\n");
    return 1;
  }
  printf("EnumerateNames succeeded\n");
  if (NACL_SRPC_RESULT_OK !=
      NaClSrpcInvokeBySignature(&channel, NACL_NAME_SERVICE_LOOKUP,
                                "SecureRandom", O_RDONLY, &status, &rng)) {
    fprintf(stderr, "nameservice lookup failed, status %d\n", status);
    return 1;
  }
  printf("rpc status %d\n", status);
  assert(NACL_NAME_SERVICE_SUCCESS == status);
  printf("rng descriptor %d\n", rng);

  dump_output(rng, RNG_OUTPUT_BYTES);

  return 0;
}
void FrameProfiler::processFrame() {

	std::lock_guard<std::mutex> vectorGuard(_eventsMutex);

	std::sort(_bufferedEvents.begin(), _bufferedEvents.end(), event_sorter);

	SCP_stringstream stream;

	SCP_vector<profile_sample> samples;

	bool start_found = false;
	bool end_found = false;
	uint64_t start_profile_time = 0;
	uint64_t end_profile_time = 0;

	for (auto& event : _bufferedEvents) {
		if (!start_found) {
			start_profile_time = event.timestamp;
			start_found = true;
		}
		if (!end_found) {
			end_profile_time = event.timestamp;
			end_found = true;
		}

		switch (event.type) {
			case EventType::Begin:
				process_begin(samples, event);
				break;
			case EventType::End:
				process_end(samples, event);
				break;
			default:
				break;
		}
	}
	_bufferedEvents.clear();

	dump_output(stream, start_profile_time, end_profile_time, samples);

	content = stream.str();
}
Exemple #5
0
int main() {
    const DrawOptions options = GetDrawOptions();
    if (options.source) {
        sk_sp<SkData> data(SkData::NewFromFileName(options.source));
        if (!data) {
            perror(options.source);
            return 1;
        } else {
            image = SkImage::MakeFromEncoded(std::move(data));
            if (!image) {
                perror("Unable to decode the source image.");
                return 1;
            }
            SkAssertResult(image->asLegacyBitmap(
                                   &source, SkImage::kRO_LegacyBitmapMode));
        }
    }
    sk_sp<SkData> rasterData, gpuData, pdfData, skpData;
    if (options.raster) {
        auto rasterSurface =
                SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(options.size));
        srand(0);
        draw(rasterSurface->getCanvas());
        rasterData.reset(encode_snapshot(rasterSurface));
    }
    if (options.gpu) {
        auto grContext = create_grcontext();
        if (!grContext) {
            fputs("Unable to get GrContext.\n", stderr);
        } else {
            auto surface = SkSurface::MakeRenderTarget(
                    grContext.get(),
                    SkBudgeted::kNo,
                    SkImageInfo::MakeN32Premul(options.size));
            if (!surface) {
                fputs("Unable to get render surface.\n", stderr);
                exit(1);
            }
            srand(0);
            draw(surface->getCanvas());
            gpuData.reset(encode_snapshot(surface));
        }
    }
    if (options.pdf) {
        SkDynamicMemoryWStream pdfStream;
        sk_sp<SkDocument> document(SkDocument::MakePDF(&pdfStream));
        srand(0);
        draw(document->beginPage(options.size.width(), options.size.height()));
        document->close();
        pdfData.reset(pdfStream.copyToData());
    }
    if (options.skp) {
        SkSize size;
        size = options.size;
        SkPictureRecorder recorder;
        srand(0);
        draw(recorder.beginRecording(size.width(), size.height()));
        auto picture = recorder.finishRecordingAsPicture();
        SkDynamicMemoryWStream skpStream;
        picture->serialize(&skpStream);
        skpData.reset(skpStream.copyToData());
    }

    printf("{\n");
    dump_output(rasterData, "Raster", !gpuData && !pdfData && !skpData);
    dump_output(gpuData, "Gpu", !pdfData && !skpData);
    dump_output(pdfData, "Pdf", !skpData);
    dump_output(skpData, "Skp");
    printf("}\n");

    return 0;
}
Exemple #6
0
void dump_program(struct state *state)
{
	int i, sect_size;
	uint8_t *ptr;

	state->hdr = next_sect(state, &sect_size);

	printf("######## HEADER: (size %d)\n", sect_size);
	printf("\tsize:           %d\n", state->hdr->size);
	printf("\trevision:       %d\n", state->hdr->revision);
	printf("\tattributes:     %d\n", state->hdr->num_attribs);
	printf("\tuniforms:       %d\n", state->hdr->num_uniforms);
	printf("\tsamplers:       %d\n", state->hdr->num_samplers);
	printf("\tvaryings:       %d\n", state->hdr->num_varyings);
	printf("\tuniform blocks: %d\n", state->hdr->num_uniformblocks);
	if (full_dump)
		dump_hex((void *)state->hdr, sect_size);
	printf("\n");

	/* there seems to be two 0xba5eba11's at the end of the header, possibly
	 * with some other stuff between them:
	 */
	ptr = next_sect(state, &sect_size);
	if (full_dump) {
		dump_hex_ascii(ptr, sect_size);
	}

	for (i = 0; (i < state->hdr->num_attribs) && (state->sz > 0); i++) {
		state->attribs[i] = next_sect(state, &sect_size);

		/* hmm, for a3xx (or maybe just newer driver version), we have some
		 * extra sections that don't seem useful, so skip these:
		 */
		while (!valid_type(state->attribs[i]->type_info)) {
			dump_hex_ascii(state->attribs[i], sect_size);
			state->attribs[i] = next_sect(state, &sect_size);
		}

		clean_ascii(state->attribs[i]->name, sect_size - 28);
		if (full_dump) {
			printf("######## ATTRIBUTE: (size %d)\n", sect_size);
			dump_attribute(state->attribs[i]);
			dump_hex((char *)state->attribs[i], sect_size);
		}
	}

	for (i = 0; (i < state->hdr->num_uniforms) && (state->sz > 0); i++) {
		state->uniforms[i] = next_sect(state, &sect_size);

		/* hmm, for a3xx (or maybe just newer driver version), we have some
		 * extra sections that don't seem useful, so skip these:
		 */
		while (!valid_type(state->uniforms[i]->type_info)) {
			dump_hex_ascii(state->uniforms[i], sect_size);
			state->uniforms[i] = next_sect(state, &sect_size);
		}

		if (is_uniform_v2(state->uniforms[i])) {
			clean_ascii(state->uniforms[i]->v2.name, sect_size - 53);
		} else {
			clean_ascii(state->uniforms[i]->v1.name, sect_size - 41);
		}

		if (full_dump) {
			printf("######## UNIFORM: (size %d)\n", sect_size);
			dump_uniform(state->uniforms[i]);
			dump_hex((char *)state->uniforms[i], sect_size);
		}
	}

	for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
		state->samplers[i] = next_sect(state, &sect_size);

		/* hmm, for a3xx (or maybe just newer driver version), we have some
		 * extra sections that don't seem useful, so skip these:
		 */
		while (!valid_type(state->samplers[i]->type_info)) {
			dump_hex_ascii(state->samplers[i], sect_size);
			state->samplers[i] = next_sect(state, &sect_size);
		}

		clean_ascii(state->samplers[i]->name, sect_size - 33);
		if (full_dump) {
			printf("######## SAMPLER: (size %d)\n", sect_size);
			dump_sampler(state->samplers[i]);
			dump_hex((char *)state->samplers[i], sect_size);
		}

	}

	// These sections show up after all of the other sampler sections
	// Loops through them all since we don't deal with them
	if (state->hdr->revision >= 7) {
		for (i = 0; (i < state->hdr->num_samplers) && (state->sz > 0); i++) {
			ptr = next_sect(state, &sect_size);
			dump_hex_ascii(ptr, sect_size);
		}
	}


	for (i = 0; (i < state->hdr->num_varyings) && (state->sz > 0); i++) {
		state->varyings[i] = next_sect(state, &sect_size);

		/* hmm, for a3xx (or maybe just newer driver version), we have some
		 * extra sections that don't seem useful, so skip these:
		 */
		while (!valid_type(state->varyings[i]->type_info)) {
			dump_hex_ascii(state->varyings[i], sect_size);
			state->varyings[i] = next_sect(state, &sect_size);
		}

		clean_ascii(state->varyings[i]->name, sect_size - 16);
		if (full_dump) {
			printf("######## VARYING: (size %d)\n", sect_size);
			dump_varying(state->varyings[i]);
			dump_hex((char *)state->varyings[i], sect_size);
		}
	}

	/* not sure exactly which revision started this, but seems at least
	 * rev7 and rev8 implicitly include a new section for gl_FragColor:
	 */
	if (state->hdr->revision >= 7) {
		/* I guess only one? */
		state->outputs[0] = next_sect(state, &sect_size);

		clean_ascii(state->outputs[0]->name, sect_size - 32);
		if (full_dump) {
			printf("######## OUTPUT: (size %d)\n", sect_size);
			dump_output(state->outputs[0]);
			dump_hex((char *)state->outputs[0], sect_size);
		}
	}

	for (i = 0; (i < state->hdr->num_uniformblocks) && (state->sz > 0); i++) {
		state->uniformblocks[i].header = next_sect(state, &sect_size);

		clean_ascii(state->uniformblocks[i].header->name, sect_size - 40);
		if (full_dump) {
			printf("######## UNIFORM BLOCK: (size %d)\n", sect_size);
			dump_uniformblock(state->uniformblocks[i].header);
			dump_hex((char *)state->uniformblocks[i].header, sect_size);
		}

		/*
		 * OpenGL ES 3.0 spec mandates a minimum amount of 16K members supported
		 * a330 supports a minimum of 65K
		 */
		state->uniformblocks[i].members = malloc(state->uniformblocks[i].header->num_members * sizeof(void*));

		int member = 0;
		for (member = 0; (member < state->uniformblocks[i].header->num_members) && (state->sz > 0); member++) {
			state->uniformblocks[i].members[member] = next_sect(state, &sect_size);

			clean_ascii(state->uniformblocks[i].members[member]->name, sect_size - 56);
			if (full_dump) {
				printf("######## UNIFORM BLOCK MEMBER: (size %d)\n", sect_size);
				dump_uniformblockmember(state->uniformblocks[i].members[member]);
				dump_hex((char *)state->uniformblocks[i].members[member], sect_size);
			}
		}
		/*
		 * Qualcomm saves the UBO members twice for each UBO
		 * Don't ask me why
		 */
		for (member = 0; (member < state->uniformblocks[i].header->num_members) && (state->sz > 0); member++) {
			state->uniformblocks[i].members[member] = next_sect(state, &sect_size);

			clean_ascii(state->uniformblocks[i].members[member]->name, sect_size - 56);
			if (full_dump) {
				printf("######## UNIFORM BLOCK MEMBER2: (size %d)\n", sect_size);
				dump_uniformblockmember(state->uniformblocks[i].members[member]);
				dump_hex((char *)state->uniformblocks[i].members[member], sect_size);
			}
		}
	}

	if (gpu_id >= 300) {
		dump_shaders_a3xx(state);
	} else {
		dump_shaders_a2xx(state);
	}

	if (!full_dump)
		return;

	/* dump ascii version of shader program: */
	ptr = next_sect(state, &sect_size);
	printf("\n#######################################################\n");
	printf("######## SHADER SRC: (size=%d)\n", sect_size);
	dump_ascii(ptr, sect_size);
	free(ptr);

	/* dump remaining sections (there shouldn't be any): */
	while (state->sz > 0) {
		ptr = next_sect(state, &sect_size);
		printf("######## section (size=%d)\n", sect_size);
		printf("as hex:\n");
		dump_hex(ptr, sect_size);
		printf("as float:\n");
		dump_float(ptr, sect_size);
		printf("as ascii:\n");
		dump_ascii(ptr, sect_size);
		free(ptr);
	}
	/* cleanup the uniform buffer members we allocated */
	if (state->hdr->num_uniformblocks > 0)
		free (state->uniformblocks[i].members);
}
Exemple #7
0
/***************************************************************************
 * Function Name: spu_perform_test
 * Description  : Tests for the hardware to do encrypt
 *                or decrypt operation 
 * Returns      : N/A
 ***************************************************************************/
void spu_perform_test(uint32 tx_pkt_id, uint32 num_pkts)
{
    int ntries = 0;
#ifdef DISABLE_ENGINES
    unsigned long aes_enable;
#endif
    uint16 rx_index;
    int done = 1;

    printk (KERN_ERR "IPSEC SPU: do_encrypt\n");

#if AES_MD5
    printk (KERN_ERR "IPSEC SPU: AES MD5 TEST\n");
#endif

#if AES_SHA1
    printk (KERN_ERR "IPSEC SPU: AES SHA1 TEST\n");
#endif

#if DES_MD5
    printk (KERN_ERR "IPSEC SPU: DES MD5 TEST\n");
#endif

#if DES_SHA1
    printk (KERN_ERR "IPSEC SPU: DES SHA1 TEST\n");
#endif

#if DES3_MD5
    printk (KERN_ERR "IPSEC SPU: DES3 MD5 TEST\n");
#endif

#if DES3_SHA1
    printk (KERN_ERR "IPSEC SPU: DES3 SHA1 TEST\n");
#endif

    if (tx_pkt_id > MAX_PKT_ID || num_pkts > MAX_PKTS_PER_TEST)
    {
	return;
    }

#ifdef DISABLE_ENGINES
    printk (KERN_ERR "IPSEC SPU: Disabling AES, DES, HASH engines 0x%08x\n",
	  SPU_CTRL);
    aes_enable = SPU_CTRL;
    /* Disable AES, DES/3DES and HASH */
    //aes_enable = (1 << 8) | (1 << 9) | (1 << 10);
    /* Disable DES/3DES and HASH */
    aes_enable = (1 << 9) | (1 << 10);
    SPU_CTRL = aes_enable;
    printk (KERN_ERR "IPSEC SPU: AES, DES, HASH Disabled 0x%08x\n", SPU_CTRL);
#endif

    num_tests_failed = num_tests_passed = 0;

    do
    {
	/*
	 * Setup the rx and tx buffer.
	 */
	rx_index = ipsec_setup_tx_rx (tx_pkt_id, &done);

	/*
	 * Enable the DMA.
	 */

//retry:
	pdev_ctrl->rx_dma->cfg |= DMA_ENABLE;
	pdev_ctrl->tx_dma->cfg |= DMA_ENABLE;
	BcmHalInterruptEnable (pdev_ctrl->rx_irq);

#ifdef SPU_DEBUG
	printk (KERN_ERR
	      "IPSEC SPU: Done Enabling Tx %p %lx and Rx %p %lx DMA\n",
	      &(pdev_ctrl->tx_dma->cfg), pdev_ctrl->tx_dma->cfg,
	      &(pdev_ctrl->rx_dma->cfg), pdev_ctrl->rx_dma->cfg);

	printk (KERN_ERR "IPSEC SPU: Tx Chn BaseDesc %lx st data %lx "
	      "len status %lx bufptr %lx\n",
	      pdev_ctrl->dma_ctrl->stram.s[1].baseDescPtr,
	      pdev_ctrl->dma_ctrl->stram.s[1].state_data,
	      pdev_ctrl->dma_ctrl->stram.s[1].desc_len_status,
	      pdev_ctrl->dma_ctrl->stram.s[1].desc_base_bufptr);
	printk (KERN_ERR "IPSEC SPU: Rx Chn BaseDesc %lx st data %lx "
	      "len status %lx bufptr %lx\n",
	      pdev_ctrl->dma_ctrl->stram.s[0].baseDescPtr,
	      pdev_ctrl->dma_ctrl->stram.s[0].state_data,
	      pdev_ctrl->dma_ctrl->stram.s[0].desc_len_status,
	      pdev_ctrl->dma_ctrl->stram.s[0].desc_base_bufptr);
	printk (KERN_ERR "IPSEC SPU: DMA CTRL Global Interrupt Status %lx "
	      "Mask %lx\n",
	      pdev_ctrl->dma_ctrl->ctrl_global_interrupt_status,
	      pdev_ctrl->dma_ctrl->ctrl_global_interrupt_mask);
#endif

	start = spu_get_cycle_count();

	/*
	 * Unblocked so check the Rx with the template and
	 * print the verdict. But first compute the elapsed
	 * time in usecs.
	 */
	if (end < start)
	{
	    proc_time = (0xFFFFFFFF - start) + end;
	}
	else
	{
	    proc_time = end - start;
	}

	proc_time = proc_time / spu_cycle_per_us;
	encrypt_decrypt_verify(tx_pkt_id, rx_index);
	dump_output (rx_index);
	start = end = proc_time = 0;
	xmit_pkt_len = recv_pkt_len = 0;
	ntries = 0;
	num_pkts--;
	tx_pkt_id++;

    } while (done && num_pkts);

    printk("Num Tests %d Failed %d Passed %d\n", (num_tests_passed + num_tests_failed), num_tests_failed, num_tests_passed);
}
Exemple #8
0
/*!
  \brief read_data() reads in the data from the ECU, checks to make sure
  enough arrived, copies it to thedestination buffer and returns;
  \param total_wanted if set to -1, input is variable and we don't error out.
  otherwise error out if count doesn't match what is asked for
  \param buffer is the pointer to buffer to stick the data.
  \param reset_on_fail is a hacky flag that should be removed, (win32ism)
  \returns TRUE on success, FALSE on failure 
  */
G_MODULE_EXPORT gint read_data(gint total_wanted, guint8 **buffer, gboolean reset_on_fail)
{
	static GMutex *serio_mutex = NULL;
	static GMutex mutex;
	static gint failcount = 0;
	static gboolean reset = FALSE;
	gboolean res = 0;
	gint total_read = 0;
	gint zerocount = 0;
	gint len = 0;
	gboolean bad_read = FALSE;
	guchar buf[4096];
	guchar *ptr = buf;
	gboolean ignore_errors = FALSE;
	Serial_Params *serial_params = NULL;;
	serial_params = (Serial_Params *)DATA_GET(global_data,"serial_params");

	ENTER();

	if (!serio_mutex)
		serio_mutex = (GMutex *)DATA_GET(global_data,"serio_mutex");

	g_mutex_lock(&mutex);

	total_read = 0;
	zerocount = 0;
	if (total_wanted == -1)
	{
		ignore_errors = TRUE;
		total_wanted = 1024;
	}
	/* Werid windows issue.  Occasional "short" reads,  but nothing else
	 * comes in for some reason. So if that happens, double what's read
	 * next time and throw it away to get things back in sync. 
	 * Ugly hack,  but couldn't find out why it did it.  might be due to
	 * excess latency in my test VM
	 */
#ifdef __WIN32__
	if (reset)
		total_wanted *= 2;
#endif

	g_mutex_lock(serio_mutex);
	while ((total_read < total_wanted ) && ((total_wanted-total_read) > 0))
	{
		MTXDBG(IO_PROCESS,_("Requesting %i bytes\n"),total_wanted-total_read);

		res = read_wrapper(serial_params->fd,
				ptr+total_read,
				total_wanted-total_read,&len);
		total_read += len;

		/* Increment bad read counter.... */
		if (!res) /* I/O Error Device disappearance or other */
		{
			MTXDBG((Dbg_Class)(IO_PROCESS|CRITICAL),_("I/O ERROR: \"%s\"\n"),(gchar *)g_strerror(errno));
			bad_read = TRUE;
			DATA_SET(global_data,"connected",GINT_TO_POINTER(FALSE));
			break;
		}
		if (len == 0) /* Short read!*/
			zerocount++;
		if ((len == 0) && (zerocount > 3))  /* Too many Short reads! */
		{
			bad_read = TRUE;
			break;
		}

		MTXDBG(IO_PROCESS,_("Read %i bytes, running total %i\n"),len,total_read);
	}
	g_mutex_unlock(serio_mutex);
	if ((bad_read) && (!ignore_errors))
	{
		MTXDBG((Dbg_Class)(IO_PROCESS|CRITICAL),_("Error reading from ECU\n"));

		serial_params->errcount++;
		if ((reset_on_fail) && (!reset))
			reset = TRUE;
		else
			reset = FALSE;
		failcount++;
		/* Excessive failures triggers port recheck */
		if (failcount > 10)
			DATA_SET(global_data,"connected",GINT_TO_POINTER(FALSE));
	}
	else
	{
		failcount = 0;
		reset = FALSE;
	}

	if (buffer)
		*buffer = g_memdup(buf,total_read);
	dump_output(total_read,buf);
	g_mutex_unlock(&mutex);
	EXIT();
	return total_read;
}
Exemple #9
0
int
main(int ac, char **av)
{
    const char *input_prefix = NULL;
    char *output_transid_file = NULL;
    char *mirror_transid_file = NULL;
    const char *mirror_directory = ".";
    char *record_prefix = NULL;
    char *record_transid_file = NULL;
    struct jsession jsdebug;
    struct jsession jsoutput;
    struct jsession jsmirror;
    char *ptr;
    int64_t mirror_transid;
    int64_t output_transid;
    int64_t record_transid;
    int64_t transid;
    int input_fd;
    struct stat st;
    struct jfile *jf;
    struct jdata *jd;
    int ch;

    while ((ch = getopt(ac, av, "2c:dfm:o:s:uvw:D:O:W:F")) != -1) {
	switch(ch) {
	case '2':
	    jmodes |= JMODEF_INPUT_FULL;
	    break;
	case 'c':
	    trans_count = strtoll(optarg, &ptr, 0);
	    switch(*ptr) {
	    case 't':
		trans_count *= 1024;
		/* fall through */
	    case 'g':
		trans_count *= 1024;
		/* fall through */
	    case 'm':
		trans_count *= 1024;
		/* fall through */
	    case 'k':
		trans_count *= 1024;
		break;
	    case 0:
		break;
	    default:
		fprintf(stderr, "Bad suffix for value specified with -c, use 'k', 'm', 'g', 't', or nothing\n");
		usage(av[0]);
	    }
	    break;
	case 'd':
	    jmodes |= JMODEF_DEBUG;
	    break;
	case 'f':
	    jmodes |= JMODEF_LOOP_FOREVER;
	    break;
	case 'v':
	    ++verbose_opt;
	    break;
	case 'm':
	    jmodes |= JMODEF_MIRROR;
	    if (strcmp(optarg, "none") != 0)
		mirror_transid_file = optarg;
	    break;
	case 'O':
	    jmodes |= JMODEF_OUTPUT_FULL;
	    /* fall through */
	case 'o':
	    jmodes |= JMODEF_OUTPUT;
	    if (strcmp(optarg, "none") != 0)
		output_transid_file = optarg;
	    break;
	case 's':
	    prefix_file_size = strtoll(optarg, &ptr, 0);
	    switch(*ptr) {
	    case 't':
		prefix_file_size *= 1024;
		/* fall through */
	    case 'g':
		prefix_file_size *= 1024;
		/* fall through */
	    case 'm':
		prefix_file_size *= 1024;
		/* fall through */
	    case 'k':
		prefix_file_size *= 1024;
		break;
	    case 0:
		break;
	    default:
		fprintf(stderr, "Bad suffix for value specified with -s, use 'k', 'm', 'g', 't', or nothing\n");
		usage(av[0]);
	    }
	    break;
	case 'u':
	    jdirection = JD_BACKWARDS;
	    break;
	case 'W':
	    jmodes |= JMODEF_RECORD_TMP;
	    /* fall through */
	case 'w':
	    jmodes |= JMODEF_RECORD;
	    record_prefix = optarg;
	    asprintf(&record_transid_file, "%s.transid", record_prefix);
	    break;
	case 'D':
	    mirror_directory = optarg;
	    break;
	case 'F':
	    ++fsync_opt;
	    break;
	default:
	    fprintf(stderr, "unknown option: -%c\n", optopt);
	    usage(av[0]);
	}
    }

    /*
     * Sanity checks
     */
    if ((jmodes & JMODEF_COMMAND_MASK) == 0)
	usage(av[0]);
    if (optind > ac + 1)  {
	fprintf(stderr, "Only one input file or prefix may be specified,\n"
			"or zero if stdin is to be the input.\n");
	usage(av[0]);
    }
    if (strcmp(mirror_directory, ".") != 0) {
	struct stat sb;
	if (stat(mirror_directory, &sb) != 0) {
	    perror ("Could not stat mirror directory");
	    usage(av[0]);
	}
	if (!S_ISDIR(sb.st_mode))
	{
	    fprintf (stderr, "Mirror directory '%s' is not a directory\n", mirror_directory);
	    usage(av[0]);
	}
    }
    if (jdirection == JD_BACKWARDS && (jmodes & (JMODEF_RECORD|JMODEF_OUTPUT))) {
	fprintf(stderr, "Undo mode is only good in mirroring mode and "
			"cannot be mixed with other modes.\n");
	exit(1);
    }

    /*
     * STEP1 - OPEN INPUT
     *
     * The input will either be a pipe, a regular file, or a journaling 
     * file prefix.
     */
    jf = NULL;
    if (optind == ac) {
	input_prefix = "<stdin>";
	input_fd = 0;
	if (fstat(0, &st) < 0 || !S_ISREG(st.st_mode)) {
	    jmodes |= JMODEF_INPUT_PIPE;
	    if (jdirection == JD_BACKWARDS) {
		fprintf(stderr, "Cannot scan journals on pipes backwards\n");
		usage(av[0]);
	    }
	}
	jf = jopen_fd(input_fd);
    } else if (stat(av[optind], &st) == 0 && S_ISREG(st.st_mode)) {
	input_prefix = av[optind];
	if ((input_fd = open(av[optind], O_RDONLY)) != 0) {
	    jf = jopen_fd(input_fd);
	} else {
	    jf = NULL;
	}
    } else {
	input_prefix = av[optind];
	jf = jopen_prefix(input_prefix, 0);
	jmodes |= JMODEF_INPUT_PREFIX;
    }
    if (jf == NULL) {
	fprintf(stderr, "Unable to open input %s: %s\n", 
		input_prefix, strerror(errno));
	exit(1);
    }

    /*
     * STEP 1 - SYNCHRONIZING THE INPUT STREAM
     *
     * Figure out the starting point for our various output modes.  Figure
     * out the earliest transaction id and try to seek to that point,
     * otherwise we might have to scan through terrabytes of data.
     *
     * Invalid transid's will be set to 0, but it should also be noted
     * that 0 is also a valid transid.
     */
    get_transid_from_file(output_transid_file, &output_transid,
			  JMODEF_OUTPUT_TRANSID_GOOD);
    get_transid_from_file(mirror_transid_file, &mirror_transid, 
			  JMODEF_MIRROR_TRANSID_GOOD);
    get_transid_from_file(record_transid_file, &record_transid, 
			  JMODEF_RECORD_TRANSID_GOOD);
    transid = LLONG_MAX;
    if ((jmodes & JMODEF_OUTPUT_TRANSID_GOOD) && output_transid < transid)
	transid = output_transid;
    if ((jmodes & JMODEF_MIRROR_TRANSID_GOOD) && mirror_transid < transid)
	transid = mirror_transid;
    if ((jmodes & JMODEF_RECORD_TRANSID_GOOD) && record_transid < transid)
	transid = record_transid;
    if ((jmodes & JMODEF_TRANSID_GOOD_MASK) == 0)
	transid = 0;
    if (verbose_opt) {
	if (jmodes & JMODEF_OUTPUT) {
	    fprintf(stderr, "Starting transid for OUTPUT: %016jx\n",
		    (uintmax_t)output_transid);
	}
	if (jmodes & JMODEF_MIRROR) {
	    fprintf(stderr, "Starting transid for MIRROR: %016jx\n",
		    (uintmax_t)mirror_transid);
	}
	if (jmodes & JMODEF_RECORD) {
	    fprintf(stderr, "Starting transid for RECORD: %016jx\n",
		    (uintmax_t)record_transid);
	}
    }

    if (strcmp(mirror_directory, ".") != 0) {
	if (chdir (mirror_directory) != 0) {
	    perror ("Could not enter mirror directory");
	    exit (1);
	}
    }

    /*
     * Now it gets more difficult.  If we are recording then the input
     * could be representative of continuing data and not have any
     * prior, older data that the output or mirror modes might need.  Those
     * modes must work off the recording data even as we write to it.
     * In that case we fork and have the sub-processes work off the
     * record output.
     *
     * Then we take the input and start recording.
     */
    if (jmodes & JMODEF_RECORD) {
	if (jrecord_init(record_prefix) < 0) {
	    fprintf(stderr, "Unable to initialize file set for: %s\n", 
		    record_prefix);
	    exit(1);
	}
	if (jmodes & JMODEF_MIRROR) {
	    fork_subprocess(jf, jscan_do_mirror, record_prefix, 
			    mirror_transid_file,
			    mirror_directory, mirror_transid);
	    /* XXX ack stream for temporary record file removal */
	}
	if (jmodes & JMODEF_OUTPUT) {
	    fork_subprocess(jf, jscan_do_output, record_prefix,
			    record_transid_file,
			    NULL, output_transid);
	    /* XXX ack stream for temporary record file removal */
	}
	jscan_do_record(jf, record_transid_file, record_prefix, record_transid);
	exit(0);
    }

    /*
     * If the input is a prefix set we can just pass it to the appropriate
     * jscan_do_*() function.  If we are doing both output and mirroring
     * we fork the mirror and do the output in the foreground since that
     * is going to stdout.
     */
    if (jmodes & JMODEF_INPUT_PREFIX) {
	if ((jmodes & JMODEF_OUTPUT) && (jmodes & JMODEF_MIRROR)) {
	    fork_subprocess(jf, jscan_do_mirror, input_prefix, 
			    mirror_transid_file,
			    mirror_directory, mirror_transid);
	    jscan_do_output(jf, output_transid_file, NULL, output_transid);
	} else if (jmodes & JMODEF_OUTPUT) {
	    jscan_do_output(jf, output_transid_file, NULL, output_transid);
	} else if (jmodes & JMODEF_MIRROR) {
	    jscan_do_mirror(jf, mirror_transid_file, mirror_directory,
			    mirror_transid);
	} else if (jmodes & JMODEF_DEBUG) {
	    jscan_do_debug(jf, NULL, NULL, 0);
	}
	exit(0);
    }

    /*
     * The input is not a prefix set and we are not recording, which means
     * we have to transfer the data on the input pipe to the output and
     * mirroring code on the fly.  This also means that we must keep track
     * of meta-data records in-memory.  However, if the input is a regular
     * file we *CAN* try to optimize where we start reading.
     *
     * NOTE: If the mirroring code encounters a transaction record that is
     * not marked begin, and it does not have the begin record, it will
     * attempt to locate the begin record if the input is not a pipe, then
     * seek back.
     */
    if ((jmodes & JMODEF_TRANSID_GOOD_MASK) && !(jmodes & JMODEF_INPUT_PIPE))
	jd = jseek(jf, transid, jdirection);
    else
	jd = jread(jf, NULL, jdirection);
    jmodes |= JMODEF_MEMORY_TRACKING;

    jsession_init(&jsdebug, jf, jdirection,
		  NULL, 0);
    jsession_init(&jsoutput, jf, jdirection, 
		  output_transid_file, output_transid);
    jsession_init(&jsmirror, jf, jdirection,
		  mirror_transid_file, mirror_transid);
    jsmirror.ss_mirror_directory = mirror_directory;

    while (jd != NULL) {
	if ((jmodes & JMODEF_DEBUG) && jsession_check(&jsdebug, jd))
	    dump_debug(&jsdebug, jd);
	if ((jmodes & JMODEF_OUTPUT) && jsession_check(&jsoutput, jd))
	    dump_output(&jsoutput, jd);
	if ((jmodes & JMODEF_MIRROR) && jsession_check(&jsmirror, jd))
	    dump_mirror(&jsmirror, jd);
	if (donecheck(jdirection, jd, transid)) {
	    jfree(jf, jd);
	    break;
	}
	jd = jread(jf, jd, jdirection);
    }
    jclose(jf);
    jsession_term(&jsdebug);
    jsession_term(&jsoutput);
    jsession_term(&jsmirror);
    return(0);
}