Merge pull request #12 from davel/davel/sqsh
[debian-nspark.git] / io.c
blob2297e3f59bfd653d3d2130c3b09f943d659a9514
2 /*
3 * file input/output
5 * $Header: io.c 1.14 95/08/01 $
6 * $Log: io.c,v $
7 * Revision 1.14 95/08/01 xx:xx:xx BB
8 * Fixed for Borland C/C++
10 * Revision 1.13 94/12/12 17:30:45 arb
11 * Added code for ArcFS outputsize checking
13 * Revision 1.12 93/08/20 12:31:20 arb
14 * Added code for ArcFS archive headers
16 * Revision 1.11 93/08/20 10:30:50 arb
17 * Added code for -C option to convert filenames to lowercase
19 * Revision 1.10 93/08/20 10:30:51 arb
20 * Changed read_header() to allow top-bit-set characters in RISCOS filenames
22 * Revision 1.9 93/03/05 14:44:02 arb
23 * Added <string.h> for RISCOS, needed for memset
25 * Revision 1.8 92/12/09 11:40:30 duplain
26 * Changed ret in check_stream() from type int. #ifdef'd out write_halfword()
27 * and write_word().
29 * Revision 1.7 92/12/07 17:18:25 duplain
30 * reformatted source.
32 * Revision 1.6 92/11/04 16:57:49 duplain
33 * Changed read_header() so it doesn't read the load/exec/attr fields if
34 * PC archive file.
36 * Revision 1.5 92/10/07 10:36:56 duplain
37 * Changed order of function so no need to include "io.h" (gcc
38 * complained on some platforms).
40 * Revision 1.4 92/10/05 11:01:07 duplain
41 * Recoded write_word() and write_halfword(). read_header() now clears the
42 * header structure prior to reading data into it.
44 * Revision 1.3 92/10/02 17:41:49 duplain
45 * Fixed read_header() so it returns immediately if comptype & 0x7f == 0.
47 * Revision 1.2 92/10/01 11:20:32 duplain
48 * Moved reading of STARTBYTE to unarc.c .
50 * Revision 1.1 92/09/29 18:02:19 duplain
51 * Initial revision
55 #include <stdio.h>
56 #include <ctype.h>
57 #include <string.h>
58 #include "spark.h"
59 #include "main.h"
60 #include "error.h"
61 #include "arcfs.h"
63 #ifdef RISCOS /* next line RISC OS only */
64 #define isascii(x) 1
65 #endif /* RISCOS */
67 #include "nsparkio.h"
71 * check for EOF or write/read errors on stream.
73 Ferror
74 check_stream(FILE *fp)
76 Ferror ret = FNOERR;
78 if (feof(fp))
79 ret = FEND;
80 else if (ferror(fp))
81 ret = FRWERR;
82 if (ret != FNOERR)
83 clearerr(fp);
84 return (ret);
88 * read a byte from the input stream.
90 Byte
91 read_byte(FILE *ifp)
93 return ((Byte) getc(ifp));
97 * read a little-endian 2-byte halfword from the input stream.
99 Halfword
100 read_halfword(FILE *ifp)
102 union
104 Halfword h;
105 Byte b[sizeof(Halfword)];
107 ret;
109 if (fread((char *) &ret.h, 1, sizeof(Halfword), ifp)!=sizeof(Halfword)) {
110 error("Read error!");
112 #if defined(__MSDOS__)
113 /* MSDOS reads bytes in the correct order. Save a bit of time
114 * by returning the value */
115 return (ret.h);
116 #else
117 /* Ensure the data is in the correct order */
118 return (ret.b[0] | ret.b[1] << 8);
119 #endif
123 * read a little-endian 4-byte word from the input stream.
125 Word
126 read_word(FILE *ifp)
128 union
130 Word w;
131 Byte b[sizeof(Word)];
133 ret;
135 if (fread((char *) &ret.w, 1, sizeof(Word), ifp)!=sizeof(Word)) {
136 error("Read error!");
138 #if defined(__MSDOS__)
139 /* MSDOS reads bytes in the correct order. Save a bit of time
140 * by returning the value */
141 return (ret.w);
142 #else
143 /* Ensure the data is in the correct order */
144 return (ret.b[0] | (ret.b[1] << 8) | (ret.b[2] << 16) | (ret.b[3] << 24));
145 #endif
149 * write a byte to the output stream.
151 void
152 write_byte(FILE *ofp, Byte byte)
154 if (writesize-- > 0)
155 putc((int) byte, ofp);
158 #ifdef notyet
161 * write a little-endian 2-byte halfword to the output stream.
163 void
164 write_halfword(FILE *ofp, Halfword halfword)
166 write_byte(ofp, halfword & 0xff);
167 write_byte(ofp, (halfword >> 8) & 0xff);
171 * write a little-endian 4-byte word to the output stream.
173 void
174 write_word(FILE *ofp, Word word)
176 write_byte(ofp, word & 0xff);
177 write_byte(ofp, (word >> 8) & 0xff);
178 write_byte(ofp, (word >> 16) & 0xff);
179 write_byte(ofp, (word >> 24) & 0xff);
182 #endif /* notyet */
185 * read a compression-header from the file
187 Header *
188 read_header(FILE *ifp)
190 static Header header;
191 register int i;
192 register char *cptr;
193 Byte byte;
195 memset((char *) &header, '\0', sizeof(header));
197 if (arcfs)
198 return (arcfs_read_header(ifp));
200 header.comptype = read_byte(ifp);
201 if (!(header.comptype & ~ARCHPACK))
202 return (&header); /* EOF */
204 for (i = 0, cptr = header.name; i <= 12; i++, cptr++)
206 byte = read_byte(ifp);
207 #ifdef RISCOS
208 if (byte < ' ')
209 #else
210 if (byte < ' ' || byte > '~')
211 #endif
212 byte = '\0';
213 else if (byte == PATHSEP) /* illegal in filename */
214 byte = '_';
215 *cptr = byte;
217 *cptr = '\0'; /* null terminate */
218 if (singlecase)
220 for (i = 0, cptr = header.name; i <= 12; i++, cptr++)
221 if (isascii(*cptr) && isupper(*cptr))
222 *cptr = tolower(*cptr);
225 header.complen = read_word(ifp);
226 header.date = read_halfword(ifp);
227 header.time = read_halfword(ifp);
228 header.crc = read_halfword(ifp);
229 if ((header.comptype & ~ARCHPACK) > CT_NOTCOMP)
230 header.origlen = read_word(ifp);
231 else
232 header.origlen = header.complen;
233 if (header.comptype & ARCHPACK)
235 header.load = read_word(ifp);
236 header.exec = read_word(ifp);
237 header.attr = read_word(ifp);
240 if (check_stream(ifp) == FRWERR)
241 return (NULL);
242 return (&header);
245 Status
246 read_sqsh_header(FILE *fp, SqshHeader *header)
248 if (fread(header->magic, 1, 4, fp) != 4)
250 return RERR;
252 if (strncmp(header->magic, "SQSH", 4) != 0)
254 error("Not a RISC OS squash file");
255 return RERR;
257 header->origlen = read_word(fp);
258 header->load = read_word(fp);
259 header->exec = read_word(fp);
260 header->reserved = read_word(fp);
262 return NOERR;
265 void
266 sqsh_header_to_header(SqshHeader *sqsh_header, Header *header)
268 header->load = sqsh_header->load;
269 header->exec = sqsh_header->exec;
270 header->origlen = sqsh_header->origlen;
271 arcfs_fixtime(header);