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