File: io.c

package info (click to toggle)
vstream-client 1.2-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 388 kB
  • ctags: 264
  • sloc: ansic: 3,883; sh: 92; makefile: 76; awk: 59
file content (130 lines) | stat: -rw-r--r-- 2,654 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
  media-filesystem library, io routines
  tridge@samba.org, January 2001
  released under the Gnu GPL v2
*/

#include "mfs.h"

static int readahead_enabled = 0;
static int vserver = -1;
static int need_bswap = 0;

void vstream_mfs_readahead(int set)
{
	readahead_enabled = set;
}

static void vserver_read_req(u32 sec, u32 count)
{
	struct vserver_cmd cmd;

	cmd.command = htonl(MFS_CMD_READ);
	cmd.param1 = htonl(sec);
	cmd.param2 = htonl(count);
	vstream_write_all(vserver, &cmd, sizeof(cmd));
}

static void vserver_receive(void *buf, u32 count)
{
	count <<= SECTOR_SHIFT;
	vstream_read_all(vserver, buf, count);
}

#define RA_BLOCKS	256
#define RA_MIN		256

void vserver_vstream_read_sectors(void *buf, u32 sec, u32 count)
{
	static struct mfs_run readahead;
	u32 discard, coming;

	if (count == 0)
		return;

	discard = coming = 0;
	if (sec >= readahead.start && sec < readahead.start + readahead.len) {
		discard = sec - readahead.start;
		coming = readahead.len - discard;
		if (coming <= count) {
			readahead.len = 0;
		} else {
			readahead.start = sec + count;
			readahead.len -= discard + count;
		}
	} else {
		discard = readahead.len;
		coming = 0;
		readahead.len = 0;
	}

	if (coming < count) {
		u32 nreq = count - coming;
		if (readahead_enabled && nreq < RA_BLOCKS) {
			readahead.start = sec + count;
			readahead.len = RA_BLOCKS - nreq;
			nreq = RA_BLOCKS;
		}
		vserver_read_req(sec + coming, nreq);
	}

	if (readahead.len <= RA_MIN && readahead_enabled) {
		if (readahead.len == 0)
			readahead.start = sec + count;
		vserver_read_req(readahead.start + readahead.len, RA_BLOCKS);
		readahead.len += RA_BLOCKS;
	}

	if (discard) {
		void *buf2 = malloc(discard << SECTOR_SHIFT);
		vserver_receive(buf2, discard);
		free(buf2);
	}

	vserver_receive(buf, count);

	if (need_bswap) {
		u16 *v = (u16 *)buf;
		int i;
		for (i=0;i<count<<(SECTOR_SHIFT-1);i++)
			v[i] = ntohs(v[i]);
	}
}

void vstream_io_need_bswap(int set)
{
	need_bswap = set;
}

/* read bytes from a sector, handling partial sectors */
void vstream_mfs_read_partial(void *buf, u32 sec, u32 size)
{
	char tmp[SECTOR_SIZE];
	if (size >= SECTOR_SIZE) {
		u32 n = size / SECTOR_SIZE;
		vserver_vstream_read_sectors(buf, sec, n);
		buf += n*SECTOR_SIZE;
		size -= n*SECTOR_SIZE;
		sec += n;
	}
	if (size == 0) return;
	vserver_vstream_read_sectors(tmp, sec, 1);
	memcpy(buf, tmp, size);
}

void vstream_set_socket_fd(int fd)
{
	vserver = fd;
}

int vstream_open_socket(char *addy)
{
	if (vserver < 0)
		vserver = vstream_vstream_open_socket_out(addy, VSERVER_PORT);
	if (vserver < 0) {
		vstream_error("Failed to connect to %s\n", addy);
		return 1;
	}
	return 0;
}