/* resres.c: read_res_file and write_res_file implementation for windres.
-
- Copyright 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998-2016 Free Software Foundation, Inc.
Written by Anders Norlander <anorland@hem2.passagen.se>.
+ Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
+/* FIXME: This file does not work correctly in a cross configuration.
+ It assumes that it can use fread and fwrite to read and write
+ integers. It does no swapping. */
+#include "sysdep.h"
+#include "bfd.h"
+#include "bucomm.h"
+#include "libiberty.h"
#include "windres.h"
-struct res_hdr
- {
- unsigned long data_size;
- unsigned long header_size;
- };
-
-static void write_res_directory
- PARAMS ((const struct res_directory *,
- const struct res_id *, const struct res_id *,
- int *, int));
-static void write_res_resource
- PARAMS ((const struct res_id *, const struct res_id *,
- const struct res_resource *, int *));
-static void write_res_bin
- PARAMS ((const struct res_resource *, const struct res_id *,
- const struct res_id *, const struct res_res_info *));
-
-static void write_res_id PARAMS ((const struct res_id *));
-static void write_res_info PARAMS ((const struct res_res_info *));
-static void write_res_data PARAMS ((const void *, size_t, int));
-static void write_res_header
- PARAMS ((unsigned long, const struct res_id *, const struct res_id *,
- const struct res_res_info *));
-
-static int read_resource_entry PARAMS ((void));
-static void read_res_data PARAMS ((void *, size_t, int));
-static void read_res_id PARAMS ((struct res_id *));
-static unichar *read_unistring PARAMS ((int *));
-static void skip_null_resource PARAMS ((void));
-
-static unsigned long get_id_size PARAMS ((const struct res_id *));
-static void res_align_file PARAMS ((void));
+#include <assert.h>
-static void
- res_add_resource
- PARAMS ((struct res_resource *, const struct res_id *,
- const struct res_id *, int, int));
+static rc_uint_type write_res_directory (windres_bfd *, rc_uint_type,
+ const rc_res_directory *, const rc_res_id *,
+ const rc_res_id *, rc_uint_type *, int);
+static rc_uint_type write_res_resource (windres_bfd *, rc_uint_type,const rc_res_id *,
+ const rc_res_id *, const rc_res_resource *,
+ rc_uint_type *);
+static rc_uint_type write_res_bin (windres_bfd *, rc_uint_type, const rc_res_resource *,
+ const rc_res_id *, const rc_res_id *,
+ const rc_res_res_info *);
-void
- res_append_resource
- PARAMS ((struct res_directory **, struct res_resource *,
- int, const struct res_id *, int));
+static rc_uint_type write_res_id (windres_bfd *, rc_uint_type, const rc_res_id *);
+static rc_uint_type write_res_info (windres_bfd *, rc_uint_type, const rc_res_res_info *);
+static rc_uint_type write_res_data_hdr (windres_bfd *, rc_uint_type, res_hdr *);
+
+static rc_uint_type write_res_header (windres_bfd *, rc_uint_type, rc_uint_type,
+ const rc_res_id *, const rc_res_id *,
+ const rc_res_res_info *);
+
+static int read_resource_entry (windres_bfd *, rc_uint_type *, rc_uint_type);
+static void read_res_data (windres_bfd *, rc_uint_type *, rc_uint_type, void *,
+ rc_uint_type);
+static void read_res_data_hdr (windres_bfd *, rc_uint_type *, rc_uint_type, res_hdr *);
+static void read_res_id (windres_bfd *, rc_uint_type *, rc_uint_type, rc_res_id *);
+static unichar *read_unistring (windres_bfd *, rc_uint_type *, rc_uint_type, rc_uint_type *);
+static void skip_null_resource (windres_bfd *, rc_uint_type *, rc_uint_type);
+static int probe_binary (windres_bfd *wrbfd, rc_uint_type);
-static struct res_directory *resources = NULL;
+static unsigned long get_id_size (const rc_res_id *);
+
+static void res_add_resource (rc_res_resource *, const rc_res_id *,
+ const rc_res_id *, rc_uint_type, int);
+
+static void res_append_resource (rc_res_directory **, rc_res_resource *,
+ int, const rc_res_id *, int);
+
+static rc_res_directory *resources = NULL;
-static FILE *fres;
static const char *filename;
extern char *program_name;
/* Read resource file */
-struct res_directory *
-read_res_file (fn)
- const char *fn;
+rc_res_directory *
+read_res_file (const char *fn)
{
+ rc_uint_type off, flen;
+ windres_bfd wrbfd;
+ bfd *abfd;
+ asection *sec;
filename = fn;
- fres = fopen (filename, "rb");
- if (fres == NULL)
- fatal ("can't open `%s' for output: %s", filename, strerror (errno));
- skip_null_resource ();
+ flen = (rc_uint_type) get_file_size (filename);
+ if (! flen)
+ fatal ("can't open '%s' for input.", filename);
+ abfd = windres_open_as_binary (filename, 1);
+ sec = bfd_get_section_by_name (abfd, ".data");
+ if (sec == NULL)
+ bfd_fatal ("bfd_get_section_by_name");
+ set_windres_bfd (&wrbfd, abfd, sec,
+ (target_is_bigendian ? WR_KIND_BFD_BIN_B
+ : WR_KIND_BFD_BIN_L));
+ off = 0;
+
+ if (! probe_binary (&wrbfd, flen))
+ set_windres_bfd_endianness (&wrbfd, ! target_is_bigendian);
- while (read_resource_entry ())
+ skip_null_resource (&wrbfd, &off, flen);
+
+ while (read_resource_entry (&wrbfd, &off, flen))
;
- fclose (fres);
+ bfd_close (abfd);
return resources;
}
/* Write resource file */
void
-write_res_file (fn, resdir)
- const char *fn;
- const struct res_directory *resdir;
+write_res_file (const char *fn,const rc_res_directory *resdir)
{
- int language;
- static const unsigned char sign[] =
+ asection *sec;
+ rc_uint_type language;
+ bfd *abfd;
+ windres_bfd wrbfd;
+ unsigned long sec_length = 0,sec_length_wrote;
+ static const bfd_byte sign[] =
{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- long fpos;
- struct res_entry *e;
- int i;
filename = fn;
- fres = fopen (filename, "wb");
- if (fres == NULL)
- fatal ("can't open `%s' for output: %s", filename, strerror (errno));
-
- /* Write 32 bit resource signature */
- write_res_data (sign, sizeof (sign), 1);
+ abfd = windres_open_as_binary (filename, 0);
+ sec = bfd_make_section_with_flags (abfd, ".data",
+ (SEC_HAS_CONTENTS | SEC_ALLOC
+ | SEC_LOAD | SEC_DATA));
+ if (sec == NULL)
+ bfd_fatal ("bfd_make_section");
+ /* Requiring this is probably a bug in BFD. */
+ sec->output_section = sec;
- /* write resources */
+ set_windres_bfd (&wrbfd, abfd, sec,
+ (target_is_bigendian ? WR_KIND_BFD_BIN_B
+ : WR_KIND_BFD_BIN_L));
language = -1;
- write_res_directory (resdir, (const struct res_id *) NULL,
- (const struct res_id *) NULL, &language, 1);
-
- /* end file on DWORD boundary */
- fpos = ftell (fres);
- if (fpos % 4)
- write_res_data (sign, fpos % 4, 1);
-
- fclose (fres);
+ sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir,
+ (const rc_res_id *) NULL,
+ (const rc_res_id *) NULL, &language, 1);
+ if (! bfd_set_section_size (abfd, sec, (sec_length + 3) & ~3))
+ bfd_fatal ("bfd_set_section_size");
+ if ((sec_length & 3) != 0)
+ set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3));
+ set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign));
+ language = -1;
+ sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir,
+ (const rc_res_id *) NULL,
+ (const rc_res_id *) NULL,
+ &language, 1);
+ if (sec_length != sec_length_wrote)
+ fatal ("res write failed with different sizes (%lu/%lu).",
+ (unsigned long) sec_length, (unsigned long) sec_length_wrote);
+
+ bfd_close (abfd);
+ return;
}
/* Read a resource entry, returns 0 when all resources are read */
static int
-read_resource_entry (void)
+read_resource_entry (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
{
- struct res_id type;
- struct res_id name;
- struct res_res_info resinfo;
- struct res_hdr reshdr;
- enum res_type rtype;
- long version;
- long n;
+ rc_res_id type;
+ rc_res_id name;
+ rc_res_res_info resinfo;
+ res_hdr reshdr;
void *buff;
- struct res_resource *r;
+ rc_res_resource *r;
+ struct bin_res_info l;
- res_align_file ();
+ off[0] = (off[0] + 3) & ~3;
/* Read header */
- if (fread (&reshdr, sizeof (reshdr), 1, fres) != 1)
+ if ((off[0] + 8) > omax)
return 0;
+ read_res_data_hdr (wrbfd, off, omax, &reshdr);
/* read resource type */
- read_res_id (&type);
+ read_res_id (wrbfd, off, omax, &type);
/* read resource id */
- read_res_id (&name);
+ read_res_id (wrbfd, off, omax, &name);
- res_align_file ();
+ off[0] = (off[0] + 3) & ~3;
/* Read additional resource header */
- read_res_data (&resinfo.version, sizeof (resinfo.version), 1);
- read_res_data (&resinfo.memflags, sizeof (resinfo.memflags), 1);
- read_res_data (&resinfo.language, sizeof (resinfo.language), 1);
- read_res_data (&version, sizeof (version), 1);
- read_res_data (&resinfo.characteristics, sizeof (resinfo.characteristics), 1);
+ read_res_data (wrbfd, off, omax, &l, BIN_RES_INFO_SIZE);
+ resinfo.version = windres_get_32 (wrbfd, l.version, 4);
+ resinfo.memflags = windres_get_16 (wrbfd, l.memflags, 2);
+ resinfo.language = windres_get_16 (wrbfd, l.language, 2);
+ /* resinfo.version2 = windres_get_32 (wrbfd, l.version2, 4); */
+ resinfo.characteristics = windres_get_32 (wrbfd, l.characteristics, 4);
- res_align_file ();
+ off[0] = (off[0] + 3) & ~3;
/* Allocate buffer for data */
buff = res_alloc (reshdr.data_size);
/* Read data */
- read_res_data (buff, reshdr.data_size, 1);
+ read_res_data (wrbfd, off, omax, buff, reshdr.data_size);
/* Convert binary data to resource */
- r = bin_to_res (type, buff, reshdr.data_size, 0);
+ r = bin_to_res (wrbfd, type, buff, reshdr.data_size);
r->res_info = resinfo;
/* Add resource to resource directory */
res_add_resource (r, &type, &name, resinfo.language, 0);
}
/* write resource directory to binary resource file */
-static void
-write_res_directory (rd, type, name, language, level)
- const struct res_directory *rd;
- const struct res_id *type;
- const struct res_id *name;
- int *language;
- int level;
+static rc_uint_type
+write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_directory *rd,
+ const rc_res_id *type, const rc_res_id *name, rc_uint_type *language,
+ int level)
{
- const struct res_entry *re;
+ const rc_res_entry *re;
for (re = rd->entries; re != NULL; re = re->next)
{
case 2:
/* If we're at level 2, the key of this resource is the name
- we are going to use in the rc printout. */
+ we are going to use in the rc printout. */
name = &re->id;
break;
case 3:
/* If we're at level 3, then this key represents a language.
Use it to update the current language. */
- if (!re->id.named
- && re->id.u.id != *language
+ if (! re->id.named
+ && re->id.u.id != (unsigned long) *language
&& (re->id.u.id & 0xffff) == re->id.u.id)
{
*language = re->id.u.id;
}
if (re->subdir)
- write_res_directory (re->u.dir, type, name, language, level + 1);
+ off = write_res_directory (wrbfd, off, re->u.dir, type, name, language,
+ level + 1);
else
{
if (level == 3)
2, and represents the name to use. We probably just
set LANGUAGE, and it will probably match what the
resource itself records if anything. */
- write_res_resource (type, name, re->u.res, language);
+ off = write_res_resource (wrbfd, off, type, name, re->u.res,
+ language);
}
else
{
fprintf (stderr, "// Resource at unexpected level %d\n", level);
- write_res_resource (type, (struct res_id *) NULL, re->u.res,
- language);
+ off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL,
+ re->u.res, language);
}
}
}
+ return off;
}
-static void
-write_res_resource (type, name, res, language)
- const struct res_id *type;
- const struct res_id *name;
- const struct res_resource *res;
- int *language;
+static rc_uint_type
+write_res_resource (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *type,
+ const rc_res_id *name, const rc_res_resource *res,
+ rc_uint_type *language ATTRIBUTE_UNUSED)
{
int rt;
case RES_TYPE_VERSIONINFO:
rt = RT_VERSION;
break;
+
+ case RES_TYPE_TOOLBAR:
+ rt = RT_TOOLBAR;
+ break;
}
if (rt != 0
&& type != NULL
- && (type->named || type->u.id != rt))
+ && (type->named || type->u.id != (unsigned long) rt))
{
fprintf (stderr, "// Unexpected resource type mismatch: ");
res_id_print (stderr, *type, 1);
abort ();
}
- write_res_bin (res, type, name, &res->res_info);
- return;
+ return write_res_bin (wrbfd, off, res, type, name, &res->res_info);
}
/* Write a resource in binary resource format */
-static void
-write_res_bin (res, type, name, resinfo)
- const struct res_resource *res;
- const struct res_id *type;
- const struct res_id *name;
- const struct res_res_info *resinfo;
+static rc_uint_type
+write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res,
+ const rc_res_id *type, const rc_res_id *name,
+ const rc_res_res_info *resinfo)
{
- unsigned long datasize = 0;
- const struct bindata *bin_rep, *data;
-
- bin_rep = res_to_bin (res, 0);
- for (data = bin_rep; data != NULL; data = data->next)
- datasize += data->length;
+ rc_uint_type noff;
+ rc_uint_type datasize = 0;
- write_res_header (datasize, type, name, resinfo);
+ noff = res_to_bin ((windres_bfd *) NULL, off, res);
+ datasize = noff - off;
- for (data = bin_rep; data != NULL; data = data->next)
- write_res_data (data->data, data->length, 1);
+ off = write_res_header (wrbfd, off, datasize, type, name, resinfo);
+ return res_to_bin (wrbfd, off, res);
}
/* Get number of bytes needed to store an id in binary format */
static unsigned long
get_id_size (id)
- const struct res_id *id;
+ const rc_res_id *id;
{
if (id->named)
return sizeof (unichar) * (id->u.n.length + 1);
}
/* Write a resource header */
-static void
-write_res_header (datasize, type, name, resinfo)
- unsigned long datasize;
- const struct res_id *type;
- const struct res_id *name;
- const struct res_res_info *resinfo;
+static rc_uint_type
+write_res_header (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type datasize,
+ const rc_res_id *type, const rc_res_id *name,
+ const rc_res_res_info *resinfo)
{
- struct res_hdr reshdr;
+ res_hdr reshdr;
reshdr.data_size = datasize;
reshdr.header_size = 24 + get_id_size (type) + get_id_size (name);
- res_align_file ();
- write_res_data (&reshdr, sizeof (reshdr), 1);
- write_res_id (type);
- write_res_id (name);
+ reshdr.header_size = (reshdr.header_size + 3) & ~3;
+
+ off = (off + 3) & ~3;
+
+ off = write_res_data_hdr (wrbfd, off, &reshdr);
+ off = write_res_id (wrbfd, off, type);
+ off = write_res_id (wrbfd, off, name);
- res_align_file ();
+ off = (off + 3) & ~3;
- write_res_info (resinfo);
- res_align_file ();
+ off = write_res_info (wrbfd, off, resinfo);
+ off = (off + 3) & ~3;
+ return off;
}
+static rc_uint_type
+write_res_data_hdr (windres_bfd *wrbfd, rc_uint_type off, res_hdr *hdr)
+{
+ if (wrbfd)
+ {
+ struct bin_res_hdr brh;
+ windres_put_32 (wrbfd, brh.data_size, hdr->data_size);
+ windres_put_32 (wrbfd, brh.header_size, hdr->header_size);
+ set_windres_bfd_content (wrbfd, &brh, off, BIN_RES_HDR_SIZE);
+ }
+ return off + BIN_RES_HDR_SIZE;
+}
-/* Write data to file, abort on failure */
static void
-write_res_data (data, size, count)
- const void *data;
- size_t size;
- int count;
+read_res_data_hdr (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
+ res_hdr *reshdr)
{
- if (fwrite (data, size, count, fres) != count)
- fatal ("%s: %s: could not write to file", program_name, filename);
+ struct bin_res_hdr brh;
+
+ if ((off[0] + BIN_RES_HDR_SIZE) > omax)
+ fatal ("%s: unexpected end of file %ld/%ld", filename,(long) off[0], (long) omax);
+
+ get_windres_bfd_content (wrbfd, &brh, off[0], BIN_RES_HDR_SIZE);
+ reshdr->data_size = windres_get_32 (wrbfd, brh.data_size, 4);
+ reshdr->header_size = windres_get_32 (wrbfd, brh.header_size, 4);
+ off[0] += BIN_RES_HDR_SIZE;
}
/* Read data from file, abort on failure */
static void
-read_res_data (data, size, count)
- void *data;
- size_t size;
- int count;
+read_res_data (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, void *data,
+ rc_uint_type size)
{
- if (fread (data, size, count, fres) != count)
- fatal ("%s: %s: unexpected end of file", program_name, filename);
+ if ((off[0] + size) > omax)
+ fatal ("%s: unexpected end of file %ld/%ld %ld", filename,(long) off[0],
+ (long) omax, (long) size);
+ get_windres_bfd_content (wrbfd, data, off[0], size);
+ off[0] += size;
}
/* Write a resource id */
-static void
-write_res_id (id)
- const struct res_id *id;
+static rc_uint_type
+write_res_id (windres_bfd *wrbfd, rc_uint_type off, const rc_res_id *id)
{
if (id->named)
{
- unsigned long len = id->u.n.length;
- unichar null_term = 0;
- write_res_data (id->u.n.name, len * sizeof (unichar), 1);
- write_res_data (&null_term, sizeof (null_term), 1);
+ rc_uint_type len = (((bfd_signed_vma) id->u.n.length < 0 ? 0 : id->u.n.length) + 1);
+ if (wrbfd)
+ {
+ rc_uint_type i;
+ bfd_byte *d = (bfd_byte *) xmalloc (len * sizeof (unichar));
+ for (i = 0; i < (len - 1); i++)
+ windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id->u.n.name[i]);
+ windres_put_16 (wrbfd, d + (i * sizeof (unichar)), 0);
+ set_windres_bfd_content (wrbfd, d, off, (len * sizeof (unichar)));
+ }
+ off += (len * sizeof (unichar));
}
else
{
- unsigned short i = 0xFFFF;
- write_res_data (&i, sizeof (i), 1);
- i = id->u.id;
- write_res_data (&i, sizeof (i), 1);
+ if (wrbfd)
+ {
+ struct bin_res_id bid;
+ windres_put_16 (wrbfd, bid.sig, 0xffff);
+ windres_put_16 (wrbfd, bid.id, id->u.id);
+ set_windres_bfd_content (wrbfd, &bid, off, BIN_RES_ID);
+ }
+ off += BIN_RES_ID;
}
+ return off;
}
/* Write resource info */
-static void
-write_res_info (info)
- const struct res_res_info *info;
+static rc_uint_type
+write_res_info (windres_bfd *wrbfd, rc_uint_type off, const rc_res_res_info *info)
{
- write_res_data (&info->version, sizeof (info->version), 1);
- write_res_data (&info->memflags, sizeof (info->memflags), 1);
- write_res_data (&info->language, sizeof (info->language), 1);
- write_res_data (&info->version, sizeof (info->version), 1);
- write_res_data (&info->characteristics, sizeof (info->characteristics), 1);
+ if (wrbfd)
+ {
+ struct bin_res_info l;
+
+ windres_put_32 (wrbfd, l.version, info->version);
+ windres_put_16 (wrbfd, l.memflags, info->memflags);
+ windres_put_16 (wrbfd, l.language, info->language);
+ windres_put_32 (wrbfd, l.version2, info->version);
+ windres_put_32 (wrbfd, l.characteristics, info->characteristics);
+ set_windres_bfd_content (wrbfd, &l, off, BIN_RES_INFO_SIZE);
+ }
+ return off + BIN_RES_INFO_SIZE;
}
/* read a resource identifier */
-void
-read_res_id (id)
- struct res_id *id;
+static void
+read_res_id (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax, rc_res_id *id)
{
+ struct bin_res_id bid;
unsigned short ord;
unichar *id_s = NULL;
- int len;
+ rc_uint_type len;
- read_res_data (&ord, sizeof (ord), 1);
+ read_res_data (wrbfd, off, omax, &bid, BIN_RES_ID - 2);
+ ord = (unsigned short) windres_get_16 (wrbfd, bid.sig, 2);
if (ord == 0xFFFF) /* an ordinal id */
{
- read_res_data (&ord, sizeof (ord), 1);
+ read_res_data (wrbfd, off, omax, bid.id, BIN_RES_ID - 2);
id->named = 0;
- id->u.id = ord;
+ id->u.id = windres_get_16 (wrbfd, bid.id, 2);
}
else
/* named id */
{
- if (fseek (fres, -sizeof (ord), SEEK_CUR) != 0)
- fatal ("%s: %s: could not seek in file", program_name, filename);
- id_s = read_unistring (&len);
+ off[0] -= 2;
+ id_s = read_unistring (wrbfd, off, omax, &len);
id->named = 1;
id->u.n.length = len;
id->u.n.name = id_s;
/* Read a null terminated UNICODE string */
static unichar *
-read_unistring (len)
- int *len;
+read_unistring (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax,
+ rc_uint_type *len)
{
unichar *s;
+ bfd_byte d[2];
unichar c;
unichar *p;
- int n;
- int l;
+ rc_uint_type l;
+ rc_uint_type soff = off[0];
- *len = 0;
- l = 0;
+ do
+ {
+ read_res_data (wrbfd, &soff, omax, d, sizeof (unichar));
+ c = windres_get_16 (wrbfd, d, 2);
+ }
+ while (c != 0);
+ l = ((soff - off[0]) / sizeof (unichar));
- /* there are hardly any names longer than 256 characters */
- p = s = (unichar *) xmalloc (sizeof (unichar) * 256);
+ /* there are hardly any names longer than 256 characters, but anyway. */
+ p = s = (unichar *) xmalloc (sizeof (unichar) * l);
do
{
- read_res_data (&c, sizeof (c), 1);
+ read_res_data (wrbfd, off, omax, d, sizeof (unichar));
+ c = windres_get_16 (wrbfd, d, 2);
*p++ = c;
- if (c != 0)
- l++;
}
while (c != 0);
- *len = l;
+ *len = l - 1;
return s;
}
-/* align file on DWORD boundary */
-static void
-res_align_file (void)
+static int
+probe_binary (windres_bfd *wrbfd, rc_uint_type omax)
{
- if (fseek (fres, ftell (fres) % 4, SEEK_CUR) != 0)
- fatal ("%s: %s: unable to align file", program_name, filename);
+ rc_uint_type off;
+ res_hdr reshdr;
+
+ off = 0;
+ read_res_data_hdr (wrbfd, &off, omax, &reshdr);
+ if (reshdr.data_size != 0)
+ return 1;
+ if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
+ || (reshdr.header_size != 0x20000000 && target_is_bigendian))
+ return 1;
+
+ /* Subtract size of HeaderSize. DataSize has to be zero. */
+ off += 0x20 - BIN_RES_HDR_SIZE;
+ if ((off + BIN_RES_HDR_SIZE) >= omax)
+ return 1;
+ read_res_data_hdr (wrbfd, &off, omax, &reshdr);
+ /* off is advanced by BIN_RES_HDR_SIZE in read_res_data_hdr()
+ which is part of reshdr.header_size. We shouldn't take it
+ into account twice. */
+ if ((off - BIN_RES_HDR_SIZE + reshdr.data_size + reshdr.header_size) > omax)
+ return 0;
+ return 1;
}
/* Check if file is a win32 binary resource file, if so
error.
*/
static void
-skip_null_resource (void)
+skip_null_resource (windres_bfd *wrbfd, rc_uint_type *off, rc_uint_type omax)
{
- struct res_hdr reshdr =
- {0, 0};
- read_res_data (&reshdr, sizeof (reshdr), 1);
- if ((reshdr.data_size != 0) || (reshdr.header_size != 0x20))
+ res_hdr reshdr;
+ read_res_data_hdr (wrbfd, off, omax, &reshdr);
+ if (reshdr.data_size != 0)
+ goto skip_err;
+ if ((reshdr.header_size != 0x20 && ! target_is_bigendian)
+ || (reshdr.header_size != 0x20000000 && target_is_bigendian))
goto skip_err;
- /* Subtract size of HeaderSize and DataSize */
- if (fseek (fres, reshdr.header_size - 8, SEEK_CUR) != 0)
+ /* Subtract size of HeaderSize. DataSize has to be zero. */
+ off[0] += 0x20 - BIN_RES_HDR_SIZE;
+ if (off[0] >= omax)
goto skip_err;
return;
}
/* Add a resource to resource directory */
-void
-res_add_resource (r, type, id, language, dupok)
- struct res_resource *r;
- const struct res_id *type;
- const struct res_id *id;
- int language;
- int dupok;
+static void
+res_add_resource (rc_res_resource *r, const rc_res_id *type, const rc_res_id *id,
+ rc_uint_type language, int dupok)
{
- struct res_id a[3];
+ rc_res_id a[3];
a[0] = *type;
a[1] = *id;
This is just copied from define_resource
and modified to add an existing resource.
*/
-void
-res_append_resource (resources, resource, cids, ids, dupok)
- struct res_directory **resources;
- struct res_resource *resource;
- int cids;
- const struct res_id *ids;
- int dupok;
+static void
+res_append_resource (rc_res_directory **res_dirs, rc_res_resource *resource,
+ int cids, const rc_res_id *ids, int dupok)
{
- struct res_entry *re = NULL;
+ rc_res_entry *re = NULL;
int i;
assert (cids > 0);
for (i = 0; i < cids; i++)
{
- struct res_entry **pp;
+ rc_res_entry **pp;
- if (*resources == NULL)
+ if (*res_dirs == NULL)
{
- static unsigned long timeval;
-
- /* Use the same timestamp for every resource created in a
- single run. */
- if (timeval == 0)
- timeval = time (NULL);
-
- *resources = ((struct res_directory *)
- res_alloc (sizeof **resources));
- (*resources)->characteristics = 0;
- (*resources)->time = timeval;
- (*resources)->major = 0;
- (*resources)->minor = 0;
- (*resources)->entries = NULL;
+ *res_dirs = ((rc_res_directory *)
+ res_alloc (sizeof (rc_res_directory)));
+
+ (*res_dirs)->characteristics = 0;
+ /* Using a real timestamp only serves to create non-deterministic
+ results. Use zero instead. */
+ (*res_dirs)->time = 0;
+ (*res_dirs)->major = 0;
+ (*res_dirs)->minor = 0;
+ (*res_dirs)->entries = NULL;
}
- for (pp = &(*resources)->entries; *pp != NULL; pp = &(*pp)->next)
+ for (pp = &(*res_dirs)->entries; *pp != NULL; pp = &(*pp)->next)
if (res_id_cmp ((*pp)->id, ids[i]) == 0)
break;
re = *pp;
else
{
- re = (struct res_entry *) res_alloc (sizeof *re);
+ re = (rc_res_entry *) res_alloc (sizeof (rc_res_entry));
re->next = NULL;
re->id = ids[i];
if ((i + 1) < cids)
if ((i + 1) < cids)
{
- if (!re->subdir)
+ if (! re->subdir)
{
fprintf (stderr, "%s: ", program_name);
res_ids_print (stderr, i, ids);
xexit (1);
}
- resources = &re->u.dir;
+ res_dirs = &re->u.dir;
}
}