Exemplo n.º 1
0
/* Knuth step T5, the insert. */
static struct ts_entry *
tsearch_insert_k(const void *key,int kc,
    struct ts_entry *p)
{
    struct ts_entry *q = allocate_ts_entry(key);
    if (!q) {
        /* out of memory */
        return NULL;
    }
    setlink(p,kc,q);
    /* Non-NULL means inserted. */
    return q;
}
Exemplo n.º 2
0
/**
 * copy a link, actually we recreate the link and only copy its stat() data.
 */
int copy_link(struct cow *cow)
{
	int len;
	char link[PATHLEN_MAX];

	if ((len = readlink(cow->from_path, link, sizeof(link)-1)) == -1) {
		syslog(LOG_WARNING,   "readlink: %s", cow->from_path);
		return (1);
	}
	
	if (symlink(cow->from_path, cow->to_path)) {
		syslog(LOG_WARNING,   "symlink: %s", link);
		return (1);
	}
	
	return setlink(cow->to_path, cow->stat);
}
Exemplo n.º 3
0
int
copy_link(FTSENT *p, int exists)
{
	int len;
	char link[MAXPATHLEN];

	if ((len = readlink(p->fts_path, link, sizeof(link)-1)) == -1) {
		warn("readlink: %s", p->fts_path);
		return (1);
	}
	link[len] = '\0';
	if (exists && unlink(to.p_path)) {
		warn("unlink: %s", to.p_path);
		return (1);
	}
	if (symlink(link, to.p_path)) {
		warn("symlink: %s", link);
		return (1);
	}
	return (pflag ? setlink(p->fts_statp) : 0);
}
Exemplo n.º 4
0
static int
copy_link(FTSENT *p, int exists)
{
	int len;
	char linkname[PATH_MAX];

	if ((len = readlink(p->fts_path, linkname, sizeof(linkname)-1)) == -1) {
		warn("readlink: %s", p->fts_path);
		return (1);
	}
	linkname[len] = '\0';
	if (exists && unlink(to.p_path)) {
		warn("unlink: %s", to.p_path);
		return (1);
	}
	if (symlink(linkname, to.p_path)) {
		warn("symlink: %s", linkname);
		return (1);
	}
	return (setlink(p->fts_statp));
}
Exemplo n.º 5
0
/*  Returns deleted node parent unless the head changed.
    Returns NULL if wanted node not found or the tree
        is now empty or the head node changed.
    Sets *did_delete if it found and deleted a node.
    Sets *tree_empty if there are no more user nodes present.
*/
static struct ts_entry *
tdelete_inner(const void *key,
  struct ts_entry *head,
  int (*compar)(const void *, const void *),
  int *tree_empty,
  int *did_delete
  )
{
    struct ts_entry *p        = 0;
    struct ts_entry *pp       = 0;
    struct pkrecord * pkarray = 0;
    int depth                 = head->llink - (struct ts_entry *)0;
    unsigned k                = 0;

    /*  Allocate extra, head is on the stack we create
        here  and the depth might increase.  */
    depth = depth + 4;
    pkarray = calloc(sizeof(struct pkrecord),depth);
    if(!pkarray) {
        /* Malloc fails, we could abort... */
        return NULL;
    }
    k = 0;
    pkarray[k].pk=head;
    pkarray[k].ak=1;
    p = head->rlink;
    while(p) {
        int kc = 0;
        k++;
        kc = compar(key,p->keyptr);
        pkarray[k].pk = p;
        pkarray[k].ak = kc;
        if(!kc) {
            break;
        }
        p  = getlink(p,kc);
    }
    if(!p) {
        /* Node to delete never found. */
        free(pkarray);
        return NULL;
    }

    {
        struct ts_entry *p  = 0;
        struct ts_entry *t  = 0;
        struct ts_entry *r  = 0;
        int pak = 0;
        int ppak = 0;

        p = pkarray[k].pk;
        pak = pkarray[k].ak;
        pp = pkarray[k-1].pk;
        ppak = pkarray[k-1].ak;

        /* Found a match. p to be deleted. */
        t = p;
        *did_delete = 1;
        if(!t->rlink) {
            if(k == 1 && !t->llink) {
                *tree_empty = 1;
                /* upper level will fix up head node. */
                free(t);
                free(pkarray);
                return NULL;
            }
            /*  t->llink might be NULL. */
            setlink(pp,ppak,t->llink);
            /*  ASSERT: t->llink NULL or t->llink
                has no children, balance zero and balance
                of t->llink not changing. */
            k--;
            /* Step D4. */
            free(t);
            goto balance;
        }
#ifdef IMPLEMENTD15
        /* Step D1.5 */
        if(!t->llink) {
            setlink(pp,ppak,t->rlink);
            /* we change the left link off ak */
            k--;
            /* Step D4. */
            free(t);
            goto balance;
        }
#endif /* IMPLEMENTD15 */
        /* Step D2 */
        r = t->rlink;
        if (!r->llink) {
            /* We decrease the height of the right tree.  */
            r->llink = t->llink;
            setlink(pp,ppak,r);
            pkarray[k].pk = r;
            pkarray[k].ak = 1;
            /*  The following essential line not mentioned
                in Knuth AFAICT. */
            r->balance = t->balance;
            /* Step D4. */
            free(t);
            goto balance;
        }
        /*  Step D3, we rearrange the tree
            and pkarray so the balance step can work.
            step D2 is insufficient so not done.  */
        k = rearrange_tree_so_p_llink_null(pkarray,k,
            head,r,
            p,pak,pp,ppak);
        goto balance;
    }
    /*  Now use pkarray decide if rebalancing
        needed and, if needed, to rebalance.
        k here matches l-1 in Knuth. */
    balance:
    {
    unsigned k2 = k;
    /*  We do not want a test in the for() itself. */
    for(  ; 1 ; k2--) {
        struct ts_entry *pk = 0;
        int ak = 0;
        int bk = 0;
        if (k2 == 0) {
            /* decreased in height */
            head->llink--;
            goto cleanup;
        }
        pk = pkarray[k2].pk;
        if (!pk) {
            /* Nothing here to work with. Move up. */
            continue;
        }
        ak = pkarray[k2].ak;
        bk = pk->balance;
        if(bk == ak) {
            pk->balance = 0;
            continue;
        }
        if(bk == 0) {
            pk->balance = -ak;
            goto cleanup;
        }
        /* ASSERT: bk == -ak. We
            will use bk == adel here (just below). */
        /* Rebalancing required. Here we use (1) and (2)
            in 6.2.3 to adjust the nodes */
        {
            /* Rebalance.  We use s for what
                is called A in Knuth Case 1, Case 2
                page 461.   r For what is called B.
                So the link movement logic looks similar
                to the tsearch insert case.*/
            struct ts_entry *r = 0;
            struct ts_entry *s = 0;
            struct ts_entry *pa = 0;
            int pak = 0;
            int adel = -ak;

            s = pk;
            r = getlink(s,adel);
            pa = pkarray[k2-1].pk;
            pak = pkarray[k2-1].ak;
            if(r->balance == adel) {
                /* case 1. */
                setlink(s,adel,getlink(r,-adel));
                setlink(r,-adel,s);

                /* A10 in tsearch. */
                setlink(pa,pak,r);
                s->balance = 0;
                r->balance = 0;
                continue;
            } else if (r->balance == -adel) {
                /* case 2 */
                /* x plays the role of p in step A9 */
                struct ts_entry*x = getlink(r,-adel);
                setlink(r,-adel,getlink(x,adel));
                setlink(x,adel,r);
                setlink(s,adel,getlink(x,-adel));
                setlink(x,-adel,s);

                /* A10 in tsearch. */
                setlink(pa,pak,x);
                if(x->balance == adel) {
                    s->balance = -adel;
                    r->balance = 0;
                } else if (x->balance  == 0) {
                    s->balance = 0;
                    r->balance = 0;
                } else if (x->balance == -adel) {
                    s->balance = 0;
                    r->balance = adel;
                }
                x->balance = 0;
                continue;
            } else {
                /*  r->balance == 0 case 3
                    we do a single rotation and
                    we are done. */
                setlink(s,adel,getlink(r,-adel));
                setlink(r,-adel,s);
                setlink(pa,pak,r);
                r->balance = -adel;
                /*s->balance = r->balance = 0; */
                goto cleanup;
            }
        }
    }
    }
    cleanup:
    free(pkarray);
#ifdef DW_CHECK_CONSISTENCY
    dwarf_check_balance(head,1);
#endif
    return pp;
}
Exemplo n.º 6
0
static unsigned
rearrange_tree_so_p_llink_null( struct pkrecord * pkarray,
    unsigned k,
    struct ts_entry *head,
    struct ts_entry *r,
    struct ts_entry *p,
    UNUSEDARG int pak,
    struct ts_entry *pp,
    int ppak)
{
    struct ts_entry *s = 0;
    unsigned k2 = 0; /* indexing pkarray */
    int pbalance = p->balance;

    /* Step D3 */
    /*  Since we are going to modify the tree by
        movement of a node down the tree a ways,
        we need to build pkarray with the (not yet
        found) new next node, in pkarray[k], not
        p.
        The deletion will be of p, but by then
        p will be moved in the tree so it has a null left link.
        P's possibly-non-null right link
    */
    k2 = k;
    k2++;
    r = p->rlink;
    pkarray[k2].pk = r;
    pkarray[k2].ak = -1;
    s = r->llink;
    /* Move down and left to get a null llink. */
    while (s->llink) {
        k2++;
        r = s;
        s = r->llink;
        pkarray[k2].pk = r;
        pkarray[k2].ak = -1;
    }
    /*  Now we move S up in place (in the tree)
        of the node P we will delete.
        and p replaces s.
        Finally winding up with a newly shaped balanced tree.
        */
    {
    struct ts_entry *tmp = 0;
    int sbalance = s->balance;
    s->llink = p->llink;
    r->llink = p;
    p->llink = 0;
    tmp = p->rlink;
    p->rlink = s->rlink;
    s->rlink = tmp;
    setlink(pp,ppak,s);
    s->balance = pbalance;
    p->balance = sbalance;
    /* Now the tree is rearranged and still in balance. */

    /* Replace the previous k position entry with S.
        We trace the right link off of the moved S node. */
    pkarray[k].pk = s;
    pkarray[k].ak = 1;

    r->llink = p->rlink;
    /*  Now p is out of the tree and  we start
        the rebalance at r. pkarray Index k2. */
    }
    /* Step D4 */
    free(p);
    return k2;
}
Exemplo n.º 7
0
/* Algorithm A of Knuth 6.2.3, balanced tree.
   key is pointer to a user data area containing the key
   and possibly more.

   We could recurse on this routine, but instead we
   iterate (like Knuth does, but using for(;;) instead
   of go-to.

  */
