Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 Jun 2007 03:10:25 +0100
From:      Angus Barrow <angus@aggyb.org>
To:        freebsd-hackers@freebsd.org
Subject:   libelf question
Message-ID:  <467F2411.7070709@aggyb.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020502060506000100030004
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi there,
    I'm trying to develop a BSD licensed version of the ar utility using
the new libelf library as this seems to be listed on the project ideas page
but doesn't seem to be being worked on.  I've started off simply trying to
get a toc printed for the archive but for some reason the time-stamp seems
to be coming back wrong for the contents of the archives.  The code in
question uses libelf to fetch a struct for each entry in an archive and it
prints out the data as a table:
  
...
Elf_Arhdr *arh;
while ((object = elf_begin(fd, ELF_C_READ, archive)) != NULL)
{
   if ((arh = elf_getarhdr(object)) == NULL)
      errx(EX_SOFTWARE, "elf_getarhdr() failed: %s.", elf_errmsg(-1));

   ...      
         char timestring[20];
         time_t timet=arh->ar_date;
         strftime(timestring, sizeof(timestring), "%b %e %H:%M %Y",
          gmtime(&timet));

    The time shown in arh->ar_date (this is the struct that the libelf
library provides for each entry in the ar archive) seems to have a negative
value (using the GNU ar the date is Jun  3 13:09 2007, I've loaded the
program in gdb also and this seems to suggest the problem is with the
library:


30   time_t timet=arh->ar_date;
(gdb) n
31   strftime(timestring, sizeof(timestring), "%b %e %H:%M %Y", 
gmtime(&timet));
(gdb) n
...
(gdb) print timet
$1 = -1515870811
(gdb) print timestring
$2 = "Dec 19 04:46 1921\000\000"

    My question is, should I log a PR about this or is there something
obvious that I'm doing wrong here.  I'm totally new to writing anything
serious in C as all my uni courses use Java and VB.net etc.  Please find
the program attached in full.

Thanks for any advice.

Angus Barrow

--------------020502060506000100030004
Content-Type: text/plain;
 name="print.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="print.c"

#include <err.h>
#include <libelf.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <time.h>
void prettyMode(int, char*);
int printToc(int fd, Elf *archive, int argc, char *argv, int VERBOSE_FLAG)
{
	Elf *object;
	
	printf("(DBG)\tprint.c:printToc(Elf, char) - argc=%d verb=%d\n",argc, VERBOSE_FLAG);
	Elf_Kind type = elf_kind(archive);
	if(type!=ELF_K_AR)
		errx(EX_DATAERR, "Type of object is not ELF_K_AR\n");
	
	Elf_Arhdr *arh;
	while ((object = elf_begin(fd, ELF_C_READ, archive)) != NULL) {

                if ((arh = elf_getarhdr(object)) == NULL)
                        errx(EX_SOFTWARE, "elf_getarhdr() failed: %s.", elf_errmsg(-1));
			
		if(VERBOSE_FLAG!=1)
		{
			printf("%s\n", arh->ar_name);
		} 
		else
		{
			char timestring[20];
			time_t timet=arh->ar_date;
			strftime(timestring, sizeof(timestring), "%b %e %H:%M %Y", gmtime(&timet));
			
			char perms[10]="---------\0";
			
			prettyMode(arh->ar_mode, perms);
			
			printf("%s %u/%u %8u %s %s\n", perms, arh->ar_uid, arh->ar_gid, arh->ar_size, timestring, arh->ar_name);

		}

		elf_next(object);
		elf_end(object);
	}
	
	elf_end(archive);
	
	return 0;
}



void prettyMode(int mode, char *string)
{
	
	/* There must be a better way or a library for this!*/
	
	if(strlen(string)<9)
	{
		printf("Urgh, that is not good!\nGive me a longer array!");
		return;
	}
	if((mode & 0400)==0400)
		string[0]='r';
	if((mode & 0200)==0200)
		string[1]='w';
	if((mode & 0100)==0100)
		string[2]='x';
		
	if((mode & 040)==040)
		string[3]='r';
	if((mode & 020)==020)
		string[4]='w';
	if((mode & 010)==010)
		string[5]='x';

	if((mode & 04)==04)
		string[6]='r';
	if((mode & 02)==02)
		string[7]='w';
	if((mode & 01)==01)
		string[8]='x';



	
}

--------------020502060506000100030004
Content-Type: text/plain;
 name="ar.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ar.c"

/*-
 * Copyright (c) 2007 Angus Barrow <angus(at)aggyb.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#include <err.h>
#include <fcntl.h>
#include <libelf.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <time.h>
#include <unistd.h>


static int VERBOSE_FLAG;
int tflag;

/*
 * This is a BSD licenced attempt at the ar program as in POSIX 1003.1.
 * It makes use of the Elf and GElf API's in FreeBSD 7-CURRENT.
 */
int main(int argc, char *argv[])
{
	int ch;
	
	/* Decide how we've been invoked and try to decide what to do! */
	VERBOSE_FLAG=-1;
	while ((ch = getopt(argc, argv, "htv")) != -1)
		switch (ch) {
			case 't':
				tflag = 1;
				break;
			case 'v':
				VERBOSE_FLAG=1;
				printf("(DBG)\tVerbose flag set\n");
				break;
			case 'h':
				printf("(DBG)\tDisplay help\n");
				/* FLOWS THROUGH */
		     	default:
				usage();
				/* NOTREACHED */
	}
	
	argc-=optind;
	argv+=optind;
	
	printf("(DBG)\tFile to open is: %s\n", *argv);
	/* Open file */
	int fd;
	if ((fd = open(*argv, O_RDONLY, 0)) < 0)
                err(EX_NOINPUT, "open \%s\" failed", *argv);
	/* Open library */
	if (elf_version(EV_CURRENT) == EV_NONE)
                errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1));
	/* Open elf object/archive */
	Elf *elf;
	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
		errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
	
	
	if(tflag==1)
	{
		printToc(fd, elf, argc, argv, VERBOSE_FLAG);
	}
	
	close(fd);
	return 0;
}

int usage()
{
	printf("Options are:\nh\t-\tDisplay this help!\nt\t-\tDisplay TOC\nv\t-\tEnable verbose mode\n");
	exit(0);
}

--------------020502060506000100030004--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?467F2411.7070709>