1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #ifndef NO_STRING_H
28 #include <string.h>
29 #else
30 #include <strings.h>
31 #endif
32 #include "timidity.h"
33 #include "mblock.h"
34 #include "zip.h"
35 #include "arc.h"
36
37 #define TARBLKSIZ 512
38 #define TARHDRSIZ 512
39
40 static long octal_value(char *s, int len);
41 static int tar_checksum(char *hdr);
42
next_tar_entry(void)43 ArchiveEntryNode *next_tar_entry(void)
44 {
45 char hdr[TARHDRSIZ];
46 long size, sizeb;
47 ArchiveEntryNode *entry;
48 URL url;
49 int flen;
50 int macbin_check;
51
52 url = arc_handler.url;
53 macbin_check = (arc_handler.counter == 0);
54
55 retry_read:
56 if(!macbin_check)
57 {
58 if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ)
59 return NULL;
60 }
61 else
62 {
63 int c = url_getc(url);
64 if(c == 0)
65 {
66 url_skip(url, 127);
67 if(arc_handler.isfile)
68 arc_handler.pos += 128;
69 if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ)
70 return NULL;
71 }
72 else
73 {
74 hdr[0] = c;
75 if(url_read(url, hdr+1, TARHDRSIZ-1) != TARHDRSIZ-1)
76 return NULL;
77 }
78 }
79
80 macbin_check = 0;
81
82 if(hdr[0] == '\0')
83 return NULL;
84 if(!tar_checksum(hdr))
85 return NULL;
86 size = octal_value(hdr + 124, 12);
87 flen = strlen(hdr);
88 if(size == 0 && flen > 0 && hdr[flen - 1] == '/')
89 {
90 if(arc_handler.isfile)
91 arc_handler.pos += TARHDRSIZ;
92 goto retry_read;
93 }
94
95 entry = new_entry_node(hdr, flen);
96 if(entry == NULL)
97 return NULL;
98 sizeb = (((size) + (TARBLKSIZ-1)) & ~(TARBLKSIZ-1));
99
100 if((arc_handler.isfile) || (size > MAX_SAFE_MALLOC_SIZE))
101 {
102 arc_handler.pos += TARHDRSIZ;
103 entry->comptype = ARCHIVEC_STORED;
104 entry->compsize = entry->origsize = size;
105 entry->start = arc_handler.pos;
106 url_skip(url, sizeb);
107 arc_handler.pos += sizeb;
108 }
109 else
110 {
111 void *data;
112 long n;
113
114 data = url_dump(url, size, &n);
115 if(size != n)
116 {
117 if(data != NULL)
118 free(data);
119 free_entry_node(entry);
120 return NULL;
121 }
122 entry->cache = arc_compress(data, size, ARC_DEFLATE_LEVEL,
123 &entry->compsize);
124 free(data);
125 entry->comptype = ARCHIVEC_DEFLATED;
126 entry->origsize = size;
127 entry->start = 0;
128 url_skip(url, sizeb - size);
129 }
130
131 return entry;
132 }
133
octal_value(char * s,int len)134 static long octal_value(char *s, int len)
135 {
136 long val;
137
138 while(len > 0 && !isdigit((int)(unsigned char)*s))
139 {
140 s++;
141 len--;
142 }
143
144 val = 0;
145 while(len > 0 && isdigit((int)(unsigned char)*s))
146 {
147 val = ((val<<3) | (*s - '0'));
148 s++;
149 len--;
150 }
151 return val;
152 }
153
tar_checksum(char * hdr)154 static int tar_checksum(char *hdr)
155 {
156 int i;
157
158 long recorded_sum;
159 long unsigned_sum; /* the POSIX one :-) */
160 long signed_sum; /* the Sun one :-( */
161
162 recorded_sum = octal_value(hdr + 148, 8);
163 unsigned_sum = 0;
164 signed_sum = 0;
165 for(i = 0; i < TARBLKSIZ; i++)
166 {
167 unsigned_sum += 0xFF & hdr[i];
168 signed_sum += hdr[i];
169 }
170
171 /* Adjust checksum to count the "chksum" field as blanks. */
172 for(i = 0; i < 8; i++)
173 {
174 unsigned_sum -= 0xFF & hdr[148 + i];
175 signed_sum -= hdr[i];
176 }
177 unsigned_sum += ' ' * 8;
178 signed_sum += ' ' * 8;
179
180 return unsigned_sum == recorded_sum || signed_sum == recorded_sum;
181 }
182