1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16 
17 #include "common.h"
18 #include "buffer.c"
19 
20 int
_check_buf(PerlIO * infile,Buffer * buf,int min_wanted,int max_wanted)21 _check_buf(PerlIO *infile, Buffer *buf, int min_wanted, int max_wanted)
22 {
23   int ret = 1;
24 
25   // Do we have enough data?
26   if ( buffer_len(buf) < min_wanted ) {
27     // Read more data
28     uint32_t read;
29     uint32_t actual_wanted;
30     unsigned char *tmp;
31 
32 #ifdef _MSC_VER
33     uint32_t pos_check = PerlIO_tell(infile);
34 #endif
35 
36     if (min_wanted > max_wanted) {
37       max_wanted = min_wanted;
38     }
39 
40     // Adjust actual amount to read by the amount we already have in the buffer
41     actual_wanted = max_wanted - buffer_len(buf);
42 
43     New(0, tmp, actual_wanted, unsigned char);
44 
45     DEBUG_TRACE("Buffering from file @ %d (min_wanted %d, max_wanted %d, adjusted to %d)\n",
46       (int)PerlIO_tell(infile), min_wanted, max_wanted, actual_wanted
47     );
48 
49     if ( (read = PerlIO_read(infile, tmp, actual_wanted)) <= 0 ) {
50       if ( PerlIO_error(infile) ) {
51         warn("Error reading: %s (wanted %d)\n", strerror(errno), actual_wanted);
52       }
53       else {
54         // Avoid printing this warning, let image format routines handle warnings and errors
55         //warn("Error: Unable to read at least %d bytes from file.\n", min_wanted);
56       }
57 
58       ret = 0;
59       goto out;
60     }
61 
62     buffer_append(buf, tmp, read);
63 
64     // Make sure we got enough
65     if ( buffer_len(buf) < min_wanted ) {
66       warn("Error: Unable to read at least %d bytes from file (only read %d).\n", min_wanted, read);
67       ret = 0;
68       goto out;
69     }
70 
71 #ifdef _MSC_VER
72     // Bug 16095, weird off-by-one bug seen only on Win32 and only when reading a filehandle
73     if (PerlIO_tell(infile) != pos_check + read) {
74       //PerlIO_printf(PerlIO_stderr(), "Win32 bug, pos should be %d, but was %d\n", pos_check + read, PerlIO_tell(infile));
75       PerlIO_seek(infile, pos_check + read, SEEK_SET);
76     }
77 #endif
78 
79     DEBUG_TRACE("Buffered %d bytes, new pos %d\n", read, (int)PerlIO_tell(infile));
80 
81 out:
82     Safefree(tmp);
83   }
84 
85   return ret;
86 }
87 
88 off_t
_file_size(PerlIO * infile)89 _file_size(PerlIO *infile)
90 {
91 #ifdef _MSC_VER
92   // Win32 doesn't work right with fstat
93   off_t file_size;
94 
95   PerlIO_seek(infile, 0, SEEK_END);
96   file_size = PerlIO_tell(infile);
97   PerlIO_seek(infile, 0, SEEK_SET);
98 
99   return file_size;
100 #else
101   struct stat buf;
102 
103   if ( !fstat( PerlIO_fileno(infile), &buf ) ) {
104     return buf.st_size;
105   }
106 
107   warn("Unable to stat: %s\n", strerror(errno));
108 
109   return 0;
110 #endif
111 }
112 
113 #ifdef AUDIO_SCAN_DEBUG
114 void
hexdump(unsigned char * data,uint32_t size)115 hexdump(unsigned char *data, uint32_t size)
116 {
117   unsigned char c;
118   int i = 1;
119   int n;
120   char bytestr[4] = {0};
121   char hexstr[ 16*3 + 5] = {0};
122   char charstr[16*1 + 5] = {0};
123 
124   if (!size) {
125     return;
126   }
127 
128   for (n = 0; n < size; n++) {
129     c = data[n];
130 
131     /* store hex str (for left side) */
132     snprintf(bytestr, sizeof(bytestr), "%02x ", c);
133     strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
134 
135     /* store char str (for right side) */
136     if (c < 21 || c > 0x7E) {
137       c = '.';
138     }
139     snprintf(bytestr, sizeof(bytestr), "%c", c);
140     strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
141 
142     if (i % 16 == 0) {
143       /* line completed */
144       PerlIO_printf(PerlIO_stderr(), "%-50.50s  %s\n", hexstr, charstr);
145       hexstr[0] = 0;
146       charstr[0] = 0;
147     }
148     i++;
149   }
150 
151   if (strlen(hexstr) > 0) {
152     /* print rest of buffer if not empty */
153     PerlIO_printf(PerlIO_stderr(), "%-50.50s  %s\n", hexstr, charstr);
154   }
155 }
156 #endif
157