xref: /aosp_15_r20/external/mtools/floppyd_io.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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