2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
13 * The routines contained in this file do all the rcs file parsing and
24 /* These need to be source after cvs.h or HAVE_MMAP won't be set... */
26 # include <sys/mman.h>
27 # ifndef HAVE_GETPAGESIZE
28 # include "getpagesize.h"
31 # define MAP_FAILED NULL
35 #ifdef MMAP_FALLBACK_TEST
36 void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
38 if (rand() & 1) return mmap(addr, len, prot, flags, fd, offset);
45 int preserve_perms = 0;
47 /* The RCS -k options, and a set of enums that must match the array.
48 These come first so that we can use enum kflag in function
50 static const char *const kflags[] =
51 {"kv", "kvl", "k", "v", "o", "b", (char *) NULL};
52 enum kflag { KFLAG_KV = 0, KFLAG_KVL, KFLAG_K, KFLAG_V, KFLAG_O, KFLAG_B };
54 /* A structure we use to buffer the contents of an RCS file. The
55 various fields are only referenced directly by the rcsbuf_*
56 functions. We declare the struct here so that we can allocate it
57 on the stack, rather than in memory. */
61 /* Points to the current position in the buffer. */
63 /* Points just after the last valid character in the buffer. */
67 /* The name of the file, used for error messages. */
69 /* The starting file position of the data in the buffer. */
71 /* The length of the value. */
73 /* Whether the value contains an '@' string. If so, we can not
74 compress whitespace characters. */
76 /* The number of embedded '@' characters in an '@' string. If
77 this is non-zero, we must search the string for pairs of '@'
78 and convert them to a single '@'. */
80 /* Whether the buffer has been mmap'ed or not. */
84 static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
85 static char *RCS_getdatebranch PROTO((RCSNode * rcs, const char *date,
87 static void rcsbuf_open PROTO ((struct rcsbuffer *, FILE *fp,
88 const char *filename, unsigned long pos));
89 static void rcsbuf_close PROTO ((struct rcsbuffer *));
90 static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
92 static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
93 static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
95 static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
96 static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
98 static void rcsbuf_valpolish PROTO ((struct rcsbuffer *, char *val, int polish,
100 static void rcsbuf_valpolish_internal PROTO ((struct rcsbuffer *, char *to,
101 const char *from, size_t *lenp));
102 static unsigned long rcsbuf_ftell PROTO ((struct rcsbuffer *));
103 static void rcsbuf_get_buffered PROTO ((struct rcsbuffer *, char **datap,
105 static void rcsbuf_cache PROTO ((RCSNode *, struct rcsbuffer *));
106 static void rcsbuf_cache_close PROTO ((void));
107 static void rcsbuf_cache_open PROTO ((RCSNode *, long, FILE **,
108 struct rcsbuffer *));
109 static int checkmagic_proc PROTO((Node *p, void *closure));
110 static void do_branches PROTO((List * list, char *val));
111 static void do_symbols PROTO((List * list, char *val));
112 static void do_locks PROTO((List * list, char *val));
113 static void free_rcsnode_contents PROTO((RCSNode *));
114 static void free_rcsvers_contents PROTO((RCSVers *));
115 static void rcsvers_delproc PROTO((Node * p));
116 static char *translate_symtag PROTO((RCSNode *, const char *));
117 static char *RCS_addbranch PROTO ((RCSNode *, const char *));
118 static char *truncate_revnum_in_place PROTO ((char *));
119 static char *truncate_revnum PROTO ((const char *));
120 static char *printable_date PROTO((const char *));
121 static char *escape_keyword_value PROTO ((const char *, int *));
122 static void expand_keywords PROTO((RCSNode *, RCSVers *, const char *,
123 const char *, size_t, enum kflag, char *,
124 size_t, char **, size_t *));
125 static void cmp_file_buffer PROTO((void *, const char *, size_t));
127 /* Routines for reading, parsing and writing RCS files. */
128 static RCSVers *getdelta PROTO ((struct rcsbuffer *, char *, char **,
130 static Deltatext *RCS_getdeltatext PROTO ((RCSNode *, FILE *,
131 struct rcsbuffer *));
132 static void freedeltatext PROTO ((Deltatext *));
134 static void RCS_putadmin PROTO ((RCSNode *, FILE *));
135 static void RCS_putdtree PROTO ((RCSNode *, char *, FILE *));
136 static void RCS_putdesc PROTO ((RCSNode *, FILE *));
137 static void putdelta PROTO ((RCSVers *, FILE *));
138 static int putrcsfield_proc PROTO ((Node *, void *));
139 static int putsymbol_proc PROTO ((Node *, void *));
140 static void RCS_copydeltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *,
141 FILE *, Deltatext *, char *));
142 static int count_delta_actions PROTO ((Node *, void *));
143 static void putdeltatext PROTO ((FILE *, Deltatext *));
145 static FILE *rcs_internal_lockfile PROTO ((char *));
146 static void rcs_internal_unlockfile PROTO ((FILE *, char *));
147 static char *rcs_lockfilename PROTO ((const char *));
149 /* The RCS file reading functions are called a lot, and they do some
150 string comparisons. This macro speeds things up a bit by skipping
151 the function call when the first characters are different. It
152 evaluates its arguments multiple times. */
153 #define STREQ(a, b) (*(char *)(a) == *(char *)(b) && strcmp ((a), (b)) == 0)
155 static char * getfullCVSname PROTO ((char *, char **));
158 * We don't want to use isspace() from the C library because:
160 * 1. The definition of "whitespace" in RCS files includes ASCII
161 * backspace, but the C locale doesn't.
162 * 2. isspace is an very expensive function call in some implementations
163 * due to the addition of wide character support.
165 static const char spacetab[] = {
166 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x00 - 0x0f */
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
168 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x8f */
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
184 #define whitespace(c) (spacetab[(unsigned char)c] != 0)
186 static char *rcs_lockfile;
187 static int rcs_lockfd = -1;
193 * locate_rcs ( const char* file, const char *repository , int *inattic )
195 * Find an RCS file in the repository, case insensitively when the cased name
196 * doesn't exist, we are running as the server, and a client has asked us to
199 * Most parts of CVS will want to rely instead on RCS_parse which calls this
200 * function and is called by recurse.c which then puts the result in useful
201 * places like the rcs field of struct file_info.
205 * repository the repository (including the directory)
206 * file the filename within that directory (without RCSEXT).
207 * inattic NULL or a pointer to the output boolean
211 * inattic If this input was non-null, the destination will be
212 * set to true if the file was found in the attic or
213 * false if not. If no RCS file is found, this value
218 * a newly-malloc'd array containing the absolute pathname of the RCS
219 * file that was found or NULL when none was found.
223 * errno can be set by the return value of the final call to
224 * locate_file_in_dir(). This should resolve to the system's existence error
225 * value (sometime ENOENT) if the Attic directory did not exist and ENOENT if
226 * the Attic was found but no matching files were found in the Attic or its
230 locate_rcs (repository, file, inattic)
231 const char *repository;
237 /* First, try to find the file as cased. */
238 retval = xmalloc (strlen (repository)
243 sprintf (retval, "%s/%s%s", repository, file, RCSEXT);
244 if (isreadable (retval))
250 sprintf (retval, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
251 if (isreadable (retval))
264 /* A few generic thoughts on error handling, in particular the
265 printing of unexpected characters that we find in the RCS file
266 (that is, why we use '\x%x' rather than %c or some such).
268 * Avoiding %c means we don't have to worry about what is printable
269 and other such stuff. In error handling, often better to keep it
272 * Hex rather than decimal or octal because character set standards
275 * Saying "character 0x%x" might make it sound like we are printing
276 a file offset. So we use '\x%x'.
278 * Would be nice to print the offset within the file, but I can
279 imagine various portability hassles (in particular, whether
280 unsigned long is always big enough to hold file offsets). */
282 /* Parse an rcsfile given a user file name and a repository. If there is
283 an error, we print an error message and return NULL. If the file
284 does not exist, we return NULL without printing anything (I'm not
285 sure this allows the caller to do anything reasonable, but it is
286 the current behavior). */
288 RCS_parse (file, repos)
294 RCSNode *retval = NULL;
298 /* We're creating a new RCSNode, so there is no hope of finding it
300 rcsbuf_cache_close ();
302 if ((rcsfile = locate_rcs (repos, file, &inattic)) == NULL)
304 /* Handle the error cases */
306 else if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL)
308 rcs = RCS_parsercsfile_i(fp, rcsfile);
313 rcs->flags |= INATTIC;
319 else if (! existence_error (errno))
321 error (0, errno, "cannot open %s", rcsfile);
329 * Parse a specific rcsfile.
332 RCS_parsercsfile (rcsfile)
338 /* We're creating a new RCSNode, so there is no hope of finding it
340 rcsbuf_cache_close ();
342 /* open the rcsfile */
343 if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) == NULL)
345 error (0, errno, "Couldn't open rcs file `%s'", rcsfile);
349 rcs = RCS_parsercsfile_i (fp, rcsfile);
359 RCS_parsercsfile_i (fp, rcsfile)
364 struct rcsbuffer rcsbuf;
368 rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
369 memset ((char *)rdata, 0, sizeof (RCSNode));
371 rdata->path = xstrdup (rcsfile);
373 /* Process HEAD, BRANCH, and EXPAND keywords from the RCS header.
375 Most cvs operations on the main branch don't need any more
376 information. Those that do call RCS_reparsercsfile to parse
377 the rest of the header and the deltas. */
379 rcsbuf_open (&rcsbuf, fp, rcsfile, 0);
381 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
383 if (STREQ (key, RCSDESC))
386 if (STREQ (RCSHEAD, key) && value != NULL)
387 rdata->head = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
389 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
391 if (STREQ (key, RCSDESC))
394 if (STREQ (RCSBRANCH, key) && value != NULL)
398 rdata->branch = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
399 if ((numdots (rdata->branch) & 1) != 0)
401 /* turn it into a branch if it's a revision */
402 cp = strrchr (rdata->branch, '.');
407 /* Look ahead for expand, stopping when we see desc or a revision
413 if (STREQ (RCSEXPAND, key))
415 rdata->expand = rcsbuf_valcopy (&rcsbuf, value, 0,
421 (isdigit ((unsigned char)*cp) || *cp == '.') && *cp != '\0';
427 if (STREQ (RCSDESC, key))
430 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
434 rdata->flags |= PARTIAL;
436 rcsbuf_cache (rdata, &rcsbuf);
441 error (0, 0, "`%s' does not appear to be a valid rcs file",
443 rcsbuf_close (&rcsbuf);
444 freercsnode (&rdata);
451 /* Do the real work of parsing an RCS file.
453 On error, die with a fatal error; if it returns at all it was successful.
455 If PFP is NULL, close the file when done. Otherwise, leave it open
456 and store the FILE * in *PFP. */
458 RCS_reparsercsfile (rdata, pfp, rcsbufp)
461 struct rcsbuffer *rcsbufp;
465 struct rcsbuffer rcsbuf;
472 assert (rdata != NULL);
473 rcsfile = rdata->path;
475 rcsbuf_cache_open (rdata, 0, &fp, &rcsbuf);
478 /* This probably shouldn't be done until later: if a file has an
479 empty revision tree (which is permissible), rdata->versions
480 should be NULL. -twp */
481 rdata->versions = getlist ();
484 * process all the special header information, break out when we get to
485 * the first revision delta
490 /* get the next key/value pair */
493 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
495 error (1, 0, "`%s' does not appear to be a valid rcs file",
502 /* Skip head, branch and expand tags; we already have them. */
503 if (STREQ (key, RCSHEAD)
504 || STREQ (key, RCSBRANCH)
505 || STREQ (key, RCSEXPAND))
510 if (STREQ (key, "access"))
514 /* We pass the POLISH parameter as 1 because
515 RCS_addaccess expects nothing but spaces. FIXME:
516 It would be easy and more efficient to change
521 "Duplicate `access' keyword found in RCS file.");
522 free (rdata->access);
524 rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1, NULL);
529 /* We always save lock information, so that we can handle
530 -kkvl correctly when checking out a file. */
531 if (STREQ (key, "locks"))
535 if (rdata->locks_data)
538 "Duplicate `locks' keyword found in RCS file.");
539 free (rdata->locks_data);
541 rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
543 if (! rcsbuf_getkey (&rcsbuf, &key, &value))
545 error (1, 0, "premature end of file reading %s", rcsfile);
547 if (STREQ (key, "strict") && value == NULL)
549 rdata->strict_locks = 1;
556 if (STREQ (RCSSYMBOLS, key))
560 if (rdata->symbols_data)
563 "Duplicate `%s' keyword found in RCS file.",
565 free (rdata->symbols_data);
567 rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
573 * check key for '.''s and digits (probably a rev) if it is a
574 * revision or `desc', we are done with the headers and are down to the
575 * revision deltas, so we break out of the loop
578 (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
581 /* Note that when comparing with RCSDATE, we are not massaging
582 VALUE from the string found in the RCS file. This is OK
583 since we know exactly what to expect. */
584 if (*cp == '\0' && strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) == 0)
587 if (STREQ (key, RCSDESC))
590 if (STREQ (key, "comment"))
595 "warning: duplicate key `%s' in RCS file `%s'",
597 free (rdata->comment);
599 rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
602 if (rdata->other == NULL)
603 rdata->other = getlist ();
605 kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
606 kv->key = xstrdup (key);
607 kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
609 if (addnode (rdata->other, kv) != 0)
611 error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
616 /* if we haven't grabbed it yet, we didn't want it */
619 /* We got out of the loop, so we have the first part of the first
620 revision delta in KEY (the revision) and VALUE (the date key
621 and its value). This is what getdelta expects to receive. */
623 while ((vnode = getdelta (&rcsbuf, rcsfile, &key, &value)) != NULL)
628 q->delproc = rcsvers_delproc;
630 q->key = vnode->version;
632 /* add the nodes to the list */
633 if (addnode (rdata->versions, q))
634 error (1, 0, "Multiple %s revision deltas found in `%s'",
638 /* Here KEY and VALUE are whatever caused getdelta to return NULL. */
640 if (STREQ (key, RCSDESC))
642 if (rdata->desc != NULL)
645 "warning: duplicate key `%s' in RCS file `%s'",
649 rdata->desc = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
652 rdata->delta_pos = rcsbuf_ftell (&rcsbuf);
655 rcsbuf_cache (rdata, &rcsbuf);
661 rdata->flags &= ~PARTIAL;
664 /* Move RCS into or out of the Attic, depending on TOATTIC. If the
665 file is already in the desired place, return without doing
666 anything. At some point may want to think about how this relates
667 to RCS_rewrite but that is a bit hairy (if one wants renames to be
668 atomic, or that kind of thing). If there is an error, print a message
669 and return 1. On success, return 0. */
671 RCS_setattic (rcs, toattic)
679 /* Some systems aren't going to let us rename an open file. */
680 rcsbuf_cache_close ();
682 /* Could make the pathname computations in this file, and probably
683 in other parts of rcs.c too, easier if the REPOS and FILE
684 arguments to RCS_parse got stashed in the RCSNode. */
690 if (rcs->flags & INATTIC)
693 /* Example: rcs->path is "/foo/bar/baz,v". */
694 newpath = xmalloc (strlen (rcs->path) + sizeof CVSATTIC + 5);
695 p = last_component (rcs->path);
696 strncpy (newpath, rcs->path, p - rcs->path);
697 strcpy (newpath + (p - rcs->path), CVSATTIC);
699 /* Create the Attic directory if it doesn't exist. */
700 omask = umask (cvsumask);
701 if (CVS_MKDIR (newpath, 0777) < 0 && errno != EEXIST)
702 error (0, errno, "cannot make directory %s", newpath);
703 (void) umask (omask);
705 strcat (newpath, "/");
708 if (CVS_RENAME (rcs->path, newpath) < 0)
710 int save_errno = errno;
712 /* The checks for isreadable look awfully fishy, but
713 I'm going to leave them here for now until I
714 can think harder about whether they take care of
715 some cases which should be handled somehow. */
717 if (isreadable (rcs->path) || !isreadable (newpath))
719 error (0, save_errno, "cannot rename %s to %s",
728 if (!(rcs->flags & INATTIC))
731 newpath = xmalloc (strlen (rcs->path));
733 /* Example: rcs->path is "/foo/bar/Attic/baz,v". */
734 p = last_component (rcs->path);
735 strncpy (newpath, rcs->path, p - rcs->path - 1);
736 newpath[p - rcs->path - 1] = '\0';
737 q = newpath + (p - rcs->path - 1) - (sizeof CVSATTIC - 1);
738 assert (strncmp (q, CVSATTIC, sizeof CVSATTIC - 1) == 0);
741 if (CVS_RENAME (rcs->path, newpath) < 0)
743 error (0, errno, "failed to move `%s' out of the attic",
757 * Fully parse the RCS file. Store all keyword/value pairs, fetch the
758 * log messages for each revision, and fetch add and delete counts for
759 * each revision (we could fetch the entire text for each revision,
760 * but the only caller, log_fileproc, doesn't need that information,
761 * so we don't waste the memory required to store it). The add and
762 * delete counts are stored on the OTHER field of the RCSVERSNODE
763 * structure, under the names ";add" and ";delete", so that we don't
764 * waste the memory space of extra fields in RCSVERSNODE for code
765 * which doesn't need this information.
769 RCS_fully_parse (rcs)
773 struct rcsbuffer rcsbuf;
775 RCS_reparsercsfile (rcs, &fp, &rcsbuf);
783 /* Rather than try to keep track of how much information we
784 have read, just read to the end of the file. */
785 if (!rcsbuf_getrevnum (&rcsbuf, &key))
788 vers = findnode (rcs->versions, key);
791 "Delta text %s without revision information in `%s'.",
796 while (rcsbuf_getkey (&rcsbuf, &key, &value))
798 if (!STREQ (key, "text"))
802 if (vnode->other == NULL)
803 vnode->other = getlist ();
805 kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
806 kv->key = xstrdup (key);
807 kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
809 if (addnode (vnode->other, kv) != 0)
813 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
814 key, vnode->version, rcs->path);
821 if (!STREQ (vnode->version, rcs->head))
823 unsigned long add, del;
827 /* This is a change text. Store the add and delete
836 rcsbuf_valpolish (&rcsbuf, value, 0, &vallen);
838 while (cp < value + vallen)
844 if (op != 'a' && op != 'd')
846 unrecognized operation '\\x%x' in %s revision %s",
847 op, rcs->path, vnode->version);
848 (void) strtoul (cp, (char **) &cp, 10);
850 error (1, 0, "space expected in %s revision %s",
851 rcs->path, vnode->version);
852 count = strtoul (cp, (char **) &cp, 10);
854 error (1, 0, "linefeed expected in %s revision %s",
855 rcs->path, vnode->version);
866 else if (cp == value + vallen)
870 premature end of value in %s revision %s",
871 rcs->path, vnode->version);
881 sprintf (buf, "%lu", add);
884 kv->key = xstrdup (";add");
885 kv->data = xstrdup (buf);
886 if (addnode (vnode->other, kv) != 0)
890 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
891 key, vnode->version, rcs->path);
895 sprintf (buf, "%lu", del);
898 kv->key = xstrdup (";delete");
899 kv->data = xstrdup (buf);
900 if (addnode (vnode->other, kv) != 0)
904 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
905 key, vnode->version, rcs->path);
910 /* We have found the "text" key which ends the data for
911 this revision. Break out of the loop and go on to the
917 rcsbuf_cache (rcs, &rcsbuf);
923 * freercsnode - free up the info for an RCSNode
929 if (rnodep == NULL || *rnodep == NULL)
932 ((*rnodep)->refcount)--;
933 if ((*rnodep)->refcount != 0)
935 *rnodep = (RCSNode *) NULL;
938 free ((*rnodep)->path);
939 if ((*rnodep)->head != (char *) NULL)
940 free ((*rnodep)->head);
941 if ((*rnodep)->branch != (char *) NULL)
942 free ((*rnodep)->branch);
943 free_rcsnode_contents (*rnodep);
944 free ((char *) *rnodep);
945 *rnodep = (RCSNode *) NULL;
949 * free_rcsnode_contents - free up the contents of an RCSNode without
950 * freeing the node itself, or the file name, or the head, or the
951 * path. This returns the RCSNode to the state it is in immediately
952 * after a call to RCS_parse.
955 free_rcsnode_contents (rnode)
958 dellist (&rnode->versions);
959 if (rnode->symbols != (List *) NULL)
960 dellist (&rnode->symbols);
961 if (rnode->symbols_data != (char *) NULL)
962 free (rnode->symbols_data);
963 if (rnode->expand != NULL)
964 free (rnode->expand);
965 if (rnode->other != (List *) NULL)
966 dellist (&rnode->other);
967 if (rnode->access != NULL)
968 free (rnode->access);
969 if (rnode->locks_data != NULL)
970 free (rnode->locks_data);
971 if (rnode->locks != (List *) NULL)
972 dellist (&rnode->locks);
973 if (rnode->comment != NULL)
974 free (rnode->comment);
975 if (rnode->desc != NULL)
979 /* free_rcsvers_contents -- free up the contents of an RCSVers node,
980 but also free the pointer to the node itself. */
981 /* Note: The `hardlinks' list is *not* freed, since it is merely a
982 pointer into the `hardlist' structure (defined in hardlink.c), and
983 that structure is freed elsewhere in the program. */
986 free_rcsvers_contents (rnode)
989 if (rnode->branches != (List *) NULL)
990 dellist (&rnode->branches);
991 if (rnode->date != (char *) NULL)
993 if (rnode->next != (char *) NULL)
995 if (rnode->author != (char *) NULL)
996 free (rnode->author);
997 if (rnode->state != (char *) NULL)
999 if (rnode->other != (List *) NULL)
1000 dellist (&rnode->other);
1001 if (rnode->other_delta != NULL)
1002 dellist (&rnode->other_delta);
1003 if (rnode->text != NULL)
1004 freedeltatext (rnode->text);
1005 free ((char *) rnode);
1009 * rcsvers_delproc - free up an RCSVers type node
1015 free_rcsvers_contents (p->data);
1018 /* These functions retrieve keys and values from an RCS file using a
1019 buffer. We use this somewhat complex approach because it turns out
1020 that for many common operations, CVS spends most of its time
1021 reading keys, so it's worth doing some fairly hairy optimization. */
1023 /* The number of bytes we try to read each time we need more data. */
1025 #define RCSBUF_BUFSIZE (8192)
1027 /* The buffer we use to store data. This grows as needed. */
1029 static char *rcsbuf_buffer = NULL;
1030 static size_t rcsbuf_buffer_size = 0;
1032 /* Whether rcsbuf_buffer is in use. This is used as a sanity check. */
1034 static int rcsbuf_inuse;
1036 /* Set up to start gathering keys and values from an RCS file. This
1037 initializes RCSBUF. */
1040 rcsbuf_open (rcsbuf, fp, filename, pos)
1041 struct rcsbuffer *rcsbuf;
1043 const char *filename;
1049 size_t mmap_off = 0;
1053 error (1, 0, "rcsbuf_open: internal error");
1057 /* When we have mmap, it is much more efficient to let the system do the
1058 * buffering and caching for us
1061 if ( fstat (fileno(fp), &fs) < 0 )
1062 error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
1066 size_t ps = getpagesize ();
1067 mmap_off = ( pos / ps ) * ps;
1070 /* Map private here since this particular buffer is read only */
1071 p = mmap ( NULL, fs.st_size - mmap_off, PROT_READ | PROT_WRITE,
1072 MAP_PRIVATE, fileno(fp), mmap_off );
1073 if (p != NULL && p != MAP_FAILED)
1075 if (rcsbuf_buffer) free (rcsbuf_buffer);
1077 rcsbuf_buffer_size = fs.st_size - mmap_off;
1078 rcsbuf->mmapped = 1;
1079 rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
1080 rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
1081 rcsbuf->pos = mmap_off;
1085 #ifndef MMAP_FALLBACK_TEST
1086 error (0, errno, "Could not map memory to RCS archive %s", filename);
1088 #endif /* HAVE_MMAP */
1089 if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
1090 expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
1092 rcsbuf->mmapped = 0;
1093 rcsbuf->ptr = rcsbuf_buffer;
1094 rcsbuf->ptrend = rcsbuf_buffer;
1098 #endif /* HAVE_MMAP */
1100 rcsbuf->filename = filename;
1102 rcsbuf->at_string = 0;
1103 rcsbuf->embedded_at = 0;
1106 /* Stop gathering keys from an RCS file. */
1109 rcsbuf_close (rcsbuf)
1110 struct rcsbuffer *rcsbuf;
1113 error (1, 0, "rcsbuf_close: internal error");
1115 if (rcsbuf->mmapped)
1117 munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
1118 rcsbuf_buffer = NULL;
1119 rcsbuf_buffer_size = 0;
1125 /* Read a key/value pair from an RCS file. This sets *KEYP to point
1126 to the key, and *VALUEP to point to the value. A missing or empty
1127 value is indicated by setting *VALUEP to NULL.
1129 This function returns 1 on success, or 0 on EOF. If there is an
1130 error reading the file, or an EOF in an unexpected location, it
1131 gives a fatal error.
1133 This sets *KEYP and *VALUEP to point to storage managed by
1134 rcsbuf_getkey. Moreover, *VALUEP has not been massaged from the
1135 RCS format: it may contain embedded whitespace and embedded '@'
1136 characters. Call rcsbuf_valcopy or rcsbuf_valpolish to do
1137 appropriate massaging. */
1139 /* Note that the extreme hair in rcsbuf_getkey is because profiling
1140 statistics show that it was worth it. */
1143 rcsbuf_getkey (rcsbuf, keyp, valp)
1144 struct rcsbuffer *rcsbuf;
1148 register const char * const my_spacetab = spacetab;
1149 register char *ptr, *ptrend;
1152 #define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
1155 rcsbuf->at_string = 0;
1156 rcsbuf->embedded_at = 0;
1159 ptrend = rcsbuf->ptrend;
1162 assert (ptr >= rcsbuf_buffer && ptr <= rcsbuf_buffer + rcsbuf_buffer_size);
1163 assert (ptrend >= rcsbuf_buffer && ptrend <= rcsbuf_buffer + rcsbuf_buffer_size);
1165 /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
1166 buffer, move back to the start of the buffer. This keeps the
1167 buffer from growing indefinitely. */
1168 if (!rcsbuf->mmapped && ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
1174 /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
1175 at a time, so we can't have more bytes than that past PTR. */
1176 assert (len <= RCSBUF_BUFSIZE);
1178 /* Update the POS field, which holds the file offset of the
1179 first byte in the RCSBUF_BUFFER buffer. */
1180 rcsbuf->pos += ptr - rcsbuf_buffer;
1182 memcpy (rcsbuf_buffer, ptr, len);
1183 ptr = rcsbuf_buffer;
1185 rcsbuf->ptrend = ptrend;
1188 /* Skip leading whitespace. */
1194 ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
1197 ptrend = rcsbuf->ptrend;
1201 if (! my_whitespace (c))
1207 /* We've found the start of the key. */
1218 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
1220 error (1, 0, "EOF in key in RCS file %s",
1222 ptrend = rcsbuf->ptrend;
1225 if (c == ';' || my_whitespace (c))
1230 /* Here *KEYP points to the key in the buffer, C is the character
1231 we found at the of the key, and PTR points to the location in
1232 the buffer where we found C. We must set *PTR to \0 in order
1233 to terminate the key. If the key ended with ';', then there is
1246 /* C must be whitespace. Skip whitespace between the key and the
1247 value. If we find ';' now, there is no value. */
1253 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
1255 error (1, 0, "EOF while looking for value in RCS file %s",
1257 ptrend = rcsbuf->ptrend;
1263 rcsbuf->ptr = ptr + 1;
1266 if (! my_whitespace (c))
1271 /* Now PTR points to the start of the value, and C is the first
1272 character of the value. */
1281 /* Optimize the common case of a value composed of a single
1284 rcsbuf->at_string = 1;
1292 while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
1294 /* Note that we pass PTREND as the PTR value to
1295 rcsbuf_fill, so that we will wind up setting PTR to
1296 the location corresponding to the old PTREND, so
1297 that we don't search the same bytes again. */
1298 ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1301 "EOF while looking for end of string in RCS file %s",
1303 ptrend = rcsbuf->ptrend;
1306 /* Handle the special case of an '@' right at the end of
1308 if (pat + 1 >= ptrend)
1310 /* Note that we pass PAT, not PTR, here. */
1311 pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
1314 /* EOF here is OK; it just means that the last
1315 character of the file was an '@' terminating a
1316 value for a key type which does not require a
1318 pat = rcsbuf->ptrend - 1;
1321 ptrend = rcsbuf->ptrend;
1323 /* Note that the value of PTR is bogus here. This is
1324 OK, because we don't use it. */
1327 if (pat + 1 >= ptrend || pat[1] != '@')
1330 /* We found an '@' pair in the string. Keep looking. */
1331 ++rcsbuf->embedded_at;
1335 /* Here PAT points to the final '@' in the string. */
1342 rcsbuf->vlen = vlen;
1347 /* Certain keywords only have a '@' string. If there is no '@'
1348 string, then the old getrcskey function assumed that they had
1349 no value, and we do the same. */
1355 if (STREQ (k, RCSDESC)
1356 || STREQ (k, "text")
1357 || STREQ (k, "log"))
1366 /* If we've already gathered a '@' string, try to skip whitespace
1376 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
1378 error (1, 0, "EOF in value in RCS file %s",
1380 ptrend = rcsbuf->ptrend;
1385 /* We're done. We already set everything up for this
1387 rcsbuf->ptr = ptr + 1;
1390 if (! my_whitespace (n))
1395 /* The value extends past the '@' string. We need to undo the
1396 '@' stripping done in the default case above. This
1397 case never happens in a plain RCS file, but it can happen
1398 if user defined phrases are used. */
1399 ((*valp)--)[rcsbuf->vlen++] = '@';
1402 /* Here we have a value which is not a simple '@' string. We need
1403 to gather up everything until the next ';', including any '@'
1404 strings. *VALP points to the start of the value. If
1405 RCSBUF->VLEN is not zero, then we have already read an '@'
1406 string, and PTR points to the data following the '@' string.
1407 Otherwise, PTR points to the start of the value. */
1411 char *start, *psemi, *pat;
1413 /* Find the ';' which must end the value. */
1415 while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
1419 /* Note that we pass PTREND as the PTR value to
1420 rcsbuf_fill, so that we will wind up setting PTR to the
1421 location corresponding to the old PTREND, so that we
1422 don't search the same bytes again. */
1423 slen = start - *valp;
1424 ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1426 error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
1427 start = *valp + slen;
1428 ptrend = rcsbuf->ptrend;
1431 /* See if there are any '@' strings in the value. */
1432 pat = memchr (start, '@', psemi - start);
1438 /* We're done with the value. Trim any trailing
1441 rcsbuf->ptr = psemi + 1;
1444 while (psemi > start && my_whitespace (psemi[-1]))
1448 vlen = psemi - start;
1451 rcsbuf->vlen = vlen;
1456 /* We found an '@' string in the value. We set RCSBUF->AT_STRING
1457 and RCSBUF->EMBEDDED_AT to indicate that we won't be able to
1458 compress whitespace correctly for this type of value.
1459 Since this type of value never arises in a normal RCS file,
1460 this should not be a big deal. It means that if anybody
1461 adds a phrase which can have both an '@' string and regular
1462 text, they will have to handle whitespace compression
1465 rcsbuf->at_string = 1;
1466 rcsbuf->embedded_at = -1;
1472 while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
1474 /* Note that we pass PTREND as the PTR value to
1475 rcsbuff_fill, so that we will wind up setting PTR
1476 to the location corresponding to the old PTREND, so
1477 that we don't search the same bytes again. */
1478 ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1481 "EOF while looking for end of string in RCS file %s",
1483 ptrend = rcsbuf->ptrend;
1486 /* Handle the special case of an '@' right at the end of
1488 if (pat + 1 >= ptrend)
1490 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
1492 error (1, 0, "EOF in value in RCS file %s",
1494 ptrend = rcsbuf->ptrend;
1500 /* We found an '@' pair in the string. Keep looking. */
1504 /* Here PAT points to the final '@' in the string. */
1508 #undef my_whitespace
1511 /* Read an RCS revision number from an RCS file. This sets *REVP to
1512 point to the revision number; it will point to space that is
1513 managed by the rcsbuf functions, and is only good until the next
1514 call to rcsbuf_getkey or rcsbuf_getrevnum.
1516 This function returns 1 on success, or 0 on EOF. If there is an
1517 error reading the file, or an EOF in an unexpected location, it
1518 gives a fatal error. */
1521 rcsbuf_getrevnum (rcsbuf, revp)
1522 struct rcsbuffer *rcsbuf;
1529 ptrend = rcsbuf->ptrend;
1533 /* Skip leading whitespace. */
1539 ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
1542 ptrend = rcsbuf->ptrend;
1546 if (! whitespace (c))
1552 if (! isdigit ((unsigned char) c) && c != '.')
1555 unexpected '\\x%x' reading revision number in RCS file %s",
1556 c, rcsbuf->filename);
1565 ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
1568 "unexpected EOF reading revision number in RCS file %s",
1570 ptrend = rcsbuf->ptrend;
1575 while (isdigit ((unsigned char) c) || c == '.');
1577 if (! whitespace (c))
1579 unexpected '\\x%x' reading revision number in RCS file %s",
1580 c, rcsbuf->filename);
1584 rcsbuf->ptr = ptr + 1;
1589 /* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
1590 updating PTR and the PTREND field. If KEYP and *KEYP are not NULL,
1591 then *KEYP points into the buffer, and must be adjusted if the
1592 buffer is changed. Likewise for VALP. Returns the new value of
1593 PTR, or NULL on error. */
1596 rcsbuf_fill (rcsbuf, ptr, keyp, valp)
1597 struct rcsbuffer *rcsbuf;
1604 if (rcsbuf->mmapped)
1607 if (rcsbuf->ptrend - rcsbuf_buffer + RCSBUF_BUFSIZE > rcsbuf_buffer_size)
1609 int poff, peoff, koff, voff;
1611 poff = ptr - rcsbuf_buffer;
1612 peoff = rcsbuf->ptrend - rcsbuf_buffer;
1613 koff = keyp == NULL ? 0 : *keyp - rcsbuf_buffer;
1614 voff = valp == NULL ? 0 : *valp - rcsbuf_buffer;
1616 expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size,
1617 rcsbuf_buffer_size + RCSBUF_BUFSIZE);
1619 ptr = rcsbuf_buffer + poff;
1620 rcsbuf->ptrend = rcsbuf_buffer + peoff;
1622 *keyp = rcsbuf_buffer + koff;
1624 *valp = rcsbuf_buffer + voff;
1627 got = fread (rcsbuf->ptrend, 1, RCSBUF_BUFSIZE, rcsbuf->fp);
1630 if (ferror (rcsbuf->fp))
1631 error (1, errno, "cannot read %s", rcsbuf->filename);
1635 rcsbuf->ptrend += got;
1640 /* Test whether the last value returned by rcsbuf_getkey is a composite
1644 rcsbuf_valcmp (rcsbuf)
1645 struct rcsbuffer *rcsbuf;
1647 return rcsbuf->at_string && rcsbuf->embedded_at < 0;
1650 /* Copy the value VAL returned by rcsbuf_getkey into a memory buffer,
1651 returning the memory buffer. Polish the value like
1652 rcsbuf_valpolish, q.v. */
1655 rcsbuf_valcopy (rcsbuf, val, polish, lenp)
1656 struct rcsbuffer *rcsbuf;
1672 vlen = rcsbuf->vlen;
1673 embedded_at = rcsbuf->embedded_at < 0 ? 0 : rcsbuf->embedded_at;
1675 ret = xmalloc (vlen - embedded_at + 1);
1677 if (rcsbuf->at_string ? embedded_at == 0 : ! polish)
1679 /* No special action to take. */
1680 memcpy (ret, val, vlen + 1);
1686 rcsbuf_valpolish_internal (rcsbuf, ret, val, lenp);
1690 /* Polish the value VAL returned by rcsbuf_getkey. The POLISH
1691 parameter is non-zero if multiple embedded whitespace characters
1692 should be compressed into a single whitespace character. Note that
1693 leading and trailing whitespace was already removed by
1694 rcsbuf_getkey. Within an '@' string, pairs of '@' characters are
1695 compressed into a single '@' character regardless of the value of
1696 POLISH. If LENP is not NULL, set *LENP to the length of the value. */
1699 rcsbuf_valpolish (rcsbuf, val, polish, lenp)
1700 struct rcsbuffer *rcsbuf;
1712 if (rcsbuf->at_string ? rcsbuf->embedded_at == 0 : ! polish)
1714 /* No special action to take. */
1716 *lenp = rcsbuf->vlen;
1720 rcsbuf_valpolish_internal (rcsbuf, val, val, lenp);
1723 /* Internal polishing routine, called from rcsbuf_valcopy and
1724 rcsbuf_valpolish. */
1727 rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
1728 struct rcsbuffer *rcsbuf;
1737 if (! rcsbuf->at_string)
1744 for (clen = len; clen > 0; ++from, --clen)
1751 /* Note that we know that clen can not drop to zero
1752 while we have whitespace, because we know there is
1753 no trailing whitespace. */
1754 while (whitespace (from[1]))
1767 *lenp = to - orig_to;
1771 const char *orig_from;
1779 embedded_at = rcsbuf->embedded_at;
1780 assert (embedded_at > 0);
1783 *lenp = len - embedded_at;
1785 for (clen = len; clen > 0; ++from, --clen)
1797 * FIXME: I restored this to an abort from an assert based on
1798 * advice from Larry Jones that asserts should not be used to
1799 * confirm the validity of an RCS file... This leaves two
1800 * issues here: 1) I am uncertain that the fact that we will
1801 * only find double '@'s hasn't already been confirmed; and:
1802 * 2) If this is the proper place to spot the error in the RCS
1803 * file, then we should print a much clearer error here for the
1808 if (*from != '@' || clen == 0)
1814 if (embedded_at == 0)
1816 /* We've found all the embedded '@' characters.
1817 We can just memcpy the rest of the buffer after
1818 this '@' character. */
1819 if (orig_to != orig_from)
1820 memcpy (to, from + 1, clen - 1);
1822 memmove (to, from + 1, clen - 1);
1831 assert (from == orig_from + len
1832 && to == orig_to + (len - rcsbuf->embedded_at));
1838 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1840 /* Copy the next word from the value VALP returned by rcsbuf_getkey into a
1841 memory buffer, updating VALP and returning the memory buffer. Return
1842 NULL when there are no more words. */
1845 rcsbuf_valword (rcsbuf, valp)
1846 struct rcsbuffer *rcsbuf;
1849 register const char * const my_spacetab = spacetab;
1850 register char *ptr, *pat;
1853 # define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
1858 for (ptr = *valp; my_whitespace (*ptr); ++ptr) ;
1861 assert (ptr - *valp == rcsbuf->vlen);
1867 /* PTR now points to the start of a value. Find out whether it is
1868 a num, an id, a string or a colon. */
1872 rcsbuf->vlen -= ++ptr - *valp;
1874 return xstrdup (":");
1879 int embedded_at = 0;
1883 while ((pat = strchr (pat, '@')) != NULL)
1891 /* Here PAT points to the final '@' in the string. */
1893 assert (rcsbuf->at_string);
1894 vlen = rcsbuf->vlen - (pat - *valp);
1895 rcsbuf->vlen = pat - ptr - 1;
1896 rcsbuf->embedded_at = embedded_at;
1897 ptr = rcsbuf_valcopy (rcsbuf, ptr, 0, (size_t *) NULL);
1899 rcsbuf->vlen = vlen;
1900 if (strchr (pat, '@') == NULL)
1901 rcsbuf->at_string = 0;
1903 rcsbuf->embedded_at = -1;
1907 /* *PTR is neither `:', `;' nor `@', so it should be the start of a num
1908 or an id. Make sure it is not another special character. */
1909 if (c == '$' || c == '.' || c == ',')
1911 error (1, 0, "invalid special character in RCS field in %s",
1918 /* Legitimate ID characters are digits, dots and any `graphic
1919 printing character that is not a special.' This test ought
1922 if (!isprint ((unsigned char) c) ||
1923 c == ';' || c == '$' || c == ',' || c == '@' || c == ':')
1927 /* PAT points to the last non-id character in this word, and C is
1928 the character in its memory cell. Check to make sure that it
1929 is a legitimate word delimiter -- whitespace or end. */
1930 if (c != '\0' && !my_whitespace (c))
1931 error (1, 0, "invalid special character in RCS field in %s",
1935 rcsbuf->vlen -= pat - *valp;
1937 return xstrdup (ptr);
1939 # undef my_whitespace
1944 /* Return the current position of an rcsbuf. */
1946 static unsigned long
1947 rcsbuf_ftell (rcsbuf)
1948 struct rcsbuffer *rcsbuf;
1950 return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer);
1953 /* Return a pointer to any data buffered for RCSBUF, along with the
1957 rcsbuf_get_buffered (rcsbuf, datap, lenp)
1958 struct rcsbuffer *rcsbuf;
1962 *datap = rcsbuf->ptr;
1963 *lenp = rcsbuf->ptrend - rcsbuf->ptr;
1966 /* CVS optimizes by quickly reading some header information from a
1967 file. If it decides it needs to do more with the file, it reopens
1968 it. We speed that up here by maintaining a cache of a single open
1969 file, to save the time it takes to reopen the file in the common
1972 static RCSNode *cached_rcs;
1973 static struct rcsbuffer cached_rcsbuf;
1975 /* Cache RCS and RCSBUF. This takes responsibility for closing
1979 rcsbuf_cache (rcs, rcsbuf)
1981 struct rcsbuffer *rcsbuf;
1983 if (cached_rcs != NULL)
1984 rcsbuf_cache_close ();
1987 cached_rcsbuf = *rcsbuf;
1990 /* If there is anything in the cache, close it. */
1993 rcsbuf_cache_close ()
1995 if (cached_rcs != NULL)
1997 rcsbuf_close (&cached_rcsbuf);
1998 if (fclose (cached_rcsbuf.fp) != 0)
1999 error (0, errno, "cannot close %s", cached_rcsbuf.filename);
2000 freercsnode (&cached_rcs);
2005 /* Open an rcsbuffer for RCS, getting it from the cache if possible.
2006 Set *FPP to the file, and *RCSBUFP to the rcsbuf. The file should
2007 be put at position POS. */
2010 rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
2014 struct rcsbuffer *prcsbuf;
2016 if (cached_rcs == rcs && !cached_rcsbuf.mmapped)
2018 if (rcsbuf_ftell (&cached_rcsbuf) != pos)
2020 if (fseek (cached_rcsbuf.fp, pos, SEEK_SET) != 0)
2021 error (1, 0, "cannot fseek RCS file %s",
2022 cached_rcsbuf.filename);
2023 cached_rcsbuf.ptr = rcsbuf_buffer;
2024 cached_rcsbuf.ptrend = rcsbuf_buffer;
2025 cached_rcsbuf.pos = pos;
2027 *pfp = cached_rcsbuf.fp;
2029 /* When RCS_parse opens a file using fopen_case, it frees the
2030 filename which we cached in CACHED_RCSBUF and stores a new
2031 file name in RCS->PATH. We avoid problems here by always
2032 copying the filename over. FIXME: This is hackish. */
2033 cached_rcsbuf.filename = rcs->path;
2035 *prcsbuf = cached_rcsbuf;
2039 /* Removing RCS from the cache removes a reference to it. */
2041 if (rcs->refcount <= 0)
2042 error (1, 0, "rcsbuf_cache_open: internal error");
2046 /* FIXME: If these routines can be rewritten to not write to the
2047 * rcs file buffer, there would be a considerably larger memory savings
2048 * from using mmap since the shared file would never need be copied to
2051 * If this happens, cached mmapped buffers would be usable, but don't
2052 * forget to make sure rcs->pos < pos here...
2054 if (cached_rcs != NULL)
2055 rcsbuf_cache_close ();
2057 *pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
2059 error (1, 0, "unable to reopen `%s'", rcs->path);
2062 if (fseek (*pfp, pos, SEEK_SET) != 0)
2063 error (1, 0, "cannot fseek RCS file %s", rcs->path);
2065 rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
2071 * process the symbols list of the rcs file
2074 do_symbols (list, val)
2086 /* skip leading whitespace */
2087 while (whitespace (*cp))
2090 /* if we got to the end, we are done */
2094 /* split it up into tag and rev */
2096 cp = strchr (cp, ':');
2099 while (!whitespace (*cp) && *cp != '\0')
2104 /* make a new node and add it to the list */
2106 p->key = xstrdup (tag);
2107 p->data = xstrdup (rev);
2108 (void) addnode (list, p);
2113 * process the locks list of the rcs file
2114 * Like do_symbols, but hash entries are keyed backwards: i.e.
2115 * an entry like `user:rev' is keyed on REV rather than on USER.
2118 do_locks (list, val)
2130 /* skip leading whitespace */
2131 while (whitespace (*cp))
2134 /* if we got to the end, we are done */
2138 /* split it up into user and rev */
2140 cp = strchr (cp, ':');
2143 while (!whitespace (*cp) && *cp != '\0')
2148 /* make a new node and add it to the list */
2150 p->key = xstrdup (rev);
2151 p->data = xstrdup (user);
2152 (void) addnode (list, p);
2157 * process the branches list of a revision delta
2160 do_branches (list, val)
2170 /* skip leading whitespace */
2171 while (whitespace (*cp))
2174 /* if we got to the end, we are done */
2178 /* find the end of this branch */
2180 while (!whitespace (*cp) && *cp != '\0')
2185 /* make a new node and add it to the list */
2187 p->key = xstrdup (branch);
2188 (void) addnode (list, p);
2195 * Returns the requested version number of the RCS file, satisfying tags and/or
2196 * dates, and walking branches, if necessary.
2198 * The result is returned; null-string if error.
2201 RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
2205 int force_tag_match;
2208 if (simple_tag != NULL)
2211 /* make sure we have something to look at... */
2212 assert (rcs != NULL);
2218 if (! RCS_nodeisbranch (rcs, tag))
2220 /* We can't get a particular date if the tag is not a
2225 /* Work out the branch. */
2226 if (! isdigit ((unsigned char) tag[0]))
2227 branch = RCS_whatbranch (rcs, tag);
2229 branch = xstrdup (tag);
2231 /* Fetch the revision of branch as of date. */
2232 rev = RCS_getdatebranch (rcs, date, branch);
2237 return RCS_gettag (rcs, tag, force_tag_match, simple_tag);
2239 return RCS_getdate (rcs, date, force_tag_match);
2241 return RCS_head (rcs);
2248 * Get existing revision number corresponding to tag or revision.
2249 * Similar to RCS_gettag but less interpretation imposed.
2251 * -- If tag designates a magic branch, RCS_tag2rev
2252 * returns the magic branch number.
2253 * -- If tag is a branch tag, returns the branch number, not
2254 * the revision of the head of the branch.
2255 * If tag or revision is not valid or does not exist in file,
2259 RCS_tag2rev (rcs, tag)
2263 char *rev, *pa, *pb;
2266 assert (rcs != NULL);
2268 if (rcs->flags & PARTIAL)
2269 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2271 /* If a valid revision, try to look it up */
2272 if ( RCS_valid_rev (tag) )
2274 /* Make a copy so we can scribble on it */
2275 rev = xstrdup (tag);
2277 /* If revision exists, return the copy */
2278 if (RCS_exist_rev (rcs, tag))
2281 /* Nope, none such. If tag is not a branch we're done. */
2285 pa = strrchr (rev, '.');
2286 if (i == 1 || *(pa-1) != RCS_MAGIC_BRANCH || *(pa-2) != '.')
2289 error (1, 0, "revision `%s' does not exist", tag);
2293 /* Try for a real (that is, exists in the RCS deltas) branch
2294 (RCS_exist_rev just checks for real revisions and revisions
2295 which have tags pointing to them). */
2296 pa = RCS_getbranch (rcs, rev, 1);
2303 /* Tag is branch, but does not exist, try corresponding
2306 * FIXME: assumes all magic branches are of
2307 * form "n.n.n ... .0.n". I'll fix if somebody can
2308 * send me a method to get a magic branch tag with
2309 * the 0 in some other position -- <dan@gasboy.com>
2311 pa = strrchr (rev, '.');
2313 /* This might happen, for instance, if an RCS file only contained
2314 * revisions 2.x and higher, and REV == "1".
2316 error (1, 0, "revision `%s' does not exist", tag);
2318 pb = xmalloc (strlen (rev) + 3);
2320 (void) sprintf (pb, "%s.%d.%s", rev, RCS_MAGIC_BRANCH, pa);
2323 if (RCS_exist_rev (rcs, rev))
2325 error (1, 0, "revision `%s' does not exist", tag);
2329 RCS_check_tag (tag); /* exit if not a valid tag */
2331 /* If tag is "HEAD", special case to get head RCS revision */
2332 if (tag && STREQ (tag, TAG_HEAD))
2333 return (RCS_head (rcs));
2335 /* If valid tag let translate_symtag say yea or nay. */
2336 rev = translate_symtag (rcs, tag);
2341 /* Trust the caller to print warnings. */
2346 * Find the revision for a specific tag.
2347 * If force_tag_match is set, return NULL if an exact match is not
2348 * possible otherwise return RCS_head (). We are careful to look for
2349 * and handle "magic" revisions specially.
2351 * If the matched tag is a branch tag, find the head of the branch.
2353 * Returns pointer to newly malloc'd string, or NULL.
2356 RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
2359 int force_tag_match;
2364 if (simple_tag != NULL)
2367 /* make sure we have something to look at... */
2368 assert (rcs != NULL);
2370 /* XXX this is probably not necessary, --jtc */
2371 if (rcs->flags & PARTIAL)
2372 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2374 /* If symtag is "HEAD", special case to get head RCS revision */
2375 if (symtag && STREQ (symtag, TAG_HEAD))
2376 #if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
2377 if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
2378 return ((char *) NULL); /* head request for removed file */
2381 return RCS_head (rcs);
2383 if (!isdigit ((unsigned char) symtag[0]))
2387 /* If we got a symbolic tag, resolve it to a numeric */
2388 version = translate_symtag (rcs, symtag);
2389 if (version != NULL)
2392 char *magic, *branch, *cp;
2397 * If this is a magic revision, we turn it into either its
2398 * physical branch equivalent (if one exists) or into
2399 * its base revision, which we assume exists.
2401 dots = numdots (tag);
2402 if (dots > 2 && (dots & 1) != 0)
2404 branch = strrchr (tag, '.');
2409 /* see if we have .magic-branch. (".0.") */
2410 magic = xmalloc (strlen (tag) + 1);
2411 (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2412 if (strncmp (magic, cp, strlen (magic)) == 0)
2414 /* it's magic. See if the branch exists */
2415 *cp = '\0'; /* turn it into a revision */
2416 (void) sprintf (magic, "%s.%s", tag, branch);
2417 branch = RCS_getbranch (rcs, magic, 1);
2431 /* The tag wasn't there, so return the head or NULL */
2432 if (force_tag_match)
2435 return RCS_head (rcs);
2439 tag = xstrdup (symtag);
2441 /* tag is always allocated and numeric now. */
2444 * numeric tag processing:
2445 * 1) revision number - just return it
2446 * 2) branch number - find head of branch
2449 /* strip trailing dots */
2450 while (tag[strlen (tag) - 1] == '.')
2451 tag[strlen (tag) - 1] = '\0';
2453 if ((numdots (tag) & 1) == 0)
2457 /* we have a branch tag, so we need to walk the branch */
2458 branch = RCS_getbranch (rcs, tag, force_tag_match);
2466 /* we have a revision tag, so make sure it exists */
2467 p = findnode (rcs->versions, tag);
2470 /* We have found a numeric revision for the revision tag.
2471 To support expanding the RCS keyword Name, if
2472 SIMPLE_TAG is not NULL, tell the the caller that this
2473 is a simple tag which co will recognize. FIXME: Are
2474 there other cases in which we should set this? In
2475 particular, what if we expand RCS keywords internally
2476 without calling co? */
2477 if (simple_tag != NULL)
2483 /* The revision wasn't there, so return the head or NULL */
2485 if (force_tag_match)
2488 return RCS_head (rcs);
2494 * Return a "magic" revision as a virtual branch off of REV for the RCS file.
2495 * A "magic" revision is one which is unique in the RCS file. By unique, I
2496 * mean we return a revision which:
2497 * - has a branch of 0 (see rcs.h RCS_MAGIC_BRANCH)
2498 * - has a revision component which is not an existing branch off REV
2499 * - has a revision component which is not an existing magic revision
2500 * - is an even-numbered revision, to avoid conflicts with vendor branches
2501 * The first point is what makes it "magic".
2503 * As an example, if we pass in 1.37 as REV, we will look for an existing
2504 * branch called 1.37.2. If it did not exist, we would look for an
2505 * existing symbolic tag with a numeric part equal to 1.37.0.2. If that
2506 * didn't exist, then we know that the 1.37.2 branch can be reserved by
2507 * creating a symbolic tag with 1.37.0.2 as the numeric part.
2509 * This allows us to fork development with very little overhead -- just a
2510 * symbolic tag is used in the RCS file. When a commit is done, a physical
2511 * branch is dynamically created to hold the new revision.
2513 * Note: We assume that REV is an RCS revision and not a branch number.
2515 static char *check_rev;
2517 RCS_magicrev (rcs, rev)
2522 char *xrev, *test_branch, *local_branch_num;
2524 xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
2527 local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM");
2528 if (local_branch_num)
2530 rev_num = atoi(local_branch_num);
2539 /* only look at even numbered branches */
2540 for ( ; ; rev_num += 2)
2542 /* see if the physical branch exists */
2543 (void) sprintf (xrev, "%s.%d", rev, rev_num);
2544 test_branch = RCS_getbranch (rcs, xrev, 1);
2545 if (test_branch != NULL) /* it did, so keep looking */
2551 /* now, create a "magic" revision */
2552 (void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
2554 /* walk the symbols list to see if a magic one already exists */
2555 if (walklist (RCS_symbols(rcs), checkmagic_proc, NULL) != 0)
2558 /* we found a free magic branch. Claim it as ours */
2564 * walklist proc to look for a match in the symbols list.
2565 * Returns 0 if the symbol does not match, 1 if it does.
2568 checkmagic_proc (p, closure)
2572 if (STREQ (check_rev, p->data))
2579 * Given an RCSNode, returns non-zero if the specified revision number
2580 * or symbolic tag resolves to a "branch" within the rcs file.
2582 * FIXME: this is the same as RCS_nodeisbranch except for the special
2583 * case for handling a null rcsnode.
2586 RCS_isbranch (rcs, rev)
2590 /* numeric revisions are easy -- even number of dots is a branch */
2591 if (isdigit ((unsigned char) *rev))
2592 return ((numdots (rev) & 1) == 0);
2594 /* assume a revision if you can't find the RCS info */
2598 /* now, look for a match in the symbols list */
2599 return (RCS_nodeisbranch (rcs, rev));
2603 * Given an RCSNode, returns non-zero if the specified revision number
2604 * or symbolic tag resolves to a "branch" within the rcs file. We do
2605 * take into account any magic branches as well.
2608 RCS_nodeisbranch (rcs, rev)
2615 assert (rcs != NULL);
2617 /* numeric revisions are easy -- even number of dots is a branch */
2618 if (isdigit ((unsigned char) *rev))
2619 return ((numdots (rev) & 1) == 0);
2621 version = translate_symtag (rcs, rev);
2622 if (version == NULL)
2624 dots = numdots (version);
2625 if ((dots & 1) == 0)
2631 /* got a symbolic tag match, but it's not a branch; see if it's magic */
2635 char *branch = strrchr (version, '.');
2636 char *cp = branch - 1;
2640 /* see if we have .magic-branch. (".0.") */
2641 magic = xmalloc (strlen (version) + 1);
2642 (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2643 if (strncmp (magic, cp, strlen (magic)) == 0)
2656 * Returns a pointer to malloc'ed memory which contains the branch
2657 * for the specified *symbolic* tag. Magic branches are handled correctly.
2660 RCS_whatbranch (rcs, rev)
2667 /* assume no branch if you can't find the RCS info */
2669 return ((char *) NULL);
2671 /* now, look for a match in the symbols list */
2672 version = translate_symtag (rcs, rev);
2673 if (version == NULL)
2674 return ((char *) NULL);
2675 dots = numdots (version);
2676 if ((dots & 1) == 0)
2679 /* got a symbolic tag match, but it's not a branch; see if it's magic */
2683 char *branch = strrchr (version, '.');
2684 char *cp = branch++ - 1;
2688 /* see if we have .magic-branch. (".0.") */
2689 magic = xmalloc (strlen (version) + 1);
2690 (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2691 if (strncmp (magic, cp, strlen (magic)) == 0)
2693 /* yep. it's magic. now, construct the real branch */
2694 *cp = '\0'; /* turn it into a revision */
2695 (void) sprintf (magic, "%s.%s", version, branch);
2702 return ((char *) NULL);
2706 * Get the head of the specified branch. If the branch does not exist,
2707 * return NULL or RCS_head depending on force_tag_match.
2708 * Returns NULL or a newly malloc'd string.
2711 RCS_getbranch (rcs, tag, force_tag_match)
2714 int force_tag_match;
2722 /* make sure we have something to look at... */
2723 assert (rcs != NULL);
2725 if (rcs->flags & PARTIAL)
2726 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2728 /* find out if the tag contains a dot, or is on the trunk */
2729 cp = strrchr (tag, '.');
2731 /* trunk processing is the special case */
2734 xtag = xmalloc (strlen (tag) + 1 + 1); /* +1 for an extra . */
2735 (void) strcpy (xtag, tag);
2736 (void) strcat (xtag, ".");
2737 for (cp = rcs->head; cp != NULL;)
2739 if (strncmp (xtag, cp, strlen (xtag)) == 0)
2741 p = findnode (rcs->versions, cp);
2745 if (force_tag_match)
2748 return (RCS_head (rcs));
2756 if (force_tag_match)
2759 return (RCS_head (rcs));
2761 return (xstrdup (cp));
2764 /* if it had a `.', terminate the string so we have the base revision */
2767 /* look up the revision this branch is based on */
2768 p = findnode (rcs->versions, tag);
2770 /* put the . back so we have the branch again */
2775 /* if the base revision didn't exist, return head or NULL */
2776 if (force_tag_match)
2779 return (RCS_head (rcs));
2782 /* find the first element of the branch we are looking for */
2784 if (vn->branches == NULL)
2786 xtag = xmalloc (strlen (tag) + 1 + 1); /* 1 for the extra '.' */
2787 (void) strcpy (xtag, tag);
2788 (void) strcat (xtag, ".");
2789 head = vn->branches->list;
2790 for (p = head->next; p != head; p = p->next)
2791 if (strncmp (p->key, xtag, strlen (xtag)) == 0)
2797 /* we didn't find a match so return head or NULL */
2798 if (force_tag_match)
2801 return (RCS_head (rcs));
2804 /* now walk the next pointers of the branch */
2808 p = findnode (rcs->versions, nextvers);
2811 /* a link in the chain is missing - return head or NULL */
2812 if (force_tag_match)
2815 return (RCS_head (rcs));
2818 nextvers = vn->next;
2819 } while (nextvers != NULL);
2821 /* we have the version in our hand, so go for it */
2822 return (xstrdup (vn->version));
2825 /* Returns the head of the branch which REV is on. REV can be a
2826 branch tag or non-branch tag; symbolic or numeric.
2828 Returns a newly malloc'd string. Returns NULL if a symbolic name
2832 RCS_branch_head (rcs, rev)
2840 assert (rcs != NULL);
2842 if (RCS_nodeisbranch (rcs, rev))
2843 return RCS_getbranch (rcs, rev, 1);
2845 if (isdigit ((unsigned char) *rev))
2846 num = xstrdup (rev);
2849 num = translate_symtag (rcs, rev);
2853 br = truncate_revnum (num);
2854 retval = RCS_getbranch (rcs, br, 1);
2860 /* Get the branch point for a particular branch, that is the first
2861 revision on that branch. For example, RCS_getbranchpoint (rcs,
2862 "1.3.2") will normally return "1.3.2.1". TARGET may be either a
2863 branch number or a revision number; if a revnum, find the
2864 branchpoint of the branch to which TARGET belongs.
2866 Return RCS_head if TARGET is on the trunk or if the root node could
2867 not be found (this is sort of backwards from our behavior on a branch;
2868 the rationale is that the return value is a revision from which you
2869 can start walking the next fields and end up at TARGET).
2870 Return NULL on error. */
2873 RCS_getbranchpoint (rcs, target)
2880 int dots, isrevnum, brlen;
2882 dots = numdots (target);
2883 isrevnum = dots & 1;
2886 /* TARGET is a trunk revision; return rcs->head. */
2887 return (RCS_head (rcs));
2889 /* Get the revision number of the node at which TARGET's branch is
2890 rooted. If TARGET is a branch number, lop off the last field;
2891 if it's a revision number, lop off the last *two* fields. */
2892 branch = xstrdup (target);
2893 bp = strrchr (branch, '.');
2895 error (1, 0, "%s: confused revision number %s",
2898 while (*--bp != '.')
2902 vp = findnode (rcs->versions, branch);
2905 error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2912 while (*bp && *bp != '.')
2914 brlen = bp - branch;
2916 vp = rev->branches->list->next;
2917 while (vp != rev->branches->list)
2919 /* BRANCH may be a genuine branch number, e.g. `1.1.3', or
2920 maybe a full revision number, e.g. `1.1.3.6'. We have
2921 found our branch point if the first BRANCHLEN characters
2922 of the revision number match, *and* if the following
2923 character is a dot. */
2924 if (strncmp (vp->key, branch, brlen) == 0 && vp->key[brlen] == '.')
2930 if (vp == rev->branches->list)
2932 error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2936 return (xstrdup (vp->key));
2940 * Get the head of the RCS file. If branch is set, this is the head of the
2941 * branch, otherwise the real head.
2942 * Returns NULL or a newly malloc'd string.
2948 /* make sure we have something to look at... */
2949 assert (rcs != NULL);
2952 * NOTE: we call getbranch with force_tag_match set to avoid any
2953 * possibility of recursion
2956 return (RCS_getbranch (rcs, rcs->branch, 1));
2958 return (xstrdup (rcs->head));
2962 * Get the most recent revision, based on the supplied date, but use some
2963 * funky stuff and follow the vendor branch maybe
2966 RCS_getdate (rcs, date, force_tag_match)
2969 int force_tag_match;
2971 char *cur_rev = NULL;
2972 char *retval = NULL;
2974 RCSVers *vers = NULL;
2976 /* make sure we have something to look at... */
2977 assert (rcs != NULL);
2979 if (rcs->flags & PARTIAL)
2980 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2982 /* if the head is on a branch, try the branch first */
2983 if (rcs->branch != NULL)
2985 retval = RCS_getdatebranch (rcs, date, rcs->branch);
2990 /* otherwise if we have a trunk, try it */
2993 p = findnode (rcs->versions, rcs->head);
2996 error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
3001 /* if the date of this one is before date, take it */
3003 if (RCS_datecmp (vers->date, date) <= 0)
3005 cur_rev = vers->version;
3009 /* if there is a next version, find the node */
3010 if (vers->next != NULL)
3011 p = findnode (rcs->versions, vers->next);
3017 error (0, 0, "%s: no head revision", rcs->path);
3020 * at this point, either we have the revision we want, or we have the
3021 * first revision on the trunk (1.1?) in our hands, or we've come up
3025 /* if we found what we're looking for, and it's not 1.1 return it */
3026 if (cur_rev != NULL)
3028 if (! STREQ (cur_rev, "1.1"))
3029 return (xstrdup (cur_rev));
3031 /* This is 1.1; if the date of 1.1 is not the same as that for the
3032 1.1.1.1 version, then return 1.1. This happens when the first
3033 version of a file is created by a regular cvs add and commit,
3034 and there is a subsequent cvs import of the same file. */
3035 p = findnode (rcs->versions, "1.1.1.1");
3038 char *date_1_1 = vers->date;
3040 assert (p->data != NULL);
3043 if (RCS_datecmp (vers->date, date_1_1) != 0)
3044 return xstrdup ("1.1");
3048 /* look on the vendor branch */
3049 retval = RCS_getdatebranch (rcs, date, CVSBRANCH);
3052 * if we found a match, return it; otherwise, we return the first
3053 * revision on the trunk or NULL depending on force_tag_match and the
3054 * date of the first rev
3059 if (vers && (!force_tag_match || RCS_datecmp (vers->date, date) <= 0))
3060 return xstrdup (vers->version);
3068 * Look up the last element on a branch that was put in before the specified
3069 * date (return the rev or NULL)
3072 RCS_getdatebranch (rcs, date, branch)
3077 char *cur_rev = NULL;
3079 char *xbranch, *xrev;
3083 /* look up the first revision on the branch */
3084 xrev = xstrdup (branch);
3085 cp = strrchr (xrev, '.');
3091 *cp = '\0'; /* turn it into a revision */
3093 assert (rcs != NULL);
3095 if (rcs->flags & PARTIAL)
3096 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3098 p = findnode (rcs->versions, xrev);
3104 /* Tentatively use this revision, if it is early enough. */
3105 if (RCS_datecmp (vers->date, date) <= 0)
3106 cur_rev = vers->version;
3108 /* If no branches list, return now. This is what happens if the branch
3109 is a (magic) branch with no revisions yet. */
3110 if (vers->branches == NULL)
3111 return xstrdup (cur_rev);
3113 /* walk the branches list looking for the branch number */
3114 xbranch = xmalloc (strlen (branch) + 1 + 1); /* +1 for the extra dot */
3115 (void) strcpy (xbranch, branch);
3116 (void) strcat (xbranch, ".");
3117 for (p = vers->branches->list->next; p != vers->branches->list; p = p->next)
3118 if (strncmp (p->key, xbranch, strlen (xbranch)) == 0)
3121 if (p == vers->branches->list)
3123 /* This is what happens if the branch is a (magic) branch with
3124 no revisions yet. Similar to the case where vers->branches ==
3125 NULL, except here there was a another branch off the same
3127 return xstrdup (cur_rev);
3130 p = findnode (rcs->versions, p->key);
3132 /* walk the next pointers until you find the end, or the date is too late */
3136 if (RCS_datecmp (vers->date, date) <= 0)
3137 cur_rev = vers->version;
3141 /* if there is a next version, find the node */
3142 if (vers->next != NULL)
3143 p = findnode (rcs->versions, vers->next);
3148 /* Return whatever we found, which may be NULL. */
3149 return xstrdup (cur_rev);
3155 * Compare two dates in RCS format. Beware the change in format on January 1,
3156 * 2000, when years go from 2-digit to full format.
3159 RCS_datecmp (date1, date2)
3160 const char *date1, *date2;
3162 int length_diff = strlen (date1) - strlen (date2);
3164 return length_diff ? length_diff : strcmp (date1, date2);
3169 /* Look up revision REV in RCS and return the date specified for the
3170 revision minus FUDGE seconds (FUDGE will generally be one, so that the
3171 logically previous revision will be found later, or zero, if we want
3174 The return value is the date being returned as a time_t, or (time_t)-1
3175 on error (previously was documented as zero on error; I haven't checked
3176 the callers to make sure that they really check for (time_t)-1, but
3177 the latter is what this function really returns). If DATE is non-NULL,
3178 then it must point to MAXDATELEN characters, and we store the same
3179 return value there in DATEFORM format. */
3181 RCS_getrevtime (rcs, rev, date, fudge)
3187 char tdate[MAXDATELEN];
3188 struct tm xtm, *ftm;
3193 /* make sure we have something to look at... */
3194 assert (rcs != NULL);
3196 if (rcs->flags & PARTIAL)
3197 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3199 /* look up the revision */
3200 p = findnode (rcs->versions, rev);
3205 /* split up the date */
3206 if (sscanf (vers->date, SDATEFORM, &xtm.tm_year, &xtm.tm_mon,
3207 &xtm.tm_mday, &xtm.tm_hour, &xtm.tm_min, &xtm.tm_sec) != 6)
3208 error (1, 0, "%s: invalid date for revision %s (%s)", rcs->path,
3211 /* If the year is from 1900 to 1999, RCS files contain only two
3212 digits, and sscanf gives us a year from 0-99. If the year is
3213 2000+, RCS files contain all four digits and we subtract 1900,
3214 because the tm_year field should contain years since 1900. */
3216 if (xtm.tm_year >= 100 && xtm.tm_year < 2000)
3217 error (0, 0, "%s: non-standard date format for revision %s (%s)",
3218 rcs->path, rev, vers->date);
3219 if (xtm.tm_year >= 1900)
3220 xtm.tm_year -= 1900;
3222 /* put the date in a form getdate can grok */
3223 (void) sprintf (tdate, "%d/%d/%d GMT %d:%d:%d", xtm.tm_mon,
3224 xtm.tm_mday, xtm.tm_year + 1900, xtm.tm_hour,
3225 xtm.tm_min, xtm.tm_sec);
3227 /* turn it into seconds since the epoch */
3228 revdate = get_date (tdate, (struct timeb *) NULL);
3229 if (revdate != (time_t) -1)
3231 revdate -= fudge; /* remove "fudge" seconds */
3234 /* put an appropriate string into ``date'' if we were given one */
3235 ftm = gmtime (&revdate);
3236 (void) sprintf (date, DATEFORM,
3237 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
3238 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
3239 ftm->tm_min, ftm->tm_sec);
3249 assert(rcs != NULL);
3251 if (rcs->flags & PARTIAL)
3252 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3254 if (rcs->locks_data) {
3255 rcs->locks = getlist ();
3256 do_locks (rcs->locks, rcs->locks_data);
3257 free(rcs->locks_data);
3258 rcs->locks_data = NULL;
3268 assert(rcs != NULL);
3270 if (rcs->flags & PARTIAL)
3271 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3273 if (rcs->symbols_data) {
3274 rcs->symbols = getlist ();
3275 do_symbols (rcs->symbols, rcs->symbols_data);
3276 free(rcs->symbols_data);
3277 rcs->symbols_data = NULL;
3280 return rcs->symbols;
3284 * Return the version associated with a particular symbolic tag.
3285 * Returns NULL or a newly malloc'd string.
3288 translate_symtag (rcs, tag)
3292 if (rcs->flags & PARTIAL)
3293 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3295 if (rcs->symbols != NULL)
3299 /* The symbols have already been converted into a list. */
3300 p = findnode (rcs->symbols, tag);
3304 return xstrdup (p->data);
3307 if (rcs->symbols_data != NULL)
3312 /* Look through the RCS symbols information. This is like
3313 do_symbols, but we don't add the information to a list. In
3314 most cases, we will only be called once for this file, so
3315 generating the list is unnecessary overhead. */
3318 cp = rcs->symbols_data;
3319 /* Keeping track of LAST below isn't strictly necessary, now that tags
3320 * should be parsed for validity before they are accepted, but tags
3321 * with spaces used to cause the code below to loop indefintely, so
3322 * I have corrected for that. Now, in the event that I missed
3323 * something, the server cannot be hung. -DRP
3326 while ((cp = strchr (cp, tag[0])) != NULL)
3328 if (cp == last) break;
3329 if ((cp == rcs->symbols_data || whitespace (cp[-1]))
3330 && strncmp (cp, tag, len) == 0
3335 /* We found the tag. Return the version number. */
3339 while (! whitespace (*cp) && *cp != '\0')
3341 r = xmalloc (cp - v + 1);
3342 strncpy (r, v, cp - v);
3347 while (! whitespace (*cp) && *cp != '\0')
3359 * The argument ARG is the getopt remainder of the -k option specified on the
3360 * command line. This function returns malloc'ed space that can be used
3361 * directly in calls to RCS V5, with the -k flag munged correctly.
3364 RCS_check_kflag (arg)
3367 static const char *const keyword_usage[] =
3369 "%s %s: invalid RCS keyword expansion mode\n",
3370 "Valid expansion modes include:\n",
3371 " -kkv\tGenerate keywords using the default form.\n",
3372 " -kkvl\tLike -kkv, except locker's name inserted.\n",
3373 " -kk\tGenerate only keyword names in keyword strings.\n",
3374 " -kv\tGenerate only keyword values in keyword strings.\n",
3375 " -ko\tGenerate the old keyword string (no changes from checked in file).\n",
3376 " -kb\tGenerate binary file unmodified (merges not allowed) (RCS 5.7).\n",
3377 "(Specify the --help global option for a list of other help options)\n",
3380 /* Big enough to hold any of the strings from kflags. */
3382 char const *const *cpp = NULL;
3386 for (cpp = kflags; *cpp != NULL; cpp++)
3388 if (STREQ (arg, *cpp))
3393 if (arg == NULL || *cpp == NULL)
3395 usage (keyword_usage);
3398 (void) sprintf (karg, "-k%s", *cpp);
3399 return (xstrdup (karg));
3403 * Do some consistency checks on the symbolic tag... These should equate
3404 * pretty close to what RCS checks, though I don't know for certain.
3410 char *invalid = "$,.:;@"; /* invalid RCS tag characters */
3414 * The first character must be an alphabetic letter. The remaining
3415 * characters cannot be non-visible graphic characters, and must not be
3416 * in the set of "invalid" RCS identifier characters.
3418 if (isalpha ((unsigned char) *tag))
3420 for (cp = tag; *cp; cp++)
3422 if (!isgraph ((unsigned char) *cp))
3423 error (1, 0, "tag `%s' has non-visible graphic characters",
3425 if (strchr (invalid, *cp))
3426 error (1, 0, "tag `%s' must not contain the characters `%s'",
3431 error (1, 0, "tag `%s' must start with a letter", tag);
3435 * TRUE if argument has valid syntax for an RCS revision or
3436 * branch number. All characters must be digits or dots, first
3437 * and last characters must be digits, and no two consecutive
3438 * characters may be dots.
3440 * Intended for classifying things, so this function doesn't
3449 if (!isdigit ((unsigned char) last))
3451 while ((c = *rev++)) /* Extra parens placate -Wall gcc option */
3460 if (!isdigit ((unsigned char) c))
3463 if (!isdigit ((unsigned char) last))
3469 * Return true if RCS revision with TAG is a dead revision.
3472 RCS_isdead (rcs, tag)
3479 assert (rcs != NULL);
3481 if (rcs->flags & PARTIAL)
3482 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3484 p = findnode (rcs->versions, tag);
3489 return (version->dead);
3492 /* Return the RCS keyword expansion mode. For example "b" for binary.
3493 Returns a pointer into storage which is allocated and freed along with
3494 the rest of the RCS information; the caller should not modify this
3495 storage. Returns NULL if the RCS file does not specify a keyword
3496 expansion mode; for all other errors, die with a fatal error. */
3501 /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3502 about RCS_reparsercsfile. */
3503 assert (rcs != NULL);
3507 /* Set keyword expansion mode to EXPAND. For example "b" for binary. */
3509 RCS_setexpand (rcs, expand)
3513 /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3514 about RCS_reparsercsfile. */
3515 assert (rcs != NULL);
3516 if (rcs->expand != NULL)
3518 rcs->expand = xstrdup (expand);
3521 /* RCS keywords, and a matching enum. */
3528 #define KEYWORD_INIT(s) (s), sizeof (s) - 1
3529 static struct rcs_keyword keywords[] =
3531 { KEYWORD_INIT ("Author"), 1 },
3532 { KEYWORD_INIT ("Date"), 1 },
3533 { KEYWORD_INIT ("CVSHeader"), 1 },
3534 { KEYWORD_INIT ("Header"), 1 },
3535 { KEYWORD_INIT ("Id"), 1 },
3536 { KEYWORD_INIT ("Locker"), 1 },
3537 { KEYWORD_INIT ("Log"), 1 },
3538 { KEYWORD_INIT ("Name"), 1 },
3539 { KEYWORD_INIT ("RCSfile"), 1 },
3540 { KEYWORD_INIT ("Revision"), 1 },
3541 { KEYWORD_INIT ("Source"), 1 },
3542 { KEYWORD_INIT ("State"), 1 },
3562 enum keyword keyword_local = KEYWORD_ID;
3564 /* Convert an RCS date string into a readable string. This is like
3565 the RCS date2str function. */
3568 printable_date (rcs_date)
3569 const char *rcs_date;
3571 int year, mon, mday, hour, min, sec;
3574 (void) sscanf (rcs_date, SDATEFORM, &year, &mon, &mday, &hour, &min,
3578 sprintf (buf, "%04d%c%02d%c%02d %02d:%02d:%02d",
3579 year, datesep, mon, datesep, mday, hour, min, sec);
3580 return xstrdup (buf);
3583 /* Escape the characters in a string so that it can be included in an
3587 escape_keyword_value (value, free_value)
3594 for (s = value; *s != '\0'; s++)
3612 return (char *) value;
3615 ret = xmalloc (strlen (value) * 4 + 1);
3618 for (s = value, t = ret; *s != '\0'; s++, t++)
3657 /* Expand RCS keywords in the memory buffer BUF of length LEN. This
3658 applies to file RCS and version VERS. If NAME is not NULL, and is
3659 not a numeric revision, then it is the symbolic tag used for the
3660 checkout. EXPAND indicates how to expand the keywords. This
3661 function sets *RETBUF and *RETLEN to the new buffer and length.
3662 This function may modify the buffer BUF. If BUF != *RETBUF, then
3663 RETBUF is a newly allocated buffer. */
3666 expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
3678 struct expand_buffer
3680 struct expand_buffer *next;
3685 struct expand_buffer *ebuf_last = NULL;
3686 size_t ebuf_len = 0;
3688 char *srch, *srch_next;
3691 if (expand == KFLAG_O || expand == KFLAG_B)
3698 /* If we are using -kkvl, dig out the locker information if any. */
3700 if (expand == KFLAG_KVL)
3703 lock = findnode (RCS_getlocks(rcs), ver->version);
3705 locker = xstrdup (lock->data);
3708 /* RCS keywords look like $STRING$ or $STRING: VALUE$. */
3711 while ((srch_next = memchr (srch, '$', srch_len)) != NULL)
3715 const struct rcs_keyword *keyword;
3722 srch_len -= (srch_next + 1) - srch;
3723 srch = srch_next + 1;
3725 /* Look for the first non alphabetic character after the '$'. */
3726 send = srch + srch_len;
3727 for (s = srch; s < send; s++)
3728 if (! isalpha ((unsigned char) *s))
3731 /* If the first non alphabetic character is not '$' or ':',
3732 then this is not an RCS keyword. */
3733 if (s == send || (*s != '$' && *s != ':'))
3736 /* See if this is one of the keywords. */
3738 for (keyword = keywords; keyword->string != NULL; keyword++)
3740 if (keyword->expandit
3741 && keyword->len == slen
3742 && strncmp (keyword->string, srch, slen) == 0)
3747 if (keyword->string == NULL)
3750 kw = (enum keyword) (keyword - keywords);
3752 /* If the keyword ends with a ':', then the old value consists
3753 of the characters up to the next '$'. If there is no '$'
3754 before the end of the line, though, then this wasn't an RCS
3755 keyword after all. */
3758 for (; s < send; s++)
3759 if (*s == '$' || *s == '\n')
3761 if (s == send || *s != '$')
3765 /* At this point we must replace the string from SRCH to S
3766 with the expansion of the keyword KW. */
3768 /* Get the value to use. */
3770 if (expand == KFLAG_K)
3779 case KEYWORD_AUTHOR:
3780 value = ver->author;
3784 value = printable_date (ver->date);
3788 case KEYWORD_CVSHEADER:
3789 case KEYWORD_HEADER:
3791 case KEYWORD_LOCALID:
3799 if (kw == KEYWORD_HEADER ||
3800 (kw == KEYWORD_LOCALID &&
3801 keyword_local == KEYWORD_HEADER))
3803 else if (kw == KEYWORD_CVSHEADER ||
3804 (kw == KEYWORD_LOCALID &&
3805 keyword_local == KEYWORD_CVSHEADER))
3806 path = getfullCVSname(rcs->path, &old_path);
3808 path = last_component (rcs->path);
3809 path = escape_keyword_value (path, &free_path);
3810 date = printable_date (ver->date);
3811 value = xmalloc (strlen (path)
3812 + strlen (ver->version)
3814 + strlen (ver->author)
3815 + strlen (ver->state)
3816 + (locker == NULL ? 0 : strlen (locker))
3819 sprintf (value, "%s %s %s %s %s%s%s",
3820 path, ver->version, date, ver->author,
3822 locker != NULL ? " " : "",
3823 locker != NULL ? locker : "");
3825 /* If free_path is set then we know we allocated path
3826 * and we can discard the const.
3828 free ((char *)path);
3836 case KEYWORD_LOCKER:
3841 case KEYWORD_RCSFILE:
3842 value = escape_keyword_value (last_component (rcs->path),
3847 if (name != NULL && ! isdigit ((unsigned char) *name))
3848 value = (char *) name;
3853 case KEYWORD_REVISION:
3854 value = ver->version;
3857 case KEYWORD_SOURCE:
3858 value = escape_keyword_value (rcs->path, &free_value);
3867 sub = xmalloc (keyword->len
3868 + (value == NULL ? 0 : strlen (value))
3870 if (expand == KFLAG_V)
3872 /* Decrement SRCH and increment S to remove the $
3881 strcpy (sub, keyword->string);
3882 sublen = strlen (keyword->string);
3883 if (expand != KFLAG_K)
3886 sub[sublen + 1] = ' ';
3892 strcpy (sub + sublen, value);
3893 sublen += strlen (value);
3895 if (expand != KFLAG_V && expand != KFLAG_K)
3905 /* The Log keyword requires special handling. This behaviour
3906 is taken from RCS 5.7. The special log message is what RCS
3908 if (kw == KEYWORD_LOG
3909 && (sizeof "checked in with -k by " <= loglen
3911 || strncmp (log, "checked in with -k by ",
3912 sizeof "checked in with -k by " - 1) != 0))
3916 size_t leader_len, leader_sp_len;
3923 /* We are going to insert the trailing $ ourselves, before
3924 the log message, so we must remove it from S, if we
3925 haven't done so already. */
3926 if (expand != KFLAG_V)
3929 /* CVS never has empty log messages, but old RCS files might. */
3933 /* Find the start of the line. */
3935 while (start > buf && start[-1] != '\n')
3938 /* Copy the start of the line to use as a comment leader. */
3939 leader_len = srch - start;
3940 if (expand != KFLAG_V)
3942 leader = xmalloc (leader_len);
3943 memcpy (leader, start, leader_len);
3944 leader_sp_len = leader_len;
3945 while (leader_sp_len > 0 && leader[leader_sp_len - 1] == ' ')
3948 /* RCS does some checking for an old style of Log here,
3949 but we don't bother. RCS issues a warning if it
3950 changes anything. */
3952 /* Count the number of newlines in the log message so that
3953 we know how many copies of the leader we will need. */
3955 logend = log + loglen;
3956 for (snl = log; snl < logend; snl++)
3960 /* If the log message did not end in a newline, increment
3961 * the newline count so we have space for the extra leader.
3962 * Failure to do so results in a buffer overrun.
3964 if (loglen && snl[-1] != '\n')
3967 date = printable_date (ver->date);
3968 sub = xrealloc (sub,
3971 + strlen (ver->version)
3973 + strlen (ver->author)
3975 /* Use CNL + 2 below: One leader for each log
3976 * line, plus the Revision/Author/Date line,
3977 * plus a trailing blank line.
3979 + (cnl + 2) * leader_len
3981 if (expand != KFLAG_V)
3988 memcpy (sub + sublen, leader, leader_len);
3989 sublen += leader_len;
3990 sprintf (sub + sublen, "Revision %s %s %s\n",
3991 ver->version, date, ver->author);
3992 sublen += strlen (sub + sublen);
4000 memcpy (sub + sublen, leader, leader_sp_len);
4001 sublen += leader_sp_len;
4010 memcpy (sub + sublen, leader, leader_len);
4011 sublen += leader_len;
4012 for (slnl = sl; slnl < logend && *slnl != '\n'; ++slnl)
4016 memcpy (sub + sublen, sl, slnl - sl);
4017 sublen += slnl - sl;
4018 if (slnl == logend && slnl[-1] != '\n')
4020 /* There was no EOL at the end of the log message. Add
4030 memcpy (sub + sublen, leader, leader_sp_len);
4031 sublen += leader_sp_len;
4036 /* Now SUB contains a string which is to replace the string
4037 from SRCH to S. SUBLEN is the length of SUB. */
4039 if (srch + sublen == s)
4041 memcpy (srch, sub, sublen);
4046 struct expand_buffer *ebuf;
4048 /* We need to change the size of the buffer. We build a
4049 list of expand_buffer structures. Each expand_buffer
4050 structure represents a portion of the final output. We
4051 concatenate them back into a single buffer when we are
4052 done. This minimizes the number of potentially large
4053 buffer copies we must do. */
4057 ebufs = (struct expand_buffer *) xmalloc (sizeof *ebuf);
4060 ebufs->free_data = 0;
4061 ebuf_len = srch - buf;
4062 ebufs->len = ebuf_len;
4067 assert (srch >= ebuf_last->data);
4068 assert (srch <= ebuf_last->data + ebuf_last->len);
4069 ebuf_len -= ebuf_last->len - (srch - ebuf_last->data);
4070 ebuf_last->len = srch - ebuf_last->data;
4073 ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
4076 ebuf->free_data = 1;
4078 ebuf_last->next = ebuf;
4082 ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
4084 ebuf->len = srch_len - (s - srch);
4085 ebuf->free_data = 0;
4087 ebuf_last->next = ebuf;
4089 ebuf_len += srch_len - (s - srch);
4092 srch_len -= (s - srch);
4108 ret = xmalloc (ebuf_len);
4111 while (ebufs != NULL)
4113 struct expand_buffer *next;
4115 memcpy (ret, ebufs->data, ebufs->len);
4117 if (ebufs->free_data)
4128 /* Check out a revision from an RCS file.
4130 If PFN is not NULL, then ignore WORKFILE and SOUT. Call PFN zero
4131 or more times with the contents of the file. CALLERDAT is passed,
4132 uninterpreted, to PFN. (The current code will always call PFN
4133 exactly once for a non empty file; however, the current code
4134 assumes that it can hold the entire file contents in memory, which
4135 is not a good assumption, and might change in the future).
4137 Otherwise, if WORKFILE is not NULL, check out the revision to
4138 WORKFILE. However, if WORKFILE is not NULL, and noexec is set,
4139 then don't do anything.
4141 Otherwise, if WORKFILE is NULL, check out the revision to SOUT. If
4142 SOUT is RUN_TTY, then write the contents of the revision to
4143 standard output. When using SOUT, the output is generally a
4144 temporary file; don't bother to get the file modes correct. When
4145 NOEXEC is set, WORKFILEs are not written but SOUTs are.
4147 REV is the numeric revision to check out. It may be NULL, which
4148 means to check out the head of the default branch.
4150 If NAMETAG is not NULL, and is not a numeric revision, then it is
4151 the tag that should be used when expanding the RCS Name keyword.
4153 OPTIONS is a string such as "-kb" or "-kv" for keyword expansion
4154 options. It may be NULL to use the default expansion mode of the
4155 file, typically "-kkv".
4157 On an error which prevented checking out the file, either print a
4158 nonfatal error and return 1, or give a fatal error. On success,
4161 /* This function mimics the behavior of `rcs co' almost exactly. The
4162 chief difference is in its support for preserving file ownership,
4163 permissions, and special files across checkin and checkout -- see
4164 comments in RCS_checkin for some issues about this. -twp */
4167 RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
4169 const char *workfile;
4171 const char *nametag;
4172 const char *options;
4174 RCSCHECKOUTPROC pfn;
4182 struct rcsbuffer rcsbuf;
4190 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4191 uid_t rcs_owner = (uid_t) -1;
4192 gid_t rcs_group = (gid_t) -1;
4194 int change_rcs_owner_or_group = 0;
4195 int change_rcs_mode = 0;
4196 int special_file = 0;
4197 unsigned long devnum_long;
4203 (void) fprintf (stderr, "%s-> RCS_checkout (%s, %s, %s, %s, %s)\n",
4204 #ifdef SERVER_SUPPORT
4205 server_active ? "S" : " ",
4210 rev != NULL ? rev : "",
4211 nametag != NULL ? nametag : "",
4212 options != NULL ? options : "",
4213 (pfn != NULL ? "(function)"
4216 : (sout != RUN_TTY ? sout : "(stdout)"))));
4219 assert (rev == NULL || isdigit ((unsigned char) *rev));
4221 if (noexec && !server_active && workfile != NULL)
4224 assert (sout == RUN_TTY || workfile == NULL);
4225 assert (pfn == NULL || (sout == RUN_TTY && workfile == NULL));
4227 /* Some callers, such as Checkin or remove_file, will pass us a
4229 if (rev != NULL && (numdots (rev) & 1) == 0)
4231 rev = RCS_getbranch (rcs, rev, 1);
4233 error (1, 0, "internal error: bad branch tag in checkout");
4237 if (rev == NULL || STREQ (rev, rcs->head))
4241 /* We want the head revision. Try to read it directly. */
4243 if (rcs->flags & PARTIAL)
4244 RCS_reparsercsfile (rcs, &fp, &rcsbuf);
4246 rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf);
4249 if (! rcsbuf_getrevnum (&rcsbuf, &key))
4250 error (1, 0, "unexpected EOF reading %s", rcs->path);
4252 if (!STREQ (rcs->head, key))
4253 error (1, 0, "Expected head revision %s, found %s.",
4256 while (rcsbuf_getkey (&rcsbuf, &key, &value))
4258 if (STREQ (key, "log"))
4263 "Duplicate log keyword found for head revision in RCS file.");
4266 log = rcsbuf_valcopy (&rcsbuf, value, 0, &loglen);
4268 else if (STREQ (key, "text"))
4277 error (0, 0, "internal error: cannot find head text");
4279 /* It's okay to discard the const when free_rev is set, because
4280 * we know we allocated it in this function.
4286 rcsbuf_valpolish (&rcsbuf, value, 0, &len);
4288 if (fstat (fileno (fp), &sb) < 0)
4289 error (1, errno, "cannot fstat %s", rcs->path);
4291 rcsbuf_cache (rcs, &rcsbuf);
4295 struct rcsbuffer *rcsbufp;
4297 /* It isn't the head revision of the trunk. We'll need to
4298 walk through the deltas. */
4301 if (rcs->flags & PARTIAL)
4302 RCS_reparsercsfile (rcs, &fp, &rcsbuf);
4306 /* If RCS_deltas didn't close the file, we could use fstat
4307 here too. Probably should change it thusly.... */
4308 if (stat (rcs->path, &sb) < 0)
4309 error (1, errno, "cannot stat %s", rcs->path);
4314 if (fstat (fileno (fp), &sb) < 0)
4315 error (1, errno, "cannot fstat %s", rcs->path);
4319 RCS_deltas (rcs, fp, rcsbufp, rev, RCS_FETCH, &value, &len,
4324 /* If OPTIONS is NULL or the empty string, then the old code would
4325 invoke the RCS co program with no -k option, which means that
4326 co would use the string we have stored in rcs->expand. */
4327 if ((options == NULL || options[0] == '\0') && rcs->expand == NULL)
4331 const char *ouroptions;
4332 const char * const *cpp;
4334 if (options != NULL && options[0] != '\0')
4336 assert (options[0] == '-' && options[1] == 'k');
4337 ouroptions = options + 2;
4340 ouroptions = rcs->expand;
4342 for (cpp = kflags; *cpp != NULL; cpp++)
4343 if (STREQ (*cpp, ouroptions))
4347 expand = (enum kflag) (cpp - kflags);
4351 "internal error: unsupported substitution string -k%s",
4357 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4358 /* Handle special files and permissions, if that is desired. */
4364 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4366 error (1, 0, "internal error: no revision information for %s",
4367 rev == NULL ? rcs->head : rev);
4370 /* First we look for symlinks, which are simplest to handle. */
4371 info = findnode (vers->other_delta, "symlink");
4376 if (pfn != NULL || (workfile == NULL && sout == RUN_TTY))
4377 error (1, 0, "symbolic link %s:%s cannot be piped",
4378 rcs->path, vers->version);
4379 if (workfile == NULL)
4384 /* Remove `dest', just in case. It's okay to get ENOENT here,
4385 since we just want the file not to be there. (TODO: decide
4386 whether it should be considered an error for `dest' to exist
4387 at this point. If so, the unlink call should be removed and
4388 `symlink' should signal the error. -twp) */
4389 if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
4390 error (1, errno, "cannot remove %s", dest);
4391 if (symlink (info->data, dest) < 0)
4392 error (1, errno, "cannot create symbolic link from %s to %s",
4393 dest, (char *)info->data);
4397 /* It's okay to discard the const when free_rev is set, because
4398 * we know we allocated it in this function.
4404 /* Next, we look at this file's hardlinks field, and see whether
4405 it is linked to any other file that has been checked out.
4406 If so, we don't do anything else -- just link it to that file.
4408 If we are checking out a file to a pipe or temporary storage,
4409 none of this should matter. Hence the `workfile != NULL'
4410 wrapper around the whole thing. -twp */
4412 if (workfile != NULL)
4414 List *links = vers->hardlinks;
4417 Node *uptodate_link;
4419 /* For each file in the hardlinks field, check to see
4420 if it exists, and if so, if it has been checked out
4421 this iteration. When walklist returns, uptodate_link
4422 should point to a hardlist node representing a file
4423 in `links' which has recently been checked out, or
4424 NULL if no file in `links' has yet been checked out. */
4426 uptodate_link = NULL;
4427 (void) walklist (links, find_checkedout_proc, &uptodate_link);
4430 /* If we've found a file that `workfile' is supposed to be
4431 linked to, and it has been checked out since CVS was
4432 invoked, then simply link workfile to that file and return.
4434 If one of these conditions is not met, then
4435 workfile is the first one in its hardlink group to
4436 be checked out, and we must continue with a full
4439 if (uptodate_link != NULL)
4441 struct hardlink_info *hlinfo = uptodate_link->data;
4443 if (link (uptodate_link->key, workfile) < 0)
4444 error (1, errno, "cannot link %s to %s",
4445 workfile, uptodate_link->key);
4446 hlinfo->checked_out = 1; /* probably unnecessary */
4450 /* It's okay to discard the const when free_rev is set,
4451 * because we know we allocated it in this function.
4459 info = findnode (vers->other_delta, "owner");
4462 change_rcs_owner_or_group = 1;
4463 rcs_owner = (uid_t) strtoul (info->data, NULL, 10);
4465 info = findnode (vers->other_delta, "group");
4468 change_rcs_owner_or_group = 1;
4469 rcs_group = (gid_t) strtoul (info->data, NULL, 10);
4471 info = findnode (vers->other_delta, "permissions");
4474 change_rcs_mode = 1;
4475 rcs_mode = (mode_t) strtoul (info->data, NULL, 8);
4477 info = findnode (vers->other_delta, "special");
4480 /* If the size of `devtype' changes, fix the sscanf call also */
4483 if (sscanf (info->data, "%15s %lu",
4484 devtype, &devnum_long) < 2)
4485 error (1, 0, "%s:%s has bad `special' newphrase %s",
4486 workfile, vers->version, (char *)info->data);
4487 devnum = devnum_long;
4488 if (STREQ (devtype, "character"))
4489 special_file = S_IFCHR;
4490 else if (STREQ (devtype, "block"))
4491 special_file = S_IFBLK;
4493 error (0, 0, "%s is a special file of unsupported type `%s'",
4494 workfile, (char *)info->data);
4497 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
4499 if (expand != KFLAG_O && expand != KFLAG_B)
4503 /* Don't fetch the delta node again if we already have it. */
4506 vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4508 error (1, 0, "internal error: no revision information for %s",
4509 rev == NULL ? rcs->head : rev);
4512 expand_keywords (rcs, vp->data, nametag, log, loglen,
4513 expand, value, len, &newvalue, &len);
4515 if (newvalue != value)
4525 /* It's okay to discard the const when free_rev is set, because
4526 * we know we allocated it in this function.
4538 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4540 error (1, 0, "special file %s cannot be piped to anything",
4543 /* The PFN interface is very simple to implement right now, as
4544 we always have the entire file in memory. */
4546 pfn (callerdat, value, len);
4548 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4549 else if (special_file)
4554 /* Can send either to WORKFILE or to SOUT, as long as SOUT is
4559 if (sout == RUN_TTY)
4560 error (1, 0, "special file %s cannot be written to stdout",
4565 /* Unlink `dest', just in case. It's okay if this provokes a
4567 if (CVS_UNLINK (dest) < 0 && existence_error (errno))
4568 error (1, errno, "cannot remove %s", dest);
4569 if (mknod (dest, special_file, devnum) < 0)
4570 error (1, errno, "could not create special file %s",
4574 "cannot create %s: unable to create special files on this system",
4581 /* Not a special file: write to WORKFILE or SOUT. */
4582 if (workfile == NULL)
4584 if (sout == RUN_TTY)
4588 /* Symbolic links should be removed before replacement, so that
4589 `fopen' doesn't follow the link and open the wrong file. */
4591 if (unlink_file (sout) < 0)
4592 error (1, errno, "cannot remove %s", sout);
4593 ofp = CVS_FOPEN (sout, expand == KFLAG_B ? "wb" : "w");
4595 error (1, errno, "cannot open %s", sout);
4600 /* Output is supposed to go to WORKFILE, so we should open that
4601 file. Symbolic links should be removed first (see above). */
4602 if (islink (workfile))
4603 if (unlink_file (workfile) < 0)
4604 error (1, errno, "cannot remove %s", workfile);
4606 ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
4608 /* If the open failed because the existing workfile was not
4609 writable, try to chmod the file and retry the open. */
4610 if (ofp == NULL && errno == EACCES
4611 && isfile (workfile) && !iswritable (workfile))
4613 xchmod (workfile, 1);
4614 ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
4619 error (0, errno, "cannot open %s", workfile);
4626 if (workfile == NULL && sout == RUN_TTY)
4628 if (expand == KFLAG_B)
4629 cvs_output_binary (value, len);
4632 /* cvs_output requires the caller to check for zero
4635 cvs_output (value, len);
4640 /* NT 4.0 is said to have trouble writing 2099999 bytes
4641 (for example) in a single fwrite. So break it down
4642 (there is no need to be writing that much at once
4643 anyway; it is possible that LARGEST_FWRITE should be
4644 somewhat larger for good performance, but for testing I
4645 want to start with a small value until/unless a bigger
4646 one proves useful). */
4647 #define LARGEST_FWRITE 8192
4649 size_t nstep = (len < LARGEST_FWRITE ? len : LARGEST_FWRITE);
4654 if (fwrite (p, 1, nstep, ofp) != nstep)
4656 error (0, errno, "cannot write %s",
4659 : (sout != RUN_TTY ? sout : "stdout")));
4675 if (workfile != NULL)
4679 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4680 if (!special_file && fclose (ofp) < 0)
4682 error (0, errno, "cannot close %s", workfile);
4686 if (change_rcs_owner_or_group)
4688 if (chown (workfile, rcs_owner, rcs_group) < 0)
4689 error (0, errno, "could not change owner or group of %s",
4693 ret = chmod (workfile,
4696 : sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
4698 if (fclose (ofp) < 0)
4700 error (0, errno, "cannot close %s", workfile);
4704 ret = chmod (workfile,
4705 sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
4709 error (0, errno, "cannot change mode of file %s",
4713 else if (sout != RUN_TTY)
4716 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4721 error (0, errno, "cannot close %s", sout);
4726 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4727 /* If we are in the business of preserving hardlinks, then
4728 mark this file as having been checked out. */
4729 if (preserve_perms && workfile != NULL)
4730 update_hardlink_info (workfile);
4736 static RCSVers *RCS_findlock_or_tip PROTO ((RCSNode *rcs));
4738 /* Find the delta currently locked by the user. From the `ci' man page:
4740 "If rev is omitted, ci tries to derive the new revision
4741 number from the caller's last lock. If the caller has
4742 locked the tip revision of a branch, the new revision is
4743 appended to that branch. The new revision number is
4744 obtained by incrementing the tip revision number. If the
4745 caller locked a non-tip revision, a new branch is started
4746 at that revision by incrementing the highest branch number
4747 at that revision. The default initial branch and level
4750 If rev is omitted and the caller has no lock, but owns the
4751 file and locking is not set to strict, then the revision
4752 is appended to the default branch (normally the trunk; see
4753 the -b option of rcs(1))."
4755 RCS_findlock_or_tip finds the unique revision locked by the caller
4756 and returns its delta node. If the caller has not locked any
4757 revisions (and is permitted to commit to an unlocked delta, as
4758 described above), return the tip of the default branch. */
4761 RCS_findlock_or_tip (rcs)
4764 char *user = getcaller();
4767 char *defaultrev = NULL;
4769 /* Find unique delta locked by caller. This code is very similar
4770 to the code in RCS_unlock -- perhaps it could be abstracted
4771 into a RCS_findlock function. */
4772 locklist = RCS_getlocks (rcs);
4774 for (p = locklist->list->next; p != locklist->list; p = p->next)
4776 if (STREQ (p->data, user))
4781 %s: multiple revisions locked by %s; please specify one", rcs->path, user);
4790 /* Found an old lock, but check that the revision still exists. */
4791 p = findnode (rcs->versions, lock->key);
4794 error (0, 0, "%s: can't unlock nonexistent revision %s",
4802 /* No existing lock. The RCS rule is that this is an error unless
4803 locking is nonstrict AND the file is owned by the current
4804 user. Trying to determine the latter is a portability nightmare
4805 in the face of NT, VMS, AFS, and other systems with non-unix-like
4806 ideas of users and owners. In the case of CVS, we should never get
4807 here (as long as the traditional behavior of making sure to call
4808 RCS_lock persists). Anyway, we skip the RCS error checks
4809 and just return the default branch or head. The reasoning is that
4810 those error checks are to make users lock before a checkin, and we do
4811 that in other ways if at all anyway (e.g. rcslock.pl). */
4813 defaultrev = RCS_getbranch (rcs, rcs->branch, 0);
4814 p = findnode (rcs->versions, defaultrev);
4815 if (defaultrev != NULL)
4819 error (0, 0, "RCS file `%s' does not contain its default revision.",
4827 /* Revision number string, R, must contain a `.'.
4828 Return a newly-malloc'd copy of the prefix of R up
4829 to but not including the final `.'. */
4837 char *dot = strrchr (r, '.');
4841 new_r = xmalloc (len + 1);
4842 memcpy (new_r, r, len);
4843 *(new_r + len) = '\0';
4847 /* Revision number string, R, must contain a `.'.
4848 R must be writable. Replace the rightmost `.' in R with
4849 the NUL byte and return a pointer to that NUL byte. */
4852 truncate_revnum_in_place (r)
4855 char *dot = strrchr (r, '.');
4861 /* Revision number strings, R and S, must each contain a `.'.
4862 R and S must be writable and must have the same number of dots.
4863 Truncate R and S for the comparison, then restored them to their
4865 Return the result (see compare_revnums) of comparing R and S
4866 ignoring differences in any component after the rightmost `.'. */
4869 compare_truncated_revnums (r, s)
4873 char *r_dot = truncate_revnum_in_place (r);
4874 char *s_dot = truncate_revnum_in_place (s);
4877 assert (numdots (r) == numdots (s));
4879 cmp = compare_revnums (r, s);
4887 /* Return a malloc'd copy of the string representing the highest branch
4888 number on BRANCHNODE. If there are no branches on BRANCHNODE, return NULL.
4889 FIXME: isn't the max rev always the last one?
4890 If so, we don't even need a loop. */
4892 static char *max_rev PROTO ((const RCSVers *));
4895 max_rev (branchnode)
4896 const RCSVers *branchnode;
4902 if (branchnode->branches == NULL)
4908 head = branchnode->branches->list;
4909 for (bp = head->next; bp != head; bp = bp->next)
4911 if (max == NULL || compare_truncated_revnums (max, bp->key) < 0)
4918 return truncate_revnum (max);
4921 /* Create BRANCH in RCS's delta tree. BRANCH may be either a branch
4922 number or a revision number. In the former case, create the branch
4923 with the specified number; in the latter case, create a new branch
4924 rooted at node BRANCH with a higher branch number than any others.
4925 Return the number of the tip node on the new branch. */
4928 RCS_addbranch (rcs, branch)
4932 char *branchpoint, *newrevnum;
4935 RCSVers *branchnode;
4939 /* Append to end by default. */
4942 branchpoint = xstrdup (branch);
4943 if ((numdots (branchpoint) & 1) == 0)
4945 truncate_revnum_in_place (branchpoint);
4948 /* Find the branch rooted at BRANCHPOINT. */
4949 nodep = findnode (rcs->versions, branchpoint);
4952 error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
4957 branchnode = nodep->data;
4959 /* If BRANCH was a full branch number, make sure it is higher than MAX. */
4960 if ((numdots (branch) & 1) == 1)
4962 if (branchnode->branches == NULL)
4964 /* We have to create the first branch on this node, which means
4965 appending ".2" to the revision number. */
4966 newrevnum = (char *) xmalloc (strlen (branch) + 3);
4967 strcpy (newrevnum, branch);
4968 strcat (newrevnum, ".2");
4972 char *max = max_rev (branchnode);
4974 newrevnum = increment_revnum (max);
4980 newrevnum = xstrdup (branch);
4982 if (branchnode->branches != NULL)
4987 /* Find the position of this new branch in the sorted list
4989 head = branchnode->branches->list;
4990 for (bp = head->next; bp != head; bp = bp->next)
4995 /* The existing list must be sorted on increasing revnum. */
4996 assert (bp->next == head
4997 || compare_truncated_revnums (bp->key,
4998 bp->next->key) < 0);
4999 dot = truncate_revnum_in_place (bp->key);
5000 found_pos = (compare_revnums (branch, bp->key) < 0);
5012 newrevnum = (char *) xrealloc (newrevnum, strlen (newrevnum) + 3);
5013 strcat (newrevnum, ".1");
5015 /* Add this new revision number to BRANCHPOINT's branches list. */
5016 if (branchnode->branches == NULL)
5017 branchnode->branches = getlist();
5019 bp->key = xstrdup (newrevnum);
5021 /* Append to the end of the list by default, that is, just before
5022 the header node, `list'. */
5024 marker = branchnode->branches->list;
5028 fail = insert_before (branchnode->branches, marker, bp);
5035 /* Check in to RCSFILE with revision REV (which must be greater than
5036 the largest revision) and message MESSAGE (which is checked for
5037 legality). If FLAGS & RCS_FLAGS_DEAD, check in a dead revision.
5038 If FLAGS & RCS_FLAGS_QUIET, tell ci to be quiet. If FLAGS &
5039 RCS_FLAGS_MODTIME, use the working file's modification time for the
5040 checkin time. WORKFILE is the working file to check in from, or
5041 NULL to use the usual RCS rules for deriving it from the RCSFILE.
5042 If FLAGS & RCS_FLAGS_KEEPFILE, don't unlink the working file;
5043 unlinking the working file is standard RCS behavior, but is rarely
5044 appropriate for CVS.
5046 This function should almost exactly mimic the behavior of `rcs ci'. The
5047 principal point of difference is the support here for preserving file
5048 ownership and permissions in the delta nodes. This is not a clean
5049 solution -- precisely because it diverges from RCS's behavior -- but
5050 it doesn't seem feasible to do this anywhere else in the code. [-twp]
5052 Return value is -1 for error (and errno is set to indicate the
5053 error), positive for error (and an error message has been printed),
5054 or zero for success. */
5057 RCS_checkin (rcs, workfile_in, message, rev, citime, flags)
5059 const char *workfile_in;
5060 const char *message;
5065 RCSVers *delta, *commitpt;
5068 char *tmpfile, *changefile;
5070 size_t darg_allocated = 0;
5071 char **dargv = NULL;
5073 int status, checkin_quiet;
5076 int adding_branch = 0;
5077 char *workfile = xstrdup (workfile_in);
5078 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5084 if (rcs->flags & PARTIAL)
5085 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5087 /* Get basename of working file. Is there a library function to
5088 do this? I couldn't find one. -twp */
5089 if (workfile == NULL)
5092 int extlen = strlen (RCSEXT);
5094 workfile = xstrdup (last_component (rcs->path));
5095 p = workfile + (strlen (workfile) - extlen);
5096 assert (strncmp (p, RCSEXT, extlen) == 0);
5100 /* If the filename is a symbolic link, follow it and replace it
5101 with the destination of the link. We need to do this before
5102 calling rcs_internal_lockfile, or else we won't put the lock in
5104 resolve_symlink (&(rcs->path));
5106 checkin_quiet = flags & RCS_FLAGS_QUIET;
5109 cvs_output (rcs->path, 0);
5110 cvs_output (" <-- ", 7);
5111 cvs_output (workfile, 0);
5112 cvs_output ("\n", 1);
5115 /* Create new delta node. */
5116 delta = (RCSVers *) xmalloc (sizeof (RCSVers));
5117 memset (delta, 0, sizeof (RCSVers));
5118 delta->author = xstrdup (getcaller ());
5119 if (flags & RCS_FLAGS_MODTIME)
5122 if (stat (workfile, &ws) < 0)
5124 error (1, errno, "cannot stat %s", workfile);
5126 modtime = ws.st_mtime;
5128 else if (flags & RCS_FLAGS_USETIME)
5131 (void) time (&modtime);
5132 ftm = gmtime (&modtime);
5133 delta->date = (char *) xmalloc (MAXDATELEN);
5134 (void) sprintf (delta->date, DATEFORM,
5135 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
5136 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
5137 ftm->tm_min, ftm->tm_sec);
5138 if (flags & RCS_FLAGS_DEAD)
5140 delta->state = xstrdup (RCSDEAD);
5144 delta->state = xstrdup ("Exp");
5146 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5147 /* If permissions should be preserved on this project, then
5148 save the permission info. */
5152 char buf[64]; /* static buffer should be safe: see usage. -twp */
5154 delta->other_delta = getlist();
5156 if (CVS_LSTAT (workfile, &sb) < 0)
5157 error (1, errno, "cannot lstat %s", workfile);
5159 if (S_ISLNK (sb.st_mode))
5162 np->type = RCSFIELD;
5163 np->key = xstrdup ("symlink");
5164 np->data = xreadlink (workfile);
5165 addnode (delta->other_delta, np);
5169 (void) sprintf (buf, "%u", sb.st_uid);
5171 np->type = RCSFIELD;
5172 np->key = xstrdup ("owner");
5173 np->data = xstrdup (buf);
5174 addnode (delta->other_delta, np);
5176 (void) sprintf (buf, "%u", sb.st_gid);
5178 np->type = RCSFIELD;
5179 np->key = xstrdup ("group");
5180 np->data = xstrdup (buf);
5181 addnode (delta->other_delta, np);
5183 (void) sprintf (buf, "%o", sb.st_mode & 07777);
5185 np->type = RCSFIELD;
5186 np->key = xstrdup ("permissions");
5187 np->data = xstrdup (buf);
5188 addnode (delta->other_delta, np);
5190 /* Save device number. */
5191 switch (sb.st_mode & S_IFMT)
5193 case S_IFREG: break;
5196 # ifdef HAVE_STRUCT_STAT_ST_RDEV
5198 np->type = RCSFIELD;
5199 np->key = xstrdup ("special");
5200 sprintf (buf, "%s %lu",
5201 ((sb.st_mode & S_IFMT) == S_IFCHR
5202 ? "character" : "block"),
5203 (unsigned long) sb.st_rdev);
5204 np->data = xstrdup (buf);
5205 addnode (delta->other_delta, np);
5208 "can't preserve %s: unable to save device files on this system",
5214 error (0, 0, "special file %s has unknown type", workfile);
5217 /* Save hardlinks. */
5218 delta->hardlinks = list_linked_files_on_disk (workfile);
5223 /* Create a new deltatext node. */
5224 dtext = (Deltatext *) xmalloc (sizeof (Deltatext));
5225 memset (dtext, 0, sizeof (Deltatext));
5227 dtext->log = make_message_rcslegal (message);
5229 /* If the delta tree is empty, then there's nothing to link the
5230 new delta into. So make a new delta tree, snarf the working
5231 file contents, and just write the new RCS file. */
5232 if (rcs->head == NULL)
5237 /* Figure out what the first revision number should be. */
5238 if (rev == NULL || *rev == '\0')
5239 newrev = xstrdup ("1.1");
5240 else if (numdots (rev) == 0)
5242 newrev = (char *) xmalloc (strlen (rev) + 3);
5243 strcpy (newrev, rev);
5244 strcat (newrev, ".1");
5247 newrev = xstrdup (rev);
5249 /* Don't need to xstrdup NEWREV because it's already dynamic, and
5250 not used for anything else. (Don't need to free it, either.) */
5252 delta->version = xstrdup (newrev);
5254 nodep->type = RCSVERS;
5255 nodep->delproc = rcsvers_delproc;
5256 nodep->data = delta;
5257 nodep->key = delta->version;
5258 (void) addnode (rcs->versions, nodep);
5260 dtext->version = xstrdup (newrev);
5262 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5263 if (preserve_perms && !S_ISREG (sb.st_mode))
5264 /* Pretend file is empty. */
5268 get_file (workfile, workfile,
5269 rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5270 &dtext->text, &bufsize, &dtext->len);
5274 cvs_output ("initial revision: ", 0);
5275 cvs_output (rcs->head, 0);
5276 cvs_output ("\n", 1);
5279 /* We are probably about to invalidate any cached file. */
5280 rcsbuf_cache_close ();
5282 fout = rcs_internal_lockfile (rcs->path);
5283 RCS_putadmin (rcs, fout);
5284 RCS_putdtree (rcs, rcs->head, fout);
5285 RCS_putdesc (rcs, fout);
5286 rcs->delta_pos = ftell (fout);
5287 if (rcs->delta_pos == -1)
5288 error (1, errno, "cannot ftell for %s", rcs->path);
5289 putdeltatext (fout, dtext);
5290 rcs_internal_unlockfile (fout, rcs->path);
5292 if ((flags & RCS_FLAGS_KEEPFILE) == 0)
5294 if (unlink_file (workfile) < 0)
5295 /* FIXME-update-dir: message does not include update_dir. */
5296 error (0, errno, "cannot remove %s", workfile);
5300 cvs_output ("done\n", 5);
5306 /* Derive a new revision number. From the `ci' man page:
5308 "If rev is a revision number, it must be higher than the
5309 latest one on the branch to which rev belongs, or must
5312 If rev is a branch rather than a revision number, the new
5313 revision is appended to that branch. The level number is
5314 obtained by incrementing the tip revision number of that
5315 branch. If rev indicates a non-existing branch, that
5316 branch is created with the initial revision numbered
5319 RCS_findlock_or_tip handles the case where REV is omitted.
5320 RCS 5.7 also permits REV to be "$" or to begin with a dot, but
5321 we do not address those cases -- every routine that calls
5322 RCS_checkin passes it a numeric revision. */
5324 if (rev == NULL || *rev == '\0')
5326 /* Figure out where the commit point is by looking for locks.
5327 If the commit point is at the tip of a branch (or is the
5328 head of the delta tree), then increment its revision number
5329 to obtain the new revnum. Otherwise, start a new
5331 commitpt = RCS_findlock_or_tip (rcs);
5332 if (commitpt == NULL)
5337 else if (commitpt->next == NULL
5338 || STREQ (commitpt->version, rcs->head))
5339 delta->version = increment_revnum (commitpt->version);
5341 delta->version = RCS_addbranch (rcs, commitpt->version);
5345 /* REV is either a revision number or a branch number. Find the
5346 tip of the target branch. */
5347 char *branch, *tip, *newrev, *p;
5350 assert (isdigit ((unsigned char) *rev));
5352 newrev = xstrdup (rev);
5353 dots = numdots (newrev);
5354 isrevnum = dots & 1;
5356 branch = xstrdup (rev);
5359 p = strrchr (branch, '.');
5363 /* Find the tip of the target branch. If we got a one- or two-digit
5364 revision number, this will be the head of the tree. Exception:
5365 if rev is a single-field revision equal to the branch number of
5366 the trunk (usually "1") then we want to treat it like an ordinary
5370 tip = xstrdup (rcs->head);
5371 assert (tip != NULL);
5372 if (atoi (tip) != atoi (branch))
5374 newrev = (char *) xrealloc (newrev, strlen (newrev) + 3);
5375 strcat (newrev, ".1");
5376 dots = isrevnum = 1;
5380 tip = xstrdup (rcs->head);
5382 tip = RCS_getbranch (rcs, branch, 1);
5384 /* If the branch does not exist, and we were supplied an exact
5385 revision number, signal an error. Otherwise, if we were
5386 given only a branch number, create it and set COMMITPT to
5387 the branch point. */
5392 error (0, 0, "%s: can't find branch point %s",
5399 delta->version = RCS_addbranch (rcs, branch);
5400 if (!delta->version)
5408 p = strrchr (branch, '.');
5410 tip = xstrdup (branch);
5416 /* NEWREV must be higher than TIP. */
5417 if (compare_revnums (tip, newrev) >= 0)
5420 "%s: revision %s too low; must be higher than %s",
5429 delta->version = xstrdup (newrev);
5432 /* Just increment the tip number to get the new revision. */
5433 delta->version = increment_revnum (tip);
5436 nodep = findnode (rcs->versions, tip);
5437 commitpt = nodep->data;
5444 assert (delta->version != NULL);
5446 /* If COMMITPT is locked by us, break the lock. If it's locked
5447 by someone else, signal an error. */
5448 nodep = findnode (RCS_getlocks (rcs), commitpt->version);
5451 if (! STREQ (nodep->data, delta->author))
5453 /* If we are adding a branch, then leave the old lock around.
5454 That is sensible in the sense that when adding a branch,
5455 we don't need to use the lock to tell us where to check
5456 in. It is fishy in the sense that if it is our own lock,
5457 we break it. However, this is the RCS 5.7 behavior (at
5458 the end of addbranch in ci.c in RCS 5.7, it calls
5459 removelock only if it is our own lock, not someone
5464 error (0, 0, "%s: revision %s locked by %s",
5466 nodep->key, (char *)nodep->data);
5475 dtext->version = xstrdup (delta->version);
5477 /* Obtain the change text for the new delta. If DELTA is to be the
5478 new head of the tree, then its change text should be the contents
5479 of the working file, and LEAFNODE's change text should be a diff.
5480 Else, DELTA's change text should be a diff between LEAFNODE and
5481 the working file. */
5483 tmpfile = cvs_temp_name();
5484 status = RCS_checkout (rcs, NULL, commitpt->version, NULL,
5485 ((rcs->expand != NULL
5486 && STREQ (rcs->expand, "b"))
5490 (RCSCHECKOUTPROC)0, NULL);
5493 "could not check out revision %s of `%s'",
5494 commitpt->version, rcs->path);
5497 changefile = cvs_temp_name();
5499 /* Diff options should include --binary if the RCS file has -kb set
5500 in its `expand' field. */
5501 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
5502 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
5503 if (rcs->expand && STREQ (rcs->expand, "b"))
5504 run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary");
5506 if (STREQ (commitpt->version, rcs->head) &&
5507 numdots (delta->version) == 1)
5509 /* If this revision is being inserted on the trunk, the change text
5510 for the new delta should be the contents of the working file ... */
5512 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5513 if (preserve_perms && !S_ISREG (sb.st_mode))
5514 /* Pretend file is empty. */
5518 get_file (workfile, workfile,
5519 rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5520 &dtext->text, &bufsize, &dtext->len);
5522 /* ... and the change text for the old delta should be a diff. */
5523 commitpt->text = (Deltatext *) xmalloc (sizeof (Deltatext));
5524 memset (commitpt->text, 0, sizeof (Deltatext));
5527 switch (diff_exec (workfile, tmpfile, NULL, NULL,
5528 dargc, dargv, changefile))
5534 /* FIXME-update-dir: message does not include update_dir. */
5535 error (1, errno, "error diffing %s", workfile);
5538 /* FIXME-update-dir: message does not include update_dir. */
5539 error (1, 0, "error diffing %s", workfile);
5543 /* OK, the text file case here is really dumb. Logically
5544 speaking we want diff to read the files in text mode,
5545 convert them to the canonical form found in RCS files
5546 (which, we hope at least, is independent of OS--always
5547 bare linefeeds), and then work with change texts in that
5548 format. However, diff_exec both generates change
5549 texts and produces output for user purposes (e.g. patch.c),
5550 and there is no way to distinguish between the two cases.
5551 So we actually implement the text file case by writing the
5552 change text as a text file, then reading it as a text file.
5553 This should cause no harm, but doesn't strike me as
5555 get_file (changefile, changefile,
5556 rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5557 &commitpt->text->text, &bufsize, &commitpt->text->len);
5559 /* If COMMITPT->TEXT->TEXT is NULL, it means that CHANGEFILE
5560 was empty and that there are no differences between revisions.
5561 In that event, we want to force RCS_rewrite to write an empty
5562 string for COMMITPT's change text. Leaving the change text
5563 field set NULL won't work, since that means "preserve the original
5564 change text for this delta." */
5565 if (commitpt->text->text == NULL)
5567 commitpt->text->text = xstrdup ("");
5568 commitpt->text->len = 0;
5573 /* This file is not being inserted at the head, but on a side
5574 branch somewhere. Make a diff from the previous revision
5575 to the working file. */
5576 switch (diff_exec (tmpfile, workfile, NULL, NULL,
5577 dargc, dargv, changefile))
5583 /* FIXME-update-dir: message does not include update_dir. */
5584 error (1, errno, "error diffing %s", workfile);
5587 /* FIXME-update-dir: message does not include update_dir. */
5588 error (1, 0, "error diffing %s", workfile);
5591 /* See the comment above, at the other get_file invocation,
5592 regarding binary vs. text. */
5593 get_file (changefile, changefile,
5594 rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5595 &dtext->text, &bufsize,
5597 if (dtext->text == NULL)
5599 dtext->text = xstrdup ("");
5604 run_arg_free_p (dargc, dargv);
5607 /* Update DELTA linkage. It is important not to do this before
5608 the very end of RCS_checkin; if an error arises that forces
5609 us to abort checking in, we must not have malformed deltas
5610 partially linked into the tree.
5612 If DELTA and COMMITPT are on different branches, do nothing --
5613 DELTA is linked to the tree through COMMITPT->BRANCHES, and we
5614 don't want to change `next' pointers.
5616 Otherwise, if the nodes are both on the trunk, link DELTA to
5617 COMMITPT; otherwise, link COMMITPT to DELTA. */
5619 if (numdots (commitpt->version) == numdots (delta->version))
5621 if (STREQ (commitpt->version, rcs->head))
5623 delta->next = rcs->head;
5624 rcs->head = xstrdup (delta->version);
5627 commitpt->next = xstrdup (delta->version);
5630 /* Add DELTA to RCS->VERSIONS. */
5631 if (rcs->versions == NULL)
5632 rcs->versions = getlist();
5634 nodep->type = RCSVERS;
5635 nodep->delproc = rcsvers_delproc;
5636 nodep->data = delta;
5637 nodep->key = delta->version;
5638 (void) addnode (rcs->versions, nodep);
5640 /* Write the new RCS file, inserting the new delta at COMMITPT. */
5643 cvs_output ("new revision: ", 14);
5644 cvs_output (delta->version, 0);
5645 cvs_output ("; previous revision: ", 21);
5646 cvs_output (commitpt->version, 0);
5647 cvs_output ("\n", 1);
5650 RCS_rewrite (rcs, dtext, commitpt->version);
5652 if ((flags & RCS_FLAGS_KEEPFILE) == 0)
5654 if (unlink_file (workfile) < 0)
5655 /* FIXME-update-dir: message does not include update_dir. */
5656 error (1, errno, "cannot remove %s", workfile);
5658 if (unlink_file (tmpfile) < 0)
5659 error (0, errno, "cannot remove %s", tmpfile);
5661 if (unlink_file (changefile) < 0)
5662 error (0, errno, "cannot remove %s", changefile);
5666 cvs_output ("done\n", 5);
5671 if (commitpt != NULL && commitpt->text != NULL)
5673 freedeltatext (commitpt->text);
5674 commitpt->text = NULL;
5677 freedeltatext (dtext);
5680 /* If delta has not been added to a List, then freeing the Node key
5681 * won't free delta->version.
5683 if (delta->version) free (delta->version);
5684 free_rcsvers_contents (delta);
5692 /* This structure is passed between RCS_cmp_file and cmp_file_buffer. */
5693 struct cmp_file_data
5695 const char *filename;
5700 /* Compare the contents of revision REV1 of RCS file RCS with the
5701 contents of REV2 if given, otherwise, compare with the contents of
5702 the file FILENAME. OPTIONS is a string for the keyword
5703 expansion options. Return 0 if the contents of the revision are
5704 the same as the contents of the file, 1 if they are different. */
5706 RCS_cmp_file (rcs, rev1, rev1_cache, rev2, options, filename)
5711 const char *options;
5712 const char *filename;
5716 if (options != NULL && options[0] != '\0')
5717 binary = STREQ (options, "-kb");
5722 expand = RCS_getexpand (rcs);
5723 if (expand != NULL && STREQ (expand, "b"))
5729 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5730 /* If CVS is to deal properly with special files (when
5731 PreservePermissions is on), the best way is to check out the
5732 revision to a temporary file and call `xcmp' on the two disk
5733 files. xcmp needs to handle non-regular files properly anyway,
5734 so calling it simplifies RCS_cmp_file. We *could* just yank
5735 the delta node out of the version tree and look for device
5736 numbers, but writing to disk and calling xcmp is a better
5737 abstraction (therefore probably more robust). -twp */
5744 tmp = cvs_temp_name();
5745 retcode = RCS_checkout(rcs, NULL, rev, NULL, options, tmp, NULL, NULL);
5749 retcode = xcmp (tmp, filename);
5750 if (CVS_UNLINK (tmp) < 0)
5751 error (0, errno, "cannot remove %s", tmp);
5759 struct cmp_file_data data;
5760 const char *use_file1;
5761 char *tmpfile = NULL;
5765 /* Open & cache rev1 */
5766 tmpfile = cvs_temp_name();
5767 if (RCS_checkout (rcs, NULL, rev1, NULL, options, tmpfile,
5768 (RCSCHECKOUTPROC)0, NULL))
5770 "cannot check out revision %s of %s",
5772 use_file1 = tmpfile;
5773 if (rev1_cache != NULL)
5774 *rev1_cache = tmpfile;
5777 use_file1 = filename;
5779 fp = CVS_FOPEN (use_file1, binary ? FOPEN_BINARY_READ : "r");
5781 /* FIXME-update-dir: should include update_dir in message. */
5782 error (1, errno, "cannot open file %s for comparing", use_file1);
5784 data.filename = use_file1;
5788 if (RCS_checkout (rcs, (char *)NULL, rev2 ? rev2 : rev1,
5789 (char *)NULL, options, RUN_TTY, cmp_file_buffer,
5792 "cannot check out revision %s of %s",
5793 rev2 ? rev2 : rev1, rcs->path);
5795 /* If we have not yet found a difference, make sure that we are at
5796 the end of the file. */
5797 if (!data.different)
5799 if (getc (fp) != EOF)
5804 if (rev1_cache == NULL && tmpfile)
5806 if (CVS_UNLINK (tmpfile ) < 0)
5807 error (0, errno, "cannot remove %s", tmpfile);
5811 return data.different;
5817 /* This is a subroutine of RCS_cmp_file. It is passed to
5819 #define CMP_BUF_SIZE (8 * 1024)
5822 cmp_file_buffer (callerdat, buffer, len)
5827 struct cmp_file_data *data = (struct cmp_file_data *)callerdat;
5830 /* If we've already found a difference, we don't need to check
5832 if (data->different)
5835 filebuf = xmalloc (len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len);
5841 checklen = len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len;
5842 if (fread (filebuf, 1, checklen, data->fp) != checklen)
5844 if (ferror (data->fp))
5845 error (1, errno, "cannot read file %s for comparing",
5847 data->different = 1;
5852 if (memcmp (filebuf, buffer, checklen) != 0)
5854 data->different = 1;
5868 /* For RCS file RCS, make symbolic tag TAG point to revision REV.
5869 This validates that TAG is OK for a user to use. Return value is
5870 -1 for error (and errno is set to indicate the error), positive for
5871 error (and an error message has been printed), or zero for success. */
5874 RCS_settag (rcs, tag, rev)
5882 if (rcs->flags & PARTIAL)
5883 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5885 /* FIXME: This check should be moved to RCS_check_tag. There is no
5886 reason for it to be here. */
5887 if (STREQ (tag, TAG_BASE)
5888 || STREQ (tag, TAG_HEAD))
5890 /* Print the name of the tag might be considered redundant
5891 with the caller, which also prints it. Perhaps this helps
5892 clarify why the tag name is considered reserved, I don't
5894 error (0, 0, "Attempt to add reserved tag name %s", tag);
5898 /* A revision number of NULL means use the head or default branch.
5899 If rev is not NULL, it may be a symbolic tag or branch number;
5900 expand it to the correct numeric revision or branch head. */
5902 rev = rcs->branch ? rcs->branch : rcs->head;
5904 /* At this point rcs->symbol_data may not have been parsed.
5905 Calling RCS_symbols will force it to be parsed into a list
5906 which we can easily manipulate. */
5907 symbols = RCS_symbols (rcs);
5908 if (symbols == NULL)
5910 symbols = getlist ();
5911 rcs->symbols = symbols;
5913 node = findnode (symbols, tag);
5917 node->data = xstrdup (rev);
5922 node->key = xstrdup (tag);
5923 node->data = xstrdup (rev);
5924 (void) addnode_at_front (symbols, node);
5930 /* Delete the symbolic tag TAG from the RCS file RCS. Return 0 if
5931 the tag was found (and removed), or 1 if it was not present. (In
5932 either case, the tag will no longer be in RCS->SYMBOLS.) */
5935 RCS_deltag (rcs, tag)
5941 if (rcs->flags & PARTIAL)
5942 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5944 symbols = RCS_symbols (rcs);
5945 if (symbols == NULL)
5948 node = findnode (symbols, tag);
5957 /* Set the default branch of RCS to REV. */
5960 RCS_setbranch (rcs, rev)
5964 if (rcs->flags & PARTIAL)
5965 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5970 if (rev == NULL && rcs->branch == NULL)
5972 if (rev != NULL && rcs->branch != NULL && STREQ (rev, rcs->branch))
5975 if (rcs->branch != NULL)
5977 rcs->branch = xstrdup (rev);
5982 /* Lock revision REV. LOCK_QUIET is 1 to suppress output. FIXME:
5983 Most of the callers only call us because RCS_checkin still tends to
5984 like a lock (a relic of old behavior inherited from the RCS ci
5985 program). If we clean this up, only "cvs admin -l" will still need
5986 to call RCS_lock. */
5988 /* FIXME-twp: if a lock owned by someone else is broken, should this
5989 send mail to the lock owner? Prompt user? It seems like such an
5990 obscure situation for CVS as almost not worth worrying much
5994 RCS_lock (rcs, rev, lock_quiet)
6004 if (rcs->flags & PARTIAL)
6005 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6007 locks = RCS_getlocks (rcs);
6009 locks = rcs->locks = getlist();
6012 /* A revision number of NULL means lock the head or default branch. */
6014 xrev = RCS_head (rcs);
6016 xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
6018 /* Make sure that the desired revision exists. Technically,
6019 we can update the locks list without even checking this,
6020 but RCS 5.7 did this. And it can't hurt. */
6021 if (xrev == NULL || findnode (rcs->versions, xrev) == NULL)
6024 error (0, 0, "%s: revision %s absent", rcs->path, rev);
6029 /* Is this rev already locked? */
6030 p = findnode (locks, xrev);
6033 if (STREQ (p->data, user))
6035 /* We already own the lock on this revision, so do nothing. */
6041 /* Well, first of all, "rev" below should be "xrev" to avoid
6042 core dumps. But more importantly, should we really be
6043 breaking the lock unconditionally? What CVS 1.9 does (via
6044 RCS) is to prompt "Revision 1.1 is already locked by fred.
6045 Do you want to break the lock? [ny](n): ". Well, we don't
6046 want to interact with the user (certainly not at the
6047 server/protocol level, and probably not in the command-line
6048 client), but isn't it more sensible to give an error and
6049 let the user run "cvs admin -u" if they want to break the
6052 /* Break the lock. */
6055 cvs_output (rev, 0);
6056 cvs_output (" unlocked\n", 0);
6060 error (1, 0, "Revision %s is already locked by %s", xrev, (char *)p->data);
6064 /* Create a new lock. */
6066 p->key = xrev; /* already xstrdupped */
6067 p->data = xstrdup (getcaller());
6068 (void) addnode_at_front (locks, p);
6072 cvs_output (xrev, 0);
6073 cvs_output (" locked\n", 0);
6079 /* Unlock revision REV. UNLOCK_QUIET is 1 to suppress output. FIXME:
6080 Like RCS_lock, this can become a no-op if we do the checkin
6083 If REV is not null and is locked by someone else, break their
6084 lock and notify them. It is an open issue whether RCS_unlock
6085 queries the user about whether or not to break the lock. */
6088 RCS_unlock (rcs, rev, unlock_quiet)
6099 if (rcs->flags & PARTIAL)
6100 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6102 /* If rev is NULL, unlock the revision held by the caller; if more
6103 than one, make the user specify the revision explicitly. This
6104 differs from RCS which unlocks the latest revision (first in
6105 rcs->locks) held by the caller. */
6110 /* No-ops: attempts to unlock an empty tree or an unlocked file. */
6111 if (rcs->head == NULL)
6114 cvs_outerr ("can't unlock an empty tree\n", 0);
6118 locks = RCS_getlocks (rcs);
6122 cvs_outerr ("No locks are set.\n", 0);
6127 for (p = locks->list->next; p != locks->list; p = p->next)
6129 if (STREQ (p->data, user))
6135 %s: multiple revisions locked by %s; please specify one", rcs->path, user);
6144 error (0, 0, "No locks are set for %s.\n", user);
6145 return 0; /* no lock found, ergo nothing to do */
6147 xrev = xstrdup (lock->key);
6151 xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
6154 error (0, 0, "%s: revision %s absent", rcs->path, rev);
6159 lock = findnode (RCS_getlocks (rcs), xrev);
6162 /* This revision isn't locked. */
6167 if (! STREQ (lock->data, user))
6169 /* If the revision is locked by someone else, notify
6170 them. Note that this shouldn't ever happen if RCS_unlock
6171 is called with a NULL revision, since that means "whatever
6172 revision is currently locked by the caller." */
6173 char *repos, *workfile;
6176 %s: revision %s locked by %s; breaking lock", rcs->path, xrev, (char *)lock->data);
6177 repos = xstrdup (rcs->path);
6178 workfile = strrchr (repos, '/');
6180 notify_do ('C', workfile, user, NULL, NULL, repos);
6187 cvs_output (xrev, 0);
6188 cvs_output (" unlocked\n", 0);
6195 /* Add USER to the access list of RCS. Do nothing if already present.
6196 FIXME-twp: check syntax of USER to make sure it's a valid id. */
6199 RCS_addaccess (rcs, user)
6205 if (rcs->flags & PARTIAL)
6206 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6208 if (rcs->access == NULL)
6209 rcs->access = xstrdup (user);
6212 access = xstrdup (rcs->access);
6213 for (a = strtok (access, " "); a != NULL; a = strtok (NULL, " "))
6215 if (STREQ (a, user))
6222 rcs->access = (char *) xrealloc
6223 (rcs->access, strlen (rcs->access) + strlen (user) + 2);
6224 strcat (rcs->access, " ");
6225 strcat (rcs->access, user);
6229 /* Remove USER from the access list of RCS. */
6232 RCS_delaccess (rcs, user)
6239 if (rcs->flags & PARTIAL)
6240 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6242 if (rcs->access == NULL)
6253 ulen = strlen (user);
6256 if (strncmp (p, user, ulen) == 0 && (p[ulen] == '\0' || p[ulen] == ' '))
6258 p = strchr (p, ' ');
6276 if (rcs->flags & PARTIAL)
6277 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6282 static int findtag PROTO ((Node *, void *));
6284 /* Return a nonzero value if the revision specified by ARG is found. */
6291 char *rev = (char *)arg;
6293 if (STREQ (node->data, rev))
6299 static int findmagictag PROTO ((Node *, void *));
6301 /* Return a nonzero value if a magic tag rooted at ARG is found. */
6304 findmagictag (node, arg)
6308 char *rev = (char *)arg;
6309 size_t len = strlen (rev);
6311 if (strncmp (node->data, rev, len) == 0 &&
6312 strncmp ((char *)node->data + len, ".0.", 3) == 0)
6318 /* Delete revisions between REV1 and REV2. The changes between the two
6319 revisions must be collapsed, and the result stored in the revision
6320 immediately preceding the lower one. Return 0 for successful completion,
6323 Solution: check out the revision preceding REV1 and the revision
6324 following REV2. Use call_diff to find aggregate diffs between
6325 these two revisions, and replace the delta text for the latter one
6326 with the new aggregate diff. Alternatively, we could write a
6327 function that takes two change texts and combines them to produce a
6328 new change text, without checking out any revs or calling diff. It
6329 would be hairy, but so, so cool.
6331 If INCLUSIVE is set, then TAG1 and TAG2, if non-NULL, tell us to
6332 delete that revision as well (cvs admin -o tag1:tag2). If clear,
6333 delete up to but not including that revision (cvs admin -o tag1::tag2).
6334 This does not affect TAG1 or TAG2 being NULL; the meaning of the start
6335 point in ::tag2 and :tag2 is the same and likewise for end points. */
6338 RCS_delete_revs (rcs, tag1, tag2, inclusive)
6346 RCSVers *revp = NULL;
6351 char *branchpoint = NULL;
6354 int rev1_inclusive = inclusive;
6355 int rev2_inclusive = inclusive;
6356 char *before = NULL;
6358 char *beforefile = NULL;
6359 char *afterfile = NULL;
6360 char *outfile = NULL;
6362 if (tag1 == NULL && tag2 == NULL)
6365 /* Assume error status until everything is finished. */
6368 /* Make sure both revisions exist. */
6371 rev1 = RCS_gettag (rcs, tag1, 1, NULL);
6372 if (rev1 == NULL || (nodep = findnode (rcs->versions, rev1)) == NULL)
6374 error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag1);
6380 rev2 = RCS_gettag (rcs, tag2, 1, NULL);
6381 if (rev2 == NULL || (nodep = findnode (rcs->versions, rev2)) == NULL)
6383 error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag2);
6388 /* If rev1 is on the trunk and rev2 is NULL, rev2 should be
6389 RCS->HEAD. (*Not* RCS_head(rcs), which may return rcs->branch
6390 instead.) We need to check this special case early, in order
6391 to make sure that rev1 and rev2 get ordered correctly. */
6392 if (rev2 == NULL && numdots (rev1) == 1)
6394 rev2 = xstrdup (rcs->head);
6401 if (rev1 != NULL && rev2 != NULL)
6403 /* A range consisting of a branch number means the latest revision
6405 if (RCS_isbranch (rcs, rev1) && STREQ (rev1, rev2))
6407 char *tmp = RCS_getbranch (rcs, rev1, 0);
6414 /* Make sure REV1 and REV2 are ordered correctly (in the
6415 same order as the next field). For revisions on the
6416 trunk, REV1 should be higher than REV2; for branches,
6417 REV1 should be lower. */
6418 /* Shouldn't we just be giving an error in the case where
6419 the user specifies the revisions in the wrong order
6420 (that is, always swap on the trunk, never swap on a
6421 branch, in the non-error cases)? It is not at all
6422 clear to me that users who specify -o 1.4:1.2 really
6423 meant to type -o 1.2:1.4, and the out of order usage
6424 has never been documented, either by cvs.texinfo or
6428 if (numdots (rev1) == 1)
6430 if (compare_revnums (rev1, rev2) <= 0)
6436 temp_inclusive = rev2_inclusive;
6437 rev2_inclusive = rev1_inclusive;
6438 rev1_inclusive = temp_inclusive;
6441 else if (compare_revnums (rev1, rev2) > 0)
6447 temp_inclusive = rev2_inclusive;
6448 rev2_inclusive = rev1_inclusive;
6449 rev1_inclusive = temp_inclusive;
6454 /* Basically the same thing; make sure that the ordering is what we
6458 assert (rev2 != NULL);
6459 if (numdots (rev2) == 1)
6461 /* Swap rev1 and rev2. */
6467 temp_inclusive = rev2_inclusive;
6468 rev2_inclusive = rev1_inclusive;
6469 rev1_inclusive = temp_inclusive;
6473 /* Put the revision number preceding the first one to delete into
6474 BEFORE (where "preceding" means according to the next field).
6475 If the first revision to delete is the first revision on its
6476 branch (e.g. 1.3.2.1), BEFORE should be the node on the trunk
6477 at which the branch is rooted. If the first revision to delete
6478 is the head revision of the trunk, set BEFORE to NULL.
6480 Note that because BEFORE may not be on the same branch as REV1,
6481 it is not very handy for navigating the revision tree. It's
6482 most useful just for checking out the revision preceding REV1. */
6484 branchpoint = RCS_getbranchpoint (rcs, rev1 != NULL ? rev1 : rev2);
6487 rev1 = xstrdup (branchpoint);
6488 if (numdots (branchpoint) > 1)
6491 bp = strrchr (branchpoint, '.');
6492 while (*--bp != '.')
6495 /* Note that this is exclusive, always, because the inclusive
6496 flag doesn't affect the meaning when rev1 == NULL. */
6497 before = xstrdup (branchpoint);
6501 else if (! STREQ (rev1, branchpoint))
6503 /* Walk deltas from BRANCHPOINT on, looking for REV1. */
6504 nodep = findnode (rcs->versions, branchpoint);
6506 while (revp->next != NULL && ! STREQ (revp->next, rev1))
6509 nodep = findnode (rcs->versions, revp->next);
6511 if (revp->next == NULL)
6513 error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, rev1);
6517 before = xstrdup (revp->version);
6521 nodep = findnode (rcs->versions, before);
6522 rev1 = xstrdup (((RCSVers *)nodep->data)->next);
6525 else if (!rev1_inclusive)
6528 nodep = findnode (rcs->versions, before);
6529 rev1 = xstrdup (((RCSVers *)nodep->data)->next);
6531 else if (numdots (branchpoint) > 1)
6533 /* Example: rev1 is "1.3.2.1", branchpoint is "1.3.2.1".
6534 Set before to "1.3". */
6536 bp = strrchr (branchpoint, '.');
6537 while (*--bp != '.')
6540 before = xstrdup (branchpoint);
6544 /* If any revision between REV1 and REV2 is locked or is a branch point,
6545 we can't delete that revision and must abort. */
6549 while (!found && next != NULL)
6551 nodep = findnode (rcs->versions, next);
6555 found = STREQ (revp->version, rev2);
6558 if ((!found && next != NULL) || rev2_inclusive || rev2 == NULL)
6560 if (findnode (RCS_getlocks (rcs), revp->version))
6562 error (0, 0, "%s: can't remove locked revision %s",
6567 if (revp->branches != NULL)
6569 error (0, 0, "%s: can't remove branch point %s",
6575 /* Doing this only for the :: syntax is for compatibility.
6576 See cvs.texinfo for somewhat more discussion. */
6578 (walklist (RCS_symbols (rcs), findtag, revp->version) ||
6579 walklist (RCS_symbols (rcs), findmagictag, revp->version)))
6581 /* We don't print which file this happens to on the theory
6582 that the caller will print the name of the file in a
6583 more useful fashion (fullname not rcs->path). */
6584 error (0, 0, "cannot remove revision %s because it has tags",
6589 /* It's misleading to print the `deleting revision' output
6590 here, since we may not actually delete these revisions.
6591 But that's how RCS does it. Bleah. Someday this should be
6592 moved to the point where the revs are actually marked for
6594 cvs_output ("deleting revision ", 0);
6595 cvs_output (revp->version, 0);
6596 cvs_output ("\n", 1);
6605 after = xstrdup (next);
6607 after = xstrdup (revp->version);
6609 else if (!inclusive)
6611 /* In the case of an empty range, for example 1.2::1.2 or
6612 1.2::1.3, we want to just do nothing. */
6618 /* This looks fishy in the cases where tag1 == NULL or tag2 == NULL.
6619 Are those cases really impossible? */
6620 assert (tag1 != NULL);
6621 assert (tag2 != NULL);
6623 error (0, 0, "%s: invalid revision range %s:%s", rcs->path,
6628 if (after == NULL && before == NULL)
6630 /* The user is trying to delete all revisions. While an
6631 RCS file without revisions makes sense to RCS (e.g. the
6632 state after "rcs -i"), CVS has never been able to cope with
6633 it. So at least for now we just make this an error.
6635 We don't include rcs->path in the message since "cvs admin"
6636 already printed "RCS file:" and the name. */
6637 error (1, 0, "attempt to delete all revisions");
6640 /* The conditionals at this point get really hairy. Here is the
6643 IF before != NULL and after == NULL
6644 THEN don't check out any revisions, just delete them
6645 IF before == NULL and after != NULL
6646 THEN only check out after's revision, and use it for the new deltatext
6648 check out both revisions and diff -n them. This could use
6649 RCS_exec_rcsdiff with some changes, like being able
6650 to suppress diagnostic messages and to direct output. */
6655 size_t bufsize, len;
6657 #if defined (WOE32) && !defined (__CYGWIN32__)
6658 /* FIXME: This is an awful kludge, but at least until I have
6659 time to work on it a little more and test it, I'd rather
6660 give a fatal error than corrupt the file. I think that we
6661 need to use "-kb" and "--binary" and "rb" to get_file
6662 (probably can do it always, not just for binary files, if
6663 we are consistent between the RCS_checkout and the diff). */
6665 char *expand = RCS_getexpand (rcs);
6666 if (expand != NULL && STREQ (expand, "b"))
6668 "admin -o not implemented yet for binary on this system");
6672 afterfile = cvs_temp_name();
6673 status = RCS_checkout (rcs, NULL, after, NULL, "-ko", afterfile,
6674 (RCSCHECKOUTPROC)0, NULL);
6680 /* We are deleting revisions from the head of the tree,
6681 so must create a new head. */
6684 get_file (afterfile, afterfile, "r", &diffbuf, &bufsize, &len);
6686 save_noexec = noexec;
6688 if (unlink_file (afterfile) < 0)
6689 error (0, errno, "cannot remove %s", afterfile);
6690 noexec = save_noexec;
6696 rcs->head = xstrdup (after);
6701 size_t darg_allocated = 0;
6702 char **dargv = NULL;
6704 beforefile = cvs_temp_name();
6705 status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
6706 (RCSCHECKOUTPROC)0, NULL);
6710 outfile = cvs_temp_name();
6711 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
6712 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
6713 status = diff_exec (beforefile, afterfile, NULL, NULL,
6714 dargc, dargv, outfile);
6715 run_arg_free_p (dargc, dargv);
6720 /* Not sure we need this message; will diff_exec already
6721 have printed an error? */
6722 error (0, 0, "%s: could not diff", rcs->path);
6729 get_file (outfile, outfile, "r", &diffbuf, &bufsize, &len);
6732 /* Save the new change text in after's delta node. */
6733 nodep = findnode (rcs->versions, after);
6736 assert (revp->text == NULL);
6738 revp->text = (Deltatext *) xmalloc (sizeof (Deltatext));
6739 memset ((Deltatext *) revp->text, 0, sizeof (Deltatext));
6740 revp->text->version = xstrdup (revp->version);
6741 revp->text->text = diffbuf;
6742 revp->text->len = len;
6744 /* If DIFFBUF is NULL, it means that OUTFILE is empty and that
6745 there are no differences between the two revisions. In that
6746 case, we want to force RCS_copydeltas to write an empty string
6747 for the new change text (leaving the text field set NULL
6748 means "preserve the original change text for this delta," so
6749 we don't want that). */
6750 if (revp->text->text == NULL)
6751 revp->text->text = xstrdup ("");
6754 /* Walk through the revisions (again) to mark each one as
6755 outdated. (FIXME: would it be safe to use the `dead' field for
6758 next != NULL && (after == NULL || ! STREQ (next, after));
6761 nodep = findnode (rcs->versions, next);
6766 /* Update delta links. If BEFORE == NULL, we're changing the
6767 head of the tree and don't need to update any `next' links. */
6770 /* If REV1 is the first node on its branch, then BEFORE is its
6771 root node (on the trunk) and we have to update its branches
6772 list. Otherwise, BEFORE is on the same branch as AFTER, and
6773 we can just change BEFORE's `next' field to point to AFTER.
6774 (This should be safe: since findnode manages its lists via
6775 the `hashnext' and `hashprev' fields, rather than `next' and
6776 `prev', mucking with `next' and `prev' should not corrupt the
6777 delta tree's internal structure. Much. -twp) */
6780 /* beforep's ->next field already should be equal to after,
6781 which I think is always NULL in this case. */
6783 else if (STREQ (rev1, branchpoint))
6785 nodep = findnode (rcs->versions, before);
6787 nodep = revp->branches->list->next;
6788 while (nodep != revp->branches->list &&
6789 ! STREQ (nodep->key, rev1))
6790 nodep = nodep->next;
6791 assert (nodep != revp->branches->list);
6797 nodep->key = xstrdup (after);
6802 nodep = findnode (rcs->versions, before);
6803 beforep = nodep->data;
6804 free (beforep->next);
6805 beforep->next = xstrdup (after);
6814 if (rev2 && rev2 != rev1)
6816 if (branchpoint != NULL)
6823 save_noexec = noexec;
6825 if (beforefile != NULL)
6827 if (unlink_file (beforefile) < 0)
6828 error (0, errno, "cannot remove %s", beforefile);
6831 if (afterfile != NULL)
6833 if (unlink_file (afterfile) < 0)
6834 error (0, errno, "cannot remove %s", afterfile);
6837 if (outfile != NULL)
6839 if (unlink_file (outfile) < 0)
6840 error (0, errno, "cannot remove %s", outfile);
6843 noexec = save_noexec;
6849 * TRUE if there exists a symbolic tag "tag" in file.
6852 RCS_exist_tag (rcs, tag)
6857 assert (rcs != NULL);
6859 if (findnode (RCS_symbols (rcs), tag))
6866 * TRUE if RCS revision number "rev" exists.
6867 * This includes magic branch revisions, not found in rcs->versions,
6868 * but only in rcs->symbols, requiring a list walk to find them.
6869 * Take advantage of list walk callback function already used by
6870 * RCS_delete_revs, above.
6873 RCS_exist_rev (rcs, rev)
6878 assert (rcs != NULL);
6880 if (rcs->flags & PARTIAL)
6881 RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6883 if (findnode(rcs->versions, rev) != 0)
6886 if (walklist (RCS_symbols(rcs), findtag, rev) != 0)
6894 /* RCS_deltas and friends. Processing of the deltas in RCS files. */
6898 /* Text of this line. Part of the same malloc'd block as the struct
6899 line itself (we probably should use the "struct hack" (char text[1])
6900 and save ourselves sizeof (char *) bytes). Does not include \n;
6901 instead has_newline indicates the presence or absence of \n. */
6903 /* Length of this line, not counting \n if has_newline is true. */
6905 /* Version in which it was introduced. */
6907 /* Nonzero if this line ends with \n. This will always be true
6908 except possibly for the last line. */
6910 /* Number of pointers to this struct line. */
6916 /* How many lines in use for this linevector? */
6917 unsigned int nlines;
6918 /* How many lines allocated for this linevector? */
6919 unsigned int lines_alloced;
6920 /* Pointer to array containing a pointer to each line. */
6921 struct line **vector;
6924 static void linevector_init PROTO ((struct linevector *));
6926 /* Initialize *VEC to be a linevector with no lines. */
6928 linevector_init (vec)
6929 struct linevector *vec;
6931 vec->lines_alloced = 0;
6936 static int linevector_add PROTO ((struct linevector *vec, const char *text,
6937 size_t len, RCSVers *vers,
6940 /* Given some text TEXT, add each of its lines to VEC before line POS
6941 (where line 0 is the first line). The last line in TEXT may or may
6942 not be \n terminated.
6943 Set the version for each of the new lines to VERS. This
6944 function returns non-zero for success. It returns zero if the line
6945 number is out of range.
6947 Each of the lines in TEXT are copied to space which is managed with
6948 the linevector (and freed by linevector_free). So the caller doesn't
6949 need to keep TEXT around after the call to this function. */
6951 linevector_add (vec, text, len, vers, pos)
6952 struct linevector *vec;
6958 const char *textend;
6962 const char *nextline_text;
6963 size_t nextline_len;
6964 int nextline_newline;
6970 textend = text + len;
6972 /* Count the number of lines we will need to add. */
6974 for (p = text; p < textend; ++p)
6975 if (*p == '\n' && p + 1 < textend)
6978 /* Expand VEC->VECTOR if needed. */
6979 if (vec->nlines + nnew >= vec->lines_alloced)
6981 if (vec->lines_alloced == 0)
6982 vec->lines_alloced = 10;
6983 while (vec->nlines + nnew >= vec->lines_alloced)
6984 vec->lines_alloced *= 2;
6985 vec->vector = xrealloc (vec->vector,
6986 vec->lines_alloced * sizeof (*vec->vector));
6989 /* Make room for the new lines in VEC->VECTOR. */
6990 for (i = vec->nlines + nnew - 1; i >= pos + nnew; --i)
6991 vec->vector[i] = vec->vector[i - nnew];
6993 if (pos > vec->nlines)
6996 /* Actually add the lines, to VEC->VECTOR. */
6998 nextline_text = text;
6999 nextline_newline = 0;
7000 for (p = text; p < textend; ++p)
7003 nextline_newline = 1;
7004 if (p + 1 == textend)
7005 /* If there are no characters beyond the last newline, we
7006 don't consider it another line. */
7008 nextline_len = p - nextline_text;
7009 q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
7011 q->text = (char *)q + sizeof (struct line);
7012 q->len = nextline_len;
7013 q->has_newline = nextline_newline;
7015 memcpy (q->text, nextline_text, nextline_len);
7016 vec->vector[i++] = q;
7018 nextline_text = (char *)p + 1;
7019 nextline_newline = 0;
7021 nextline_len = p - nextline_text;
7022 q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
7024 q->text = (char *)q + sizeof (struct line);
7025 q->len = nextline_len;
7026 q->has_newline = nextline_newline;
7028 memcpy (q->text, nextline_text, nextline_len);
7031 vec->nlines += nnew;
7036 static void linevector_copy PROTO ((struct linevector *, struct linevector *));
7038 /* Copy FROM to TO, copying the vectors but not the lines pointed to. */
7040 linevector_copy (to, from)
7041 struct linevector *to;
7042 struct linevector *from;
7046 for (ln = 0; ln < to->nlines; ++ln)
7048 if (--to->vector[ln]->refcount == 0)
7049 free (to->vector[ln]);
7051 if (from->nlines > to->lines_alloced)
7053 if (to->lines_alloced == 0)
7054 to->lines_alloced = 10;
7055 while (from->nlines > to->lines_alloced)
7056 to->lines_alloced *= 2;
7057 to->vector = (struct line **)
7058 xrealloc (to->vector, to->lines_alloced * sizeof (*to->vector));
7060 memcpy (to->vector, from->vector,
7061 from->nlines * sizeof (*to->vector));
7062 to->nlines = from->nlines;
7063 for (ln = 0; ln < to->nlines; ++ln)
7064 ++to->vector[ln]->refcount;
7067 static void linevector_free PROTO ((struct linevector *));
7069 /* Free storage associated with linevector. */
7071 linevector_free (vec)
7072 struct linevector *vec;
7076 if (vec->vector != NULL)
7078 for (ln = 0; ln < vec->nlines; ++ln)
7079 if (vec->vector[ln] && --vec->vector[ln]->refcount == 0)
7080 free (vec->vector[ln]);
7086 static char *month_printname PROTO ((char *));
7088 /* Given a textual string giving the month (1-12), terminated with any
7089 character not recognized by atoi, return the 3 character name to
7090 print it with. I do not think it is a good idea to change these
7091 strings based on the locale; they are standard abbreviations (for
7092 example in rfc822 mail messages) which should be widely understood.
7093 Returns a pointer into static readonly storage. */
7095 month_printname (month)
7098 static const char *const months[] =
7099 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
7100 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
7103 mnum = atoi (month);
7104 if (mnum < 1 || mnum > 12)
7106 return (char *)months[mnum - 1];
7110 apply_rcs_changes PROTO ((struct linevector *, const char *, size_t,
7111 const char *, RCSVers *, RCSVers *));
7113 /* Apply changes to the line vector LINES. DIFFBUF is a buffer of
7114 * length DIFFLEN holding the change text from an RCS file (the output
7115 * of diff -n). NAME is used in error messages. The VERS field of
7116 * any line added is set to ADDVERS. The VERS field of any line
7117 * deleted is set to DELVERS, unless DELVERS is NULL, in which case
7118 * the VERS field of deleted lines is unchanged.
7121 * Non-zero if the change text is applied successfully to ORIG_LINES.
7123 * If the change text does not appear to apply to ORIG_LINES (e.g., a
7124 * line number is invalid), this function will return zero and ORIG_LINES
7125 * will remain unmolested.
7128 * If the change text is improperly formatted (e.g., it is not the output
7129 * of diff -n), the function calls error with a status of 1, causing the
7133 apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers)
7134 struct linevector *orig_lines;
7135 const char *diffbuf;
7144 /* The RCS format throws us for a loop in that the deltafrags (if
7145 we define a deltafrag as an add or a delete) need to be applied
7146 in reverse order. So we stick them into a linked list. */
7148 enum {FRAG_ADD, FRAG_DELETE} type;
7150 unsigned long nlines;
7151 const char *new_lines;
7153 struct deltafrag *next;
7155 struct deltafrag *dfhead;
7156 struct deltafrag **dftail;
7157 struct deltafrag *df;
7158 unsigned long numlines, lastmodline, offset;
7159 struct linevector lines;
7164 numlines = orig_lines->nlines; /* start with init # of lines */
7165 for (p = diffbuf; p != NULL && p < diffbuf + difflen; )
7168 if (op != 'a' && op != 'd')
7169 /* Can't just skip over the deltafrag, because the value
7170 of op determines the syntax. */
7171 error (1, 0, "unrecognized operation '\\x%x' in %s",
7173 *dftail = df = xmalloc (sizeof *df);
7174 *(dftail = &df->next) = NULL;
7176 df->pos = strtoul (p, (char **) &q, 10);
7179 error (1, 0, "number expected in %s", name);
7182 error (1, 0, "space expected in %s", name);
7183 df->nlines = strtoul (p, (char **) &q, 10);
7185 error (1, 0, "number expected in %s", name);
7188 error (1, 0, "linefeed expected in %s", name);
7194 df->type = FRAG_ADD;
7196 /* The text we want is the number of lines specified, or
7197 until the end of the value, whichever comes first (it
7198 will be the former except in the case where we are
7199 adding a line which does not end in newline). */
7200 for (q = p; i != 0; ++q)
7203 else if (q == diffbuf + difflen)
7206 error (1, 0, "premature end of change in %s", name);
7211 /* Stash away a pointer to the text we are adding. */
7216 numlines += df->nlines;
7220 /* Correct for the fact that line numbers in RCS files
7225 df->type = FRAG_DELETE;
7226 numlines -= df->nlines;
7230 /* New temp data structure to hold new org before
7231 copy back into original structure. */
7232 lines.nlines = lines.lines_alloced = numlines;
7233 lines.vector = xmalloc (numlines * sizeof *lines.vector);
7235 /* We changed the list order to first to last -- so the
7236 list never gets larger than the size numlines. */
7239 /* offset created when adding/removing lines
7240 between new and original structure */
7243 for (df = dfhead; df != NULL; )
7246 unsigned long deltaend;
7248 if (df->pos > orig_lines->nlines)
7251 /* On error, just free the rest of the list. */
7254 /* Here we need to get to the line where the next insert will
7255 begin, which is DF->pos in ORIG_LINES. We will fill up to
7256 DF->pos - OFFSET in LINES with original items. */
7257 for (deltaend = df->pos - offset;
7258 lastmodline < deltaend;
7261 /* we need to copy from the orig structure into new one */
7262 lines.vector[lastmodline] =
7263 orig_lines->vector[lastmodline + offset];
7264 lines.vector[lastmodline]->refcount++;
7271 const char *textend, *p;
7272 const char *nextline_text;
7274 int nextline_newline;
7275 size_t nextline_len;
7277 textend = df->new_lines + df->len;
7278 nextline_newline = 0;
7279 nextline_text = df->new_lines;
7280 for (p = df->new_lines; p < textend; ++p)
7284 nextline_newline = 1;
7285 if (p + 1 == textend)
7287 /* If there are no characters beyond the
7288 last newline, we don't consider it
7293 nextline_len = p - nextline_text;
7294 q = xmalloc (sizeof *q + nextline_len);
7296 q->text = (char *)(q + 1);
7297 q->len = nextline_len;
7298 q->has_newline = nextline_newline;
7300 memcpy (q->text, nextline_text, nextline_len);
7301 lines.vector[lastmodline++] = q;
7304 nextline_text = (char *)p + 1;
7305 nextline_newline = 0;
7308 nextline_len = p - nextline_text;
7309 q = xmalloc (sizeof *q + nextline_len);
7311 q->text = (char *)(q + 1);
7312 q->len = nextline_len;
7313 q->has_newline = nextline_newline;
7315 memcpy (q->text, nextline_text, nextline_len);
7316 lines.vector[lastmodline++] = q;
7318 /* For each line we add the offset between the #'s
7325 /* we are removing this many lines from the source. */
7326 offset += df->nlines;
7328 if (df->pos + df->nlines > orig_lines->nlines)
7331 for (ln = df->pos; ln < df->pos + df->nlines; ++ln)
7332 if (orig_lines->vector[ln]->refcount > 1)
7333 /* Annotate needs this but, since the original
7334 * vector is disposed of before returning from
7335 * this function, we only need keep track if
7336 * there are multiple references.
7338 orig_lines->vector[ln]->vers = delvers;
7350 /* No reason to try and move a half-mutated and known invalid
7351 * text into the output buffer.
7353 linevector_free (&lines);
7357 /* add the rest of the remaining lines to the data vector */
7358 for (; lastmodline < numlines; lastmodline++)
7360 /* we need to copy from the orig structure into new one */
7361 lines.vector[lastmodline] = orig_lines->vector[lastmodline
7363 lines.vector[lastmodline]->refcount++;
7366 /* Move the lines vector to the original structure for output,
7367 * first deleting the old.
7369 linevector_free (orig_lines);
7370 orig_lines->vector = lines.vector;
7371 orig_lines->lines_alloced = numlines;
7372 orig_lines->nlines = lines.nlines;
7378 /* Apply an RCS change text to a buffer. The function name starts
7379 with rcs rather than RCS because this does not take an RCSNode
7380 argument. NAME is used in error messages. TEXTBUF is the text
7381 buffer to change, and TEXTLEN is the size. DIFFBUF and DIFFLEN are
7382 the change buffer and size. The new buffer is returned in *RETBUF
7383 and *RETLEN. The new buffer is allocated by xmalloc.
7385 Return 1 for success. On failure, call error and return 0. */
7388 rcs_change_text (name, textbuf, textlen, diffbuf, difflen, retbuf, retlen)
7392 const char *diffbuf;
7397 struct linevector lines;
7403 linevector_init (&lines);
7405 if (! linevector_add (&lines, textbuf, textlen, NULL, 0))
7406 error (1, 0, "cannot initialize line vector");
7408 if (! apply_rcs_changes (&lines, diffbuf, difflen, name, NULL, NULL))
7410 error (0, 0, "invalid change text in %s", name);
7420 for (ln = 0; ln < lines.nlines; ++ln)
7422 n += lines.vector[ln]->len + 1;
7427 for (ln = 0; ln < lines.nlines; ++ln)
7429 memcpy (p, lines.vector[ln]->text, lines.vector[ln]->len);
7430 p += lines.vector[ln]->len;
7431 if (lines.vector[ln]->has_newline)
7435 *retlen = p - *retbuf;
7436 assert (*retlen <= n);
7441 linevector_free (&lines);
7446 /* Walk the deltas in RCS to get to revision VERSION.
7448 If OP is RCS_ANNOTATE, then write annotations using cvs_output.
7450 If OP is RCS_FETCH, then put the contents of VERSION into a
7451 newly-malloc'd array and put a pointer to it in *TEXT. Each line
7452 is \n terminated; the caller is responsible for converting text
7453 files if desired. The total length is put in *LEN.
7455 If FP is non-NULL, it should be a file descriptor open to the file
7456 RCS with file position pointing to the deltas. We close the file
7459 If LOG is non-NULL, then *LOG is set to the log message of VERSION,
7460 and *LOGLEN is set to the length of the log message.
7462 On error, give a fatal error. */
7465 RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
7468 struct rcsbuffer *rcsbuf;
7469 const char *version;
7470 enum rcs_delta_op op;
7476 struct rcsbuffer rcsbuf_local;
7477 char *branchversion;
7484 RCSVers *trunk_vers;
7486 int ishead, isnext, isversion, onbranch;
7488 struct linevector headlines;
7489 struct linevector curlines;
7490 struct linevector trunklines;
7497 rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf_local);
7498 rcsbuf = &rcsbuf_local;
7503 if (log) *log = NULL;
7513 linevector_init (&curlines);
7514 linevector_init (&headlines);
7515 linevector_init (&trunklines);
7517 /* We set BRANCHVERSION to the version we are currently looking
7518 for. Initially, this is the version on the trunk from which
7519 VERSION branches off. If VERSION is not a branch, then
7520 BRANCHVERSION is just VERSION. */
7521 branchversion = xstrdup (version);
7522 cpversion = strchr (branchversion, '.');
7523 if (cpversion != NULL)
7524 cpversion = strchr (cpversion + 1, '.');
7525 if (cpversion != NULL)
7529 if (! rcsbuf_getrevnum (rcsbuf, &key))
7530 error (1, 0, "unexpected EOF reading RCS file %s", rcs->path);
7532 /* look up the revision */
7533 node = findnode (rcs->versions, key);
7536 "Delta text %s without revision information in `%s'.",
7539 if (next != NULL && ! STREQ (next, key))
7541 /* This is not the next version we need. It is a branch
7542 version which we want to ignore. */
7550 /* Stash the previous version. */
7556 /* Compare key and trunkversion now, because key points to
7557 storage controlled by rcsbuf_getkey. */
7558 if (STREQ (branchversion, key))
7566 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7567 error (1, 0, "%s does not appear to be a valid rcs file",
7572 && STREQ (key, "log")
7573 && STREQ (branchversion, version))
7577 error (0, 0, "Duplicate `log' keyword in RCS file (`%s').",
7581 *log = rcsbuf_valcopy (rcsbuf, value, 0, loglen);
7584 if (STREQ (key, "text"))
7586 rcsbuf_valpolish (rcsbuf, value, 0, &vallen);
7589 if (! linevector_add (&curlines, value, vallen, NULL, 0))
7590 error (1, 0, "invalid rcs file %s", rcs->path);
7596 if (! apply_rcs_changes (&curlines, value, vallen,
7598 onbranch ? vers : NULL,
7599 onbranch ? NULL : prev_vers))
7600 error (1, 0, "invalid change text in %s", rcs->path);
7608 /* This is either the version we want, or it is the
7609 branchpoint to the version we want. */
7610 if (STREQ (branchversion, version))
7612 /* This is the version we want. */
7613 linevector_copy (&headlines, &curlines);
7617 /* We have found this version by tracking up a
7618 branch. Restore back to the lines we saved
7619 when we left the trunk, and continue tracking
7624 linevector_copy (&curlines, &trunklines);
7631 /* We need to look up the branch. */
7634 if (numdots (branchversion) < 2)
7638 /* We are leaving the trunk; save the current
7639 lines so that we can restore them when we
7640 continue tracking down the trunk. */
7642 linevector_copy (&trunklines, &curlines);
7644 /* Reset the version information we have
7645 accumulated so far. It only applies to the
7646 changes from the head to this version. */
7647 for (ln = 0; ln < curlines.nlines; ++ln)
7648 curlines.vector[ln]->vers = NULL;
7651 /* The next version we want is the entry on
7652 VERS->branches which matches this branch. For
7653 example, suppose VERSION is 1.21.4.3 and
7654 BRANCHVERSION was 1.21. Then we look for an entry
7655 starting with "1.21.4" and we'll put it (probably
7656 1.21.4.1) in NEXT. We'll advance BRANCHVERSION by
7657 two dots (in this example, to 1.21.4.3). */
7659 if (vers->branches == NULL)
7660 error (1, 0, "missing expected branches in %s",
7663 error (1, 0, "Invalid revision number in `%s'.",
7667 cpversion = strchr (cpversion, '.');
7668 if (cpversion == NULL)
7669 error (1, 0, "version number confusion in %s",
7671 for (p = vers->branches->list->next;
7672 p != vers->branches->list;
7674 if (strncmp (p->key, branchversion,
7675 cpversion - branchversion) == 0)
7677 if (p == vers->branches->list)
7678 error (1, 0, "missing expected branch in %s",
7683 cpversion = strchr (cpversion + 1, '.');
7684 if (cpversion != NULL)
7688 if (op == RCS_FETCH && foundhead)
7690 } while (next != NULL);
7692 free (branchversion);
7694 rcsbuf_cache (rcs, rcsbuf);
7697 error (1, 0, "could not find desired version %s in %s",
7698 version, rcs->path);
7700 /* Now print out or return the data we have just computed. */
7707 for (ln = 0; ln < headlines.nlines; ++ln)
7710 /* Period which separates year from month in date. */
7712 /* Period which separates month from day in date. */
7716 prvers = headlines.vector[ln]->vers;
7720 buf = xmalloc (strlen (prvers->version) + 24);
7721 sprintf (buf, "%-12s (%-8.8s ",
7724 cvs_output (buf, 0);
7727 /* Now output the date. */
7728 ym = strchr (prvers->date, '.');
7731 /* ??- is an ANSI trigraph. The ANSI way to
7732 avoid it is \? but some pre ANSI compilers
7733 complain about the unrecognized escape
7734 sequence. Of course string concatenation
7735 ("??" "-???") is also an ANSI-ism. Testing
7736 __STDC__ seems to be a can of worms, since
7737 compilers do all kinds of things with it. */
7738 cvs_output ("??", 0);
7739 cvs_output ("-???", 0);
7740 cvs_output ("-??", 0);
7744 md = strchr (ym + 1, '.');
7746 cvs_output ("??", 0);
7748 cvs_output (md + 1, 2);
7750 cvs_output ("-", 1);
7751 cvs_output (month_printname (ym + 1), 0);
7752 cvs_output ("-", 1);
7753 /* Only output the last two digits of the year. Our output
7754 lines are long enough as it is without printing the
7756 cvs_output (ym - 2, 2);
7758 cvs_output ("): ", 0);
7759 if (headlines.vector[ln]->len != 0)
7760 cvs_output (headlines.vector[ln]->text,
7761 headlines.vector[ln]->len);
7762 cvs_output ("\n", 1);
7772 assert (text != NULL);
7773 assert (len != NULL);
7776 for (ln = 0; ln < headlines.nlines; ++ln)
7778 n += headlines.vector[ln]->len + 1;
7781 for (ln = 0; ln < headlines.nlines; ++ln)
7783 memcpy (p, headlines.vector[ln]->text,
7784 headlines.vector[ln]->len);
7785 p += headlines.vector[ln]->len;
7786 if (headlines.vector[ln]->has_newline)
7795 linevector_free (&curlines);
7796 linevector_free (&headlines);
7797 linevector_free (&trunklines);
7802 /* Read the information for a single delta from the RCS buffer RCSBUF,
7803 whose name is RCSFILE. *KEYP and *VALP are either NULL, or the
7804 first key/value pair to read, as set by rcsbuf_getkey. Return NULL
7805 if there are no more deltas. Store the key/value pair which
7806 terminated the read in *KEYP and *VALP. */
7809 getdelta (rcsbuf, rcsfile, keyp, valp)
7810 struct rcsbuffer *rcsbuf;
7816 char *key, *value, *cp;
7819 /* Get revision number if it wasn't passed in. This uses
7820 rcsbuf_getkey because it doesn't croak when encountering
7821 unexpected input. As a result, we have to play unholy games
7822 with `key' and `value'. */
7830 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7831 error (1, 0, "%s: unexpected EOF", rcsfile);
7834 /* Make sure that it is a revision number and not a cabbage
7837 (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
7840 /* Note that when comparing with RCSDATE, we are not massaging
7841 VALUE from the string found in the RCS file. This is OK since
7842 we know exactly what to expect. */
7843 if (*cp != '\0' || strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) != 0)
7850 vnode = (RCSVers *) xmalloc (sizeof (RCSVers));
7851 memset (vnode, 0, sizeof (RCSVers));
7853 vnode->version = xstrdup (key);
7855 /* Grab the value of the date from value. Note that we are not
7856 massaging VALUE from the string found in the RCS file. */
7857 cp = value + (sizeof RCSDATE) - 1; /* skip the "date" keyword */
7858 while (whitespace (*cp)) /* take space off front of value */
7861 vnode->date = xstrdup (cp);
7863 /* Get author field. */
7864 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7866 error (1, 0, "unexpected end of file reading %s", rcsfile);
7868 if (! STREQ (key, "author"))
7870 unable to parse %s; `author' not in the expected place", rcsfile);
7871 vnode->author = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7873 /* Get state field. */
7874 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7876 error (1, 0, "unexpected end of file reading %s", rcsfile);
7878 if (! STREQ (key, "state"))
7880 unable to parse %s; `state' not in the expected place", rcsfile);
7881 vnode->state = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7882 /* The value is optional, according to rcsfile(5). */
7883 if (value != NULL && STREQ (value, RCSDEAD))
7888 /* Note that "branches" and "next" are in fact mandatory, according
7891 /* fill in the branch list (if any branches exist) */
7892 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7894 error (1, 0, "unexpected end of file reading %s", rcsfile);
7896 if (STREQ (key, RCSDESC))
7900 /* Probably could/should be a fatal error. */
7901 error (0, 0, "warning: 'branches' keyword missing from %s", rcsfile);
7904 if (value != (char *) NULL)
7906 vnode->branches = getlist ();
7907 /* Note that we are not massaging VALUE from the string found
7909 do_branches (vnode->branches, value);
7912 /* fill in the next field if there is a next revision */
7913 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7915 error (1, 0, "unexpected end of file reading %s", rcsfile);
7917 if (STREQ (key, RCSDESC))
7921 /* Probably could/should be a fatal error. */
7922 error (0, 0, "warning: 'next' keyword missing from %s", rcsfile);
7925 if (value != (char *) NULL)
7926 vnode->next = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7929 * XXX - this is where we put the symbolic link stuff???
7930 * (into newphrases in the deltas).
7934 if (! rcsbuf_getkey (rcsbuf, &key, &value))
7935 error (1, 0, "unexpected end of file reading %s", rcsfile);
7937 /* The `desc' keyword is the end of the deltas. */
7938 if (strcmp (key, RCSDESC) == 0)
7941 #ifdef PRESERVE_PERMISSIONS_SUPPORT
7943 /* The `hardlinks' value is a group of words, which must
7944 be parsed separately and added as a list to vnode->hardlinks. */
7945 if (strcmp (key, "hardlinks") == 0)
7949 vnode->hardlinks = getlist();
7950 while ((word = rcsbuf_valword (rcsbuf, &value)) != NULL)
7952 Node *n = getnode();
7954 addnode (vnode->hardlinks, n);
7960 /* Enable use of repositories created by certain obsolete
7961 versions of CVS. This code should remain indefinately;
7962 there is no procedure for converting old repositories, and
7963 checking for it is harmless. */
7964 if (STREQ (key, RCSDEAD))
7967 if (vnode->state != NULL)
7968 free (vnode->state);
7969 vnode->state = xstrdup (RCSDEAD);
7972 /* if we have a new revision number, we're done with this delta */
7974 (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
7977 /* Note that when comparing with RCSDATE, we are not massaging
7978 VALUE from the string found in the RCS file. This is OK
7979 since we know exactly what to expect. */
7980 if (*cp == '\0' && strncmp (RCSDATE, value, strlen (RCSDATE)) == 0)
7983 /* At this point, key and value represent a user-defined field
7984 in the delta node. */
7985 if (vnode->other_delta == NULL)
7986 vnode->other_delta = getlist ();
7988 kv->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
7989 kv->key = xstrdup (key);
7990 kv->data = rcsbuf_valcopy (rcsbuf, value, kv->type == RCSFIELD,
7992 if (addnode (vnode->other_delta, kv) != 0)
7994 /* Complaining about duplicate keys in newphrases seems
7995 questionable, in that we don't know what they mean and
7996 doc/RCSFILES has no prohibition on several newphrases
7997 with the same key. But we can't store more than one as
7998 long as we store them in a List *. */
7999 error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
8005 /* Return the key which caused us to fail back to the caller. */
8016 if (d->version != NULL)
8020 if (d->text != NULL)
8022 if (d->other != (List *) NULL)
8023 dellist (&d->other);
8028 RCS_getdeltatext (rcs, fp, rcsbuf)
8031 struct rcsbuffer *rcsbuf;
8038 /* Get the revision number. */
8039 if (! rcsbuf_getrevnum (rcsbuf, &num))
8041 /* If num == NULL, it means we reached EOF naturally. That's
8046 error (1, 0, "%s: unexpected EOF", rcs->path);
8049 p = findnode (rcs->versions, num);
8052 "Delta text %s without revision information in `%s'.",
8055 d = (Deltatext *) xmalloc (sizeof (Deltatext));
8056 d->version = xstrdup (num);
8058 /* Get the log message. */
8059 if (! rcsbuf_getkey (rcsbuf, &key, &value))
8060 error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
8061 if (! STREQ (key, "log"))
8062 error (1, 0, "%s, delta %s: expected `log', got `%s'",
8063 rcs->path, num, key);
8064 d->log = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
8066 /* Get random newphrases. */
8067 d->other = getlist();
8070 if (! rcsbuf_getkey (rcsbuf, &key, &value))
8071 error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
8073 if (STREQ (key, "text"))
8077 p->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
8078 p->key = xstrdup (key);
8079 p->data = rcsbuf_valcopy (rcsbuf, value, p->type == RCSFIELD,
8081 if (addnode (d->other, p) < 0)
8083 error (0, 0, "warning: %s, delta %s: duplicate field `%s'",
8084 rcs->path, num, key);
8088 /* Get the change text. We already know that this key is `text'. */
8089 d->text = rcsbuf_valcopy (rcsbuf, value, 0, &d->len);
8094 /* RCS output functions, for writing RCS format files from RCSNode
8097 For most of this work, RCS 5.7 uses an `aprintf' function which aborts
8098 program upon error. Instead, these functions check the output status
8099 of the stream right before closing it, and aborts if an error condition
8100 is found. The RCS solution is probably the better one: it produces
8101 more overhead, but will produce a clearer diagnostic in the case of
8102 catastrophic error. In either case, however, the repository will probably
8103 not get corrupted. */
8106 putsymbol_proc (symnode, fparg)
8110 FILE *fp = (FILE *) fparg;
8112 /* A fiddly optimization: this code used to just call fprintf, but
8113 in an old repository with hundreds of tags this can get called
8114 hundreds of thousands of times when doing a cvs tag. Since
8115 tagging is a relatively common operation, and using putc and
8116 fputs is just as comprehensible, the change is worthwhile. */
8119 fputs (symnode->key, fp);
8121 fputs (symnode->data, fp);
8125 static int putlock_proc PROTO ((Node *, void *));
8127 /* putlock_proc is like putsymbol_proc, but key and data are reversed. */
8130 putlock_proc (symnode, fp)
8134 return fprintf ((FILE *) fp, "\n\t%s:%s", (char *)symnode->data, symnode->key);
8138 putrcsfield_proc (node, vfp)
8142 FILE *fp = (FILE *) vfp;
8144 /* Some magic keys used internally by CVS start with `;'. Skip them. */
8145 if (node->key[0] == ';')
8148 fprintf (fp, "\n%s\t", node->key);
8149 if (node->data != NULL)
8151 /* If the field's value contains evil characters,
8152 it must be stringified. */
8153 /* FIXME: This does not quite get it right. "7jk8f" is not a legal
8154 value for a value in a newpharse, according to doc/RCSFILES,
8155 because digits are not valid in an "id". We might do OK by
8156 always writing strings (enclosed in @@). Would be nice to
8157 explicitly mention this one way or another in doc/RCSFILES.
8158 A case where we are wrong in a much more clear-cut way is that
8159 we let through non-graphic characters such as whitespace and
8160 control characters. */
8162 if (node->type == RCSCMPFLD || strpbrk (node->data, "$,.:;@") == NULL)
8163 fputs (node->data, fp);
8167 expand_at_signs (node->data, (off_t) strlen (node->data), fp);
8172 /* desc, log and text fields should not be terminated with semicolon;
8173 all other fields should be. */
8174 if (! STREQ (node->key, "desc") &&
8175 ! STREQ (node->key, "log") &&
8176 ! STREQ (node->key, "text"))
8183 #ifdef PRESERVE_PERMISSIONS_SUPPORT
8185 /* Save a filename in a `hardlinks' RCS field. NODE->KEY will contain
8186 a full pathname, but currently only basenames are stored in the RCS
8187 node. Assume that the filename includes nasty characters and
8191 puthardlink_proc (node, vfp)
8195 FILE *fp = (FILE *) vfp;
8196 char *basename = strrchr (node->key, '/');
8198 if (basename == NULL)
8199 basename = node->key;
8205 (void) expand_at_signs (basename, strlen (basename), fp);
8213 /* Output the admin node for RCS into stream FP. */
8216 RCS_putadmin (rcs, fp)
8220 fprintf (fp, "%s\t%s;\n", RCSHEAD, rcs->head ? rcs->head : "");
8222 fprintf (fp, "%s\t%s;\n", RCSBRANCH, rcs->branch);
8224 fputs ("access", fp);
8228 s = xstrdup (rcs->access);
8229 for (p = strtok (s, " \n\t"); p != NULL; p = strtok (NULL, " \n\t"))
8230 fprintf (fp, "\n\t%s", p);
8235 fputs (RCSSYMBOLS, fp);
8236 /* If we haven't had to convert the symbols to a list yet, don't
8237 force a conversion now; just write out the string. */
8238 if (rcs->symbols == NULL && rcs->symbols_data != NULL)
8241 fputs (rcs->symbols_data, fp);
8244 walklist (RCS_symbols (rcs), putsymbol_proc, (void *) fp);
8247 fputs ("locks", fp);
8248 if (rcs->locks_data)
8249 fprintf (fp, "\t%s", rcs->locks_data);
8250 else if (rcs->locks)
8251 walklist (rcs->locks, putlock_proc, (void *) fp);
8252 if (rcs->strict_locks)
8253 fprintf (fp, "; strict");
8258 fprintf (fp, "comment\t@");
8259 expand_at_signs (rcs->comment, (off_t) strlen (rcs->comment), fp);
8262 if (rcs->expand && ! STREQ (rcs->expand, "kv"))
8263 fprintf (fp, "%s\t@%s@;\n", RCSEXPAND, rcs->expand);
8265 walklist (rcs->other, putrcsfield_proc, (void *) fp);
8277 /* Skip if no revision was supplied, or if it is outdated (cvs admin -o) */
8278 if (vers == NULL || vers->outdated)
8281 fprintf (fp, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
8283 RCSDATE, vers->date,
8284 "author", vers->author,
8285 "state", vers->state ? vers->state : "");
8287 if (vers->branches != NULL)
8289 start = vers->branches->list;
8290 for (bp = start->next; bp != start; bp = bp->next)
8291 fprintf (fp, "\n\t%s", bp->key);
8294 fprintf (fp, ";\nnext\t%s;", vers->next ? vers->next : "");
8296 walklist (vers->other_delta, putrcsfield_proc, fp);
8298 #ifdef PRESERVE_PERMISSIONS_SUPPORT
8299 if (vers->hardlinks)
8301 fprintf (fp, "\nhardlinks");
8302 walklist (vers->hardlinks, puthardlink_proc, fp);
8310 RCS_putdtree (rcs, rev, fp)
8318 /* Previously, this function used a recursive implementation, but
8319 if the trunk has a huge number of revisions and the program
8320 stack is not big, a stack overflow could occur, so this
8321 nonrecursive version was developed to be more safe. */
8322 Node *branchlist, *onebranch;
8324 List *onebranchlist;
8329 branches = getlist();
8331 for (; rev != NULL;)
8333 /* Find the delta node for this revision. */
8334 p = findnode (rcs->versions, rev);
8338 "error parsing repository file %s, file may be corrupt.",
8344 /* Print the delta node and go for its `next' node. This
8345 prints the trunk. If there are any branches printed on this
8346 revision, mark we have some. */
8347 putdelta (versp, fp);
8348 /* Store branch information into branch list so to write its
8350 if (versp->branches != NULL)
8353 branch->data = versp->branches;
8355 addnode(branches, branch);
8361 /* If there are any branches printed on this revision,
8362 print those trunks as well. */
8363 branchlist = branches->list;
8364 for (branch = branchlist->next;
8365 branch != branchlist;
8366 branch = branch->next)
8368 onebranchlist = (List *)(branch->data);
8369 onebranch = onebranchlist->list;
8370 for (p = onebranch->next; p != onebranch; p = p->next)
8371 RCS_putdtree (rcs, p->key, fp);
8373 branch->data = NULL; /* so to prevent its freeing on dellist */
8380 RCS_putdesc (rcs, fp)
8384 fprintf (fp, "\n\n%s\n@", RCSDESC);
8385 if (rcs->desc != NULL)
8387 off_t len = (off_t) strlen (rcs->desc);
8390 expand_at_signs (rcs->desc, len, fp);
8391 if (rcs->desc[len-1] != '\n')
8399 putdeltatext (fp, d)
8403 fprintf (fp, "\n\n%s\nlog\n@", d->version);
8406 int loglen = strlen (d->log);
8407 expand_at_signs (d->log, (off_t) loglen, fp);
8408 if (d->log[loglen-1] != '\n')
8413 walklist (d->other, putrcsfield_proc, fp);
8415 fputs ("\ntext\n@", fp);
8416 if (d->text != NULL)
8417 expand_at_signs (d->text, (off_t) d->len, fp);
8421 /* TODO: the whole mechanism for updating deltas is kludgey... more
8422 sensible would be to supply all the necessary info in a `newdeltatext'
8423 field for RCSVers nodes. -twp */
8425 /* Copy delta text nodes from FIN to FOUT. If NEWDTEXT is non-NULL, it
8426 is a new delta text node, and should be added to the tree at the
8427 node whose revision number is INSERTPT. (Note that trunk nodes are
8428 written in decreasing order, and branch nodes are written in
8429 increasing order.) */
8432 RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
8435 struct rcsbuffer *rcsbufin;
8437 Deltatext *newdtext;
8443 int insertbefore, found;
8450 /* Count the number of versions for which we have to do some
8451 special operation. */
8452 actions = walklist (rcs->versions, count_delta_actions, (void *) NULL);
8454 /* Make a note of whether NEWDTEXT should be inserted
8455 before or after its INSERTPT. */
8456 insertbefore = (newdtext != NULL && numdots (newdtext->version) == 1);
8458 while (actions != 0 || newdtext != NULL)
8462 dtext = RCS_getdeltatext (rcs, fin, rcsbufin);
8464 /* We shouldn't hit EOF here, because that would imply that
8465 some action was not taken, or that we could not insert
8468 error (1, 0, "internal error: EOF too early in RCS_copydeltas");
8470 found = (insertpt != NULL && STREQ (dtext->version, insertpt));
8471 if (found && insertbefore)
8473 putdeltatext (fout, newdtext);
8478 np = findnode (rcs->versions, dtext->version);
8481 "Delta text %s without revision information in `%s'.",
8482 dtext->version, rcs->path);
8486 /* If this revision has been outdated, just skip it. */
8487 if (dadmin->outdated)
8489 freedeltatext (dtext);
8494 /* Update the change text for this delta. New change text
8495 data may come from cvs admin -m, cvs admin -o, or cvs ci. */
8496 if (dadmin->text != NULL)
8498 if (dadmin->text->log != NULL || dadmin->text->text != NULL)
8500 if (dadmin->text->log != NULL)
8503 dtext->log = dadmin->text->log;
8504 dadmin->text->log = NULL;
8506 if (dadmin->text->text != NULL)
8509 dtext->text = dadmin->text->text;
8510 dtext->len = dadmin->text->len;
8511 dadmin->text->text = NULL;
8514 putdeltatext (fout, dtext);
8515 freedeltatext (dtext);
8517 if (found && !insertbefore)
8519 putdeltatext (fout, newdtext);
8525 /* Copy the rest of the file directly, without bothering to
8526 interpret it. The caller will handle error checking by calling
8529 We just wrote a newline to the file, either in putdeltatext or
8530 in the caller. However, we may not have read the corresponding
8531 newline from the file, because rcsbuf_getkey returns as soon as
8532 it finds the end of the '@' string for the desc or text key.
8533 Therefore, we may read three newlines when we should really
8534 only write two, and we check for that case here. This is not
8535 an semantically important issue; we only do it to make our RCS
8536 files look traditional. */
8540 rcsbuf_get_buffered (rcsbufin, &bufrest, &buflen);
8543 if (bufrest[0] != '\n'
8544 || strncmp (bufrest, "\n\n\n", buflen < 3 ? buflen : 3) != 0)
8560 fwrite (bufrest, 1, buflen, fout);
8562 if (!rcsbufin->mmapped)
8564 /* This bit isn't necessary when using mmap since the entire file
8565 * will already be available via the RCS buffer. Besides, the
8566 * mmap code doesn't always keep the file pointer up to date, so
8567 * this adds some data twice.
8569 while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
8574 && strncmp (buf, "\n\n\n", nls) == 0)
8576 fwrite (buf + 1, 1, got - 1, fout);
8580 fwrite (buf, 1, got, fout);
8588 /* A helper procedure for RCS_copydeltas. This is called via walklist
8589 to count the number of RCS revisions for which some special action
8593 count_delta_actions (np, ignore)
8597 RCSVers *dadmin = np->data;
8599 if (dadmin->outdated)
8602 if (dadmin->text != NULL
8603 && (dadmin->text->log != NULL || dadmin->text->text != NULL))
8612 * Clean up temporary files
8617 /* Note that the checks for existence_error are because we are
8618 called from a signal handler, so we don't know whether the
8619 files got created. */
8621 /* FIXME: Do not perform buffered I/O from an interrupt handler like
8622 this (via error). However, I'm leaving the error-calling code there
8623 in the hope that on the rare occasion the error call is actually made
8624 (e.g., a fluky I/O error or permissions problem prevents the deletion
8625 of a just-created file) reentrancy won't be an issue. */
8626 if (rcs_lockfile != NULL)
8628 char *tmp = rcs_lockfile;
8629 rcs_lockfile = NULL;
8630 if (rcs_lockfd >= 0)
8632 if (close (rcs_lockfd) != 0)
8633 error (0, errno, "error closing lock file %s", tmp);
8636 if (unlink_file (tmp) < 0
8637 && !existence_error (errno))
8638 error (0, errno, "cannot remove %s", tmp);
8642 /* RCS_internal_lockfile and RCS_internal_unlockfile perform RCS-style
8643 locking on the specified RCSFILE: for a file called `foo,v', open
8644 for writing a file called `,foo,'.
8646 Note that we what do here is quite different from what RCS does.
8647 RCS creates the ,foo, file before it reads the RCS file (if it
8648 knows that it will be writing later), so that it actually serves as
8649 a lock. We don't; instead we rely on CVS writelocks. This means
8650 that if someone is running RCS on the file at the same time they
8651 are running CVS on it, they might lose (we read the file,
8652 then RCS writes it, then we write it, clobbering the
8653 changes made by RCS). I believe the current sentiment about this
8654 is "well, don't do that".
8656 A concern has been expressed about whether adopting the RCS
8657 strategy would slow us down. I don't think so, since we need to
8658 write the ,foo, file anyway (unless perhaps if O_EXCL is slower or
8661 These do not perform quite the same function as the RCS -l option
8662 for locking files: they are intended to prevent competing RCS
8663 processes from stomping all over each other's laundry. Hence,
8664 they are `internal' locking functions.
8666 If there is an error, give a fatal error; if we return we always
8667 return a non-NULL value. */
8670 rcs_internal_lockfile (rcsfile)
8675 static int first_call = 1;
8680 /* clean up if we get a signal */
8682 (void) SIG_register (SIGABRT, rcs_cleanup);
8685 (void) SIG_register (SIGHUP, rcs_cleanup);
8688 (void) SIG_register (SIGINT, rcs_cleanup);
8691 (void) SIG_register (SIGQUIT, rcs_cleanup);
8694 (void) SIG_register (SIGPIPE, rcs_cleanup);
8697 (void) SIG_register (SIGTERM, rcs_cleanup);
8701 /* Get the lock file name: `,file,' for RCS file `file,v'. */
8702 assert (rcs_lockfile == NULL);
8703 assert (rcs_lockfd < 0);
8704 rcs_lockfile = rcs_lockfilename (rcsfile);
8706 /* Use the existing RCS file mode, or read-only if this is a new
8707 file. (Really, this is a lie -- if this is a new file,
8708 RCS_checkin uses the permissions from the working copy. For
8709 actually creating the file, we use 0444 as a safe default mode.) */
8710 if (stat (rcsfile, &rstat) < 0)
8712 if (existence_error (errno))
8713 rstat.st_mode = S_IRUSR | S_IRGRP | S_IROTH;
8715 error (1, errno, "cannot stat %s", rcsfile);
8718 /* Try to open exclusively. POSIX.1 guarantees that O_EXCL|O_CREAT
8719 guarantees an exclusive open. According to the RCS source, with
8720 NFS v2 we must also throw in O_TRUNC and use an open mask that makes
8721 the file unwriteable. For extensive justification, see the comments for
8722 rcswriteopen() in rcsedit.c, in RCS 5.7. This is kind of pointless
8723 in the CVS case; see comment at the start of this file concerning
8724 general ,foo, file strategy.
8726 There is some sentiment that with NFSv3 and such, that one can
8727 rely on O_EXCL these days. This might be true for unix (I
8728 don't really know), but I am still pretty skeptical in the case
8729 of the non-unix systems. */
8730 rcs_lockfd = open (rcs_lockfile,
8731 OPEN_BINARY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
8732 S_IRUSR | S_IRGRP | S_IROTH);
8736 error (1, errno, "could not open lock file `%s'", rcs_lockfile);
8739 /* Force the file permissions, and return a stream object. */
8740 /* Because we change the modes later, we don't worry about
8741 this in the non-HAVE_FCHMOD case. */
8743 if (fchmod (rcs_lockfd, rstat.st_mode) < 0)
8744 error (1, errno, "cannot change mode for %s", rcs_lockfile);
8746 fp = fdopen (rcs_lockfd, FOPEN_BINARY_WRITE);
8748 error (1, errno, "cannot fdopen %s", rcs_lockfile);
8754 rcs_internal_unlockfile (fp, rcsfile)
8758 assert (rcs_lockfile != NULL);
8759 assert (rcs_lockfd >= 0);
8761 /* Abort if we could not write everything successfully to LOCKFILE.
8762 This is not a great error-handling mechanism, but should prevent
8763 corrupting the repository. */
8766 /* Using errno here may well be misleanding since the most recent
8767 call that set errno may not have anything whatsoever to do with
8768 the error that set the flag, but it's better than nothing. The
8769 real solution is to check each call to fprintf rather than waiting
8770 until the end like this. */
8771 error (1, errno, "error writing to lock file %s", rcs_lockfile);
8773 /* Flush and sync the file, or the user may be told the commit completed,
8774 * while a server crash/power failure could still cause the data to be
8777 * Invoking rename(",<file>," , "<file>,v") on Linux and almost all UNIXs
8778 * only flushes the inode for the target file to disk, it does not
8779 * guarantee flush of the kernel buffers allocated for the ,<file>,.
8780 * Depending upon the load on the machine, the Linux kernel's flush daemon
8781 * process may not flush for a while. In the meantime the CVS transaction
8782 * could have been declared committed to the end CVS user (CVS process has
8783 * returned the final "OK"). If the machine crashes prior to syncing the
8784 * changes to disk, the committed transaction can be lost.
8786 if (fflush (fp) != 0)
8787 error (1, errno, "error flushing file `%s' to kernel buffers",
8790 if (fsync (rcs_lockfd) < 0)
8791 error (1, errno, "error fsyncing file `%s'", rcs_lockfile);
8794 if (fclose (fp) == EOF)
8795 error (1, errno, "error closing lock file %s", rcs_lockfile);
8798 rename_file (rcs_lockfile, rcsfile);
8801 /* Use a temporary to make sure there's no interval
8802 (after rcs_lockfile has been freed but before it's set to NULL)
8803 during which the signal handler's use of rcs_lockfile would
8804 reference freed memory. */
8805 char *tmp = rcs_lockfile;
8806 rcs_lockfile = NULL;
8812 rcs_lockfilename (rcsfile)
8813 const char *rcsfile;
8815 char *lockfile, *lockp;
8816 const char *rcsbase, *rcsp, *rcsend;
8819 /* Create the lockfile name. */
8820 rcslen = strlen (rcsfile);
8821 lockfile = (char *) xmalloc (rcslen + 10);
8822 rcsbase = last_component (rcsfile);
8823 rcsend = rcsfile + rcslen - sizeof(RCSEXT);
8824 for (lockp = lockfile, rcsp = rcsfile; rcsp < rcsbase; ++rcsp)
8827 while (rcsp <= rcsend)
8835 /* Rewrite an RCS file. The basic idea here is that the caller should
8836 first call RCS_reparsercsfile, then munge the data structures as
8837 desired (via RCS_delete_revs, RCS_settag, &c), then call RCS_rewrite. */
8840 RCS_rewrite (rcs, newdtext, insertpt)
8842 Deltatext *newdtext;
8846 struct rcsbuffer rcsbufin;
8853 /* Make sure we're operating on an actual file and not a symlink. */
8854 resolve_symlink (&(rcs->path));
8856 fout = rcs_internal_lockfile (rcs->path);
8858 RCS_putadmin (rcs, fout);
8859 RCS_putdtree (rcs, rcs->head, fout);
8860 RCS_putdesc (rcs, fout);
8862 /* Open the original RCS file and seek to the first delta text. */
8863 rcsbuf_cache_open (rcs, rcs->delta_pos, &fin, &rcsbufin);
8865 /* Update delta_pos to the current position in the output file.
8866 Do NOT move these statements: they must be done after fin has
8867 been positioned at the old delta_pos, but before any delta
8868 texts have been written to fout.
8870 rcs->delta_pos = ftell (fout);
8871 if (rcs->delta_pos == -1)
8872 error (1, errno, "cannot ftell in RCS file %s", rcs->path);
8874 RCS_copydeltas (rcs, fin, &rcsbufin, fout, newdtext, insertpt);
8876 /* We don't want to call rcsbuf_cache here, since we're about to
8878 rcsbuf_close (&rcsbufin);
8880 /* The only case in which using errno here would be meaningful
8881 is if we happen to have left errno unmolested since the call
8882 which produced the error (e.g. fread). That is pretty
8883 fragile even if it happens to sometimes be true. The real
8884 solution is to make sure that all the code which reads
8885 from fin checks for errors itself (some does, some doesn't). */
8886 error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
8887 if (fclose (fin) < 0)
8888 error (0, errno, "warning: closing RCS file `%s'", rcs->path);
8890 rcs_internal_unlockfile (fout, rcs->path);
8893 /* Abandon changes to an RCS file. */
8899 free_rcsnode_contents (rcs);
8900 rcs->symbols_data = NULL;
8903 rcs->locks_data = NULL;
8904 rcs->comment = NULL;
8906 rcs->flags |= PARTIAL;
8910 * For a given file with full pathname PATH and revision number REV,
8911 * produce a file label suitable for passing to diff. The default
8912 * file label as used by RCS 5.7 looks like this:
8914 * FILENAME <tab> YYYY/MM/DD <sp> HH:MM:SS <tab> REVNUM
8916 * The date and time used are the revision's last checkin date and time.
8917 * If REV is NULL, use the working copy's mtime instead.
8919 * /dev/null is not statted but assumed to have been created on the Epoch.
8920 * At least using the POSIX.2 definition of patch, this should cause creation
8921 * of files on platforms such as Windoze where the null IO device isn't named
8922 * /dev/null to be parsed by patch properly.
8925 make_file_label (path, rev, rcs)
8930 char datebuf[MAXDATELEN + 1];
8933 label = (char *) xmalloc (strlen (path)
8934 + (rev == NULL ? 0 : strlen (rev) + 1)
8940 char date[MAXDATELEN + 1];
8941 /* revs cannot be attached to /dev/null ... duh. */
8942 assert (strcmp(DEVNULL, path));
8943 RCS_getrevtime (rcs, rev, datebuf, 0);
8944 (void) date_to_internet (date, datebuf);
8945 (void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
8952 if (strcmp(DEVNULL, path))
8954 const char *file = last_component (path);
8955 if (CVS_STAT (file, &sb) < 0)
8956 /* Assume that if the stat fails,then the later read for the
8959 error (1, errno, "could not get info for `%s'", path);
8960 wm = gmtime (&sb.st_mtime);
8968 (void) tm_to_internet (datebuf, wm);
8969 (void) sprintf (label, "-L%s\t%s", path, datebuf);
8975 RCS_setlocalid (arg)
8978 char *copy, *next, *key;
8980 copy = xstrdup(arg);
8982 key = strtok(next, "=");
8984 keywords[KEYWORD_LOCALID].string = xstrdup(key);
8985 keywords[KEYWORD_LOCALID].len = strlen(key);
8986 keywords[KEYWORD_LOCALID].expandit = 1;
8989 while (key = strtok(NULL, ",")) {
8990 if (!strcmp(key, keywords[KEYWORD_ID].string))
8991 keyword_local = KEYWORD_ID;
8992 else if (!strcmp(key, keywords[KEYWORD_HEADER].string))
8993 keyword_local = KEYWORD_HEADER;
8994 else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string))
8995 keyword_local = KEYWORD_CVSHEADER;
8997 error(1, 0, "Unknown LocalId mode: %s", key);
9009 struct rcs_keyword *keyword;
9011 copy = xstrdup(arg);
9026 for (keyword = keywords; keyword->string != NULL; keyword++)
9028 keyword->expandit = 0;
9031 key = strtok(next, ",");
9033 for (keyword = keywords; keyword->string != NULL; keyword++) {
9034 if (strcmp (keyword->string, key) == 0)
9035 keyword->expandit = include;
9037 key = strtok(NULL, ",");
9043 #define ATTIC "/" CVSATTIC
9045 getfullCVSname(CVSname, pathstore)
9046 char *CVSname, **pathstore;
9048 if (current_parsed_root->directory) {
9051 int alen = sizeof(ATTIC) - 1;
9053 *pathstore = xstrdup(CVSname);
9054 if ((c = strrchr(*pathstore, '/')) != NULL) {
9055 if (c - *pathstore >= alen) {
9056 if (!strncmp(c - alen, ATTIC, alen)) {
9057 while (*c != '\0') {
9066 rootlen = strlen(current_parsed_root->directory);
9067 if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) &&
9068 (*pathstore)[rootlen] == '/')
9069 CVSname = (*pathstore + rootlen + 1);
9071 CVSname = (*pathstore);