source: trunk/minix/commands/i386/mtools-3.9.7/floppyd_io.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 9.9 KB
Line 
1/*
2 * IO to the floppyd daemon running on the local X-Server Host
3 *
4 * written by:
5 *
6 * Peter Schlaile
7 *
8 * udbz@rz.uni-karlsruhe.de
9 *
10 */
11
12#include "sysincludes.h"
13#include "stream.h"
14#include "mtools.h"
15#include "msdos.h"
16#include "scsi.h"
17#include "partition.h"
18#include "floppyd_io.h"
19
20#ifdef USE_FLOPPYD
21
22/* ######################################################################## */
23
24
25typedef unsigned char Byte;
26typedef unsigned long Dword;
27
28char* AuthErrors[] = {
29 "Auth success!",
30 "Auth failed: Packet oversized!",
31 "Auth failed: X-Cookie doesn't match!",
32 "Auth failed: Wrong transmission protocol version!",
33 "Auth failed: Device locked!"
34};
35
36
37typedef struct RemoteFile_t {
38 Class_t *Class;
39 int refs;
40 Stream_t *Next;
41 Stream_t *Buffer;
42 int fd;
43 mt_off_t offset;
44 mt_off_t lastwhere;
45 mt_off_t size;
46} RemoteFile_t;
47
48
49#ifndef HAVE_HTONS
50unsigned short myhtons(unsigned short parm)
51{
52 Byte val[2];
53
54 val[0] = (parm >> 8) & 0xff;
55 val[1] = parm & 0xff;
56
57 return *((unsigned short*) (val));
58}
59#endif
60
61Dword byte2dword(Byte* val)
62{
63 Dword l;
64 l = (val[0] << 24) + (val[1] << 16) + (val[2] << 8) + val[3];
65
66 return l;
67}
68
69void dword2byte(Dword parm, Byte* rval)
70{
71 rval[0] = (parm >> 24) & 0xff;
72 rval[1] = (parm >> 16) & 0xff;
73 rval[2] = (parm >> 8) & 0xff;
74 rval[3] = parm & 0xff;
75}
76
77Dword read_dword(int handle)
78{
79 Byte val[4];
80
81 read(handle, val, 4);
82
83 return byte2dword(val);
84}
85
86void write_dword(int handle, Dword parm)
87{
88 Byte val[4];
89
90 dword2byte(parm, val);
91
92 write(handle, val, 4);
93}
94
95
96/* ######################################################################## */
97
98int authenticate_to_floppyd(int sock, char *display)
99{
100 off_t filelen;
101 Byte buf[16];
102 char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
103 char *xcookie;
104 Dword errcode;
105
106 command[4] = display;
107
108 filelen=strlen(display);
109 filelen += 100;
110
111 xcookie = (char *) safe_malloc(filelen+4);
112 filelen = safePopenOut(command, xcookie+4, filelen);
113 if(filelen < 1)
114 return AUTH_AUTHFAILED;
115
116 dword2byte(4,buf);
117 dword2byte(FLOPPYD_PROTOCOL_VERSION,buf+4);
118 write(sock, buf, 8);
119
120 if (read_dword(sock) != 4) {
121 return AUTH_WRONGVERSION;
122 }
123
124 errcode = read_dword(sock);
125
126 if (errcode != AUTH_SUCCESS) {
127 return errcode;
128 }
129
130 dword2byte(filelen, xcookie);
131 write(sock, xcookie, filelen+4);
132
133 if (read_dword(sock) != 4) {
134 return AUTH_PACKETOVERSIZE;
135 }
136
137 errcode = read_dword(sock);
138
139 return errcode;
140}
141
142
143static int floppyd_reader(int fd, char* buffer, int len)
144{
145 Dword errcode;
146 Dword gotlen;
147 int l;
148 int start;
149 Byte buf[16];
150
151 dword2byte(1, buf);
152 buf[4] = OP_READ;
153 dword2byte(4, buf+5);
154 dword2byte(len, buf+9);
155 write(fd, buf, 13);
156
157 if (read_dword(fd) != 8) {
158 errno = EIO;
159 return -1;
160 }
161
162 gotlen = read_dword(fd);
163 errcode = read_dword(fd);
164
165 if (gotlen != -1) {
166 if (read_dword(fd) != gotlen) {
167 errno = EIO;
168 return -1;
169 }
170 for (start = 0, l = 0; start < gotlen; start += l) {
171 l = read(fd, buffer+start, gotlen-start);
172 if (l == 0) {
173 errno = EIO;
174 return -1;
175 }
176 }
177 } else {
178 errno = errcode;
179 }
180 return gotlen;
181}
182
183static int floppyd_writer(int fd, char* buffer, int len)
184{
185 Dword errcode;
186 Dword gotlen;
187 Byte buf[16];
188
189 dword2byte(1, buf);
190 buf[4] = OP_WRITE;
191 dword2byte(len, buf+5);
192
193 write(fd, buf, 9);
194 write(fd, buffer, len);
195
196 if (read_dword(fd) != 8) {
197 errno = EIO;
198 return -1;
199 }
200
201 gotlen = read_dword(fd);
202 errcode = read_dword(fd);
203
204 errno = errcode;
205
206 return gotlen;
207}
208
209static int floppyd_lseek(int fd, mt_off_t offset, int whence)
210{
211 Dword errcode;
212 Dword gotlen;
213 Byte buf[32];
214
215 dword2byte(1, buf);
216 buf[4] = OP_SEEK;
217
218 dword2byte(8, buf+5);
219 dword2byte(truncBytes32(offset), buf+9);
220 dword2byte(whence, buf+13);
221
222 write(fd, buf, 17);
223
224 if (read_dword(fd) != 8) {
225 errno = EIO;
226 return -1;
227 }
228
229 gotlen = read_dword(fd);
230 errcode = read_dword(fd);
231
232 errno = errcode;
233
234 return gotlen;
235}
236
237/* ######################################################################## */
238
239typedef int (*iofn) (int, char *, int);
240
241static int floppyd_io(Stream_t *Stream, char *buf, mt_off_t where, int len,
242 iofn io)
243{
244 DeclareThis(RemoteFile_t);
245 int ret;
246
247 where += This->offset;
248
249 if (where != This->lastwhere ){
250 if(floppyd_lseek( This->fd, where, SEEK_SET) < 0 ){
251 perror("floppyd_lseek");
252 This->lastwhere = (mt_off_t) -1;
253 return -1;
254 }
255 }
256 ret = io(This->fd, buf, len);
257 if ( ret == -1 ){
258 perror("floppyd_io");
259 This->lastwhere = (mt_off_t) -1;
260 return -1;
261 }
262 This->lastwhere = where + ret;
263 return ret;
264}
265
266static int floppyd_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
267{
268 return floppyd_io(Stream, buf, where, len, (iofn) floppyd_reader);
269}
270
271static int floppyd_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len)
272{
273 return floppyd_io(Stream, buf, where, len, (iofn) floppyd_writer);
274}
275
276static int floppyd_flush(Stream_t *Stream)
277{
278#if 0
279 Byte buf[16];
280
281 DeclareThis(RemoteFile_t);
282
283 dword2byte(1, buf);
284 buf[4] = OP_FLUSH;
285
286 write(This->fd, buf, 5);
287
288 if (read_dword(This->fd) != 8) {
289 errno = EIO;
290 return -1;
291 }
292
293 read_dword(This->fd);
294 read_dword(This->fd);
295#endif
296 return 0;
297}
298
299static int floppyd_free(Stream_t *Stream)
300{
301 Byte buf[16];
302
303 DeclareThis(RemoteFile_t);
304
305 if (This->fd > 2) {
306 dword2byte(1, buf);
307 buf[4] = OP_CLOSE;
308 write(This->fd, buf, 5);
309 return close(This->fd);
310 } else {
311 return 0;
312 }
313}
314
315static int floppyd_geom(Stream_t *Stream, struct device *dev,
316 struct device *orig_dev,
317 int media, struct bootsector *boot)
318{
319 size_t tot_sectors;
320 int sect_per_track;
321 DeclareThis(RemoteFile_t);
322
323 dev->ssize = 2; /* allow for init_geom to change it */
324 dev->use_2m = 0x80; /* disable 2m mode to begin */
325
326 if(media == 0xf0 || media >= 0x100){
327 dev->heads = WORD(nheads);
328 dev->sectors = WORD(nsect);
329 tot_sectors = DWORD(bigsect);
330 SET_INT(tot_sectors, WORD(psect));
331 sect_per_track = dev->heads * dev->sectors;
332 tot_sectors += sect_per_track - 1; /* round size up */
333 dev->tracks = tot_sectors / sect_per_track;
334
335 } else if (media >= 0xf8){
336 media &= 3;
337 dev->heads = old_dos[media].heads;
338 dev->tracks = old_dos[media].tracks;
339 dev->sectors = old_dos[media].sectors;
340 dev->ssize = 0x80;
341 dev->use_2m = ~1;
342 } else {
343 fprintf(stderr,"Unknown media type\n");
344 exit(1);
345 }
346
347 This->size = (mt_off_t) 512 * dev->sectors * dev->tracks * dev->heads;
348
349 return 0;
350}
351
352
353static int floppyd_data(Stream_t *Stream, time_t *date, mt_size_t *size,
354 int *type, int *address)
355{
356 DeclareThis(RemoteFile_t);
357
358 if(date)
359 /* unknown, and irrelevant anyways */
360 *date = 0;
361 if(size)
362 /* the size derived from the geometry */
363 *size = (mt_size_t) This->size;
364 if(type)
365 *type = 0; /* not a directory */
366 if(address)
367 *address = 0;
368 return 0;
369}
370
371/* ######################################################################## */
372
373static Class_t FloppydFileClass = {
374 floppyd_read,
375 floppyd_write,
376 floppyd_flush,
377 floppyd_free,
378 floppyd_geom,
379 floppyd_data
380};
381
382/* ######################################################################## */
383
384int get_host_and_port(const char* name, char** hostname, char **display,
385 short* port)
386{
387 char* newname = strdup(name);
388 char* p;
389 char* p2;
390
391 p = newname;
392 while (*p != '/' && *p) p++;
393 p2 = p;
394 if (*p) p++;
395 *p2 = 0;
396
397 *port = atoi(p);
398 if (*port == 0) {
399 *port = FLOPPYD_DEFAULT_PORT;
400 }
401
402 *display = strdup(newname);
403
404 p = newname;
405 while (*p != ':' && *p) p++;
406 p2 = p;
407 if (*p) p++;
408 *p2 = 0;
409
410 *port += atoi(p); /* add display number to the port */
411
412 if (!*newname || strcmp(newname, "unix") == 0) {
413 free(newname);
414 newname = strdup("localhost");
415 }
416
417 *hostname = newname;
418 return 1;
419}
420
421/*
422 * * Return the IP address of the specified host.
423 * */
424static IPaddr_t getipaddress(char *ipaddr)
425{
426
427 struct hostent *host;
428 IPaddr_t ip;
429
430 if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
431 (strcmp(ipaddr, "255.255.255.255") != 0)) {
432
433 if ((host = gethostbyname(ipaddr)) != NULL) {
434 memcpy(&ip, host->h_addr, sizeof(ip));
435 }
436
437 endhostent();
438 }
439
440#ifdef DEBUG
441 fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
442#endif
443
444 return (ip);
445}
446
447/*
448 * * Connect to the floppyd server.
449 * */
450static int connect_to_server(IPaddr_t ip, short port)
451{
452
453 struct sockaddr_in addr;
454 int sock;
455
456 /*
457 * Allocate a socket.
458 */
459 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
460 return (-1);
461 }
462
463 /*
464 * Set the address to connect to.
465 */
466
467 addr.sin_family = AF_INET;
468#ifndef HAVE_HTONS
469 addr.sin_port = myhtons(port);
470#else
471 addr.sin_port = htons(port);
472#endif
473 addr.sin_addr.s_addr = ip;
474
475 /*
476 * Connect our socket to the above address.
477 */
478 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
479 return (-1);
480 }
481
482 /*
483 * Set the keepalive socket option to on.
484 */
485 {
486 int on = 1;
487 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
488 (char *)&on, sizeof(on));
489 }
490
491 return (sock);
492}
493
494static int ConnectToFloppyd(const char* name);
495
496Stream_t *FloppydOpen(struct device *dev, struct device *dev2,
497 char *name, int mode, char *errmsg,
498 int mode2, int locked)
499{
500 RemoteFile_t *This;
501
502 if (!dev || !(dev->misc_flags & FLOPPYD_FLAG))
503 return NULL;
504
505 This = New(RemoteFile_t);
506 if (!This){
507 printOom();
508 return NULL;
509 }
510 This->Class = &FloppydFileClass;
511 This->Next = 0;
512 This->offset = 0;
513 This->lastwhere = 0;
514 This->refs = 1;
515 This->Buffer = 0;
516
517 This->fd = ConnectToFloppyd(name);
518 if (This->fd == -1) {
519 Free(This);
520 return NULL;
521 }
522 return (Stream_t *) This;
523}
524
525static int ConnectToFloppyd(const char* name)
526{
527 char* hostname;
528 char* display;
529 short port;
530 int rval = get_host_and_port(name, &hostname, &display, &port);
531 int sock;
532 int reply;
533
534 if (!rval) return -1;
535
536 sock = connect_to_server(getipaddress(hostname), port);
537
538 if (sock == -1) {
539 fprintf(stderr,
540 "Can't connect to floppyd server on %s, port %i!\n",
541 hostname, port);
542 return -1;
543 }
544
545 reply = authenticate_to_floppyd(sock, display);
546
547 if (reply != 0) {
548 fprintf(stderr,
549 "Permission denied, authentication failed!\n"
550 "%s\n", AuthErrors[reply]);
551 return -1;
552 }
553
554 free(hostname);
555 free(display);
556
557 return sock;
558}
559#endif
Note: See TracBrowser for help on using the repository browser.