Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <libsec.h>
#include <ctype.h>
#include "iso9660.h"

/*
 * We keep an array sorted by bad atom pointer.
 * The theory is that since we don't free memory very often,
 * the array will be mostly sorted already and insertions will
 * usually be near the end, so we won't spend much time
 * keeping it sorted.
 */

/*
 * Binary search a Tx list.
 * If no entry is found, return a pointer to
 * where a new such entry would go.
 */
static Tx*
txsearch(char *atom, Tx *t, int n)
{
        while(n > 0) {
                if(atom < t[n/2].bad)
                        n = n/2;
                else if(atom > t[n/2].bad) {
                        t += n/2+1;
                        n -= (n/2+1);
                } else
                        return &t[n/2];
        }
        return t;
}

void
addtx(char *b, char *g)
{
        Tx *t;
        Conform *c;

        if(map == nil)
                map = emalloc(sizeof(*map));
        c = map;

        if(c->nt%32 == 0)
                c->t = erealloc(c->t, (c->nt+32)*sizeof(c->t[0]));
        t = txsearch(b, c->t, c->nt);
        if(t < c->t+c->nt && t->bad == b) {
                fprint(2, "warning: duplicate entry for %s in _conform.map\n", b);
                return;
        }

        if(t != c->t+c->nt)
                memmove(t+1, t, (c->t+c->nt - t)*sizeof(Tx));
        t->bad = b;
        t->good = g;
        c->nt++;
}

char*
conform(char *s, int isdir)
{
        Tx *t;
        char buf[10], *g;
        Conform *c;

        c = map;
        s = atom(s);
        if(c){
                t = txsearch(s, c->t, c->nt);
                if(t < c->t+c->nt && t->bad == s)
                        return t->good;
        }

        sprint(buf, "%c%.6d", isdir ? 'D' : 'F', c ? c->nt : 0);
        g = atom(buf);
        addtx(s, g);
        return g;
}

#ifdef NOTUSED
static int
isalldigit(char *s)
{
        while(*s)
                if(!isdigit(*s++))
                        return 0;
        return 1;
}
#endif

static int
goodcmp(const void *va, const void *vb)
{
        Tx *a, *b;

        a = (Tx*)va;
        b = (Tx*)vb;
        return strcmp(a->good, b->good);
}

static int
badatomcmp(const void *va, const void *vb)
{
        Tx *a, *b;

        a = (Tx*)va;
        b = (Tx*)vb;
        if(a->good < b->good)
                return -1;
        if(a->good > b->good)
                return 1;
        return 0;
}

void
wrconform(Cdimg *cd, int n, ulong *pblock, uvlong *plength)
{
        char buf[1024];
        int i;
        Conform *c;

        c = map;
        *pblock = cd->nextblock;
        if(c==nil || n==c->nt){
                *plength = 0;
                return;
        }

        Cwseek(cd, (vlong)cd->nextblock * Blocksize);
        qsort(c->t, c->nt, sizeof(c->t[0]), goodcmp);
        for(i=n; i<c->nt; i++) {
                snprint(buf, sizeof buf, "%s %s\n", c->t[i].good, c->t[i].bad);
                Cwrite(cd, buf, strlen(buf));
        }
        qsort(c->t, c->nt, sizeof(c->t[0]), badatomcmp);
        *plength = Cwoffset(cd) - (vlong)*pblock * Blocksize;
        chat("write _conform.map at %lud+%llud\n", *pblock, *plength);
        Cpadblock(cd);
}