11/* $Id: torread.c 529 2009-09-11 08:44:53Z michael $ */
2- #include <fcntl.h>
3- #include <unistd.h>
4- #include <sys/stat.h>
5- #include <sys/mman.h>
62#include <stdint.h>
73#include <stdio.h>
84#include <stdlib.h>
5+ #include <malloc.h>
6+ #include <unistd.h>
97
108const uint8_t sp = ' ' ;
119const uint8_t ret = '\n' ;
@@ -20,27 +18,27 @@ const uint8_t eqv='=';
2018
2119enum obj_type {OBJ_NUL , OBJ_INT , OBJ_STR , OBJ_LST , OBJ_DCT };
2220
23- void Byte2Hex (uint8_t ch );
24- void PrintSpc (int num );
21+ void Byte2Hex (uint8_t ch , FILE * fdo );
22+ void PrintSpc (int num , FILE * fdo );
2523enum obj_type DetType (const uint8_t * d , size_t shift );
2624size_t FindSym (const uint8_t * d , uint8_t s , size_t shift , size_t len );
27- size_t PrintInt (const uint8_t * d , size_t shift , size_t len );
28- size_t PrintStr (const uint8_t * d , size_t shift , size_t len );
29- size_t PrintLst (const uint8_t * d , size_t shift , size_t len , int skip );
30- size_t PrintDct (const uint8_t * d , size_t shift , size_t len , int skip );
31- size_t PrintObj (const uint8_t * d , size_t shift , size_t len , int skip );
25+ size_t PrintInt (const uint8_t * d , size_t shift , size_t len , FILE * fdo );
26+ size_t PrintStr (const uint8_t * d , size_t shift , size_t len , FILE * fdo );
27+ size_t PrintLst (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo );
28+ size_t PrintDct (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo );
29+ size_t PrintObj (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo );
3230
33- void Byte2Hex (uint8_t ch )
31+ void Byte2Hex (uint8_t ch , FILE * fdo )
3432{
3533 static const uint8_t cnv []= {'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'A' ,'B' ,'C' ,'D' ,'E' ,'F' };
36- fwrite (cnv + (( ch & (15 << 4 )) >> 4 ), 1 , 1 , stdout );
37- fwrite (cnv + (ch & 15 ), 1 , 1 , stdout );
34+ fwrite (cnv + (( ch & (15 << 4 )) >> 4 ), 1 , 1 , fdo );
35+ fwrite (cnv + (ch & 15 ), 1 , 1 , fdo );
3836}
3937
40- void PrintSpc (int num )
38+ void PrintSpc (int num , FILE * fdo )
4139{
4240 int i ;
43- for (i = 0 ; i < num ; i ++ ) fwrite (& sp , 1 , 1 , stdout );
41+ for (i = 0 ; i < num ; i ++ ) fwrite (& sp , 1 , 1 , fdo );
4442}
4543
4644enum obj_type DetType (const uint8_t * d , size_t shift )
@@ -61,140 +59,167 @@ size_t FindSym(const uint8_t* d, uint8_t s, size_t shift, size_t len)
6159 exit (2 );
6260}
6361
64- size_t PrintObj (const uint8_t * d , size_t shift , size_t len , int skip )
62+ size_t PrintObj (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo )
6563{
6664 switch (DetType (d , shift ))
6765 {
6866 case (OBJ_NUL ):
6967 exit (2 );
7068 case (OBJ_INT ):
71- return PrintInt (d , shift , len );
69+ return PrintInt (d , shift , len , fdo );
7270 case (OBJ_STR ):
73- return PrintStr (d , shift , len );
71+ return PrintStr (d , shift , len , fdo );
7472 case (OBJ_LST ):
75- return PrintLst (d , shift , len , skip );
73+ return PrintLst (d , shift , len , skip , fdo );
7674 case (OBJ_DCT ):
77- return PrintDct (d , shift , len , skip );
75+ return PrintDct (d , shift , len , skip , fdo );
7876 }
7977 exit (2 );
8078}
8179
82- size_t PrintInt (const uint8_t * d , size_t shift , size_t len )
80+ size_t PrintInt (const uint8_t * d , size_t shift , size_t len , FILE * fdo )
8381{
8482 size_t e = FindSym (d , 'e' , shift , len );
85- fwrite (d + shift + 1 , e - shift - 1 , 1 , stdout );
83+ fwrite (d + shift + 1 , e - shift - 1 , 1 , fdo );
8684 return e + 1 ;
8785}
8886
89- size_t PrintStr (const uint8_t * d , size_t shift , size_t len )
87+ size_t PrintStr (const uint8_t * d , size_t shift , size_t len , FILE * fdo )
9088{
9189 size_t e = FindSym (d , ':' , shift , len );
9290 int l = atoi ((const char * )(d + shift ));
9391 if (e + l >= len ) exit (2 );
9492 size_t p ;
9593
96- fwrite (& quo , 1 , 1 , stdout );
94+ fwrite (& quo , 1 , 1 , fdo );
9795 for (p = e + 1 ; p <= e + l ; p ++ )
9896 {
9997 if (d [p ] == 127 || d [p ] < 32 )
10098 {
101- fwrite (& scr , 1 , 1 , stdout );
102- fwrite (& hxp , 1 , 1 , stdout );
103- Byte2Hex (d [p ]);
99+ fwrite (& scr , 1 , 1 , fdo );
100+ fwrite (& hxp , 1 , 1 , fdo );
101+ Byte2Hex (d [p ], fdo );
104102 }
105103 else if (d [p ] == '\\' )
106104 {
107- fwrite (& scr , 1 , 1 , stdout );
108- fwrite (& scr , 1 , 1 , stdout );
105+ fwrite (& scr , 1 , 1 , fdo );
106+ fwrite (& scr , 1 , 1 , fdo );
109107 }
110108 else if (d [p ] == '\"' )
111109 {
112- fwrite (& scr , 1 , 1 , stdout );
113- fwrite (& quo , 1 , 1 , stdout );
110+ fwrite (& scr , 1 , 1 , fdo );
111+ fwrite (& quo , 1 , 1 , fdo );
114112 }
115- else fwrite (d + p , 1 , 1 , stdout );
113+ else fwrite (d + p , 1 , 1 , fdo );
116114 }
117115
118- fwrite (& quo , 1 , 1 , stdout );
116+ fwrite (& quo , 1 , 1 , fdo );
119117 return e + l + 1 ;
120118}
121119
122- size_t PrintLst (const uint8_t * d , size_t shift , size_t len , int skip )
120+ size_t PrintLst (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo )
123121{
124122 size_t ishift = shift + 1 ;
125123
126- fwrite (& blst , 1 , 1 , stdout );
127- fwrite (& ret , 1 , 1 , stdout );
124+ fwrite (& blst , 1 , 1 , fdo );
125+ fwrite (& ret , 1 , 1 , fdo );
128126
129127 while (d [ishift ] != 'e' )
130128 {
131- PrintSpc (skip + 1 );
132- ishift = PrintObj (d , ishift , len , skip + 1 );
133- fwrite (& ret , 1 , 1 , stdout );
129+ PrintSpc (skip + 1 , fdo );
130+ ishift = PrintObj (d , ishift , len , skip + 1 , fdo );
131+ fwrite (& ret , 1 , 1 , fdo );
134132 if (ishift >= len ) exit (2 );
135133 }
136- PrintSpc (skip );
137- fwrite (& elst , 1 , 1 , stdout );
134+ PrintSpc (skip , fdo );
135+ fwrite (& elst , 1 , 1 , fdo );
138136 return ishift + 1 ;
139137}
140138
141- size_t PrintDct (const uint8_t * d , size_t shift , size_t len , int skip )
139+ size_t PrintDct (const uint8_t * d , size_t shift , size_t len , int skip , FILE * fdo )
142140{
143141 size_t ishift = shift + 1 ;
144142
145- fwrite (& bdct , 1 , 1 , stdout );
146- fwrite (& ret , 1 , 1 , stdout );
143+ fwrite (& bdct , 1 , 1 , fdo );
144+ fwrite (& ret , 1 , 1 , fdo );
147145
148146 while (d [ishift ] != 'e' )
149147 {
150- PrintSpc (skip + 1 );
148+ PrintSpc (skip + 1 , fdo );
151149 if (DetType (d , ishift ) != OBJ_STR ) exit (2 );
152- ishift = PrintStr (d , ishift , len );
153- fwrite (& sp , 1 , 1 , stdout );
154- fwrite (& eqv , 1 , 1 , stdout );
155- fwrite (& sp , 1 , 1 , stdout );
156- ishift = PrintObj (d , ishift , len , skip + 1 );
157- fwrite (& ret , 1 , 1 , stdout );
150+ ishift = PrintStr (d , ishift , len , fdo );
151+ fwrite (& sp , 1 , 1 , fdo );
152+ fwrite (& eqv , 1 , 1 , fdo );
153+ fwrite (& sp , 1 , 1 , fdo );
154+ ishift = PrintObj (d , ishift , len , skip + 1 , fdo );
155+ fwrite (& ret , 1 , 1 , fdo );
158156 if (ishift >= len ) exit (2 );
159157 }
160- PrintSpc (skip );
161- fwrite (& edct , 1 , 1 , stdout );
158+ PrintSpc (skip , fdo );
159+ fwrite (& edct , 1 , 1 , fdo );
162160 return ishift + 1 ;
163161}
164162
165163int main (int argc , char * * argv )
166164{
167- if (argc != 2 )
165+ if (argc < 3 )
168166 {
169- fprintf (stderr , "Usage: %s file.torrent > file.torrent. txt" , argv [0 ]);
167+ fprintf (stderr , "Usage: %s file.torrent file.txt\n " , argv [0 ]);
170168 return 1 ;
171169 }
172170
173- int fd ;
174- struct stat st ;
171+ FILE * fd , * fdo ;
175172 uint8_t * pdata ;
173+ size_t flen = 0 ;
176174
177- fd = open (argv [1 ],O_RDONLY );
178- if (fd == -1 )
175+ fd = fopen (argv [1 ],"rb" );
176+ if (fd == NULL )
179177 {
180178 fprintf (stderr , "ERROR: Can't open %s" , argv [1 ]);
181179 return 1 ;
182180 }
183- if (fstat (fd , & st ) != 0 )
181+ fdo = fopen (argv [2 ],"wb" );
182+ if (fdo == NULL )
184183 {
185- fprintf (stderr , "ERROR: Can't read %s" , argv [1 ]);
184+ fprintf (stderr , "ERROR: Can't write %s" , argv [2 ]);
186185 return 1 ;
187186 }
188- if (st .st_size == 0 )
187+
188+ fseek (fd ,0l ,SEEK_END );
189+ flen = ftell (fd );
190+ if (flen == 0 )
189191 {
190192 fprintf (stderr , "ERROR: File %s empty" , argv [1 ]);
191193 return 1 ;
192194 }
193- pdata = (uint8_t * ) mmap (0 , st .st_size , PROT_READ , MAP_SHARED , fd , 0 );
194- PrintDct (pdata , 0 , st .st_size , 0 );
195- fwrite (& ret , 1 , 1 , stdout );
196- munmap (pdata , st .st_size );
197- close (fd );
195+ if (flen > 16777216 )
196+ {
197+ printf ("Torrent metadata file %s is %ld bytes long.\n" ,argv [1 ],flen );
198+ printf ("That is unusually large for a torrent file. You may have specified an\n" );
199+ printf ("incorrect file. The metadata must be loaded into memory, so this may\n" );
200+ printf ("take some time or fail due to lack of memory.\n" );
201+ printf ("\n" );
202+ }
203+ rewind (fd );
204+
205+ pdata = malloc (flen );
206+ if (pdata == NULL )
207+ {
208+ printf ("Unable to malloc %ld bytes for torrent file\n" ,flen );
209+ return 2 ;
210+ }
211+ flen = fread (pdata ,1 ,flen ,fd );
212+ if (flen == 0 )
213+ {
214+ fprintf (stderr , "ERROR: File %s empty" , argv [1 ]);
215+ return 1 ;
216+ }
217+
218+ PrintDct (pdata , 0 , flen , 0 , fdo );
219+ fwrite (& ret , 1 , 1 , fdo );
220+ free (pdata );
221+ fclose (fd );
222+ fclose (fdo );
198223
199224 return 0 ;
200225}
0 commit comments