1*d5c9a868SElliott Hughes /* Copyright 1999 Peter Schlaile.
2*d5c9a868SElliott Hughes * Copyright 1999-2002,2005-2007,2009 Alain Knaff.
3*d5c9a868SElliott Hughes * This file is part of mtools.
4*d5c9a868SElliott Hughes *
5*d5c9a868SElliott Hughes * Mtools is free software: you can redistribute it and/or modify
6*d5c9a868SElliott Hughes * it under the terms of the GNU General Public License as published by
7*d5c9a868SElliott Hughes * the Free Software Foundation, either version 3 of the License, or
8*d5c9a868SElliott Hughes * (at your option) any later version.
9*d5c9a868SElliott Hughes *
10*d5c9a868SElliott Hughes * Mtools is distributed in the hope that it will be useful,
11*d5c9a868SElliott Hughes * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*d5c9a868SElliott Hughes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*d5c9a868SElliott Hughes * GNU General Public License for more details.
14*d5c9a868SElliott Hughes *
15*d5c9a868SElliott Hughes * You should have received a copy of the GNU General Public License
16*d5c9a868SElliott Hughes * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
17*d5c9a868SElliott Hughes *
18*d5c9a868SElliott Hughes * IO to the floppyd daemon running on the local X-Server Host
19*d5c9a868SElliott Hughes *
20*d5c9a868SElliott Hughes * written by:
21*d5c9a868SElliott Hughes *
22*d5c9a868SElliott Hughes * Peter Schlaile
23*d5c9a868SElliott Hughes *
24*d5c9a868SElliott Hughes * [email protected]
25*d5c9a868SElliott Hughes *
26*d5c9a868SElliott Hughes */
27*d5c9a868SElliott Hughes
28*d5c9a868SElliott Hughes #include "sysincludes.h"
29*d5c9a868SElliott Hughes #include "stream.h"
30*d5c9a868SElliott Hughes #include "mtools.h"
31*d5c9a868SElliott Hughes #include "msdos.h"
32*d5c9a868SElliott Hughes #include "scsi.h"
33*d5c9a868SElliott Hughes #include "floppyd_io.h"
34*d5c9a868SElliott Hughes
35*d5c9a868SElliott Hughes /* ######################################################################## */
36*d5c9a868SElliott Hughes
37*d5c9a868SElliott Hughes
38*d5c9a868SElliott Hughes static const char* AuthErrors[] = {
39*d5c9a868SElliott Hughes "Auth success",
40*d5c9a868SElliott Hughes "Auth failed: Packet oversized",
41*d5c9a868SElliott Hughes "Auth failed: X-Cookie doesn't match",
42*d5c9a868SElliott Hughes "Auth failed: Wrong transmission protocol version",
43*d5c9a868SElliott Hughes "Auth failed: Device locked",
44*d5c9a868SElliott Hughes "Auth failed: Bad packet",
45*d5c9a868SElliott Hughes "Auth failed: I/O Error"
46*d5c9a868SElliott Hughes };
47*d5c9a868SElliott Hughes
48*d5c9a868SElliott Hughes
49*d5c9a868SElliott Hughes typedef struct RemoteFile_t {
50*d5c9a868SElliott Hughes struct Stream_t head;
51*d5c9a868SElliott Hughes
52*d5c9a868SElliott Hughes int fd;
53*d5c9a868SElliott Hughes mt_off_t offset;
54*d5c9a868SElliott Hughes mt_off_t lastwhere;
55*d5c9a868SElliott Hughes mt_off_t size;
56*d5c9a868SElliott Hughes unsigned int version;
57*d5c9a868SElliott Hughes unsigned int capabilities;
58*d5c9a868SElliott Hughes int drive;
59*d5c9a868SElliott Hughes } RemoteFile_t;
60*d5c9a868SElliott Hughes
61*d5c9a868SElliott Hughes
62*d5c9a868SElliott Hughes #include "byte_dword.h"
63*d5c9a868SElliott Hughes #include "read_dword.h"
64*d5c9a868SElliott Hughes
65*d5c9a868SElliott Hughes
66*d5c9a868SElliott Hughes /* ######################################################################## */
67*d5c9a868SElliott Hughes
authenticate_to_floppyd(RemoteFile_t * floppyd,int sock,char * display)68*d5c9a868SElliott Hughes static unsigned int authenticate_to_floppyd(RemoteFile_t *floppyd,
69*d5c9a868SElliott Hughes int sock, char *display)
70*d5c9a868SElliott Hughes {
71*d5c9a868SElliott Hughes size_t cookielen;
72*d5c9a868SElliott Hughes uint16_t filelen;
73*d5c9a868SElliott Hughes ssize_t newlen;
74*d5c9a868SElliott Hughes Byte buf[16];
75*d5c9a868SElliott Hughes const char *command[] = { "xauth", "xauth", "extract", "-", 0, 0 };
76*d5c9a868SElliott Hughes char *xcookie;
77*d5c9a868SElliott Hughes Dword errcode;
78*d5c9a868SElliott Hughes int l;
79*d5c9a868SElliott Hughes
80*d5c9a868SElliott Hughes command[4] = display;
81*d5c9a868SElliott Hughes
82*d5c9a868SElliott Hughes cookielen=strlen(display);
83*d5c9a868SElliott Hughes cookielen += 100;
84*d5c9a868SElliott Hughes
85*d5c9a868SElliott Hughes xcookie = (char *) safe_malloc(cookielen+4);
86*d5c9a868SElliott Hughes newlen = safePopenOut(command, xcookie+4, cookielen);
87*d5c9a868SElliott Hughes if(newlen < 1 || newlen > UINT16_MAX)
88*d5c9a868SElliott Hughes return AUTH_AUTHFAILED;
89*d5c9a868SElliott Hughes filelen = (uint16_t) newlen;
90*d5c9a868SElliott Hughes
91*d5c9a868SElliott Hughes /* Version negotiation */
92*d5c9a868SElliott Hughes dword2byte(4,buf);
93*d5c9a868SElliott Hughes dword2byte(floppyd->version,buf+4);
94*d5c9a868SElliott Hughes if(write(sock, buf, 8) < 8)
95*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
96*d5c9a868SElliott Hughes
97*d5c9a868SElliott Hughes if ( (l = (int) read_dword(sock)) < 4) {
98*d5c9a868SElliott Hughes return AUTH_WRONGVERSION;
99*d5c9a868SElliott Hughes }
100*d5c9a868SElliott Hughes
101*d5c9a868SElliott Hughes errcode = read_dword(sock);
102*d5c9a868SElliott Hughes
103*d5c9a868SElliott Hughes if (errcode != AUTH_SUCCESS) {
104*d5c9a868SElliott Hughes return errcode;
105*d5c9a868SElliott Hughes }
106*d5c9a868SElliott Hughes
107*d5c9a868SElliott Hughes if(l >= 8)
108*d5c9a868SElliott Hughes floppyd->version = read_dword(sock);
109*d5c9a868SElliott Hughes if(l >= 12)
110*d5c9a868SElliott Hughes floppyd->capabilities = read_dword(sock);
111*d5c9a868SElliott Hughes
112*d5c9a868SElliott Hughes dword2byte(filelen, (Byte *)xcookie);
113*d5c9a868SElliott Hughes if(write(sock, xcookie, filelen+4) < ((ssize_t) (filelen + 4)))
114*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
115*d5c9a868SElliott Hughes
116*d5c9a868SElliott Hughes if (read_dword(sock) != 4) {
117*d5c9a868SElliott Hughes return AUTH_PACKETOVERSIZE;
118*d5c9a868SElliott Hughes }
119*d5c9a868SElliott Hughes
120*d5c9a868SElliott Hughes errcode = read_dword(sock);
121*d5c9a868SElliott Hughes
122*d5c9a868SElliott Hughes return errcode;
123*d5c9a868SElliott Hughes }
124*d5c9a868SElliott Hughes
125*d5c9a868SElliott Hughes
floppyd_reader(int fd,char * buffer,uint32_t len)126*d5c9a868SElliott Hughes static ssize_t floppyd_reader(int fd, char* buffer, uint32_t len)
127*d5c9a868SElliott Hughes {
128*d5c9a868SElliott Hughes Dword errcode;
129*d5c9a868SElliott Hughes Dword gotlen;
130*d5c9a868SElliott Hughes Byte buf[16];
131*d5c9a868SElliott Hughes
132*d5c9a868SElliott Hughes dword2byte(1, buf);
133*d5c9a868SElliott Hughes buf[4] = OP_READ;
134*d5c9a868SElliott Hughes dword2byte(4, buf+5);
135*d5c9a868SElliott Hughes dword2byte(len, buf+9);
136*d5c9a868SElliott Hughes if(write(fd, buf, 13) < 13)
137*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
138*d5c9a868SElliott Hughes
139*d5c9a868SElliott Hughes if (read_dword(fd) != 8) {
140*d5c9a868SElliott Hughes errno = EIO;
141*d5c9a868SElliott Hughes return -1;
142*d5c9a868SElliott Hughes }
143*d5c9a868SElliott Hughes
144*d5c9a868SElliott Hughes gotlen = read_dword(fd);
145*d5c9a868SElliott Hughes errcode = read_dword(fd);
146*d5c9a868SElliott Hughes
147*d5c9a868SElliott Hughes if (gotlen != (Dword) -1) {
148*d5c9a868SElliott Hughes size_t l;
149*d5c9a868SElliott Hughes unsigned int start;
150*d5c9a868SElliott Hughes if (read_dword(fd) != gotlen) {
151*d5c9a868SElliott Hughes errno = EIO;
152*d5c9a868SElliott Hughes return -1;
153*d5c9a868SElliott Hughes }
154*d5c9a868SElliott Hughes for (start = 0, l = 0; start < gotlen; start += l) {
155*d5c9a868SElliott Hughes ssize_t ret = read(fd, buffer+start, gotlen-start);
156*d5c9a868SElliott Hughes if( ret < 0)
157*d5c9a868SElliott Hughes return -1;
158*d5c9a868SElliott Hughes if (ret == 0) {
159*d5c9a868SElliott Hughes errno = EIO;
160*d5c9a868SElliott Hughes return -1;
161*d5c9a868SElliott Hughes }
162*d5c9a868SElliott Hughes l = (size_t) ret;
163*d5c9a868SElliott Hughes }
164*d5c9a868SElliott Hughes } else {
165*d5c9a868SElliott Hughes errno = (int) errcode;
166*d5c9a868SElliott Hughes }
167*d5c9a868SElliott Hughes return (ssize_t) gotlen;
168*d5c9a868SElliott Hughes }
169*d5c9a868SElliott Hughes
floppyd_writer(int fd,char * buffer,uint32_t len)170*d5c9a868SElliott Hughes static ssize_t floppyd_writer(int fd, char* buffer, uint32_t len)
171*d5c9a868SElliott Hughes {
172*d5c9a868SElliott Hughes int errcode;
173*d5c9a868SElliott Hughes int32_t gotlen;
174*d5c9a868SElliott Hughes Byte buf[16];
175*d5c9a868SElliott Hughes ssize_t ret;
176*d5c9a868SElliott Hughes
177*d5c9a868SElliott Hughes dword2byte(1, buf);
178*d5c9a868SElliott Hughes buf[4] = OP_WRITE;
179*d5c9a868SElliott Hughes dword2byte(len, buf+5);
180*d5c9a868SElliott Hughes
181*d5c9a868SElliott Hughes cork(fd, 1);
182*d5c9a868SElliott Hughes if(write(fd, buf, 9) < 9)
183*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
184*d5c9a868SElliott Hughes ret = write(fd, buffer, len);
185*d5c9a868SElliott Hughes if(ret == -1 || (size_t) ret < len)
186*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
187*d5c9a868SElliott Hughes cork(fd, 0);
188*d5c9a868SElliott Hughes
189*d5c9a868SElliott Hughes if (read_dword(fd) != 8) {
190*d5c9a868SElliott Hughes errno = EIO;
191*d5c9a868SElliott Hughes return -1;
192*d5c9a868SElliott Hughes }
193*d5c9a868SElliott Hughes
194*d5c9a868SElliott Hughes gotlen = read_sdword(fd);
195*d5c9a868SElliott Hughes errcode = read_sdword(fd);
196*d5c9a868SElliott Hughes
197*d5c9a868SElliott Hughes errno = errcode;
198*d5c9a868SElliott Hughes if(errno != 0 && gotlen == 0) {
199*d5c9a868SElliott Hughes if (errno == EBADF)
200*d5c9a868SElliott Hughes errno = EROFS;
201*d5c9a868SElliott Hughes gotlen = -1;
202*d5c9a868SElliott Hughes }
203*d5c9a868SElliott Hughes
204*d5c9a868SElliott Hughes return gotlen;
205*d5c9a868SElliott Hughes }
206*d5c9a868SElliott Hughes
floppyd_lseek(int fd,int32_t offset,int whence)207*d5c9a868SElliott Hughes static int floppyd_lseek(int fd, int32_t offset, int whence)
208*d5c9a868SElliott Hughes {
209*d5c9a868SElliott Hughes int errcode;
210*d5c9a868SElliott Hughes int gotlen;
211*d5c9a868SElliott Hughes Byte buf[32];
212*d5c9a868SElliott Hughes
213*d5c9a868SElliott Hughes dword2byte(1, buf);
214*d5c9a868SElliott Hughes buf[4] = OP_SEEK;
215*d5c9a868SElliott Hughes
216*d5c9a868SElliott Hughes dword2byte(8, buf+5);
217*d5c9a868SElliott Hughes sdword2byte(offset, buf+9);
218*d5c9a868SElliott Hughes sdword2byte(whence, buf+13);
219*d5c9a868SElliott Hughes
220*d5c9a868SElliott Hughes if(write(fd, buf, 17) < 17)
221*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
222*d5c9a868SElliott Hughes
223*d5c9a868SElliott Hughes if (read_dword(fd) != 8) {
224*d5c9a868SElliott Hughes errno = EIO;
225*d5c9a868SElliott Hughes return -1;
226*d5c9a868SElliott Hughes }
227*d5c9a868SElliott Hughes
228*d5c9a868SElliott Hughes gotlen = read_sdword(fd);
229*d5c9a868SElliott Hughes errcode = read_sdword(fd);
230*d5c9a868SElliott Hughes
231*d5c9a868SElliott Hughes errno = errcode;
232*d5c9a868SElliott Hughes
233*d5c9a868SElliott Hughes return gotlen;
234*d5c9a868SElliott Hughes }
235*d5c9a868SElliott Hughes
236*d5c9a868SElliott Hughes #if SIZEOF_OFF_T >= 8
floppyd_lseek64(int fd,mt_off_t offset,int whence)237*d5c9a868SElliott Hughes static mt_off_t floppyd_lseek64(int fd, mt_off_t offset, int whence)
238*d5c9a868SElliott Hughes {
239*d5c9a868SElliott Hughes int errcode;
240*d5c9a868SElliott Hughes struct SQwordRet gotlen;
241*d5c9a868SElliott Hughes Byte buf[32];
242*d5c9a868SElliott Hughes
243*d5c9a868SElliott Hughes dword2byte(1, buf);
244*d5c9a868SElliott Hughes buf[4] = OP_SEEK64;
245*d5c9a868SElliott Hughes
246*d5c9a868SElliott Hughes dword2byte(12, buf+5);
247*d5c9a868SElliott Hughes qword2byte((uint32_t)offset, buf+9);
248*d5c9a868SElliott Hughes sdword2byte(whence, buf+17);
249*d5c9a868SElliott Hughes
250*d5c9a868SElliott Hughes if(write(fd, buf, 21) < 21)
251*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
252*d5c9a868SElliott Hughes
253*d5c9a868SElliott Hughes if (read_dword(fd) != 12) {
254*d5c9a868SElliott Hughes errno = EIO;
255*d5c9a868SElliott Hughes return -1;
256*d5c9a868SElliott Hughes }
257*d5c9a868SElliott Hughes
258*d5c9a868SElliott Hughes gotlen = read_sqword(fd);
259*d5c9a868SElliott Hughes errcode = read_sdword(fd);
260*d5c9a868SElliott Hughes
261*d5c9a868SElliott Hughes errno = errcode;
262*d5c9a868SElliott Hughes
263*d5c9a868SElliott Hughes return gotlen.v;
264*d5c9a868SElliott Hughes }
265*d5c9a868SElliott Hughes #endif
266*d5c9a868SElliott Hughes
floppyd_open(RemoteFile_t * This,int mode)267*d5c9a868SElliott Hughes static int floppyd_open(RemoteFile_t *This, int mode)
268*d5c9a868SElliott Hughes {
269*d5c9a868SElliott Hughes int errcode;
270*d5c9a868SElliott Hughes int gotlen;
271*d5c9a868SElliott Hughes Byte buf[16];
272*d5c9a868SElliott Hughes
273*d5c9a868SElliott Hughes if(! (This->capabilities & FLOPPYD_CAP_EXPLICIT_OPEN) ) {
274*d5c9a868SElliott Hughes /* floppyd has no "explicit seek" capabilities */
275*d5c9a868SElliott Hughes return 0;
276*d5c9a868SElliott Hughes }
277*d5c9a868SElliott Hughes
278*d5c9a868SElliott Hughes dword2byte(1, buf);
279*d5c9a868SElliott Hughes if((mode & O_ACCMODE) == O_RDONLY)
280*d5c9a868SElliott Hughes buf[4] = OP_OPRO;
281*d5c9a868SElliott Hughes else
282*d5c9a868SElliott Hughes buf[4] = OP_OPRW;
283*d5c9a868SElliott Hughes dword2byte(4, buf+5);
284*d5c9a868SElliott Hughes sdword2byte(This->drive, buf+9);
285*d5c9a868SElliott Hughes
286*d5c9a868SElliott Hughes if(write(This->fd, buf, 13) < 13)
287*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
288*d5c9a868SElliott Hughes
289*d5c9a868SElliott Hughes if (read_dword(This->fd) != 8) {
290*d5c9a868SElliott Hughes errno = EIO;
291*d5c9a868SElliott Hughes return -1;
292*d5c9a868SElliott Hughes }
293*d5c9a868SElliott Hughes
294*d5c9a868SElliott Hughes gotlen = read_sdword(This->fd);
295*d5c9a868SElliott Hughes errcode = read_sdword(This->fd);
296*d5c9a868SElliott Hughes
297*d5c9a868SElliott Hughes errno = errcode;
298*d5c9a868SElliott Hughes
299*d5c9a868SElliott Hughes return gotlen;
300*d5c9a868SElliott Hughes }
301*d5c9a868SElliott Hughes
302*d5c9a868SElliott Hughes
303*d5c9a868SElliott Hughes /* ######################################################################## */
304*d5c9a868SElliott Hughes
305*d5c9a868SElliott Hughes typedef ssize_t (*iofn) (int, char *, uint32_t);
306*d5c9a868SElliott Hughes
floppyd_io(Stream_t * Stream,char * buf,mt_off_t where,size_t len,iofn io)307*d5c9a868SElliott Hughes static ssize_t floppyd_io(Stream_t *Stream, char *buf, mt_off_t where,
308*d5c9a868SElliott Hughes size_t len, iofn io)
309*d5c9a868SElliott Hughes {
310*d5c9a868SElliott Hughes DeclareThis(RemoteFile_t);
311*d5c9a868SElliott Hughes ssize_t ret;
312*d5c9a868SElliott Hughes
313*d5c9a868SElliott Hughes where += This->offset;
314*d5c9a868SElliott Hughes
315*d5c9a868SElliott Hughes if (where != This->lastwhere ){
316*d5c9a868SElliott Hughes #if SIZEOF_OFF_T >= 8
317*d5c9a868SElliott Hughes if(This->capabilities & FLOPPYD_CAP_LARGE_SEEK) {
318*d5c9a868SElliott Hughes if(floppyd_lseek64( This->fd, where, SEEK_SET) < 0 ){
319*d5c9a868SElliott Hughes perror("floppyd_lseek64");
320*d5c9a868SElliott Hughes This->lastwhere = -1;
321*d5c9a868SElliott Hughes return -1;
322*d5c9a868SElliott Hughes }
323*d5c9a868SElliott Hughes } else
324*d5c9a868SElliott Hughes #endif
325*d5c9a868SElliott Hughes {
326*d5c9a868SElliott Hughes if(where > INT32_MAX || where < INT32_MIN) {
327*d5c9a868SElliott Hughes fprintf(stderr, "Seek position out of range\n");
328*d5c9a868SElliott Hughes return -1;
329*d5c9a868SElliott Hughes }
330*d5c9a868SElliott Hughes if(floppyd_lseek(This->fd, (int32_t) where, SEEK_SET) < 0 ){
331*d5c9a868SElliott Hughes perror("floppyd_lseek");
332*d5c9a868SElliott Hughes This->lastwhere = -1;
333*d5c9a868SElliott Hughes return -1;
334*d5c9a868SElliott Hughes }
335*d5c9a868SElliott Hughes }
336*d5c9a868SElliott Hughes }
337*d5c9a868SElliott Hughes ret = io(This->fd, buf,
338*d5c9a868SElliott Hughes (len > INT32_MAX) ? (uint32_t)INT32_MAX+1 : (uint32_t) len);
339*d5c9a868SElliott Hughes if ( ret == -1 ){
340*d5c9a868SElliott Hughes perror("floppyd_io");
341*d5c9a868SElliott Hughes This->lastwhere = -1;
342*d5c9a868SElliott Hughes return -1;
343*d5c9a868SElliott Hughes }
344*d5c9a868SElliott Hughes This->lastwhere = where + ret;
345*d5c9a868SElliott Hughes return ret;
346*d5c9a868SElliott Hughes }
347*d5c9a868SElliott Hughes
floppyd_pread(Stream_t * Stream,char * buf,mt_off_t where,size_t len)348*d5c9a868SElliott Hughes static ssize_t floppyd_pread(Stream_t *Stream, char *buf,
349*d5c9a868SElliott Hughes mt_off_t where, size_t len)
350*d5c9a868SElliott Hughes {
351*d5c9a868SElliott Hughes return floppyd_io(Stream, buf, where, len, floppyd_reader);
352*d5c9a868SElliott Hughes }
353*d5c9a868SElliott Hughes
floppyd_pwrite(Stream_t * Stream,char * buf,mt_off_t where,size_t len)354*d5c9a868SElliott Hughes static ssize_t floppyd_pwrite(Stream_t *Stream, char *buf,
355*d5c9a868SElliott Hughes mt_off_t where, size_t len)
356*d5c9a868SElliott Hughes {
357*d5c9a868SElliott Hughes return floppyd_io(Stream, buf, where, len, floppyd_writer);
358*d5c9a868SElliott Hughes }
359*d5c9a868SElliott Hughes
floppyd_flush(Stream_t * Stream)360*d5c9a868SElliott Hughes static int floppyd_flush(Stream_t *Stream)
361*d5c9a868SElliott Hughes {
362*d5c9a868SElliott Hughes Byte buf[16];
363*d5c9a868SElliott Hughes
364*d5c9a868SElliott Hughes DeclareThis(RemoteFile_t);
365*d5c9a868SElliott Hughes
366*d5c9a868SElliott Hughes dword2byte(1, buf);
367*d5c9a868SElliott Hughes buf[4] = OP_FLUSH;
368*d5c9a868SElliott Hughes dword2byte(1, buf+5);
369*d5c9a868SElliott Hughes buf[9] = '\0';
370*d5c9a868SElliott Hughes
371*d5c9a868SElliott Hughes if(write(This->fd, buf, 10) < 10)
372*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
373*d5c9a868SElliott Hughes
374*d5c9a868SElliott Hughes if (read_dword(This->fd) != 8) {
375*d5c9a868SElliott Hughes errno = EIO;
376*d5c9a868SElliott Hughes return -1;
377*d5c9a868SElliott Hughes }
378*d5c9a868SElliott Hughes
379*d5c9a868SElliott Hughes read_dword(This->fd);
380*d5c9a868SElliott Hughes read_dword(This->fd);
381*d5c9a868SElliott Hughes return 0;
382*d5c9a868SElliott Hughes }
383*d5c9a868SElliott Hughes
floppyd_free(Stream_t * Stream)384*d5c9a868SElliott Hughes static int floppyd_free(Stream_t *Stream)
385*d5c9a868SElliott Hughes {
386*d5c9a868SElliott Hughes Byte buf[16];
387*d5c9a868SElliott Hughes int gotlen;
388*d5c9a868SElliott Hughes int errcode;
389*d5c9a868SElliott Hughes DeclareThis(RemoteFile_t);
390*d5c9a868SElliott Hughes
391*d5c9a868SElliott Hughes if (This->fd > 2) {
392*d5c9a868SElliott Hughes dword2byte(1, buf);
393*d5c9a868SElliott Hughes buf[4] = OP_CLOSE;
394*d5c9a868SElliott Hughes if(write(This->fd, buf, 5) < 5)
395*d5c9a868SElliott Hughes return AUTH_IO_ERROR;
396*d5c9a868SElliott Hughes shutdown(This->fd, 1);
397*d5c9a868SElliott Hughes if (read_dword(This->fd) != 8) {
398*d5c9a868SElliott Hughes errno = EIO;
399*d5c9a868SElliott Hughes return -1;
400*d5c9a868SElliott Hughes }
401*d5c9a868SElliott Hughes
402*d5c9a868SElliott Hughes gotlen = read_sdword(This->fd);
403*d5c9a868SElliott Hughes errcode = read_sdword(This->fd);
404*d5c9a868SElliott Hughes
405*d5c9a868SElliott Hughes errno = errcode;
406*d5c9a868SElliott Hughes
407*d5c9a868SElliott Hughes close(This->fd);
408*d5c9a868SElliott Hughes return gotlen;
409*d5c9a868SElliott Hughes } else {
410*d5c9a868SElliott Hughes return 0;
411*d5c9a868SElliott Hughes }
412*d5c9a868SElliott Hughes }
413*d5c9a868SElliott Hughes
414*d5c9a868SElliott Hughes
415*d5c9a868SElliott Hughes
floppyd_data(Stream_t * Stream,time_t * date,mt_off_t * size,int * type,uint32_t * address)416*d5c9a868SElliott Hughes static int floppyd_data(Stream_t *Stream, time_t *date, mt_off_t *size,
417*d5c9a868SElliott Hughes int *type, uint32_t *address)
418*d5c9a868SElliott Hughes {
419*d5c9a868SElliott Hughes DeclareThis(RemoteFile_t);
420*d5c9a868SElliott Hughes
421*d5c9a868SElliott Hughes if(date)
422*d5c9a868SElliott Hughes /* unknown, and irrelevant anyways */
423*d5c9a868SElliott Hughes *date = 0;
424*d5c9a868SElliott Hughes if(size)
425*d5c9a868SElliott Hughes /* the size derived from the geometry */
426*d5c9a868SElliott Hughes *size = This->size;
427*d5c9a868SElliott Hughes if(type)
428*d5c9a868SElliott Hughes *type = 0; /* not a directory */
429*d5c9a868SElliott Hughes if(address)
430*d5c9a868SElliott Hughes *address = 0;
431*d5c9a868SElliott Hughes return 0;
432*d5c9a868SElliott Hughes }
433*d5c9a868SElliott Hughes
434*d5c9a868SElliott Hughes /* ######################################################################## */
435*d5c9a868SElliott Hughes
436*d5c9a868SElliott Hughes static Class_t FloppydFileClass = {
437*d5c9a868SElliott Hughes 0,
438*d5c9a868SElliott Hughes 0,
439*d5c9a868SElliott Hughes floppyd_pread,
440*d5c9a868SElliott Hughes floppyd_pwrite,
441*d5c9a868SElliott Hughes floppyd_flush,
442*d5c9a868SElliott Hughes floppyd_free,
443*d5c9a868SElliott Hughes set_geom_noop,
444*d5c9a868SElliott Hughes floppyd_data,
445*d5c9a868SElliott Hughes 0, /* pre_allocate */
446*d5c9a868SElliott Hughes 0, /* get_dosConvert */
447*d5c9a868SElliott Hughes 0 /* discard */
448*d5c9a868SElliott Hughes };
449*d5c9a868SElliott Hughes
450*d5c9a868SElliott Hughes /* ######################################################################## */
451*d5c9a868SElliott Hughes
get_host_and_port_and_drive(const char * name,char ** hostname,char ** display,uint16_t * port,int * drive)452*d5c9a868SElliott Hughes static int get_host_and_port_and_drive(const char* name, char** hostname,
453*d5c9a868SElliott Hughes char **display, uint16_t* port,
454*d5c9a868SElliott Hughes int *drive)
455*d5c9a868SElliott Hughes {
456*d5c9a868SElliott Hughes char* newname = strdup(name);
457*d5c9a868SElliott Hughes char* p;
458*d5c9a868SElliott Hughes char* p2;
459*d5c9a868SElliott Hughes
460*d5c9a868SElliott Hughes p = newname;
461*d5c9a868SElliott Hughes while (*p != '/' && *p) p++;
462*d5c9a868SElliott Hughes p2 = p;
463*d5c9a868SElliott Hughes if (*p) p++;
464*d5c9a868SElliott Hughes *p2 = 0;
465*d5c9a868SElliott Hughes
466*d5c9a868SElliott Hughes *port = FLOPPYD_DEFAULT_PORT;
467*d5c9a868SElliott Hughes if(*p >= '0' && *p <= '9')
468*d5c9a868SElliott Hughes *port = strtou16(p, &p, 0);
469*d5c9a868SElliott Hughes if(*p == '/')
470*d5c9a868SElliott Hughes p++;
471*d5c9a868SElliott Hughes *drive = 0;
472*d5c9a868SElliott Hughes if(*p >= '0' && *p <= '9')
473*d5c9a868SElliott Hughes *drive = strtoi(p, &p, 0);
474*d5c9a868SElliott Hughes
475*d5c9a868SElliott Hughes *display = strdup(newname);
476*d5c9a868SElliott Hughes
477*d5c9a868SElliott Hughes p = newname;
478*d5c9a868SElliott Hughes while (*p != ':' && *p) p++;
479*d5c9a868SElliott Hughes p2 = p;
480*d5c9a868SElliott Hughes if (*p) p++;
481*d5c9a868SElliott Hughes *p2 = 0;
482*d5c9a868SElliott Hughes
483*d5c9a868SElliott Hughes *port += atoi(p); /* add display number to the port */
484*d5c9a868SElliott Hughes
485*d5c9a868SElliott Hughes if (!*newname || strcmp(newname, "unix") == 0) {
486*d5c9a868SElliott Hughes free(newname);
487*d5c9a868SElliott Hughes newname = strdup("localhost");
488*d5c9a868SElliott Hughes }
489*d5c9a868SElliott Hughes
490*d5c9a868SElliott Hughes *hostname = newname;
491*d5c9a868SElliott Hughes return 1;
492*d5c9a868SElliott Hughes }
493*d5c9a868SElliott Hughes
494*d5c9a868SElliott Hughes /*
495*d5c9a868SElliott Hughes * * Return the IP address of the specified host.
496*d5c9a868SElliott Hughes * */
getipaddress(char * ipaddr)497*d5c9a868SElliott Hughes static in_addr_t getipaddress(char *ipaddr)
498*d5c9a868SElliott Hughes {
499*d5c9a868SElliott Hughes struct hostent *host;
500*d5c9a868SElliott Hughes in_addr_t ip;
501*d5c9a868SElliott Hughes
502*d5c9a868SElliott Hughes if (((ip = inet_addr(ipaddr)) == INADDR_NONE) &&
503*d5c9a868SElliott Hughes (strcmp(ipaddr, "255.255.255.255") != 0)) {
504*d5c9a868SElliott Hughes
505*d5c9a868SElliott Hughes if ((host = gethostbyname(ipaddr)) != NULL) {
506*d5c9a868SElliott Hughes memcpy(&ip, host->h_addr, sizeof(ip));
507*d5c9a868SElliott Hughes }
508*d5c9a868SElliott Hughes
509*d5c9a868SElliott Hughes endhostent();
510*d5c9a868SElliott Hughes }
511*d5c9a868SElliott Hughes
512*d5c9a868SElliott Hughes #ifdef DEBUG
513*d5c9a868SElliott Hughes fprintf(stderr, "IP lookup %s -> 0x%08lx\n", ipaddr, ip);
514*d5c9a868SElliott Hughes #endif
515*d5c9a868SElliott Hughes
516*d5c9a868SElliott Hughes return (ip);
517*d5c9a868SElliott Hughes }
518*d5c9a868SElliott Hughes
519*d5c9a868SElliott Hughes /*
520*d5c9a868SElliott Hughes * * Connect to the floppyd server.
521*d5c9a868SElliott Hughes * */
connect_to_server(in_addr_t ip,uint16_t port)522*d5c9a868SElliott Hughes static int connect_to_server(in_addr_t ip, uint16_t port)
523*d5c9a868SElliott Hughes {
524*d5c9a868SElliott Hughes
525*d5c9a868SElliott Hughes struct sockaddr_in addr;
526*d5c9a868SElliott Hughes int sock;
527*d5c9a868SElliott Hughes
528*d5c9a868SElliott Hughes /*
529*d5c9a868SElliott Hughes * Allocate a socket.
530*d5c9a868SElliott Hughes */
531*d5c9a868SElliott Hughes if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
532*d5c9a868SElliott Hughes return (-1);
533*d5c9a868SElliott Hughes }
534*d5c9a868SElliott Hughes
535*d5c9a868SElliott Hughes /*
536*d5c9a868SElliott Hughes * Set the address to connect to.
537*d5c9a868SElliott Hughes */
538*d5c9a868SElliott Hughes
539*d5c9a868SElliott Hughes addr.sin_family = AF_INET;
540*d5c9a868SElliott Hughes addr.sin_port = htons(port);
541*d5c9a868SElliott Hughes addr.sin_addr.s_addr = ip;
542*d5c9a868SElliott Hughes
543*d5c9a868SElliott Hughes /*
544*d5c9a868SElliott Hughes * Connect our socket to the above address.
545*d5c9a868SElliott Hughes */
546*d5c9a868SElliott Hughes if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
547*d5c9a868SElliott Hughes return (-1);
548*d5c9a868SElliott Hughes }
549*d5c9a868SElliott Hughes
550*d5c9a868SElliott Hughes /*
551*d5c9a868SElliott Hughes * Set the keepalive socket option to on.
552*d5c9a868SElliott Hughes */
553*d5c9a868SElliott Hughes {
554*d5c9a868SElliott Hughes int on = 1;
555*d5c9a868SElliott Hughes setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
556*d5c9a868SElliott Hughes (char *)&on, sizeof(on));
557*d5c9a868SElliott Hughes }
558*d5c9a868SElliott Hughes
559*d5c9a868SElliott Hughes return (sock);
560*d5c9a868SElliott Hughes }
561*d5c9a868SElliott Hughes
562*d5c9a868SElliott Hughes static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
563*d5c9a868SElliott Hughes char *errmsg);
564*d5c9a868SElliott Hughes
FloppydOpen(struct device * dev,const char * name,int mode,char * errmsg,mt_off_t * maxSize)565*d5c9a868SElliott Hughes Stream_t *FloppydOpen(struct device *dev,
566*d5c9a868SElliott Hughes const char *name, int mode, char *errmsg,
567*d5c9a868SElliott Hughes mt_off_t *maxSize)
568*d5c9a868SElliott Hughes {
569*d5c9a868SElliott Hughes RemoteFile_t *This;
570*d5c9a868SElliott Hughes
571*d5c9a868SElliott Hughes if (!dev || !(dev->misc_flags & FLOPPYD_FLAG))
572*d5c9a868SElliott Hughes return NULL;
573*d5c9a868SElliott Hughes
574*d5c9a868SElliott Hughes This = New(RemoteFile_t);
575*d5c9a868SElliott Hughes if (!This){
576*d5c9a868SElliott Hughes printOom();
577*d5c9a868SElliott Hughes return NULL;
578*d5c9a868SElliott Hughes }
579*d5c9a868SElliott Hughes init_head(&This->head, &FloppydFileClass, NULL);
580*d5c9a868SElliott Hughes
581*d5c9a868SElliott Hughes This->offset = 0;
582*d5c9a868SElliott Hughes This->lastwhere = 0;
583*d5c9a868SElliott Hughes
584*d5c9a868SElliott Hughes This->fd = ConnectToFloppyd(This, name, errmsg);
585*d5c9a868SElliott Hughes if (This->fd == -1) {
586*d5c9a868SElliott Hughes Free(This);
587*d5c9a868SElliott Hughes return NULL;
588*d5c9a868SElliott Hughes }
589*d5c9a868SElliott Hughes
590*d5c9a868SElliott Hughes if(floppyd_open(This, mode) < 0) {
591*d5c9a868SElliott Hughes sprintf(errmsg,
592*d5c9a868SElliott Hughes "Can't open remote drive: %s", strerror(errno));
593*d5c9a868SElliott Hughes close(This->fd);
594*d5c9a868SElliott Hughes Free(This);
595*d5c9a868SElliott Hughes return NULL;
596*d5c9a868SElliott Hughes }
597*d5c9a868SElliott Hughes
598*d5c9a868SElliott Hughes if(maxSize) {
599*d5c9a868SElliott Hughes *maxSize =
600*d5c9a868SElliott Hughes ((This->capabilities & FLOPPYD_CAP_LARGE_SEEK) ?
601*d5c9a868SElliott Hughes max_off_t_seek : max_off_t_31);
602*d5c9a868SElliott Hughes }
603*d5c9a868SElliott Hughes return &This->head;
604*d5c9a868SElliott Hughes }
605*d5c9a868SElliott Hughes
ConnectToFloppyd(RemoteFile_t * floppyd,const char * name,char * errmsg)606*d5c9a868SElliott Hughes static int ConnectToFloppyd(RemoteFile_t *floppyd, const char* name,
607*d5c9a868SElliott Hughes char *errmsg)
608*d5c9a868SElliott Hughes {
609*d5c9a868SElliott Hughes char* hostname;
610*d5c9a868SElliott Hughes char* display;
611*d5c9a868SElliott Hughes uint16_t port;
612*d5c9a868SElliott Hughes int rval = get_host_and_port_and_drive(name, &hostname, &display,
613*d5c9a868SElliott Hughes &port, &floppyd->drive);
614*d5c9a868SElliott Hughes int sock;
615*d5c9a868SElliott Hughes unsigned int reply;
616*d5c9a868SElliott Hughes
617*d5c9a868SElliott Hughes if (!rval) return -1;
618*d5c9a868SElliott Hughes
619*d5c9a868SElliott Hughes floppyd->version = FLOPPYD_PROTOCOL_VERSION;
620*d5c9a868SElliott Hughes floppyd->capabilities = 0;
621*d5c9a868SElliott Hughes while(1) {
622*d5c9a868SElliott Hughes sock = connect_to_server(getipaddress(hostname), port);
623*d5c9a868SElliott Hughes
624*d5c9a868SElliott Hughes if (sock == -1) {
625*d5c9a868SElliott Hughes #ifdef HAVE_SNPRINTF
626*d5c9a868SElliott Hughes snprintf(errmsg, 200,
627*d5c9a868SElliott Hughes "Can't connect to floppyd server on %s, port %i (%s)!",
628*d5c9a868SElliott Hughes hostname, port, strerror(errno));
629*d5c9a868SElliott Hughes #else
630*d5c9a868SElliott Hughes sprintf(errmsg,
631*d5c9a868SElliott Hughes "Can't connect to floppyd server on %s, port %i!",
632*d5c9a868SElliott Hughes hostname, port);
633*d5c9a868SElliott Hughes #endif
634*d5c9a868SElliott Hughes return -1;
635*d5c9a868SElliott Hughes }
636*d5c9a868SElliott Hughes
637*d5c9a868SElliott Hughes reply = authenticate_to_floppyd(floppyd, sock, display);
638*d5c9a868SElliott Hughes if(floppyd->version == FLOPPYD_PROTOCOL_VERSION_OLD)
639*d5c9a868SElliott Hughes break;
640*d5c9a868SElliott Hughes if(reply == AUTH_WRONGVERSION) {
641*d5c9a868SElliott Hughes /* fall back on old version */
642*d5c9a868SElliott Hughes floppyd->version = FLOPPYD_PROTOCOL_VERSION_OLD;
643*d5c9a868SElliott Hughes continue;
644*d5c9a868SElliott Hughes }
645*d5c9a868SElliott Hughes break;
646*d5c9a868SElliott Hughes }
647*d5c9a868SElliott Hughes
648*d5c9a868SElliott Hughes if (reply != 0) {
649*d5c9a868SElliott Hughes fprintf(stderr,
650*d5c9a868SElliott Hughes "Permission denied, authentication failed!\n"
651*d5c9a868SElliott Hughes "%s\n", AuthErrors[reply]);
652*d5c9a868SElliott Hughes return -1;
653*d5c9a868SElliott Hughes }
654*d5c9a868SElliott Hughes
655*d5c9a868SElliott Hughes free(hostname);
656*d5c9a868SElliott Hughes free(display);
657*d5c9a868SElliott Hughes
658*d5c9a868SElliott Hughes return sock;
659*d5c9a868SElliott Hughes }
660