From owner-svn-src-projects@FreeBSD.ORG Sun Oct 19 09:09:00 2008 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3A7EB1065689; Sun, 19 Oct 2008 09:09:00 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 27D948FC12; Sun, 19 Oct 2008 09:09:00 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9J990iI038935; Sun, 19 Oct 2008 09:09:00 GMT (envelope-from lulf@svn.freebsd.org) Received: (from lulf@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9J98xMc038924; Sun, 19 Oct 2008 09:08:59 GMT (envelope-from lulf@svn.freebsd.org) Message-Id: <200810190908.m9J98xMc038924@svn.freebsd.org> From: Ulf Lilleengen Date: Sun, 19 Oct 2008 09:08:59 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184054 - in projects/csup_cvsmode: contrib/csup usr.bin/csup X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Oct 2008 09:09:00 -0000 Author: lulf Date: Sun Oct 19 09:08:59 2008 New Revision: 184054 URL: http://svn.freebsd.org/changeset/base/184054 Log: - Import csup work from p4. Added: projects/csup_cvsmode/contrib/csup/lex.rcs.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsfile.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsfile.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsparse.c (contents, props changed) projects/csup_cvsmode/contrib/csup/rcsparse.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcstokenizer.h (contents, props changed) projects/csup_cvsmode/contrib/csup/rcstokenizer.l Modified: projects/csup_cvsmode/contrib/csup/Makefile projects/csup_cvsmode/contrib/csup/config.c projects/csup_cvsmode/contrib/csup/detailer.c projects/csup_cvsmode/contrib/csup/diff.c projects/csup_cvsmode/contrib/csup/diff.h projects/csup_cvsmode/contrib/csup/fattr.c projects/csup_cvsmode/contrib/csup/fattr.h projects/csup_cvsmode/contrib/csup/keyword.c projects/csup_cvsmode/contrib/csup/keyword.h projects/csup_cvsmode/contrib/csup/lister.c projects/csup_cvsmode/contrib/csup/misc.c projects/csup_cvsmode/contrib/csup/misc.h projects/csup_cvsmode/contrib/csup/mux.c projects/csup_cvsmode/contrib/csup/proto.c projects/csup_cvsmode/contrib/csup/status.c projects/csup_cvsmode/contrib/csup/stream.c projects/csup_cvsmode/contrib/csup/stream.h projects/csup_cvsmode/contrib/csup/updater.c projects/csup_cvsmode/usr.bin/csup/Makefile Modified: projects/csup_cvsmode/contrib/csup/Makefile ============================================================================== --- projects/csup_cvsmode/contrib/csup/Makefile Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/Makefile Sun Oct 19 09:08:59 2008 (r184054) @@ -9,10 +9,11 @@ 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 + pathcomp.c proto.c status.c stream.c threads.c token.l updater.c \ + rcsfile.c rcsparse.c lex.rcs.c CFLAGS+= -I. -I${.CURDIR} -g -pthread -DHAVE_FFLAGS -DNDEBUG -WARNS?= 6 +WARNS?= 1 # A bit of tweaking is needed to get this Makefile working # with the bsd.prog.mk of all the *BSD OSes... Modified: projects/csup_cvsmode/contrib/csup/config.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/config.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/config.c Sun Oct 19 09:08:59 2008 (r184054) @@ -444,10 +444,10 @@ coll_add(char *name) "\"%s\"\n", cur_coll->co_name); exit(1); } - if (!(cur_coll->co_options & CO_CHECKOUTMODE)) { +/* 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) { Modified: projects/csup_cvsmode/contrib/csup/detailer.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/detailer.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/detailer.c Sun Oct 19 09:08:59 2008 (r184054) @@ -30,6 +30,11 @@ #include #include #include +#include + +#include +#include +#include #include "config.h" #include "detailer.h" @@ -37,6 +42,7 @@ #include "misc.h" #include "mux.h" #include "proto.h" +#include "rcsfile.h" #include "status.h" #include "stream.h" @@ -56,8 +62,15 @@ struct detailer { static int detailer_batch(struct detailer *); static int detailer_coll(struct detailer *, struct coll *, struct status *); -static int detailer_dofile(struct detailer *, struct coll *, +static int detailer_dofile_co(struct detailer *, struct coll *, struct status *, char *); +static int detailer_dofile_rcs(struct detailer *, struct coll *, + char *, char *); +static int detailer_dofile_regular(struct detailer *, char *, char *); +static int detailer_checkrcsattr(struct detailer *, struct coll *, char *, + struct fattr *, int); +int detailer_send_details(struct detailer *, struct coll *, char *, + char *, struct fattr *); void * detailer(void *arg) @@ -93,6 +106,7 @@ detailer(void *arg) xasprintf(&args->errmsg, "Detailer failed: " "Network read failure: %s", strerror(errno)); } + lprintf(-1, "Error is '%s'\n", args->errmsg); args->status = STATUS_TRANSIENTFAILURE; break; case DETAILER_ERR_WRITE: @@ -131,8 +145,9 @@ detailer_batch(struct detailer *d) 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) + 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) @@ -147,8 +162,9 @@ detailer_batch(struct detailer *d) return (DETAILER_ERR_MSG); error = detailer_coll(d, coll, st); status_close(st, NULL); - if (error) + if (error) { return (error); + } if (coll->co_options & CO_COMPRESS) { stream_filter_stop(rd); stream_filter_stop(wr); @@ -156,10 +172,12 @@ detailer_batch(struct detailer *d) stream_flush(wr); } line = stream_getln(rd, NULL); - if (line == NULL) + if (line == NULL) { return (DETAILER_ERR_READ); - if (strcmp(line, ".") != 0) + } + if (strcmp(line, ".") != 0) { return (DETAILER_ERR_PROTO); + } error = proto_printf(wr, ".\n"); if (error) return (DETAILER_ERR_WRITE); @@ -186,8 +204,13 @@ detailer_batch(struct detailer *d) } 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 (coll->co_options & CO_CHECKOUTMODE) + error = proto_printf(wr, "Y %s %s %s\n", + fixup->f_name, coll->co_tag, coll->co_date); + else { + error = proto_printf(wr, "A %s\n", + fixup->f_name); + } if (error) return (DETAILER_ERR_WRITE); fixup = NULL; @@ -208,35 +231,107 @@ detailer_batch(struct detailer *d) static int detailer_coll(struct detailer *d, struct coll *coll, struct status *st) { + struct fattr *rcsattr; struct stream *rd, *wr; - char *cmd, *file, *line, *msg; - int error; + char *attr, *cmd, *file, *line, *msg, *target, *path; + int error, attic; rd = d->rd; wr = d->wr; + attic = 0; line = stream_getln(rd, NULL); - if (line == NULL) + if (line == NULL) { return (DETAILER_ERR_READ); + } while (strcmp(line, ".") != 0) { cmd = proto_get_ascii(&line); - if (cmd == NULL || strlen(cmd) != 1) + 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 'I': + case 'i': + case 'j': + /* Directory operations. */ + file = proto_get_ascii(&line); if (file == NULL || line != NULL) return (DETAILER_ERR_PROTO); - error = proto_printf(wr, "D %s\n", file); + error = proto_printf(wr, "%s %s\n", cmd, file); + if (error) + return (DETAILER_ERR_WRITE); + break; + case 'J': + /* Set directory attributes. */ + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || line != NULL || attr == NULL) + return (DETAILER_ERR_PROTO); + error = proto_printf(wr, "%s %s %s\n", cmd, file, attr); if (error) return (DETAILER_ERR_WRITE); break; + case 'H': + case 'h': + /* Create a hard link. */ + file = proto_get_ascii(&line); + target = proto_get_ascii(&line); + if (file == NULL || target == NULL) + return (DETAILER_ERR_PROTO); + error = proto_printf(wr, "%s %s %s\n", cmd, file, + target); + break; + case 't': + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || attr == NULL || line != NULL) { + return (DETAILER_ERR_PROTO); + } + rcsattr = fattr_decode(attr); + if (rcsattr == NULL) { + return (DETAILER_ERR_PROTO); + } + error = detailer_checkrcsattr(d, coll, file, rcsattr, + 1); + break; + + case 'T': + file = proto_get_ascii(&line); + attr = proto_get_ascii(&line); + if (file == NULL || attr == NULL || line != NULL) + return (DETAILER_ERR_PROTO); + rcsattr = fattr_decode(attr); + if (rcsattr == NULL) + return (DETAILER_ERR_PROTO); + error = detailer_checkrcsattr(d, coll, file, rcsattr, + 0); + 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 (coll->co_options & CO_CHECKOUTMODE) { + error = detailer_dofile_co(d, coll, st, file); + } else { + path = cvspath(coll->co_prefix, file, 0); + rcsattr = fattr_frompath(path, FATTR_NOFOLLOW); + error = detailer_send_details(d, coll, file, + path, rcsattr); + if (rcsattr != NULL) + fattr_free(rcsattr); + free(path); + } if (error) return (error); break; @@ -248,6 +343,7 @@ detailer_coll(struct detailer *d, struct lprintf(-1, "Server warning: %s\n", msg); break; default: + lprintf(-1, "Line: %s, cmd %s\n", line, cmd); return (DETAILER_ERR_PROTO); } stream_flush(wr); @@ -261,8 +357,81 @@ detailer_coll(struct detailer *d, struct return (0); } +/* + * Tell the server to update a regular file. + */ static int -detailer_dofile(struct detailer *d, struct coll *coll, struct status *st, +detailer_dofile_regular(struct detailer *d, char *name, char *path) +{ + struct stream *wr; + struct stat st; + char md5[MD5_DIGEST_SIZE]; + int error; + + wr = d->wr; + + error = stat(path, &st); + /* If we don't have it or it's unaccessible, we want it again. */ + if (error) { + proto_printf(wr, "A %s\n", name); + return (0); + } + + /* If not, we want the file to be updated. */ + error = MD5_File(path, md5); + if (error) { + lprintf(-1, "Error reading \"%s\"\n", name); + return (error); + } + error = proto_printf(wr, "R %s %O %s\n", name, st.st_size, md5); + if (error) + return (DETAILER_ERR_WRITE); + return (0); +} + +/* + * Tell the server to update an RCS file that we have, or send it if we don't. + */ +static int +detailer_dofile_rcs(struct detailer *d, struct coll *coll, char *name, + char *path) +{ + struct stream *wr; + struct fattr *fa; + struct rcsfile *rf; + int error; + + wr = d->wr; + + path = atticpath(coll->co_prefix, name); + fa = fattr_frompath(path, FATTR_NOFOLLOW); + if (fa == NULL) { + /* We don't have it, so send request to get it. */ + error = proto_printf(wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + free(path); + return (0); + } + + rf = rcsfile_frompath(path, name, coll->co_cvsroot, coll->co_tag); + free(path); + if (rf == NULL) { + lprintf(-1, "Error parsing, resend file.\n"); + error = proto_printf(wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + return (0); + } + /* Tell to update the RCS file. The client version details follow. */ + rcsfile_send_details(rf, wr); + rcsfile_free(rf); + fattr_free(fa); + return (0); +} + +static int +detailer_dofile_co(struct detailer *d, struct coll *coll, struct status *st, char *file) { char md5[MD5_DIGEST_SIZE]; @@ -274,8 +443,9 @@ detailer_dofile(struct detailer *d, stru wr = d->wr; path = checkoutpath(coll->co_prefix, file); - if (path == NULL) + 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 @@ -337,3 +507,78 @@ detailer_dofile(struct detailer *d, stru return (DETAILER_ERR_WRITE); return (0); } + +int +detailer_checkrcsattr(struct detailer *d, struct coll *coll, char *name, + struct fattr *server_attr, int attic) +{ + struct fattr *client_attr; + char *attr, *path; + int error; + + /* + * I don't think we can use the status file, since it only records file + * attributes in cvsmode. + */ + client_attr = NULL; + path = cvspath(coll->co_prefix, name, attic); + if (path == NULL) { + return (DETAILER_ERR_PROTO); + } + + if (access(path, F_OK) == 0 && + ((client_attr = fattr_frompath(path, FATTR_NOFOLLOW)) != NULL) && + fattr_equal(client_attr, server_attr)) { + attr = fattr_encode(client_attr, NULL, 0); + if (attic) { + error = proto_printf(d->wr, "l %s %s\n", name, attr); + } else { + error = proto_printf(d->wr, "L %s %s\n", name, attr); + } + free(attr); + free(path); + fattr_free(client_attr); + if (error) + return (DETAILER_ERR_WRITE); + return (0); + } + /* We don't have it, so tell the server to send it. */ + error = detailer_send_details(d, coll, name, path, client_attr); + fattr_free(client_attr); + free(path); + return (error); +} + +int +detailer_send_details(struct detailer *d, struct coll *coll, char *name, + char *path, struct fattr *fa) +{ + int error; + size_t len; + + /* + * Try to check if the file exists either live or dead to see if we can + * edit it and put it live or dead, rather than receiving the entire + * file. + */ + if (fa == NULL) { + path = atticpath(coll->co_prefix, name); + fa = fattr_frompath(path, FATTR_NOFOLLOW); + } + if (fa == NULL) { + error = proto_printf(d->wr, "A %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + } else if (fattr_type(fa) == FT_FILE) { + if (isrcs(name, &len) && !(coll->co_options & CO_NORCS)) { + detailer_dofile_rcs(d, coll, name, path); + } else { + detailer_dofile_regular(d, name, path); + } + } else { + error = proto_printf(d->wr, "N %s\n", name); + if (error) + return (DETAILER_ERR_WRITE); + } + return (0); +} Modified: projects/csup_cvsmode/contrib/csup/diff.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/diff.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/diff.c Sun Oct 19 09:08:59 2008 (r184054) @@ -26,25 +26,33 @@ * $FreeBSD$ */ +#include + #include #include #include #include #include +#include #include "diff.h" #include "keyword.h" #include "misc.h" #include "stream.h" +#include "queue.h" typedef long lineno_t; #define EC_ADD 0 #define EC_DEL 1 +#define MAXKEY LONG_MAX /* Editing command and state. */ struct editcmd { int cmd; + long key; + int havetext; + int offset; lineno_t where; lineno_t count; lineno_t lasta; @@ -55,15 +63,23 @@ struct editcmd { struct diffinfo *di; struct stream *orig; struct stream *dest; + LIST_ENTRY(editcmd) next; +}; + +struct diffstart { + LIST_HEAD(, editcmd) dhead; }; static int diff_geteditcmd(struct editcmd *, char *); static int diff_copyln(struct editcmd *, lineno_t); +static int diff_ignoreln(struct editcmd *, lineno_t); static void diff_write(struct editcmd *, void *, size_t); +static int diff_insert_edit(struct diffstart *, struct editcmd *); +static int diff_free(struct diffstart *); int diff_apply(struct stream *rd, struct stream *orig, struct stream *dest, - struct keyword *keyword, struct diffinfo *di) + struct keyword *keyword, struct diffinfo *di, int comode) { struct editcmd ec; lineno_t i; @@ -104,7 +120,7 @@ diff_apply(struct stream *rd, struct str line = stream_getln(rd, &size); if (line == NULL) return (-1); - if (line[0] == '.') { + if (comode && line[0] == '.') { line++; size--; } @@ -143,6 +159,213 @@ diff_apply(struct stream *rd, struct str return (0); } +static int +diff_write_reverse(struct stream *dest, struct diffstart *ds) +{ + long firstoutputlinedeleted, endline, startline, editline, num_deleted, + num_added; + int num; + struct editcmd *ec, *nextec; + + nextec = LIST_FIRST(&ds->dhead); + editline = 0; + num = 0; + while (nextec != NULL) { + ec = nextec; + nextec = LIST_NEXT(nextec, next); + if (nextec == NULL) + break; + num++; + num_deleted = 0; + if (ec->havetext) + num_deleted = ec->count; + num_added = num_deleted + nextec->offset - ec->offset; + if (num_deleted > 0) { + firstoutputlinedeleted = ec->key - num_deleted + 1; + stream_printf(dest, "d%ld %ld\n", firstoutputlinedeleted, + num_deleted); + if (num_added <= 0) + continue; + } + if (num_added > 0) { + stream_printf(dest, "a%ld %ld\n", ec->key, num_added); + startline = ec->key - num_deleted + 1 + ec->offset; + endline = startline + num_added - 1; + + /* Copy lines from original file. First ignore some. */ + ec->editline = editline; + diff_ignoreln(ec, startline - 1); + diff_copyln(ec, endline); + editline = ec->editline; + } + } + return (0); +} + +/* + * Insert a diff into the list sorted on key. Should perhaps use quicker + * algorithms than insertion sort, but do this for now. + */ +static int +diff_insert_edit(struct diffstart *ds, struct editcmd *ec) +{ + struct editcmd *curec; + + if (ec == NULL) + return (0); + + if (LIST_EMPTY(&ds->dhead)) { + LIST_INSERT_HEAD(&ds->dhead, ec, next); + return (0); + } + + /* Insertion sort based on key. */ + /* XXX: check if this gets too slow. */ + LIST_FOREACH(curec, &ds->dhead, next) { + if (ec->key < curec->key) { + LIST_INSERT_BEFORE(curec, ec, next); + return (0); + } + if (LIST_NEXT(curec, next) == NULL) + break; + } + /* Just insert it after. */ + LIST_INSERT_AFTER(curec, ec, next); + return (0); +} + +static int +diff_free(struct diffstart *ds) +{ + struct editcmd *ec; + int freecount = 0; + + while(!LIST_EMPTY(&ds->dhead)) { + ec = LIST_FIRST(&ds->dhead); + LIST_REMOVE(ec, next); + free(ec); + freecount++; + } + return freecount; +} + +/* + * Write the reverse diff from the diff in rd, and original file into + * destination. This algorithm is the same as used in cvsup. + */ +int +diff_reverse(struct stream *rd, struct stream *orig, struct stream *dest, + struct keyword *keyword, struct diffinfo *di) +{ + struct diffstart ds; + struct editcmd ec, *addec, *delec; + lineno_t i; + char *line; + int error, offset; + int malloccount = 0, freecount = 0; + + memset(&ec, 0, sizeof(ec)); + ec.orig = orig; + ec.dest = dest; + ec.keyword = keyword; + ec.di = di; + addec = NULL; + delec = NULL; + ec.havetext = 0; + offset = 0; + LIST_INIT(&ds.dhead); + + /* Start with next since we need it. */ + line = stream_getln(rd, NULL); + /* First we build up the list of diffs from input. */ + while (line != NULL) { + error = diff_geteditcmd(&ec, line); + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + if (error) + break; + if (ec.cmd == EC_ADD) { + addec = xmalloc(sizeof(struct editcmd)); + malloccount++; + *addec = ec; + addec->havetext = 1; + /* Ignore the lines we was supposed to add. */ + for (i = 0; i < ec.count; i++) { + line = stream_getln(rd, NULL); + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + if (line == NULL) + return (-1); + } + + /* Get the next diff command if we have one. */ + addec->key = addec->where + addec->count - offset; + if (delec != NULL && delec->key == addec->key - addec->count) { + delec->key = addec->key; + delec->havetext = addec->havetext; + delec->count = addec->count; + + diff_insert_edit(&ds, delec); + free(addec); + freecount++; + delec = NULL; + addec = NULL; + } else { + if (delec != NULL) { + diff_insert_edit(&ds, delec); + } + delec = NULL; + addec->offset = offset; + diff_insert_edit(&ds, addec); + addec = NULL; + } + offset -= ec.count; + } else if (ec.cmd == EC_DEL) { + if (delec != NULL) { + /* Update offset to our next. */ + diff_insert_edit(&ds, delec); + delec = NULL; + } + delec = xmalloc(sizeof(struct editcmd)); + malloccount++; + *delec = ec; + delec->key = delec->where - 1 - offset; + delec->offset = offset; + delec->count = 0; + delec->havetext = 0; + /* Important to use the count we had before reset.*/ + offset += ec.count; + } + line = stream_getln(rd, NULL); + } + + while (line != NULL) { + /*fprintf(stderr, "Diff line '%s'\n", line);*/ + line = stream_getln(rd, NULL); + } + /*fprintf(stderr, "Done with diff\n");*/ + if (delec != NULL) { + diff_insert_edit(&ds, delec); + delec = NULL; + } + + addec = xmalloc(sizeof(struct editcmd)); + malloccount++; + /* Should be filesize, but we set it to max value. */ + addec->key = MAXKEY; + addec->offset = offset; + addec->havetext = 0; + addec->count = 0; + diff_insert_edit(&ds, addec); + addec = NULL; + + /*fprintf(stderr, "Done with last diff\n");*/ + diff_write_reverse(dest, &ds); + freecount += diff_free(&ds); + /*fprintf(stderr, "Diff did a total of %d mallocs\n", malloccount); + fprintf(stderr, "Diff did a total of %d frees\n", freecount);*/ + stream_flush(dest); + return (0); +} + /* Get an editing command from the diff. */ static int diff_geteditcmd(struct editcmd *ec, char *line) @@ -194,6 +417,22 @@ diff_copyln(struct editcmd *ec, lineno_t return (0); } +/* Ignore lines from the original version of the file up to line "to". */ +static int +diff_ignoreln(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++; + } + 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) Modified: projects/csup_cvsmode/contrib/csup/diff.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/diff.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/diff.h Sun Oct 19 09:08:59 2008 (r184054) @@ -45,6 +45,8 @@ struct diffinfo { }; int diff_apply(struct stream *, struct stream *, struct stream *, - struct keyword *, struct diffinfo *); + struct keyword *, struct diffinfo *, int); +int diff_reverse(struct stream *, struct stream *, + struct stream *, struct keyword *, struct diffinfo *); #endif /* !_DIFF_H_ */ Modified: projects/csup_cvsmode/contrib/csup/fattr.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/fattr.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/fattr.c Sun Oct 19 09:08:59 2008 (r184054) @@ -44,7 +44,7 @@ /* * 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 + * support the extended file flags ? la chflags() and fattr_posix.h for * bare POSIX systems that don't. */ #ifdef HAVE_FFLAGS @@ -449,7 +449,7 @@ fattr_encode(const struct fattr *fa, fat piece++; } if (mask & FA_DEV) { - vallen = snprintf(piece->val, sizeof(piece->val), "%lld", + vallen = snprintf(piece->val, sizeof(piece->val), "%llx", (long long)fa->dev); len += snprintf(piece->len, sizeof(piece->len), "%lld", (long long)vallen) + vallen + 1; @@ -534,6 +534,13 @@ fattr_getlinkcount(const struct fattr *f return (fa->linkcount); } +char * +fattr_getlinktarget(const struct fattr *fa) +{ + + return (fa->linktarget); +} + /* * Eat the specified attribute and put it in the file attribute * structure. Returns NULL on error, or a pointer to the next @@ -732,23 +739,32 @@ fattr_makenode(const struct fattr *fa, c mode_t modemask, mode; int error; + error = 0; + 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); + + if (fa->type == FT_DIRECTORY) + error = mkdir(path, mode); + else if (fa->type == FT_SYMLINK) { + error = symlink(fa->linktarget, path); + } else if (fa->type == FT_CDEV) { + lprintf(-1, "Character devices not supported!\n"); + } else if (fa->type == FT_BDEV) { + lprintf(-1, "Block devices not supported!\n"); + } return (error); } -int -fattr_delete(const char *path) +int fattr_delete(const char *path) { struct fattr *fa; int error; @@ -830,8 +846,9 @@ fattr_install(struct fattr *fa, const ch error = rmdir(topath); else error = unlink(topath); - if (error) + if (error) { goto bad; + } } } @@ -842,8 +859,9 @@ fattr_install(struct fattr *fa, const ch tv[1].tv_sec = fa->modtime; /* Modification time. */ tv[1].tv_usec = 0; error = utimes(frompath, tv); - if (error) + if (error) { goto bad; + } } if (mask & FA_OWNER || mask & FA_GROUP) { uid = -1; @@ -853,8 +871,9 @@ fattr_install(struct fattr *fa, const ch if (mask & FA_GROUP) gid = fa->gid; error = chown(frompath, uid, gid); - if (error) + if (error) { goto bad; + } } if (mask & FA_MODE) { newmode = fa->mode & modemask; @@ -936,3 +955,12 @@ fattr_equal(const struct fattr *fa1, con return (0); return (1); } + +/* + * Must have to get the correct filesize sendt by the server. + */ +off_t +fattr_filesize(const struct fattr *fa) +{ + return (fa->size); +} Modified: projects/csup_cvsmode/contrib/csup/fattr.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/fattr.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/fattr.h Sun Oct 19 09:08:59 2008 (r184054) @@ -101,6 +101,7 @@ 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 *); +char *fattr_getlinktarget(const struct fattr *); void fattr_umask(struct fattr *, mode_t); void fattr_merge(struct fattr *, const struct fattr *); void fattr_mergedefault(struct fattr *); @@ -111,5 +112,7 @@ int fattr_install(struct fattr *, cons int fattr_equal(const struct fattr *, const struct fattr *); void fattr_free(struct fattr *); int fattr_supported(int); +off_t fattr_filesize(const struct fattr *); + #endif /* !_FATTR_H_ */ Modified: projects/csup_cvsmode/contrib/csup/keyword.c ============================================================================== --- projects/csup_cvsmode/contrib/csup/keyword.c Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/keyword.c Sun Oct 19 09:08:59 2008 (r184054) @@ -152,6 +152,29 @@ keyword_decode_expand(const char *expand return (-1); } +const char * +keyword_encode_expand(int expand) +{ + + switch (expand) { + case EXPAND_DEFAULT: + return ("."); + case EXPAND_KEYVALUE: + return ("kv"); + case EXPAND_KEYVALUELOCKER: + return ("kvl"); + case EXPAND_KEY: + return ("k"); + case EXPAND_OLD: + return ("o"); + case EXPAND_BINARY: + return ("b"); + case EXPAND_VALUE: + return ("v"); + } + return (NULL); +} + void keyword_free(struct keyword *keyword) { Modified: projects/csup_cvsmode/contrib/csup/keyword.h ============================================================================== --- projects/csup_cvsmode/contrib/csup/keyword.h Sun Oct 19 08:43:16 2008 (r184053) +++ projects/csup_cvsmode/contrib/csup/keyword.h Sun Oct 19 09:08:59 2008 (r184054) @@ -42,6 +42,7 @@ struct keyword; struct keyword *keyword_new(void); int keyword_decode_expand(const char *); +const char *keyword_encode_expand(int); int keyword_alias(struct keyword *, const char *, const char *); int keyword_enable(struct keyword *, const char *); int keyword_disable(struct keyword *, const char *); Added: projects/csup_cvsmode/contrib/csup/lex.rcs.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/csup_cvsmode/contrib/csup/lex.rcs.c Sun Oct 19 09:08:59 2008 (r184054) @@ -0,0 +1,2094 @@ + +#line 3 "lex.rcs.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***