[Midnightbsd-cvs] src: contrib/csup: remove csup from the base system.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Fri Apr 3 01:16:14 EDT 2009
Log Message:
-----------
remove csup from the base system. We've had some open bug reports on this and it looks like we might migrate off cvs anyway. It does not support cvs 1.12.x properly.
Removed Files:
-------------
src/contrib/csup:
GNUmakefile
Makefile
README
TODO
attrstack.c
attrstack.h
config.c
config.h
csup.1
detailer.c
detailer.h
diff.c
diff.h
fattr.c
fattr.h
fattr_bsd.h
fattr_posix.h
fixups.c
fixups.h
fnmatch.c
fnmatch.h
globtree.c
globtree.h
idcache.c
idcache.h
keyword.c
keyword.h
lister.c
lister.h
main.c
main.h
misc.c
misc.h
mux.c
mux.h
parse.y
pathcomp.c
pathcomp.h
proto.c
proto.h
queue.h
status.c
status.h
stream.c
stream.h
threads.c
threads.h
token.h
token.l
updater.c
updater.h
-------------- next part --------------
--- contrib/csup/lister.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/lister.c,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "attrstack.h"
-#include "config.h"
-#include "fattr.h"
-#include "globtree.h"
-#include "lister.h"
-#include "misc.h"
-#include "mux.h"
-#include "proto.h"
-#include "status.h"
-#include "stream.h"
-
-/* Internal error codes. */
-#define LISTER_ERR_WRITE (-1) /* Error writing to server. */
-#define LISTER_ERR_STATUS (-2) /* Status file error in lstr->errmsg. */
-
-struct lister {
- struct config *config;
- struct stream *wr;
- char *errmsg;
-};
-
-static int lister_batch(struct lister *);
-static int lister_coll(struct lister *, struct coll *, struct status *);
-static int lister_dodirdown(struct lister *, struct coll *,
- struct statusrec *, struct attrstack *as);
-static int lister_dodirup(struct lister *, struct coll *,
- struct statusrec *, struct attrstack *as);
-static int lister_dofile(struct lister *, struct coll *,
- struct statusrec *);
-static int lister_dodead(struct lister *, struct coll *,
- struct statusrec *);
-
-void *
-lister(void *arg)
-{
- struct thread_args *args;
- struct lister lbuf, *l;
- int error;
-
- args = arg;
- l = &lbuf;
- l->config = args->config;
- l->wr = args->wr;
- l->errmsg = NULL;
- error = lister_batch(l);
- switch (error) {
- case LISTER_ERR_WRITE:
- xasprintf(&args->errmsg,
- "TreeList failed: Network write failure: %s",
- strerror(errno));
- args->status = STATUS_TRANSIENTFAILURE;
- break;
- case LISTER_ERR_STATUS:
- xasprintf(&args->errmsg,
- "TreeList failed: %s. Delete it and try again.",
- l->errmsg);
- free(l->errmsg);
- args->status = STATUS_FAILURE;
- break;
- default:
- assert(error == 0);
- args->status = STATUS_SUCCESS;
- };
- return (NULL);
-}
-
-static int
-lister_batch(struct lister *l)
-{
- struct config *config;
- struct stream *wr;
- struct status *st;
- struct coll *coll;
- int error;
-
- config = l->config;
- wr = l->wr;
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- if (coll->co_options & CO_SKIP)
- continue;
- st = status_open(coll, -1, &l->errmsg);
- if (st == NULL)
- return (LISTER_ERR_STATUS);
- error = proto_printf(wr, "COLL %s %s\n", coll->co_name,
- coll->co_release);
- if (error)
- return (LISTER_ERR_WRITE);
- stream_flush(wr);
- if (coll->co_options & CO_COMPRESS)
- stream_filter_start(wr, STREAM_FILTER_ZLIB, NULL);
- error = lister_coll(l, coll, st);
- status_close(st, NULL);
- if (error)
- return (error);
- if (coll->co_options & CO_COMPRESS)
- stream_filter_stop(wr);
- stream_flush(wr);
- }
- error = proto_printf(wr, ".\n");
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
-}
-
-/* List a single collection based on the status file. */
-static int
-lister_coll(struct lister *l, struct coll *coll, struct status *st)
-{
- struct stream *wr;
- struct attrstack *as;
- struct statusrec *sr;
- struct fattr *fa;
- size_t i;
- int depth, error, ret, prunedepth;
-
- wr = l->wr;
- depth = 0;
- prunedepth = INT_MAX;
- as = attrstack_new();
- while ((ret = status_get(st, NULL, 0, 0, &sr)) == 1) {
- switch (sr->sr_type) {
- case SR_DIRDOWN:
- depth++;
- if (depth < prunedepth) {
- error = lister_dodirdown(l, coll, sr, as);
- if (error < 0)
- goto bad;
- if (error)
- prunedepth = depth;
- }
- break;
- case SR_DIRUP:
- if (depth < prunedepth) {
- error = lister_dodirup(l, coll, sr, as);
- if (error)
- goto bad;
- } else if (depth == prunedepth) {
- /* Finished pruning. */
- prunedepth = INT_MAX;
- }
- depth--;
- continue;
- case SR_CHECKOUTLIVE:
- if (depth < prunedepth) {
- error = lister_dofile(l, coll, sr);
- if (error)
- goto bad;
- }
- break;
- case SR_CHECKOUTDEAD:
- if (depth < prunedepth) {
- error = lister_dodead(l, coll, sr);
- if (error)
- goto bad;
- }
- break;
- }
- }
- if (ret == -1) {
- l->errmsg = status_errmsg(st);
- error = LISTER_ERR_STATUS;
- goto bad;
- }
- assert(status_eof(st));
- assert(depth == 0);
- error = proto_printf(wr, ".\n");
- attrstack_free(as);
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
-bad:
- for (i = 0; i < attrstack_size(as); i++) {
- fa = attrstack_pop(as);
- fattr_free(fa);
- }
- attrstack_free(as);
- return (error);
-}
-
-/* Handle a directory up entry found in the status file. */
-static int
-lister_dodirdown(struct lister *l, struct coll *coll, struct statusrec *sr,
- struct attrstack *as)
-{
- struct config *config;
- struct stream *wr;
- struct fattr *fa, *fa2;
- char *path;
- int error;
-
- config = l->config;
- wr = l->wr;
- if (!globtree_test(coll->co_dirfilter, sr->sr_file))
- return (1);
- if (coll->co_options & CO_TRUSTSTATUSFILE) {
- fa = fattr_new(FT_DIRECTORY, -1);
- } else {
- xasprintf(&path, "%s/%s", coll->co_prefix, sr->sr_file);
- fa = fattr_frompath(path, FATTR_NOFOLLOW);
- if (fa == NULL) {
- /* The directory doesn't exist, prune
- * everything below it. */
- free(path);
- return (1);
- }
- if (fattr_type(fa) == FT_SYMLINK) {
- fa2 = fattr_frompath(path, FATTR_FOLLOW);
- if (fa2 != NULL && fattr_type(fa2) == FT_DIRECTORY) {
- /* XXX - When not in checkout mode, CVSup warns
- * here about the file being a symlink to a
- * directory instead of a directory. */
- fattr_free(fa);
- fa = fa2;
- } else {
- fattr_free(fa2);
- }
- }
- free(path);
- }
-
- if (fattr_type(fa) != FT_DIRECTORY) {
- fattr_free(fa);
- /* Report it as something bogus so
- * that it will be replaced. */
- error = proto_printf(wr, "F %s %F\n", pathlast(sr->sr_file),
- fattr_bogus, config->fasupport, coll->co_attrignore);
- if (error)
- return (LISTER_ERR_WRITE);
- return (1);
- }
-
- /* It really is a directory. */
- attrstack_push(as, fa);
- error = proto_printf(wr, "D %s\n", pathlast(sr->sr_file));
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
-}
-
-/* Handle a directory up entry found in the status file. */
-static int
-lister_dodirup(struct lister *l, struct coll *coll, struct statusrec *sr,
- struct attrstack *as)
-{
- struct config *config;
- const struct fattr *sendattr;
- struct stream *wr;
- struct fattr *fa, *fa2;
- int error;
-
- config = l->config;
- wr = l->wr;
- fa = attrstack_pop(as);
- if (coll->co_options & CO_TRUSTSTATUSFILE) {
- fattr_free(fa);
- fa = sr->sr_clientattr;
- }
-
- fa2 = sr->sr_clientattr;
- if (fattr_equal(fa, fa2))
- sendattr = fa;
- else
- sendattr = fattr_bogus;
- error = proto_printf(wr, "U %F\n", sendattr, config->fasupport,
- coll->co_attrignore);
- if (error)
- return (LISTER_ERR_WRITE);
- if (!(coll->co_options & CO_TRUSTSTATUSFILE))
- fattr_free(fa);
- /* XXX CVSup flushes here for some reason with a comment saying
- "Be smarter". We don't flush when listing other file types. */
- stream_flush(wr);
- return (0);
-}
-
-/* Handle a checkout live entry found in the status file. */
-static int
-lister_dofile(struct lister *l, struct coll *coll, struct statusrec *sr)
-{
- struct config *config;
- struct stream *wr;
- const struct fattr *sendattr, *fa;
- struct fattr *fa2, *rfa;
- char *path, *spath;
- int error;
-
- if (!globtree_test(coll->co_filefilter, sr->sr_file))
- return (0);
- config = l->config;
- wr = l->wr;
- rfa = NULL;
- sendattr = NULL;
- error = 0;
- if (!(coll->co_options & CO_TRUSTSTATUSFILE)) {
- path = checkoutpath(coll->co_prefix, sr->sr_file);
- if (path == NULL) {
- spath = coll_statuspath(coll);
- xasprintf(&l->errmsg, "Error in \"%s\": "
- "Invalid filename \"%s\"", spath, sr->sr_file);
- free(spath);
- return (LISTER_ERR_STATUS);
- }
- rfa = fattr_frompath(path, FATTR_NOFOLLOW);
- free(path);
- if (rfa == NULL) {
- /*
- * According to the checkouts file we should have
- * this file but we don't. Maybe the user deleted
- * the file, or maybe the checkouts file is wrong.
- * List the file with bogus attributes to cause the
- * server to get things back in sync again.
- */
- sendattr = fattr_bogus;
- goto send;
- }
- fa = rfa;
- } else {
- fa = sr->sr_clientattr;
- }
- fa2 = fattr_forcheckout(sr->sr_serverattr, coll->co_umask);
- if (!fattr_equal(fa, sr->sr_clientattr) || !fattr_equal(fa, fa2) ||
- strcmp(coll->co_tag, sr->sr_tag) != 0 ||
- strcmp(coll->co_date, sr->sr_date) != 0) {
- /*
- * The file corresponds to the information we have
- * recorded about it, and its moded is correct for
- * the requested umask setting.
- */
- sendattr = fattr_bogus;
- } else {
- /*
- * Either the file has been touched, or we are asking
- * for a different revision than the one we recorded
- * information about, or its mode isn't right (because
- * it was last updated using a version of CVSup that
- * wasn't so strict about modes).
- */
- sendattr = sr->sr_serverattr;
- }
- fattr_free(fa2);
- if (rfa != NULL)
- fattr_free(rfa);
-send:
- error = proto_printf(wr, "F %s %F\n", pathlast(sr->sr_file), sendattr,
- config->fasupport, coll->co_attrignore);
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
-}
-
-/* Handle a checkout dead entry found in the status file. */
-static int
-lister_dodead(struct lister *l, struct coll *coll, struct statusrec *sr)
-{
- struct config *config;
- struct stream *wr;
- const struct fattr *sendattr;
- struct fattr *fa;
- char *path, *spath;
- int error;
-
- if (!globtree_test(coll->co_filefilter, sr->sr_file))
- return (0);
- config = l->config;
- wr = l->wr;
- if (!(coll->co_options & CO_TRUSTSTATUSFILE)) {
- path = checkoutpath(coll->co_prefix, sr->sr_file);
- if (path == NULL) {
- spath = coll_statuspath(coll);
- xasprintf(&l->errmsg, "Error in \"%s\": "
- "Invalid filename \"%s\"", spath, sr->sr_file);
- free(spath);
- return (LISTER_ERR_STATUS);
- }
- fa = fattr_frompath(path, FATTR_NOFOLLOW);
- free(path);
- if (fa != NULL && fattr_type(fa) != FT_DIRECTORY) {
- /*
- * We shouldn't have this file but we do. Report
- * it to the server, which will either send a
- * deletion request, of (if the file has come alive)
- * sent the correct version.
- */
- fattr_free(fa);
- error = proto_printf(wr, "F %s %F\n",
- pathlast(sr->sr_file), fattr_bogus,
- config->fasupport, coll->co_attrignore);
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
- }
- fattr_free(fa);
- }
- if (strcmp(coll->co_tag, sr->sr_tag) != 0 ||
- strcmp(coll->co_date, sr->sr_date) != 0)
- sendattr = fattr_bogus;
- else
- sendattr = sr->sr_serverattr;
- error = proto_printf(wr, "f %s %F\n", pathlast(sr->sr_file), sendattr,
- config->fasupport, coll->co_attrignore);
- if (error)
- return (LISTER_ERR_WRITE);
- return (0);
-}
--- contrib/csup/globtree.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/globtree.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _GLOBTREE_H_
-#define _GLOBTREE_H_
-
-#include "fnmatch.h"
-
-struct globtree;
-
-struct globtree *globtree_true(void);
-struct globtree *globtree_false(void);
-struct globtree *globtree_match(const char *, int);
-struct globtree *globtree_regex(const char *);
-struct globtree *globtree_and(struct globtree *, struct globtree *);
-struct globtree *globtree_or(struct globtree *, struct globtree *);
-struct globtree *globtree_not(struct globtree *);
-int globtree_test(struct globtree *, const char *);
-void globtree_free(struct globtree *);
-
-#endif /* !_GLOBTREE_H_ */
--- contrib/csup/pathcomp.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/pathcomp.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "misc.h"
-#include "pathcomp.h"
-
-struct pathcomp {
- char *target;
- size_t targetlen;
- char *trashed;
- char *prev;
- size_t prevlen;
- size_t goal;
- size_t curlen;
-};
-
-struct pathcomp *
-pathcomp_new(void)
-{
- struct pathcomp *pc;
-
- pc = xmalloc(sizeof(struct pathcomp));
- pc->curlen = 0;
- pc->target = NULL;
- pc->targetlen = 0;
- pc->trashed = NULL;
- pc->prev = NULL;
- pc->prevlen = 0;
- return (pc);
-}
-
-int
-pathcomp_put(struct pathcomp *pc, int type, char *path)
-{
- char *cp;
-
- assert(pc->target == NULL);
- if (*path == '/')
- return (-1);
-
- switch (type) {
- case PC_DIRDOWN:
- pc->target = path;
- pc->targetlen = strlen(path);
- break;
- case PC_FILE:
- case PC_DIRUP:
- cp = strrchr(path, '/');
- pc->target = path;
- if (cp != NULL)
- pc->targetlen = cp - path;
- else
- pc->targetlen = 0;
- break;
- }
- if (pc->prev != NULL)
- pc->goal = commonpathlength(pc->prev, pc->prevlen, pc->target,
- pc->targetlen);
- else
- pc->goal = 0;
- if (pc->curlen == pc->goal) /* No need to go up. */
- pc->goal = pc->targetlen;
- return (0);
-}
-
-int
-pathcomp_get(struct pathcomp *pc, int *type, char **name)
-{
- char *cp;
- size_t slashpos, start;
-
- if (pc->curlen > pc->goal) { /* Going up. */
- assert(pc->prev != NULL);
- pc->prev[pc->curlen] = '\0';
- cp = pc->prev + pc->curlen - 1;
- while (cp >= pc->prev) {
- if (*cp == '/')
- break;
- cp--;
- }
- if (cp >= pc->prev)
- slashpos = cp - pc->prev;
- else
- slashpos = 0;
- pc->curlen = slashpos;
- if (pc->curlen <= pc->goal) { /* Done going up. */
- assert(pc->curlen == pc->goal);
- pc->goal = pc->targetlen;
- }
- *type = PC_DIRUP;
- *name = pc->prev;
- return (1);
- } else if (pc->curlen < pc->goal) { /* Going down. */
- /* Restore the previously overwritten '/' character. */
- if (pc->trashed != NULL) {
- *pc->trashed = '/';
- pc->trashed = NULL;
- }
- if (pc->curlen == 0)
- start = pc->curlen;
- else
- start = pc->curlen + 1;
- slashpos = start;
- while (slashpos < pc->goal) {
- if (pc->target[slashpos] == '/')
- break;
- slashpos++;
- }
- if (pc->target[slashpos] != '\0') {
- assert(pc->target[slashpos] == '/');
- pc->trashed = pc->target + slashpos;
- pc->target[slashpos] = '\0';
- }
- pc->curlen = slashpos;
- *type = PC_DIRDOWN;
- *name = pc->target;
- return (1);
- } else { /* Done. */
- if (pc->target != NULL) {
- if (pc->trashed != NULL) {
- *pc->trashed = '/';
- pc->trashed = NULL;
- }
- if (pc->prev != NULL)
- free(pc->prev);
- pc->prev = xmalloc(pc->targetlen + 1);
- memcpy(pc->prev, pc->target, pc->targetlen);
- pc->prev[pc->targetlen] = '\0';
- pc->prevlen = pc->targetlen;
- pc->target = NULL;
- pc->targetlen = 0;
- }
- return (0);
- }
-}
-
-void
-pathcomp_finish(struct pathcomp *pc)
-{
-
- pc->target = NULL;
- pc->targetlen = 0;
- pc->goal = 0;
-}
-
-void
-pathcomp_free(struct pathcomp *pc)
-{
-
- if (pc->prev != NULL)
- free(pc->prev);
- free(pc);
-}
--- contrib/csup/GNUmakefile
+++ /dev/null
@@ -1,64 +0,0 @@
-# A simple gmake Makefile, to be used on Linux and Darwin. It shouldn't
-# be used elsewhere because it assumes that the target system doesn't
-# support BSD extended file flags.
-#
-# $FreeBSD: src/contrib/csup/GNUmakefile,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
-# $MidnightBSD: src/contrib/csup/GNUmakefile,v 1.1 2006/12/27 01:28:42 laffer1 Exp $
-#
-
-PREFIX?=/usr/local
-OWNER?= 0
-GROUP?= 0
-
-UNAME= $(shell uname -s)
-
-SRCS= attrstack.c config.c detailer.c diff.c fattr.c fixups.c fnmatch.c \
- globtree.c idcache.c keyword.c lister.c main.c misc.c mux.c pathcomp.c \
- parse.c proto.c status.c stream.c threads.c token.c updater.c
-OBJS= $(SRCS:.c=.o)
-
-WARNS= -Wall -W -Wno-unused-parameter -Wmissing-prototypes -Wpointer-arith \
- -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wshadow \
- -Wcast-align -Wunused-parameter -Wchar-subscripts -Winline \
- -Wnested-externs -Wredundant-decls -Wno-format-y2k
-
-CFLAGS+= -g -O -pipe -DNDEBUG -I$(PREFIX)/include
-ifeq ($(UNAME), Linux)
- CFLAGS+= -D_XOPEN_SOURCE -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
-endif
-ifeq ($(UNAME), Darwin)
- CFLAGS+= -DHAVE_FFLAGS
-endif
-CFLAGS+= $(WARNS)
-LDFLAGS= -L$(PREFIX)/lib -lcrypto -lz -lpthread
-
-.PHONY: all clean install
-
-all: csup csup.1.gz
-
-csup: $(OBJS)
- $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
-
-config.c: parse.h
-
-token.c: token.l
-
-parse.c: parse.y
-
-parse.h: parse.c
-
-clean:
- rm -f csup $(OBJS) parse.c parse.h token.c csup.1.gz
-
-%.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $<
-
-%.c: %.y
- $(YACC) -d -o $@ $<
-
-csup.1.gz: csup.1
- gzip -cn $< > $@
-
-install: csup csup.1.gz
- install -s -o $(OWNER) -g $(GROUP) csup $(PREFIX)/bin
- install -s -o $(OWNER) -g $(GROUP) csup.1.gz $(PREFIX)/share/man/man1
--- contrib/csup/attrstack.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $Id$
- */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "attrstack.h"
-#include "fattr.h"
-#include "misc.h"
-
-#define ATTRSTACK_DEFSIZE 16 /* Initial size of the stack. */
-
-struct attrstack {
- struct fattr **stack;
- size_t cur;
- size_t size;
-};
-
-struct attrstack *
-attrstack_new(void)
-{
- struct attrstack *as;
-
- as = xmalloc(sizeof(struct attrstack));
- as->stack = xmalloc(sizeof(struct fattr *) * ATTRSTACK_DEFSIZE);
- as->size = ATTRSTACK_DEFSIZE;
- as->cur = 0;
- return (as);
-}
-
-struct fattr *
-attrstack_pop(struct attrstack *as)
-{
-
- assert(as->cur > 0);
- return (as->stack[--as->cur]);
-}
-
-void
-attrstack_push(struct attrstack *as, struct fattr *fa)
-{
-
- if (as->cur >= as->size) {
- as->size *= 2;
- as->stack = xrealloc(as->stack,
- sizeof(struct fattr *) * as->size);
- }
- as->stack[as->cur++] = fa;
-}
-
-size_t
-attrstack_size(struct attrstack *as)
-{
-
- return (as->cur);
-}
-
-void
-attrstack_free(struct attrstack *as)
-{
-
- assert(as->cur == 0);
- free(as->stack);
- free(as);
-}
--- contrib/csup/threads.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*-
- * Copyright (c) 2004-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/threads.c,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <assert.h>
-#include <err.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "misc.h"
-#include "queue.h"
-#include "threads.h"
-
-/*
- * This API is a wrapper around the pthread(3) API, which mainly
- * allows me to wait for multiple threads to exit. We use a
- * condition variable to signal a thread's death. All threads
- * created with this API have a common entry/exit point, so we
- * don't need to add any code in the threads themselves.
- */
-
-/* Structure describing a thread. */
-struct thread {
- pthread_t thread;
- void *(*start)(void *);
- void *data;
- struct threads *threads;
- LIST_ENTRY(thread) runlist;
- STAILQ_ENTRY(thread) deadlist;
-};
-
-/* A set of threads. */
-struct threads {
- pthread_mutex_t threads_mtx;
- pthread_cond_t thread_exited;
- LIST_HEAD(, thread) threads_running;
- STAILQ_HEAD(, thread) threads_dead;
-};
-
-static void *thread_start(void *); /* Common entry point for threads. */
-
-static void threads_lock(struct threads *);
-static void threads_unlock(struct threads *);
-
-static void
-threads_lock(struct threads *tds)
-{
- int error;
-
- error = pthread_mutex_lock(&tds->threads_mtx);
- assert(!error);
-}
-
-static void
-threads_unlock(struct threads *tds)
-{
- int error;
-
- error = pthread_mutex_unlock(&tds->threads_mtx);
- assert(!error);
-}
-
-/* Create a new set of threads. */
-struct threads *
-threads_new(void)
-{
- struct threads *tds;
-
- tds = xmalloc(sizeof(struct threads));
- pthread_mutex_init(&tds->threads_mtx, NULL);
- pthread_cond_init(&tds->thread_exited, NULL);
- LIST_INIT(&tds->threads_running);
- STAILQ_INIT(&tds->threads_dead);
- return (tds);
-}
-
-/* Create a new thread in this set. */
-void
-threads_create(struct threads *tds, void *(*start)(void *), void *data)
-{
- pthread_attr_t attr;
- struct thread *td;
- int error;
-
- td = xmalloc(sizeof(struct thread));
- td->threads = tds;
- td->start = start;
- td->data = data;
- /* We don't use pthread_join() to wait for the threads to finish. */
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- threads_lock(tds);
- error = pthread_create(&td->thread, &attr, thread_start, td);
- if (error)
- err(1, "pthread_create");
- LIST_INSERT_HEAD(&tds->threads_running, td, runlist);
- threads_unlock(tds);
-}
-
-/* Wait for a thread in the set to exit, and return its data pointer. */
-void *
-threads_wait(struct threads *tds)
-{
- struct thread *td;
- void *data;
-
- threads_lock(tds);
- while (STAILQ_EMPTY(&tds->threads_dead)) {
- assert(!LIST_EMPTY(&tds->threads_running));
- pthread_cond_wait(&tds->thread_exited, &tds->threads_mtx);
- }
- td = STAILQ_FIRST(&tds->threads_dead);
- STAILQ_REMOVE_HEAD(&tds->threads_dead, deadlist);
- threads_unlock(tds);
- data = td->data;
- free(td);
- return (data);
-}
-
-/* Free a threads set. */
-void
-threads_free(struct threads *tds)
-{
-
- assert(LIST_EMPTY(&tds->threads_running));
- assert(STAILQ_EMPTY(&tds->threads_dead));
- pthread_cond_destroy(&tds->thread_exited);
- pthread_mutex_destroy(&tds->threads_mtx);
- free(tds);
-}
-
-/*
- * Common entry point for threads. This just calls the real start
- * routine, and then signals the thread's death, after having
- * removed the thread from the list.
- */
-static void *
-thread_start(void *data)
-{
- struct threads *tds;
- struct thread *td;
-
- td = data;
- tds = td->threads;
- td->start(td->data);
- threads_lock(tds);
- LIST_REMOVE(td, runlist);
- STAILQ_INSERT_TAIL(&tds->threads_dead, td, deadlist);
- pthread_cond_signal(&tds->thread_exited);
- threads_unlock(tds);
- return (NULL);
-}
--- contrib/csup/main.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/main.c,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/file.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "fattr.h"
-#include "misc.h"
-#include "proto.h"
-#include "stream.h"
-
-#define USAGE_OPTFMT " %-12s %s\n"
-#define USAGE_OPTFMTSUB " %-14s %s\n", ""
-
-int verbose = 1;
-
-static void
-usage(char *argv0)
-{
-
- lprintf(-1, "Usage: %s [options] supfile\n", basename(argv0));
- lprintf(-1, " Options:\n");
- lprintf(-1, USAGE_OPTFMT, "-1", "Don't retry automatically on failure "
- "(same as \"-r 0\")");
- lprintf(-1, USAGE_OPTFMT, "-4", "Force usage of IPv4 addresses");
- lprintf(-1, USAGE_OPTFMT, "-6", "Force usage of IPv6 addresses");
- lprintf(-1, USAGE_OPTFMT, "-A addr",
- "Bind local socket to a specific address");
- lprintf(-1, USAGE_OPTFMT, "-b base",
- "Override supfile's \"base\" directory");
- lprintf(-1, USAGE_OPTFMT, "-c collDir",
- "Subdirectory of \"base\" for collections (default \"sup\")");
- lprintf(-1, USAGE_OPTFMT, "-d delLimit",
- "Allow at most \"delLimit\" file deletions (default unlimited)");
- lprintf(-1, USAGE_OPTFMT, "-h host",
- "Override supfile's \"host\" name");
- lprintf(-1, USAGE_OPTFMT, "-i pattern",
- "Include only files/directories matching pattern.");
- lprintf(-1, USAGE_OPTFMTSUB,
- "May be repeated for an OR operation. Default is");
- lprintf(-1, USAGE_OPTFMTSUB, "to include each entire collection.");
- lprintf(-1, USAGE_OPTFMT, "-k",
- "Keep bad temporary files when fixups are required");
- lprintf(-1, USAGE_OPTFMT, "-l lockfile",
- "Lock file during update; fail if already locked");
- lprintf(-1, USAGE_OPTFMT, "-L n",
- "Verbosity level (0..2, default 1)");
- lprintf(-1, USAGE_OPTFMT, "-p port",
- "Alternate server port (default 5999)");
- lprintf(-1, USAGE_OPTFMT, "-r n",
- "Maximum retries on transient errors (default unlimited)");
- lprintf(-1, USAGE_OPTFMT, "-s",
- "Don't stat client files; trust the checkouts file");
- lprintf(-1, USAGE_OPTFMT, "-v", "Print version and exit");
- lprintf(-1, USAGE_OPTFMT, "-z", "Enable compression for all "
- "collections");
- lprintf(-1, USAGE_OPTFMT, "-Z", "Disable compression for all "
- "collections");
-}
-
-int
-main(int argc, char *argv[])
-{
- struct tm tm;
- struct backoff_timer *timer;
- struct config *config;
- struct coll *override;
- struct addrinfo *res;
- struct sockaddr *laddr;
- socklen_t laddrlen;
- struct stream *lock;
- char *argv0, *file, *lockfile;
- int family, error, lockfd, lflag, overridemask;
- int c, i, deletelim, port, retries, status;
- time_t nexttry;
-
- error = 0;
- family = PF_UNSPEC;
- deletelim = -1;
- port = 0;
- lflag = 0;
- lockfd = 0;
- nexttry = 0;
- retries = -1;
- argv0 = argv[0];
- laddr = NULL;
- laddrlen = 0;
- lockfile = NULL;
- override = coll_new(NULL);
- overridemask = 0;
-
- while ((c = getopt(argc, argv,
- "146A:b:c:d:gh:i:kl:L:p:P:r:svzZ")) != -1) {
- switch (c) {
- case '1':
- retries = 0;
- break;
- case '4':
- family = AF_INET;
- break;
- case '6':
- family = AF_INET6;
- break;
- case 'A':
- error = getaddrinfo(optarg, NULL, NULL, &res);
- if (error) {
- lprintf(-1, "%s: %s\n", optarg,
- gai_strerror(error));
- return (1);
- }
- laddrlen = res->ai_addrlen;
- laddr = xmalloc(laddrlen);
- memcpy(laddr, res->ai_addr, laddrlen);
- freeaddrinfo(res);
- break;
- case 'b':
- if (override->co_base != NULL)
- free(override->co_base);
- override->co_base = xstrdup(optarg);
- break;
- case 'c':
- override->co_colldir = optarg;
- break;
- case 'd':
- error = asciitoint(optarg, &deletelim, 0);
- if (error || deletelim < 0) {
- lprintf(-1, "Invalid deletion limit\n");
- usage(argv0);
- return (1);
- }
- break;
- case 'g':
- /* For compatibility. */
- break;
- case 'h':
- if (override->co_host != NULL)
- free(override->co_host);
- override->co_host = xstrdup(optarg);
- break;
- case 'i':
- pattlist_add(override->co_accepts, optarg);
- break;
- case 'k':
- override->co_options |= CO_KEEPBADFILES;
- overridemask |= CO_KEEPBADFILES;
- break;
- case 'l':
- lockfile = optarg;
- lflag = 1;
- lockfd = open(lockfile,
- O_CREAT | O_WRONLY | O_TRUNC, 0700);
- if (lockfd != -1) {
- error = flock(lockfd, LOCK_EX | LOCK_NB);
- if (error == -1 && errno == EWOULDBLOCK) {
- if (lockfd != -1)
- close(lockfd);
- lprintf(-1, "\"%s\" is already locked "
- "by another process\n", lockfile);
- return (1);
- }
- }
- if (lockfd == -1 || error == -1) {
- if (lockfd != -1)
- close(lockfd);
- lprintf(-1, "Error locking \"%s\": %s\n",
- lockfile, strerror(errno));
- return (1);
- }
- lock = stream_open_fd(lockfd,
- NULL, stream_write_fd, NULL);
- (void)stream_printf(lock, "%10ld\n", (long)getpid());
- stream_close(lock);
- break;
- case 'L':
- error = asciitoint(optarg, &verbose, 0);
- if (error) {
- lprintf(-1, "Invalid verbosity\n");
- usage(argv0);
- return (1);
- }
- break;
- case 'p':
- /* Use specified server port. */
- error = asciitoint(optarg, &port, 0);
- if (error) {
- lprintf(-1, "Invalid server port\n");
- usage(argv0);
- return (1);
- }
- if (port <= 0 || port >= 65536) {
- lprintf(-1, "Invalid port %d\n", port);
- return (1);
- }
- if (port < 1024) {
- lprintf(-1, "Reserved port %d not permitted\n",
- port);
- return (1);
- }
- break;
- case 'P':
- /* For compatibility. */
- if (strcmp(optarg, "m") != 0) {
- lprintf(-1,
- "Client only supports multiplexed mode\n");
- return (1);
- }
- break;
- case 'r':
- error = asciitoint(optarg, &retries, 0);
- if (error || retries < 0) {
- lprintf(-1, "Invalid retry limit\n");
- usage(argv0);
- return (1);
- }
- break;
- case 's':
- override->co_options |= CO_TRUSTSTATUSFILE;
- overridemask |= CO_TRUSTSTATUSFILE;
- break;
- case 'v':
- lprintf(0, "CVSup client written in C\n");
- lprintf(0, "Software version: %s\n", PROTO_SWVER);
- lprintf(0, "Protocol version: %d.%d\n",
- PROTO_MAJ, PROTO_MIN);
- lprintf(0, "http://mu.org/~mux/csup.html\n");
- return (0);
- break;
- case 'z':
- /* Force compression on all collections. */
- override->co_options |= CO_COMPRESS;
- overridemask |= CO_COMPRESS;
- break;
- case 'Z':
- /* Disables compression on all collections. */
- override->co_options &= ~CO_COMPRESS;
- overridemask &= ~CO_COMPRESS;
- break;
- case '?':
- default:
- usage(argv0);
- return (1);
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc < 1) {
- usage(argv0);
- return (1);
- }
-
- file = argv[0];
- lprintf(2, "Parsing supfile \"%s\"\n", file);
- config = config_init(file, override, overridemask);
- coll_free(override);
- if (config == NULL)
- return (1);
-
- if (config_checkcolls(config) == 0) {
- lprintf(-1, "No collections selected\n");
- return (1);
- }
-
- if (laddr != NULL) {
- config->laddr = laddr;
- config->laddrlen = laddrlen;
- }
- config->deletelim = deletelim;
- lprintf(2, "Connecting to %s\n", config->host);
-
- i = 0;
- fattr_init(); /* Initialize the fattr API. */
- timer = bt_new(300, 7200, 2.0, 0.1);
- for (;;) {
- status = proto_connect(config, family, port);
- if (status == STATUS_SUCCESS) {
- status = proto_run(config);
- if (status != STATUS_TRANSIENTFAILURE)
- break;
- }
- if (retries >= 0 && i >= retries)
- break;
- nexttry = time(0) + bt_get(timer);
- localtime_r(&nexttry, &tm);
- lprintf(1, "Will retry at %02d:%02d:%02d\n",
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- bt_pause(timer);
- lprintf(1, "Retrying\n");
- i++;
- }
- bt_free(timer);
- fattr_fini();
- if (lflag) {
- unlink(lockfile);
- flock(lockfd, LOCK_UN);
- close(lockfd);
- }
- config_free(config);
- if (status != STATUS_SUCCESS)
- return (1);
- return (0);
-}
--- contrib/csup/idcache.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/idcache.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _IDCACHE_H_
-#define _IDCACHE_H_
-
-#include <sys/types.h>
-
-void idcache_init(void);
-void idcache_fini(void);
-
-char *getuserbyid(uid_t);
-char *getgroupbyid(gid_t);
-int getuidbyname(const char *, uid_t *);
-int getgidbyname(const char *, gid_t *);
-
-#endif /* !_IDCACHE_H_ */
--- contrib/csup/diff.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/diff.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "diff.h"
-#include "keyword.h"
-#include "misc.h"
-#include "stream.h"
-
-typedef long lineno_t;
-
-#define EC_ADD 0
-#define EC_DEL 1
-
-/* Editing command and state. */
-struct editcmd {
- int cmd;
- lineno_t where;
- lineno_t count;
- lineno_t lasta;
- lineno_t lastd;
- lineno_t editline;
- /* For convenience. */
- struct keyword *keyword;
- struct diffinfo *di;
- struct stream *orig;
- struct stream *dest;
-};
-
-static int diff_geteditcmd(struct editcmd *, char *);
-static int diff_copyln(struct editcmd *, lineno_t);
-static void diff_write(struct editcmd *, void *, size_t);
-
-int
-diff_apply(struct stream *rd, struct stream *orig, struct stream *dest,
- struct keyword *keyword, struct diffinfo *di)
-{
- struct editcmd ec;
- lineno_t i;
- char *line;
- size_t size;
- int empty, error, noeol;
-
- memset(&ec, 0, sizeof(ec));
- empty = 0;
- noeol = 0;
- ec.di = di;
- ec.keyword = keyword;
- ec.orig = orig;
- ec.dest = dest;
- line = stream_getln(rd, NULL);
- while (line != NULL && strcmp(line, ".") != 0 &&
- strcmp(line, ".+") != 0) {
- /*
- * The server sends an empty line and then terminates
- * with .+ for forced (and thus empty) commits.
- */
- if (*line == '\0') {
- if (empty)
- return (-1);
- empty = 1;
- line = stream_getln(rd, NULL);
- continue;
- }
- error = diff_geteditcmd(&ec, line);
- if (error)
- return (-1);
-
- if (ec.cmd == EC_ADD) {
- error = diff_copyln(&ec, ec.where);
- if (error)
- return (-1);
- for (i = 0; i < ec.count; i++) {
- line = stream_getln(rd, &size);
- if (line == NULL)
- return (-1);
- if (line[0] == '.') {
- line++;
- size--;
- }
- diff_write(&ec, line, size);
- }
- } else {
- assert(ec.cmd == EC_DEL);
- error = diff_copyln(&ec, ec.where - 1);
- if (error)
- return (-1);
- for (i = 0; i < ec.count; i++) {
- line = stream_getln(orig, NULL);
- if (line == NULL)
- return (-1);
- ec.editline++;
- }
- }
- line = stream_getln(rd, NULL);
- }
- if (line == NULL)
- return (-1);
- /* If we got ".+", there's no ending newline. */
- if (strcmp(line, ".+") == 0 && !empty)
- noeol = 1;
- ec.where = 0;
- while ((line = stream_getln(orig, &size)) != NULL)
- diff_write(&ec, line, size);
- stream_flush(dest);
- if (noeol) {
- error = stream_truncate_rel(dest, -1);
- if (error) {
- warn("stream_truncate_rel");
- return (-1);
- }
- }
- return (0);
-}
-
-/* Get an editing command from the diff. */
-static int
-diff_geteditcmd(struct editcmd *ec, char *line)
-{
- char *end;
-
- if (line[0] == 'a')
- ec->cmd = EC_ADD;
- else if (line[0] == 'd')
- ec->cmd = EC_DEL;
- else
- return (-1);
- errno = 0;
- ec->where = strtol(line + 1, &end, 10);
- if (errno || ec->where < 0 || *end != ' ')
- return (-1);
- line = end + 1;
- errno = 0;
- ec->count = strtol(line, &end, 10);
- if (errno || ec->count <= 0 || *end != '\0')
- return (-1);
- if (ec->cmd == EC_ADD) {
- if (ec->where < ec->lasta)
- return (-1);
- ec->lasta = ec->where + 1;
- } else {
- if (ec->where < ec->lasta || ec->where < ec->lastd)
- return (-1);
- ec->lasta = ec->where;
- ec->lastd = ec->where + ec->count;
- }
- return (0);
-}
-
-/* Copy lines from the original version of the file up to line "to". */
-static int
-diff_copyln(struct editcmd *ec, lineno_t to)
-{
- char *line;
- size_t size;
-
- while (ec->editline < to) {
- line = stream_getln(ec->orig, &size);
- if (line == NULL)
- return (-1);
- ec->editline++;
- diff_write(ec, line, size);
- }
- return (0);
-}
-
-/* Write a new line to the file, expanding RCS keywords appropriately. */
-static void
-diff_write(struct editcmd *ec, void *buf, size_t size)
-{
- char *line, *newline;
- size_t newsize;
- int ret;
-
- line = buf;
- ret = keyword_expand(ec->keyword, ec->di, line, size,
- &newline, &newsize);
- if (ret) {
- stream_write(ec->dest, newline, newsize);
- free(newline);
- } else {
- stream_write(ec->dest, buf, size);
- }
-}
--- contrib/csup/proto.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/proto.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _PROTO_H_
-#define _PROTO_H_
-
-#include <time.h>
-
-#include "misc.h"
-
-#define PROTO_MAJ 17
-#define PROTO_MIN 0
-#define PROTO_SWVER "CSUP_1_0"
-
-struct stream;
-
-int proto_connect(struct config *, int, uint16_t);
-int proto_run(struct config *);
-int proto_printf(struct stream *, const char *, ...);
-char *proto_get_ascii(char **);
-char *proto_get_rest(char **);
-int proto_get_int(char **, int *, int);
-int proto_get_time(char **, time_t *);
-
-#endif /* !_PROTO_H_ */
--- contrib/csup/TODO
+++ /dev/null
@@ -1,32 +0,0 @@
-$FreeBSD: src/contrib/csup/TODO,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
-$MidnightBSD: src/contrib/csup/TODO,v 1.1 2006/12/27 01:28:42 laffer1 Exp $
-
-BUGS:
-
-- Fix every XXX in the code :-).
-- The stream API needs some polishing. It needs proper error numbers
- and a stream_error() function similar to the ferror() function.
-- The yacc/lex code to parse the configuration file is sub-optimal. It
- has global variables because of yacc, but I think it should be possible
- to do it better by using YYFUNC_PROTOTYPE or something. I think it
- should also be possible to completely get rid of the lex file.
-- The $Log$ CVS keyword is not supported.
-- Add missing support for supfile keywords and add sanity checks for
- some of them. Also, we're not supposed to choke on unknown keywords
- to stay in line with CVSup, which just ignores them in order to
- maintain compatibility with sup configuration files.
-
-MISSING FEATURES:
-
-- Add support for authentication.
-- Add support for shell commands sent by the server.
-- Add missing support for various CVSup options : -D, -a (requires
- authentication support), -e and -E (requires shell commands support)
- and the destDir parameter.
-- For now, this code should build fine on FreeBSD, NetBSD, OpenBSD,
- Linux and Darwin. Solaris support would also be nice at some point.
-- Implement some new useful options : the ability to generate CVS
- checkout files (files in CVS/ subdirectores), a command line override
- to only update a specific collection and a third verbosity level to
- display commit log messages.
-- Add support for CVS mode (maybe?).
--- contrib/csup/keyword.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/keyword.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _KEYWORD_H_
-#define _KEYWORD_H_
-
-/* CVS expansion modes. */
-#define EXPAND_DEFAULT 0
-#define EXPAND_KEYVALUE 1
-#define EXPAND_KEYVALUELOCKER 2
-#define EXPAND_KEY 3
-#define EXPAND_OLD 4
-#define EXPAND_BINARY 5
-#define EXPAND_VALUE 6
-
-struct diffinfo;
-struct keyword;
-
-struct keyword *keyword_new(void);
-int keyword_decode_expand(const char *);
-int keyword_alias(struct keyword *, const char *, const char *);
-int keyword_enable(struct keyword *, const char *);
-int keyword_disable(struct keyword *, const char *);
-void keyword_prepare(struct keyword *);
-int keyword_expand(struct keyword *, struct diffinfo *, char *,
- size_t, char **, size_t *);
-void keyword_free(struct keyword *);
-
-#endif /* !_KEYWORD_H_ */
--- contrib/csup/updater.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/updater.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _UPDATER_H_
-#define _UPDATER_H
-
-void *updater(void *);
-
-#endif /* !_UPDATER_H_ */
--- contrib/csup/updater.c
+++ /dev/null
@@ -1,1011 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/updater.c,v 1.1.1.2.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "diff.h"
-#include "fattr.h"
-#include "fixups.h"
-#include "keyword.h"
-#include "updater.h"
-#include "misc.h"
-#include "mux.h"
-#include "proto.h"
-#include "status.h"
-#include "stream.h"
-
-/* Internal error codes. */
-#define UPDATER_ERR_PROTO (-1) /* Protocol error. */
-#define UPDATER_ERR_MSG (-2) /* Error is in updater->errmsg. */
-#define UPDATER_ERR_READ (-3) /* Error reading from server. */
-#define UPDATER_ERR_DELETELIM (-4) /* File deletion limit exceeded. */
-
-/* Everything needed to update a file. */
-struct file_update {
- struct statusrec srbuf;
- char *destpath;
- char *temppath;
- char *coname; /* Points somewhere in destpath. */
- char *wantmd5;
- struct coll *coll;
- struct status *st;
- /* Those are only used for diff updating. */
- char *author;
- struct stream *orig;
- struct stream *to;
- int expand;
-};
-
-struct updater {
- struct config *config;
- struct stream *rd;
- char *errmsg;
- int deletecount;
-};
-
-static struct file_update *fup_new(struct coll *, struct status *);
-static int fup_prepare(struct file_update *, char *);
-static void fup_cleanup(struct file_update *);
-static void fup_free(struct file_update *);
-
-static void updater_prunedirs(char *, char *);
-static int updater_batch(struct updater *, int);
-static int updater_docoll(struct updater *, struct file_update *, int);
-static int updater_delete(struct updater *, struct file_update *);
-static void updater_deletefile(const char *);
-static int updater_checkout(struct updater *, struct file_update *, int);
-static int updater_setattrs(struct updater *, struct file_update *,
- char *, char *, char *, char *, char *, struct fattr *);
-static int updater_updatefile(struct updater *, struct file_update *fup,
- const char *, int);
-static int updater_diff(struct updater *, struct file_update *);
-static int updater_diff_batch(struct updater *, struct file_update *);
-static int updater_diff_apply(struct updater *, struct file_update *,
- char *);
-
-static struct file_update *
-fup_new(struct coll *coll, struct status *st)
-{
- struct file_update *fup;
-
- fup = xmalloc(sizeof(struct file_update));
- memset(fup, 0, sizeof(*fup));
- fup->coll = coll;
- fup->st = st;
- return (fup);
-}
-
-static int
-fup_prepare(struct file_update *fup, char *name)
-{
- struct coll *coll;
-
- coll = fup->coll;
- fup->destpath = checkoutpath(coll->co_prefix, name);
- if (fup->destpath == NULL)
- return (-1);
- fup->coname = fup->destpath + coll->co_prefixlen + 1;
- return (0);
-}
-
-/* Called after each file update to reinit the structure. */
-static void
-fup_cleanup(struct file_update *fup)
-{
- struct statusrec *sr;
-
- sr = &fup->srbuf;
-
- if (fup->destpath != NULL) {
- free(fup->destpath);
- fup->destpath = NULL;
- }
- if (fup->temppath != NULL) {
- free(fup->temppath);
- fup->temppath = NULL;
- }
- fup->coname = NULL;
- if (fup->author != NULL) {
- free(fup->author);
- fup->author = NULL;
- }
- fup->expand = 0;
- if (fup->wantmd5 != NULL) {
- free(fup->wantmd5);
- fup->wantmd5 = NULL;
- }
- if (fup->orig != NULL) {
- stream_close(fup->orig);
- fup->orig = NULL;
- }
- if (fup->to != NULL) {
- stream_close(fup->to);
- fup->to = NULL;
- }
- if (sr->sr_file != NULL)
- free(sr->sr_file);
- if (sr->sr_tag != NULL)
- free(sr->sr_tag);
- if (sr->sr_date != NULL)
- free(sr->sr_date);
- if (sr->sr_revnum != NULL)
- free(sr->sr_revnum);
- if (sr->sr_revdate != NULL)
- free(sr->sr_revdate);
- fattr_free(sr->sr_clientattr);
- fattr_free(sr->sr_serverattr);
- memset(sr, 0, sizeof(*sr));
-}
-
-static void
-fup_free(struct file_update *fup)
-{
-
- fup_cleanup(fup);
- free(fup);
-}
-
-void *
-updater(void *arg)
-{
- struct thread_args *args;
- struct updater upbuf, *up;
- int error;
-
- args = arg;
-
- up = &upbuf;
- up->config = args->config;
- up->rd = args->rd;
- up->errmsg = NULL;
- up->deletecount = 0;
-
- error = updater_batch(up, 0);
-
- /*
- * Make sure to close the fixups even in case of an error,
- * so that the lister thread doesn't block indefinitely.
- */
- fixups_close(up->config->fixups);
- if (!error)
- error = updater_batch(up, 1);
- switch (error) {
- case UPDATER_ERR_PROTO:
- xasprintf(&args->errmsg, "Updater failed: Protocol error");
- args->status = STATUS_FAILURE;
- break;
- case UPDATER_ERR_MSG:
- xasprintf(&args->errmsg, "Updater failed: %s", up->errmsg);
- free(up->errmsg);
- args->status = STATUS_FAILURE;
- break;
- case UPDATER_ERR_READ:
- if (stream_eof(up->rd)) {
- xasprintf(&args->errmsg, "Updater failed: "
- "Premature EOF from server");
- } else {
- xasprintf(&args->errmsg, "Updater failed: "
- "Network read failure: %s", strerror(errno));
- }
- args->status = STATUS_TRANSIENTFAILURE;
- break;
- case UPDATER_ERR_DELETELIM:
- xasprintf(&args->errmsg, "Updater failed: "
- "File deletion limit exceeded");
- args->status = STATUS_FAILURE;
- break;
- default:
- assert(error == 0);
- args->status = STATUS_SUCCESS;
- };
- return (NULL);
-}
-
-static int
-updater_batch(struct updater *up, int isfixups)
-{
- struct stream *rd;
- struct coll *coll;
- struct status *st;
- struct file_update *fup;
- char *line, *cmd, *errmsg, *collname, *release;
- int error;
-
- rd = up->rd;
- STAILQ_FOREACH(coll, &up->config->colls, co_next) {
- if (coll->co_options & CO_SKIP)
- continue;
- umask(coll->co_umask);
- line = stream_getln(rd, NULL);
- if (line == NULL)
- return (UPDATER_ERR_READ);
- cmd = proto_get_ascii(&line);
- collname = proto_get_ascii(&line);
- release = proto_get_ascii(&line);
- if (release == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
- if (strcmp(cmd, "COLL") != 0 ||
- strcmp(collname, coll->co_name) != 0 ||
- strcmp(release, coll->co_release) != 0)
- return (UPDATER_ERR_PROTO);
-
- if (!isfixups)
- lprintf(1, "Updating collection %s/%s\n", coll->co_name,
- coll->co_release);
-
- if (coll->co_options & CO_COMPRESS)
- stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL);
-
- st = status_open(coll, coll->co_scantime, &errmsg);
- if (st == NULL) {
- up->errmsg = errmsg;
- return (UPDATER_ERR_MSG);
- }
- fup = fup_new(coll, st);
- error = updater_docoll(up, fup, isfixups);
- status_close(st, &errmsg);
- fup_free(fup);
- if (errmsg != NULL) {
- /* Discard previous error. */
- if (up->errmsg != NULL)
- free(up->errmsg);
- up->errmsg = errmsg;
- return (UPDATER_ERR_MSG);
- }
- if (error)
- return (error);
-
- if (coll->co_options & CO_COMPRESS)
- stream_filter_stop(rd);
- }
- line = stream_getln(rd, NULL);
- if (line == NULL)
- return (UPDATER_ERR_READ);
- if (strcmp(line, ".") != 0)
- return (UPDATER_ERR_PROTO);
- return (0);
-}
-
-static int
-updater_docoll(struct updater *up, struct file_update *fup, int isfixups)
-{
- struct stream *rd;
- struct coll *coll;
- struct statusrec srbuf, *sr;
- struct fattr *rcsattr, *tmp;
- char *cmd, *line, *msg, *attr;
- char *name, *tag, *date, *revdate;
- char *expand, *wantmd5, *revnum;
- time_t t;
- int error, needfixupmsg;
-
- error = 0;
- rd = up->rd;
- coll = fup->coll;
- needfixupmsg = isfixups;
- while ((line = stream_getln(rd, NULL)) != NULL) {
- if (strcmp(line, ".") == 0)
- break;
- memset(&srbuf, 0, sizeof(srbuf));
- if (needfixupmsg) {
- lprintf(1, "Applying fixups for collection %s/%s\n",
- coll->co_name, coll->co_release);
- needfixupmsg = 0;
- }
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || strlen(cmd) != 1)
- return (UPDATER_ERR_PROTO);
- switch (cmd[0]) {
- case 'T':
- /* Update recorded information for checked-out file. */
- name = proto_get_ascii(&line);
- tag = proto_get_ascii(&line);
- date = proto_get_ascii(&line);
- revnum = proto_get_ascii(&line);
- revdate = proto_get_ascii(&line);
- attr = proto_get_ascii(&line);
- if (attr == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
-
- rcsattr = fattr_decode(attr);
- if (rcsattr == NULL)
- return (UPDATER_ERR_PROTO);
-
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
- error = updater_setattrs(up, fup, name, tag, date,
- revnum, revdate, rcsattr);
- fattr_free(rcsattr);
- if (error)
- return (error);
- break;
- case 'c':
- /* Checkout dead file. */
- name = proto_get_ascii(&line);
- tag = proto_get_ascii(&line);
- date = proto_get_ascii(&line);
- attr = proto_get_ascii(&line);
- if (attr == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
-
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
- /* Theoritically, the file does not exist on the client.
- Just to make sure, we'll delete it here, if it
- exists. */
- if (access(fup->destpath, F_OK) == 0) {
- error = updater_delete(up, fup);
- if (error)
- return (error);
- }
-
- sr = &srbuf;
- sr->sr_type = SR_CHECKOUTDEAD;
- sr->sr_file = name;
- sr->sr_tag = tag;
- sr->sr_date = date;
- sr->sr_serverattr = fattr_decode(attr);
- if (sr->sr_serverattr == NULL)
- return (UPDATER_ERR_PROTO);
-
- error = status_put(fup->st, sr);
- fattr_free(sr->sr_serverattr);
- if (error) {
- up->errmsg = status_errmsg(fup->st);
- return (UPDATER_ERR_MSG);
- }
- break;
- case 'U':
- /* Update live checked-out file. */
- name = proto_get_ascii(&line);
- tag = proto_get_ascii(&line);
- date = proto_get_ascii(&line);
- proto_get_ascii(&line); /* XXX - oldRevNum */
- proto_get_ascii(&line); /* XXX - fromAttic */
- proto_get_ascii(&line); /* XXX - logLines */
- expand = proto_get_ascii(&line);
- attr = proto_get_ascii(&line);
- wantmd5 = proto_get_ascii(&line);
- if (wantmd5 == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
-
- sr = &fup->srbuf;
- sr->sr_type = SR_CHECKOUTLIVE;
- sr->sr_file = xstrdup(name);
- sr->sr_date = xstrdup(date);
- sr->sr_tag = xstrdup(tag);
- sr->sr_serverattr = fattr_decode(attr);
- if (sr->sr_serverattr == NULL)
- return (UPDATER_ERR_PROTO);
-
- fup->expand = keyword_decode_expand(expand);
- if (fup->expand == -1)
- return (UPDATER_ERR_PROTO);
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
-
- fup->wantmd5 = xstrdup(wantmd5);
- fup->temppath = tempname(fup->destpath);
- error = updater_diff(up, fup);
- if (error)
- return (error);
- break;
- case 'u':
- /* Update dead checked-out file. */
- name = proto_get_ascii(&line);
- tag = proto_get_ascii(&line);
- date = proto_get_ascii(&line);
- attr = proto_get_ascii(&line);
- if (attr == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
-
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
- error = updater_delete(up, fup);
- if (error)
- return (error);
- sr = &srbuf;
- sr->sr_type = SR_CHECKOUTDEAD;
- sr->sr_file = name;
- sr->sr_tag = tag;
- sr->sr_date = date;
- sr->sr_serverattr = fattr_decode(attr);
- if (sr->sr_serverattr == NULL)
- return (UPDATER_ERR_PROTO);
- error = status_put(fup->st, sr);
- fattr_free(sr->sr_serverattr);
- if (error) {
- up->errmsg = status_errmsg(fup->st);
- return (UPDATER_ERR_MSG);
- }
- break;
- case 'C':
- case 'Y':
- /* Checkout file. */
- name = proto_get_ascii(&line);
- tag = proto_get_ascii(&line);
- date = proto_get_ascii(&line);
- revnum = proto_get_ascii(&line);
- revdate = proto_get_ascii(&line);
- attr = proto_get_ascii(&line);
- if (attr == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
-
- sr = &fup->srbuf;
- sr->sr_type = SR_CHECKOUTLIVE;
- sr->sr_file = xstrdup(name);
- sr->sr_tag = xstrdup(tag);
- sr->sr_date = xstrdup(date);
- sr->sr_revnum = xstrdup(revnum);
- sr->sr_revdate = xstrdup(revdate);
- sr->sr_serverattr = fattr_decode(attr);
- if (sr->sr_serverattr == NULL)
- return (UPDATER_ERR_PROTO);
-
- t = rcsdatetotime(revdate);
- if (t == -1)
- return (UPDATER_ERR_PROTO);
-
- sr->sr_clientattr = fattr_new(FT_FILE, t);
- tmp = fattr_forcheckout(sr->sr_serverattr,
- coll->co_umask);
- fattr_override(sr->sr_clientattr, tmp, FA_MASK);
- fattr_free(tmp);
- fattr_mergedefault(sr->sr_clientattr);
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
- fup->temppath = tempname(fup->destpath);
- if (*cmd == 'Y')
- error = updater_checkout(up, fup, 1);
- else
- error = updater_checkout(up, fup, 0);
- if (error)
- return (error);
- break;
- case 'D':
- /* Delete file. */
- name = proto_get_ascii(&line);
- if (name == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
- error = fup_prepare(fup, name);
- if (error)
- return (UPDATER_ERR_PROTO);
- error = updater_delete(up, fup);
- if (error)
- return (error);
- error = status_delete(fup->st, name, 0);
- if (error) {
- up->errmsg = status_errmsg(fup->st);
- return (UPDATER_ERR_MSG);
- }
- break;
- case '!':
- /* Warning from server. */
- msg = proto_get_rest(&line);
- if (msg == NULL)
- return (UPDATER_ERR_PROTO);
- lprintf(-1, "Server warning: %s\n", msg);
- break;
- default:
- return (UPDATER_ERR_PROTO);
- }
- fup_cleanup(fup);
- }
- if (line == NULL)
- return (UPDATER_ERR_READ);
- return (0);
-}
-
-/* Delete file. */
-static int
-updater_delete(struct updater *up, struct file_update *fup)
-{
- struct config *config;
- struct coll *coll;
-
- config = up->config;
- coll = fup->coll;
- if (coll->co_options & CO_DELETE) {
- lprintf(1, " Delete %s\n", fup->coname);
- if (config->deletelim >= 0 &&
- up->deletecount >= config->deletelim)
- return (UPDATER_ERR_DELETELIM);
- up->deletecount++;
- updater_deletefile(fup->destpath);
- if (coll->co_options & CO_CHECKOUTMODE)
- updater_prunedirs(coll->co_prefix, fup->destpath);
- } else {
- lprintf(1," NoDelete %s\n", fup->coname);
- }
- return (0);
-}
-
-static void
-updater_deletefile(const char *path)
-{
- int error;
-
- error = fattr_delete(path);
- if (error && errno != ENOENT) {
- lprintf(-1, "Cannot delete \"%s\": %s\n",
- path, strerror(errno));
- }
-}
-
-static int
-updater_setattrs(struct updater *up, struct file_update *fup, char *name,
- char *tag, char *date, char *revnum, char *revdate, struct fattr *rcsattr)
-{
- struct statusrec sr;
- struct status *st;
- struct coll *coll;
- struct fattr *fileattr, *fa;
- char *path;
- int error, rv;
-
- coll = fup->coll;
- st = fup->st;
- path = fup->destpath;
-
- fileattr = fattr_frompath(path, FATTR_NOFOLLOW);
- if (fileattr == NULL) {
- /* The file has vanished. */
- error = status_delete(st, name, 0);
- if (error) {
- up->errmsg = status_errmsg(st);
- return (UPDATER_ERR_MSG);
- }
- return (0);
- }
- fa = fattr_forcheckout(rcsattr, coll->co_umask);
- fattr_override(fileattr, fa, FA_MASK);
- fattr_free(fa);
-
- rv = fattr_install(fileattr, path, NULL);
- if (rv == -1) {
- lprintf(1, " SetAttrs %s\n", fup->coname);
- fattr_free(fileattr);
- xasprintf(&up->errmsg, "Cannot set attributes for \"%s\": %s",
- path, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- if (rv == 1) {
- lprintf(1, " SetAttrs %s\n", fup->coname);
- fattr_free(fileattr);
- fileattr = fattr_frompath(path, FATTR_NOFOLLOW);
- if (fileattr == NULL) {
- /* We're being very unlucky. */
- error = status_delete(st, name, 0);
- if (error) {
- up->errmsg = status_errmsg(st);
- return (UPDATER_ERR_MSG);
- }
- return (0);
- }
- }
-
- fattr_maskout(fileattr, FA_COIGNORE);
-
- sr.sr_type = SR_CHECKOUTLIVE;
- sr.sr_file = name;
- sr.sr_tag = tag;
- sr.sr_date = date;
- sr.sr_revnum = revnum;
- sr.sr_revdate = revdate;
- sr.sr_clientattr = fileattr;
- sr.sr_serverattr = rcsattr;
-
- error = status_put(st, &sr);
- fattr_free(fileattr);
- if (error) {
- up->errmsg = status_errmsg(st);
- return (UPDATER_ERR_MSG);
- }
- return (0);
-}
-
-static int
-updater_updatefile(struct updater *up, struct file_update *fup,
- const char *md5, int isfixup)
-{
- struct coll *coll;
- struct status *st;
- struct statusrec *sr;
- struct fattr *fileattr;
- int error, rv;
-
- coll = fup->coll;
- sr = &fup->srbuf;
- st = fup->st;
-
- if (strcmp(fup->wantmd5, md5) != 0) {
- if (isfixup) {
- lprintf(-1, "%s: Checksum mismatch -- "
- "file not updated\n", fup->destpath);
- } else {
- lprintf(-1, "%s: Checksum mismatch -- "
- "will transfer entire file\n", fup->destpath);
- fixups_put(up->config->fixups, fup->coll, sr->sr_file);
- }
- if (coll->co_options & CO_KEEPBADFILES)
- lprintf(-1, "Bad version saved in %s\n", fup->temppath);
- else
- updater_deletefile(fup->temppath);
- return (0);
- }
-
- fattr_umask(sr->sr_clientattr, coll->co_umask);
- rv = fattr_install(sr->sr_clientattr, fup->destpath, fup->temppath);
- if (rv == -1) {
- xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s",
- fup->temppath, fup->destpath, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
-
- /* XXX Executes */
- /*
- * We weren't necessarily able to set all the file attributes to the
- * desired values, and any executes may have altered the attributes.
- * To make sure we record the actual attribute values, we fetch
- * them from the file.
- *
- * However, we preserve the link count as received from the
- * server. This is important for preserving hard links in mirror
- * mode.
- */
- fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
- if (fileattr == NULL) {
- xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath,
- strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT);
- fattr_free(sr->sr_clientattr);
- sr->sr_clientattr = fileattr;
-
- /*
- * To save space, don't write out the device and inode unless
- * the link count is greater than 1. These attributes are used
- * only for detecting hard links. If the link count is 1 then we
- * know there aren't any hard links.
- */
- if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) ||
- fattr_getlinkcount(sr->sr_clientattr) <= 1)
- fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE);
-
- if (coll->co_options & CO_CHECKOUTMODE)
- fattr_maskout(sr->sr_clientattr, FA_COIGNORE);
-
- error = status_put(st, sr);
- if (error) {
- up->errmsg = status_errmsg(st);
- return (UPDATER_ERR_MSG);
- }
- return (0);
-}
-
-static int
-updater_diff(struct updater *up, struct file_update *fup)
-{
- char md5[MD5_DIGEST_SIZE];
- struct coll *coll;
- struct statusrec *sr;
- struct fattr *fa, *tmp;
- char *author, *path, *revnum, *revdate;
- char *line, *cmd;
- int error;
-
- coll = fup->coll;
- sr = &fup->srbuf;
- path = fup->destpath;
-
- lprintf(1, " Edit %s\n", fup->coname);
- while ((line = stream_getln(up->rd, NULL)) != NULL) {
- if (strcmp(line, ".") == 0)
- break;
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || strcmp(cmd, "D") != 0)
- return (UPDATER_ERR_PROTO);
- revnum = proto_get_ascii(&line);
- proto_get_ascii(&line); /* XXX - diffbase */
- revdate = proto_get_ascii(&line);
- author = proto_get_ascii(&line);
- if (author == NULL || line != NULL)
- return (UPDATER_ERR_PROTO);
- if (sr->sr_revnum != NULL)
- free(sr->sr_revnum);
- if (sr->sr_revdate != NULL)
- free(sr->sr_revdate);
- if (fup->author != NULL)
- free(fup->author);
- sr->sr_revnum = xstrdup(revnum);
- sr->sr_revdate = xstrdup(revdate);
- fup->author = xstrdup(author);
- if (fup->orig == NULL) {
- /* First patch, the "origin" file is the one we have. */
- fup->orig = stream_open_file(path, O_RDONLY);
- if (fup->orig == NULL) {
- xasprintf(&up->errmsg, "%s: Cannot open: %s",
- path, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- } else {
- /* Subsequent patches. */
- stream_close(fup->orig);
- fup->orig = fup->to;
- stream_rewind(fup->orig);
- unlink(fup->temppath);
- free(fup->temppath);
- fup->temppath = tempname(path);
- }
- fup->to = stream_open_file(fup->temppath,
- O_RDWR | O_CREAT | O_TRUNC, 0600);
- if (fup->to == NULL) {
- xasprintf(&up->errmsg, "%s: Cannot open: %s",
- fup->temppath, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- lprintf(2, " Add delta %s %s %s\n", sr->sr_revnum,
- sr->sr_revdate, fup->author);
- error = updater_diff_batch(up, fup);
- if (error)
- return (error);
- }
- if (line == NULL)
- return (UPDATER_ERR_READ);
-
- fa = fattr_frompath(path, FATTR_FOLLOW);
- tmp = fattr_forcheckout(sr->sr_serverattr, coll->co_umask);
- fattr_override(fa, tmp, FA_MASK);
- fattr_free(tmp);
- fattr_maskout(fa, FA_MODTIME);
- sr->sr_clientattr = fa;
-
- if (MD5_File(fup->temppath, md5) == -1) {
- xasprintf(&up->errmsg,
- "Cannot calculate checksum for \"%s\": %s",
- path, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- error = updater_updatefile(up, fup, md5, 0);
- return (error);
-}
-
-static int
-updater_diff_batch(struct updater *up, struct file_update *fup)
-{
- struct stream *rd;
- char *cmd, *line, *state, *tok;
- int error;
-
- state = NULL;
- rd = up->rd;
- while ((line = stream_getln(rd, NULL)) != NULL) {
- if (strcmp(line, ".") == 0)
- break;
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || strlen(cmd) != 1) {
- error = UPDATER_ERR_PROTO;
- goto bad;
- }
- switch (cmd[0]) {
- case 'L':
- line = stream_getln(rd, NULL);
- /* XXX - We're just eating the log for now. */
- while (line != NULL && strcmp(line, ".") != 0 &&
- strcmp(line, ".+") != 0)
- line = stream_getln(rd, NULL);
- if (line == NULL) {
- error = UPDATER_ERR_READ;
- goto bad;
- }
- break;
- case 'S':
- tok = proto_get_ascii(&line);
- if (tok == NULL || line != NULL) {
- error = UPDATER_ERR_PROTO;
- goto bad;
- }
- if (state != NULL)
- free(state);
- state = xstrdup(tok);
- break;
- case 'T':
- error = updater_diff_apply(up, fup, state);
- if (error)
- goto bad;
- break;
- default:
- error = UPDATER_ERR_PROTO;
- goto bad;
- }
- }
- if (line == NULL) {
- error = UPDATER_ERR_READ;
- goto bad;
- }
- if (state != NULL)
- free(state);
- return (0);
-bad:
- if (state != NULL)
- free(state);
- return (error);
-}
-
-int
-updater_diff_apply(struct updater *up, struct file_update *fup, char *state)
-{
- struct diffinfo dibuf, *di;
- struct coll *coll;
- struct statusrec *sr;
- int error;
-
- coll = fup->coll;
- sr = &fup->srbuf;
- di = &dibuf;
-
- di->di_rcsfile = sr->sr_file;
- di->di_cvsroot = coll->co_cvsroot;
- di->di_revnum = sr->sr_revnum;
- di->di_revdate = sr->sr_revdate;
- di->di_author = fup->author;
- di->di_tag = sr->sr_tag;
- di->di_state = state;
- di->di_expand = fup->expand;
-
- error = diff_apply(up->rd, fup->orig, fup->to, coll->co_keyword, di);
- if (error) {
- /* XXX Bad error message */
- xasprintf(&up->errmsg, "Bad diff from server");
- return (UPDATER_ERR_MSG);
- }
- return (0);
-}
-
-static int
-updater_checkout(struct updater *up, struct file_update *fup, int isfixup)
-{
- char md5[MD5_DIGEST_SIZE];
- struct statusrec *sr;
- struct coll *coll;
- struct stream *to;
- char *cmd, *path, *line;
- size_t size;
- ssize_t nbytes;
- int error, first;
-
- coll = fup->coll;
- sr = &fup->srbuf;
- path = fup->destpath;
-
- if (isfixup)
- lprintf(1, " Fixup %s\n", fup->coname);
- else
- lprintf(1, " Checkout %s\n", fup->coname);
- error = mkdirhier(path, coll->co_umask);
- if (error) {
- xasprintf(&up->errmsg,
- "Cannot create directories leading to \"%s\": %s",
- path, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
-
- to = stream_open_file(fup->temppath,
- O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (to == NULL) {
- xasprintf(&up->errmsg, "%s: Cannot create: %s",
- fup->temppath, strerror(errno));
- return (UPDATER_ERR_MSG);
- }
- stream_filter_start(to, STREAM_FILTER_MD5, md5);
- line = stream_getln(up->rd, &size);
- first = 1;
- while (line != NULL) {
- if (line[size - 1] == '\n')
- size--;
- if ((size == 1 && *line == '.') ||
- (size == 2 && memcmp(line, ".+", 2) == 0))
- break;
- if (size >= 2 && memcmp(line, "..", 2) == 0) {
- size--;
- line++;
- }
- if (!first) {
- nbytes = stream_write(to, "\n", 1);
- if (nbytes == -1)
- goto bad;
- }
- stream_write(to, line, size);
- line = stream_getln(up->rd, &size);
- first = 0;
- }
- if (line == NULL) {
- stream_close(to);
- return (UPDATER_ERR_READ);
- }
- if (size == 1 && *line == '.') {
- nbytes = stream_write(to, "\n", 1);
- if (nbytes == -1)
- goto bad;
- }
- stream_close(to);
- /* Get the checksum line. */
- line = stream_getln(up->rd, NULL);
- if (line == NULL)
- return (UPDATER_ERR_READ);
- cmd = proto_get_ascii(&line);
- fup->wantmd5 = proto_get_ascii(&line);
- if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0)
- return (UPDATER_ERR_PROTO);
- error = updater_updatefile(up, fup, md5, isfixup);
- fup->wantmd5 = NULL; /* So that it doesn't get freed. */
- if (error)
- return (error);
- return (0);
-bad:
- xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
- strerror(errno));
- return (UPDATER_ERR_MSG);
-}
-
-/*
- * Remove all empty directories below file.
- * This function will trash the path passed to it.
- */
-static void
-updater_prunedirs(char *base, char *file)
-{
- char *cp;
- int error;
-
- while ((cp = strrchr(file, '/')) != NULL) {
- *cp = '\0';
- if (strcmp(base, file) == 0)
- return;
- error = rmdir(file);
- if (error)
- return;
- }
-}
--- contrib/csup/threads.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*-
- * Copyright (c) 2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/threads.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _THREADS_H_
-#define _THREADS_H_
-
-struct threads;
-
-struct threads *threads_new(void);
-void threads_create(struct threads *, void *(*)(void *), void *);
-void *threads_wait(struct threads *);
-void threads_free(struct threads *);
-
-#endif /* !_THREADS_H_ */
--- contrib/csup/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-# $FreeBSD: src/contrib/csup/Makefile,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
-# $MidnightBSD: src/contrib/csup/Makefile,v 1.1 2006/12/27 01:28:42 laffer1 Exp $
-
-PREFIX?= /usr/local
-BINDIR?= ${PREFIX}/bin
-MANDIR?= ${PREFIX}/man/man
-
-UNAME!= /usr/bin/uname -s
-
-PROG= csup
-SRCS= attrstack.c config.c detailer.c diff.c fattr.c fixups.c fnmatch.c \
- globtree.c idcache.c keyword.c lister.c main.c misc.c mux.c parse.y \
- pathcomp.c proto.c status.c stream.c threads.c token.l updater.c
-
-CFLAGS+= -I. -I${.CURDIR} -g -pthread -DHAVE_FFLAGS -DNDEBUG
-WARNS?= 6
-
-# A bit of tweaking is needed to get this Makefile working
-# with the bsd.prog.mk of all the *BSD OSes...
-.if (${UNAME} == "NetBSD")
-LDFLAGS+= -pthread
-YHEADER= yes
-
-.elif (${UNAME} == "OpenBSD")
-# I bet there's a better way to do this with the OpenBSD mk
-# framework but well, this works and I got bored.
-LDFLAGS+= -pthread
-YFLAGS= -d
-CLEANFILES+= parse.c parse.h y.tab.h
-
-config.c: parse.h
-
-token.l: parse.h
-
-y.tab.h: parse.c
-
-parse.h: y.tab.h
- cp ${.ALLSRC} ${.TARGET}
-
-.endif
-
-DPADD= ${LIBCRYPTO} ${LIBZ}
-LDADD= -lcrypto -lz
-
-.include <bsd.prog.mk>
--- contrib/csup/fnmatch.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. 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, 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
- *
- * From FreeBSD fnmatch.h 1.7
- * $Id: fnmatch.h,v 1.4 2001/10/04 02:46:21 jdp Exp $
- */
-
-#ifndef _FNMATCH_H_
-#define _FNMATCH_H_
-
-#define FNM_NOMATCH 1 /* Match failed. */
-
-#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
-#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
-#define FNM_PERIOD 0x04 /* Period must be matched by period. */
-#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
-#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
-#define FNM_PREFIX_DIRS 0x20 /* Directory prefixes of pattern match too. */
-
-/* Make this compile successfully with "gcc -traditional" */
-#ifndef __STDC__
-#define const /* empty */
-#endif
-
-int fnmatch(const char *, const char *, int);
-
-#endif /* !_FNMATCH_H_ */
--- contrib/csup/csup.1
+++ /dev/null
@@ -1,902 +0,0 @@
-.\" Copyright 1996-2003 John D. Polstra.
-.\" 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, 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.
-.\"
-.\" $Id: cvsup.1,v 1.70 2003/03/04 18:23:46 jdp Exp $
-.\" $FreeBSD: src/contrib/csup/csup.1,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
-.\"
-.Dd February 1, 2006
-.Os FreeBSD
-.Dt CSUP 1
-.Sh NAME
-.Nm csup
-.Nd network distribution package for CVS repositories
-.Sh SYNOPSIS
-.Nm
-.Op Fl 146ksvzZ
-.Op Fl A Ar addr
-.Op Fl b Ar base
-.Op Fl c Ar collDir
-.Op Fl d Ar delLimit
-.Op Fl h Ar host
-.Op Fl i Ar pattern
-.Op Fl l Ar lockfile
-.Op Fl L Ar verbosity
-.Op Fl p Ar port
-.Op Fl r Ar maxRetries
-.Ar supfile
-.Sh DESCRIPTION
-.Nm
-is a software package for updating collections of files across a network.
-It is a rewrite of the
-.Nm CVSup
-software in C.
-This manual page describes the usage of the
-.Nm
-client program.
-.Pp
-Unlike more traditional network distribution packages, such as
-.Nm rdist
-and
-.Nm sup ,
-.Nm
-has specific optimizations for distributing CVS repositories.
-.Nm
-takes advantage of the properties of CVS repositories and the files they
-contain (in particular, RCS files), enabling it to perform updates much
-faster than traditional systems.
-.Pp
-.Nm
-is a general-purpose network file updating package.
-It is extremely fast,
-even for collections of files which have nothing to do with CVS or
-RCS.
-.Sh OPTIONS
-The client program
-.Nm
-requires at least a single argument,
-.Ar supfile .
-It names a file describing one or more collections of files to be
-transferred and/or updated from the server.
-The
-.Ar supfile
-has a format similar to the corresponding file used by
-.Nm sup .
-In most cases,
-.Nm
-can use existing
-.Nm sup Ar supfiles .
-.Pp
-The following options are supported by
-.Nm :
-.Bl -tag -width Fl
-.It Fl 1
-Disables automatic retries when transient failures occur.
-Without this option, a transient failure such as a dropped network
-connection causes
-.Nm
-to retry repeatedly, using randomized exponential backoff to space the
-retries.
-This option is equivalent to
-.Fl r Cm 0 .
-.It Fl 4
-Forces
-.Nm
-to use IPv4 addresses only.
-.It Fl 6
-Forces
-.Nm
-to use IPv6 addresses only.
-.It Fl A Ar addr
-Specifies a local address to bind to when connecting to the server.
-The local address might be a hostname or a numeric host address string
-consisting of a dotted decimal IPv4 address or an IPv6 address.
-This may be useful on hosts which have multiple IP addresses.
-.It Fl b Ar base
-Specifies the base directory under which
-.Nm
-will maintain its bookkeeping files, overriding any
-.Cm base
-specifications in the
-.Ar supfile .
-.It Fl c Ar collDir
-Specifies the subdirectory of
-.Ar base
-where the information about the collections is maintained.
-The default is
-.Pa sup .
-.It Fl d Ar delLimit
-Specifies the maximum number of files that may be deleted in a
-single update run.
-Any attempt to exceed the limit results in a fatal error.
-This can provide some protection against temporary configuration
-mistakes on the server.
-The default limit is infinity.
-.It Fl h Ar host
-Specifies the server host to contact, overriding any
-.Cm host
-specifications in the
-.Ar supfile .
-.It Fl i Ar pattern
-Causes
-.Nm
-to include only files and directories matching
-.Ar pattern
-in the update. If a directory matches the pattern, then the entire
-subtree rooted at the directory is included. If this option is
-specified multiple times, the patterns are combined using the
-.Ql or
-operation. If no
-.Fl i
-options are given, the default is to update all files in each
-collection.
-.Pp
-The
-.Ar pattern
-is a standard file name pattern.
-It is interpreted relative to the collection's prefix directory.
-Slash characters are matched only by explicit slashes in the pattern.
-Leading periods in file name are not treated specially.
-.It Fl k
-Causes
-.Nm
-to keep the temporary copies of any incorrectly edited files, in the
-event of checksum mismatches.
-This option is for debugging, to help determine why the files were
-edited incorrectly.
-Regardless of whether this option is specified, the permanent versions
-of faulty files are replaced with correct versions obtained by
-transferring the files in their entirety.
-Such transfers are called fixups.
-.It Fl l Ar lockfile
-Creates and locks the
-.Ar lockfile
-while the update is in progress.
-If
-.Ar lockfile
-is already locked,
-.Nm
-fails without performing automatic retries.
-This option is useful when
-.Nm
-is executed periodically from
-.Nm cron .
-It prevents a job from interfering with an earlier job that is perhaps
-taking extra long because of network problems.
-.Pp
-The process-ID is written to the lock file in text form when the lock
-is successfully acquired.
-Upon termination of the update, the lock file is removed.
-.It Fl L Ar verbosity
-Sets the verbosity level for output.
-A level of 0 causes
-.Nm
-to be completely silent unless errors occur.
-A level of 1 (the default) causes each updated file to be listed.
-A level of 2 provides more detailed information about the updates
-performed on each file.
-All messages are directed to the standard output.
-.It Fl p Ar port
-Sets the TCP port to which
-.Nm
-attempts to connect on the server host.
-The default port is 5999.
-.It Fl r Ar maxRetries
-Limits the number of automatic retries that will be attempted when
-transient errors such as lost network connections are encountered.
-By default,
-.Nm
-will retry indefinitely until an update is successfully completed.
-The retries are spaced using randomized exponential backoff.
-Note that
-.Fl r Cm 0
-is equivalent to the
-.Fl 1
-option.
-.It Fl s
-Suppresses the check of each client file's status against what is
-recorded in the list file. Instead, the list file is assumed to be
-accurate. This option greatly reduces the amount of disk activity and
-results in faster updates with less load on the client host. However
-it should only be used if client's files are never modified locally in
-any way. Mirror sites may find this option beneficial to reduce the
-disk load on their systems. For safety, even mirror sites should run
-.Nm
-occasionally (perhaps once a day) without the
-.Fl s
-option.
-.Pp
-Without the
-.Fl s
-option,
-.Nm
-performs a
-.Xr stat 2
-call on each file and verifies that its attributes match those
-recorded in the list file. This ensures that any file changes made
-outside of
-.Nm
-are detected and corrected.
-.Pp
-If the
-.Fl s
-option is used when one or more files have been modified locally, the
-results are undefined. Local file damage may remain uncorrected,
-updates may be missed, or
-.Nm
-may abort prematurely.
-.It Fl v
-Prints the version number and exits, without contacting the server.
-.It Fl z
-Enables compression for all collections, as if the
-.Cm compress
-keyword were added to every collection in the
-.Ar supfile .
-.It Fl Z
-Disables compression for all collections, as if the
-.Cm compress
-keyword were removed from every collection in the
-.Ar supfile .
-.El
-.Pp
-The
-.Ar supfile
-is a text file which specifies the file collections to be updated.
-Comments begin with
-.Ql #
-and extend to the end of the line. Lines that are empty except for
-comments and white space are ignored. Each remaining line begins
-with the name of a server-defined collection of files. Following the
-collection name on the line are zero or more keywords or keyword=value
-pairs.
-.Pp
-Default settings may be specified in lines whose collection name is
-.Cm *default .
-Such defaults will apply to subsequent lines in the
-.Ar supfile .
-Multiple
-.Cm *default
-lines may be present.
-New values augment or override any defaults specified earlier in the
-.Ar supfile .
-Values specified explicitly for a collection override any default
-values.
-.Pp
-The most commonly used keywords are:
-.Bl -tag -width Fl
-.It Cm release= Ns Ar releaseName
-This specifies the release of the files within a collection.
-Like collection names, release names are defined by the server
-configuration files. Usually there is only one release in each
-collection, but there may be any number. Collections which come from
-a CVS repository often use
-.Cm release=cvs
-by convention. Non-CVS collections conventionally use
-.Cm release=current .
-.It Cm base= Ns Ar base
-This specifies a directory under which
-.Nm
-will maintain its bookkeeping files, describing the state of each
-collection on the client machine.
-The
-.Ar base
-directory must already exist;
-.Nm
-will not create it.
-The default
-.Ar base
-directory is
-.Pa /usr/local/etc/csup .
-.It Cm prefix= Ns Ar prefix
-This is the directory under which updated files will be placed.
-By default, it is the same as
-.Ar base .
-If it is not an absolute pathname, it is interpreted relative to
-.Ar base .
-The
-.Ar prefix
-directory must already exist;
-.Nm
-will not create it.
-.Pp
-As a special case, if
-.Ar prefix
-is a symbolic link pointing to a nonexistent file named
-.Ql SKIP ,
-then
-.Nm
-will skip the collection.
-The parameters associated with the collection are still checked for
-validity, but none of its files will be updated.
-This feature allows a site to use a standard
-.Ar supfile
-on several machines, yet control which collections get updated on a
-per-machine basis.
-.It Cm host= Ns Ar hostname
-This specifies the server machine from which all files will be taken.
-.Nm
-requires that all collections in a single run come from the same host.
-If you wish to update collections from several different hosts, you must
-run
-.Nm
-several times.
-.It Cm delete
-The presence of this keyword gives
-.Nm
-permission to delete files.
-If it is missing, no files will be deleted.
-.Pp
-The presence of the
-.Cm delete
-keyword puts
-.Nm
-into so-called
-.Em exact
-mode. In exact mode,
-.Nm
-does its best to make the client's files correspond to those on the server.
-This includes deleting individual deltas and symbolic tags from RCS
-files, as well as deleting entire files.
-In exact mode,
-.Nm
-verifies every edited file with a checksum, to ensure that the edits
-have produced a file identical to the master copy on the server.
-If the checksum test fails for a file, then
-.Nm
-falls back upon transferring the entire file.
-.Pp
-In general,
-.Nm
-deletes only files which are known to the server.
-Extra files present in the client's tree are left alone, even in exact
-mode.
-More precisely,
-.Nm
-is willing to delete two classes of files:
-.Bl -bullet -compact
-.It
-Files that were previously created or updated by
-.Nm
-itself.
-.It
-Checked-out versions of files which are marked as dead on the server.
-.El
-.It Cm use-rel-suffix
-Causes
-.Nm
-to append a suffix constructed from the release and tag to the name of
-each list file that it maintains.
-See
-.Sx THE LIST FILE
-for details.
-.It Cm compress
-This enables compression of all data sent across the network.
-Compression is quite effective, normally eliminating 65% to 75% of the
-bytes that would otherwise need to be transferred.
-However, it is costly in terms of CPU time on both the client and the
-server.
-On local area networks, compression is generally counter-productive; it
-actually slows down file updates.
-On links with speeds of 56K bits/second or less, compression is almost
-always beneficial.
-For network links with speeds between these two extremes, let
-experimentation be your guide.
-.Pp
-The
-.Fl z
-command line option enables the
-.Cm compress
-keyword for all collections, regardless of what is specified in the supfile.
-Likewise, the
-.Fl Z
-command line option disables the
-.Cm compress
-option for all collections.
-.Nm
-uses a looser checksum for RCS files, which ignores harmless
-differences in white space. Different versions of CVS and RCS produce
-a variety of differences in white space for the same RCS files. Thus
-the strict checksum can report spurious mismatches for files which are
-logically identical. This can lead to numerous unneeded
-.Dq fixups ,
-and thus to slow updates.
-.It Cm umask= Ns Ar n
-Causes
-.Nm
-to use a umask value of
-.Ar n
-(an octal number) when updating the files in the collection.
-This option is ignored if
-.Cm preserve
-is specified.
-.El
-.Pp
-Some additional, more specialized keywords are described below.
-Unrecognized keywords are silently ignored for backward compatibility
-with
-.Nm sup .
-.Sh CVS MODE
-.Nm CVSup
-supports two primary modes of operation.
-They are called
-.Em CVS
-mode and
-.Em checkout
-mode.
-.Nm
-only supports the checkout mode for now.
-.Pp
-In CVS mode, the client receives copies of the actual RCS files making
-up the master CVS repository. CVS mode is the default mode of operation.
-It is appropriate when the user wishes to maintain a full copy of the
-CVS repository on the client machine.
-.Pp
-CVS mode is also appropriate for file collections which are not
-based upon a CVS repository. The files are simply transferred
-verbatim, without interpretation.
-.Sh CHECKOUT MODE
-In checkout mode, the client receives specific revisions of files,
-checked out directly from the server's CVS repository.
-Checkout mode allows the client to receive any version from the
-repository, without requiring any extra disk space on the server for
-storing multiple versions in checked-out form.
-Checkout mode provides much flexibility beyond that basic functionality,
-however.
-The client can specify any CVS symbolic tag, or any date, or both, and
-.Nm
-will provide the corresponding checked-out versions of the files in the
-repository.
-.Pp
-Checkout mode is selected on a per-collection basis, by the presence of
-one or both of the following keywords in the
-.Ar supfile :
-.Bl -tag -width Fl
-.It Cm tag= Ns Ar tagname
-This specifies a symbolic tag that should be used to select the
-revisions that are checked out from the CVS repository.
-The tag may refer to either a branch or a specific revision.
-It must be symbolic; numeric revision numbers are not supported.
-.Pp
-For the FreeBSD source repository, the most commonly used tags will be:
-.Bl -tag -width RELENG_6
-.It Li RELENG_6
-The
-.Ql stable
-branch.
-.It Li \&.
-The main branch (the
-.Ql current
-release).
-This is the default, if only the
-.Cm date
-keyword is given.
-.El
-.Sm off
-.It Xo Cm date=
-.Op Ar cc
-.Ar yy.mm.dd.hh.mm.ss
-.Xc
-.Sm on
-This specifies a date that should be used to select the revisions that
-are checked out from the CVS repository.
-The client will receive the revisions that were in effect at the
-specified date and time.
-.Pp
-At present, the date format is inflexible. All 17 or 19 characters must
-be specified, exactly as shown.
-For the years 2000 and beyond, specify the century
-.Ar cc .
-For earlier years, specify only the last two digits
-.Ar yy .
-Dates and times are considered to
-be GMT.
-The default date is
-.Ql \&. ,
-which means
-.Dq as late as possible .
-.El
-.Pp
-To enable checkout mode, you must specify at least one of these keywords.
-If both are missing,
-.Nm
-defaults to CVS mode.
-.Pp
-If both a branch tag and a date are specified, then the revisions on the
-given branch, as of the given date, will be checked out. It is
-permitted, but not particularly useful, to specify a date with a
-specific release tag.
-.Pp
-In checkout mode, the tag and/or date may be changed between updates.
-For example, suppose that a collection has been transferred using the
-specification
-.Ql tag=. .
-The user could later change the specification to
-.Ql tag=RELENG_3 .
-This would cause
-.Nm
-to edit the checked-out files in such a way as to transform them from the
-.Ql current
-versions to the
-.Ql stable
-versions.
-In general,
-.Nm
-is willing to transform any tag/date combination into any other tag/date
-combination, by applying the intervening RCS deltas to the existing files.
-.Pp
-When transforming a collection of checked-out files from one tag to
-another, it is important to specify the
-.Cm list
-keyword in the
-.Ar supfile ,
-to ensure that the same list file is used both before and after the
-transformation.
-The list file is described in
-.Sx THE LIST FILE ,
-below.
-.Sh THE LIST FILE
-For efficiency,
-.Nm
-maintains a bookkeeping file for each collection, called the list file.
-The list file contains information about which files and revisions the client
-currently possesses.
-It also contains information used for verifying that the list file
-is consistent with the actual files in the client's tree.
-.Pp
-The list file is not strictly necessary. If it is deleted, or becomes
-inconsistent with the actual client files,
-.Nm
-falls back upon a less efficient method of identifying the client's
-files and performing its updates.
-Depending on
-.Nm csup Ns No 's
-mode of operation, the fallback method employs time stamps, checksums, or
-analysis of RCS files.
-.Pp
-Because the list file is not essential,
-.Nm
-is able to
-.Dq adopt
-an existing file tree acquired by FTP or from a CD-ROM.
-.Nm
-identifies the client's versions of the files, updates them as
-necessary, and creates a list file for future use.
-Adopting a foreign file tree is not as fast as performing a normal
-update.
-It also produces a heavier load on the server.
-.Pp
-The list file is stored in a collection-specific directory; see
-.Sx FILES
-for details.
-Its name always begins with
-.Ql checkouts .
-If the keyword
-.Cm use-rel-suffix
-is specified in the
-.Ar supfile ,
-a suffix, formed from the release and tag, is appended to the name.
-The default suffix can be overridden by specifying an explicit suffix in
-the
-.Ar supfile :
-.Bl -tag -width Fl
-.It Cm list= Ns Ar suffix
-This specifies a suffix for the name of the list file. A leading dot is
-provided automatically.
-For example,
-.Ql list=stable
-would produce a list file named
-.Pa checkouts.stable ,
-regardless of the release, tag, or
-.Cm use-rel-suffix
-keyword.
-.El
-.Sh REFUSE FILES
-The user can specify sets of files that he does not wish to receive.
-The files are specified as file name patterns in so-called
-.Em refuse
-files.
-The patterns are separated by whitespace, and multiple patterns are
-permitted on each line.
-Files and directories matching the patterns are neither updated nor
-deleted; they are simply ignored.
-.Pp
-There is currently no provision for comments in refuse files.
-.Pp
-The patterns are similar to those of
-.Xr sh 1 ,
-except that there is no special treatment for slashes or for
-filenames that begin with a period.
-For example, the pattern
-.Ql *.c
-will match any file name ending with
-.Ql \&.c
-including those in subdirectories, such as
-.Ql foo/bar/lam.c .
-All patterns are interpreted relative to the collection's prefix
-directory.
-.Pp
-If the files are coming from a CVS repository, as is usually
-the case, then they will be RCS files. These have a
-.Ql \&,v
-suffix which must be taken into account in the patterns. For
-example, the FreeBSD documentation files are in a sub-directory of
-.Ar base
-called
-.Ql doc .
-If
-.Ql Makefile
-from that directory is not required then the line
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa doc/Makefile
-.El
-.Pp
-will not work because the file on the server is called
-.Ql Makefile,v.
-A better solution would be
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa doc/Makefile*
-.El
-.Pp
-which will match whether
-.Ql Makefile
-is an RCS file or not.
-.Pp
-As another example, to receive the FreeBSD documentation files without
-the Japanese, Russian, and Chinese translations, create a refuse file
-containing the following lines:
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa doc/ja*
-.It
-.Pa doc/ru*
-.It
-.Pa doc/zh*
-.El
-.Pp
-As many as three refuse files are examined for each
-.Ar supfile
-line.
-There can be a global refuse file named
-.Sm off
-.Ar base / Ar collDir Pa /refuse
-.Sm on
-which applies to all collections and releases.
-There can be a per-collection refuse file named
-.Sm off
-.Xo Ar base / Ar collDir / Ar collection
-.Pa /refuse
-.Xc
-.Sm on
-which applies to a specific collection.
-Finally, there can be a per-release and tag refuse file which applies only
-to a given release/tag combination within a collection.
-The name of the latter is formed by suffixing the name of the
-per-collection refuse file in the same manner as described above for the
-list file.
-None of the refuse files are required to exist.
-.Pp
-.Nm
-has a built-in default value of
-.Ar /usr/local/etc/cvsup
-for
-.Ar base
-and
-.Ar sup
-for
-.Ar collDir
-but it is possible to override both of these. The value of
-.Ar base
-can be changed using the
-.Fl b
-option or a
-.Ar base=pathname
-entry in the
-.Ar supfile .
-(If both are used the
-.Fl b
-option will override the
-.Ar supfile
-entry.) The value of
-.Ar collDir
-can only be changed with the
-.Fl c
-option; there is no
-.Ar supfile
-command to change it.
-.Pp
-As an example, suppose that the
-.Ar base
-and
-.Ar collDir
-both have their default values, and that the collection and release are
-.Ql src-all
-and
-.Ql cvs ,
-respectively.
-Assume further that checkout mode is being used with
-.Ql tag=RELENG_3 .
-The three possible refuse files would then be named:
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa /usr/local/etc/cvsup/sup/refuse
-.It
-.Pa /usr/local/etc/cvsup/sup/src-all/refuse
-.It
-.Pa /usr/local/etc/cvsup/sup/src-all/refuse.cvs:RELENG_3
-.El
-.Pp
-If the
-.Ar supfile
-includes the command
-.Ar base=/foo
-the refuse files would be:
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa /foo/sup/refuse
-.It
-.Pa /foo/sup/src-all/refuse
-.It
-.Pa /foo/sup/src-all/refuse.cvs:RELENG_3
-.El
-.Pp
-If
-.Fl b
-.Ar /bar
-is used (even with
-.Ar base=/foo
-in the
-.Ar supfile ) :
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa /bar/sup/refuse
-.It
-.Pa /bar/sup/src-all/refuse
-.It
-.Pa /bar/sup/src-all/refuse.cvs:RELENG_3
-.El
-.Pp
-and with
-.Fl c
-.Ar stool
-as well:
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Pa /bar/stool/refuse
-.It
-.Pa /bar/stool/src-all/refuse
-.It
-.Pa /bar/stool/src-all/refuse.cvs:RELENG_3
-.El
-.Sh csup AND FIREWALLS
-In its default mode,
-.Nm
-will work through any firewall which permits outbound connections to
-port 5999 of the server host.
-.Sh USING csup WITH SOCKS
-.Nm
-can be used through a SOCKS proxy server with the standard
-.Nm runsocks
-command.
-Your
-.Nm
-executable needs to be dynamically-linked with the system
-libraries for
-.Nm runsocks
-to work properly.
-.Sh USING ssh PORT FORWARDING
-As an alternative to SOCKS, a user behind a firewall can penetrate it
-with the TCP port forwarding provided by the Secure Shell package
-.Nm ssh .
-The user must have a login account on the
-.Nm CVSup
-server host in order to do this.
-The procedure is as follows:
-.Bl -enum
-.It
-Establish a connection to the server host with
-.Nm ssh ,
-like this:
-.Bd -literal
-ssh -f -x -L 5999:localhost:5999 serverhost sleep 60
-.Ed
-.Pp
-Replace
-.Ar serverhost
-with the hostname of the CVSup server, but type
-.Ql localhost
-literally.
-This sets up the required port forwarding.
-You must start
-.Nm
-before the 60-second
-.Nm sleep
-finishes.
-Once the update has begun,
-.Nm ssh
-will keep the forwarded channels open as long as they are needed.
-.It
-Run
-.Nm
-on the local host, including the arguments
-.Ql -h localhost
-on the command line.
-.El
-.Sh FILES
-.Bl -tag -width base/sup/collection/checkouts*xx -compact
-.It Pa /usr/local/etc/cvsup
-Default
-.Ar base
-directory.
-.It Pa sup
-Default
-.Ar collDir
-subdirectory.
-.Sm off
-.It Xo Ar base / Ar collDir / Ar collection
-.Pa /checkouts*
-.Xc
-.Sm on
-List files.
-.El
-.Sh SEE ALSO
-.Xr cvs 1 ,
-.Xr rcsintro 1 ,
-.Xr ssh 1 .
-.Pp
-.Bd -literal
-http://mu.org/~mux/csup.html
-.Ed
-.Sh AUTHORS
-.An -nosplit
-.An Maxime Henrion Aq mux at FreeBSD.org
-is the author of
-.Nm ,
-the rewrite of
-.Nm CVSup
-in C.
-.An John Polstra Aq jdp at polstra.com
-is the author of
-.Nm CVSup .
-.Sh LEGALITIES
-CVSup is a registered trademark of John D. Polstra.
-.Pp
-.Nm
-is released under a 2-clauses BSD license.
-.Sh BUGS
-An RCS file is not recognized as such unless its name ends with
-.Ql \&,v .
-.Pp
-Any directory named
-.Ql Attic
-is assumed to be a CVS Attic, and is treated specially.
-.Pp
-.Nm
-is not compatible with CVS 1.12 repositories.
--- contrib/csup/proto.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/proto.c,v 1.1.1.2.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <sys/param.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <netdb.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "detailer.h"
-#include "fattr.h"
-#include "fixups.h"
-#include "globtree.h"
-#include "keyword.h"
-#include "lister.h"
-#include "misc.h"
-#include "mux.h"
-#include "proto.h"
-#include "queue.h"
-#include "stream.h"
-#include "threads.h"
-#include "updater.h"
-
-struct killer {
- pthread_t thread;
- sigset_t sigset;
- struct mux *mux;
- int killedby;
-};
-
-static void killer_start(struct killer *, struct mux *);
-static void *killer_run(void *);
-static void killer_stop(struct killer *);
-
-static int proto_waitconnect(int);
-static int proto_greet(struct config *);
-static int proto_negproto(struct config *);
-static int proto_login(struct config *);
-static int proto_fileattr(struct config *);
-static int proto_xchgcoll(struct config *);
-static struct mux *proto_mux(struct config *);
-
-static int proto_escape(struct stream *, const char *);
-static void proto_unescape(char *);
-
-static int
-proto_waitconnect(int s)
-{
- fd_set readfd;
- socklen_t len;
- int error, rv, soerror;
-
- FD_ZERO(&readfd);
- FD_SET(s, &readfd);
-
- do {
- rv = select(s + 1, &readfd, NULL, NULL, NULL);
- } while (rv == -1 && errno == EINTR);
- if (rv == -1)
- return (-1);
- /* Check that the connection was really successful. */
- len = sizeof(soerror);
- error = getsockopt(s, SOL_SOCKET, SO_ERROR, &soerror, &len);
- if (error) {
- /* We have no choice but faking an error here. */
- errno = ECONNREFUSED;
- return (-1);
- }
- if (soerror) {
- errno = soerror;
- return (-1);
- }
- return (0);
-}
-
-/* Connect to the CVSup server. */
-int
-proto_connect(struct config *config, int family, uint16_t port)
-{
- char addrbuf[NI_MAXHOST];
- /* Enough to hold sizeof("cvsup") or any port number. */
- char servname[8];
- struct addrinfo *res, *ai, hints;
- int error, opt, s;
-
- s = -1;
- if (port != 0)
- snprintf(servname, sizeof(servname), "%d", port);
- else {
- strncpy(servname, "cvsup", sizeof(servname) - 1);
- servname[sizeof(servname) - 1] = '\0';
- }
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- error = getaddrinfo(config->host, servname, &hints, &res);
- /*
- * Try with the hardcoded port number for OSes that don't
- * have cvsup defined in the /etc/services file.
- */
- if (error == EAI_SERVICE) {
- strncpy(servname, "5999", sizeof(servname) - 1);
- servname[sizeof(servname) - 1] = '\0';
- error = getaddrinfo(config->host, servname, &hints, &res);
- }
- if (error) {
- lprintf(0, "Name lookup failure for \"%s\": %s\n", config->host,
- gai_strerror(error));
- return (STATUS_TRANSIENTFAILURE);
- }
- for (ai = res; ai != NULL; ai = ai->ai_next) {
- s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (s != -1) {
- error = 0;
- if (config->laddr != NULL) {
- opt = 1;
- (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- &opt, sizeof(opt));
- error = bind(s, config->laddr,
- config->laddrlen);
- }
- if (!error) {
- error = connect(s, ai->ai_addr, ai->ai_addrlen);
- if (error && errno == EINTR)
- error = proto_waitconnect(s);
- }
- if (error)
- close(s);
- }
- (void)getnameinfo(ai->ai_addr, ai->ai_addrlen, addrbuf,
- sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
- if (s == -1 || error) {
- lprintf(0, "Cannot connect to %s: %s\n", addrbuf,
- strerror(errno));
- continue;
- }
- lprintf(1, "Connected to %s\n", addrbuf);
- freeaddrinfo(res);
- config->socket = s;
- return (STATUS_SUCCESS);
- }
- freeaddrinfo(res);
- return (STATUS_TRANSIENTFAILURE);
-}
-
-/* Greet the server. */
-static int
-proto_greet(struct config *config)
-{
- char *line, *cmd, *msg, *swver;
- struct stream *s;
-
- s = config->server;
- line = stream_getln(s, NULL);
- cmd = proto_get_ascii(&line);
- if (cmd == NULL)
- goto bad;
- if (strcmp(cmd, "OK") == 0) {
- (void)proto_get_ascii(&line); /* major number */
- (void)proto_get_ascii(&line); /* minor number */
- swver = proto_get_ascii(&line);
- } else if (strcmp(cmd, "!") == 0) {
- msg = proto_get_rest(&line);
- if (msg == NULL)
- goto bad;
- lprintf(-1, "Rejected by server: %s\n", msg);
- return (STATUS_TRANSIENTFAILURE);
- } else
- goto bad;
- lprintf(2, "Server software version: %s\n",
- swver != NULL ? swver : ".");
- return (STATUS_SUCCESS);
-bad:
- lprintf(-1, "Invalid greeting from server\n");
- return (STATUS_FAILURE);
-}
-
-/* Negotiate protocol version with the server. */
-static int
-proto_negproto(struct config *config)
-{
- struct stream *s;
- char *cmd, *line, *msg;
- int error, maj, min;
-
- s = config->server;
- proto_printf(s, "PROTO %d %d %s\n", PROTO_MAJ, PROTO_MIN, PROTO_SWVER);
- stream_flush(s);
- line = stream_getln(s, NULL);
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || line == NULL)
- goto bad;
- if (strcmp(cmd, "!") == 0) {
- msg = proto_get_rest(&line);
- lprintf(-1, "Protocol negotiation failed: %s\n", msg);
- return (1);
- } else if (strcmp(cmd, "PROTO") != 0)
- goto bad;
- error = proto_get_int(&line, &maj, 10);
- if (!error)
- error = proto_get_int(&line, &min, 10);
- if (error)
- goto bad;
- if (maj != PROTO_MAJ || min != PROTO_MIN) {
- lprintf(-1, "Server protocol version %d.%d not supported "
- "by client\n", maj, min);
- return (STATUS_FAILURE);
- }
- return (STATUS_SUCCESS);
-bad:
- lprintf(-1, "Invalid PROTO command from server\n");
- return (STATUS_FAILURE);
-}
-
-static int
-proto_login(struct config *config)
-{
- struct stream *s;
- char hostbuf[MAXHOSTNAMELEN];
- char *line, *login, *host, *cmd, *realm, *challenge, *msg;
- int error;
-
- s = config->server;
- error = gethostname(hostbuf, sizeof(hostbuf));
- hostbuf[sizeof(hostbuf) - 1] = '\0';
- if (error)
- host = NULL;
- else
- host = hostbuf;
- login = getlogin();
- proto_printf(s, "USER %s %s\n", login != NULL ? login : "?",
- host != NULL ? host : "?");
- stream_flush(s);
- line = stream_getln(s, NULL);
- cmd = proto_get_ascii(&line);
- realm = proto_get_ascii(&line);
- challenge = proto_get_ascii(&line);
- if (challenge == NULL || line != NULL)
- goto bad;
- if (strcmp(realm, ".") != 0 || strcmp(challenge, ".") != 0) {
- lprintf(-1, "Authentication required by the server and not "
- "supported by client\n");
- return (STATUS_FAILURE);
- }
- proto_printf(s, "AUTHMD5 . . .\n");
- stream_flush(s);
- line = stream_getln(s, NULL);
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || line == NULL)
- goto bad;
- if (strcmp(cmd, "OK") == 0)
- return (STATUS_SUCCESS);
- if (strcmp(cmd, "!") == 0) {
- msg = proto_get_rest(&line);
- if (msg == NULL)
- goto bad;
- lprintf(-1, "Server error: %s\n", msg);
- return (STATUS_FAILURE);
- }
-bad:
- lprintf(-1, "Invalid server reply to AUTHMD5\n");
- return (STATUS_FAILURE);
-}
-
-/*
- * File attribute support negotiation.
- */
-static int
-proto_fileattr(struct config *config)
-{
- fattr_support_t support;
- struct stream *s;
- char *line, *cmd;
- int error, i, n, attr;
-
- s = config->server;
- lprintf(2, "Negotiating file attribute support\n");
- proto_printf(s, "ATTR %d\n", FT_NUMBER);
- for (i = 0; i < FT_NUMBER; i++)
- proto_printf(s, "%x\n", fattr_supported(i));
- proto_printf(s, ".\n");
- stream_flush(s);
- line = stream_getln(s, NULL);
- if (line == NULL)
- goto bad;
- cmd = proto_get_ascii(&line);
- error = proto_get_int(&line, &n, 10);
- if (error || line != NULL || strcmp(cmd, "ATTR") != 0 || n > FT_NUMBER)
- goto bad;
- for (i = 0; i < n; i++) {
- line = stream_getln(s, NULL);
- if (line == NULL)
- goto bad;
- error = proto_get_int(&line, &attr, 16);
- if (error)
- goto bad;
- support[i] = fattr_supported(i) & attr;
- }
- for (i = n; i < FT_NUMBER; i++)
- support[i] = 0;
- line = stream_getln(s, NULL);
- if (line == NULL || strcmp(line, ".") != 0)
- goto bad;
- memcpy(config->fasupport, support, sizeof(config->fasupport));
- return (STATUS_SUCCESS);
-bad:
- lprintf(-1, "Protocol error negotiating attribute support\n");
- return (STATUS_FAILURE);
-}
-
-/*
- * Exchange collection information.
- */
-static int
-proto_xchgcoll(struct config *config)
-{
- struct coll *coll;
- struct stream *s;
- struct globtree *diraccept, *dirrefuse;
- struct globtree *fileaccept, *filerefuse;
- char *line, *cmd, *collname, *pat;
- char *msg, *release, *ident, *rcskey, *prefix;
- size_t i, len;
- int error, flags, options;
-
- s = config->server;
- lprintf(2, "Exchanging collection information\n");
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- proto_printf(s, "COLL %s %s %o %d\n", coll->co_name,
- coll->co_release, coll->co_umask, coll->co_options);
- for (i = 0; i < pattlist_size(coll->co_accepts); i++) {
- proto_printf(s, "ACC %s\n",
- pattlist_get(coll->co_accepts, i));
- }
- for (i = 0; i < pattlist_size(coll->co_refusals); i++) {
- proto_printf(s, "REF %s\n",
- pattlist_get(coll->co_refusals, i));
- }
- proto_printf(s, ".\n");
- }
- proto_printf(s, ".\n");
- stream_flush(s);
-
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- if (coll->co_options & CO_SKIP)
- continue;
- coll->co_norsync = globtree_false();
- line = stream_getln(s, NULL);
- if (line == NULL)
- goto bad;
- cmd = proto_get_ascii(&line);
- collname = proto_get_ascii(&line);
- release = proto_get_ascii(&line);
- error = proto_get_int(&line, &options, 10);
- if (error || line != NULL)
- goto bad;
- if (strcmp(cmd, "COLL") != 0 ||
- strcmp(collname, coll->co_name) != 0 ||
- strcmp(release, coll->co_release) != 0)
- goto bad;
- coll->co_options =
- (coll->co_options | (options & CO_SERVMAYSET)) &
- ~(~options & CO_SERVMAYCLEAR);
- while ((line = stream_getln(s, NULL)) != NULL) {
- if (strcmp(line, ".") == 0)
- break;
- cmd = proto_get_ascii(&line);
- if (cmd == NULL)
- goto bad;
- if (strcmp(cmd, "!") == 0) {
- msg = proto_get_rest(&line);
- if (msg == NULL)
- goto bad;
- lprintf(-1, "Server message: %s\n", msg);
- } else if (strcmp(cmd, "PRFX") == 0) {
- prefix = proto_get_ascii(&line);
- if (prefix == NULL || line != NULL)
- goto bad;
- coll->co_cvsroot = xstrdup(prefix);
- } else if (strcmp(cmd, "KEYALIAS") == 0) {
- ident = proto_get_ascii(&line);
- rcskey = proto_get_ascii(&line);
- if (rcskey == NULL || line != NULL)
- goto bad;
- error = keyword_alias(coll->co_keyword, ident,
- rcskey);
- if (error)
- goto bad;
- } else if (strcmp(cmd, "KEYON") == 0) {
- ident = proto_get_ascii(&line);
- if (ident == NULL || line != NULL)
- goto bad;
- error = keyword_enable(coll->co_keyword, ident);
- if (error)
- goto bad;
- } else if (strcmp(cmd, "KEYOFF") == 0) {
- ident = proto_get_ascii(&line);
- if (ident == NULL || line != NULL)
- goto bad;
- error = keyword_disable(coll->co_keyword,
- ident);
- if (error)
- goto bad;
- } else if (strcmp(cmd, "NORS") == 0) {
- pat = proto_get_ascii(&line);
- if (pat == NULL || line != NULL)
- goto bad;
- coll->co_norsync = globtree_or(coll->co_norsync,
- globtree_match(pat, FNM_PATHNAME));
- } else if (strcmp(cmd, "RNORS") == 0) {
- pat = proto_get_ascii(&line);
- if (pat == NULL || line != NULL)
- goto bad;
- coll->co_norsync = globtree_or(coll->co_norsync,
- globtree_match(pat, FNM_PATHNAME |
- FNM_LEADING_DIR));
- } else
- goto bad;
- }
- if (line == NULL)
- goto bad;
- keyword_prepare(coll->co_keyword);
-
- diraccept = globtree_true();
- fileaccept = globtree_true();
- dirrefuse = globtree_false();
- filerefuse = globtree_false();
-
- if (pattlist_size(coll->co_accepts) > 0) {
- globtree_free(diraccept);
- globtree_free(fileaccept);
- diraccept = globtree_false();
- fileaccept = globtree_false();
- flags = FNM_PATHNAME | FNM_LEADING_DIR |
- FNM_PREFIX_DIRS;
- for (i = 0; i < pattlist_size(coll->co_accepts); i++) {
- pat = pattlist_get(coll->co_accepts, i);
- diraccept = globtree_or(diraccept,
- globtree_match(pat, flags));
-
- len = strlen(pat);
- if (coll->co_options & CO_CHECKOUTMODE &&
- (len == 0 || pat[len - 1] != '*')) {
- /* We must modify the pattern so that it
- refers to the RCS file, rather than
- the checked-out file. */
- xasprintf(&pat, "%s,v", pat);
- fileaccept = globtree_or(fileaccept,
- globtree_match(pat, flags));
- free(pat);
- } else {
- fileaccept = globtree_or(fileaccept,
- globtree_match(pat, flags));
- }
- }
- }
-
- for (i = 0; i < pattlist_size(coll->co_refusals); i++) {
- pat = pattlist_get(coll->co_refusals, i);
- dirrefuse = globtree_or(dirrefuse,
- globtree_match(pat, 0));
- len = strlen(pat);
- if (coll->co_options & CO_CHECKOUTMODE &&
- (len == 0 || pat[len - 1] != '*')) {
- /* We must modify the pattern so that it refers
- to the RCS file, rather than the checked-out
- file. */
- xasprintf(&pat, "%s,v", pat);
- filerefuse = globtree_or(filerefuse,
- globtree_match(pat, 0));
- free(pat);
- } else {
- filerefuse = globtree_or(filerefuse,
- globtree_match(pat, 0));
- }
- }
-
- coll->co_dirfilter = globtree_and(diraccept,
- globtree_not(dirrefuse));
- coll->co_filefilter = globtree_and(fileaccept,
- globtree_not(filerefuse));
-
- /* At this point we don't need the pattern lists anymore. */
- pattlist_free(coll->co_accepts);
- pattlist_free(coll->co_refusals);
- coll->co_accepts = NULL;
- coll->co_refusals = NULL;
-
- /* Set up a mask of file attributes that we don't want to sync
- with the server. */
- if (!(coll->co_options & CO_SETOWNER))
- coll->co_attrignore |= FA_OWNER | FA_GROUP;
- if (!(coll->co_options & CO_SETMODE))
- coll->co_attrignore |= FA_MODE;
- if (!(coll->co_options & CO_SETFLAGS))
- coll->co_attrignore |= FA_FLAGS;
- }
- return (STATUS_SUCCESS);
-bad:
- lprintf(-1, "Protocol error during collection exchange\n");
- return (STATUS_FAILURE);
-}
-
-static struct mux *
-proto_mux(struct config *config)
-{
- struct mux *m;
- struct stream *s, *wr;
- struct chan *chan0, *chan1;
- int id;
-
- s = config->server;
- lprintf(2, "Establishing multiplexed-mode data connection\n");
- proto_printf(s, "MUX\n");
- stream_flush(s);
- m = mux_open(config->socket, &chan0);
- if (m == NULL) {
- lprintf(-1, "Cannot open the multiplexer\n");
- return (NULL);
- }
- id = chan_listen(m);
- if (id == -1) {
- lprintf(-1, "ChannelMux.Listen failed: %s\n", strerror(errno));
- mux_close(m);
- return (NULL);
- }
- wr = stream_open(chan0, NULL, (stream_writefn_t *)chan_write, NULL);
- proto_printf(wr, "CHAN %d\n", id);
- stream_close(wr);
- chan1 = chan_accept(m, id);
- if (chan1 == NULL) {
- lprintf(-1, "ChannelMux.Accept failed: %s\n", strerror(errno));
- mux_close(m);
- return (NULL);
- }
- config->chan0 = chan0;
- config->chan1 = chan1;
- return (m);
-}
-
-/*
- * Initializes the connection to the CVSup server, that is handle
- * the protocol negotiation, logging in, exchanging file attributes
- * support and collections information, and finally run the update
- * session.
- */
-int
-proto_run(struct config *config)
-{
- struct thread_args lister_args;
- struct thread_args detailer_args;
- struct thread_args updater_args;
- struct thread_args *args;
- struct killer killer;
- struct threads *workers;
- struct mux *m;
- int i, status;
-
- /*
- * We pass NULL for the close() function because we'll reuse
- * the socket after the stream is closed.
- */
- config->server = stream_open_fd(config->socket, stream_read_fd,
- stream_write_fd, NULL);
- status = proto_greet(config);
- if (status == STATUS_SUCCESS)
- status = proto_negproto(config);
- if (status == STATUS_SUCCESS)
- status = proto_login(config);
- if (status == STATUS_SUCCESS)
- status = proto_fileattr(config);
- if (status == STATUS_SUCCESS)
- status = proto_xchgcoll(config);
- if (status != STATUS_SUCCESS)
- return (status);
-
- /* Multi-threaded action starts here. */
- m = proto_mux(config);
- if (m == NULL)
- return (STATUS_FAILURE);
-
- stream_close(config->server);
- config->server = NULL;
- config->fixups = fixups_new();
- killer_start(&killer, m);
-
- /* Start the worker threads. */
- workers = threads_new();
- args = &lister_args;
- args->config = config;
- args->status = -1;
- args->errmsg = NULL;
- args->rd = NULL;
- args->wr = stream_open(config->chan0,
- NULL, (stream_writefn_t *)chan_write, NULL);
- threads_create(workers, lister, args);
-
- args = &detailer_args;
- args->config = config;
- args->status = -1;
- args->errmsg = NULL;
- args->rd = stream_open(config->chan0,
- (stream_readfn_t *)chan_read, NULL, NULL);
- args->wr = stream_open(config->chan1,
- NULL, (stream_writefn_t *)chan_write, NULL);
- threads_create(workers, detailer, args);
-
- args = &updater_args;
- args->config = config;
- args->status = -1;
- args->errmsg = NULL;
- args->rd = stream_open(config->chan1,
- (stream_readfn_t *)chan_read, NULL, NULL);
- args->wr = NULL;
- threads_create(workers, updater, args);
-
- lprintf(2, "Running\n");
- /* Wait for all the worker threads to finish. */
- status = STATUS_SUCCESS;
- for (i = 0; i < 3; i++) {
- args = threads_wait(workers);
- if (args->rd != NULL)
- stream_close(args->rd);
- if (args->wr != NULL)
- stream_close(args->wr);
- if (args->status != STATUS_SUCCESS) {
- assert(args->errmsg != NULL);
- if (status == STATUS_SUCCESS) {
- status = args->status;
- /* Shutdown the multiplexer to wake up all
- the other threads. */
- mux_shutdown(m, args->errmsg, status);
- }
- free(args->errmsg);
- }
- }
- threads_free(workers);
- if (status == STATUS_SUCCESS) {
- lprintf(2, "Shutting down connection to server\n");
- chan_close(config->chan0);
- chan_close(config->chan1);
- chan_wait(config->chan0);
- chan_wait(config->chan1);
- mux_shutdown(m, NULL, STATUS_SUCCESS);
- }
- killer_stop(&killer);
- fixups_free(config->fixups);
- status = mux_close(m);
- if (status == STATUS_SUCCESS) {
- lprintf(1, "Finished successfully\n");
- } else if (status == STATUS_INTERRUPTED) {
- lprintf(-1, "Interrupted\n");
- if (killer.killedby != -1)
- kill(getpid(), killer.killedby);
- }
- return (status);
-}
-
-/*
- * Write a string into the stream, escaping characters as needed.
- * Characters escaped:
- *
- * SPACE -> "\_"
- * TAB -> "\t"
- * NEWLINE -> "\n"
- * CR -> "\r"
- * \ -> "\\"
- */
-static int
-proto_escape(struct stream *wr, const char *s)
-{
- size_t len;
- ssize_t n;
- char c;
-
- /* Handle characters that need escaping. */
- do {
- len = strcspn(s, " \t\r\n\\");
- n = stream_write(wr, s, len);
- if (n == -1)
- return (-1);
- c = s[len];
- switch (c) {
- case ' ':
- n = stream_write(wr, "\\_", 2);
- break;
- case '\t':
- n = stream_write(wr, "\\t", 2);
- break;
- case '\r':
- n = stream_write(wr, "\\r", 2);
- break;
- case '\n':
- n = stream_write(wr, "\\n", 2);
- break;
- case '\\':
- n = stream_write(wr, "\\\\", 2);
- break;
- }
- if (n == -1)
- return (-1);
- s += len + 1;
- } while (c != '\0');
- return (0);
-}
-
-/*
- * A simple printf() implementation specifically tailored for csup.
- * List of the supported formats:
- *
- * %c Print a char.
- * %d or %i Print an int as decimal.
- * %x Print an int as hexadecimal.
- * %o Print an int as octal.
- * %t Print a time_t as decimal.
- * %s Print a char * escaping some characters as needed.
- * %S Print a char * without escaping.
- * %f Print an encoded struct fattr *.
- * %F Print an encoded struct fattr *, specifying the supported
- * attributes.
- */
-int
-proto_printf(struct stream *wr, const char *format, ...)
-{
- fattr_support_t *support;
- long long longval;
- struct fattr *fa;
- const char *fmt;
- va_list ap;
- char *cp, *s, *attr;
- ssize_t n;
- int rv, val, ignore;
- char c;
-
- n = 0;
- rv = 0;
- fmt = format;
- va_start(ap, format);
- while ((cp = strchr(fmt, '%')) != NULL) {
- if (cp > fmt) {
- n = stream_write(wr, fmt, cp - fmt);
- if (n == -1)
- return (-1);
- }
- if (*++cp == '\0')
- goto done;
- switch (*cp) {
- case 'c':
- c = va_arg(ap, int);
- rv = stream_printf(wr, "%c", c);
- break;
- case 'd':
- case 'i':
- val = va_arg(ap, int);
- rv = stream_printf(wr, "%d", val);
- break;
- case 'x':
- val = va_arg(ap, int);
- rv = stream_printf(wr, "%x", val);
- break;
- case 'o':
- val = va_arg(ap, int);
- rv = stream_printf(wr, "%o", val);
- break;
- case 'S':
- s = va_arg(ap, char *);
- assert(s != NULL);
- rv = stream_printf(wr, "%s", s);
- break;
- case 's':
- s = va_arg(ap, char *);
- assert(s != NULL);
- rv = proto_escape(wr, s);
- break;
- case 't':
- longval = (long long)va_arg(ap, time_t);
- rv = stream_printf(wr, "%lld", longval);
- break;
- case 'f':
- fa = va_arg(ap, struct fattr *);
- attr = fattr_encode(fa, NULL, 0);
- rv = proto_escape(wr, attr);
- free(attr);
- break;
- case 'F':
- fa = va_arg(ap, struct fattr *);
- support = va_arg(ap, fattr_support_t *);
- ignore = va_arg(ap, int);
- attr = fattr_encode(fa, *support, ignore);
- rv = proto_escape(wr, attr);
- free(attr);
- break;
- case '%':
- n = stream_write(wr, "%", 1);
- if (n == -1)
- return (-1);
- break;
- }
- if (rv == -1)
- return (-1);
- fmt = cp + 1;
- }
- if (*fmt != '\0') {
- rv = stream_printf(wr, "%s", fmt);
- if (rv == -1)
- return (-1);
- }
-done:
- va_end(ap);
- return (0);
-}
-
-/*
- * Unescape the string, see proto_escape().
- */
-static void
-proto_unescape(char *s)
-{
- char *cp, *cp2;
-
- cp = s;
- while ((cp = strchr(cp, '\\')) != NULL) {
- switch (cp[1]) {
- case '_':
- *cp = ' ';
- break;
- case 't':
- *cp = '\t';
- break;
- case 'r':
- *cp = '\r';
- break;
- case 'n':
- *cp = '\n';
- break;
- case '\\':
- *cp = '\\';
- break;
- default:
- *cp = *(cp + 1);
- }
- cp2 = ++cp;
- while (*cp2 != '\0') {
- *cp2 = *(cp2 + 1);
- cp2++;
- }
- }
-}
-
-/*
- * Get an ascii token in the string.
- */
-char *
-proto_get_ascii(char **s)
-{
- char *ret;
-
- ret = strsep(s, " ");
- if (ret == NULL)
- return (NULL);
- /* Make sure we disallow 0-length fields. */
- if (*ret == '\0') {
- *s = NULL;
- return (NULL);
- }
- proto_unescape(ret);
- return (ret);
-}
-
-/*
- * Get the rest of the string.
- */
-char *
-proto_get_rest(char **s)
-{
- char *ret;
-
- if (s == NULL)
- return (NULL);
- ret = *s;
- proto_unescape(ret);
- *s = NULL;
- return (ret);
-}
-
-/*
- * Get an int token.
- */
-int
-proto_get_int(char **s, int *val, int base)
-{
- char *cp;
- int error;
-
- cp = proto_get_ascii(s);
- if (cp == NULL)
- return (-1);
- error = asciitoint(cp, val, base);
- return (error);
-}
-
-/*
- * Get a time_t token.
- *
- * Ideally, we would use an intmax_t and strtoimax() here, but strtoll()
- * is more portable and 64bits should be enough for a timestamp.
- */
-int
-proto_get_time(char **s, time_t *val)
-{
- long long tmp;
- char *cp, *end;
-
- cp = proto_get_ascii(s);
- if (cp == NULL)
- return (-1);
- errno = 0;
- tmp = strtoll(cp, &end, 10);
- if (errno || *end != '\0')
- return (-1);
- *val = (time_t)tmp;
- return (0);
-}
-
-/* Start the killer thread. It is used to protect against some signals
- during the multi-threaded run so that we can gracefully fail. */
-static void
-killer_start(struct killer *k, struct mux *m)
-{
- int error;
-
- k->mux = m;
- k->killedby = -1;
- sigemptyset(&k->sigset);
- sigaddset(&k->sigset, SIGINT);
- sigaddset(&k->sigset, SIGHUP);
- sigaddset(&k->sigset, SIGTERM);
- sigaddset(&k->sigset, SIGPIPE);
- pthread_sigmask(SIG_BLOCK, &k->sigset, NULL);
- error = pthread_create(&k->thread, NULL, killer_run, k);
- if (error)
- err(1, "pthread_create");
-}
-
-/* The main loop of the killer thread. */
-static void *
-killer_run(void *arg)
-{
- struct killer *k;
- int error, sig, old;
-
- k = arg;
-again:
- error = sigwait(&k->sigset, &sig);
- assert(!error);
- if (sig == SIGINT || sig == SIGHUP || sig == SIGTERM) {
- if (k->killedby == -1) {
- k->killedby = sig;
- /* Ensure we don't get canceled during the shutdown. */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old);
- mux_shutdown(k->mux, "Cleaning up ...",
- STATUS_INTERRUPTED);
- pthread_setcancelstate(old, NULL);
- }
- }
- goto again;
-}
-
-/* Stop the killer thread. */
-static void
-killer_stop(struct killer *k)
-{
- void *val;
- int error;
-
- error = pthread_cancel(k->thread);
- assert(!error);
- pthread_join(k->thread, &val);
- assert(val == PTHREAD_CANCELED);
- pthread_sigmask(SIG_UNBLOCK, &k->sigset, NULL);
-}
--- contrib/csup/diff.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/diff.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _DIFF_H_
-#define _DIFF_H_
-
-struct stream;
-struct keyword;
-struct file_update;
-
-/* Description of an RCS delta. */
-struct diffinfo {
- char *di_rcsfile; /* RCS filename */
- char *di_cvsroot; /* CVS root prefix */
- char *di_revnum; /* Revision number */
- char *di_revdate; /* Revision date */
- char *di_author; /* Author of the delta */
- char *di_tag; /* CVS tag, if any */
- char *di_state; /* State of the branch */
- int di_expand; /* CVS expansion mode */
-};
-
-int diff_apply(struct stream *, struct stream *, struct stream *,
- struct keyword *, struct diffinfo *);
-
-#endif /* !_DIFF_H_ */
--- contrib/csup/token.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/token.h,v 1.1.1.2.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _TOKEN_H_
-#define _TOKEN_H_
-
-void yyerror(const char *);
-int yylex(void);
-int yyparse(void);
-
-/* Parsing tokens. */
-#define PT_BASE 0
-#define PT_DATE 1
-#define PT_HOST 2
-#define PT_PREFIX 3
-#define PT_RELEASE 4
-#define PT_TAG 5
-#define PT_UMASK 6
-#define PT_COMPRESS 7
-#define PT_DELETE 8
-#define PT_USE_REL_SUFFIX 9
-#define PT_LIST 10
-#define PT_NORSYNC 11
-
-#endif /* !_TOKEN_H_ */
--- contrib/csup/fnmatch.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * 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, 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * From FreeBSD fnmatch.c 1.11
- * $Id: fnmatch.c,v 1.3 1997/08/19 02:34:30 jdp Exp $
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
-#endif /* LIBC_SCCS and not lint */
-
-/*
- * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- * Compares a filename or pathname to a pattern.
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "fnmatch.h"
-
-#define EOS '\0'
-
-static const char *rangematch(const char *, char, int);
-
-int
-fnmatch(const char *pattern, const char *string, int flags)
-{
- const char *stringstart;
- char c, test;
-
- for (stringstart = string;;)
- switch (c = *pattern++) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return (0);
- return (*string == EOS ? 0 : FNM_NOMATCH);
- case '?':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
- ++string;
- break;
- case '*':
- c = *pattern;
- /* Collapse multiple stars. */
- while (c == '*')
- c = *++pattern;
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS)
- if (flags & FNM_PATHNAME)
- return ((flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH);
- else
- return (0);
- else if (c == '/' && flags & FNM_PATHNAME) {
- if ((string = strchr(string, '/')) == NULL)
- return (FNM_NOMATCH);
- break;
- }
-
- /* General case, use recursion. */
- while ((test = *string) != EOS) {
- if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
- return (0);
- if (test == '/' && flags & FNM_PATHNAME)
- break;
- ++string;
- }
- return (FNM_NOMATCH);
- case '[':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && flags & FNM_PATHNAME)
- return (FNM_NOMATCH);
- if ((pattern =
- rangematch(pattern, *string, flags)) == NULL)
- return (FNM_NOMATCH);
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = *pattern++) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- if (c == *string)
- ;
- else if ((flags & FNM_CASEFOLD) &&
- (tolower((unsigned char)c) ==
- tolower((unsigned char)*string)))
- ;
- else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
- ((c == '/' && string != stringstart) ||
- (string == stringstart+1 && *stringstart == '/')))
- return (0);
- else
- return (FNM_NOMATCH);
- string++;
- break;
- }
- /* NOTREACHED */
-}
-
-static const char *
-rangematch(const char *pattern, char test, int flags)
-{
- int negate, ok;
- char c, c2;
-
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin at ngai.kaleida.com)
- */
- if ( (negate = (*pattern == '!' || *pattern == '^')) )
- ++pattern;
-
- if (flags & FNM_CASEFOLD)
- test = tolower((unsigned char)test);
-
- for (ok = 0; (c = *pattern++) != ']';) {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *pattern++;
- if (c == EOS)
- return (NULL);
-
- if (flags & FNM_CASEFOLD)
- c = tolower((unsigned char)c);
-
- if (*pattern == '-'
- && (c2 = *(pattern+1)) != EOS && c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = *pattern++;
- if (c2 == EOS)
- return (NULL);
-
- if (flags & FNM_CASEFOLD)
- c2 = tolower((unsigned char)c2);
-
- if ((unsigned char)c <= (unsigned char)test &&
- (unsigned char)test <= (unsigned char)c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- }
- return (ok == negate ? NULL : pattern);
-}
--- contrib/csup/misc.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/misc.c,v 1.1.1.3.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <openssl/md5.h>
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "fattr.h"
-#include "main.h"
-#include "misc.h"
-
-struct pattlist {
- char **patterns;
- size_t size;
- size_t in;
-};
-
-struct backoff_timer {
- time_t min;
- time_t max;
- time_t interval;
- float backoff;
- float jitter;
-};
-
-static void bt_update(struct backoff_timer *);
-static void bt_addjitter(struct backoff_timer *);
-
-int
-asciitoint(const char *s, int *val, int base)
-{
- char *end;
- long longval;
-
- errno = 0;
- longval = strtol(s, &end, base);
- if (errno || *end != '\0')
- return (-1);
- if (longval > INT_MAX || longval < INT_MIN) {
- errno = ERANGE;
- return (-1);
- }
- *val = longval;
- return (0);
-}
-
-int
-lprintf(int level, const char *fmt, ...)
-{
- FILE *to;
- va_list ap;
- int ret;
-
- if (level > verbose)
- return (0);
- if (level == -1)
- to = stderr;
- else
- to = stdout;
- va_start(ap, fmt);
- ret = vfprintf(to, fmt, ap);
- va_end(ap);
- fflush(to);
- return (ret);
-}
-
-/*
- * Compute the MD5 checksum of a file. The md parameter must
- * point to a buffer containing at least MD5_DIGEST_SIZE bytes.
- *
- * Do not confuse OpenSSL's MD5_DIGEST_LENGTH with our own
- * MD5_DIGEST_SIZE macro.
- */
-int
-MD5_File(char *path, char *md)
-{
- char buf[1024];
- MD5_CTX ctx;
- ssize_t n;
- int fd;
-
- fd = open(path, O_RDONLY);
- if (fd == -1)
- return (-1);
- MD5_Init(&ctx);
- while ((n = read(fd, buf, sizeof(buf))) > 0)
- MD5_Update(&ctx, buf, n);
- close(fd);
- if (n == -1)
- return (-1);
- MD5_End(md, &ctx);
- return (0);
-}
-
-/*
- * Wrapper around MD5_Final() that converts the 128 bits MD5 hash
- * to an ASCII string representing this value in hexadecimal.
- */
-void
-MD5_End(char *md, MD5_CTX *c)
-{
- unsigned char md5[MD5_DIGEST_LENGTH];
- const char hex[] = "0123456789abcdef";
- int i, j;
-
- MD5_Final(md5, c);
- j = 0;
- for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
- md[j++] = hex[md5[i] >> 4];
- md[j++] = hex[md5[i] & 0xf];
- }
- md[j] = '\0';
-}
-
-int
-pathcmp(const char *s1, const char *s2)
-{
- char c1, c2;
-
- do {
- c1 = *s1++;
- if (c1 == '/')
- c1 = 1;
- c2 = *s2++;
- if (c2 == '/')
- c2 = 1;
- } while (c1 == c2 && c1 != '\0');
-
- return (c1 - c2);
-}
-
-size_t
-commonpathlength(const char *a, size_t alen, const char *b, size_t blen)
-{
- size_t i, minlen, lastslash;
-
- minlen = min(alen, blen);
- lastslash = 0;
- for (i = 0; i < minlen; i++) {
- if (a[i] != b[i])
- return (lastslash);
- if (a[i] == '/') {
- if (i == 0) /* Include the leading slash. */
- lastslash = 1;
- else
- lastslash = i;
- }
- }
-
- /* One path is a prefix of the other/ */
- if (alen > minlen) { /* Path "b" is a prefix of "a". */
- if (a[minlen] == '/')
- return (minlen);
- else
- return (lastslash);
- } else if (blen > minlen) { /* Path "a" is a prefix of "b". */
- if (b[minlen] == '/')
- return (minlen);
- else
- return (lastslash);
- }
-
- /* The paths are identical. */
- return (minlen);
-}
-
-char *
-pathlast(char *path)
-{
- char *s;
-
- s = strrchr(path, '/');
- if (s == NULL)
- return (path);
- return (++s);
-}
-
-int
-rcsdatetotm(const char *revdate, struct tm *tm)
-{
- char *cp;
- size_t len;
-
- cp = strchr(revdate, '.');
- if (cp == NULL)
- return (-1);
- len = cp - revdate;
- if (len >= 4)
- cp = strptime(revdate, "%Y.%m.%d.%H.%M.%S", tm);
- else if (len == 2)
- cp = strptime(revdate, "%y.%m.%d.%H.%M.%S", tm);
- else
- return (-1);
- if (cp == NULL || *cp != '\0')
- return (-1);
- return (0);
-}
-
-time_t
-rcsdatetotime(const char *revdate)
-{
- struct tm tm;
- time_t t;
- int error;
-
- error = rcsdatetotm(revdate, &tm);
- if (error)
- return (error);
- t = timegm(&tm);
- return (t);
-}
-
-/*
- * Returns a buffer allocated with malloc() containing the absolute
- * pathname to the checkout file made from the prefix and the path
- * of the corresponding RCS file relatively to the prefix. If the
- * filename is not an RCS filename, NULL will be returned.
- */
-char *
-checkoutpath(const char *prefix, const char *file)
-{
- const char *cp;
- char *path;
- size_t len;
-
- if (file[0] == '/')
- return (NULL);
- cp = file;
- while ((cp = strstr(cp, "..")) != NULL) {
- if (cp == file || cp[2] == '\0' ||
- (cp[-1] == '/' && cp[2] == '/'))
- return (NULL);
- cp += 2;
- }
- len = strlen(file);
- if (len < 2 || file[len - 1] != 'v' || file[len - 2] != ',')
- return (NULL);
- xasprintf(&path, "%s/%.*s", prefix, (int)len - 2, file);
- return (path);
-}
-
-int
-mkdirhier(char *path, mode_t mask)
-{
- struct fattr *fa;
- size_t i, last, len;
- int error, finish, rv;
-
- finish = 0;
- last = 0;
- len = strlen(path);
- for (i = len - 1; i > 0; i--) {
- if (path[i] == '/') {
- path[i] = '\0';
- if (access(path, F_OK) == 0) {
- path[i] = '/';
- break;
- }
- if (errno != ENOENT) {
- path[i] = '/';
- if (last == 0)
- return (-1);
- finish = 1;
- break;
- }
- last = i;
- }
- }
- if (last == 0)
- return (0);
-
- i = strlen(path);
- fa = fattr_new(FT_DIRECTORY, -1);
- fattr_mergedefault(fa);
- fattr_umask(fa, mask);
- while (i < len) {
- if (!finish) {
- rv = 0;
- error = fattr_makenode(fa, path);
- if (!error)
- rv = fattr_install(fa, path, NULL);
- if (error || rv == -1)
- finish = 1;
- }
- path[i] = '/';
- i += strlen(path + i);
- }
- assert(i == len);
- if (finish)
- return (-1);
- return (0);
-}
-
-/*
- * Compute temporary pathnames.
- * This can look a bit like overkill but we mimic CVSup's behaviour.
- */
-#define TEMPNAME_PREFIX "#cvs.csup"
-
-static pthread_mutex_t tempname_mtx = PTHREAD_MUTEX_INITIALIZER;
-static pid_t tempname_pid = -1;
-static int tempname_count;
-
-char *
-tempname(const char *path)
-{
- char *cp, *temp;
- int count, error;
-
- error = pthread_mutex_lock(&tempname_mtx);
- assert(!error);
- if (tempname_pid == -1) {
- tempname_pid = getpid();
- tempname_count = 0;
- }
- count = tempname_count++;
- error = pthread_mutex_unlock(&tempname_mtx);
- assert(!error);
- cp = strrchr(path, '/');
- if (cp == NULL)
- xasprintf(&temp, "%s-%ld.%d", TEMPNAME_PREFIX,
- (long)tempname_pid, count);
- else
- xasprintf(&temp, "%.*s%s-%ld.%d", (int)(cp - path + 1), path,
- TEMPNAME_PREFIX, (long)tempname_pid, count);
- return (temp);
-}
-
-void *
-xmalloc(size_t size)
-{
- void *buf;
-
- buf = malloc(size);
- if (buf == NULL)
- err(1, "malloc");
- return (buf);
-}
-
-void *
-xrealloc(void *buf, size_t size)
-{
-
- buf = realloc(buf, size);
- if (buf == NULL)
- err(1, "realloc");
- return (buf);
-}
-
-char *
-xstrdup(const char *str)
-{
- char *buf;
-
- buf = strdup(str);
- if (buf == NULL)
- err(1, "strdup");
- return (buf);
-}
-
-int
-xasprintf(char **ret, const char *format, ...)
-{
- va_list ap;
- int rv;
-
- va_start(ap, format);
- rv = vasprintf(ret, format, ap);
- va_end(ap);
- if (*ret == NULL)
- err(1, "asprintf");
- return (rv);
-}
-
-struct pattlist *
-pattlist_new(void)
-{
- struct pattlist *p;
-
- p = xmalloc(sizeof(struct pattlist));
- p->size = 4; /* Initial size. */
- p->patterns = xmalloc(p->size * sizeof(char *));
- p->in = 0;
- return (p);
-}
-
-void
-pattlist_add(struct pattlist *p, const char *pattern)
-{
-
- if (p->in == p->size) {
- p->size *= 2;
- p->patterns = xrealloc(p->patterns, p->size * sizeof(char *));
- }
- assert(p->in < p->size);
- p->patterns[p->in++] = xstrdup(pattern);
-}
-
-char *
-pattlist_get(struct pattlist *p, size_t i)
-{
-
- assert(i < p->in);
- return (p->patterns[i]);
-}
-
-size_t
-pattlist_size(struct pattlist *p)
-{
-
- return (p->in);
-}
-
-void
-pattlist_free(struct pattlist *p)
-{
- size_t i;
-
- for (i = 0; i < p->in; i++)
- free(p->patterns[i]);
- free(p->patterns);
- free(p);
-}
-
-/* Creates a backoff timer. */
-struct backoff_timer *
-bt_new(time_t min, time_t max, float backoff, float jitter)
-{
- struct backoff_timer *bt;
-
- bt = xmalloc(sizeof(struct backoff_timer));
- bt->min = min;
- bt->max = max;
- bt->backoff = backoff;
- bt->jitter = jitter;
- bt->interval = min;
- bt_addjitter(bt);
- srandom(time(0));
- return (bt);
-}
-
-/* Updates the backoff timer. */
-static void
-bt_update(struct backoff_timer *bt)
-{
-
- bt->interval = (time_t)min(bt->interval * bt->backoff, bt->max);
- bt_addjitter(bt);
-}
-
-/* Adds some jitter. */
-static void
-bt_addjitter(struct backoff_timer *bt)
-{
- long mag;
-
- mag = (long)(bt->jitter * bt->interval);
- /* We want a random number between -mag and mag. */
- bt->interval += (time_t)(random() % (2 * mag) - mag);
-}
-
-/* Returns the current timer value. */
-time_t
-bt_get(struct backoff_timer *bt)
-{
-
- return (bt->interval);
-}
-
-/* Times out for bt->interval seconds. */
-void
-bt_pause(struct backoff_timer *bt)
-{
-
- sleep(bt->interval);
- bt_update(bt);
-}
-
-void
-bt_free(struct backoff_timer *bt)
-{
-
- free(bt);
-}
--- contrib/csup/token.l
+++ /dev/null
@@ -1,80 +0,0 @@
-%{
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/token.l,v 1.1.1.2.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <err.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "parse.h"
-#include "misc.h"
-#include "token.h"
-
-#define YY_NO_UNPUT
-
-int lineno = 1;
-
-%}
-
-%option noyywrap
-
-%%
-
-[ \t]+ ;
-#.* ;
-\*default { return DEFAULT; }
-base { yylval.i = PT_BASE; return NAME; }
-date { yylval.i = PT_DATE; return NAME; }
-host { yylval.i = PT_HOST; return NAME; }
-prefix { yylval.i = PT_PREFIX; return NAME; }
-release { yylval.i = PT_RELEASE; return NAME; }
-tag { yylval.i = PT_TAG; return NAME; }
-umask { yylval.i = PT_UMASK; return NAME; }
-list { yylval.i = PT_LIST; return NAME; }
-norsync { yylval.i = PT_NORSYNC; return NAME; }
-= { return EQUAL; }
-compress { yylval.i = PT_COMPRESS; return BOOLEAN; }
-delete { yylval.i = PT_DELETE; return BOOLEAN; }
-use-rel-suffix { yylval.i = PT_USE_REL_SUFFIX; return BOOLEAN; }
-[a-zA-Z0-9./_-]+ {
- yylval.str = strdup(yytext);
- if (yylval.str == NULL)
- err(1, "strdup");
- return STRING;
- }
-\n lineno++;
-
-%%
-
-void
-yyerror(const char *s)
-{
-
- lprintf(-1, "Parse error line %d: %s: %s\n", lineno, s, yytext);
- exit(1);
-}
--- contrib/csup/fattr_posix.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $Id$
- */
-
-/*
- * The file attributes we support in a POSIX environment.
- */
-fattr_support_t fattr_support = {
- /* FT_UNKNOWN */
- 0,
- /* FT_FILE */
- FA_FILETYPE | FA_MODTIME | FA_SIZE | FA_OWNER | FA_GROUP | FA_MODE |
- FA_LINKCOUNT | FA_INODE | FA_DEV,
- /* FT_DIRECTORY */
- FA_FILETYPE | FA_OWNER | FA_GROUP | FA_MODE,
- /* FT_CDEV */
- FA_FILETYPE | FA_RDEV | FA_OWNER | FA_GROUP | FA_MODE | FA_LINKCOUNT |
- FA_DEV | FA_INODE,
- /* FT_BDEV */
- FA_FILETYPE | FA_RDEV | FA_OWNER | FA_GROUP | FA_MODE | FA_LINKCOUNT |
- FA_DEV | FA_INODE,
- /* FT_SYMLINK */
- FA_FILETYPE | FA_LINKTARGET
-};
--- contrib/csup/main.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $Id$
- */
-
-extern int verbose;
--- contrib/csup/detailer.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/detailer.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _DETAILER_H_
-#define _DETAILER_H_
-
-void *detailer(void *);
-
-#endif /* !_DETAILER_H_ */
--- contrib/csup/misc.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/misc.h,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _MISC_H_
-#define _MISC_H_
-
-#include <openssl/md5.h>
-
-#include <sys/types.h>
-
-/* If we're not compiling in a C99 environment, define the C99 types. */
-#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901
-
-#ifdef uint32_t
-#undef uint32_t
-#endif
-#define uint32_t u_int32_t
-
-#ifdef uint16_t
-#undef uint16_t
-#endif
-#define uint16_t u_int16_t
-
-#ifdef uint8_t
-#undef uint8_t
-#endif
-#define uint8_t u_int8_t
-
-#else
-#include <stdint.h>
-#endif
-
-/* This is a GCC-specific keyword but some other compilers (namely icc)
- understand it, and the code won't work if we can't disable padding
- anyways. */
-#undef __packed
-#define __packed __attribute__((__packed__))
-
-/* We explicitely don't define this with icc because it defines __GNUC__
- but doesn't support it. */
-#undef __printflike
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
- (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC__MINOR__ >= 7)
-#define __printflike(fmtarg, firstvararg) \
- __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
-#else
-#define __printflike(fmtarg, firstvararg)
-#endif
-
-/* Exit codes. */
-#define STATUS_SUCCESS 0
-#define STATUS_FAILURE 1
-#define STATUS_TRANSIENTFAILURE 2
-#define STATUS_INTERRUPTED 3
-
-struct config;
-struct stream;
-
-/* Thread parameters. */
-struct thread_args {
- struct config *config;
- struct stream *rd;
- struct stream *wr;
- int status;
- char *errmsg;
-};
-
-/* Minimum size for MD5_File() and MD5_End() buffers. */
-#define MD5_DIGEST_SIZE 33
-
-#define min(a, b) ((a) > (b) ? (b) : (a))
-#define max(a, b) ((a) < (b) ? (b) : (a))
-
-struct backoff_timer;
-struct pattlist;
-struct tm;
-
-int asciitoint(const char *, int *, int);
-int lprintf(int, const char *, ...) __printflike(2, 3);
-int MD5_File(char *, char *);
-void MD5_End(char *, MD5_CTX *);
-int rcsdatetotm(const char *, struct tm *);
-time_t rcsdatetotime(const char *);
-int pathcmp(const char *, const char *);
-size_t commonpathlength(const char *, size_t, const char *, size_t);
-char *pathlast(char *);
-char *checkoutpath(const char *, const char *);
-int mkdirhier(char *, mode_t);
-char *tempname(const char *);
-void *xmalloc(size_t);
-void *xrealloc(void *, size_t);
-char *xstrdup(const char *);
-int xasprintf(char **, const char *, ...) __printflike(2, 3);
-
-struct pattlist *pattlist_new(void);
-void pattlist_add(struct pattlist *, const char *);
-char *pattlist_get(struct pattlist *, size_t);
-size_t pattlist_size(struct pattlist *);
-void pattlist_free(struct pattlist *);
-
-struct backoff_timer *bt_new(time_t, time_t, float, float);
-time_t bt_get(struct backoff_timer *);
-void bt_pause(struct backoff_timer *);
-void bt_free(struct backoff_timer *);
-
-#endif /* !_MISC_H_ */
--- contrib/csup/stream.c
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/stream.c,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <zlib.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "misc.h"
-#include "stream.h"
-
-/*
- * Simple stream API to make my life easier. If the fgetln() and
- * funopen() functions were standard and if funopen() wasn't using
- * wrong types for the function pointers, I could have just used
- * stdio, but life sucks.
- *
- * For now, streams are always block-buffered.
- */
-
-/*
- * Try to quiet warnings as much as possible with GCC while staying
- * compatible with other compilers.
- */
-#ifndef __unused
-#if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7)
-#define __unused __attribute__((__unused__))
-#else
-#define __unused
-#endif
-#endif
-
-/*
- * Flags passed to the flush methods.
- *
- * STREAM_FLUSH_CLOSING is passed during the last flush call before
- * closing a stream. This allows the zlib filter to emit the EOF
- * marker as appropriate. In all other cases, STREAM_FLUSH_NORMAL
- * should be passed.
- *
- * These flags are completely unused in the default flush method,
- * but they are very important for the flush method of the zlib
- * filter.
- */
-typedef enum {
- STREAM_FLUSH_NORMAL,
- STREAM_FLUSH_CLOSING
-} stream_flush_t;
-
-/*
- * This is because buf_new() will always allocate size + 1 bytes,
- * so our buffer sizes will still be power of 2 values.
- */
-#define STREAM_BUFSIZ 1023
-
-struct buf {
- char *buf;
- size_t size;
- size_t in;
- size_t off;
-};
-
-struct stream {
- void *cookie;
- int fd;
- struct buf *rdbuf;
- struct buf *wrbuf;
- stream_readfn_t *readfn;
- stream_writefn_t *writefn;
- stream_closefn_t *closefn;
- int eof;
- struct stream_filter *filter;
- void *fdata;
-};
-
-typedef int stream_filter_initfn_t(struct stream *, void *);
-typedef void stream_filter_finifn_t(struct stream *);
-typedef int stream_filter_flushfn_t(struct stream *, struct buf *,
- stream_flush_t);
-typedef ssize_t stream_filter_fillfn_t(struct stream *, struct buf *);
-
-struct stream_filter {
- stream_filter_t id;
- stream_filter_initfn_t *initfn;
- stream_filter_finifn_t *finifn;
- stream_filter_fillfn_t *fillfn;
- stream_filter_flushfn_t *flushfn;
-};
-
-/* Low-level buffer API. */
-#define buf_avail(buf) ((buf)->size - (buf)->off - (buf)->in)
-#define buf_count(buf) ((buf)->in)
-#define buf_size(buf) ((buf)->size)
-
-static struct buf *buf_new(size_t);
-static void buf_more(struct buf *, size_t);
-static void buf_less(struct buf *, size_t);
-static void buf_free(struct buf *);
-static void buf_grow(struct buf *, size_t);
-
-/* Internal stream functions. */
-static ssize_t stream_fill(struct stream *);
-static ssize_t stream_fill_default(struct stream *, struct buf *);
-static int stream_flush_int(struct stream *, stream_flush_t);
-static int stream_flush_default(struct stream *, struct buf *,
- stream_flush_t);
-
-/* Filters specific functions. */
-static struct stream_filter *stream_filter_lookup(stream_filter_t);
-static int stream_filter_init(struct stream *, void *);
-static void stream_filter_fini(struct stream *);
-
-/* The zlib stream filter declarations. */
-#define ZFILTER_EOF 1 /* Got Z_STREAM_END. */
-
-struct zfilter {
- int flags;
- struct buf *rdbuf;
- struct buf *wrbuf;
- z_stream *rdstate;
- z_stream *wrstate;
-};
-
-static int zfilter_init(struct stream *, void *);
-static void zfilter_fini(struct stream *);
-static ssize_t zfilter_fill(struct stream *, struct buf *);
-static int zfilter_flush(struct stream *, struct buf *,
- stream_flush_t);
-
-/* The MD5 stream filter. */
-struct md5filter {
- MD5_CTX ctx;
- char *md5;
-};
-
-static int md5filter_init(struct stream *, void *);
-static void md5filter_fini(struct stream *);
-static ssize_t md5filter_fill(struct stream *, struct buf *);
-static int md5filter_flush(struct stream *, struct buf *,
- stream_flush_t);
-
-/* The available stream filters. */
-struct stream_filter stream_filters[] = {
- {
- STREAM_FILTER_NULL,
- NULL,
- NULL,
- stream_fill_default,
- stream_flush_default
- },
- {
- STREAM_FILTER_ZLIB,
- zfilter_init,
- zfilter_fini,
- zfilter_fill,
- zfilter_flush
- },
- {
- STREAM_FILTER_MD5,
- md5filter_init,
- md5filter_fini,
- md5filter_fill,
- md5filter_flush
- }
-};
-
-
-/* Create a new buffer. */
-static struct buf *
-buf_new(size_t size)
-{
- struct buf *buf;
-
- buf = xmalloc(sizeof(struct buf));
- /*
- * We keep one spare byte so that stream_getln() can put a '\0'
- * there in case the stream doesn't have an ending newline.
- */
- buf->buf = xmalloc(size + 1);
- buf->size = size;
- buf->in = 0;
- buf->off = 0;
- return (buf);
-}
-
-/*
- * Grow the size of the buffer. If "need" is 0, bump its size to the
- * next power of 2 value. Otherwise, bump it to the next power of 2
- * value bigger than "need".
- */
-static void
-buf_grow(struct buf *buf, size_t need)
-{
-
- if (need == 0)
- buf->size = buf->size * 2 + 1; /* Account for the spare byte. */
- else {
- assert(need > buf->size);
- while (buf->size < need)
- buf->size = buf->size * 2 + 1;
- }
- buf->buf = xrealloc(buf->buf, buf->size + 1);
-}
-
-/* Make more room in the buffer if needed. */
-static void
-buf_prewrite(struct buf *buf)
-{
-
- if (buf_count(buf) == buf_size(buf))
- buf_grow(buf, 0);
- if (buf_count(buf) > 0 && buf_avail(buf) == 0) {
- memmove(buf->buf, buf->buf + buf->off, buf_count(buf));
- buf->off = 0;
- }
-}
-
-/* Account for "n" bytes being added in the buffer. */
-static void
-buf_more(struct buf *buf, size_t n)
-{
-
- assert(n <= buf_avail(buf));
- buf->in += n;
-}
-
-/* Account for "n" bytes having been read in the buffer. */
-static void
-buf_less(struct buf *buf, size_t n)
-{
-
- assert(n <= buf_count(buf));
- buf->in -= n;
- if (buf->in == 0)
- buf->off = 0;
- else
- buf->off += n;
-}
-
-/* Free a buffer. */
-static void
-buf_free(struct buf *buf)
-{
-
- free(buf->buf);
- free(buf);
-}
-
-static struct stream *
-stream_new(stream_readfn_t *readfn, stream_writefn_t *writefn,
- stream_closefn_t *closefn)
-{
- struct stream *stream;
-
- stream = xmalloc(sizeof(struct stream));
- if (readfn == NULL && writefn == NULL) {
- errno = EINVAL;
- return (NULL);
- }
- if (readfn != NULL)
- stream->rdbuf = buf_new(STREAM_BUFSIZ);
- else
- stream->rdbuf = NULL;
- if (writefn != NULL)
- stream->wrbuf = buf_new(STREAM_BUFSIZ);
- else
- stream->wrbuf = NULL;
- stream->cookie = NULL;
- stream->fd = -1;
- stream->readfn = readfn;
- stream->writefn = writefn;
- stream->closefn = closefn;
- stream->filter = stream_filter_lookup(STREAM_FILTER_NULL);
- stream->fdata = NULL;
- stream->eof = 0;
- return (stream);
-}
-
-/* Create a new stream associated with a void *. */
-struct stream *
-stream_open(void *cookie, stream_readfn_t *readfn, stream_writefn_t *writefn,
- stream_closefn_t *closefn)
-{
- struct stream *stream;
-
- stream = stream_new(readfn, writefn, closefn);
- stream->cookie = cookie;
- return (stream);
-}
-
-/* Associate a file descriptor with a stream. */
-struct stream *
-stream_open_fd(int fd, stream_readfn_t *readfn, stream_writefn_t *writefn,
- stream_closefn_t *closefn)
-{
- struct stream *stream;
-
- stream = stream_new(readfn, writefn, closefn);
- stream->cookie = &stream->fd;
- stream->fd = fd;
- return (stream);
-}
-
-/* Like open() but returns a stream. */
-struct stream *
-stream_open_file(const char *path, int flags, ...)
-{
- struct stream *stream;
- stream_readfn_t *readfn;
- stream_writefn_t *writefn;
- va_list ap;
- mode_t mode;
- int fd;
-
- va_start(ap, flags);
- if (flags & O_CREAT) {
- /*
- * GCC says I should not be using mode_t here since it's
- * promoted to an int when passed through `...'.
- */
- mode = va_arg(ap, int);
- fd = open(path, flags, mode);
- } else
- fd = open(path, flags);
- va_end(ap);
- if (fd == -1)
- return (NULL);
-
- flags &= O_ACCMODE;
- if (flags == O_RDONLY) {
- readfn = stream_read_fd;
- writefn = NULL;
- } else if (flags == O_WRONLY) {
- readfn = NULL;
- writefn = stream_write_fd;
- } else if (flags == O_RDWR) {
- assert(flags == O_RDWR);
- readfn = stream_read_fd;
- writefn = stream_write_fd;
- } else {
- errno = EINVAL;
- close(fd);
- return (NULL);
- }
-
- stream = stream_open_fd(fd, readfn, writefn, stream_close_fd);
- if (stream == NULL)
- close(fd);
- return (stream);
-}
-
-/* Return the file descriptor associated with this stream, or -1. */
-int
-stream_fileno(struct stream *stream)
-{
-
- return (stream->fd);
-}
-
-/* Convenience read function for file descriptors. */
-ssize_t
-stream_read_fd(void *cookie, void *buf, size_t size)
-{
- ssize_t nbytes;
- int fd;
-
- fd = *(int *)cookie;
- nbytes = read(fd, buf, size);
- return (nbytes);
-}
-
-/* Convenience write function for file descriptors. */
-ssize_t
-stream_write_fd(void *cookie, const void *buf, size_t size)
-{
- ssize_t nbytes;
- int fd;
-
- fd = *(int *)cookie;
- nbytes = write(fd, buf, size);
- return (nbytes);
-}
-
-/* Convenience close function for file descriptors. */
-int
-stream_close_fd(void *cookie)
-{
- int fd, ret;
-
- fd = *(int *)cookie;
- ret = close(fd);
- return (ret);
-}
-
-/* Read some bytes from the stream. */
-ssize_t
-stream_read(struct stream *stream, void *buf, size_t size)
-{
- struct buf *rdbuf;
- ssize_t ret;
- size_t n;
-
- rdbuf = stream->rdbuf;
- if (buf_count(rdbuf) == 0) {
- ret = stream_fill(stream);
- if (ret <= 0)
- return (-1);
- }
- n = min(size, buf_count(rdbuf));
- memcpy(buf, rdbuf->buf + rdbuf->off, n);
- buf_less(rdbuf, n);
- return (n);
-}
-
-/*
- * Read a line from the stream and return a pointer to it.
- *
- * If "len" is non-NULL, the length of the string will be put into it.
- * The pointer is only valid until the next stream API call. The line
- * can be modified by the caller, provided he doesn't write before or
- * after it.
- *
- * This is somewhat similar to the BSD fgetln() function, except that
- * "len" can be NULL here. In that case the string is terminated by
- * overwriting the '\n' character with a NUL character. If it's the
- * last line in the stream and it has no ending newline, we can still
- * add '\0' after it, because we keep one spare byte in the buffers.
- *
- * However, be warned that one can't handle binary lines properly
- * without knowing the size of the string since those can contain
- * NUL characters.
- */
-char *
-stream_getln(struct stream *stream, size_t *len)
-{
- struct buf *buf;
- char *cp, *line;
- ssize_t n;
- size_t done, size;
-
- buf = stream->rdbuf;
- if (buf_count(buf) == 0) {
- n = stream_fill(stream);
- if (n <= 0)
- return (NULL);
- }
- cp = memchr(buf->buf + buf->off, '\n', buf_count(buf));
- for (done = buf_count(buf); cp == NULL; done += n) {
- n = stream_fill(stream);
- if (n < 0)
- return (NULL);
- if (n == 0)
- /* Last line of the stream. */
- cp = buf->buf + buf->off + buf->in - 1;
- else
- cp = memchr(buf->buf + buf->off + done, '\n',
- buf_count(buf) - done);
- }
- line = buf->buf + buf->off;
- assert(cp >= line);
- size = cp - line + 1;
- buf_less(buf, size);
- if (len != NULL) {
- *len = size;
- } else {
- /* Terminate the string when len == NULL. */
- if (line[size - 1] == '\n')
- line[size - 1] = '\0';
- else
- line[size] = '\0';
- }
- return (line);
-}
-
-/* Write some bytes to a stream. */
-ssize_t
-stream_write(struct stream *stream, const void *src, size_t nbytes)
-{
- struct buf *buf;
- int error;
-
- buf = stream->wrbuf;
- if (nbytes > buf_size(buf))
- buf_grow(buf, nbytes);
- if (nbytes > buf_avail(buf)) {
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (-1);
- }
- memcpy(buf->buf + buf->off + buf->in, src, nbytes);
- buf_more(buf, nbytes);
- return (nbytes);
-}
-
-/* Formatted output to a stream. */
-int
-stream_printf(struct stream *stream, const char *fmt, ...)
-{
- struct buf *buf;
- va_list ap;
- int error, ret;
-
- buf = stream->wrbuf;
-again:
- va_start(ap, fmt);
- ret = vsnprintf(buf->buf + buf->off + buf->in, buf_avail(buf), fmt, ap);
- va_end(ap);
- if (ret < 0)
- return (ret);
- if ((unsigned)ret >= buf_avail(buf)) {
- if ((unsigned)ret >= buf_size(buf))
- buf_grow(buf, ret + 1);
- if ((unsigned)ret >= buf_avail(buf)) {
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (-1);
- }
- goto again;
- }
- buf_more(buf, ret);
- return (ret);
-}
-
-/* Flush the entire write buffer of the stream. */
-int
-stream_flush(struct stream *stream)
-{
- int error;
-
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- return (error);
-}
-
-/* Internal flush API. */
-static int
-stream_flush_int(struct stream *stream, stream_flush_t how)
-{
- struct buf *buf;
- int error;
-
- buf = stream->wrbuf;
- error = (*stream->filter->flushfn)(stream, buf, how);
- assert(buf_count(buf) == 0);
- return (error);
-}
-
-/* The default flush method. */
-static int
-stream_flush_default(struct stream *stream, struct buf *buf,
- stream_flush_t __unused how)
-{
- ssize_t n;
-
- while (buf_count(buf) > 0) {
- do {
- n = (*stream->writefn)(stream->cookie,
- buf->buf + buf->off, buf_count(buf));
- } while (n == -1 && errno == EINTR);
- if (n <= 0)
- return (-1);
- buf_less(buf, n);
- }
- return (0);
-}
-
-/* Flush the write buffer and call fsync() on the file descriptor. */
-int
-stream_sync(struct stream *stream)
-{
- int error;
-
- if (stream->fd == -1) {
- errno = EINVAL;
- return (-1);
- }
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (-1);
- error = fsync(stream->fd);
- return (error);
-}
-
-/* Like truncate() but on a stream. */
-int
-stream_truncate(struct stream *stream, off_t size)
-{
- int error;
-
- if (stream->fd == -1) {
- errno = EINVAL;
- return (-1);
- }
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (-1);
- error = ftruncate(stream->fd, size);
- return (error);
-}
-
-/* Like stream_truncate() except the off_t parameter is an offset. */
-int
-stream_truncate_rel(struct stream *stream, off_t off)
-{
- struct stat sb;
- int error;
-
- if (stream->fd == -1) {
- errno = EINVAL;
- return (-1);
- }
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (-1);
- error = fstat(stream->fd, &sb);
- if (error)
- return (-1);
- error = stream_truncate(stream, sb.st_size + off);
- return (error);
-}
-
-/* Rewind the stream. */
-int
-stream_rewind(struct stream *stream)
-{
- int error;
-
- if (stream->fd == -1) {
- errno = EINVAL;
- return (-1);
- }
- if (stream->rdbuf != NULL)
- buf_less(stream->rdbuf, buf_count(stream->rdbuf));
- if (stream->wrbuf != NULL) {
- error = stream_flush_int(stream, STREAM_FLUSH_NORMAL);
- if (error)
- return (error);
- }
- error = lseek(stream->fd, 0, SEEK_SET);
- return (error);
-}
-
-/* Return EOF status. */
-int
-stream_eof(struct stream *stream)
-{
-
- return (stream->eof);
-}
-
-/* Close a stream and free any resources held by it. */
-int
-stream_close(struct stream *stream)
-{
- int error;
-
- if (stream == NULL)
- return (0);
-
- error = 0;
- if (stream->wrbuf != NULL)
- error = stream_flush_int(stream, STREAM_FLUSH_CLOSING);
- stream_filter_fini(stream);
- if (stream->closefn != NULL)
- /*
- * We might overwrite a previous error from stream_flush(),
- * but we have no choice, because wether it had worked or
- * not, we need to close the file descriptor.
- */
- error = (*stream->closefn)(stream->cookie);
- if (stream->rdbuf != NULL)
- buf_free(stream->rdbuf);
- if (stream->wrbuf != NULL)
- buf_free(stream->wrbuf);
- free(stream);
- return (error);
-}
-
-/* The default fill method. */
-static ssize_t
-stream_fill_default(struct stream *stream, struct buf *buf)
-{
- ssize_t n;
-
- if (stream->eof)
- return (0);
- assert(buf_avail(buf) > 0);
- n = (*stream->readfn)(stream->cookie, buf->buf + buf->off + buf->in,
- buf_avail(buf));
- if (n < 0)
- return (-1);
- if (n == 0) {
- stream->eof = 1;
- return (0);
- }
- buf_more(buf, n);
- return (n);
-}
-
-/*
- * Refill the read buffer. This function is not permitted to return
- * without having made more bytes available, unless there was an error.
- * Moreover, stream_fill() returns the number of bytes added.
- */
-static ssize_t
-stream_fill(struct stream *stream)
-{
- struct stream_filter *filter;
- struct buf *buf;
-#ifndef NDEBUG
- size_t oldcount;
-#endif
- ssize_t n;
-
- filter = stream->filter;
- buf = stream->rdbuf;
- buf_prewrite(buf);
-#ifndef NDEBUG
- oldcount = buf_count(buf);
-#endif
- n = (*filter->fillfn)(stream, buf);
- assert((n > 0 && n == (signed)(buf_count(buf) - oldcount)) ||
- (n <= 0 && buf_count(buf) == oldcount));
- return (n);
-}
-
-/*
- * Lookup a stream filter.
- *
- * We are not supposed to get passed an invalid filter id, since
- * filter ids are an enum type and we don't have invalid filter
- * ids in the enum :-). Thus, we are not checking for out of
- * bounds access here. If it happens, it's the caller's fault
- * anyway.
- */
-static struct stream_filter *
-stream_filter_lookup(stream_filter_t id)
-{
- struct stream_filter *filter;
-
- filter = stream_filters;
- while (filter->id != id)
- filter++;
- return (filter);
-}
-
-static int
-stream_filter_init(struct stream *stream, void *data)
-{
- struct stream_filter *filter;
- int error;
-
- filter = stream->filter;
- if (filter->initfn == NULL)
- return (0);
- error = (*filter->initfn)(stream, data);
- return (error);
-}
-
-static void
-stream_filter_fini(struct stream *stream)
-{
- struct stream_filter *filter;
-
- filter = stream->filter;
- if (filter->finifn != NULL)
- (*filter->finifn)(stream);
-}
-
-/*
- * Start a filter on a stream.
- */
-int
-stream_filter_start(struct stream *stream, stream_filter_t id, void *data)
-{
- struct stream_filter *filter;
- int error;
-
- filter = stream->filter;
- if (id == filter->id)
- return (0);
- stream_filter_fini(stream);
- stream->filter = stream_filter_lookup(id);
- stream->fdata = NULL;
- error = stream_filter_init(stream, data);
- return (error);
-}
-
-
-/* Stop a filter, this is equivalent to setting the null filter. */
-void
-stream_filter_stop(struct stream *stream)
-{
-
- stream_filter_start(stream, STREAM_FILTER_NULL, NULL);
-}
-
-/* The zlib stream filter implementation. */
-
-/* Take no chances with zlib... */
-static void *
-zfilter_alloc(void __unused *opaque, unsigned int items, unsigned int size)
-{
-
- return (xmalloc(items * size));
-}
-
-static void
-zfilter_free(void __unused *opaque, void *ptr)
-{
-
- free(ptr);
-}
-
-static int
-zfilter_init(struct stream *stream, void __unused *data)
-{
- struct zfilter *zf;
- struct buf *buf;
- z_stream *state;
- int rv;
-
- zf = xmalloc(sizeof(struct zfilter));
- memset(zf, 0, sizeof(struct zfilter));
- if (stream->rdbuf != NULL) {
- state = xmalloc(sizeof(z_stream));
- state->zalloc = zfilter_alloc;
- state->zfree = zfilter_free;
- state->opaque = Z_NULL;
- rv = inflateInit(state);
- if (rv != Z_OK)
- errx(1, "inflateInit: %s", state->msg);
- buf = buf_new(buf_size(stream->rdbuf));
- zf->rdbuf = stream->rdbuf;
- stream->rdbuf = buf;
- zf->rdstate = state;
- }
- if (stream->wrbuf != NULL) {
- state = xmalloc(sizeof(z_stream));
- state->zalloc = zfilter_alloc;
- state->zfree = zfilter_free;
- state->opaque = Z_NULL;
- rv = deflateInit(state, Z_DEFAULT_COMPRESSION);
- if (rv != Z_OK)
- errx(1, "deflateInit: %s", state->msg);
- buf = buf_new(buf_size(stream->wrbuf));
- zf->wrbuf = stream->wrbuf;
- stream->wrbuf = buf;
- zf->wrstate = state;
- }
- stream->fdata = zf;
- return (0);
-}
-
-static void
-zfilter_fini(struct stream *stream)
-{
- struct zfilter *zf;
- struct buf *zbuf;
- z_stream *state;
- ssize_t n;
-
- zf = stream->fdata;
- if (zf->rdbuf != NULL) {
- state = zf->rdstate;
- zbuf = zf->rdbuf;
- /*
- * Even if it has produced all the bytes, zlib sometimes
- * hasn't seen the EOF marker, so we need to call inflate()
- * again to make sure we have eaten all the zlib'ed bytes.
- */
- if ((zf->flags & ZFILTER_EOF) == 0) {
- n = zfilter_fill(stream, stream->rdbuf);
- assert(n == 0 && zf->flags & ZFILTER_EOF);
- }
- inflateEnd(state);
- free(state);
- buf_free(stream->rdbuf);
- stream->rdbuf = zbuf;
- }
- if (zf->wrbuf != NULL) {
- state = zf->wrstate;
- zbuf = zf->wrbuf;
- /*
- * Compress the remaining bytes in the buffer, if any,
- * and emit an EOF marker as appropriate. We ignore
- * the error because we can't do anything about it at
- * this point, and it can happen if we're getting
- * disconnected.
- */
- (void)zfilter_flush(stream, stream->wrbuf,
- STREAM_FLUSH_CLOSING);
- deflateEnd(state);
- free(state);
- buf_free(stream->wrbuf);
- stream->wrbuf = zbuf;
- }
- free(zf);
-}
-
-static int
-zfilter_flush(struct stream *stream, struct buf *buf, stream_flush_t how)
-{
- struct zfilter *zf;
- struct buf *zbuf;
- z_stream *state;
- size_t lastin, lastout, ate, prod;
- int done, error, flags, rv;
-
- zf = stream->fdata;
- state = zf->wrstate;
- zbuf = zf->wrbuf;
-
- if (how == STREAM_FLUSH_NORMAL)
- flags = Z_SYNC_FLUSH;
- else
- flags = Z_FINISH;
-
- done = 0;
- rv = Z_OK;
-
-again:
- /*
- * According to zlib.h, we should have at least 6 bytes
- * available when using deflate() with Z_SYNC_FLUSH.
- */
- if ((buf_avail(zbuf) < 6 && flags == Z_SYNC_FLUSH) ||
- rv == Z_BUF_ERROR || buf_avail(buf) == 0) {
- error = stream_flush_default(stream, zbuf, how);
- if (error)
- return (error);
- }
-
- state->next_in = (Bytef *)(buf->buf + buf->off);
- state->avail_in = buf_count(buf);
- state->next_out = (Bytef *)(zbuf->buf + zbuf->off + zbuf->in);
- state->avail_out = buf_avail(zbuf);
- lastin = state->avail_in;
- lastout = state->avail_out;
- rv = deflate(state, flags);
- if (rv != Z_BUF_ERROR && rv != Z_OK && rv != Z_STREAM_END)
- errx(1, "deflate: %s", state->msg);
- ate = lastin - state->avail_in;
- prod = lastout - state->avail_out;
- buf_less(buf, ate);
- buf_more(zbuf, prod);
- if ((flags == Z_SYNC_FLUSH && buf_count(buf) > 0) ||
- (flags == Z_FINISH && rv != Z_STREAM_END) ||
- (rv == Z_BUF_ERROR))
- goto again;
-
- assert(rv == Z_OK || (rv == Z_STREAM_END && flags == Z_FINISH));
- error = stream_flush_default(stream, zbuf, how);
- return (error);
-}
-
-static ssize_t
-zfilter_fill(struct stream *stream, struct buf *buf)
-{
- struct zfilter *zf;
- struct buf *zbuf;
- z_stream *state;
- size_t lastin, lastout, new;
- ssize_t n;
- int rv;
-
- zf = stream->fdata;
- state = zf->rdstate;
- zbuf = zf->rdbuf;
-
- assert(buf_avail(buf) > 0);
- if (buf_count(zbuf) == 0) {
- n = stream_fill_default(stream, zbuf);
- if (n <= 0)
- return (n);
- }
-again:
- assert(buf_count(zbuf) > 0);
- state->next_in = (Bytef *)(zbuf->buf + zbuf->off);
- state->avail_in = buf_count(zbuf);
- state->next_out = (Bytef *)(buf->buf + buf->off + buf->in);
- state->avail_out = buf_avail(buf);
- lastin = state->avail_in;
- lastout = state->avail_out;
- rv = inflate(state, Z_SYNC_FLUSH);
- buf_less(zbuf, lastin - state->avail_in);
- new = lastout - state->avail_out;
- if (new == 0 && rv != Z_STREAM_END) {
- n = stream_fill_default(stream, zbuf);
- if (n == -1)
- return (-1);
- if (n == 0)
- return (0);
- goto again;
- }
- if (rv != Z_STREAM_END && rv != Z_OK)
- errx(1, "inflate: %s", state->msg);
- if (rv == Z_STREAM_END)
- zf->flags |= ZFILTER_EOF;
- buf_more(buf, new);
- return (new);
-}
-
-/* The MD5 stream filter implementation. */
-static int
-md5filter_init(struct stream *stream, void *data)
-{
- struct md5filter *mf;
-
- mf = xmalloc(sizeof(struct md5filter));
- MD5_Init(&mf->ctx);
- mf->md5 = data;
- stream->fdata = mf;
- return (0);
-}
-
-static void
-md5filter_fini(struct stream *stream)
-{
- struct md5filter *mf;
-
- mf = stream->fdata;
- MD5_End(mf->md5, &mf->ctx);
- free(stream->fdata);
-}
-
-static ssize_t
-md5filter_fill(struct stream *stream, struct buf *buf)
-{
- ssize_t n;
-
- assert(buf_avail(buf) > 0);
- n = stream_fill_default(stream, buf);
- return (n);
-}
-
-static int
-md5filter_flush(struct stream *stream, struct buf *buf, stream_flush_t how)
-{
- struct md5filter *mf;
- int error;
-
- mf = stream->fdata;
- MD5_Update(&mf->ctx, buf->buf + buf->off, buf->in);
- error = stream_flush_default(stream, buf, how);
- return (error);
-}
--- contrib/csup/mux.c
+++ /dev/null
@@ -1,1201 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/mux.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <netinet/in.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "misc.h"
-#include "mux.h"
-
-/*
- * Packet types.
- */
-#define MUX_STARTUPREQ 0
-#define MUX_STARTUPREP 1
-#define MUX_CONNECT 2
-#define MUX_ACCEPT 3
-#define MUX_RESET 4
-#define MUX_DATA 5
-#define MUX_WINDOW 6
-#define MUX_CLOSE 7
-
-/*
- * Header sizes.
- */
-#define MUX_STARTUPHDRSZ 3
-#define MUX_CONNECTHDRSZ 8
-#define MUX_ACCEPTHDRSZ 8
-#define MUX_RESETHDRSZ 2
-#define MUX_DATAHDRSZ 4
-#define MUX_WINDOWHDRSZ 6
-#define MUX_CLOSEHDRSZ 2
-
-#define MUX_PROTOVER 0 /* Protocol version. */
-
-struct mux_header {
- uint8_t type;
- union {
- struct {
- uint16_t version;
- } __packed mh_startup;
- struct {
- uint8_t id;
- uint16_t mss;
- uint32_t window;
- } __packed mh_connect;
- struct {
- uint8_t id;
- uint16_t mss;
- uint32_t window;
- } __packed mh_accept;
- struct {
- uint8_t id;
- } __packed mh_reset;
- struct {
- uint8_t id;
- uint16_t len;
- } __packed mh_data;
- struct {
- uint8_t id;
- uint32_t window;
- } __packed mh_window;
- struct {
- uint8_t id;
- } __packed mh_close;
- } mh_u;
-} __packed;
-
-#define mh_startup mh_u.mh_startup
-#define mh_connect mh_u.mh_connect
-#define mh_accept mh_u.mh_accept
-#define mh_reset mh_u.mh_reset
-#define mh_data mh_u.mh_data
-#define mh_window mh_u.mh_window
-#define mh_close mh_u.mh_close
-
-#define MUX_MAXCHAN 2
-
-/* Channel states. */
-#define CS_UNUSED 0
-#define CS_LISTENING 1
-#define CS_CONNECTING 2
-#define CS_ESTABLISHED 3
-#define CS_RDCLOSED 4
-#define CS_WRCLOSED 5
-#define CS_CLOSED 6
-
-/* Channel flags. */
-#define CF_CONNECT 0x01
-#define CF_ACCEPT 0x02
-#define CF_RESET 0x04
-#define CF_WINDOW 0x08
-#define CF_DATA 0x10
-#define CF_CLOSE 0x20
-
-#define CHAN_SBSIZE (16 * 1024) /* Send buffer size. */
-#define CHAN_RBSIZE (16 * 1024) /* Receive buffer size. */
-#define CHAN_MAXSEGSIZE 1024 /* Maximum segment size. */
-
-/* Circular buffer. */
-struct buf {
- uint8_t *data;
- size_t size;
- size_t in;
- size_t out;
-};
-
-struct chan {
- int flags;
- int state;
- pthread_mutex_t lock;
- struct mux *mux;
-
- /* Receiver state variables. */
- struct buf *recvbuf;
- pthread_cond_t rdready;
- uint32_t recvseq;
- uint16_t recvmss;
-
- /* Sender state variables. */
- struct buf *sendbuf;
- pthread_cond_t wrready;
- uint32_t sendseq;
- uint32_t sendwin;
- uint16_t sendmss;
-};
-
-struct mux {
- int closed;
- int status;
- int socket;
- pthread_mutex_t lock;
- pthread_cond_t done;
- struct chan *channels[MUX_MAXCHAN];
- int nchans;
-
- /* Sender thread data. */
- pthread_t sender;
- pthread_cond_t sender_newwork;
- pthread_cond_t sender_started;
- int sender_waiting;
- int sender_ready;
- int sender_lastid;
-
- /* Receiver thread data. */
- pthread_t receiver;
-};
-
-static int sock_writev(int, struct iovec *, int);
-static int sock_write(int, void *, size_t);
-static ssize_t sock_read(int, void *, size_t);
-static int sock_readwait(int, void *, size_t);
-
-static int mux_init(struct mux *);
-static void mux_lock(struct mux *);
-static void mux_unlock(struct mux *);
-
-static struct chan *chan_new(struct mux *);
-static struct chan *chan_get(struct mux *, int);
-static struct chan *chan_connect(struct mux *, int);
-static void chan_lock(struct chan *);
-static void chan_unlock(struct chan *);
-static int chan_insert(struct mux *, struct chan *);
-static void chan_free(struct chan *);
-
-static struct buf *buf_new(size_t);
-static size_t buf_count(struct buf *);
-static size_t buf_avail(struct buf *);
-static void buf_get(struct buf *, void *, size_t);
-static void buf_put(struct buf *, const void *, size_t);
-static void buf_free(struct buf *);
-
-static void sender_wakeup(struct mux *);
-static void *sender_loop(void *);
-static int sender_waitforwork(struct mux *, int *);
-static int sender_scan(struct mux *, int *);
-static void sender_cleanup(void *);
-
-static void *receiver_loop(void *);
-
-static int
-sock_writev(int s, struct iovec *iov, int iovcnt)
-{
- ssize_t nbytes;
-
-again:
- nbytes = writev(s, iov, iovcnt);
- if (nbytes != -1) {
- while (nbytes > 0 && (size_t)nbytes >= iov->iov_len) {
- nbytes -= iov->iov_len;
- iov++;
- iovcnt--;
- }
- if (nbytes == 0)
- return (0);
- iov->iov_len -= nbytes;
- iov->iov_base = (char *)iov->iov_base + nbytes;
- } else if (errno != EINTR) {
- return (-1);
- }
- goto again;
-}
-
-static int
-sock_write(int s, void *buf, size_t size)
-{
- struct iovec iov;
- int ret;
-
- iov.iov_base = buf;
- iov.iov_len = size;
- ret = sock_writev(s, &iov, 1);
- return (ret);
-}
-
-static ssize_t
-sock_read(int s, void *buf, size_t size)
-{
- ssize_t nbytes;
-
-again:
- nbytes = read(s, buf, size);
- if (nbytes == -1 && errno == EINTR)
- goto again;
- return (nbytes);
-}
-
-static int
-sock_readwait(int s, void *buf, size_t size)
-{
- char *cp;
- ssize_t nbytes;
- size_t left;
-
- cp = buf;
- left = size;
- while (left > 0) {
- nbytes = sock_read(s, cp, left);
- if (nbytes == 0) {
- errno = ECONNRESET;
- return (-1);
- }
- if (nbytes < 0)
- return (-1);
- left -= nbytes;
- cp += nbytes;
- }
- return (0);
-}
-
-static void
-mux_lock(struct mux *m)
-{
- int error;
-
- error = pthread_mutex_lock(&m->lock);
- assert(!error);
-}
-
-static void
-mux_unlock(struct mux *m)
-{
- int error;
-
- error = pthread_mutex_unlock(&m->lock);
- assert(!error);
-}
-
-/* Create a TCP multiplexer on the given socket. */
-struct mux *
-mux_open(int sock, struct chan **chan)
-{
- struct mux *m;
- struct chan *chan0;
- int error;
-
- m = xmalloc(sizeof(struct mux));
- memset(m->channels, 0, sizeof(m->channels));
- m->nchans = 0;
- m->closed = 0;
- m->status = -1;
- m->socket = sock;
-
- m->sender_waiting = 0;
- m->sender_lastid = 0;
- m->sender_ready = 0;
- pthread_mutex_init(&m->lock, NULL);
- pthread_cond_init(&m->done, NULL);
- pthread_cond_init(&m->sender_newwork, NULL);
- pthread_cond_init(&m->sender_started, NULL);
-
- error = mux_init(m);
- if (error)
- goto bad;
- chan0 = chan_connect(m, 0);
- if (chan0 == NULL)
- goto bad;
- *chan = chan0;
- return (m);
-bad:
- mux_shutdown(m, NULL, STATUS_FAILURE);
- (void)mux_close(m);
- return (NULL);
-}
-
-int
-mux_close(struct mux *m)
-{
- struct chan *chan;
- int i, status;
-
- assert(m->closed);
- for (i = 0; i < m->nchans; i++) {
- chan = m->channels[i];
- if (chan != NULL)
- chan_free(chan);
- }
- pthread_cond_destroy(&m->sender_started);
- pthread_cond_destroy(&m->sender_newwork);
- pthread_cond_destroy(&m->done);
- pthread_mutex_destroy(&m->lock);
- status = m->status;
- free(m);
- return (status);
-}
-
-/* Close a channel. */
-int
-chan_close(struct chan *chan)
-{
-
- chan_lock(chan);
- if (chan->state == CS_ESTABLISHED) {
- chan->state = CS_WRCLOSED;
- chan->flags |= CF_CLOSE;
- } else if (chan->state == CS_RDCLOSED) {
- chan->state = CS_CLOSED;
- chan->flags |= CF_CLOSE;
- } else if (chan->state == CS_WRCLOSED || chan->state == CS_CLOSED) {
- chan_unlock(chan);
- return (0);
- } else {
- chan_unlock(chan);
- return (-1);
- }
- chan_unlock(chan);
- sender_wakeup(chan->mux);
- return (0);
-}
-
-void
-chan_wait(struct chan *chan)
-{
-
- chan_lock(chan);
- while (chan->state != CS_CLOSED)
- pthread_cond_wait(&chan->rdready, &chan->lock);
- chan_unlock(chan);
-}
-
-/* Returns the ID of an available channel in the listening state. */
-int
-chan_listen(struct mux *m)
-{
- struct chan *chan;
- int i;
-
- mux_lock(m);
- for (i = 0; i < m->nchans; i++) {
- chan = m->channels[i];
- chan_lock(chan);
- if (chan->state == CS_UNUSED) {
- mux_unlock(m);
- chan->state = CS_LISTENING;
- chan_unlock(chan);
- return (i);
- }
- chan_unlock(chan);
- }
- mux_unlock(m);
- chan = chan_new(m);
- chan->state = CS_LISTENING;
- i = chan_insert(m, chan);
- if (i == -1)
- chan_free(chan);
- return (i);
-}
-
-struct chan *
-chan_accept(struct mux *m, int id)
-{
- struct chan *chan;
-
- chan = chan_get(m, id);
- while (chan->state == CS_LISTENING)
- pthread_cond_wait(&chan->rdready, &chan->lock);
- if (chan->state != CS_ESTABLISHED) {
- errno = ECONNRESET;
- chan_unlock(chan);
- return (NULL);
- }
- chan_unlock(chan);
- return (chan);
-}
-
-/* Read bytes from a channel. */
-ssize_t
-chan_read(struct chan *chan, void *buf, size_t size)
-{
- char *cp;
- size_t count, n;
-
- cp = buf;
- chan_lock(chan);
- for (;;) {
- if (chan->state == CS_RDCLOSED || chan->state == CS_CLOSED) {
- chan_unlock(chan);
- return (0);
- }
- if (chan->state != CS_ESTABLISHED &&
- chan->state != CS_WRCLOSED) {
- chan_unlock(chan);
- errno = EBADF;
- return (-1);
- }
- count = buf_count(chan->recvbuf);
- if (count > 0)
- break;
- pthread_cond_wait(&chan->rdready, &chan->lock);
- }
- n = min(count, size);
- buf_get(chan->recvbuf, cp, n);
- chan->recvseq += n;
- chan->flags |= CF_WINDOW;
- chan_unlock(chan);
- /* We need to wake up the sender so that it sends a window update. */
- sender_wakeup(chan->mux);
- return (n);
-}
-
-/* Write bytes to a channel. */
-ssize_t
-chan_write(struct chan *chan, const void *buf, size_t size)
-{
- const char *cp;
- size_t avail, n, pos;
-
- pos = 0;
- cp = buf;
- chan_lock(chan);
- while (pos < size) {
- for (;;) {
- if (chan->state != CS_ESTABLISHED &&
- chan->state != CS_RDCLOSED) {
- chan_unlock(chan);
- errno = EPIPE;
- return (-1);
- }
- avail = buf_avail(chan->sendbuf);
- if (avail > 0)
- break;
- pthread_cond_wait(&chan->wrready, &chan->lock);
- }
- n = min(avail, size - pos);
- buf_put(chan->sendbuf, cp + pos, n);
- pos += n;
- }
- chan_unlock(chan);
- sender_wakeup(chan->mux);
- return (size);
-}
-
-/*
- * Internal channel API.
- */
-
-static struct chan *
-chan_connect(struct mux *m, int id)
-{
- struct chan *chan;
-
- chan = chan_get(m, id);
- if (chan->state != CS_UNUSED) {
- chan_unlock(chan);
- return (NULL);
- }
- chan->state = CS_CONNECTING;
- chan->flags |= CF_CONNECT;
- chan_unlock(chan);
- sender_wakeup(m);
- chan_lock(chan);
- while (chan->state == CS_CONNECTING)
- pthread_cond_wait(&chan->wrready, &chan->lock);
- if (chan->state != CS_ESTABLISHED) {
- chan_unlock(chan);
- return (NULL);
- }
- chan_unlock(chan);
- return (chan);
-}
-
-/*
- * Get a channel from its ID, creating it if necessary.
- * The channel is returned locked.
- */
-static struct chan *
-chan_get(struct mux *m, int id)
-{
- struct chan *chan;
-
- assert(id < MUX_MAXCHAN);
- mux_lock(m);
- chan = m->channels[id];
- if (chan == NULL) {
- chan = chan_new(m);
- m->channels[id] = chan;
- m->nchans++;
- }
- chan_lock(chan);
- mux_unlock(m);
- return (chan);
-}
-
-/* Lock a channel. */
-static void
-chan_lock(struct chan *chan)
-{
- int error;
-
- error = pthread_mutex_lock(&chan->lock);
- assert(!error);
-}
-
-/* Unlock a channel. */
-static void
-chan_unlock(struct chan *chan)
-{
- int error;
-
- error = pthread_mutex_unlock(&chan->lock);
- assert(!error);
-}
-
-/*
- * Create a new channel.
- */
-static struct chan *
-chan_new(struct mux *m)
-{
- struct chan *chan;
-
- chan = xmalloc(sizeof(struct chan));
- chan->state = CS_UNUSED;
- chan->flags = 0;
- chan->mux = m;
- chan->sendbuf = buf_new(CHAN_SBSIZE);
- chan->sendseq = 0;
- chan->sendwin = 0;
- chan->sendmss = 0;
- chan->recvbuf = buf_new(CHAN_RBSIZE);
- chan->recvseq = 0;
- chan->recvmss = CHAN_MAXSEGSIZE;
- pthread_mutex_init(&chan->lock, NULL);
- pthread_cond_init(&chan->rdready, NULL);
- pthread_cond_init(&chan->wrready, NULL);
- return (chan);
-}
-
-/* Free any resources associated with a channel. */
-static void
-chan_free(struct chan *chan)
-{
-
- pthread_cond_destroy(&chan->rdready);
- pthread_cond_destroy(&chan->wrready);
- pthread_mutex_destroy(&chan->lock);
- buf_free(chan->recvbuf);
- buf_free(chan->sendbuf);
- free(chan);
-}
-
-/* Insert the new channel in the channel list. */
-static int
-chan_insert(struct mux *m, struct chan *chan)
-{
- int i;
-
- mux_lock(m);
- for (i = 0; i < MUX_MAXCHAN; i++) {
- if (m->channels[i] == NULL) {
- m->channels[i] = chan;
- m->nchans++;
- mux_unlock(m);
- return (i);
- }
- }
- errno = ENOBUFS;
- return (-1);
-}
-
-/*
- * Initialize the multiplexer protocol.
- *
- * This means negotiating protocol version and starting
- * the receiver and sender threads.
- */
-static int
-mux_init(struct mux *m)
-{
- struct mux_header mh;
- int error;
-
- mh.type = MUX_STARTUPREQ;
- mh.mh_startup.version = htons(MUX_PROTOVER);
- error = sock_write(m->socket, &mh, MUX_STARTUPHDRSZ);
- if (error)
- return (-1);
- error = sock_readwait(m->socket, &mh, MUX_STARTUPHDRSZ);
- if (error)
- return (-1);
- if (mh.type != MUX_STARTUPREP ||
- ntohs(mh.mh_startup.version) != MUX_PROTOVER)
- return (-1);
- mux_lock(m);
- error = pthread_create(&m->sender, NULL, sender_loop, m);
- if (error) {
- mux_unlock(m);
- return (-1);
- }
- /*
- * Make sure the sender thread has run and is waiting for new work
- * before going on. Otherwise, it might lose the race and a
- * request, which will cause a deadlock.
- */
- while (!m->sender_ready)
- pthread_cond_wait(&m->sender_started, &m->lock);
-
- mux_unlock(m);
- error = pthread_create(&m->receiver, NULL, receiver_loop, m);
- if (error)
- return (-1);
- return (0);
-}
-
-/*
- * Close all the channels, terminate the sender and receiver thread.
- * This is an important function because it is used everytime we need
- * to wake up all the worker threads to abort the program.
- *
- * This function accepts an error message that will be printed if the
- * multiplexer wasn't already closed. This is useful because it ensures
- * that only the first error message will be printed, and that it will
- * be printed before doing the actual shutdown work. If this is a
- * normal shutdown, NULL can be passed instead.
- *
- * The "status" parameter of the first mux_shutdown() call is retained
- * and then returned by mux_close(), so that the main thread can know
- * what type of error happened in the end, if any.
- */
-void
-mux_shutdown(struct mux *m, const char *errmsg, int status)
-{
- pthread_t self, sender, receiver;
- struct chan *chan;
- const char *name;
- void *val;
- int i, ret;
-
- mux_lock(m);
- if (m->closed) {
- mux_unlock(m);
- return;
- }
- m->closed = 1;
- m->status = status;
- self = pthread_self();
- sender = m->sender;
- receiver = m->receiver;
- if (errmsg != NULL) {
- if (pthread_equal(self, receiver))
- name = "Receiver";
- else if (pthread_equal(self, sender))
- name = "Sender";
- else
- name = NULL;
- if (name == NULL)
- lprintf(-1, "%s\n", errmsg);
- else
- lprintf(-1, "%s: %s\n", name, errmsg);
- }
-
- for (i = 0; i < MUX_MAXCHAN; i++) {
- if (m->channels[i] != NULL) {
- chan = m->channels[i];
- chan_lock(chan);
- if (chan->state != CS_UNUSED) {
- chan->state = CS_CLOSED;
- chan->flags = 0;
- pthread_cond_broadcast(&chan->rdready);
- pthread_cond_broadcast(&chan->wrready);
- }
- chan_unlock(chan);
- }
- }
- mux_unlock(m);
-
- if (!pthread_equal(self, receiver)) {
- ret = pthread_cancel(receiver);
- assert(!ret);
- pthread_join(receiver, &val);
- assert(val == PTHREAD_CANCELED);
- }
- if (!pthread_equal(self, sender)) {
- ret = pthread_cancel(sender);
- assert(!ret);
- pthread_join(sender, &val);
- assert(val == PTHREAD_CANCELED);
- }
-}
-
-static void
-sender_wakeup(struct mux *m)
-{
- int waiting;
-
- mux_lock(m);
- waiting = m->sender_waiting;
- mux_unlock(m);
- /*
- * We don't care about the race here: if the sender was
- * waiting and is not anymore, we'll just send a useless
- * signal; if he wasn't waiting then he won't go to sleep
- * before having sent what we want him to.
- */
- if (waiting)
- pthread_cond_signal(&m->sender_newwork);
-}
-
-static void *
-sender_loop(void *arg)
-{
- struct iovec iov[3];
- struct mux_header mh;
- struct mux *m;
- struct chan *chan;
- struct buf *buf;
- uint32_t winsize;
- uint16_t hdrsize, size, len;
- int error, id, iovcnt, what=0;
-
- m = (struct mux *)arg;
-again:
- id = sender_waitforwork(m, &what);
- chan = chan_get(m, id);
- hdrsize = size = 0;
- switch (what) {
- case CF_CONNECT:
- mh.type = MUX_CONNECT;
- mh.mh_connect.id = id;
- mh.mh_connect.mss = htons(chan->recvmss);
- mh.mh_connect.window = htonl(chan->recvseq +
- chan->recvbuf->size);
- hdrsize = MUX_CONNECTHDRSZ;
- break;
- case CF_ACCEPT:
- mh.type = MUX_ACCEPT;
- mh.mh_accept.id = id;
- mh.mh_accept.mss = htons(chan->recvmss);
- mh.mh_accept.window = htonl(chan->recvseq +
- chan->recvbuf->size);
- hdrsize = MUX_ACCEPTHDRSZ;
- break;
- case CF_RESET:
- mh.type = MUX_RESET;
- mh.mh_reset.id = id;
- hdrsize = MUX_RESETHDRSZ;
- break;
- case CF_WINDOW:
- mh.type = MUX_WINDOW;
- mh.mh_window.id = id;
- mh.mh_window.window = htonl(chan->recvseq +
- chan->recvbuf->size);
- hdrsize = MUX_WINDOWHDRSZ;
- break;
- case CF_DATA:
- mh.type = MUX_DATA;
- mh.mh_data.id = id;
- size = min(buf_count(chan->sendbuf), chan->sendmss);
- winsize = chan->sendwin - chan->sendseq;
- if (winsize < size)
- size = winsize;
- mh.mh_data.len = htons(size);
- hdrsize = MUX_DATAHDRSZ;
- break;
- case CF_CLOSE:
- mh.type = MUX_CLOSE;
- mh.mh_close.id = id;
- hdrsize = MUX_CLOSEHDRSZ;
- break;
- }
- if (size > 0) {
- assert(mh.type == MUX_DATA);
- /*
- * Older FreeBSD versions (and maybe other OSes) have the
- * iov_base field defined as char *. Cast to char * to
- * silence a warning in this case.
- */
- iov[0].iov_base = (char *)&mh;
- iov[0].iov_len = hdrsize;
- iovcnt = 1;
- /* We access the buffer directly to avoid some copying. */
- buf = chan->sendbuf;
- len = min(size, buf->size + 1 - buf->out);
- iov[iovcnt].iov_base = buf->data + buf->out;
- iov[iovcnt].iov_len = len;
- iovcnt++;
- if (size > len) {
- /* Wrapping around. */
- iov[iovcnt].iov_base = buf->data;
- iov[iovcnt].iov_len = size - len;
- iovcnt++;
- }
- /*
- * Since we're the only thread sending bytes from the
- * buffer and modifying buf->out, it's safe to unlock
- * here during I/O. It avoids keeping the channel lock
- * too long, since write() might block.
- */
- chan_unlock(chan);
- error = sock_writev(m->socket, iov, iovcnt);
- if (error)
- goto bad;
- chan_lock(chan);
- chan->sendseq += size;
- buf->out += size;
- if (buf->out > buf->size)
- buf->out -= buf->size + 1;
- pthread_cond_signal(&chan->wrready);
- chan_unlock(chan);
- } else {
- chan_unlock(chan);
- error = sock_write(m->socket, &mh, hdrsize);
- if (error)
- goto bad;
- }
- goto again;
-bad:
- if (error == EPIPE)
- mux_shutdown(m, strerror(errno), STATUS_TRANSIENTFAILURE);
- else
- mux_shutdown(m, strerror(errno), STATUS_FAILURE);
- return (NULL);
-}
-
-static void
-sender_cleanup(void *arg)
-{
- struct mux *m;
-
- m = (struct mux *)arg;
- mux_unlock(m);
-}
-
-static int
-sender_waitforwork(struct mux *m, int *what)
-{
- int id;
-
- mux_lock(m);
- pthread_cleanup_push(sender_cleanup, m);
- if (!m->sender_ready) {
- pthread_cond_signal(&m->sender_started);
- m->sender_ready = 1;
- }
- while ((id = sender_scan(m, what)) == -1) {
- m->sender_waiting = 1;
- pthread_cond_wait(&m->sender_newwork, &m->lock);
- }
- m->sender_waiting = 0;
- pthread_cleanup_pop(1);
- return (id);
-}
-
-/*
- * Scan for work to do for the sender. Has to be called with
- * the multiplexer lock held.
- */
-static int
-sender_scan(struct mux *m, int *what)
-{
- struct chan *chan;
- int id;
-
- if (m->nchans <= 0)
- return (-1);
- id = m->sender_lastid;
- do {
- id++;
- if (id >= m->nchans)
- id = 0;
- chan = m->channels[id];
- chan_lock(chan);
- if (chan->state != CS_UNUSED) {
- if (chan->sendseq != chan->sendwin &&
- buf_count(chan->sendbuf) > 0)
- chan->flags |= CF_DATA;
- if (chan->flags) {
- /* By order of importance. */
- if (chan->flags & CF_CONNECT)
- *what = CF_CONNECT;
- else if (chan->flags & CF_ACCEPT)
- *what = CF_ACCEPT;
- else if (chan->flags & CF_RESET)
- *what = CF_RESET;
- else if (chan->flags & CF_WINDOW)
- *what = CF_WINDOW;
- else if (chan->flags & CF_DATA)
- *what = CF_DATA;
- else if (chan->flags & CF_CLOSE)
- *what = CF_CLOSE;
- chan->flags &= ~*what;
- chan_unlock(chan);
- m->sender_lastid = id;
- return (id);
- }
- }
- chan_unlock(chan);
- } while (id != m->sender_lastid);
- return (-1);
-}
-
-/* Read the rest of a packet header depending on its type. */
-#define SOCK_READREST(s, mh, hsize) \
- sock_readwait(s, (char *)&mh + sizeof(mh.type), (hsize) - sizeof(mh.type))
-
-void *
-receiver_loop(void *arg)
-{
- struct mux_header mh;
- struct mux *m;
- struct chan *chan;
- struct buf *buf;
- uint16_t size, len;
- int error;
-
- m = (struct mux *)arg;
- while ((error = sock_readwait(m->socket, &mh.type,
- sizeof(mh.type))) == 0) {
- switch (mh.type) {
- case MUX_CONNECT:
- error = SOCK_READREST(m->socket, mh, MUX_CONNECTHDRSZ);
- if (error)
- goto bad;
- chan = chan_get(m, mh.mh_connect.id);
- if (chan->state == CS_LISTENING) {
- chan->state = CS_ESTABLISHED;
- chan->sendmss = ntohs(mh.mh_connect.mss);
- chan->sendwin = ntohl(mh.mh_connect.window);
- chan->flags |= CF_ACCEPT;
- pthread_cond_signal(&chan->rdready);
- } else
- chan->flags |= CF_RESET;
- chan_unlock(chan);
- sender_wakeup(m);
- break;
- case MUX_ACCEPT:
- error = SOCK_READREST(m->socket, mh, MUX_ACCEPTHDRSZ);
- if (error)
- goto bad;
- chan = chan_get(m, mh.mh_accept.id);
- if (chan->state == CS_CONNECTING) {
- chan->sendmss = ntohs(mh.mh_accept.mss);
- chan->sendwin = ntohl(mh.mh_accept.window);
- chan->state = CS_ESTABLISHED;
- pthread_cond_signal(&chan->wrready);
- chan_unlock(chan);
- } else {
- chan->flags |= CF_RESET;
- chan_unlock(chan);
- sender_wakeup(m);
- }
- break;
- case MUX_RESET:
- error = SOCK_READREST(m->socket, mh, MUX_RESETHDRSZ);
- if (error)
- goto bad;
- goto badproto;
- case MUX_WINDOW:
- error = SOCK_READREST(m->socket, mh, MUX_WINDOWHDRSZ);
- if (error)
- goto bad;
- chan = chan_get(m, mh.mh_window.id);
- if (chan->state == CS_ESTABLISHED ||
- chan->state == CS_RDCLOSED) {
- chan->sendwin = ntohl(mh.mh_window.window);
- chan_unlock(chan);
- sender_wakeup(m);
- } else {
- chan_unlock(chan);
- }
- break;
- case MUX_DATA:
- error = SOCK_READREST(m->socket, mh, MUX_DATAHDRSZ);
- if (error)
- goto bad;
- chan = chan_get(m, mh.mh_data.id);
- len = ntohs(mh.mh_data.len);
- buf = chan->recvbuf;
- if ((chan->state != CS_ESTABLISHED &&
- chan->state != CS_WRCLOSED) ||
- (len > buf_avail(buf) ||
- len > chan->recvmss)) {
- chan_unlock(chan);
- goto badproto;
- return (NULL);
- }
- /*
- * Similarly to the sender code, it's safe to
- * unlock the channel here.
- */
- chan_unlock(chan);
- size = min(buf->size + 1 - buf->in, len);
- error = sock_readwait(m->socket,
- buf->data + buf->in, size);
- if (error)
- goto bad;
- if (len > size) {
- /* Wrapping around. */
- error = sock_readwait(m->socket,
- buf->data, len - size);
- if (error)
- goto bad;
- }
- chan_lock(chan);
- buf->in += len;
- if (buf->in > buf->size)
- buf->in -= buf->size + 1;
- pthread_cond_signal(&chan->rdready);
- chan_unlock(chan);
- break;
- case MUX_CLOSE:
- error = SOCK_READREST(m->socket, mh, MUX_CLOSEHDRSZ);
- if (error)
- goto bad;
- chan = chan_get(m, mh.mh_close.id);
- if (chan->state == CS_ESTABLISHED)
- chan->state = CS_RDCLOSED;
- else if (chan->state == CS_WRCLOSED)
- chan->state = CS_CLOSED;
- else
- goto badproto;
- pthread_cond_signal(&chan->rdready);
- chan_unlock(chan);
- break;
- default:
- goto badproto;
- }
- }
-bad:
- if (errno == ECONNRESET || errno == ECONNABORTED)
- mux_shutdown(m, strerror(errno), STATUS_TRANSIENTFAILURE);
- else
- mux_shutdown(m, strerror(errno), STATUS_FAILURE);
- return (NULL);
-badproto:
- mux_shutdown(m, "Protocol error", STATUS_FAILURE);
- return (NULL);
-}
-
-/*
- * Circular buffers API.
- */
-
-static struct buf *
-buf_new(size_t size)
-{
- struct buf *buf;
-
- buf = xmalloc(sizeof(struct buf));
- buf->data = xmalloc(size + 1);
- buf->size = size;
- buf->in = 0;
- buf->out = 0;
- return (buf);
-}
-
-static void
-buf_free(struct buf *buf)
-{
-
- free(buf->data);
- free(buf);
-}
-
-/* Number of bytes stored in the buffer. */
-static size_t
-buf_count(struct buf *buf)
-{
- size_t count;
-
- if (buf->in >= buf->out)
- count = buf->in - buf->out;
- else
- count = buf->size + 1 + buf->in - buf->out;
- return (count);
-}
-
-/* Number of bytes available in the buffer. */
-static size_t
-buf_avail(struct buf *buf)
-{
- size_t avail;
-
- if (buf->out > buf->in)
- avail = buf->out - buf->in - 1;
- else
- avail = buf->size + buf->out - buf->in;
- return (avail);
-}
-
-static void
-buf_put(struct buf *buf, const void *data, size_t size)
-{
- const char *cp;
- size_t len;
-
- assert(size > 0);
- assert(buf_avail(buf) >= size);
- cp = data;
- len = buf->size + 1 - buf->in;
- if (len < size) {
- /* Wrapping around. */
- memcpy(buf->data + buf->in, cp, len);
- memcpy(buf->data, cp + len, size - len);
- } else {
- /* Not wrapping around. */
- memcpy(buf->data + buf->in, cp, size);
- }
- buf->in += size;
- if (buf->in > buf->size)
- buf->in -= buf->size + 1;
-}
-
-static void
-buf_get(struct buf *buf, void *data, size_t size)
-{
- char *cp;
- size_t len;
-
- assert(size > 0);
- assert(buf_count(buf) >= size);
- cp = data;
- len = buf->size + 1 - buf->out;
- if (len < size) {
- /* Wrapping around. */
- memcpy(cp, buf->data + buf->out, len);
- memcpy(cp + len, buf->data, size - len);
- } else {
- /* Not wrapping around. */
- memcpy(cp, buf->data + buf->out, size);
- }
- buf->out += size;
- if (buf->out > buf->size)
- buf->out -= buf->size + 1;
-}
--- contrib/csup/globtree.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/globtree.c,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/types.h>
-
-#include <assert.h>
-#include <regex.h>
-#include <stdlib.h>
-
-#include "fnmatch.h"
-#include "globtree.h"
-#include "misc.h"
-
-/*
- * The "GlobTree" interface allows one to construct arbitrarily complex
- * boolean expressions for evaluating whether to accept or reject a
- * filename. The globtree_test() function returns true or false
- * according to whether the name is accepted or rejected by the
- * expression.
- *
- * Expressions are trees constructed from nodes representing either
- * primitive matching operations (primaries) or operators that are
- * applied to their subexpressions. The simplest primitives are
- * globtree_false(), which matches nothing, and globtree_true(), which
- * matches everything.
- *
- * A more useful primitive is the matching operation, constructed with
- * globtree_match(). It will call fnmatch() with the suppliedi
- * shell-style pattern to determine if the filename matches.
- *
- * Expressions can be combined with the boolean operators AND, OR, and
- * NOT, to form more complex expressions.
- */
-
-/* Node types. */
-#define GLOBTREE_NOT 0
-#define GLOBTREE_AND 1
-#define GLOBTREE_OR 2
-#define GLOBTREE_MATCH 3
-#define GLOBTREE_REGEX 4
-#define GLOBTREE_TRUE 5
-#define GLOBTREE_FALSE 6
-
-/* A node. */
-struct globtree {
- int type;
- struct globtree *left;
- struct globtree *right;
-
- /* The "data" field points to the text pattern for GLOBTREE_MATCH
- nodes, and to the regex_t for GLOBTREE_REGEX nodes. For any
- other node, it is set to NULL. */
- void *data;
- /* The "flags" field contains the flags to pass to fnmatch() for
- GLOBTREE_MATCH nodes. */
- int flags;
-};
-
-static struct globtree *globtree_new(int);
-static int globtree_eval(struct globtree *, const char *);
-
-static struct globtree *
-globtree_new(int type)
-{
- struct globtree *gt;
-
- gt = xmalloc(sizeof(struct globtree));
- gt->type = type;
- gt->data = NULL;
- gt->flags = 0;
- gt->left = NULL;
- gt->right = NULL;
- return (gt);
-}
-
-struct globtree *
-globtree_true(void)
-{
- struct globtree *gt;
-
- gt = globtree_new(GLOBTREE_TRUE);
- return (gt);
-}
-
-struct globtree *
-globtree_false(void)
-{
- struct globtree *gt;
-
- gt = globtree_new(GLOBTREE_FALSE);
- return (gt);
-}
-
-struct globtree *
-globtree_match(const char *pattern, int flags)
-{
- struct globtree *gt;
-
- gt = globtree_new(GLOBTREE_MATCH);
- gt->data = xstrdup(pattern);
- gt->flags = flags;
- return (gt);
-}
-
-struct globtree *
-globtree_regex(const char *pattern)
-{
- struct globtree *gt;
- int error;
-
- gt = globtree_new(GLOBTREE_REGEX);
- gt->data = xmalloc(sizeof(regex_t));
- error = regcomp(gt->data, pattern, REG_NOSUB);
- assert(!error);
- return (gt);
-}
-
-struct globtree *
-globtree_and(struct globtree *left, struct globtree *right)
-{
- struct globtree *gt;
-
- if (left->type == GLOBTREE_FALSE || right->type == GLOBTREE_FALSE) {
- globtree_free(left);
- globtree_free(right);
- gt = globtree_false();
- return (gt);
- }
- if (left->type == GLOBTREE_TRUE) {
- globtree_free(left);
- return (right);
- }
- if (right->type == GLOBTREE_TRUE) {
- globtree_free(right);
- return (left);
- }
- gt = globtree_new(GLOBTREE_AND);
- gt->left = left;
- gt->right = right;
- return (gt);
-}
-
-struct globtree *
-globtree_or(struct globtree *left, struct globtree *right)
-{
- struct globtree *gt;
-
- if (left->type == GLOBTREE_TRUE || right->type == GLOBTREE_TRUE) {
- globtree_free(left);
- globtree_free(right);
- gt = globtree_true();
- return (gt);
- }
- if (left->type == GLOBTREE_FALSE) {
- globtree_free(left);
- return (right);
- }
- if (right->type == GLOBTREE_FALSE) {
- globtree_free(right);
- return (left);
- }
- gt = globtree_new(GLOBTREE_OR);
- gt->left = left;
- gt->right = right;
- return (gt);
-}
-
-struct globtree *
-globtree_not(struct globtree *child)
-{
- struct globtree *gt;
-
- if (child->type == GLOBTREE_TRUE) {
- globtree_free(child);
- gt = globtree_new(GLOBTREE_FALSE);
- return (gt);
- }
- if (child->type == GLOBTREE_FALSE) {
- globtree_free(child);
- gt = globtree_new(GLOBTREE_TRUE);
- return (gt);
- }
- gt = globtree_new(GLOBTREE_NOT);
- gt->left = child;
- return (gt);
-}
-
-/* Evaluate one node (must be a leaf node). */
-static int
-globtree_eval(struct globtree *gt, const char *path)
-{
- int rv;
-
- switch (gt->type) {
- case GLOBTREE_TRUE:
- return (1);
- case GLOBTREE_FALSE:
- return (0);
- case GLOBTREE_MATCH:
- assert(gt->data != NULL);
- rv = fnmatch(gt->data, path, gt->flags);
- if (rv == 0)
- return (1);
- assert(rv == FNM_NOMATCH);
- return (0);
- case GLOBTREE_REGEX:
- assert(gt->data != NULL);
- rv = regexec(gt->data, path, 0, NULL, 0);
- if (rv == 0)
- return (1);
- assert(rv == REG_NOMATCH);
- return (0);
- }
-
- assert(0);
- return (-1);
-}
-
-/* Small stack API to walk the tree iteratively. */
-typedef enum {
- STATE_DOINGLEFT,
- STATE_DOINGRIGHT
-} walkstate_t;
-
-struct stack {
- struct stackelem *stack;
- size_t size;
- size_t in;
-};
-
-struct stackelem {
- struct globtree *node;
- walkstate_t state;
-};
-
-static void
-stack_init(struct stack *stack)
-{
-
- stack->in = 0;
- stack->size = 8; /* Initial size. */
- stack->stack = xmalloc(sizeof(struct stackelem) * stack->size);
-}
-
-static size_t
-stack_size(struct stack *stack)
-{
-
- return (stack->in);
-}
-
-static void
-stack_push(struct stack *stack, struct globtree *node, walkstate_t state)
-{
- struct stackelem *e;
-
- if (stack->in == stack->size) {
- stack->size *= 2;
- stack->stack = xrealloc(stack->stack,
- sizeof(struct stackelem) * stack->size);
- }
- e = stack->stack + stack->in++;
- e->node = node;
- e->state = state;
-}
-
-static void
-stack_pop(struct stack *stack, struct globtree **node, walkstate_t *state)
-{
- struct stackelem *e;
-
- assert(stack->in > 0);
- e = stack->stack + --stack->in;
- *node = e->node;
- *state = e->state;
-}
-
-static void
-stack_free(struct stack *s)
-{
-
- free(s->stack);
-}
-
-/* Tests if the supplied filename matches. */
-int
-globtree_test(struct globtree *gt, const char *path)
-{
- struct stack stack;
- walkstate_t state;
- int val;
-
- stack_init(&stack);
- for (;;) {
-doleft:
- /* Descend to the left until we hit bottom. */
- while (gt->left != NULL) {
- stack_push(&stack, gt, STATE_DOINGLEFT);
- gt = gt->left;
- }
-
- /* Now we're at a leaf node. Evaluate it. */
- val = globtree_eval(gt, path);
- /* Ascend, propagating the value through operator nodes. */
- for (;;) {
- if (stack_size(&stack) == 0) {
- stack_free(&stack);
- return (val);
- }
- stack_pop(&stack, >, &state);
- switch (gt->type) {
- case GLOBTREE_NOT:
- val = !val;
- break;
- case GLOBTREE_AND:
- /* If we haven't yet evaluated the right subtree
- and the partial result is true, descend to
- the right. Otherwise the result is already
- determined to be val. */
- if (state == STATE_DOINGLEFT && val) {
- stack_push(&stack, gt,
- STATE_DOINGRIGHT);
- gt = gt->right;
- goto doleft;
- }
- break;
- case GLOBTREE_OR:
- /* If we haven't yet evaluated the right subtree
- and the partial result is false, descend to
- the right. Otherwise the result is already
- determined to be val. */
- if (state == STATE_DOINGLEFT && !val) {
- stack_push(&stack, gt,
- STATE_DOINGRIGHT);
- gt = gt->right;
- goto doleft;
- }
- break;
- default:
- /* We only push nodes that have children. */
- assert(0);
- return (-1);
- }
- }
- }
-}
-
-/*
- * We could de-recursify this function using a stack, but it would be
- * overkill since it is never called from a thread context with a
- * limited stack size nor used in a critical path, so I think we can
- * afford keeping it recursive.
- */
-void
-globtree_free(struct globtree *gt)
-{
-
- if (gt->data != NULL) {
- if (gt->type == GLOBTREE_REGEX)
- regfree(gt->data);
- free(gt->data);
- }
- if (gt->left != NULL)
- globtree_free(gt->left);
- if (gt->right != NULL)
- globtree_free(gt->right);
- free(gt);
-}
--- contrib/csup/lister.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/lister.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _LISTER_H_
-#define _LISTER_H_
-
-void *lister(void *);
-
-#endif /* !_LISTER_H_ */
--- contrib/csup/config.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/config.h,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <time.h>
-
-#include "fattr.h"
-#include "queue.h"
-#include "misc.h"
-
-/*
- * Collection options.
- */
-#define CO_BACKUP 0x00000001
-#define CO_DELETE 0x00000002
-#define CO_KEEP 0x00000004
-#define CO_OLD 0x00000008
-#define CO_UNLINKBUSY 0x00000010
-#define CO_NOUPDATE 0x00000020
-#define CO_COMPRESS 0x00000040
-#define CO_USERELSUFFIX 0x00000080
-#define CO_EXACTRCS 0x00000100
-#define CO_CHECKRCS 0x00000200
-#define CO_SKIP 0x00000400
-#define CO_CHECKOUTMODE 0x00000800
-#define CO_NORSYNC 0x00001000
-#define CO_KEEPBADFILES 0x00002000
-#define CO_EXECUTE 0x00004000
-#define CO_SETOWNER 0x00008000
-#define CO_SETMODE 0x00010000
-#define CO_SETFLAGS 0x00020000
-#define CO_NORCS 0x00040000
-#define CO_STRICTCHECKRCS 0x00080000
-#define CO_TRUSTSTATUSFILE 0x00100000
-#define CO_DODELETESONLY 0x00200000
-#define CO_DETAILALLRCSFILES 0x00400000
-
-#define CO_MASK 0x007fffff
-
-/* Options that the server is allowed to set. */
-#define CO_SERVMAYSET (CO_SKIP | CO_NORSYNC | CO_NORCS)
-/* Options that the server is allowed to clear. */
-#define CO_SERVMAYCLEAR CO_CHECKRCS
-
-struct coll {
- char *co_name;
- char *co_host;
- char *co_base;
- char *co_date;
- char *co_prefix;
- size_t co_prefixlen;
- char *co_release;
- char *co_tag;
- char *co_cvsroot;
- int co_attrignore;
- struct pattlist *co_accepts;
- struct pattlist *co_refusals;
- struct globtree *co_dirfilter;
- struct globtree *co_filefilter;
- struct globtree *co_norsync;
- const char *co_colldir;
- char *co_listsuffix;
- time_t co_scantime; /* Set by the detailer thread. */
- int co_options;
- mode_t co_umask;
- struct keyword *co_keyword;
- STAILQ_ENTRY(coll) co_next;
-};
-
-struct config {
- STAILQ_HEAD(, coll) colls;
- struct fixups *fixups;
- char *host;
- struct sockaddr *laddr;
- socklen_t laddrlen;
- int deletelim;
- int socket;
- struct chan *chan0;
- struct chan *chan1;
- struct stream *server;
- fattr_support_t fasupport;
-};
-
-struct config *config_init(const char *, struct coll *, int);
-int config_checkcolls(struct config *);
-void config_free(struct config *);
-
-struct coll *coll_new(struct coll *);
-void coll_override(struct coll *, struct coll *, int);
-char *coll_statuspath(struct coll *);
-char *coll_statussuffix(struct coll *);
-void coll_add(char *);
-void coll_free(struct coll *);
-void coll_setdef(void);
-void coll_setopt(int, char *);
-
-#endif /* !_CONFIG_H_ */
--- contrib/csup/stream.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/stream.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _STREAM_H_
-#define _STREAM_H_
-
-#include "misc.h"
-
-/* Stream filters. */
-typedef enum {
- STREAM_FILTER_NULL,
- STREAM_FILTER_ZLIB,
- STREAM_FILTER_MD5
-} stream_filter_t;
-
-struct stream;
-
-typedef ssize_t stream_readfn_t(void *, void *, size_t);
-typedef ssize_t stream_writefn_t(void *, const void *, size_t);
-typedef int stream_closefn_t(void *);
-
-/* Convenience functions for handling file descriptors. */
-stream_readfn_t stream_read_fd;
-stream_writefn_t stream_write_fd;
-stream_closefn_t stream_close_fd;
-
-struct stream *stream_open(void *, stream_readfn_t *, stream_writefn_t *,
- stream_closefn_t *);
-struct stream *stream_open_fd(int, stream_readfn_t *, stream_writefn_t *,
- stream_closefn_t *);
-struct stream *stream_open_file(const char *, int, ...);
-int stream_fileno(struct stream *);
-ssize_t stream_read(struct stream *, void *, size_t);
-ssize_t stream_write(struct stream *, const void *, size_t);
-char *stream_getln(struct stream *, size_t *);
-int stream_printf(struct stream *, const char *, ...)
- __printflike(2, 3);
-int stream_flush(struct stream *);
-int stream_sync(struct stream *);
-int stream_truncate(struct stream *, off_t);
-int stream_truncate_rel(struct stream *, off_t);
-int stream_rewind(struct stream *);
-int stream_eof(struct stream *);
-int stream_close(struct stream *);
-int stream_filter_start(struct stream *, stream_filter_t, void *);
-void stream_filter_stop(struct stream *);
-
-#endif /* !_STREAM_H_ */
--- contrib/csup/fattr_bsd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $Id$
- */
-
-/*
- * The file attributes we support in a BSD environment.
- *
- * This is similar to fattr_posix.h, except that we support the FA_FLAGS
- * attribute when it makes sense. The FA_FLAGS attribute is for the
- * extended BSD file flags, see chflags(2).
- */
-fattr_support_t fattr_support = {
- /* FT_UNKNOWN */
- 0,
- /* FT_FILE */
- FA_FILETYPE | FA_MODTIME | FA_SIZE | FA_OWNER | FA_GROUP | FA_MODE |
- FA_FLAGS | FA_LINKCOUNT | FA_INODE | FA_DEV,
- /* FT_DIRECTORY */
- FA_FILETYPE | FA_OWNER | FA_GROUP | FA_MODE | FA_FLAGS,
- /* FT_CDEV */
- FA_FILETYPE | FA_RDEV | FA_OWNER | FA_GROUP | FA_MODE | FA_FLAGS |
- FA_LINKCOUNT | FA_DEV | FA_INODE,
- /* FT_BDEV */
- FA_FILETYPE | FA_RDEV | FA_OWNER | FA_GROUP | FA_MODE | FA_FLAGS |
- FA_LINKCOUNT | FA_DEV | FA_INODE,
- /* FT_SYMLINK */
- FA_FILETYPE | FA_LINKTARGET
-};
--- contrib/csup/fixups.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/fixups.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "fixups.h"
-#include "misc.h"
-#include "queue.h"
-
-/*
- * A synchronized queue to implement fixups. The updater thread adds
- * fixup requests to the queue with fixups_put() when a checksum
- * mismatch error occured. It then calls fixups_close() when he's
- * done requesting fixups. The detailer thread gets the fixups with
- * fixups_get() and then send the requests to the server.
- *
- * The queue is synchronized with a mutex and a condition variable.
- */
-
-struct fixups {
- pthread_mutex_t lock;
- pthread_cond_t cond;
- STAILQ_HEAD(, fixup) fixupq;
- struct fixup *cur;
- size_t size;
- int closed;
-};
-
-static void fixups_lock(struct fixups *);
-static void fixups_unlock(struct fixups *);
-
-static struct fixup *fixup_new(struct coll *, const char *);
-static void fixup_free(struct fixup *);
-
-static void
-fixups_lock(struct fixups *f)
-{
- int error;
-
- error = pthread_mutex_lock(&f->lock);
- assert(!error);
-}
-
-static void
-fixups_unlock(struct fixups *f)
-{
- int error;
-
- error = pthread_mutex_unlock(&f->lock);
- assert(!error);
-}
-
-static struct fixup *
-fixup_new(struct coll *coll, const char *name)
-{
- struct fixup *fixup;
-
- fixup = xmalloc(sizeof(struct fixup));
- fixup->f_name = xstrdup(name);
- fixup->f_coll = coll;
- return (fixup);
-}
-
-static void
-fixup_free(struct fixup *fixup)
-{
-
- free(fixup->f_name);
- free(fixup);
-}
-
-/* Create a new fixup queue. */
-struct fixups *
-fixups_new(void)
-{
- struct fixups *f;
-
- f = xmalloc(sizeof(struct fixups));
- f->size = 0;
- f->closed = 0;
- f->cur = NULL;
- STAILQ_INIT(&f->fixupq);
- pthread_mutex_init(&f->lock, NULL);
- pthread_cond_init(&f->cond, NULL);
- return (f);
-}
-
-/* Add a fixup request to the queue. */
-void
-fixups_put(struct fixups *f, struct coll *coll, const char *name)
-{
- struct fixup *fixup;
- int dosignal;
-
- dosignal = 0;
- fixup = fixup_new(coll, name);
- fixups_lock(f);
- assert(!f->closed);
- STAILQ_INSERT_TAIL(&f->fixupq, fixup, f_link);
- if (f->size++ == 0)
- dosignal = 1;
- fixups_unlock(f);
- if (dosignal)
- pthread_cond_signal(&f->cond);
-}
-
-/* Get a fixup request from the queue. */
-struct fixup *
-fixups_get(struct fixups *f)
-{
- struct fixup *fixup, *tofree;
-
- fixups_lock(f);
- while (f->size == 0 && !f->closed)
- pthread_cond_wait(&f->cond, &f->lock);
- if (f->closed) {
- fixups_unlock(f);
- return (NULL);
- }
- assert(f->size > 0);
- fixup = STAILQ_FIRST(&f->fixupq);
- tofree = f->cur;
- f->cur = fixup;
- STAILQ_REMOVE_HEAD(&f->fixupq, f_link);
- f->size--;
- fixups_unlock(f);
- if (tofree != NULL)
- fixup_free(tofree);
- return (fixup);
-}
-
-/* Close the writing end of the queue. */
-void
-fixups_close(struct fixups *f)
-{
- int dosignal;
-
- dosignal = 0;
- fixups_lock(f);
- if (f->size == 0 && !f->closed)
- dosignal = 1;
- f->closed = 1;
- fixups_unlock(f);
- if (dosignal)
- pthread_cond_signal(&f->cond);
-}
-
-/* Free a fixups queue. */
-void
-fixups_free(struct fixups *f)
-{
- struct fixup *fixup, *fixup2;
-
- assert(f->closed);
- /*
- * Free any fixup that has been left on the queue.
- * This can happen if we have been aborted prematurely.
- */
- fixup = STAILQ_FIRST(&f->fixupq);
- while (fixup != NULL) {
- fixup2 = STAILQ_NEXT(fixup, f_link);
- fixup_free(fixup);
- fixup = fixup2;
- }
- if (f->cur != NULL)
- fixup_free(f->cur);
- pthread_cond_destroy(&f->cond);
- pthread_mutex_destroy(&f->lock);
- free(f);
-}
--- contrib/csup/fattr.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/fattr.c,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "fattr.h"
-#include "idcache.h"
-#include "misc.h"
-
-/*
- * Include the appropriate definition for the file attributes we support.
- * There are two different files: fattr_bsd.h for BSD-like systems that
- * support the extended file flags à la chflags() and fattr_posix.h for
- * bare POSIX systems that don't.
- */
-#ifdef HAVE_FFLAGS
-#include "fattr_bsd.h"
-#else
-#include "fattr_posix.h"
-#endif
-
-#ifdef __FreeBSD__
-#include <osreldate.h>
-#endif
-
-/* Define fflags_t if we're on a system that doesn't have it. */
-#if !defined(__FreeBSD_version) || __FreeBSD_version < 500030
-typedef uint32_t fflags_t;
-#endif
-
-#define FA_MASKRADIX 16
-#define FA_FILETYPERADIX 10
-#define FA_MODTIMERADIX 10
-#define FA_SIZERADIX 10
-#define FA_RDEVRADIX 16
-#define FA_MODERADIX 8
-#define FA_FLAGSRADIX 16
-#define FA_LINKCOUNTRADIX 10
-#define FA_DEVRADIX 16
-#define FA_INODERADIX 10
-
-#define FA_PERMMASK (S_IRWXU | S_IRWXG | S_IRWXO)
-#define FA_SETIDMASK (S_ISUID | S_ISGID | S_ISVTX)
-
-struct fattr {
- int mask;
- int type;
- time_t modtime;
- off_t size;
- char *linktarget;
- dev_t rdev;
- uid_t uid;
- gid_t gid;
- mode_t mode;
- fflags_t flags;
- nlink_t linkcount;
- dev_t dev;
- ino_t inode;
-};
-
-static const struct fattr bogus = {
- FA_MODTIME | FA_SIZE | FA_MODE,
- FT_UNKNOWN,
- 1,
- 0,
- NULL,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
-};
-
-static struct fattr *defaults[FT_NUMBER];
-
-void
-fattr_init(void)
-{
- struct fattr *fa;
- int i;
-
- for (i = 0; i < FT_NUMBER; i++) {
- fa = fattr_new(i, -1);
- if (i == FT_DIRECTORY)
- fa->mode = 0777;
- else
- fa->mode = 0666;
- fa->mask |= FA_MODE;
- defaults[i] = fa;
- }
- /* Initialize the uid/gid lookup cache. */
- idcache_init();
-}
-
-void
-fattr_fini(void)
-{
- int i;
-
- idcache_fini();
- for (i = 0; i < FT_NUMBER; i++)
- fattr_free(defaults[i]);
-}
-
-const struct fattr *fattr_bogus = &bogus;
-
-static char *fattr_scanattr(struct fattr *, int, const char *);
-
-int
-fattr_supported(int type)
-{
-
- return (fattr_support[type]);
-}
-
-struct fattr *
-fattr_new(int type, time_t modtime)
-{
- struct fattr *new;
-
- new = xmalloc(sizeof(struct fattr));
- memset(new, 0, sizeof(struct fattr));
- new->type = type;
- if (type != FT_UNKNOWN)
- new->mask |= FA_FILETYPE;
- if (modtime != -1) {
- new->modtime = modtime;
- new->mask |= FA_MODTIME;
- }
- if (fattr_supported(new->type) & FA_LINKCOUNT) {
- new->mask |= FA_LINKCOUNT;
- new->linkcount = 1;
- }
- return (new);
-}
-
-/* Returns a new file attribute structure based on a stat structure. */
-struct fattr *
-fattr_fromstat(struct stat *sb)
-{
- struct fattr *fa;
-
- fa = fattr_new(FT_UNKNOWN, -1);
- if (S_ISREG(sb->st_mode))
- fa->type = FT_FILE;
- else if (S_ISDIR(sb->st_mode))
- fa->type = FT_DIRECTORY;
- else if (S_ISCHR(sb->st_mode))
- fa->type = FT_CDEV;
- else if (S_ISBLK(sb->st_mode))
- fa->type = FT_BDEV;
- else if (S_ISLNK(sb->st_mode))
- fa->type = FT_SYMLINK;
- else
- fa->type = FT_UNKNOWN;
-
- fa->mask = FA_FILETYPE | fattr_supported(fa->type);
- if (fa->mask & FA_MODTIME)
- fa->modtime = sb->st_mtime;
- if (fa->mask & FA_SIZE)
- fa->size = sb->st_size;
- if (fa->mask & FA_RDEV)
- fa->rdev = sb->st_rdev;
- if (fa->mask & FA_OWNER)
- fa->uid = sb->st_uid;
- if (fa->mask & FA_GROUP)
- fa->gid = sb->st_gid;
- if (fa->mask & FA_MODE)
- fa->mode = sb->st_mode & (FA_SETIDMASK | FA_PERMMASK);
-#ifdef HAVE_FFLAGS
- if (fa->mask & FA_FLAGS)
- fa->flags = sb->st_flags;
-#endif
- if (fa->mask & FA_LINKCOUNT)
- fa->linkcount = sb->st_nlink;
- if (fa->mask & FA_DEV)
- fa->dev = sb->st_dev;
- if (fa->mask & FA_INODE)
- fa->inode = sb->st_ino;
- return (fa);
-}
-
-struct fattr *
-fattr_frompath(const char *path, int nofollow)
-{
- struct fattr *fa;
- struct stat sb;
- int error, len;
-
- if (nofollow)
- error = lstat(path, &sb);
- else
- error = stat(path, &sb);
- if (error)
- return (NULL);
- fa = fattr_fromstat(&sb);
- if (fa->mask & FA_LINKTARGET) {
- char buf[1024];
-
- len = readlink(path, buf, sizeof(buf));
- if (len == -1) {
- fattr_free(fa);
- return (NULL);
- }
- if ((unsigned)len > sizeof(buf) - 1) {
- fattr_free(fa);
- errno = ENAMETOOLONG;
- return (NULL);
- }
- buf[len] = '\0';
- fa->linktarget = xstrdup(buf);
- }
- return (fa);
-}
-
-struct fattr *
-fattr_fromfd(int fd)
-{
- struct fattr *fa;
- struct stat sb;
- int error;
-
- error = fstat(fd, &sb);
- if (error)
- return (NULL);
- fa = fattr_fromstat(&sb);
- return (fa);
-}
-
-int
-fattr_type(const struct fattr *fa)
-{
-
- return (fa->type);
-}
-
-/* Returns a new file attribute structure from its encoded text form. */
-struct fattr *
-fattr_decode(char *attr)
-{
- struct fattr *fa;
- char *next;
-
- fa = fattr_new(FT_UNKNOWN, -1);
- next = fattr_scanattr(fa, FA_MASK, attr);
- if (next == NULL || (fa->mask & ~FA_MASK) > 0)
- goto bad;
- if (fa->mask & FA_FILETYPE) {
- next = fattr_scanattr(fa, FA_FILETYPE, next);
- if (next == NULL)
- goto bad;
- if (fa->type < 0 || fa->type > FT_MAX)
- fa->type = FT_UNKNOWN;
- } else {
- /* The filetype attribute is always valid. */
- fa->mask |= FA_FILETYPE;
- fa->type = FT_UNKNOWN;
- }
- fa->mask = fa->mask & fattr_supported(fa->type);
- if (fa->mask & FA_MODTIME)
- next = fattr_scanattr(fa, FA_MODTIME, next);
- if (fa->mask & FA_SIZE)
- next = fattr_scanattr(fa, FA_SIZE, next);
- if (fa->mask & FA_LINKTARGET)
- next = fattr_scanattr(fa, FA_LINKTARGET, next);
- if (fa->mask & FA_RDEV)
- next = fattr_scanattr(fa, FA_RDEV, next);
- if (fa->mask & FA_OWNER)
- next = fattr_scanattr(fa, FA_OWNER, next);
- if (fa->mask & FA_GROUP)
- next = fattr_scanattr(fa, FA_GROUP, next);
- if (fa->mask & FA_MODE)
- next = fattr_scanattr(fa, FA_MODE, next);
- if (fa->mask & FA_FLAGS)
- next = fattr_scanattr(fa, FA_FLAGS, next);
- if (fa->mask & FA_LINKCOUNT) {
- next = fattr_scanattr(fa, FA_LINKCOUNT, next);
- } else if (fattr_supported(fa->type) & FA_LINKCOUNT) {
- /* If the link count is missing but supported, fake it as 1. */
- fa->mask |= FA_LINKCOUNT;
- fa->linkcount = 1;
- }
- if (fa->mask & FA_DEV)
- next = fattr_scanattr(fa, FA_DEV, next);
- if (fa->mask & FA_INODE)
- next = fattr_scanattr(fa, FA_INODE, next);
- if (next == NULL)
- goto bad;
- return (fa);
-bad:
- fattr_free(fa);
- return (NULL);
-}
-
-char *
-fattr_encode(const struct fattr *fa, fattr_support_t support, int ignore)
-{
- struct {
- char val[32];
- char len[4];
- int extval;
- char *ext;
- } pieces[FA_NUMBER], *piece;
- char *cp, *s, *username, *groupname;
- size_t len, vallen;
- mode_t mode, modemask;
- int mask, n, i;
-
- username = NULL;
- groupname = NULL;
- if (support == NULL)
- mask = fa->mask;
- else
- mask = fa->mask & support[fa->type];
- mask &= ~ignore;
- if (fa->mask & FA_OWNER) {
- username = getuserbyid(fa->uid);
- if (username == NULL)
- mask &= ~FA_OWNER;
- }
- if (fa->mask & FA_GROUP) {
- groupname = getgroupbyid(fa->gid);
- if (groupname == NULL)
- mask &= ~FA_GROUP;
- }
- if (fa->mask & FA_LINKCOUNT && fa->linkcount == 1)
- mask &= ~FA_LINKCOUNT;
-
- memset(pieces, 0, FA_NUMBER * sizeof(*pieces));
- len = 0;
- piece = pieces;
- vallen = snprintf(piece->val, sizeof(piece->val), "%x", mask);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- if (mask & FA_FILETYPE) {
- vallen = snprintf(piece->val, sizeof(piece->val),
- "%d", fa->type);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_MODTIME) {
- vallen = snprintf(piece->val, sizeof(piece->val),
- "%lld", (long long)fa->modtime);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_SIZE) {
- vallen = snprintf(piece->val, sizeof(piece->val),
- "%lld", (long long)fa->size);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_LINKTARGET) {
- vallen = strlen(fa->linktarget);
- piece->extval = 1;
- piece->ext = fa->linktarget;
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_RDEV) {
- vallen = snprintf(piece->val, sizeof(piece->val),
- "%lld", (long long)fa->rdev);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_OWNER) {
- vallen = strlen(username);
- piece->extval = 1;
- piece->ext = username;
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_GROUP) {
- vallen = strlen(groupname);
- piece->extval = 1;
- piece->ext = groupname;
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_MODE) {
- if (mask & FA_OWNER && mask & FA_GROUP)
- modemask = FA_SETIDMASK | FA_PERMMASK;
- else
- modemask = FA_PERMMASK;
- mode = fa->mode & modemask;
- vallen = snprintf(piece->val, sizeof(piece->val),
- "%o", mode);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_FLAGS) {
- vallen = snprintf(piece->val, sizeof(piece->val), "%llx",
- (long long)fa->flags);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_LINKCOUNT) {
- vallen = snprintf(piece->val, sizeof(piece->val), "%lld",
- (long long)fa->linkcount);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_DEV) {
- vallen = snprintf(piece->val, sizeof(piece->val), "%lld",
- (long long)fa->dev);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
- if (mask & FA_INODE) {
- vallen = snprintf(piece->val, sizeof(piece->val), "%lld",
- (long long)fa->inode);
- len += snprintf(piece->len, sizeof(piece->len), "%lld",
- (long long)vallen) + vallen + 1;
- piece++;
- }
-
- s = xmalloc(len + 1);
-
- n = piece - pieces;
- piece = pieces;
- cp = s;
- for (i = 0; i < n; i++) {
- if (piece->extval)
- len = sprintf(cp, "%s#%s", piece->len, piece->ext);
- else
- len = sprintf(cp, "%s#%s", piece->len, piece->val);
- cp += len;
- piece++;
- }
- return (s);
-}
-
-struct fattr *
-fattr_dup(const struct fattr *from)
-{
- struct fattr *fa;
-
- fa = fattr_new(FT_UNKNOWN, -1);
- fattr_override(fa, from, FA_MASK);
- return (fa);
-}
-
-void
-fattr_free(struct fattr *fa)
-{
-
- if (fa == NULL)
- return;
- if (fa->linktarget != NULL)
- free(fa->linktarget);
- free(fa);
-}
-
-void
-fattr_umask(struct fattr *fa, mode_t newumask)
-{
-
- if (fa->mask & FA_MODE)
- fa->mode = fa->mode & ~newumask;
-}
-
-void
-fattr_maskout(struct fattr *fa, int mask)
-{
-
- /* Don't forget to free() the linktarget attribute if we remove it. */
- if (mask & FA_LINKTARGET && fa->mask & FA_LINKTARGET) {
- free(fa->linktarget);
- fa->linktarget = NULL;
- }
- fa->mask &= ~mask;
-}
-
-int
-fattr_getmask(const struct fattr *fa)
-{
-
- return (fa->mask);
-}
-
-nlink_t
-fattr_getlinkcount(const struct fattr *fa)
-{
-
- return (fa->linkcount);
-}
-
-/*
- * Eat the specified attribute and put it in the file attribute
- * structure. Returns NULL on error, or a pointer to the next
- * attribute to parse.
- *
- * This would be much prettier if we had strntol() so that we're
- * not forced to write '\0' to the string before calling strtol()
- * and then put back the old value...
- *
- * We need to use (unsigned) long long types here because some
- * of the opaque types we're parsing (off_t, time_t...) may need
- * 64bits to fit.
- */
-static char *
-fattr_scanattr(struct fattr *fa, int type, const char *attr)
-{
- char *attrend, *attrstart, *end;
- size_t len;
- unsigned long attrlen;
- int error;
- mode_t modemask;
- char tmp;
-
- if (attr == NULL)
- return (NULL);
- errno = 0;
- attrlen = strtoul(attr, &end, 10);
- if (errno || *end != '#')
- return (NULL);
- len = strlen(attr);
- attrstart = end + 1;
- attrend = attrstart + attrlen;
- tmp = *attrend;
- *attrend = '\0';
- switch (type) {
- /* Using FA_MASK here is a bit bogus semantically. */
- case FA_MASK:
- errno = 0;
- fa->mask = (int)strtol(attrstart, &end, FA_MASKRADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_FILETYPE:
- errno = 0;
- fa->type = (int)strtol(attrstart, &end, FA_FILETYPERADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_MODTIME:
- errno = 0;
- fa->modtime = (time_t)strtoll(attrstart, &end, FA_MODTIMERADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_SIZE:
- errno = 0;
- fa->size = (off_t)strtoll(attrstart, &end, FA_SIZERADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_LINKTARGET:
- fa->linktarget = xstrdup(attrstart);
- break;
- case FA_RDEV:
- errno = 0;
- fa->rdev = (dev_t)strtoll(attrstart, &end, FA_RDEVRADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_OWNER:
- error = getuidbyname(attrstart, &fa->uid);
- if (error)
- fa->mask &= ~FA_OWNER;
- break;
- case FA_GROUP:
- error = getgidbyname(attrstart, &fa->gid);
- if (error)
- fa->mask &= ~FA_GROUP;
- break;
- case FA_MODE:
- errno = 0;
- fa->mode = (mode_t)strtol(attrstart, &end, FA_MODERADIX);
- if (errno || end != attrend)
- goto bad;
- if (fa->mask & FA_OWNER && fa->mask & FA_GROUP)
- modemask = FA_SETIDMASK | FA_PERMMASK;
- else
- modemask = FA_PERMMASK;
- fa->mode &= modemask;
- break;
- case FA_FLAGS:
- errno = 0;
- fa->flags = (fflags_t)strtoul(attrstart, &end, FA_FLAGSRADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_LINKCOUNT:
- errno = 0;
- fa->linkcount = (nlink_t)strtol(attrstart, &end, FA_FLAGSRADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_DEV:
- errno = 0;
- fa->dev = (dev_t)strtoll(attrstart, &end, FA_DEVRADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- case FA_INODE:
- errno = 0;
- fa->inode = (ino_t)strtoll(attrstart, &end, FA_INODERADIX);
- if (errno || end != attrend)
- goto bad;
- break;
- }
- *attrend = tmp;
- return (attrend);
-bad:
- *attrend = tmp;
- return (NULL);
-}
-
-/* Return a file attribute structure built from the RCS file attributes. */
-struct fattr *
-fattr_forcheckout(const struct fattr *rcsattr, mode_t mask)
-{
- struct fattr *fa;
-
- fa = fattr_new(FT_FILE, -1);
- if (rcsattr->mask & FA_MODE) {
- if ((rcsattr->mode & 0111) > 0)
- fa->mode = 0777;
- else
- fa->mode = 0666;
- fa->mode &= ~mask;
- fa->mask |= FA_MODE;
- }
- return (fa);
-}
-
-/* Merge attributes from "from" that aren't present in "fa". */
-void
-fattr_merge(struct fattr *fa, const struct fattr *from)
-{
-
- fattr_override(fa, from, from->mask & ~fa->mask);
-}
-
-/* Merge default attributes. */
-void
-fattr_mergedefault(struct fattr *fa)
-{
-
- fattr_merge(fa, defaults[fa->type]);
-}
-
-/* Override selected attributes of "fa" with values from "from". */
-void
-fattr_override(struct fattr *fa, const struct fattr *from, int mask)
-{
-
- mask &= from->mask;
- if (fa->mask & FA_LINKTARGET && mask & FA_LINKTARGET)
- free(fa->linktarget);
- fa->mask |= mask;
- if (mask & FA_FILETYPE)
- fa->type = from->type;
- if (mask & FA_MODTIME)
- fa->modtime = from->modtime;
- if (mask & FA_SIZE)
- fa->size = from->size;
- if (mask & FA_LINKTARGET)
- fa->linktarget = xstrdup(from->linktarget);
- if (mask & FA_RDEV)
- fa->rdev = from->rdev;
- if (mask & FA_OWNER)
- fa->uid = from->uid;
- if (mask & FA_GROUP)
- fa->gid = from->gid;
- if (mask & FA_MODE)
- fa->mode = from->mode;
- if (mask & FA_FLAGS)
- fa->flags = from->flags;
- if (mask & FA_LINKCOUNT)
- fa->linkcount = from->linkcount;
- if (mask & FA_DEV)
- fa->dev = from->dev;
- if (mask & FA_INODE)
- fa->inode = from->inode;
-}
-
-/* Create a node. */
-int
-fattr_makenode(const struct fattr *fa, const char *path)
-{
- mode_t modemask, mode;
- int error;
-
- if (fa->mask & FA_OWNER && fa->mask & FA_GROUP)
- modemask = FA_SETIDMASK | FA_PERMMASK;
- else
- modemask = FA_PERMMASK;
-
- /* We only implement fattr_makenode() for dirs for now. */
- assert(fa->type == FT_DIRECTORY);
- if (fa->mask & FA_MODE)
- mode = fa->mode & modemask;
- else
- mode = 0700;
- error = mkdir(path, mode);
- return (error);
-}
-
-int
-fattr_delete(const char *path)
-{
- struct fattr *fa;
- int error;
-
- fa = fattr_frompath(path, FATTR_NOFOLLOW);
- if (fa == NULL) {
- if (errno == ENOENT)
- return (0);
- return (-1);
- }
-
-#ifdef HAVE_FFLAGS
- /* Clear flags. */
- if (fa->mask & FA_FLAGS && fa->flags != 0) {
- fa->flags = 0;
- (void)chflags(path, fa->flags);
- }
-#endif
-
- if (fa->type == FT_DIRECTORY)
- error = rmdir(path);
- else
- error = unlink(path);
- fattr_free(fa);
- return (error);
-}
-
-/*
- * Changes those attributes we can change. Returns -1 on error,
- * 0 if no update was needed, and 1 if an update was needed and
- * it has been applied successfully.
- */
-int
-fattr_install(struct fattr *fa, const char *topath, const char *frompath)
-{
- struct timeval tv[2];
- struct fattr *old;
- int error, inplace, mask;
- mode_t modemask, newmode;
- uid_t uid;
- gid_t gid;
-
- mask = fa->mask & fattr_supported(fa->type);
- if (mask & FA_OWNER && mask & FA_GROUP)
- modemask = FA_SETIDMASK | FA_PERMMASK;
- else
- modemask = FA_PERMMASK;
-
- inplace = 0;
- if (frompath == NULL) {
- /* Changing attributes in place. */
- frompath = topath;
- inplace = 1;
- }
- old = fattr_frompath(topath, FATTR_NOFOLLOW);
- if (old != NULL) {
- if (inplace && fattr_equal(fa, old)) {
- fattr_free(old);
- return (0);
- }
-
-#ifdef HAVE_FFLAGS
- /*
- * Determine whether we need to clear the flags of the target.
- * This is bogus in that it assumes a value of 0 is safe and
- * that non-zero is unsafe. I'm not really worried by that
- * since as far as I know that's the way things are.
- */
- if ((old->mask & FA_FLAGS) && old->flags > 0) {
- (void)chflags(topath, 0);
- old->flags = 0;
- }
-#endif
-
- /* Determine whether we need to remove the target first. */
- if (!inplace && (fa->type == FT_DIRECTORY) !=
- (old->type == FT_DIRECTORY)) {
- if (old->type == FT_DIRECTORY)
- error = rmdir(topath);
- else
- error = unlink(topath);
- if (error)
- goto bad;
- }
- }
-
- /* Change those attributes that we can before moving the file
- * into place. That makes installation atomic in most cases. */
- if (mask & FA_MODTIME) {
- gettimeofday(tv, NULL); /* Access time. */
- tv[1].tv_sec = fa->modtime; /* Modification time. */
- tv[1].tv_usec = 0;
- error = utimes(frompath, tv);
- if (error)
- goto bad;
- }
- if (mask & FA_OWNER || mask & FA_GROUP) {
- uid = -1;
- gid = -1;
- if (mask & FA_OWNER)
- uid = fa->uid;
- if (mask & FA_GROUP)
- gid = fa->gid;
- error = chown(frompath, uid, gid);
- if (error)
- goto bad;
- }
- if (mask & FA_MODE) {
- newmode = fa->mode & modemask;
- /* Merge in set*id bits from the old attribute. */
- if (old != NULL && old->mask & FA_MODE) {
- newmode |= (old->mode & ~modemask);
- newmode &= (FA_SETIDMASK | FA_PERMMASK);
- }
- error = chmod(frompath, newmode);
- if (error)
- goto bad;
- }
-
- if (!inplace) {
- error = rename(frompath, topath);
- if (error)
- goto bad;
- }
-
-#ifdef HAVE_FFLAGS
- /* Set the flags. */
- if (mask & FA_FLAGS)
- (void)chflags(topath, fa->flags);
-#endif
- fattr_free(old);
- return (1);
-bad:
- fattr_free(old);
- return (-1);
-}
-
-/*
- * Returns 1 if both attributes are equal, 0 otherwise.
- *
- * This function only compares attributes that are valid in both
- * files. A file of unknown type ("FT_UNKNOWN") is unequal to
- * anything, including itself.
- */
-int
-fattr_equal(const struct fattr *fa1, const struct fattr *fa2)
-{
- int mask;
-
- mask = fa1->mask & fa2->mask;
- if (fa1->type == FT_UNKNOWN || fa2->type == FT_UNKNOWN)
- return (0);
- if (mask & FA_MODTIME)
- if (fa1->modtime != fa2->modtime)
- return (0);
- if (mask & FA_SIZE)
- if (fa1->size != fa2->size)
- return (0);
- if (mask & FA_LINKTARGET)
- if (strcmp(fa1->linktarget, fa2->linktarget) != 0)
- return (0);
- if (mask & FA_RDEV)
- if (fa1->rdev != fa2->rdev)
- return (0);
- if (mask & FA_OWNER)
- if (fa1->uid != fa2->uid)
- return (0);
- if (mask & FA_GROUP)
- if (fa1->gid != fa2->gid)
- return (0);
- if (mask & FA_MODE)
- if (fa1->mode != fa2->mode)
- return (0);
- if (mask & FA_FLAGS)
- if (fa1->flags != fa2->flags)
- return (0);
- if (mask & FA_LINKCOUNT)
- if (fa1->linkcount != fa2->linkcount)
- return (0);
- if (mask & FA_DEV)
- if (fa1->dev != fa2->dev)
- return (0);
- if (mask & FA_INODE)
- if (fa1->inode != fa2->inode)
- return (0);
- return (1);
-}
--- contrib/csup/keyword.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/keyword.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "diff.h"
-#include "keyword.h"
-#include "misc.h"
-#include "queue.h"
-#include "stream.h"
-
-/*
- * The keyword API is used to expand the CVS/RCS keywords in files,
- * such as $Id$, $Revision$, etc. The server does it for us when it
- * sends us entire files, but we need to handle the expansion when
- * applying a diff update.
- */
-
-enum rcskey {
- RCSKEY_AUTHOR,
- RCSKEY_CVSHEADER,
- RCSKEY_DATE,
- RCSKEY_HEADER,
- RCSKEY_ID,
- RCSKEY_LOCKER,
- RCSKEY_LOG,
- RCSKEY_NAME,
- RCSKEY_RCSFILE,
- RCSKEY_REVISION,
- RCSKEY_SOURCE,
- RCSKEY_STATE
-};
-
-typedef enum rcskey rcskey_t;
-
-struct tag {
- char *ident;
- rcskey_t key;
- int enabled;
- STAILQ_ENTRY(tag) next;
-};
-
-static struct tag *tag_new(const char *, rcskey_t);
-static char *tag_expand(struct tag *, struct diffinfo *);
-static void tag_free(struct tag *);
-
-struct keyword {
- STAILQ_HEAD(, tag) keywords; /* Enabled keywords. */
- size_t minkeylen;
- size_t maxkeylen;
-};
-
-/* Default CVS keywords. */
-static struct {
- const char *ident;
- rcskey_t key;
-} tag_defaults[] = {
- { "Author", RCSKEY_AUTHOR },
- { "CVSHeader", RCSKEY_CVSHEADER },
- { "Date", RCSKEY_DATE },
- { "Header", RCSKEY_HEADER },
- { "Id", RCSKEY_ID },
- { "Locker", RCSKEY_LOCKER },
- { "Log", RCSKEY_LOG },
- { "Name", RCSKEY_NAME },
- { "RCSfile", RCSKEY_RCSFILE },
- { "Revision", RCSKEY_REVISION },
- { "Source", RCSKEY_SOURCE },
- { "State", RCSKEY_STATE },
- { NULL, 0, }
-};
-
-struct keyword *
-keyword_new(void)
-{
- struct keyword *new;
- struct tag *tag;
- size_t len;
- int i;
-
- new = xmalloc(sizeof(struct keyword));
- STAILQ_INIT(&new->keywords);
- new->minkeylen = ~0;
- new->maxkeylen = 0;
- for (i = 0; tag_defaults[i].ident != NULL; i++) {
- tag = tag_new(tag_defaults[i].ident, tag_defaults[i].key);
- STAILQ_INSERT_TAIL(&new->keywords, tag, next);
- len = strlen(tag->ident);
- /*
- * These values are only computed here and not updated when
- * adding an alias. This is a bug, but CVSup has it and we
- * need to be bug-to-bug compatible since the server will
- * expect us to do the same, and we will fail with an MD5
- * checksum mismatch if we don't.
- */
- new->minkeylen = min(new->minkeylen, len);
- new->maxkeylen = max(new->maxkeylen, len);
- }
- return (new);
-}
-
-int
-keyword_decode_expand(const char *expand)
-{
-
- if (strcmp(expand, ".") == 0)
- return (EXPAND_DEFAULT);
- else if (strcmp(expand, "kv") == 0)
- return (EXPAND_KEYVALUE);
- else if (strcmp(expand, "kvl") == 0)
- return (EXPAND_KEYVALUELOCKER);
- else if (strcmp(expand, "k") == 0)
- return (EXPAND_KEY);
- else if (strcmp(expand, "o") == 0)
- return (EXPAND_OLD);
- else if (strcmp(expand, "b") == 0)
- return (EXPAND_BINARY);
- else if (strcmp(expand, "v") == 0)
- return (EXPAND_VALUE);
- else
- return (-1);
-}
-
-void
-keyword_free(struct keyword *keyword)
-{
- struct tag *tag;
-
- if (keyword == NULL)
- return;
- while (!STAILQ_EMPTY(&keyword->keywords)) {
- tag = STAILQ_FIRST(&keyword->keywords);
- STAILQ_REMOVE_HEAD(&keyword->keywords, next);
- tag_free(tag);
- }
- free(keyword);
-}
-
-int
-keyword_alias(struct keyword *keyword, const char *ident, const char *rcskey)
-{
- struct tag *new, *tag;
-
- STAILQ_FOREACH(tag, &keyword->keywords, next) {
- if (strcmp(tag->ident, rcskey) == 0) {
- new = tag_new(ident, tag->key);
- STAILQ_INSERT_HEAD(&keyword->keywords, new, next);
- return (0);
- }
- }
- errno = ENOENT;
- return (-1);
-}
-
-int
-keyword_enable(struct keyword *keyword, const char *ident)
-{
- struct tag *tag;
- int all;
-
- all = 0;
- if (strcmp(ident, ".") == 0)
- all = 1;
-
- STAILQ_FOREACH(tag, &keyword->keywords, next) {
- if (!all && strcmp(tag->ident, ident) != 0)
- continue;
- tag->enabled = 1;
- if (!all)
- return (0);
- }
- if (!all) {
- errno = ENOENT;
- return (-1);
- }
- return (0);
-}
-
-int
-keyword_disable(struct keyword *keyword, const char *ident)
-{
- struct tag *tag;
- int all;
-
- all = 0;
- if (strcmp(ident, ".") == 0)
- all = 1;
-
- STAILQ_FOREACH(tag, &keyword->keywords, next) {
- if (!all && strcmp(tag->ident, ident) != 0)
- continue;
- tag->enabled = 0;
- if (!all)
- return (0);
- }
-
- if (!all) {
- errno = ENOENT;
- return (-1);
- }
- return (0);
-}
-
-void
-keyword_prepare(struct keyword *keyword)
-{
- struct tag *tag, *temp;
-
- STAILQ_FOREACH_SAFE(tag, &keyword->keywords, next, temp) {
- if (!tag->enabled) {
- STAILQ_REMOVE(&keyword->keywords, tag, tag, next);
- tag_free(tag);
- continue;
- }
- }
-}
-
-/*
- * Expand appropriate RCS keywords. If there's no tag to expand,
- * keyword_expand() returns 0, otherwise it returns 1 and writes a
- * pointer to the new line in *buf and the new len in *len. The
- * new line is allocated with malloc() and needs to be freed by the
- * caller after use.
- */
-int
-keyword_expand(struct keyword *keyword, struct diffinfo *di, char *line,
- size_t size, char **buf, size_t *len)
-{
- struct tag *tag;
- char *dollar, *keystart, *valstart, *vallim, *next;
- char *linestart, *newline, *newval, *cp, *tmp;
- size_t left, newsize, vallen;
-
- if (di->di_expand == EXPAND_OLD || di->di_expand == EXPAND_BINARY)
- return (0);
- newline = NULL;
- newsize = 0;
- left = size;
- linestart = cp = line;
-again:
- dollar = memchr(cp, '$', left);
- if (dollar == NULL) {
- if (newline != NULL) {
- *buf = newline;
- *len = newsize;
- return (1);
- }
- return (0);
- }
- keystart = dollar + 1;
- left -= keystart - cp;
- vallim = memchr(keystart, '$', left);
- if (vallim == NULL) {
- if (newline != NULL) {
- *buf = newline;
- *len = newsize;
- return (1);
- }
- return (0);
- }
- if (vallim == keystart) {
- cp = keystart;
- goto again;
- }
- valstart = memchr(keystart, ':', left);
- if (valstart == keystart) {
- cp = vallim;
- left -= vallim - keystart;
- goto again;
- }
- if (valstart == NULL || valstart > vallim)
- valstart = vallim;
-
- if (valstart < keystart + keyword->minkeylen ||
- valstart > keystart + keyword->maxkeylen) {
- cp = vallim;
- left -= vallim -keystart;
- goto again;
- }
- STAILQ_FOREACH(tag, &keyword->keywords, next) {
- if (strncmp(tag->ident, keystart, valstart - keystart) == 0 &&
- tag->ident[valstart - keystart] == '\0') {
- if (newline != NULL)
- tmp = newline;
- else
- tmp = NULL;
- newval = NULL;
- if (di->di_expand == EXPAND_KEY) {
- newsize = dollar - linestart + 1 +
- valstart - keystart + 1 +
- size - (vallim + 1 - linestart);
- newline = xmalloc(newsize);
- cp = newline;
- memcpy(cp, linestart, dollar - linestart);
- cp += dollar - linestart;
- *cp++ = '$';
- memcpy(cp, keystart, valstart - keystart);
- cp += valstart - keystart;
- *cp++ = '$';
- next = cp;
- memcpy(cp, vallim + 1,
- size - (vallim + 1 - linestart));
- } else if (di->di_expand == EXPAND_VALUE) {
- newval = tag_expand(tag, di);
- if (newval == NULL)
- vallen = 0;
- else
- vallen = strlen(newval);
- newsize = dollar - linestart +
- vallen +
- size - (vallim + 1 - linestart);
- newline = xmalloc(newsize);
- cp = newline;
- memcpy(cp, linestart, dollar - linestart);
- cp += dollar - linestart;
- if (newval != NULL) {
- memcpy(cp, newval, vallen);
- cp += vallen;
- }
- next = cp;
- memcpy(cp, vallim + 1,
- size - (vallim + 1 - linestart));
- } else {
- assert(di->di_expand == EXPAND_DEFAULT ||
- di->di_expand == EXPAND_KEYVALUE ||
- di->di_expand == EXPAND_KEYVALUELOCKER);
- newval = tag_expand(tag, di);
- if (newval == NULL)
- vallen = 0;
- else
- vallen = strlen(newval);
- newsize = dollar - linestart + 1 +
- valstart - keystart + 2 +
- vallen + 2 +
- size - (vallim + 1 - linestart);
- newline = xmalloc(newsize);
- cp = newline;
- memcpy(cp, linestart, dollar - linestart);
- cp += dollar - linestart;
- *cp++ = '$';
- memcpy(cp, keystart, valstart - keystart);
- cp += valstart - keystart;
- *cp++ = ':';
- *cp++ = ' ';
- if (newval != NULL) {
- memcpy(cp, newval, vallen);
- cp += vallen;
- }
- *cp++ = ' ';
- *cp++ = '$';
- next = cp;
- memcpy(cp, vallim + 1,
- size - (vallim + 1 - linestart));
- }
- if (newval != NULL)
- free(newval);
- if (tmp != NULL)
- free(tmp);
- /*
- * Continue looking for tags in the rest of the line.
- */
- cp = next;
- size = newsize;
- left = size - (cp - newline);
- linestart = newline;
- goto again;
- }
- }
- cp = vallim;
- left = size - (cp - linestart);
- goto again;
-}
-
-static struct tag *
-tag_new(const char *ident, rcskey_t key)
-{
- struct tag *new;
-
- new = xmalloc(sizeof(struct tag));
- new->ident = xstrdup(ident);
- new->key = key;
- new->enabled = 1;
- return (new);
-}
-
-static void
-tag_free(struct tag *tag)
-{
-
- free(tag->ident);
- free(tag);
-}
-
-/*
- * Expand a specific tag and return the new value. If NULL
- * is returned, the tag is empty.
- */
-static char *
-tag_expand(struct tag *tag, struct diffinfo *di)
-{
- /*
- * CVS formats dates as "XXXX/XX/XX XX:XX:XX". 32 bytes
- * is big enough until year 10,000,000,000,000,000 :-).
- */
- char cvsdate[32];
- struct tm tm;
- char *filename, *val;
- int error;
-
- error = rcsdatetotm(di->di_revdate, &tm);
- if (error)
- err(1, "strptime");
- if (strftime(cvsdate, sizeof(cvsdate), "%Y/%m/%d %H:%M:%S", &tm) == 0)
- err(1, "strftime");
- filename = strrchr(di->di_rcsfile, '/');
- if (filename == NULL)
- filename = di->di_rcsfile;
- else
- filename++;
-
- switch (tag->key) {
- case RCSKEY_AUTHOR:
- xasprintf(&val, "%s", di->di_author);
- break;
- case RCSKEY_CVSHEADER:
- xasprintf(&val, "%s %s %s %s %s", di->di_rcsfile,
- di->di_revnum, cvsdate, di->di_author, di->di_state);
- break;
- case RCSKEY_DATE:
- xasprintf(&val, "%s", cvsdate);
- break;
- case RCSKEY_HEADER:
- xasprintf(&val, "%s/%s %s %s %s %s", di->di_cvsroot,
- di->di_rcsfile, di->di_revnum, cvsdate, di->di_author,
- di->di_state);
- break;
- case RCSKEY_ID:
- xasprintf(&val, "%s %s %s %s %s", filename, di->di_revnum,
- cvsdate, di->di_author, di->di_state);
- break;
- case RCSKEY_LOCKER:
- /*
- * Unimplemented even in CVSup sources. It seems we don't
- * even have this information sent by the server.
- */
- return (NULL);
- case RCSKEY_LOG:
- /* XXX */
- printf("%s: Implement Log keyword expansion\n", __func__);
- return (NULL);
- case RCSKEY_NAME:
- if (di->di_tag != NULL)
- xasprintf(&val, "%s", di->di_tag);
- else
- return (NULL);
- break;
- case RCSKEY_RCSFILE:
- xasprintf(&val, "%s", filename);
- break;
- case RCSKEY_REVISION:
- xasprintf(&val, "%s", di->di_revnum);
- break;
- case RCSKEY_SOURCE:
- xasprintf(&val, "%s/%s", di->di_cvsroot, di->di_rcsfile);
- break;
- case RCSKEY_STATE:
- xasprintf(&val, "%s", di->di_state);
- break;
- }
- return (val);
-}
--- contrib/csup/fixups.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/fixups.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _FIXUPS_H_
-#define _FIXUPS_H_
-
-#include "queue.h"
-
-struct coll;
-struct fixups;
-
-struct fixup {
- struct coll *f_coll;
- char *f_name;
- STAILQ_ENTRY(fixup) f_link; /* Not for consumers. */
-};
-
-struct fixups *fixups_new(void);
-void fixups_put(struct fixups *, struct coll *, const char *);
-struct fixup *fixups_get(struct fixups *);
-void fixups_close(struct fixups *);
-void fixups_free(struct fixups *);
-
-#endif /* !_FIXUPS_H_ */
--- contrib/csup/status.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/status.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _STATUS_H_
-#define _STATUS_H_
-
-#include <time.h>
-
-struct coll;
-struct fattr;
-struct status;
-
-#define SR_DIRDOWN 0
-#define SR_CHECKOUTLIVE 1
-#define SR_CHECKOUTDEAD 2
-#define SR_FILELIVE 3
-#define SR_FILEDEAD 4
-#define SR_DIRUP 5
-
-struct statusrec {
- int sr_type;
- char *sr_file;
- char *sr_tag;
- char *sr_date;
- char *sr_revnum;
- char *sr_revdate;
-
- /*
- * "clientrttr" contains the attributes of the client's file if there
- * is one. "serverattr" contains the attributes of the corresponding
- * file on the server. In CVS mode, these are identical. But in
- * checkout mode, "clientattr" represents the checked-out file while
- * "serverattr" represents the corresponding RCS file on the server.
- */
- struct fattr *sr_serverattr;
- struct fattr *sr_clientattr;
-};
-
-struct status *status_open(struct coll *, time_t, char **);
-int status_get(struct status *, char *, int, int,
- struct statusrec **);
-int status_put(struct status *, struct statusrec *);
-int status_eof(struct status *);
-char *status_errmsg(struct status *);
-int status_delete(struct status *, char *, int);
-void status_close(struct status *, char **);
-
-#endif /* !_STATUS_H_ */
--- contrib/csup/queue.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. 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, 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.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $FreeBSD: src/contrib/csup/queue.h,v 1.1.1.2.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#ifndef _QUEUE_H_
-#define _QUEUE_H_
-
-#undef __offsetof
-#define __offsetof(type, field) ((size_t)(&((type *)0)->field))
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#undef STAILQ_HEAD
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first;/* first element */ \
- struct type **stqh_last;/* addr of last next element */ \
-}
-
-#undef STAILQ_HEAD_INITIALIZER
-#define STAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).stqh_first }
-
-#undef STAILQ_ENTRY
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-#undef STAILQ_EMPTY
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#undef STAILQ_FIRST
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-
-#undef STAILQ_FOREACH
-#define STAILQ_FOREACH(var, head, field) \
- for((var) = STAILQ_FIRST((head)); \
- (var); \
- (var) = STAILQ_NEXT((var), field))
-
-#undef STAILQ_FOREACH_SAFE
-#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = STAILQ_FIRST((head)); \
- (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#undef STAILQ_INIT
-#define STAILQ_INIT(head) do { \
- STAILQ_FIRST((head)) = NULL; \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#undef STAILQ_INSERT_AFTER
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_NEXT((tqelm), field) = (elm); \
-} while (0)
-
-#undef STAILQ_INSERT_HEAD
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
- STAILQ_FIRST((head)) = (elm); \
-} while (0)
-
-#undef STAILQ_INSERT_TAIL
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- STAILQ_NEXT((elm), field) = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &STAILQ_NEXT((elm), field); \
-} while (0)
-
-#undef STAILQ_LAST
-#define STAILQ_LAST(head, type, field) \
- (STAILQ_EMPTY((head)) ? \
- NULL : \
- ((struct type *)(void *) \
- ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
-
-#undef STAILQ_NEXT
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#undef STAILQ_REMOVE
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- if (STAILQ_FIRST((head)) == (elm)) { \
- STAILQ_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = STAILQ_FIRST((head)); \
- while (STAILQ_NEXT(curelm, field) != (elm)) \
- curelm = STAILQ_NEXT(curelm, field); \
- if ((STAILQ_NEXT(curelm, field) = \
- STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
- (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
- } \
-} while (0)
-
-#undef STAILQ_REMOVE_HEAD
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if ((STAILQ_FIRST((head)) = \
- STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-#undef STAILQ_REMOVE_HEAD_UNTIL
-#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
- if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
- (head)->stqh_last = &STAILQ_FIRST((head)); \
-} while (0)
-
-/*
- * List declarations.
- */
-#undef LIST_HEAD
-#define LIST_HEAD(name, type) \
-struct name { \
- struct type *lh_first; /* first element */ \
-}
-
-#undef LIST_HEAD_INITIALIZER
-#define LIST_HEAD_INITIALIZER(head) \
- { NULL }
-
-#undef LIST_ENTRY
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-
-#undef LIST_EMPTY
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#undef LIST_FIRST
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#undef LIST_FOREACH
-#define LIST_FOREACH(var, head, field) \
- for ((var) = LIST_FIRST((head)); \
- (var); \
- (var) = LIST_NEXT((var), field))
-
-#undef LIST_FOREACH_SAFE
-#define LIST_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = LIST_FIRST((head)); \
- (var) && ((tvar) = LIST_NEXT((var), field), 1); \
- (var) = (tvar))
-
-#undef LIST_INIT
-#define LIST_INIT(head) do { \
- LIST_FIRST((head)) = NULL; \
-} while (0)
-
-#undef LIST_INSERT_AFTER
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
- LIST_NEXT((listelm), field)->field.le_prev = \
- &LIST_NEXT((elm), field); \
- LIST_NEXT((listelm), field) = (elm); \
- (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
-} while (0)
-
-#undef LIST_INSERT_BEFORE
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- LIST_NEXT((elm), field) = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
-} while (0)
-
-#undef LIST_INSERT_HEAD
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
- LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
- LIST_FIRST((head)) = (elm); \
- (elm)->field.le_prev = &LIST_FIRST((head)); \
-} while (0)
-
-#undef LIST_NEXT
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#undef LIST_REMOVE
-#define LIST_REMOVE(elm, field) do { \
- if (LIST_NEXT((elm), field) != NULL) \
- LIST_NEXT((elm), field)->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = LIST_NEXT((elm), field); \
-} while (0)
-
-#endif /* !_QUEUE_H_ */
--- contrib/csup/pathcomp.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/pathcomp.h,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-#ifndef _PATHCOMP_H
-#define _PATHCOMP_H
-
-/* File types */
-#define PC_DIRDOWN 0
-#define PC_FILE 1
-#define PC_DIRUP 2
-
-struct pathcomp;
-
-struct pathcomp *pathcomp_new(void);
-int pathcomp_put(struct pathcomp *, int, char *);
-int pathcomp_get(struct pathcomp *, int *, char **);
-void pathcomp_finish(struct pathcomp *);
-void pathcomp_free(struct pathcomp *);
-
-#endif /* !_PATHCOMP_H */
--- contrib/csup/status.c
+++ /dev/null
@@ -1,842 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/status.c,v 1.1.1.1.2.1 2006/05/15 13:40:40 mux Exp $
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "fattr.h"
-#include "misc.h"
-#include "pathcomp.h"
-#include "proto.h"
-#include "queue.h"
-#include "status.h"
-#include "stream.h"
-
-#define STATUS_VERSION 5
-
-/* Internal error codes. */
-#define STATUS_ERR_READ (-1)
-#define STATUS_ERR_WRITE (-2)
-#define STATUS_ERR_PARSE (-3)
-#define STATUS_ERR_UNSORTED (-4)
-#define STATUS_ERR_TRUNC (-5)
-#define STATUS_ERR_BOGUS_DIRUP (-6)
-#define STATUS_ERR_BAD_TYPE (-7)
-#define STATUS_ERR_RENAME (-8)
-
-static struct status *status_new(char *, time_t, struct stream *);
-static struct statusrec *status_rd(struct status *);
-static struct statusrec *status_rdraw(struct status *, char **);
-static int status_wr(struct status *, struct statusrec *);
-static int status_wrraw(struct status *, struct statusrec *,
- char *);
-static struct status *status_fromrd(char *, struct stream *);
-static struct status *status_fromnull(char *);
-static void status_free(struct status *);
-
-static void statusrec_init(struct statusrec *);
-static void statusrec_fini(struct statusrec *);
-static int statusrec_cook(struct statusrec *, char *);
-static int statusrec_cmp(struct statusrec *, struct statusrec *);
-
-struct status {
- char *path;
- char *tempfile;
- int error;
- int suberror;
- struct pathcomp *pc;
- struct statusrec buf;
- struct statusrec *previous;
- struct statusrec *current;
- struct stream *rd;
- struct stream *wr;
- time_t scantime;
- int eof;
- int linenum;
- int depth;
- int dirty;
-};
-
-static void
-statusrec_init(struct statusrec *sr)
-{
-
- memset(sr, 0, sizeof(*sr));
-}
-
-static int
-statusrec_cook(struct statusrec *sr, char *line)
-{
- char *clientattr, *serverattr;
-
- switch (sr->sr_type) {
- case SR_DIRDOWN:
- /* Nothing to do. */
- if (line != NULL)
- return (-1);
- break;
- case SR_CHECKOUTLIVE:
- sr->sr_tag = proto_get_ascii(&line);
- sr->sr_date = proto_get_ascii(&line);
- serverattr = proto_get_ascii(&line);
- sr->sr_revnum = proto_get_ascii(&line);
- sr->sr_revdate = proto_get_ascii(&line);
- clientattr = proto_get_ascii(&line);
- if (clientattr == NULL || line != NULL)
- return (-1);
- sr->sr_serverattr = fattr_decode(serverattr);
- if (sr->sr_serverattr == NULL)
- return (-1);
- sr->sr_clientattr = fattr_decode(clientattr);
- if (sr->sr_clientattr == NULL) {
- fattr_free(sr->sr_serverattr);
- return (-1);
- }
- break;
- case SR_CHECKOUTDEAD:
- sr->sr_tag = proto_get_ascii(&line);
- sr->sr_date = proto_get_ascii(&line);
- serverattr = proto_get_ascii(&line);
- if (serverattr == NULL || line != NULL)
- return (-1);
- sr->sr_serverattr = fattr_decode(serverattr);
- if (sr->sr_serverattr == NULL)
- return (-1);
- break;
- case SR_DIRUP:
- clientattr = proto_get_ascii(&line);
- if (clientattr == NULL || line != NULL)
- return (-1);
- sr->sr_clientattr = fattr_decode(clientattr);
- if (sr->sr_clientattr == NULL)
- return (-1);
- break;
- default:
- return (-1);
- }
- return (0);
-}
-
-static struct statusrec *
-status_rd(struct status *st)
-{
- struct statusrec *sr;
- char *line;
- int error;
-
- sr = status_rdraw(st, &line);
- if (sr == NULL)
- return (NULL);
- error = statusrec_cook(sr, line);
- if (error) {
- st->error = STATUS_ERR_PARSE;
- return (NULL);
- }
- return (sr);
-}
-
-static struct statusrec *
-status_rdraw(struct status *st, char **linep)
-{
- struct statusrec sr;
- char *cmd, *line, *file;
-
- if (st->rd == NULL || st->eof)
- return (NULL);
- line = stream_getln(st->rd, NULL);
- if (line == NULL) {
- if (stream_eof(st->rd)) {
- if (st->depth != 0) {
- st->error = STATUS_ERR_TRUNC;
- return (NULL);
- }
- st->eof = 1;
- return (NULL);
- }
- st->error = STATUS_ERR_READ;
- st->suberror = errno;
- return (NULL);
- }
- st->linenum++;
- cmd = proto_get_ascii(&line);
- file = proto_get_ascii(&line);
- if (file == NULL || strlen(cmd) != 1) {
- st->error = STATUS_ERR_PARSE;
- return (NULL);
- }
-
- switch (cmd[0]) {
- case 'D':
- sr.sr_type = SR_DIRDOWN;
- st->depth++;
- break;
- case 'C':
- sr.sr_type = SR_CHECKOUTLIVE;
- break;
- case 'c':
- sr.sr_type = SR_CHECKOUTDEAD;
- break;
- case 'U':
- sr.sr_type = SR_DIRUP;
- if (st->depth <= 0) {
- st->error = STATUS_ERR_BOGUS_DIRUP;
- return (NULL);
- }
- st->depth--;
- break;
- default:
- st->error = STATUS_ERR_BAD_TYPE;
- st->suberror = cmd[0];
- return (NULL);
- }
-
- sr.sr_file = xstrdup(file);
- if (st->previous != NULL &&
- statusrec_cmp(st->previous, &sr) >= 0) {
- st->error = STATUS_ERR_UNSORTED;
- free(sr.sr_file);
- return (NULL);
- }
-
- if (st->previous == NULL) {
- st->previous = &st->buf;
- } else {
- statusrec_fini(st->previous);
- statusrec_init(st->previous);
- }
- st->previous->sr_type = sr.sr_type;
- st->previous->sr_file = sr.sr_file;
- *linep = line;
- return (st->previous);
-}
-
-static int
-status_wr(struct status *st, struct statusrec *sr)
-{
- struct pathcomp *pc;
- const struct fattr *fa;
- char *name;
- int error, type, usedirupattr;
-
- pc = st->pc;
- error = 0;
- usedirupattr = 0;
- if (sr->sr_type == SR_DIRDOWN) {
- pathcomp_put(pc, PC_DIRDOWN, sr->sr_file);
- } else if (sr->sr_type == SR_DIRUP) {
- pathcomp_put(pc, PC_DIRUP, sr->sr_file);
- usedirupattr = 1;
- } else {
- pathcomp_put(pc, PC_FILE, sr->sr_file);
- }
-
- while (pathcomp_get(pc, &type, &name)) {
- if (type == PC_DIRDOWN) {
- error = proto_printf(st->wr, "D %s\n", name);
- } else if (type == PC_DIRUP) {
- if (usedirupattr)
- fa = sr->sr_clientattr;
- else
- fa = fattr_bogus;
- usedirupattr = 0;
- error = proto_printf(st->wr, "U %s %f\n", name, fa);
- }
- if (error)
- goto bad;
- }
-
- switch (sr->sr_type) {
- case SR_DIRDOWN:
- case SR_DIRUP:
- /* Already emitted above. */
- break;
- case SR_CHECKOUTLIVE:
- error = proto_printf(st->wr, "C %s %s %s %f %s %s %f\n",
- sr->sr_file, sr->sr_tag, sr->sr_date, sr->sr_serverattr,
- sr->sr_revnum, sr->sr_revdate, sr->sr_clientattr);
- break;
- case SR_CHECKOUTDEAD:
- error = proto_printf(st->wr, "c %s %s %s %f\n", sr->sr_file,
- sr->sr_tag, sr->sr_date, sr->sr_serverattr);
- break;
- }
- if (error)
- goto bad;
- return (0);
-bad:
- st->error = STATUS_ERR_WRITE;
- st->suberror = errno;
- return (-1);
-}
-
-static int
-status_wrraw(struct status *st, struct statusrec *sr, char *line)
-{
- char *name;
- char cmd;
- int error, ret, type;
-
- if (st->wr == NULL)
- return (0);
-
- /*
- * Keep the compressor in sync. At this point, the necessary
- * DirDowns and DirUps should have already been emitted, so the
- * compressor should return exactly one value in the PC_DIRDOWN
- * and PC_DIRUP case and none in the PC_FILE case.
- */
- if (sr->sr_type == SR_DIRDOWN)
- pathcomp_put(st->pc, PC_DIRDOWN, sr->sr_file);
- else if (sr->sr_type == SR_DIRUP)
- pathcomp_put(st->pc, PC_DIRUP, sr->sr_file);
- else
- pathcomp_put(st->pc, PC_FILE, sr->sr_file);
- if (sr->sr_type == SR_DIRDOWN || sr->sr_type == SR_DIRUP) {
- ret = pathcomp_get(st->pc, &type, &name);
- assert(ret);
- if (sr->sr_type == SR_DIRDOWN)
- assert(type == PC_DIRDOWN);
- else
- assert(type == PC_DIRUP);
- }
- ret = pathcomp_get(st->pc, &type, &name);
- assert(!ret);
-
- switch (sr->sr_type) {
- case SR_DIRDOWN:
- cmd = 'D';
- break;
- case SR_DIRUP:
- cmd = 'U';
- break;
- case SR_CHECKOUTLIVE:
- cmd = 'C';
- break;
- case SR_CHECKOUTDEAD:
- cmd = 'c';
- break;
- default:
- assert(0);
- return (-1);
- }
- if (sr->sr_type == SR_DIRDOWN)
- error = proto_printf(st->wr, "%c %S\n", cmd, sr->sr_file);
- else
- error = proto_printf(st->wr, "%c %s %S\n", cmd, sr->sr_file,
- line);
- if (error) {
- st->error = STATUS_ERR_WRITE;
- st->suberror = errno;
- return (-1);
- }
- return (0);
-}
-
-static void
-statusrec_fini(struct statusrec *sr)
-{
-
- fattr_free(sr->sr_serverattr);
- fattr_free(sr->sr_clientattr);
- free(sr->sr_file);
-}
-
-static int
-statusrec_cmp(struct statusrec *a, struct statusrec *b)
-{
- size_t lena, lenb;
-
- if (a->sr_type == SR_DIRUP || b->sr_type == SR_DIRUP) {
- lena = strlen(a->sr_file);
- lenb = strlen(b->sr_file);
- if (a->sr_type == SR_DIRUP &&
- ((lena < lenb && b->sr_file[lena] == '/') || lena == lenb)
- && strncmp(a->sr_file, b->sr_file, lena) == 0)
- return (1);
- if (b->sr_type == SR_DIRUP &&
- ((lenb < lena && a->sr_file[lenb] == '/') || lenb == lena)
- && strncmp(a->sr_file, b->sr_file, lenb) == 0)
- return (-1);
- }
- return (pathcmp(a->sr_file, b->sr_file));
-}
-
-static struct status *
-status_new(char *path, time_t scantime, struct stream *file)
-{
- struct status *st;
-
- st = xmalloc(sizeof(struct status));
- st->path = path;
- st->error = 0;
- st->suberror = 0;
- st->tempfile = NULL;
- st->scantime = scantime;
- st->rd = file;
- st->wr = NULL;
- st->previous = NULL;
- st->current = NULL;
- st->dirty = 0;
- st->eof = 0;
- st->linenum = 0;
- st->depth = 0;
- st->pc = pathcomp_new();
- statusrec_init(&st->buf);
- return (st);
-}
-
-static void
-status_free(struct status *st)
-{
-
- if (st->previous != NULL)
- statusrec_fini(st->previous);
- if (st->rd != NULL)
- stream_close(st->rd);
- if (st->wr != NULL)
- stream_close(st->wr);
- if (st->tempfile != NULL)
- free(st->tempfile);
- free(st->path);
- pathcomp_free(st->pc);
- free(st);
-}
-
-static struct status *
-status_fromrd(char *path, struct stream *file)
-{
- struct status *st;
- char *id, *line;
- time_t scantime;
- int error, ver;
-
- /* Get the first line of the file and validate it. */
- line = stream_getln(file, NULL);
- if (line == NULL) {
- stream_close(file);
- return (NULL);
- }
- id = proto_get_ascii(&line);
- error = proto_get_int(&line, &ver, 10);
- if (error) {
- stream_close(file);
- return (NULL);
- }
- error = proto_get_time(&line, &scantime);
- if (error || line != NULL) {
- stream_close(file);
- return (NULL);
- }
-
- if (strcmp(id, "F") != 0 || ver != STATUS_VERSION) {
- stream_close(file);
- return (NULL);
- }
-
- st = status_new(path, scantime, file);
- st->linenum = 1;
- return (st);
-}
-
-static struct status *
-status_fromnull(char *path)
-{
- struct status *st;
-
- st = status_new(path, -1, NULL);
- st->eof = 1;
- return (st);
-}
-
-/*
- * Open the status file. If scantime is not -1, the file is opened
- * for updating, otherwise, it is opened read-only. If the status file
- * couldn't be opened, NULL is returned and errmsg is set to the error
- * message.
- */
-struct status *
-status_open(struct coll *coll, time_t scantime, char **errmsg)
-{
- struct status *st;
- struct stream *file;
- struct fattr *fa;
- char *destpath, *path;
- int error, rv;
-
- path = coll_statuspath(coll);
- file = stream_open_file(path, O_RDONLY);
- if (file == NULL) {
- if (errno != ENOENT) {
- xasprintf(errmsg, "Could not open \"%s\": %s\n",
- path, strerror(errno));
- free(path);
- return (NULL);
- }
- st = status_fromnull(path);
- } else {
- st = status_fromrd(path, file);
- if (st == NULL) {
- xasprintf(errmsg, "Error in \"%s\": Bad header line",
- path);
- free(path);
- return (NULL);
- }
- }
-
- if (scantime != -1) {
- /* Open for writing too. */
- xasprintf(&destpath, "%s/%s/%s/", coll->co_base,
- coll->co_colldir, coll->co_name);
- st->tempfile = tempname(destpath);
- if (mkdirhier(destpath, coll->co_umask) != 0) {
- xasprintf(errmsg, "Cannot create directories leading "
- "to \"%s\": %s", destpath, strerror(errno));
- free(destpath);
- status_free(st);
- return (NULL);
- }
- free(destpath);
- st->wr = stream_open_file(st->tempfile,
- O_CREAT | O_TRUNC | O_WRONLY, 0644);
- if (st->wr == NULL) {
- xasprintf(errmsg, "Cannot create \"%s\": %s",
- st->tempfile, strerror(errno));
- status_free(st);
- return (NULL);
- }
- fa = fattr_new(FT_FILE, -1);
- fattr_mergedefault(fa);
- fattr_umask(fa, coll->co_umask);
- rv = fattr_install(fa, st->tempfile, NULL);
- fattr_free(fa);
- if (rv == -1) {
- xasprintf(errmsg,
- "Cannot set attributes for \"%s\": %s",
- st->tempfile, strerror(errno));
- status_free(st);
- return (NULL);
- }
- if (scantime != st->scantime)
- st->dirty = 1;
- error = proto_printf(st->wr, "F %d %t\n", STATUS_VERSION,
- scantime);
- if (error) {
- st->error = STATUS_ERR_WRITE;
- st->suberror = errno;
- *errmsg = status_errmsg(st);
- status_free(st);
- return (NULL);
- }
- }
- return (st);
-}
-
-/*
- * Get an entry from the status file. If name is NULL, the next entry
- * is returned. If name is not NULL, the entry matching this name is
- * returned, or NULL if it couldn't be found. If deleteto is set to 1,
- * all the entries read from the status file while looking for the
- * given name are deleted.
- */
-int
-status_get(struct status *st, char *name, int isdirup, int deleteto,
- struct statusrec **psr)
-{
- struct statusrec key;
- struct statusrec *sr;
- char *line;
- int c, error;
-
- if (st->eof)
- return (0);
-
- if (st->error)
- return (-1);
-
- if (name == NULL) {
- sr = status_rd(st);
- if (sr == NULL) {
- if (st->error)
- return (-1);
- return (0);
- }
- *psr = sr;
- return (1);
- }
-
- if (st->current != NULL) {
- sr = st->current;
- st->current = NULL;
- } else {
- sr = status_rd(st);
- if (sr == NULL) {
- if (st->error)
- return (-1);
- return (0);
- }
- }
-
- key.sr_file = name;
- if (isdirup)
- key.sr_type = SR_DIRUP;
- else
- key.sr_type = SR_CHECKOUTLIVE;
-
- c = statusrec_cmp(sr, &key);
- if (c < 0) {
- if (st->wr != NULL && !deleteto) {
- error = status_wr(st, sr);
- if (error)
- return (-1);
- }
- /* Loop until we find the good entry. */
- for (;;) {
- sr = status_rdraw(st, &line);
- if (sr == NULL) {
- if (st->error)
- return (-1);
- return (0);
- }
- c = statusrec_cmp(sr, &key);
- if (c >= 0)
- break;
- if (st->wr != NULL && !deleteto) {
- error = status_wrraw(st, sr, line);
- if (error)
- return (-1);
- }
- }
- error = statusrec_cook(sr, line);
- if (error) {
- st->error = STATUS_ERR_PARSE;
- return (-1);
- }
- }
- st->current = sr;
- if (c != 0)
- return (0);
- *psr = sr;
- return (1);
-}
-
-/*
- * Put this entry into the status file. If an entry with the same name
- * existed in the status file, it is replaced by this one, otherwise,
- * the entry is added to the status file.
- */
-int
-status_put(struct status *st, struct statusrec *sr)
-{
- struct statusrec *old;
- int error, ret;
-
- ret = status_get(st, sr->sr_file, sr->sr_type == SR_DIRUP, 0, &old);
- if (ret == -1)
- return (-1);
- if (ret) {
- if (old->sr_type == SR_DIRDOWN) {
- /* DirUp should never match DirDown */
- assert(old->sr_type != SR_DIRUP);
- if (sr->sr_type == SR_CHECKOUTLIVE ||
- sr->sr_type == SR_CHECKOUTDEAD) {
- /* We are replacing a directory with a file.
- Delete all entries inside the directory we
- are replacing. */
- ret = status_get(st, sr->sr_file, 1, 1, &old);
- if (ret == -1)
- return (-1);
- assert(ret);
- }
- } else
- st->current = NULL;
- }
- st->dirty = 1;
- error = status_wr(st, sr);
- if (error)
- return (-1);
- return (0);
-}
-
-/*
- * Delete the specified entry from the status file.
- */
-int
-status_delete(struct status *st, char *name, int isdirup)
-{
- struct statusrec *sr;
- int ret;
-
- ret = status_get(st, name, isdirup, 0, &sr);
- if (ret == -1)
- return (-1);
- if (ret) {
- st->current = NULL;
- st->dirty = 1;
- }
- return (0);
-}
-
-/*
- * Check whether we hit the end of file.
- */
-int
-status_eof(struct status *st)
-{
-
- return (st->eof);
-}
-
-/*
- * Returns the error message if there was an error, otherwise returns
- * NULL. The error message is allocated dynamically and needs to be
- * freed by the caller after use.
- */
-char *
-status_errmsg(struct status *st)
-{
- char *errmsg;
-
- if (!st->error)
- return (NULL);
- switch (st->error) {
- case STATUS_ERR_READ:
- xasprintf(&errmsg, "Read failure on \"%s\": %s",
- st->path, strerror(st->suberror));
- break;
- case STATUS_ERR_WRITE:
- xasprintf(&errmsg, "Write failure on \"%s\": %s",
- st->tempfile, strerror(st->suberror));
- break;
- case STATUS_ERR_PARSE:
- xasprintf(&errmsg, "Error in \"%s\": %d: "
- "Could not parse status record", st->path, st->linenum);
- break;
- case STATUS_ERR_UNSORTED:
- xasprintf(&errmsg, "Error in \"%s\": %d: "
- "File is not sorted properly", st->path, st->linenum);
- break;
- case STATUS_ERR_TRUNC:
- xasprintf(&errmsg, "Error in \"%s\": "
- "File is truncated", st->path);
- break;
- case STATUS_ERR_BOGUS_DIRUP:
- xasprintf(&errmsg, "Error in \"%s\": %d: "
- "\"U\" entry has no matching \"D\"", st->path, st->linenum);
- break;
- case STATUS_ERR_BAD_TYPE:
- xasprintf(&errmsg, "Error in \"%s\": %d: "
- "Invalid file type \"%c\"", st->path, st->linenum,
- st->suberror);
- break;
- case STATUS_ERR_RENAME:
- xasprintf(&errmsg, "Cannot rename \"%s\" to \"%s\": %s",
- st->tempfile, st->path, strerror(st->suberror));
- break;
- default:
- assert(0);
- return (NULL);
- }
- return (errmsg);
-}
-
-/*
- * Close the status file and free any resource associated with it.
- * It is OK to pass NULL for errmsg only if the status file was
- * opened read-only. If it wasn't opened read-only, status_close()
- * can produce an error and errmsg is not allowed to be NULL. If
- * there was no errors, errmsg is set to NULL.
- */
-void
-status_close(struct status *st, char **errmsg)
-{
- struct statusrec *sr;
- char *line, *name;
- int error, type;
-
- if (st->wr != NULL) {
- if (st->dirty) {
- if (st->current != NULL) {
- error = status_wr(st, st->current);
- if (error) {
- *errmsg = status_errmsg(st);
- goto bad;
- }
- st->current = NULL;
- }
- /* Copy the rest of the file. */
- while ((sr = status_rdraw(st, &line)) != NULL) {
- error = status_wrraw(st, sr, line);
- if (error) {
- *errmsg = status_errmsg(st);
- goto bad;
- }
- }
- if (st->error) {
- *errmsg = status_errmsg(st);
- goto bad;
- }
-
- /* Close off all the open directories. */
- pathcomp_finish(st->pc);
- while (pathcomp_get(st->pc, &type, &name)) {
- assert(type == PC_DIRUP);
- error = proto_printf(st->wr, "U %s %f\n",
- name, fattr_bogus);
- if (error) {
- st->error = STATUS_ERR_WRITE;
- st->suberror = errno;
- *errmsg = status_errmsg(st);
- goto bad;
- }
- }
-
- /* Rename tempfile. */
- error = rename(st->tempfile, st->path);
- if (error) {
- st->error = STATUS_ERR_RENAME;
- st->suberror = errno;
- *errmsg = status_errmsg(st);
- goto bad;
- }
- } else {
- /* Just discard the tempfile. */
- unlink(st->tempfile);
- }
- *errmsg = NULL;
- }
- status_free(st);
- return;
-bad:
- status_free(st);
-}
--- contrib/csup/parse.y
+++ /dev/null
@@ -1,91 +0,0 @@
-%{
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/parse.y,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/types.h>
-
-#include "config.h"
-#include "token.h"
-
-%}
-
-%union {
- char *str;
- int i;
-}
-
-%token DEFAULT
-%token <i> NAME
-%token <i> BOOLEAN
-%token EQUAL
-%token <str> STRING
-
-%%
-
-config_file
- : config_list
- |
- ;
-
-config_list
- : config
- | config_list config
- ;
-
-config
- : default_line
- | collection
- ;
-
-default_line
- : DEFAULT options
- { coll_setdef(); }
- ;
-
-collection
- : STRING options
- { coll_add($1); }
- ;
-
-options
- :
- | options option
- ;
-
-option
- : BOOLEAN
- { coll_setopt($1, NULL); }
- | value
- ;
-
-value
- : NAME EQUAL STRING
- { coll_setopt($1, $3); }
- ;
-
-%%
--- contrib/csup/detailer.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/detailer.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "detailer.h"
-#include "fixups.h"
-#include "misc.h"
-#include "mux.h"
-#include "proto.h"
-#include "status.h"
-#include "stream.h"
-
-/* Internal error codes. */
-#define DETAILER_ERR_PROTO (-1) /* Protocol error. */
-#define DETAILER_ERR_MSG (-2) /* Error is in detailer->errmsg. */
-#define DETAILER_ERR_READ (-3) /* Error reading from server. */
-#define DETAILER_ERR_WRITE (-4) /* Error writing to server. */
-
-struct detailer {
- struct config *config;
- struct stream *rd;
- struct stream *wr;
- char *errmsg;
-};
-
-static int detailer_batch(struct detailer *);
-static int detailer_coll(struct detailer *, struct coll *,
- struct status *);
-static int detailer_dofile(struct detailer *, struct coll *,
- struct status *, char *);
-
-void *
-detailer(void *arg)
-{
- struct thread_args *args;
- struct detailer dbuf, *d;
- int error;
-
- args = arg;
-
- d = &dbuf;
- d->config = args->config;
- d->rd = args->rd;
- d->wr = args->wr;
- d->errmsg = NULL;
-
- error = detailer_batch(d);
- switch (error) {
- case DETAILER_ERR_PROTO:
- xasprintf(&args->errmsg, "Detailer failed: Protocol error");
- args->status = STATUS_FAILURE;
- break;
- case DETAILER_ERR_MSG:
- xasprintf(&args->errmsg, "Detailer failed: %s", d->errmsg);
- free(d->errmsg);
- args->status = STATUS_FAILURE;
- break;
- case DETAILER_ERR_READ:
- if (stream_eof(d->rd)) {
- xasprintf(&args->errmsg, "Detailer failed: "
- "Premature EOF from server");
- } else {
- xasprintf(&args->errmsg, "Detailer failed: "
- "Network read failure: %s", strerror(errno));
- }
- args->status = STATUS_TRANSIENTFAILURE;
- break;
- case DETAILER_ERR_WRITE:
- xasprintf(&args->errmsg, "Detailer failed: "
- "Network write failure: %s", strerror(errno));
- args->status = STATUS_TRANSIENTFAILURE;
- break;
- default:
- assert(error == 0);
- args->status = STATUS_SUCCESS;
- }
- return (NULL);
-}
-
-static int
-detailer_batch(struct detailer *d)
-{
- struct config *config;
- struct stream *rd, *wr;
- struct coll *coll;
- struct status *st;
- struct fixup *fixup;
- char *cmd, *collname, *line, *release;
- int error, fixupseof;
-
- config = d->config;
- rd = d->rd;
- wr = d->wr;
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- if (coll->co_options & CO_SKIP)
- continue;
- line = stream_getln(rd, NULL);
- cmd = proto_get_ascii(&line);
- collname = proto_get_ascii(&line);
- release = proto_get_ascii(&line);
- error = proto_get_time(&line, &coll->co_scantime);
- if (error || line != NULL || strcmp(cmd, "COLL") != 0 ||
- strcmp(collname, coll->co_name) != 0 ||
- strcmp(release, coll->co_release) != 0)
- return (DETAILER_ERR_PROTO);
- error = proto_printf(wr, "COLL %s %s\n", coll->co_name,
- coll->co_release);
- if (error)
- return (DETAILER_ERR_WRITE);
- stream_flush(wr);
- if (coll->co_options & CO_COMPRESS) {
- stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL);
- stream_filter_start(wr, STREAM_FILTER_ZLIB, NULL);
- }
- st = status_open(coll, -1, &d->errmsg);
- if (st == NULL)
- return (DETAILER_ERR_MSG);
- error = detailer_coll(d, coll, st);
- status_close(st, NULL);
- if (error)
- return (error);
- if (coll->co_options & CO_COMPRESS) {
- stream_filter_stop(rd);
- stream_filter_stop(wr);
- }
- stream_flush(wr);
- }
- line = stream_getln(rd, NULL);
- if (line == NULL)
- return (DETAILER_ERR_READ);
- if (strcmp(line, ".") != 0)
- return (DETAILER_ERR_PROTO);
- error = proto_printf(wr, ".\n");
- if (error)
- return (DETAILER_ERR_WRITE);
- stream_flush(wr);
-
- /* Now send fixups if needed. */
- fixup = NULL;
- fixupseof = 0;
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- if (coll->co_options & CO_SKIP)
- continue;
- error = proto_printf(wr, "COLL %s %s\n", coll->co_name,
- coll->co_release);
- if (error)
- return (DETAILER_ERR_WRITE);
- if (coll->co_options & CO_COMPRESS)
- stream_filter_start(wr, STREAM_FILTER_ZLIB, NULL);
- while (!fixupseof) {
- if (fixup == NULL)
- fixup = fixups_get(config->fixups);
- if (fixup == NULL) {
- fixupseof = 1;
- break;
- }
- if (fixup->f_coll != coll)
- break;
- error = proto_printf(wr, "Y %s %s %s\n", fixup->f_name,
- coll->co_tag, coll->co_date);
- if (error)
- return (DETAILER_ERR_WRITE);
- fixup = NULL;
- }
- error = proto_printf(wr, ".\n");
- if (error)
- return (DETAILER_ERR_WRITE);
- if (coll->co_options & CO_COMPRESS)
- stream_filter_stop(wr);
- stream_flush(wr);
- }
- error = proto_printf(wr, ".\n");
- if (error)
- return (DETAILER_ERR_WRITE);
- return (0);
-}
-
-static int
-detailer_coll(struct detailer *d, struct coll *coll, struct status *st)
-{
- struct stream *rd, *wr;
- char *cmd, *file, *line, *msg;
- int error;
-
- rd = d->rd;
- wr = d->wr;
- line = stream_getln(rd, NULL);
- if (line == NULL)
- return (DETAILER_ERR_READ);
- while (strcmp(line, ".") != 0) {
- cmd = proto_get_ascii(&line);
- if (cmd == NULL || strlen(cmd) != 1)
- return (DETAILER_ERR_PROTO);
- switch (cmd[0]) {
- case 'D':
- /* Delete file. */
- file = proto_get_ascii(&line);
- if (file == NULL || line != NULL)
- return (DETAILER_ERR_PROTO);
- error = proto_printf(wr, "D %s\n", file);
- if (error)
- return (DETAILER_ERR_WRITE);
- break;
- case 'U':
- /* Add or update file. */
- file = proto_get_ascii(&line);
- if (file == NULL || line != NULL)
- return (DETAILER_ERR_PROTO);
- error = detailer_dofile(d, coll, st, file);
- if (error)
- return (error);
- break;
- case '!':
- /* Warning from server. */
- msg = proto_get_rest(&line);
- if (msg == NULL)
- return (DETAILER_ERR_PROTO);
- lprintf(-1, "Server warning: %s\n", msg);
- break;
- default:
- return (DETAILER_ERR_PROTO);
- }
- stream_flush(wr);
- line = stream_getln(rd, NULL);
- if (line == NULL)
- return (DETAILER_ERR_READ);
- }
- error = proto_printf(wr, ".\n");
- if (error)
- return (DETAILER_ERR_WRITE);
- return (0);
-}
-
-static int
-detailer_dofile(struct detailer *d, struct coll *coll, struct status *st,
- char *file)
-{
- char md5[MD5_DIGEST_SIZE];
- struct stream *wr;
- struct fattr *fa;
- struct statusrec *sr;
- char *path;
- int error, ret;
-
- wr = d->wr;
- path = checkoutpath(coll->co_prefix, file);
- if (path == NULL)
- return (DETAILER_ERR_PROTO);
- fa = fattr_frompath(path, FATTR_NOFOLLOW);
- if (fa == NULL) {
- /* We don't have the file, so the only option at this
- point is to tell the server to send it. The server
- may figure out that the file is dead, in which case
- it will tell us. */
- error = proto_printf(wr, "C %s %s %s\n",
- file, coll->co_tag, coll->co_date);
- free(path);
- if (error)
- return (DETAILER_ERR_WRITE);
- return (0);
- }
- ret = status_get(st, file, 0, 0, &sr);
- if (ret == -1) {
- d->errmsg = status_errmsg(st);
- free(path);
- return (DETAILER_ERR_MSG);
- }
- if (ret == 0)
- sr = NULL;
-
- /* If our recorded information doesn't match the file that the
- client has, then ignore the recorded information. */
- if (sr != NULL && (sr->sr_type != SR_CHECKOUTLIVE ||
- !fattr_equal(sr->sr_clientattr, fa)))
- sr = NULL;
- fattr_free(fa);
- if (sr != NULL && strcmp(sr->sr_revdate, ".") != 0) {
- error = proto_printf(wr, "U %s %s %s %s %s\n", file,
- coll->co_tag, coll->co_date, sr->sr_revnum, sr->sr_revdate);
- free(path);
- if (error)
- return (DETAILER_ERR_WRITE);
- return (0);
- }
-
- /*
- * We don't have complete and/or accurate recorded information
- * about what version of the file we have. Compute the file's
- * checksum as an aid toward identifying which version it is.
- */
- error = MD5_File(path, md5);
- if (error) {
- xasprintf(&d->errmsg,
- "Cannot calculate checksum for \"%s\": %s", path,
- strerror(errno));
- return (DETAILER_ERR_MSG);
- }
- free(path);
- if (sr == NULL) {
- error = proto_printf(wr, "S %s %s %s %s\n", file,
- coll->co_tag, coll->co_date, md5);
- } else {
- error = proto_printf(wr, "s %s %s %s %s %s\n", file,
- coll->co_tag, coll->co_date, sr->sr_revnum, md5);
- }
- if (error)
- return (DETAILER_ERR_WRITE);
- return (0);
-}
--- contrib/csup/mux.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 2003-2004, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/mux.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _MUX_H_
-#define _MUX_H_
-
-struct mux;
-struct chan;
-
-struct mux *mux_open(int, struct chan **);
-void mux_shutdown(struct mux *, const char *, int);
-int mux_close(struct mux *);
-
-void chan_wait(struct chan *);
-int chan_listen(struct mux *);
-struct chan *chan_accept(struct mux *, int);
-ssize_t chan_read(struct chan *, void *, size_t);
-ssize_t chan_write(struct chan *, const void *, size_t);
-int chan_close(struct chan *);
-
-#endif /* !_MUX_H_ */
--- contrib/csup/fattr.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/fattr.h,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#ifndef _FATTR_H_
-#define _FATTR_H_
-
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <time.h>
-
-/*
- * File types.
- */
-#define FT_UNKNOWN 0 /* Unknown file type. */
-#define FT_FILE 1 /* Regular file. */
-#define FT_DIRECTORY 2 /* Directory. */
-#define FT_CDEV 3 /* Character device. */
-#define FT_BDEV 4 /* Block device. */
-#define FT_SYMLINK 5 /* Symbolic link. */
-#define FT_MAX FT_SYMLINK /* Maximum file type number. */
-#define FT_NUMBER (FT_MAX + 1) /* Number of file types. */
-
-/*
- * File attributes.
- */
-#define FA_FILETYPE 0x0001 /* True for all supported file types. */
-#define FA_MODTIME 0x0002 /* Last file modification time. */
-#define FA_SIZE 0x0004 /* Size of the file. */
-#define FA_LINKTARGET 0x0008 /* Target of a symbolic link. */
-#define FA_RDEV 0x0010 /* Device for a device node. */
-#define FA_OWNER 0x0020 /* Owner of the file. */
-#define FA_GROUP 0x0040 /* Group of the file. */
-#define FA_MODE 0x0080 /* File permissions. */
-#define FA_FLAGS 0x0100 /* 4.4BSD flags, a la chflags(2). */
-#define FA_LINKCOUNT 0x0200 /* Hard link count. */
-#define FA_DEV 0x0400 /* Device holding the inode. */
-#define FA_INODE 0x0800 /* Inode number. */
-
-#define FA_MASK 0x0fff
-
-#define FA_NUMBER 12 /* Number of file attributes. */
-
-/* Attributes that we might be able to change. */
-#define FA_CHANGEABLE (FA_MODTIME | FA_OWNER | FA_GROUP | FA_MODE | FA_FLAGS)
-
-/*
- * Attributes that we don't want to save in the "checkouts" file
- * when in checkout mode.
- */
-#define FA_COIGNORE (FA_MASK & ~(FA_FILETYPE|FA_MODTIME|FA_SIZE|FA_MODE))
-
-/* These are for fattr_frompath(). */
-#define FATTR_FOLLOW 0
-#define FATTR_NOFOLLOW 1
-
-struct stat;
-struct fattr;
-
-typedef int fattr_support_t[FT_NUMBER];
-
-extern const struct fattr *fattr_bogus;
-
-void fattr_init(void);
-void fattr_fini(void);
-
-struct fattr *fattr_new(int, time_t);
-struct fattr *fattr_default(int);
-struct fattr *fattr_fromstat(struct stat *);
-struct fattr *fattr_frompath(const char *, int);
-struct fattr *fattr_fromfd(int);
-struct fattr *fattr_decode(char *);
-struct fattr *fattr_forcheckout(const struct fattr *, mode_t);
-struct fattr *fattr_dup(const struct fattr *);
-char *fattr_encode(const struct fattr *, fattr_support_t, int);
-int fattr_type(const struct fattr *);
-void fattr_maskout(struct fattr *, int);
-int fattr_getmask(const struct fattr *);
-nlink_t fattr_getlinkcount(const struct fattr *);
-void fattr_umask(struct fattr *, mode_t);
-void fattr_merge(struct fattr *, const struct fattr *);
-void fattr_mergedefault(struct fattr *);
-void fattr_override(struct fattr *, const struct fattr *, int);
-int fattr_makenode(const struct fattr *, const char *);
-int fattr_delete(const char *path);
-int fattr_install(struct fattr *, const char *, const char *);
-int fattr_equal(const struct fattr *, const struct fattr *);
-void fattr_free(struct fattr *);
-int fattr_supported(int);
-
-#endif /* !_FATTR_H_ */
--- contrib/csup/attrstack.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $Id$
- */
-#ifndef _ATTRSTACK_H_
-#define _ATTRSTACK_H_
-
-struct fattr;
-struct attrstack;
-
-struct attrstack *attrstack_new(void);
-void attrstack_push(struct attrstack *, struct fattr *);
-struct fattr *attrstack_pop(struct attrstack *);
-size_t attrstack_size(struct attrstack *);
-void attrstack_free(struct attrstack *);
-
-#endif /* !_ATTRSTACK_H_ */
--- contrib/csup/config.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/*-
- * Copyright (c) 2003-2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/config.c,v 1.1.1.2.2.1 2006/05/15 13:40:39 mux Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "config.h"
-#include "globtree.h"
-#include "keyword.h"
-#include "misc.h"
-#include "parse.h"
-#include "stream.h"
-#include "token.h"
-
-static int config_parse_refusefiles(struct coll *);
-static int config_parse_refusefile(struct coll *, char *);
-
-extern FILE *yyin;
-
-/* These are globals because I can't think of a better way with yacc. */
-static STAILQ_HEAD(, coll) colls;
-static struct coll *cur_coll;
-static struct coll *defaults;
-static struct coll *ovcoll;
-static int ovmask;
-static const char *cfgfile;
-
-/*
- * Extract all the configuration information from the config
- * file and some command line parameters.
- */
-struct config *
-config_init(const char *file, struct coll *override, int overridemask)
-{
- struct config *config;
- struct coll *coll;
- size_t slen;
- char *prefix;
- int error;
- mode_t mask;
-
- config = xmalloc(sizeof(struct config));
- memset(config, 0, sizeof(struct config));
- STAILQ_INIT(&colls);
-
- defaults = coll_new(NULL);
- /* Set the default umask. */
- mask = umask(0);
- umask(mask);
- defaults->co_umask = mask;
- ovcoll = override;
- ovmask = overridemask;
-
- /* Extract a list of collections from the configuration file. */
- cur_coll = coll_new(defaults);
- yyin = fopen(file, "r");
- if (yyin == NULL) {
- lprintf(-1, "Cannot open \"%s\": %s\n", file, strerror(errno));
- goto bad;
- }
- cfgfile = file;
- error = yyparse();
- fclose(yyin);
- if (error)
- goto bad;
-
- memcpy(&config->colls, &colls, sizeof(colls));
- if (STAILQ_EMPTY(&config->colls)) {
- lprintf(-1, "Empty supfile\n");
- goto bad;
- }
-
- /* Fixup the list of collections. */
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- if (coll->co_base == NULL)
- coll->co_base = xstrdup("/usr/local/etc/cvsup");
- if (coll->co_colldir == NULL)
- coll->co_colldir = "sup";
- if (coll->co_prefix == NULL) {
- coll->co_prefix = xstrdup(coll->co_base);
- /*
- * If prefix is not an absolute pathname, it is
- * interpreted relative to base.
- */
- } else if (coll->co_prefix[0] != '/') {
- slen = strlen(coll->co_base);
- if (slen > 0 && coll->co_base[slen - 1] != '/')
- xasprintf(&prefix, "%s/%s", coll->co_base,
- coll->co_prefix);
- else
- xasprintf(&prefix, "%s%s", coll->co_base,
- coll->co_prefix);
- free(coll->co_prefix);
- coll->co_prefix = prefix;
- }
- coll->co_prefixlen = strlen(coll->co_prefix);
- /* Determine whether to checksum RCS files or not. */
- if (coll->co_options & CO_EXACTRCS)
- coll->co_options |= CO_CHECKRCS;
- else
- coll->co_options &= ~CO_CHECKRCS;
- /* In recent versions, we always try to set the file modes. */
- coll->co_options |= CO_SETMODE;
- /* XXX We don't support the rsync updating algorithm yet. */
- coll->co_options |= CO_NORSYNC;
- error = config_parse_refusefiles(coll);
- if (error)
- goto bad;
- }
-
- coll_free(cur_coll);
- coll_free(defaults);
- config->host = STAILQ_FIRST(&config->colls)->co_host;
- return (config);
-bad:
- coll_free(cur_coll);
- coll_free(defaults);
- config_free(config);
- return (NULL);
-}
-
-int
-config_checkcolls(struct config *config)
-{
- char linkname[4];
- struct stat sb;
- struct coll *coll;
- int error, numvalid, ret;
-
- numvalid = 0;
- STAILQ_FOREACH(coll, &config->colls, co_next) {
- error = stat(coll->co_prefix, &sb);
- if (error || !S_ISDIR(sb.st_mode)) {
- /* Skip this collection, and warn about it unless its
- prefix is a symbolic link pointing to "SKIP". */
- coll->co_options |= CO_SKIP;
- ret = readlink(coll->co_prefix, linkname,
- sizeof(linkname));
- if (ret != 4 || memcmp(linkname, "SKIP", 4) != 0) {
- lprintf(-1,"Nonexistent prefix \"%s\" for "
- "%s/%s\n", coll->co_prefix, coll->co_name,
- coll->co_release);
- }
- continue;
- }
- numvalid++;
- }
- return (numvalid);
-}
-
-static int
-config_parse_refusefiles(struct coll *coll)
-{
- char *collstem, *suffix, *supdir, *path;
- int error;
-
- if (coll->co_colldir[0] == '/')
- supdir = xstrdup(coll->co_colldir);
- else
- xasprintf(&supdir, "%s/%s", coll->co_base, coll->co_colldir);
-
- /* First, the global refuse file that applies to all collections. */
- xasprintf(&path, "%s/refuse", supdir);
- error = config_parse_refusefile(coll, path);
- free(path);
- if (error) {
- free(supdir);
- return (error);
- }
-
- /* Next the per-collection refuse files that applies to all release/tag
- combinations. */
- xasprintf(&collstem, "%s/%s/refuse", supdir, coll->co_name);
- free(supdir);
- error = config_parse_refusefile(coll, collstem);
- if (error) {
- free(collstem);
- return (error);
- }
-
- /* Finally, the per-release and per-tag refuse file. */
- suffix = coll_statussuffix(coll);
- if (suffix != NULL) {
- xasprintf(&path, "%s%s", collstem, suffix);
- free(suffix);
- error = config_parse_refusefile(coll, path);
- free(path);
- }
- free(collstem);
- return (error);
-}
-
-/*
- * Parses a "refuse" file, and records the relevant information in
- * coll->co_refusals. If the file does not exist, it is silently
- * ignored.
- */
-static int
-config_parse_refusefile(struct coll *coll, char *path)
-{
- struct stream *rd;
- char *cp, *line, *pat;
-
- rd = stream_open_file(path, O_RDONLY);
- if (rd == NULL)
- return (0);
- while ((line = stream_getln(rd, NULL)) != NULL) {
- pat = line;
- for (;;) {
- /* Trim leading whitespace. */
- pat += strspn(pat, " \t");
- if (pat[0] == '\0')
- break;
- cp = strpbrk(pat, " \t");
- if (cp != NULL)
- *cp = '\0';
- pattlist_add(coll->co_refusals, pat);
- if (cp == NULL)
- break;
- pat = cp + 1;
- }
- }
- if (!stream_eof(rd)) {
- stream_close(rd);
- lprintf(-1, "Read failure from \"%s\": %s\n", path,
- strerror(errno));
- return (-1);
- }
- stream_close(rd);
- return (0);
-}
-
-void
-config_free(struct config *config)
-{
- struct coll *coll;
-
- while (!STAILQ_EMPTY(&config->colls)) {
- coll = STAILQ_FIRST(&config->colls);
- STAILQ_REMOVE_HEAD(&config->colls, co_next);
- coll_free(coll);
- }
- if (config->server != NULL)
- stream_close(config->server);
- if (config->laddr != NULL)
- free(config->laddr);
- free(config);
-}
-
-/* Create a new collection, inheriting options from the default collection. */
-struct coll *
-coll_new(struct coll *def)
-{
- struct coll *new;
-
- new = xmalloc(sizeof(struct coll));
- memset(new, 0, sizeof(struct coll));
- if (def != NULL) {
- new->co_options = def->co_options;
- new->co_umask = def->co_umask;
- if (def->co_host != NULL)
- new->co_host = xstrdup(def->co_host);
- if (def->co_base != NULL)
- new->co_base = xstrdup(def->co_base);
- if (def->co_date != NULL)
- new->co_date = xstrdup(def->co_date);
- if (def->co_prefix != NULL)
- new->co_prefix = xstrdup(def->co_prefix);
- if (def->co_release != NULL)
- new->co_release = xstrdup(def->co_release);
- if (def->co_tag != NULL)
- new->co_tag = xstrdup(def->co_tag);
- if (def->co_listsuffix != NULL)
- new->co_listsuffix = xstrdup(def->co_listsuffix);
- } else {
- new->co_tag = xstrdup(".");
- new->co_date = xstrdup(".");
- }
- new->co_keyword = keyword_new();
- new->co_accepts = pattlist_new();
- new->co_refusals = pattlist_new();
- new->co_attrignore = FA_DEV | FA_INODE;
- return (new);
-}
-
-void
-coll_override(struct coll *coll, struct coll *from, int mask)
-{
- size_t i;
- int newoptions, oldoptions;
-
- newoptions = from->co_options & mask;
- oldoptions = coll->co_options & (CO_MASK & ~mask);
-
- if (from->co_release != NULL) {
- if (coll->co_release != NULL)
- free(coll->co_release);
- coll->co_release = xstrdup(from->co_release);
- }
- if (from->co_host != NULL) {
- if (coll->co_host != NULL)
- free(coll->co_host);
- coll->co_host = xstrdup(from->co_host);
- }
- if (from->co_base != NULL) {
- if (coll->co_base != NULL)
- free(coll->co_base);
- coll->co_base = xstrdup(from->co_base);
- }
- if (from->co_colldir != NULL)
- coll->co_colldir = from->co_colldir;
- if (from->co_prefix != NULL) {
- if (coll->co_prefix != NULL)
- free(coll->co_prefix);
- coll->co_prefix = xstrdup(from->co_prefix);
- }
- if (newoptions & CO_CHECKOUTMODE) {
- if (from->co_tag != NULL) {
- if (coll->co_tag != NULL)
- free(coll->co_tag);
- coll->co_tag = xstrdup(from->co_tag);
- }
- if (from->co_date != NULL) {
- if (coll->co_date != NULL)
- free(coll->co_date);
- coll->co_date = xstrdup(from->co_date);
- }
- }
- if (from->co_listsuffix != NULL) {
- if (coll->co_listsuffix != NULL)
- free(coll->co_listsuffix);
- coll->co_listsuffix = xstrdup(from->co_listsuffix);
- }
- for (i = 0; i < pattlist_size(from->co_accepts); i++) {
- pattlist_add(coll->co_accepts,
- pattlist_get(from->co_accepts, i));
- }
- for (i = 0; i < pattlist_size(from->co_refusals); i++) {
- pattlist_add(coll->co_refusals,
- pattlist_get(from->co_refusals, i));
- }
- coll->co_options = oldoptions | newoptions;
-}
-
-char *
-coll_statussuffix(struct coll *coll)
-{
- const char *tag;
- char *suffix;
-
- if (coll->co_listsuffix != NULL) {
- xasprintf(&suffix, ".%s", coll->co_listsuffix);
- } else if (coll->co_options & CO_USERELSUFFIX) {
- if (coll->co_tag == NULL)
- tag = ".";
- else
- tag = coll->co_tag;
- if (coll->co_release != NULL) {
- if (coll->co_options & CO_CHECKOUTMODE) {
- xasprintf(&suffix, ".%s:%s",
- coll->co_release, tag);
- } else {
- xasprintf(&suffix, ".%s", coll->co_release);
- }
- } else if (coll->co_options & CO_CHECKOUTMODE) {
- xasprintf(&suffix, ":%s", tag);
- }
- } else
- suffix = NULL;
- return (suffix);
-}
-
-char *
-coll_statuspath(struct coll *coll)
-{
- char *path, *suffix;
-
- suffix = coll_statussuffix(coll);
- if (suffix != NULL) {
- if (coll->co_colldir[0] == '/')
- xasprintf(&path, "%s/%s/checkouts%s", coll->co_colldir,
- coll->co_name, suffix);
- else
- xasprintf(&path, "%s/%s/%s/checkouts%s", coll->co_base,
- coll->co_colldir, coll->co_name, suffix);
- } else {
- if (coll->co_colldir[0] == '/')
- xasprintf(&path, "%s/%s/checkouts", coll->co_colldir,
- coll->co_name);
- else
- xasprintf(&path, "%s/%s/%s/checkouts", coll->co_base,
- coll->co_colldir, coll->co_name);
- }
- free(suffix);
- return (path);
-}
-
-void
-coll_add(char *name)
-{
- struct coll *coll;
-
- cur_coll->co_name = name;
- coll_override(cur_coll, ovcoll, ovmask);
- if (cur_coll->co_release == NULL) {
- lprintf(-1, "Release not specified for collection "
- "\"%s\"\n", cur_coll->co_name);
- exit(1);
- }
- if (cur_coll->co_host == NULL) {
- lprintf(-1, "Host not specified for collection "
- "\"%s\"\n", cur_coll->co_name);
- exit(1);
- }
- if (!(cur_coll->co_options & CO_CHECKOUTMODE)) {
- lprintf(-1, "Client only supports checkout mode\n");
- exit(1);
- }
- if (!STAILQ_EMPTY(&colls)) {
- coll = STAILQ_LAST(&colls, coll, co_next);
- if (strcmp(coll->co_host, cur_coll->co_host) != 0) {
- lprintf(-1, "All \"host\" fields in the supfile "
- "must be the same\n");
- exit(1);
- }
- }
- STAILQ_INSERT_TAIL(&colls, cur_coll, co_next);
- cur_coll = coll_new(defaults);
-}
-
-void
-coll_free(struct coll *coll)
-{
-
- if (coll == NULL)
- return;
- if (coll->co_host != NULL)
- free(coll->co_host);
- if (coll->co_base != NULL)
- free(coll->co_base);
- if (coll->co_date != NULL)
- free(coll->co_date);
- if (coll->co_prefix != NULL)
- free(coll->co_prefix);
- if (coll->co_release != NULL)
- free(coll->co_release);
- if (coll->co_tag != NULL)
- free(coll->co_tag);
- if (coll->co_cvsroot != NULL)
- free(coll->co_cvsroot);
- if (coll->co_name != NULL)
- free(coll->co_name);
- if (coll->co_listsuffix != NULL)
- free(coll->co_listsuffix);
- keyword_free(coll->co_keyword);
- if (coll->co_dirfilter != NULL)
- globtree_free(coll->co_dirfilter);
- if (coll->co_dirfilter != NULL)
- globtree_free(coll->co_filefilter);
- if (coll->co_norsync != NULL)
- globtree_free(coll->co_norsync);
- if (coll->co_accepts != NULL)
- pattlist_free(coll->co_accepts);
- if (coll->co_refusals != NULL)
- pattlist_free(coll->co_refusals);
- free(coll);
-}
-
-void
-coll_setopt(int opt, char *value)
-{
- struct coll *coll;
- int error, mask;
-
- coll = cur_coll;
- switch (opt) {
- case PT_HOST:
- if (coll->co_host != NULL)
- free(coll->co_host);
- coll->co_host = value;
- break;
- case PT_BASE:
- if (coll->co_base != NULL)
- free(coll->co_base);
- coll->co_base = value;
- break;
- case PT_DATE:
- if (coll->co_date != NULL)
- free(coll->co_date);
- coll->co_date = value;
- coll->co_options |= CO_CHECKOUTMODE;
- break;
- case PT_PREFIX:
- if (coll->co_prefix != NULL)
- free(coll->co_prefix);
- coll->co_prefix = value;
- break;
- case PT_RELEASE:
- if (coll->co_release != NULL)
- free(coll->co_release);
- coll->co_release = value;
- break;
- case PT_TAG:
- if (coll->co_tag != NULL)
- free(coll->co_tag);
- coll->co_tag = value;
- coll->co_options |= CO_CHECKOUTMODE;
- break;
- case PT_LIST:
- if (strchr(value, '/') != NULL) {
- lprintf(-1, "Parse error in \"%s\": \"list\" suffix "
- "must not contain slashes\n", cfgfile);
- exit(1);
- }
- if (coll->co_listsuffix != NULL)
- free(coll->co_listsuffix);
- coll->co_listsuffix = value;
- break;
- case PT_UMASK:
- error = asciitoint(value, &mask, 8);
- free(value);
- if (error) {
- lprintf(-1, "Parse error in \"%s\": Invalid "
- "umask value\n", cfgfile);
- exit(1);
- }
- coll->co_umask = mask;
- break;
- case PT_USE_REL_SUFFIX:
- coll->co_options |= CO_USERELSUFFIX;
- break;
- case PT_DELETE:
- coll->co_options |= CO_DELETE | CO_EXACTRCS;
- break;
- case PT_COMPRESS:
- coll->co_options |= CO_COMPRESS;
- break;
- case PT_NORSYNC:
- coll->co_options |= CO_NORSYNC;
- break;
- }
-}
-
-/* Set "coll" as being the default collection. */
-void
-coll_setdef(void)
-{
-
- coll_free(defaults);
- defaults = cur_coll;
- cur_coll = coll_new(defaults);
-}
--- contrib/csup/idcache.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*-
- * Copyright (c) 2006, Maxime Henrion <mux at FreeBSD.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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
- *
- * $FreeBSD: src/contrib/csup/idcache.c,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
- */
-#include <sys/types.h>
-
-#include <assert.h>
-#include <grp.h>
-#include <pthread.h>
-#include <pwd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "idcache.h"
-#include "misc.h"
-
-/*
- * Constants and data structures used to implement the thread-safe
- * group and password file caches. Cache sizes must be prime.
- */
-#define UIDTONAME_SZ 317 /* Size of uid -> user name cache */
-#define NAMETOUID_SZ 317 /* Size of user name -> uid cache */
-#define GIDTONAME_SZ 317 /* Size of gid -> group name cache */
-#define NAMETOGID_SZ 317 /* Size of group name -> gid cache */
-
-/* Node structures used to cache lookups. */
-struct uidc {
- char *name; /* user name */
- uid_t uid; /* cached uid */
- int valid; /* is this a valid or a miss entry */
- struct uidc *next; /* for collisions */
-};
-
-struct gidc {
- char *name; /* group name */
- gid_t gid; /* cached gid */
- int valid; /* is this a valid or a miss entry */
- struct gidc *next; /* for collisions */
-};
-
-static struct uidc **uidtoname; /* uid to user name cache */
-static struct gidc **gidtoname; /* gid to group name cache */
-static struct uidc **nametouid; /* user name to uid cache */
-static struct gidc **nametogid; /* group name to gid cache */
-
-static pthread_mutex_t uid_mtx;
-static pthread_mutex_t gid_mtx;
-
-static void uid_lock(void);
-static void uid_unlock(void);
-static void gid_lock(void);
-static void gid_unlock(void);
-
-static uint32_t hash(const char *);
-
-/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
- as used by ELF for hashing function names. */
-static uint32_t
-hash(const char *name)
-{
- uint32_t g, h;
-
- h = 0;
- while(*name != '\0') {
- h = (h << 4) + *name++;
- if ((g = h & 0xF0000000)) {
- h ^= g >> 24;
- h &= 0x0FFFFFFF;
- }
- }
- return (h);
-}
-
-static void
-uid_lock(void)
-{
- int error;
-
- error = pthread_mutex_lock(&uid_mtx);
- assert(!error);
-}
-
-static void
-uid_unlock(void)
-{
- int error;
-
- error = pthread_mutex_unlock(&uid_mtx);
- assert(!error);
-}
-
-static void
-gid_lock(void)
-{
- int error;
-
- error = pthread_mutex_lock(&gid_mtx);
- assert(!error);
-}
-
-static void
-gid_unlock(void)
-{
- int error;
-
- error = pthread_mutex_unlock(&gid_mtx);
- assert(!error);
-}
-
-static void
-uidc_insert(struct uidc **tbl, struct uidc *uidc, uint32_t key)
-{
-
- uidc->next = tbl[key];
- tbl[key] = uidc;
-}
-
-static void
-gidc_insert(struct gidc **tbl, struct gidc *gidc, uint32_t key)
-{
-
- gidc->next = tbl[key];
- tbl[key] = gidc;
-}
-
-/* Return the user name for this uid, or NULL if it's not found. */
-char *
-getuserbyid(uid_t uid)
-{
- struct passwd *pw;
- struct uidc *uidc, *uidc2;
- uint32_t key, key2;
-
- key = uid % UIDTONAME_SZ;
- uid_lock();
- uidc = uidtoname[key];
- while (uidc != NULL) {
- if (uidc->uid == uid)
- break;
- uidc = uidc->next;
- }
-
- if (uidc == NULL) {
- /* We didn't find this uid, look it up and add it. */
- uidc = xmalloc(sizeof(struct uidc));
- uidc->uid = uid;
- pw = getpwuid(uid);
- if (pw != NULL) {
- /* This uid is in the password file. */
- uidc->name = xstrdup(pw->pw_name);
- uidc->valid = 1;
- /* Also add it to the name -> gid table. */
- uidc2 = xmalloc(sizeof(struct uidc));
- uidc2->uid = uid;
- uidc2->name = uidc->name; /* We reuse the pointer. */
- uidc2->valid = 1;
- key2 = hash(uidc->name) % NAMETOUID_SZ;
- uidc_insert(nametouid, uidc2, key2);
- } else {
- /* Add a miss entry for this uid. */
- uidc->name = NULL;
- uidc->valid = 0;
- }
- uidc_insert(uidtoname, uidc, key);
- }
- /* It is safe to unlock here since the cache structure
- is not going to get freed or changed. */
- uid_unlock();
- return (uidc->name);
-}
-
-/* Return the group name for this gid, or NULL if it's not found. */
-char *
-getgroupbyid(gid_t gid)
-{
- struct group *gr;
- struct gidc *gidc, *gidc2;
- uint32_t key, key2;
-
- key = gid % GIDTONAME_SZ;
- gid_lock();
- gidc = gidtoname[key];
- while (gidc != NULL) {
- if (gidc->gid == gid)
- break;
- gidc = gidc->next;
- }
-
- if (gidc == NULL) {
- /* We didn't find this gid, look it up and add it. */
- gidc = xmalloc(sizeof(struct gidc));
- gidc->gid = gid;
- gr = getgrgid(gid);
- if (gr != NULL) {
- /* This gid is in the group file. */
- gidc->name = xstrdup(gr->gr_name);
- gidc->valid = 1;
- /* Also add it to the name -> gid table. */
- gidc2 = xmalloc(sizeof(struct gidc));
- gidc2->gid = gid;
- gidc2->name = gidc->name; /* We reuse the pointer. */
- gidc2->valid = 1;
- key2 = hash(gidc->name) % NAMETOGID_SZ;
- gidc_insert(nametogid, gidc2, key2);
- } else {
- /* Add a miss entry for this gid. */
- gidc->name = NULL;
- gidc->valid = 0;
- }
- gidc_insert(gidtoname, gidc, key);
- }
- /* It is safe to unlock here since the cache structure
- is not going to get freed or changed. */
- gid_unlock();
- return (gidc->name);
-}
-
-/* Finds the uid for this user name. If it's found, the gid is stored
- in *uid and 0 is returned. Otherwise, -1 is returned. */
-int
-getuidbyname(const char *name, uid_t *uid)
-{
- struct passwd *pw;
- struct uidc *uidc, *uidc2;
- uint32_t key, key2;
-
- uid_lock();
- key = hash(name) % NAMETOUID_SZ;
- uidc = nametouid[key];
- while (uidc != NULL) {
- if (strcmp(uidc->name, name) == 0)
- break;
- uidc = uidc->next;
- }
-
- if (uidc == NULL) {
- uidc = xmalloc(sizeof(struct uidc));
- uidc->name = xstrdup(name);
- pw = getpwnam(name);
- if (pw != NULL) {
- /* This user name is in the password file. */
- uidc->valid = 1;
- uidc->uid = pw->pw_uid;
- /* Also add it to the uid -> name table. */
- uidc2 = xmalloc(sizeof(struct uidc));
- uidc2->name = uidc->name; /* We reuse the pointer. */
- uidc2->uid = uidc->uid;
- uidc2->valid = 1;
- key2 = uidc2->uid % UIDTONAME_SZ;
- uidc_insert(uidtoname, uidc2, key2);
- } else {
- /* Add a miss entry for this user name. */
- uidc->valid = 0;
- uidc->uid = (uid_t)-1; /* Should not be accessed. */
- }
- uidc_insert(nametouid, uidc, key);
- }
- /* It is safe to unlock here since the cache structure
- is not going to get freed or changed. */
- uid_unlock();
- if (!uidc->valid)
- return (-1);
- *uid = uidc->uid;
- return (0);
-}
-
-/* Finds the gid for this group name. If it's found, the gid is stored
- in *gid and 0 is returned. Otherwise, -1 is returned. */
-int
-getgidbyname(const char *name, gid_t *gid)
-{
- struct group *gr;
- struct gidc *gidc, *gidc2;
- uint32_t key, key2;
-
- gid_lock();
- key = hash(name) % NAMETOGID_SZ;
- gidc = nametogid[key];
- while (gidc != NULL) {
- if (strcmp(gidc->name, name) == 0)
- break;
- gidc = gidc->next;
- }
-
- if (gidc == NULL) {
- gidc = xmalloc(sizeof(struct gidc));
- gidc->name = xstrdup(name);
- gr = getgrnam(name);
- if (gr != NULL) {
- /* This group name is in the group file. */
- gidc->gid = gr->gr_gid;
- gidc->valid = 1;
- /* Also add it to the gid -> name table. */
- gidc2 = xmalloc(sizeof(struct gidc));
- gidc2->name = gidc->name; /* We reuse the pointer. */
- gidc2->gid = gidc->gid;
- gidc2->valid = 1;
- key2 = gidc2->gid % GIDTONAME_SZ;
- gidc_insert(gidtoname, gidc2, key2);
- } else {
- /* Add a miss entry for this group name. */
- gidc->gid = (gid_t)-1; /* Should not be accessed. */
- gidc->valid = 0;
- }
- gidc_insert(nametogid, gidc, key);
- }
- /* It is safe to unlock here since the cache structure
- is not going to get freed or changed. */
- gid_unlock();
- if (!gidc->valid)
- return (-1);
- *gid = gidc->gid;
- return (0);
-}
-
-/* Initialize the cache structures. */
-void
-idcache_init(void)
-{
-
- pthread_mutex_init(&uid_mtx, NULL);
- pthread_mutex_init(&gid_mtx, NULL);
- uidtoname = xmalloc(UIDTONAME_SZ * sizeof(struct uidc *));
- gidtoname = xmalloc(GIDTONAME_SZ * sizeof(struct gidc *));
- nametouid = xmalloc(NAMETOUID_SZ * sizeof(struct uidc *));
- nametogid = xmalloc(NAMETOGID_SZ * sizeof(struct gidc *));
- memset(uidtoname, 0, UIDTONAME_SZ * sizeof(struct uidc *));
- memset(gidtoname, 0, GIDTONAME_SZ * sizeof(struct gidc *));
- memset(nametouid, 0, NAMETOUID_SZ * sizeof(struct uidc *));
- memset(nametogid, 0, NAMETOGID_SZ * sizeof(struct gidc *));
-}
-
-/* Cleanup the cache structures. */
-void
-idcache_fini(void)
-{
- struct uidc *uidc, *uidc2;
- struct gidc *gidc, *gidc2;
- size_t i;
-
- for (i = 0; i < UIDTONAME_SZ; i++) {
- uidc = uidtoname[i];
- while (uidc != NULL) {
- if (uidc->name != NULL) {
- assert(uidc->valid);
- free(uidc->name);
- }
- uidc2 = uidc->next;
- free(uidc);
- uidc = uidc2;
- }
- }
- free(uidtoname);
- for (i = 0; i < NAMETOUID_SZ; i++) {
- uidc = nametouid[i];
- while (uidc != NULL) {
- assert(uidc->name != NULL);
- /* If it's a valid entry, it has been added to both the
- uidtoname and nametouid tables, and the name pointer
- has been reused for both entries. Thus, the name
- pointer has already been freed in the loop above. */
- if (!uidc->valid)
- free(uidc->name);
- uidc2 = uidc->next;
- free(uidc);
- uidc = uidc2;
- }
- }
- free(nametouid);
- for (i = 0; i < GIDTONAME_SZ; i++) {
- gidc = gidtoname[i];
- while (gidc != NULL) {
- if (gidc->name != NULL) {
- assert(gidc->valid);
- free(gidc->name);
- }
- gidc2 = gidc->next;
- free(gidc);
- gidc = gidc2;
- }
- }
- free(gidtoname);
- for (i = 0; i < NAMETOGID_SZ; i++) {
- gidc = nametogid[i];
- while (gidc != NULL) {
- assert(gidc->name != NULL);
- /* See above comment. */
- if (!gidc->valid)
- free(gidc->name);
- gidc2 = gidc->next;
- free(gidc);
- gidc = gidc2;
- }
- }
- free(nametogid);
- pthread_mutex_destroy(&uid_mtx);
- pthread_mutex_destroy(&gid_mtx);
-}
--- contrib/csup/README
+++ /dev/null
@@ -1,40 +0,0 @@
-$FreeBSD: src/contrib/csup/README,v 1.1.1.1.2.1 2006/05/15 13:40:39 mux Exp $
-$MidnightBSD: src/contrib/csup/README,v 1.1 2006/12/27 01:28:42 laffer1 Exp $
-
-Authors
--------
-
-CVSup was originally written in Modula-3 by
- John Polstra <jdp at polstra.com>.
-
-Csup is a rewrite of CVSup in C. It has been mostly written by
- Maxime Henrion <mux at FreeBSD.org>.
-
-A few contributors have helped him in his task and they are listed here in
-alphabetical order :
-
- Olivier Houchard <cognet at FreeBSD.org>
- Ulf Lilleengen <lulf at kerneled.org>
- Christoph Mathys <cmathys at bluewin.ch> (Google SoC Project)
- Etienne Vidal <etienne.vidal at gmail.com>
-
-
-Building & Installing
----------------------
-
-Csup should build and run fine under any *BSD OS (that includes FreeBSD,
-NetBSD, OpenBSD and DragonFlyBSD), as well as Linux and Darwin. If you
-have a problem building from source, drop me a mail!
-
-There is one Makefile specifically tailored for *BSD systems named
-Makefile and another one that is gmake-specific for Darwin and Linux
-users named GNUmakefile. You don't really need to worry about that
-since whatever your "make" command is, it should pick up the correct
-Makefile.
-
-As usual, to build the source code, just run "make". Once this is done,
-just run "make install" to install the binary and manual page.
-
-Be warned however that if the packaging system of your OS knows about
-csup, it is certainly better to install it from there rather than by
-hand, so that it can then be properly deinstalled.
More information about the Midnightbsd-cvs
mailing list