This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libbfd problem


Hello,

I have just attached my 'ar' like program. The purpose is that to
extract a debian package, but it seems to not work on my armv7. It
works perfectly on i686, x86_64 host linux distributions.
When I try to run it on armv7, I get empty or unreasonable files... I
use libbfd library for this task, please help me :)

Best Regards,
Laszlo Papp
#include <bfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/limits.h>
#include <sys/stat.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>

#define REDIRECT_STDERR_TO_STDOUT " 2>&1"
#define CONTROL_FILE_DEBIAN "control.tar.gz"
#define DATA_FILE_DEBIAN "data.tar.gz"
#define DEBIAN_BINARY "debian-binary"

#define BUFSIZE 8192

void list_matching_formats(char **p)
{
  fprintf(stderr, "Matching formats:");
  while (*p)
    fprintf (stderr, " %s", *p++);
  fputc ('\n', stderr);
}

void bfd_nonfatal(const char *string)
{
  const char *errmsg = bfd_errmsg(bfd_get_error());

  if (string)
    fprintf(stderr, "%s: %s\n", string, errmsg);
  else
    fprintf(stderr, "%s\n", errmsg);
}

void bfd_fatal(const char *string)
{
  bfd_nonfatal(string);
  exit(1);
}

bfd *open_inarch(const char *archive_filename, const char *file)
{
  const char *target = 0;
  bfd **last_one = 0;
  bfd *next_one = 0;
  struct stat sbuf;
  bfd *arch = 0;
  char **matching = 0;
  const char *output_filename = 0;

  bfd_set_error(bfd_error_no_error);

  target = 0;

  printf("TESTP0\r\n");
  if (stat(archive_filename, &sbuf)) {
    printf("TESTP1\r\n");
    /* Try to figure out the target to use for the archive from the
       first object on the list.  */
    if (file) {
      bfd *obj;

      obj = bfd_openr(file, 0);
      if (obj) {
        if (bfd_check_format (obj, bfd_object))
          target = bfd_get_target (obj);
        (void) bfd_close (obj);
      }
    }

    /* Create an empty archive.  */
    arch = bfd_openw(archive_filename, target);
    if (arch == 0 || !bfd_set_format(arch, bfd_archive) || !bfd_close(arch))
      bfd_fatal(archive_filename);
    /* If we die creating a new archive, don't leave it around.  */
    output_filename = archive_filename;
  }

  arch = bfd_openr(archive_filename, target);
  if (arch == 0) {
    printf("TESTP2\r\n");
bloser:
    bfd_fatal(archive_filename);
  }

  if (!bfd_check_format_matches(arch, bfd_archive, &matching)) {
    printf("TESTP3\r\n");
    bfd_nonfatal(archive_filename);
    if (bfd_get_error() == bfd_error_file_ambiguously_recognized) {
      list_matching_formats (matching);
      free(matching);
    }
    exit(1);
  }

  last_one = &(arch->archive_next);
  /* Read all the contents right away, regardless.  */
  for (next_one = bfd_openr_next_archived_file(arch, 0);
      next_one;
      next_one = bfd_openr_next_archived_file(arch, next_one)) {
    /* PROGRESS (1); */
    *last_one = next_one;
    last_one = &next_one->archive_next;
  }

  *last_one = (bfd *)0;
  if (bfd_get_error() != bfd_error_no_more_archived_files)
    goto bloser;
  printf("TESTP4\r\n");
  return arch;
}

/* Normalize a file name specified on the command line into a file
   name which we will use in an archive.  */
static const char *normalize(const char *file, bfd *abfd)
{
  const char *filename;

  filename = strrchr (file, '/');
  if (filename != (char *)0)
    ++filename;
  else
    filename = file;

  return filename;
}

/*  Extract a member of the archive into its own file.
 *  We defer opening the new file until after we have read a BUFSIZ chunk of the
 *  old one, since we know we have just read the archive header for the old
 *  one.  Since most members are shorter than BUFSIZ, this means we will read
 *  the old header, read the old data, write a new inode for the new file, and
 *  write the new data, and be done. This 'optimization' is what comes from
 *  sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
 *  Gilmore
 */
