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