1/*  Copyright 1996,1997,1999,2001-2003,2008,2009 Alain Knaff.
2 *  This file is part of mtools.
3 *
4 *  Mtools is free software: you can redistribute it and/or modify
5 *  it under the terms of the GNU General Public License as published by
6 *  the Free Software Foundation, either version 3 of the License, or
7 *  (at your option) any later version.
8 *
9 *  Mtools is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *  GNU General Public License for more details.
13 *
14 *  You should have received a copy of the GNU General Public License
15 *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "sysincludes.h"
19#include "msdos.h"
20#include "mtools.h"
21#include "codepage.h"
22
23typedef struct Filter_t {
24	Class_t *Class;
25	int refs;
26	Stream_t *Next;
27	Stream_t *Buffer;
28
29	int dospos;
30	int unixpos;
31	int mode;
32	int rw;
33	int lastchar;
34	/* int convertCharset; */
35} Filter_t;
36
37#define F_READ 1
38#define F_WRITE 2
39
40/* read filter filters out messy dos' bizarre end of lines and final 0x1a's */
41
42static int read_filter(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len)
43{
44	DeclareThis(Filter_t);
45	int i,j,ret;
46	unsigned char newchar;
47
48	off_t where = truncBytes32(iwhere);
49
50	if ( where != This->unixpos ){
51		fprintf(stderr,"Bad offset\n");
52		exit(1);
53	}
54	if (This->rw == F_WRITE){
55		fprintf(stderr,"Change of transfer direction!\n");
56		exit(1);
57	}
58	This->rw = F_READ;
59
60	ret = READS(This->Next, buf, (mt_off_t) This->dospos, len);
61	if ( ret < 0 )
62		return ret;
63
64	j = 0;
65	for (i=0; i< ret; i++){
66		if ( buf[i] == '\r' )
67			continue;
68		if (buf[i] == 0x1a)
69			break;
70		newchar = buf[i];
71		/*
72		if (This->convertCharset) newchar = contents_to_unix(newchar);
73		*/
74		This->lastchar = buf[j++] = newchar;
75	}
76
77	This->dospos += i;
78	This->unixpos += j;
79	return j;
80}
81
82static int write_filter(Stream_t *Stream, char *buf, mt_off_t iwhere,
83						size_t len)
84{
85	DeclareThis(Filter_t);
86	unsigned int i,j;
87	int ret;
88	char buffer[1025];
89	unsigned char newchar;
90
91	off_t where = truncBytes32(iwhere);
92
93	if(This->unixpos == -1)
94		return -1;
95
96	if (where != This->unixpos ){
97		fprintf(stderr,"Bad offset\n");
98		exit(1);
99	}
100
101	if (This->rw == F_READ){
102		fprintf(stderr,"Change of transfer direction!\n");
103		exit(1);
104	}
105	This->rw = F_WRITE;
106
107	j=i=0;
108	while(i < 1024 && j < len){
109		if (buf[j] == '\n' ){
110			buffer[i++] = '\r';
111			buffer[i++] = '\n';
112			j++;
113			continue;
114		}
115		newchar = buf[j++];
116		/*
117		if (This->convertCharset) newchar = to_dos(newchar);
118		*/
119		buffer[i++] = newchar;
120	}
121	This->unixpos += j;
122
123	ret = force_write(This->Next, buffer, (mt_off_t) This->dospos, i);
124	if(ret >0 )
125		This->dospos += ret;
126	if ( ret != (signed int) i ){
127		/* no space on target file ? */
128		This->unixpos = -1;
129		return -1;
130	}
131	return j;
132}
133
134static int free_filter(Stream_t *Stream)
135{
136	DeclareThis(Filter_t);
137	char buffer=0x1a;
138
139	/* write end of file */
140	if (This->rw == F_WRITE)
141		return force_write(This->Next, &buffer, (mt_off_t) This->dospos, 1);
142	else
143		return 0;
144}
145
146static Class_t FilterClass = {
147	read_filter,
148	write_filter,
149	0, /* flush */
150	free_filter,
151	0, /* set geometry */
152	get_data_pass_through,
153	0
154};
155
156Stream_t *open_filter(Stream_t *Next, int convertCharset)
157{
158	Filter_t *This;
159
160	This = New(Filter_t);
161	if (!This)
162		return NULL;
163	This->Class = &FilterClass;
164	This->dospos = This->unixpos = This->rw = 0;
165	This->Next = Next;
166	This->refs = 1;
167	This->Buffer = 0;
168	/*
169	  This->convertCharset = convertCharset;
170	*/
171
172	return (Stream_t *) This;
173}
174