void extract_file(bfd *abfd)
{
  FILE *ostream;
  char *cbuf = 0;
  size_t nread, tocopy;
  size_t ncopied = 0;
  size_t size;
  struct stat buf;
  const char *output_filename = 0;
  static FILE *output_file = 0;

  cbuf = (char *)malloc(BUFSIZE);
  printf("FN: %s\r\n", abfd->filename);
  if (bfd_stat_arch_elt(abfd, &buf))
    /* xgettext:c-format */
    printf("internal stat error on %s", bfd_get_filename(abfd));
  size = buf.st_size;
  printf("SIZE: %i\r\n", buf.st_size);

  bfd_seek(abfd, (file_ptr)0, SEEK_SET);

  ostream = 0;
  if (size == 0) {
    /* Seems like an abstraction violation, eh?  Well it's OK! */
    output_filename = bfd_get_filename(abfd);
    ostream = fopen(output_filename, "wb");
    if (ostream == 0) {
      printf("ERR1\r\n");
      perror(output_filename);
      exit(1);
    }

    output_file = ostream;
  } else {
    while (ncopied < size) {
      tocopy = size - ncopied;
      if (tocopy > BUFSIZE)
        tocopy = BUFSIZE;

      nread = bfd_bread(cbuf, (bfd_size_type) tocopy, abfd);
      if (nread != tocopy)
        /* xgettext:c-format */
        // printf("%s is not a valid archive",
            //bfd_get_filename(bfd_my_archive(abfd)));

      /* See comment above; this saves disk arm motion */
      if (ostream == 0) {
        /* Seems like an abstraction violation, eh?  Well it's OK! */
        output_filename = bfd_get_filename(abfd);

        ostream = fopen(output_filename, "wb");
        if (ostream == 0) {
          perror(output_filename);
          exit(1);
        }

        output_file = ostream;
      }

      /* fwrite in mingw32 may return int instead of size_t. Cast
         the return value to size_t to avoid comparison between
         signed and unsigned values.  */
      if ((size_t)fwrite(cbuf, 1, nread, ostream) != nread)
        printf("%s: %s", output_filename, strerror(errno)); ncopied += tocopy;
    }
  }

  if (ostream)
    fclose(ostream);

  output_file = 0;
  output_filename = 0;

  chmod(bfd_get_filename(abfd), buf.st_mode);
  free(cbuf);
  cbuf = 0;
}

/* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
   COUNT is the length of the FILES chain; FUNCTION is called on each entry
   whose name matches one in FILES.  */
static void map_over_members(bfd *arch, void (*function)(bfd *), char **files, int count)
{
  bfd *head;
  int match_count;

  printf("COUNT: %i\r\n", count);
  if (count == 0) {
    for (head = arch->archive_next; head; head = head->archive_next) {
      /* PROGRESS (1); */
      function(head);
    }
    return;
  }

  /* This may appear to be a baroque way of accomplishing what we want.
     However we have to iterate over the filenames in order to notice where
     a filename is requested but does not exist in the archive.  Ditto
     mapping over each file each time -- we want to hack multiple
     references.  */

  for (; count > 0; ++files, --count) {
    bfd_boolean found = FALSE;

    match_count = 0;
    for (head = arch->archive_next; head; head = head->archive_next) {
      const char *filename;

      /* PROGRESS(1); */
      filename = head->filename;
      printf("MOM_FN: %s\r\n", filename);
      if (filename == 0) {
        /* Some archive formats don't get the filenames filled in
           until the elements are opened.  */
        struct stat buf;
        bfd_stat_arch_elt(head, &buf);
      // } else if (bfd_is_thin_archive(arch)) {
      //  /* Thin archives store full pathnames.  Need to normalize.  */
       // filename = normalize(filename, arch);
      //  printf("THIN_NORM_FN: %s\r\n", filename);
     }

      if (filename && (!strcmp(normalize(*files, arch), filename))) {
        ++match_count;
        found = TRUE;
        printf("NORM_FN: %s\r\n", filename);
        function(head);
      }
    }

    if (!found)
      // xgettext:c-format
      fprintf(stderr, "no entry %s in archive\n", *files);
  }
}

int main(int argc, char **argv)
{
    char *extracted_files[] = {DEBIAN_BINARY, CONTROL_FILE_DEBIAN, DATA_FILE_DEBIAN, 0};
  bfd *arch = 0;

  arch = open_inarch(argv[1], extracted_files[0]);
  map_over_members(arch, extract_file, extracted_files, sizeof(extracted_files)/sizeof(extracted_files[0])-1);

    return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]