X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fasranlib%2Fasranlib.c;h=dde9f787a24beafdac75ff1f1607070418072b89;hb=1edc7c1316ae901d7dc6aeaae8117c6af4089c89;hp=ba92f7e17b4842d7bf663be3945df859ea148299;hpb=89cfbf54f2bfdb6644f63ffe57298207a602e8bf;p=fw%2Fsdcc
diff --git a/as/asranlib/asranlib.c b/as/asranlib/asranlib.c
index ba92f7e1..dde9f787 100644
--- a/as/asranlib/asranlib.c
+++ b/as/asranlib/asranlib.c
@@ -26,15 +26,16 @@ along with this program. If not, see . */
#ifdef _WIN32
#include
-#define mktemp _mktemp
+#else
+#include
#endif
#define NELEM(x) (sizeof (x) / sizeof (*x))
-int verbose = 0;
-int list = 0;
-int print_index = 0;
+static int verbose = 0;
+static int list = 0;
+static int print_index = 0;
int
is_ar (FILE * libfp)
@@ -206,7 +207,11 @@ ar_get_header (struct ar_hdr *hdr, FILE * libfp, char **p_obj_name)
buf[AR_SIZE_LEN] = '\0';
hdr->ar_size = strtol (buf, NULL, 0);
- obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp);
+ if (NULL == (obj_name = get_member_name (hdr->ar_name, &size, p_obj_name != NULL, libfp)) && p_obj_name != NULL)
+ {
+ /* Malformed archive */
+ return 0;
+ }
if (p_obj_name != NULL)
*p_obj_name = obj_name;
@@ -230,7 +235,7 @@ get_member_name_by_offset (FILE * fp, long offset)
struct symbol_s
{
const char *name;
- off_t offset;
+ size_t offset;
struct symbol_s *next;
};
@@ -265,7 +270,6 @@ add_symbol (const char *sym, void *param)
return 0;
}
-
int
is_rel (FILE * libfp)
{
@@ -357,16 +361,16 @@ enum_symbols (FILE * fp, long size, int (*func) (const char *sym, void *param),
return 0;
}
-
static int
process_symbol_table (struct ar_hdr *hdr, FILE *fp)
{
+ long pos = ftell (fp);
+
if (print_index)
{
char *buf, *po, *ps;
int i;
long nsym;
- long pos;
printf ("Archive index:\n");
@@ -378,8 +382,6 @@ process_symbol_table (struct ar_hdr *hdr, FILE *fp)
return 0;
}
- pos = ftell (fp);
-
nsym = sgetl (buf);
po = buf + 4;
@@ -392,13 +394,18 @@ process_symbol_table (struct ar_hdr *hdr, FILE *fp)
offset = sgetl (po);
po += 4;
- printf ("%s in ", ps);
- ps += strlen(ps) + 1;
+ if (NULL == (obj = get_member_name_by_offset (fp, offset))) /* member name */
+ return 0;
- obj = get_member_name_by_offset (fp, offset); /* member name */
- printf ("%s\n", obj);
+ printf ("%s in %s", ps, obj);
+ if (verbose)
+ printf (" at 0x%04x\n", offset);
+ else
+ putchar ('\n');
free (obj);
+ ps += strlen(ps) + 1;
+
}
free (buf);
@@ -406,11 +413,9 @@ process_symbol_table (struct ar_hdr *hdr, FILE *fp)
putchar ('\n');
}
- else
- {
- /* skip the symbol table */
- fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR);
- }
+
+ /* skip the symbol table */
+ fseek (fp, pos + hdr->ar_size + (hdr->ar_size & 1), SEEK_SET);
return 1;
}
@@ -418,13 +423,14 @@ process_symbol_table (struct ar_hdr *hdr, FILE *fp)
static int
process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp)
{
+ long pos = ftell (fp);
+
if (print_index)
{
char *buf, *po, *ps;
int i;
long tablesize;
long nsym;
- long pos;
printf ("Archive index:\n");
@@ -436,8 +442,6 @@ process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp)
return 0;
}
- pos = ftell (fp);
-
tablesize = sgetl (buf);
nsym = tablesize / 8;
@@ -457,21 +461,18 @@ process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp)
printf ("%s in ", ps + sym);
- obj = get_member_name_by_offset (fp, offset); /* member name */
+ if (NULL == (obj = get_member_name_by_offset (fp, offset))) /* member name */
+ return 0;
+
printf ("%s\n", obj);
free (obj);
}
free (buf);
-
- fseek (fp, pos, SEEK_SET);
-
putchar ('\n');
}
- else
- {
- /* skip the symbol table */
- fseek (fp, hdr->ar_size + (hdr->ar_size & 1), SEEK_CUR);
- }
+
+ /* skip the symbol table */
+ fseek (fp, pos + hdr->ar_size + (hdr->ar_size & 1), SEEK_SET);
return 1;
}
@@ -480,32 +481,44 @@ int
get_symbols (FILE * fp, const char *archive)
{
struct ar_hdr hdr;
+ size_t hdr_len;
char *name;
- if (!is_ar (fp) || !ar_get_header (&hdr, fp, &name))
+ if (!is_ar (fp) || !(hdr_len = ar_get_header (&hdr, fp, &name)))
{
- fprintf (stderr, "asranlib: %s: File format not recognized\n", archive);
- exit (1);
+ free (name);
+
+ return 0;
}
if (AR_IS_SYMBOL_TABLE (name))
{
free (name);
- process_symbol_table (&hdr, fp);
- if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL))
+ if (!process_symbol_table (&hdr, fp))
+ return 0;
+
+ if (feof (fp))
return 1;
+ else if (!(hdr_len = ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)))
+ return 0;
}
else if (AR_IS_BSD_SYMBOL_TABLE (name))
{
free (name);
- process_bsd_symbol_table (&hdr, fp);
- if (!ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL))
+ if (!process_bsd_symbol_table (&hdr, fp))
+ return 0;
+
+ if (feof (fp))
return 1;
+ else if (!(hdr_len = ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)))
+ return 0;
}
+ else if (!verbose && !list)
+ free (name);
- first_member_offset = ftell (fp) - ARHDR_LEN;
+ first_member_offset = ftell (fp) - hdr_len;
/* walk trough all archive members */
do
@@ -522,17 +535,11 @@ get_symbols (FILE * fp, const char *archive)
{
long mdule_offset = ftell (fp);
- offset = mdule_offset - ARHDR_LEN;
+ offset = mdule_offset - hdr_len;
enum_symbols (fp, hdr.ar_size, add_symbol, NULL);
- fseek (fp, mdule_offset + hdr.ar_size, SEEK_SET);
-
- if (hdr.ar_size & 1)
- {
- int c = getc (fp);
- assert (c == EOF || c == '\n');
- }
+ fseek (fp, mdule_offset + hdr.ar_size + (hdr.ar_size & 1), SEEK_SET);
}
if (verbose)
@@ -550,9 +557,9 @@ get_symbols (FILE * fp, const char *archive)
fseek (fp, hdr.ar_size + (hdr.ar_size & 1), SEEK_CUR);
}
}
- while (ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL));
+ while ((hdr_len = ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)));
- return 1;
+ return feof (fp) ? 1 : 0;
}
void
@@ -567,7 +574,13 @@ do_ranlib (const char *archive)
exit (1);
}
- if (get_symbols (infp, archive))
+ if (!get_symbols (infp, archive))
+ {
+ fprintf (stderr, "asranlib: %s: Malformed archive\n", archive);
+ fclose (infp);
+ exit (1);
+ }
+ else if (!list && !print_index)
{
FILE *outfp;
struct symbol_s *symp;
@@ -577,7 +590,10 @@ do_ranlib (const char *archive)
int nsym;
int symtab_size;
char tmpfile[] = "arXXXXXX";
+ struct stat stat_buf;
+ int can_stat;
+ /* TODO: create tmpfile in temporery directory (TMP, TMPDIR, /usr/tmp, /tmp) */
#ifdef _WIN32
if (NULL == _mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb")))
{
@@ -633,7 +649,6 @@ do_ranlib (const char *archive)
fwrite (buf, 1, sizeof (buf), outfp);
}
-
for (symp = symlist; symp; symp = symp->next)
{
fputs (symp->name, outfp);
@@ -649,6 +664,17 @@ do_ranlib (const char *archive)
putc (pad, outfp);
fclose (outfp);
+
+ if (0 != fstat(fileno(infp), &stat_buf))
+ {
+ fprintf (stderr, "asranlib: can't stat %s: ", infp);
+ perror (NULL);
+ fclose (infp);
+ can_stat = 0;
+ }
+ else
+ can_stat = 1;
+
fclose (infp);
if (0 != remove (archive))
@@ -661,6 +687,11 @@ do_ranlib (const char *archive)
fprintf (stderr, "asranlib: can't rename %s to %s: ", tmpfile, archive);
perror (NULL);
}
+ else if (!can_stat || 0 != chmod (archive, stat_buf.st_mode))
+ {
+ fprintf (stderr, "asranlib: can't chmod %s: ", archive);
+ perror (NULL);
+ }
}
else
fclose (infp);
@@ -695,18 +726,18 @@ void usage (void);
struct opt_s
{
- const char *short_opt;
+ char short_opt;
const char *long_opt;
void (*optfnc) (void);
const char *comment;
}
opts[] =
{
- { "-v", "--verbose", &do_verbose, "Be more verbose about the operation" },
- { "-V", "--version", &print_version, "Print this help message" },
- { "-h", "--help", &usage, "Print version information" },
- { "-t", "--list", &do_list, "List the contents of an archive" },
- { "-s", "--print-armap", &print_armap, "Print the archive index" },
+ { 'v', "verbose", &do_verbose, "Be more verbose about the operation" },
+ { 'V', "version", &print_version, "Print this help message" },
+ { 'h', "help", &usage, "Print version information" },
+ { 't', "list", &do_list, "List the contents of an archive" },
+ { 's', "print-armap", &print_armap, "Print the archive index" },
};
void
@@ -720,15 +751,19 @@ usage (void)
for (i = 0; i < NELEM (opts); ++i)
{
- int len = 3;
- printf (" %s ", (NULL != opts[i].short_opt) ? opts[i].short_opt : " ");
+ int len = 5;
+ if ('\0' != opts[i].short_opt)
+ printf (" -%c ", opts[i].short_opt);
+ else
+ printf (" ");
+
if (NULL != opts[i].long_opt)
{
- printf ("%s ", opts[i].long_opt);
+ printf ("--%s ", opts[i].long_opt);
len += strlen (opts[i].long_opt);
}
- while (len++ < 32)
+ while (len++ < 30)
putchar (' ');
printf ("%s\n", opts[i].comment);
}
@@ -738,39 +773,77 @@ usage (void)
exit (1);
}
-void
-process_options (int argc, char *argv[])
+int
+main (int argc, char *argv[])
{
char **argp;
int noopts = 0;
int narch = 0;
+
for (argp = argv + 1; *argp; ++argp)
{
if (!noopts && (*argp)[0] == '-')
{
int i;
- if ((*argp)[1] == '-' && (*argp)[2] == '\0')
+ if ((*argp)[1] == '-')
{
- noopts = 1;
- continue;
+ if ((*argp)[2] == '\0')
+ {
+ /* end of options */
+ noopts = 1;
+ continue;
+ }
+ else
+ {
+ /* long option */
+ for (i = 0; i < NELEM (opts); ++i)
+ {
+ if (0 == strcmp (&(*argp)[2], opts[i].long_opt))
+ {
+ if (NULL != opts[i].optfnc)
+ {
+ (*opts[i].optfnc) ();
+ break;
+ }
+ }
+ }
+ if (i >= NELEM (opts))
+ {
+ fprintf (stderr, "asranlib: unrecognized option `%s'\n", *argp);
+ usage ();
+ }
+ }
}
-
- for (i = 0; i < NELEM (opts); ++i)
+ else
{
- if (0 == strcmp (*argp, opts[i].short_opt) || 0 == strcmp (*argp, opts[i].long_opt))
+ char *optp;
+
+ /* short option */
+ for (optp = &(*argp)[1]; *optp != '\0'; ++optp)
{
- if (NULL != opts[i].optfnc)
+ for (i = 0; i < NELEM (opts); ++i)
+ {
+ if (*optp == opts[i].short_opt)
+ {
+ if (NULL != opts[i].optfnc)
+ {
+ (*opts[i].optfnc) ();
+ break;
+ }
+ }
+ }
+ if (i >= NELEM (opts))
{
- (*opts[i].optfnc) ();
- break;
+ fprintf (stderr, "asranlib: invalid option -- %c\n", *optp);
+ usage ();
}
}
}
}
-
else
{
+ /* not an option */
do_ranlib (*argp);
++narch;
}
@@ -778,12 +851,6 @@ process_options (int argc, char *argv[])
if (!narch)
usage ();
-}
-
-int
-main (int argc, char *argv[])
-{
- process_options (argc, argv);
return 0;
}