static struct ts_entry *
tsearch_inner( const void *key, struct ts_entry* head,
    int (*compar)(const void *, const void *),
    int*inserted,
    struct ts_entry **nullme,
    int * comparres)
{
    /* t points to parent of p */
    struct ts_entry *t = head;
    /* p moves down tree, p starts as root. */
    struct ts_entry *p = head->rlink;
    /* s points where rebalancing may be needed. */
    struct ts_entry *s = p;
    struct ts_entry *r = 0;
    struct ts_entry *q = 0;

    int a = 0;
    int kc = 0;
    for(;;) {
        /* A2. */
        kc = compar(key,p->keyptr);
        if(kc) {
            /* A3 and A4 handled here. */
            q = getlink(p,kc);
            if(!q) {
                /* Does step A5. */
                q = tsearch_inner_do_insert(key,kc,inserted,p);
                if (!q) {
                    /*  Out of memory. */
                    return q;
                }
                break; /* to A5. */
            }
            if(q->balance) {
                t = p;
                s = q;
            }
            p = q;
            continue;
        }
        /* K = KEY(P) in Knuth. */
        /* kc == 0, we found the entry we search for. */
        return p;
    }
    /* A5:  work already done. */

    /* A6: */
    {
        /*  Balance factors on nodes betwen S and Q need to be
            changed from zero to +-1  */
        int kc2 = compar(key,s->keyptr);
        if (kc2 < 0) {
            a = -1;
        } else {
            a = 1;
        }
        r = p = getlink(s,a);
        while (p != q) {
            int kc3 = compar(key,p->keyptr);
            if(kc3 < 0) {
                p->balance = -1;
                p = p->llink;
            } else if (kc3 > 0) {
                p->balance = 1;
                p = p->rlink;
            } else {
                /* ASSERT: p == q */
                break;
            }
        }
    }

    /* A7: */
    {
        if(! s->balance) {
            /* Tree has grown higher. */
            s->balance = a;
            /* Counting in pointers, not integers. Ugh. */
            head->llink  = head->llink + 1;
            return q;
        }
        if(s->balance == -a) {
            /* Tree is more balanced */
            s->balance = 0;
            return q;
        }
        if (s->balance == a) {
            /* Rebalance. */
            if(r->balance == a) {
                /* single rotation, step A8. */
                p = r;
                setlink(s,a,getlink(r,-a));
                setlink(r,-a,s);
                s->balance = 0;
                r->balance = 0;
            } else if (r->balance == -a) {
                /* double rotation, step A9. */
                p = getlink(r,-a);
                setlink(r,-a,getlink(p,a));
                setlink(p,a,r);
                setlink(s,a,getlink(p,-a));
                setlink(p,-a,s);
                if(p->balance == a) {
                    s->balance = -a;
                    r->balance = 0;
                } else if (p->balance  == 0) {
                    s->balance = 0;
                    r->balance = 0;
                } else if (p->balance == -a) {
                    s->balance = 0;
                    r->balance = a;
                }
                p->balance = 0;
            } else {
                fprintf(stderr,"Impossible balanced tree situation!\n");
                /* Impossible. Cannot be here. */
                exit(1);
            }
        } else {
            fprintf(stderr,"Impossible balanced tree situation!!\n");
            /* Impossible. Cannot be here. */
            exit(1);
        }
    }

    /* A10: */
    if (s == t->rlink) {
        t->rlink = p;
    } else {
        t->llink = p;
    }
#ifdef DW_CHECK_CONSISTENCY
    dwarf_check_balance(head,1);
#endif
    return q;
}