1 /*
2  *  Copyright (C) 1999-2004 Etymon Systems, Inc.
3  *
4  *  Authors:  Nassib Nassar
5  */
6 
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include "linbuf.h"
12 #include "util.h"
13 
14 #define LINBUFSEGSIZE ((size_t) 1000000000)
15 
16 static size_t bufsize;
17 static FILE *fbuf;
18 static unsigned char **linbuf;
19 static size_t *linbuflen;
20 static int linbufn;
21 
createbuf()22 static int createbuf()
23 {
24 	int x;
25 	size_t z;
26 
27 	linbufn = (bufsize / LINBUFSEGSIZE) + 1;
28 	linbuf = (unsigned char **) malloc(linbufn * sizeof (unsigned char *));
29 	if (!linbuf)
30 		return aferr(AFEMEM);
31 	linbuflen = (size_t *) malloc(linbufn * sizeof (size_t));
32 	if (!linbuflen)
33 		return aferr(AFEMEM);
34 	for (z = bufsize, x = 0; z > 0; z -= LINBUFSEGSIZE, x++) {
35 		linbuf[x] = (unsigned char *) malloc( linbuflen[x] = (
36 			z < LINBUFSEGSIZE ? z : LINBUFSEGSIZE) );
37 		if (!linbuf[x])
38 			return aferr(AFEMEM);
39 		if (z < LINBUFSEGSIZE)
40 			break;
41 	}
42 
43 	return 0;
44 }
45 
fillbuf()46 static int fillbuf()
47 {
48 	int x;
49 
50 	if (fseeko(fbuf, 0, SEEK_SET) < 0)
51                 return aferr(AFEDBIO);
52 	for (x = 0; x < linbufn; x++) {
53 		if (fread(linbuf[x], 1, linbuflen[x], fbuf) < linbuflen[x])
54 			return aferr(AFEDBIO);
55 	}
56 
57 	return 0;
58 }
59 
aflinbuf(FILE * f,int mem)60 int aflinbuf(FILE *f, int mem)
61 {
62 	off_t fsize;
63 
64 	afgetfsize(f, &fsize);
65 	bufsize = ((size_t) mem) * 1048576;
66 /*	printf("aflinbuf: %i %lu %lu\n", mem, (unsigned long) fsize,
67 	(unsigned long) bufsize);*/
68 	bufsize = fsize < bufsize ? fsize : bufsize;
69 	fbuf = f;
70 	if (createbuf() < 0)
71 		return -1;
72 	if (fillbuf() < 0)
73 		return -1;
74 
75 	return 0;
76 }
77 
bufcpy(unsigned char * ptr,off_t offset,size_t size)78 void bufcpy(unsigned char *ptr, off_t offset, size_t size)
79 {
80 	int x;
81 	int b, bx;
82 
83 	b = offset / LINBUFSEGSIZE;
84 	bx = offset % LINBUFSEGSIZE;
85 	for (x = 0; x < size; x++) {
86 		ptr[x] = linbuf[b][bx];
87 		if (++bx >= linbuflen[b]) {
88 			b++;
89 			bx = 0;
90 		}
91 	}
92 }
93 
aflinread(void * ptr,off_t offset,size_t size)94 int aflinread(void *ptr, off_t offset, size_t size)
95 {
96 	if ((offset + size) <= bufsize) {
97 /*		printf("."); fflush(stdout);*/
98 		bufcpy((unsigned char *)ptr, offset, size);
99 	} else {
100 /*		printf("\n%lu %lu %lu\n", (unsigned long) offset,
101 		(unsigned long) size,
102 		(unsigned long) bufsize);*/
103 /*		printf("*"); fflush(stdout);*/
104 		fseeko(fbuf, offset, SEEK_SET);
105 		if (fread(ptr, 1, size, fbuf) < size)
106 			return aferr(AFEDBIO);
107 	}
108 
109 	return 0;
110 }
111