#include <string.h>
#include <assert.h>
#include <time.h>
+#include <sys/stat.h>
#include "dbuf_string.h"
#include "lkar.h"
#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)
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;
return 0;
}
-
int
is_rel (FILE * libfp)
{
return 0;
}
-
static int
process_symbol_table (struct ar_hdr *hdr, FILE *fp)
{
offset = sgetl (po);
po += 4;
- 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 in %s", ps, obj);
if (verbose)
printf (" at 0x%04x\n", offset);
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');
}
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 (!(hdr_len = 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 (!(hdr_len = 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) - 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)
}
while ((hdr_len = ar_get_header (&hdr, fp, (verbose || list) ? &name : NULL)));
- return 1;
+ return feof (fp) ? 1 : 0;
}
void
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;
int nsym;
int symtab_size;
char tmpfile[] = "arXXXXXX";
+ struct stat stat_buf;
+ int can_stat;
#ifdef _WIN32
if (NULL == _mktemp (tmpfile) || NULL == (outfp = fopen (tmpfile, "wb")))
fwrite (buf, 1, sizeof (buf), outfp);
}
-
for (symp = symlist; symp; symp = symp->next)
{
fputs (symp->name, outfp);
putc (pad, outfp);
fclose (outfp);
+
+ if (0 != fstat(fileno(infp), &stat_buf))
+ {
+ fprintf (stderr, "asranlib: can't stat %s: ", archive);
+ perror (NULL);
+ fclose (infp);
+ can_stat = 0;
+ }
+ else
+ can_stat = 1;
+
fclose (infp);
if (0 != remove (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);
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
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);
}
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)
{
- (*opts[i].optfnc) ();
- break;
+ if (*optp == opts[i].short_opt)
+ {
+ if (NULL != opts[i].optfnc)
+ {
+ (*opts[i].optfnc) ();
+ break;
+ }
+ }
+ }
+ if (i >= NELEM (opts))
+ {
+ fprintf (stderr, "asranlib: invalid option -- %c\n", *optp);
+ usage ();
}
}
}
}
-
else
{
+ /* not an option */
do_ranlib (*argp);
++narch;
}
if (!narch)
usage ();
-}
-
-int
-main (int argc, char *argv[])
-{
- process_options (argc, argv);
return 0;
}