X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=as%2Fasranlib%2Fasranlib.c;h=dde9f787a24beafdac75ff1f1607070418072b89;hb=1edc7c1316ae901d7dc6aeaae8117c6af4089c89;hp=ab13c6785b857739342ffda4c68af151f5d16f4d;hpb=b7fec7bdb767e95165097f43e52cf1cbc4ee6017;p=fw%2Fsdcc diff --git a/as/asranlib/asranlib.c b/as/asranlib/asranlib.c index ab13c678..dde9f787 100644 --- a/as/asranlib/asranlib.c +++ b/as/asranlib/asranlib.c @@ -33,9 +33,9 @@ along with this program. If not, see . */ #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) @@ -207,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; @@ -231,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; }; @@ -266,7 +270,6 @@ add_symbol (const char *sym, void *param) return 0; } - int is_rel (FILE * libfp) { @@ -358,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"); @@ -379,8 +382,6 @@ process_symbol_table (struct ar_hdr *hdr, FILE *fp) return 0; } - pos = ftell (fp); - nsym = sgetl (buf); po = buf + 4; @@ -393,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); @@ -407,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; } @@ -419,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"); @@ -437,8 +442,6 @@ process_bsd_symbol_table (struct ar_hdr *hdr, FILE *fp) return 0; } - pos = ftell (fp); - tablesize = sgetl (buf); nsym = tablesize / 8; @@ -458,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; } @@ -481,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 @@ -523,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) @@ -551,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 @@ -568,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; @@ -578,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"))) { @@ -634,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); @@ -650,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)) @@ -662,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); @@ -696,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 @@ -721,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); } @@ -739,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; } @@ -779,12 +851,6 @@ process_options (int argc, char *argv[]) if (!narch) usage (); -} - -int -main (int argc, char *argv[]) -{ - process_options (argc, argv); return 0; }