Universität Ulm, SAI, Übungen zu Systemnahe Software I

Lösungsbeispiel zu Blatt 9 (Aufgabe 13): names

Verwaltung von Listen von Dateinamen für SAM.

names.h

/*
 *      names.h - Headerfile for SAM filename handling.
 *
 *      Martin Hasch, University of Ulm, January 1997
 */

#ifndef NAMES_H
#define NAMES_H

#include        "sam.h"

typedef struct names_l {
        char            *nl_filename;
        sam_Name        nl_name;
        struct names_l  *nl_prev, *nl_next;
} *names_List;

/*
 *      Add given filename and corresponding archive member name to list
 *      or replace entry with same archive member name.
 *      Return modified list.
 */
names_List names_add(names_List list, char *filename);

/*
 *      Search list for given archive member name.  If it is there,
 *      return a pointer to the entry, otherwise return NULL.
 */
names_List names_get(names_List list, sam_Name name);

/*
 *      Delete an entry from list.  Return modified list.
 */
names_List names_delete(names_List list, names_List entry);

/*
 *      Print for each entry of list an error message indicating that
 *      the entry was not found.
 */
void names_notfound(names_List list);

#endif  /* NAMES_H */

names.c

/*
 *      names.c - SAM filename handling.
 *
 *      Martin Hasch, University of Ulm, January 1997
 */

#include        <stdio.h>
#include        <stdlib.h>
#include        <string.h>
#include        "sam.h"
#include        "names.h"

#define PATHSEP '/'

/*
 *      typedef struct names_l {
 *              char            *nl_filename;
 *              sam_Name        nl_name;
 *              struct names_l  *nl_prev, *nl_next;
 *      } *names_List;
 */

/*
 *      Get archive member name from given filename and copy it to name.
 */
static void make_name(sam_Name name, char *filename)
{
        size_t len = 0;
        char * base = filename + strlen(filename);

        while ( base > filename && base[-1] == PATHSEP )
                --base;
        while ( base > filename && base[-1] != PATHSEP )
                ++len, --base;
        if ( !len )
                len = 1;
        else if ( len > SAM_NAMELEN )
                len = SAM_NAMELEN;

        (void) strncpy(name, base, len);
        name[len] = '\0';
}

/*
 *      Add given filename and corresponding archive member name to list
 *      or replace entry with same archive member name.
 *      Return modified list.
 */
names_List names_add(names_List list, char *filename)
{
        names_List this, prev;
        sam_Name name;

        make_name(name, filename);
        prev = NULL;
        this = list;
        while ( this != NULL ) {
                if ( !strcmp(this->nl_name, name) ) {
                        this->nl_filename = filename;
                        return list;
                }
                prev = this;
                this = this->nl_next;
        }

        this = (names_List) malloc( sizeof(struct names_l) );
        if ( this == NULL ) {
                perror("storage allocation");
                exit(ECODE_PROBLEM);
        }

        this->nl_filename = filename;
        (void) strncpy(this->nl_name, name, sizeof this->nl_name);
        this->nl_next = NULL;
        this->nl_prev = prev;
        if ( prev == NULL )
                list = this;
        else
                prev->nl_next = this;

        return list;
}

/*
 *      Search list for given archive member name.  If it is there,
 *      return a pointer to the entry, otherwise return NULL.
 */
names_List names_get(names_List list, sam_Name name)
{
        while ( list != NULL ) {
                if ( !strcmp(list->nl_name, name) )
                        return list;
                list = list->nl_next;
        }
        return list;
}

/*
 *      Delete an entry from list.  Return modified list.
 */
names_List names_delete(names_List list, names_List entry)
{
        if ( entry->nl_next != NULL )
                entry->nl_next->nl_prev = entry->nl_prev;
        if ( entry->nl_prev != NULL )
                entry->nl_prev->nl_next = entry->nl_next;
        else
                list = entry->nl_next;
        free(entry);
        return list;
}

/*
 *      Print for each entry of list an error message indicating that
 *      the entry was not found.
 */
void names_notfound(names_List list)
{
        while ( list != NULL ) {
                (void) fprintf(stderr, "%s: not found in archive\n",
                        list->nl_name);
                list = list->nl_next;
        }
}

<- Alle Module
Martin Hasch, Februar 1997