-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtestRio.c
172 lines (152 loc) · 4.54 KB
/
testRio.c
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
* Example of how to perform remote IO calls to the filesystem.
* The code intentionally does not abstract common patterns to be as
* linear as possible.
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <magenta/syscalls.h>
#include <magenta/syscalls/object.h>
#include <mxio/remoteio.h>
#include "private-remoteio.h" // copied from mxio library
/* steal a copy of mxio's root handle for ourselves */
mx_handle_t getRoot(void)
{
mxrio_t *r = (mxrio_t*)mxio_root_handle;
return r->h;
}
void
showHandle(mx_handle_t h)
{
mx_info_handle_basic_t info;
mx_status_t x;
x = mx_object_get_info(h, MX_INFO_HANDLE_BASIC, &info, sizeof info, 0, 0);
if(x != MX_OK) {
printf("%x: bad handle\n", h);
} else {
printf("%x type %d rights %x koid %lx\n", h, info.type, info.rights, info.koid);
}
}
void
dumpHex(const void *vp, size_t sz)
{
const unsigned char *p = (const unsigned char *)vp;
size_t i;
while(sz > 0) {
for(i = 0; i < 8 && i < sz; i++) {
printf("%02x ", p[i]);
}
printf("\n");
p += i;
sz -= i;
}
}
int main(int argc, char **argv)
{
const char *fn = "/dev/zero";
mx_status_t x;
mx_handle_t root, h1, h2;
if(argc > 1) fn = argv[1];
/*
* Each process has a handle to the root filesystem. Our libraries
* know about it. To make calls, we need to steal a copy.
*/
root = getRoot();
showHandle(root);
/* to open a file we need a new channel pair */
if(mx_channel_create(0, &h1, &h2) != MX_OK) {
printf("cant get channel\n");
return 1;
}
/*
* We build an OPEN call, passing in half of the channel pair.
* We keep the other half and use it to talk to the server.
* Note: the server on the far end of this channel may not necessarily
* be the same as our root filesystem server. The server can forward
* the pair along to other servers as needed.
*/
printf("path %s\n", fn);
mxrio_msg_t msg;
memset(&msg, 0, sizeof msg);
msg.txid = 0x01010101;
msg.op = MXRIO_OPEN;
msg.datalen = strlen(fn);
msg.arg = O_RDONLY;
msg.arg2.mode = 0666;
msg.hcount = 1;
strcpy((char*)msg.data, fn);
mx_handle_t handtab[4];
handtab[0] = h2;
/* send the message */
x = mx_channel_write(root, 0, &msg, MXRIO_HDR_SZ + msg.datalen, handtab, msg.hcount);
if(x != MX_OK) {
printf("write failed %d\n", x);
return 1;
}
printf("wrote\n");
/* wait for a response from h1 (not root!) */
x = mx_object_wait_one(h1, MX_CHANNEL_READABLE, MX_TIME_INFINITE, 0);
if(x != MX_OK) {
printf("wait failed %d\n", x);
return 1;
}
/*
* Read the response from h1. It will have a status code
* and info about the type of connection. We expect status == MX_OK
* and type == MXIO_PROTOCOL_REMOTE.
*/
uint32_t nb, nh;
mxrio_object_t obj;
x = mx_channel_read(h1, 0, &obj, handtab, sizeof obj,
sizeof handtab / sizeof handtab[0], &nb, &nh);
if(x != MX_OK) {
printf("read failed %d\n", x);
return 1;
}
if(nb < 8) {
printf("short read %d\n", nb);
return 1;
}
printf("status %d type %d\n", obj.status, obj.type);
if(obj.status != 0 || obj.type != 2) { // remote object
printf("not what I expected!\n");
return 1;
}
/* we have our open handle now, so lets do a read operation */
memset(&msg, 0, sizeof msg);
msg.txid = 0x02020202;
msg.op = MXRIO_READ_AT;
msg.arg = 8;
msg.arg2.off = 0;
x = mx_channel_write(h1, 0, &msg, MXRIO_HDR_SZ + msg.datalen, 0, 0);
if(x != MX_OK) {
printf("write2 failed %d\n", x);
return 1;
}
/*
* We have to wait for a response. We could have used
* mx_channel_call here to writ, wait and read all at once.
*/
x = mx_object_wait_one(h1, MX_CHANNEL_READABLE, MX_TIME_INFINITE, 0);
if(x != MX_OK) {
printf("wait2 failed %d\n", x);
return 1;
}
/* read the result (also a msg) */
x = mx_channel_read(h1, 0, &msg, handtab, sizeof msg,
sizeof handtab / sizeof handtab[0], &nb, &nh);
if(x != MX_OK) {
printf("read2 failed %d\n", x);
return 1;
}
if(nb < MXRIO_HDR_SZ) {
printf("short read2 %d\n", nb);
return 1;
}
/* We have our read response. Print out the contents. */
printf("data len %d\n", msg.datalen);
printf("data: ");
dumpHex(msg.data, msg.datalen);
return 0;
}