lh3
12/29/2014 - 1:54 AM

Peek file content

Peek file content

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>

#define KO_BUFSIZE 0x40000

typedef struct {
	FILE *fp_in, *fp_out;
	int bufsize, is_closed;
	uint8_t *buf;
	uint64_t offset;
	pthread_t tid;
} kofile_t;

static void *worker(void *data)
{
	kofile_t *f = (kofile_t*)data;
	do {
		if (fwrite(f->buf, 1, f->bufsize, f->fp_out) != f->bufsize) break;
		f->offset += f->bufsize;
		f->bufsize = fread(f->buf, 1, KO_BUFSIZE, f->fp_in);
	} while (f->bufsize > 0);
	fclose(f->fp_in);
	fclose(f->fp_out);
	f->is_closed = 1;
	pthread_exit(0);
}

const uint8_t *ksf_peek(void *data, int *size, uint64_t *offset)
{
	kofile_t *f = (kofile_t*)data;
	*size = f->bufsize;
	*offset = f->offset;
	return f->buf;
}

void *ksf_open(const char *fn, int *_fd)
{
	int fd[2];
	kofile_t *fp;

	*_fd = -1;
	if (pipe(fd) < 0) return 0;
	if ((fp = (kofile_t*)calloc(1, sizeof(kofile_t))) == 0) return 0;
	if ((fp->fp_in = fn? fopen(fn, "rb") : stdin) == 0) {
		free(fp);
		return 0;
	}
	fp->fp_out = fdopen(fd[1], "wb");
	fp->buf = (uint8_t*)calloc(KO_BUFSIZE, 1);
	fp->bufsize = fread(fp->buf, 1, KO_BUFSIZE, fp->fp_in);
	pthread_create(&fp->tid, 0, worker, fp);
	*_fd = fd[0];
	return (void*)fp;
}

int ksf_close(void *data)
{
	kofile_t *f = (kofile_t*)data;
	if (f == 0) return -1;
	pthread_kill(f->tid, 13); // send SIGPIPE
	pthread_join(f->tid, 0);
	if (!f->is_closed) {
		fclose(f->fp_in);
		fclose(f->fp_out);
	}
	free(f->buf);
	return 0;
}

#ifdef MAIN_KSFILE
int main(int argc, char *argv[])
{
	void *fp;
	int fd, size;
	uint64_t offset;
	const uint8_t *buf;
	FILE *f;
	uint8_t b[0x10000];

	fp = ksf_open(argv[1], &fd);
	buf = ksf_peek(fp, &size, &offset);
	fprintf(stderr, "First two bytes: %.2X %.2X; size: %d; offset: %lu; fd: %d\n", buf[0], buf[1], size, (long)offset, fd);
	f = fdopen(fd, "rb");
	while (fread(b, 1, 0x10000, f) > 0);
	ksf_close(fp);
	return 0;
}
#endif