Fixed some issues found by winapi_check.
[wine] / tools / bin2res.c
1 /************************************************
2  *
3  * Converting binary resources from/to *.rc files
4  *
5  * Copyright 1999 Juergen Schmied
6  *
7  * 11/99 first release
8  */
9
10 #include "config.h"
11
12 #ifdef HAVE_SYS_PARAM_H
13 # include <sys/param.h>
14 #endif
15 #include <sys/types.h>
16 #include <sys/stat.h>
17
18 #include <ctype.h>
19 #include <string.h>
20
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include <fcntl.h>
25 #include <unistd.h>
26 #ifdef HAVE_SYS_MMAN_H
27 # include <sys/mman.h>
28 #endif
29 #include "winuser.h"
30
31 extern char*   g_lpstrFileName;
32
33 /* global options */
34
35 char*   g_lpstrFileName = NULL;
36 char*   g_lpstrInputFile = NULL;
37 int     b_to_binary = 0;
38 int     b_force_overwrite = 0;
39 LPBYTE p_in_file = NULL;
40
41 static char*    errorOpenFile = "Unable to open file.\n";
42 static char*    errorRCFormat = "Unexpexted syntax in rc file line %i\n";
43
44 void usage(void)
45 {
46     printf("Usage: bin2res [-d bin] [input file]\n");
47     printf("  -d bin convert a *.res back to a binary\n");
48     printf("  -f force overwriting newer files\n");
49     exit(-1);
50 }
51
52 void parse_options(int argc, char **argv)
53 {
54   int i;
55
56   switch( argc )
57   {
58     case 2:
59          g_lpstrInputFile = argv[1];
60          break;
61
62     case 3:
63     case 4:
64     case 5:
65          for( i = 1; i < argc - 1; i++ )
66          {
67            if( argv[i][0] != '-' ||
68                strlen(argv[i]) != 2 ) break;
69
70            if( argv[i][1] == 'd')
71            {
72              if (strcmp ("bin", argv[i+1])==0)
73              {
74                b_to_binary =1;
75                i++;
76              }
77              else
78              {
79                usage();
80              }
81              
82            }
83            else if ( argv[i][1] == 'f')
84            {
85              b_force_overwrite = 1;
86            }
87            else
88            {
89              usage();
90            }
91          } 
92          if( i == argc - 1 )
93          {
94            g_lpstrInputFile = argv[i];
95            break;
96          }
97     default: usage();
98   }
99 }
100
101 int insert_hex (char * infile, FILE * outfile)
102 {
103         int i;
104         int             fd;
105         struct stat     st;
106
107         if( (fd = open( infile, O_RDONLY))==-1 ) 
108         {
109           fprintf(stderr, errorOpenFile );
110           exit(1);
111         }
112         if ((fstat(fd, &st) == -1) || (p_in_file = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
113         {
114           fprintf(stderr, errorOpenFile );
115           close(fd);
116           exit(1);
117         }
118
119         fprintf (outfile, "{\n '");
120         i = 0;
121         while (1)
122         {
123           fprintf(outfile, "%02X", p_in_file[i]);
124           if (++i >= st.st_size) break;
125           fprintf(outfile, "%s", (i == (i & 0xfffffff0)) ? "'\n '" :" ");
126         }
127         fprintf (outfile, "'\n}");
128         munmap(p_in_file, st.st_size);
129         close(fd);
130         return 1;       
131 }
132
133 int convert_to_res ()
134 {
135         FILE    *fin, *ftemp;
136         char    buffer[255];
137         char    infile[255];
138         char    tmpfile[L_tmpnam];
139         char    *pos;
140         int     c, len;
141         struct stat     st;
142         int line = 0;
143         time_t  tinput;
144         long startpos, endpos;
145
146         strcpy( tmpfile, g_lpstrInputFile );
147         strcat( tmpfile, "-tmp" );
148         /* FIXME: should use better tmp name and create with O_EXCL */
149         if( (ftemp = fopen( tmpfile, "w")) == NULL ) goto error_open_file;
150         
151         if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
152         tinput = st.st_ctime;
153         
154         while ( NULL != fgets(buffer, 255, fin))
155         {
156           fputs(buffer, ftemp);
157           line++;
158           if ( (pos = strstr(buffer, "BINRES")) != NULL)
159           {
160             /* get the out-file name */
161             len = 0; pos += 6; startpos=0; endpos=0;
162             while ( *pos == ' ') pos++;
163             while ( pos[len] != ' ') len++;
164             strncpy(infile, pos, len);
165             infile[len]=0;
166             
167             if ( (!stat(infile, &st) && st.st_ctime > tinput) || b_force_overwrite)
168             {
169               /* write a output file */
170               printf("[%s:c]", infile);
171               while((c = fgetc(fin))!='{' && c != EOF) fputc(c, ftemp);
172               if (c == EOF ) goto error_rc_format;
173               while((c = fgetc(fin))!='}' && c != EOF);
174               if (c == EOF ) goto error_rc_format;
175
176               insert_hex(infile, ftemp);
177             }
178             else
179             {
180               printf("[%s:s]", infile);
181             }
182           }
183         }
184         
185         fclose(fin);
186         fclose(ftemp);
187         if (rename(tmpfile, g_lpstrInputFile) == -1)
188         {
189             perror("rename");
190             unlink(tmpfile);
191             return 0;
192         }
193         return 1;       
194
195 error_open_file:
196         fprintf(stderr, errorOpenFile );
197         return 0;
198
199 error_rc_format:        
200         fprintf(stderr, errorRCFormat, line);
201         return 0;
202 }
203
204 int convert_to_bin()
205 {
206         FILE    *fin, *fout;
207         char    buffer[255];
208         char    outfile[255];
209         char    *pos;
210         int     len, index, in_resource;
211         unsigned int    byte;
212         struct stat     st;
213         int line = 0;
214         time_t  tinput;
215                 
216         if( (fin = fopen( g_lpstrInputFile, "r")) == NULL || stat(g_lpstrInputFile, &st)) goto error_open_file;
217         tinput = st.st_ctime;
218         
219         while ( NULL != fgets(buffer, 255, fin))
220         {
221           line++;
222           if ( (pos = strstr(buffer, "BINRES")) != NULL)
223           {
224             /* get the out-file name */
225             len = 0; pos += 6;
226             while ( *pos == ' ') pos++;
227             while ( pos[len] != ' ') len++;
228             strncpy(outfile, pos, len);
229             outfile[len]=0;
230             
231             if ( stat(outfile, &st) || st.st_ctime < tinput || b_force_overwrite)
232             {
233               /* write a output file */
234               printf("[%s:c]", outfile);
235               if ( (fout = fopen( outfile, "w")) == NULL) goto error_open_file;
236
237               in_resource = 0;
238               while (1)
239               {
240                 if ( NULL == fgets(buffer, 255, fin)) goto error_rc_format;
241                 line++;
242
243                 /* parse a line */
244                 for ( index = 0; buffer[index] != 0; index++ )
245                 {
246                   if ( ! in_resource )
247                   {
248                     if ( buffer[index] == '{' ) in_resource = 1;
249                     continue;
250                   }
251
252                   if ( buffer[index] == ' ' || buffer[index] == '\''|| buffer[index] == '\n' ) continue;
253                   if ( buffer[index] == '}' ) goto end_of_resource;
254                   if ( ! isxdigit(buffer[index])) goto error_rc_format;
255                   index += sscanf(&buffer[index], "%02x", &byte);
256                   fputc(byte, fout);
257                 }  
258               }
259               fclose(fout);
260             }
261             else
262             {
263               printf("[%s:s]", outfile);
264             }
265 end_of_resource:            
266           }
267         }
268         
269         fclose(fin);
270         return 1;       
271
272 error_open_file:
273         fprintf(stderr, errorOpenFile );
274         return 0;
275
276 error_rc_format:        
277         fprintf(stderr, errorRCFormat, line);
278         return 0;
279 }
280
281 int main(int argc, char **argv)
282 {
283         parse_options( argc, argv);
284
285         if (b_to_binary == 0)
286         {
287           convert_to_res();
288         }
289         else
290         {
291           convert_to_bin();
292         }
293         printf("\n");
294         return 0;
295 }