1 /*
2  *
3  * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
4  *
5  * This file has been copied from EMILE, http://emile.sf.net
6  *
7  */
8 
9 #include "libiso9660.h"
10 #include "libopenbios/bindings.h"
11 #include "libc/diskio.h"
12 
iso9660_read(iso9660_FILE * _file,char * buf,size_t count)13 size_t iso9660_read(iso9660_FILE *_file, char *buf, size_t count)
14 {
15 	iso9660_FILE *file = (iso9660_FILE*)_file;
16 	size_t read = 0;
17 
18 	if ( count > (file->size  - file->offset) )
19 		count = file->size  - file->offset;
20 
21 	while (count > 0)
22 	{
23 		size_t part;
24 		int offset_extent;
25 		int offset_index;
26 
27 		offset_extent = file->base +
28 				    (file->offset / ISOFS_BLOCK_SIZE);
29 		offset_index = file->offset % ISOFS_BLOCK_SIZE;
30 
31 		if (file->current != offset_extent)
32 		{
33 			if ( (offset_index == 0) &&
34 			     (count >= ISOFS_BLOCK_SIZE) )
35 			{
36 				/* direct i/o */
37 
38 				int extents_nb;
39 
40 				extents_nb = count / ISOFS_BLOCK_SIZE;
41 
42 				part = extents_nb * ISOFS_BLOCK_SIZE;
43 
44 				seek_io(file->volume->fd,
45 					offset_extent * ISOFS_BLOCK_SIZE);
46 				read_io(file->volume->fd, buf + read, part);
47 
48 				file->offset += part;
49 				count -= part;
50 				read += part;
51 
52 				continue;
53 			}
54 
55 			file->current = offset_extent;
56 			seek_io(file->volume->fd,
57 				offset_extent * ISOFS_BLOCK_SIZE);
58 			read_io(file->volume->fd, file->buffer,
59 				ISOFS_BLOCK_SIZE);
60 		}
61 
62 		part = ISOFS_BLOCK_SIZE - offset_index;
63 		if (count < part)
64 			part = count;
65 
66 		memcpy(buf + read, file->buffer + offset_index, part);
67 
68 		file->offset += part;
69 		count -= part;
70 		read += part;
71 	}
72 
73 	return read;
74 }
75