-1

I have the same question posted here:

How to print the name of the files inside an archive file?

but those answers don't necessarily address the problem. I have an archived file week.a and I'd like to print out the names of the files inside that archive, called mon.txt, and fri.txt.

It should work just like the ar -t command, except I'm not allowed to use that.

What I've tried: My first attempt was to create a for loop and print out the arguments, but then I realized the file is already archived by that point, and so that wouldn't work. My second attempt was to look at the print_contents function of ar, which I've listed below:

static void
print_contents (bfd *abfd)
{
  size_t ncopied = 0;
  char *cbuf = (char *) xmalloc (BUFSIZE);
  struct stat buf;
  size_t size;
  if (bfd_stat_arch_elt (abfd, &buf) != 0)
    /* xgettext:c-format */
    fatal (_("internal stat error on %s"), bfd_get_filename (abfd));

  if (verbose)
    printf ("\n<%s>\n\n", bfd_get_filename (abfd));

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

  size = buf.st_size;
  while (ncopied < size)
    {

      size_t nread;
      size_t tocopy = size - ncopied;
      if (tocopy > BUFSIZE)
    tocopy = BUFSIZE;

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

      /* 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, stdout) != nread)
    fatal ("stdout: %s", strerror (errno));
      ncopied += tocopy;
    }
  free (cbuf);
}

But with this route, I don't really know what a lot of that code means or does (I'm very new to C). Could someone help make sense of this code, or point me in the right direction for writing my program? Thank you.

Community
  • 1
  • 1
Milap
  • 147
  • 1
  • 6
  • 15
  • Where is this from? (what environment) – ryyker Oct 20 '13 at 22:30
  • GNU binutils package ar.c, just an excerpt. – Milap Oct 20 '13 at 22:34
  • 1
    The Wikipedia page on ar http://en.wikipedia.org/wiki/Ar_(Unix) has enough information on the file format to write a parser that extracts the file names. – Andreas Bombe Oct 20 '13 at 22:52
  • Hey, I looked into that also. It doesn't really say anything in terms of C code that I could use or look at to understand, especially not for a beginner. Could you elaborate why you said that? – Milap Oct 20 '13 at 22:59
  • Forget ar.c - too complicated by stuff you don't need (the code you posted is not useful for solving the problem). Focus on understanding the file format. See comment of @AndreasBombe. Based on that write down pseudo code to check the global header, then read the first file header. Then write C to print the name of the first file in the archive. Update the pseudocode to skip over the the file contents and loop reading file header etc., until end of file. Check magic numbers as you go so you know you are reading from the correct place. See http://www.cplusplus.com/reference/cstdio/ – Bull Oct 20 '13 at 23:13
  • The key point is that ar format does not contain binary information in the headers, it's all formatted as printable characters. So I expect your homework assignment expects you to practice using scanf() to extract information from a file stream. – Andreas Bombe Oct 20 '13 at 23:29
  • Ah I see. My biggest problem was going from concept to code but I between your comment and B...'s comment, I think I've gotten a good start. Thanks. – Milap Oct 21 '13 at 02:58

2 Answers2

2

Based on format at wikipedia.org/wiki/Ar_(Unix), the basic shape of your program will be:

fopen(filename)
fscanf 8 characters/* global header */
check header is "!<arch>" followed by LF
while not at end of file  /* check return value of fcanf below  */
    fscanf each item in file header
    print filename /* first 16 characters of file header */
    check magic number is 0x60 0x0A
    skip file size characters  /* file contents - can use fseek with origin = SEEK_CUR */

fclose(file)

Refer to the C stdio library documentation for details of functions needed. Or see Wikipedia C file input/output

Bull
  • 11,771
  • 9
  • 42
  • 53
  • Thanks, this helped a lot and I've gotten a good start on it from here. Appreciate it. – Milap Oct 21 '13 at 02:56
  • **dont** use `feof()` And please do not advise it to beginners. – joop Sep 02 '14 at 10:06
  • @joop, I agree, corrected. Others should see http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong – Bull Sep 02 '14 at 13:02
1
int counting(FILE *f)
{  

    int count=0;
    rewind(f);

    struct ar_hdr myheader;

    fseek(f,8,SEEK_CUR);

    while(fread(&myheader,sizeof(struct ar_hdr),1,f)>0)
    {
        long test;

        test = atol(myheader.ar_size);
        fseek(f,test,SEEK_CUR);
        count++;
    }       
    printf("count is : %d\n",count);
    return count;
}

this code i had written to count the number of files in archive.. u can use the same to print the file names inside it as well

benka
  • 4,732
  • 35
  • 47
  • 58
ash123
  • 53
  • 9