Bring cvs-1.12.9 into the CVS repository
[dragonfly.git] / contrib / cvs-1.12.9 / src / rcs.c
1 /*
2  * Copyright (c) 1992, Brian Berliner and Jeff Polk
3  * 
4  * You may distribute under the terms of the GNU General Public License as
5  * specified in the README file that comes with the CVS source distribution.
6  * 
7  * The routines contained in this file do all the rcs file parsing and
8  * manipulation
9  */
10
11 #include "cvs.h"
12 #include "edit.h"
13 #include "hardlink.h"
14
15 /* These need to be source after cvs.h or HAVE_MMAP won't be set... */
16 #ifdef HAVE_MMAP
17 # include <sys/mman.h>
18 # ifndef HAVE_GETPAGESIZE
19 #  include "getpagesize.h"
20 # endif
21 # ifndef MAP_FAILED
22 #  define MAP_FAILED NULL
23 # endif
24 #endif
25
26 int preserve_perms = 0;
27
28 /* The RCS -k options, and a set of enums that must match the array.
29    These come first so that we can use enum kflag in function
30    prototypes.  */
31 static const char *const kflags[] =
32   {"kv", "kvl", "k", "v", "o", "b", (char *) NULL};
33 enum kflag { KFLAG_KV = 0, KFLAG_KVL, KFLAG_K, KFLAG_V, KFLAG_O, KFLAG_B };
34
35 /* A structure we use to buffer the contents of an RCS file.  The
36    various fields are only referenced directly by the rcsbuf_*
37    functions.  We declare the struct here so that we can allocate it
38    on the stack, rather than in memory.  */
39
40 struct rcsbuffer
41 {
42     /* Points to the current position in the buffer.  */
43     char *ptr;
44     /* Points just after the last valid character in the buffer.  */
45     char *ptrend;
46     /* The file.  */
47     FILE *fp;
48     /* The name of the file, used for error messages.  */
49     const char *filename;
50     /* The starting file position of the data in the buffer.  */
51     unsigned long pos;
52     /* The length of the value.  */
53     size_t vlen;
54     /* Whether the value contains an '@' string.  If so, we can not
55        compress whitespace characters.  */
56     int at_string;
57     /* The number of embedded '@' characters in an '@' string.  If
58        this is non-zero, we must search the string for pairs of '@'
59        and convert them to a single '@'.  */
60     int embedded_at;
61 };
62
63 static RCSNode *RCS_parsercsfile_i (FILE * fp, const char *rcsfile);
64 static char *RCS_getdatebranch (RCSNode * rcs, const char *date,
65                                 const char *branch);
66 static void rcsbuf_open (struct rcsbuffer *, FILE *fp,
67                          const char *filename, unsigned long pos);
68 static void rcsbuf_close (struct rcsbuffer *);
69 static int rcsbuf_getkey (struct rcsbuffer *, char **keyp,
70                                  char **valp);
71 static int rcsbuf_getrevnum (struct rcsbuffer *, char **revp);
72 static char *rcsbuf_fill (struct rcsbuffer *, char *ptr, char **keyp,
73                           char **valp);
74 static int rcsbuf_valcmp (struct rcsbuffer *);
75 static char *rcsbuf_valcopy (struct rcsbuffer *, char *val, int polish,
76                              size_t *lenp);
77 static void rcsbuf_valpolish (struct rcsbuffer *, char *val, int polish,
78                               size_t *lenp);
79 static void rcsbuf_valpolish_internal (struct rcsbuffer *, char *to,
80                                        const char *from, size_t *lenp);
81 static off_t rcsbuf_ftello (struct rcsbuffer *);
82 static void rcsbuf_get_buffered (struct rcsbuffer *, char **datap,
83                                         size_t *lenp);
84 static void rcsbuf_cache (RCSNode *, struct rcsbuffer *);
85 static void rcsbuf_cache_close (void);
86 static void rcsbuf_cache_open (RCSNode *, off_t, FILE **,
87                                       struct rcsbuffer *);
88 static int checkmagic_proc (Node *p, void *closure);
89 static void do_branches (List * list, char *val);
90 static void do_symbols (List * list, char *val);
91 static void do_locks (List * list, char *val);
92 static void free_rcsnode_contents (RCSNode *);
93 static void free_rcsvers_contents (RCSVers *);
94 static void rcsvers_delproc (Node * p);
95 static char *translate_symtag (RCSNode *, const char *);
96 static char *RCS_addbranch (RCSNode *, const char *);
97 static char *truncate_revnum_in_place (char *);
98 static char *truncate_revnum (const char *);
99 static char *printable_date (const char *);
100 static char *escape_keyword_value (const char *, int *);
101 static void expand_keywords (RCSNode *, RCSVers *, const char *,
102                              const char *, size_t, enum kflag, char *,
103                              size_t, char **, size_t *);
104 static void cmp_file_buffer (void *, const char *, size_t);
105
106 /* Routines for reading, parsing and writing RCS files. */
107 static RCSVers *getdelta (struct rcsbuffer *, char *, char **,
108                                  char **);
109 static Deltatext *RCS_getdeltatext (RCSNode *, FILE *,
110                                            struct rcsbuffer *);
111 static void freedeltatext (Deltatext *);
112
113 static void RCS_putadmin (RCSNode *, FILE *);
114 static void RCS_putdtree (RCSNode *, char *, FILE *);
115 static void RCS_putdesc (RCSNode *, FILE *);
116 static void putdelta (RCSVers *, FILE *);
117 static int putrcsfield_proc (Node *, void *);
118 static int putsymbol_proc (Node *, void *);
119 static void RCS_copydeltas (RCSNode *, FILE *, struct rcsbuffer *,
120                                    FILE *, Deltatext *, char *);
121 static int count_delta_actions (Node *, void *);
122 static void putdeltatext (FILE *, Deltatext *);
123
124 static FILE *rcs_internal_lockfile (char *);
125 static void rcs_internal_unlockfile (FILE *, char *);
126 static char *rcs_lockfilename (const char *);
127
128 /* The RCS file reading functions are called a lot, and they do some
129    string comparisons.  This macro speeds things up a bit by skipping
130    the function call when the first characters are different.  It
131    evaluates its arguments multiple times.  */
132 #define STREQ(a, b) (*(char *)(a) == *(char *)(b) && strcmp ((a), (b)) == 0)
133
134 static char * getfullCVSname (char *, char **);
135
136 /*
137  * We don't want to use isspace() from the C library because:
138  *
139  * 1. The definition of "whitespace" in RCS files includes ASCII
140  *    backspace, but the C locale doesn't.
141  * 2. isspace is an very expensive function call in some implementations
142  *    due to the addition of wide character support.
143  */
144 static const char spacetab[] = {
145         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x00 - 0x0f */
146         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
147         1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
148         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
149         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
150         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
151         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x8f */
152         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
153         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
154         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
155         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
156         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
157         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
158         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
159         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
160         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 - 0xff */
161 };
162
163 #define whitespace(c)   (spacetab[(unsigned char)c] != 0)
164
165 static char *rcs_lockfile = NULL;
166 static int rcs_lockfd = -1;
167
168
169
170 /*
171  * char *
172  * locate_rcs ( const char* file, const char *repository , int *inattic )
173  *
174  * Find an RCS file in the repository, case insensitively when the cased name
175  * doesn't exist, we are running as the server, and a client has asked us to
176  * ignore case.
177  *
178  * Most parts of CVS will want to rely instead on RCS_parse which calls this
179  * function and is called by recurse.c which then puts the result in useful
180  * places like the rcs field of struct file_info.
181  *
182  * INPUTS
183  *
184  *  repository          the repository (including the directory)
185  *  file                the filename within that directory (without RCSEXT).
186  *  inattic             NULL or a pointer to the output boolean
187  *
188  * OUTPUTS
189  *
190  *  inattic             If this input was non-null, the destination will be
191  *                      set to true if the file was found in the attic or
192  *                      false if not.  If no RCS file is found, this value
193  *                      is undefined.
194  *
195  * RETURNS
196  *
197  *  a newly-malloc'd array containing the absolute pathname of the RCS
198  *  file that was found or NULL when none was found.
199  *
200  * ERRORS
201  *
202  *  errno can be set by the return value of the final call to
203  *  locate_file_in_dir().  This should resolve to the system's existence error
204  *  value (sometime ENOENT) if the Attic directory did not exist and ENOENT if
205  *  the Attic was found but no matching files were found in the Attic or its
206  *  parent.
207  */
208 static char *
209 locate_rcs (const char *repository, const char *file, int *inattic)
210 {
211     char *retval;
212
213     /* First, try to find the file as cased. */
214     retval = xmalloc (strlen (repository)
215                       + sizeof (CVSATTIC)
216                       + strlen (file)
217                       + sizeof (RCSEXT)
218                       + 3);
219     sprintf (retval, "%s/%s%s", repository, file, RCSEXT);
220     if (isreadable (retval))
221     {
222         if (inattic)
223             *inattic = 0;
224         return retval;
225     }
226     sprintf (retval, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
227     if (isreadable (retval))
228     {
229         if (inattic)
230             *inattic = 1;
231         return retval;
232     }
233     free (retval);
234
235     return NULL;
236 }
237
238
239
240 /* A few generic thoughts on error handling, in particular the
241    printing of unexpected characters that we find in the RCS file
242    (that is, why we use '\x%x' rather than %c or some such).
243
244    * Avoiding %c means we don't have to worry about what is printable
245    and other such stuff.  In error handling, often better to keep it
246    simple.
247
248    * Hex rather than decimal or octal because character set standards
249    tend to use hex.
250
251    * Saying "character 0x%x" might make it sound like we are printing
252    a file offset.  So we use '\x%x'.
253
254    * Would be nice to print the offset within the file, but I can
255    imagine various portability hassles (in particular, whether
256    unsigned long is always big enough to hold file offsets).  */
257
258 /* Parse an rcsfile given a user file name and a repository.  If there is
259    an error, we print an error message and return NULL.  If the file
260    does not exist, we return NULL without printing anything (I'm not
261    sure this allows the caller to do anything reasonable, but it is
262    the current behavior).  */
263 RCSNode *
264 RCS_parse (const char *file, const char *repos)
265 {
266     RCSNode *rcs;
267     FILE *fp;
268     RCSNode *retval = NULL;
269     char *rcsfile;
270     int inattic;
271
272     /* We're creating a new RCSNode, so there is no hope of finding it
273        in the cache.  */
274     rcsbuf_cache_close ();
275
276     if ((rcsfile = locate_rcs (repos, file, &inattic)) == NULL)
277     {
278         /* Handle the error cases */
279     }
280     else if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL) 
281     {
282         rcs = RCS_parsercsfile_i(fp, rcsfile);
283         if (rcs != NULL)
284         {       
285             rcs->flags |= VALID;
286             if ( inattic )
287                 rcs->flags |= INATTIC;
288         }
289
290         free ( rcsfile );
291         retval = rcs;
292     }
293     else if (! existence_error (errno))
294     {
295         free ( rcsfile );
296         error (0, errno, "cannot open %s", rcsfile);
297     }
298
299     return retval;
300 }
301
302 /*
303  * Parse a specific rcsfile.
304  */
305 RCSNode *
306 RCS_parsercsfile (const char *rcsfile)
307 {
308     FILE *fp;
309     RCSNode *rcs;
310
311     /* We're creating a new RCSNode, so there is no hope of finding it
312        in the cache.  */
313     rcsbuf_cache_close ();
314
315     /* open the rcsfile */
316     if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) == NULL)
317     {
318         error (0, errno, "Couldn't open rcs file `%s'", rcsfile);
319         return (NULL);
320     }
321
322     rcs = RCS_parsercsfile_i (fp, rcsfile);
323
324     return (rcs);
325 }
326
327
328
329 /*
330  */ 
331 static RCSNode *
332 RCS_parsercsfile_i (FILE *fp, const char *rcsfile)
333 {
334     RCSNode *rdata;
335     struct rcsbuffer rcsbuf;
336     char *key, *value;
337
338     /* make a node */
339     rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
340     memset ((char *)rdata, 0, sizeof (RCSNode));
341     rdata->refcount = 1;
342     rdata->path = xstrdup (rcsfile);
343
344     /* Process HEAD, BRANCH, and EXPAND keywords from the RCS header.
345
346        Most cvs operations on the main branch don't need any more
347        information.  Those that do call RCS_reparsercsfile to parse
348        the rest of the header and the deltas.  */
349
350     rcsbuf_open (&rcsbuf, fp, rcsfile, 0);
351
352     if (! rcsbuf_getkey (&rcsbuf, &key, &value))
353         goto l_error;
354     if (STREQ (key, RCSDESC))
355         goto l_error;
356
357     if (STREQ (RCSHEAD, key) && value != NULL)
358         rdata->head = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
359
360     if (! rcsbuf_getkey (&rcsbuf, &key, &value))
361         goto l_error;
362     if (STREQ (key, RCSDESC))
363         goto l_error;
364
365     if (STREQ (RCSBRANCH, key) && value != NULL)
366     {
367         char *cp;
368
369         rdata->branch = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
370         if ((numdots (rdata->branch) & 1) != 0)
371         {
372             /* turn it into a branch if it's a revision */
373             cp = strrchr (rdata->branch, '.');
374             *cp = '\0';
375         }
376     }
377
378     /* Look ahead for expand, stopping when we see desc or a revision
379        number.  */
380     while (1)
381     {
382         char *cp;
383
384         if (STREQ (RCSEXPAND, key))
385         {
386             rdata->expand = rcsbuf_valcopy (&rcsbuf, value, 0,
387                                             (size_t *)NULL);
388             break;
389         }
390
391         for (cp = key;
392              (isdigit ((unsigned char)*cp) || *cp == '.') && *cp != '\0';
393              cp++)
394             /* do nothing */ ;
395         if (*cp == '\0')
396             break;
397
398         if (STREQ (RCSDESC, key))
399             break;
400
401         if (! rcsbuf_getkey (&rcsbuf, &key, &value))
402             break;
403     }
404
405     rdata->flags |= PARTIAL;
406
407     rcsbuf_cache (rdata, &rcsbuf);
408
409     return rdata;
410
411 l_error:
412     error (0, 0, "`%s' does not appear to be a valid rcs file",
413            rcsfile);
414     rcsbuf_close (&rcsbuf);
415     freercsnode (&rdata);
416     fclose (fp);
417     return NULL;
418 }
419
420
421
422 /* Do the real work of parsing an RCS file.
423
424    On error, die with a fatal error; if it returns at all it was successful.
425
426    If PFP is NULL, close the file when done.  Otherwise, leave it open
427    and store the FILE * in *PFP.  */
428 void
429 RCS_reparsercsfile (RCSNode *rdata, FILE **pfp, struct rcsbuffer *rcsbufp)
430 {
431     FILE *fp;
432     char *rcsfile;
433     struct rcsbuffer rcsbuf;
434     Node *q, *kv;
435     RCSVers *vnode;
436     int gotkey;
437     char *cp;
438     char *key, *value;
439
440     assert (rdata != NULL);
441     rcsfile = rdata->path;
442
443     rcsbuf_cache_open (rdata, 0, &fp, &rcsbuf);
444
445     /* make a node */
446     /* This probably shouldn't be done until later: if a file has an
447        empty revision tree (which is permissible), rdata->versions
448        should be NULL. -twp */
449     rdata->versions = getlist ();
450
451     /*
452      * process all the special header information, break out when we get to
453      * the first revision delta
454      */
455     gotkey = 0;
456     for (;;)
457     {
458         /* get the next key/value pair */
459         if (!gotkey)
460         {
461             if (! rcsbuf_getkey (&rcsbuf, &key, &value))
462             {
463                 error (1, 0, "`%s' does not appear to be a valid rcs file",
464                        rcsfile);
465             }
466         }
467
468         gotkey = 0;
469
470         /* Skip head, branch and expand tags; we already have them. */
471         if (STREQ (key, RCSHEAD)
472             || STREQ (key, RCSBRANCH)
473             || STREQ (key, RCSEXPAND))
474         {
475             continue;
476         }
477
478         if (STREQ (key, "access"))
479         {
480             if (value != NULL)
481             {
482                 /* We pass the POLISH parameter as 1 because
483                    RCS_addaccess expects nothing but spaces.  FIXME:
484                    It would be easy and more efficient to change
485                    RCS_addaccess.  */
486                 rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1,
487                                                 (size_t *) NULL);
488             }
489             continue;
490         }
491
492         /* We always save lock information, so that we can handle
493            -kkvl correctly when checking out a file. */
494         if (STREQ (key, "locks"))
495         {
496             if (value != NULL)
497                 rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0,
498                                                     (size_t *) NULL);
499             if (! rcsbuf_getkey (&rcsbuf, &key, &value))
500             {
501                 error (1, 0, "premature end of file reading %s", rcsfile);
502             }
503             if (STREQ (key, "strict") && value == NULL)
504             {
505                 rdata->strict_locks = 1;
506             }
507             else
508                 gotkey = 1;
509             continue;
510         }
511
512         if (STREQ (RCSSYMBOLS, key))
513         {
514             if (value != NULL)
515                 rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0,
516                                                       (size_t *) NULL);
517             continue;
518         }
519
520         /*
521          * check key for '.''s and digits (probably a rev) if it is a
522          * revision or `desc', we are done with the headers and are down to the
523          * revision deltas, so we break out of the loop
524          */
525         for (cp = key;
526              (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
527              cp++)
528              /* do nothing */ ;
529         /* Note that when comparing with RCSDATE, we are not massaging
530            VALUE from the string found in the RCS file.  This is OK
531            since we know exactly what to expect.  */
532         if (*cp == '\0' && strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) == 0)
533             break;
534
535         if (STREQ (key, RCSDESC))
536             break;
537
538         if (STREQ (key, "comment"))
539         {
540             rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0,
541                                              (size_t *) NULL);
542             continue;
543         }
544         if (rdata->other == NULL)
545             rdata->other = getlist ();
546         kv = getnode ();
547         kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
548         kv->key = xstrdup (key);
549         kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
550                                    (size_t *) NULL);
551         if (addnode (rdata->other, kv) != 0)
552         {
553             error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
554                    key, rcsfile);
555             freenode (kv);
556         }
557
558         /* if we haven't grabbed it yet, we didn't want it */
559     }
560
561     /* We got out of the loop, so we have the first part of the first
562        revision delta in KEY (the revision) and VALUE (the date key
563        and its value).  This is what getdelta expects to receive.  */
564
565     while ((vnode = getdelta (&rcsbuf, rcsfile, &key, &value)) != NULL)
566     {
567         /* get the node */
568         q = getnode ();
569         q->type = RCSVERS;
570         q->delproc = rcsvers_delproc;
571         q->data = vnode;
572         q->key = vnode->version;
573
574         /* add the nodes to the list */
575         if (addnode (rdata->versions, q) != 0)
576         {
577 #if 0
578                 purify_printf("WARNING: Adding duplicate version: %s (%s)\n",
579                          q->key, rcsfile);
580                 freenode (q);
581 #endif
582         }
583     }
584
585     /* Here KEY and VALUE are whatever caused getdelta to return NULL.  */
586
587     if (STREQ (key, RCSDESC))
588     {
589         if (rdata->desc != NULL)
590         {
591             error (0, 0,
592                    "warning: duplicate key `%s' in RCS file `%s'",
593                    key, rcsfile);
594             free (rdata->desc);
595         }
596         rdata->desc = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
597     }
598
599     rdata->delta_pos = rcsbuf_ftello (&rcsbuf);
600
601     if (pfp == NULL)
602         rcsbuf_cache (rdata, &rcsbuf);
603     else
604     {
605         *pfp = fp;
606         *rcsbufp = rcsbuf;
607     }
608     rdata->flags &= ~PARTIAL;
609 }
610
611 /* Move RCS into or out of the Attic, depending on TOATTIC.  If the
612    file is already in the desired place, return without doing
613    anything.  At some point may want to think about how this relates
614    to RCS_rewrite but that is a bit hairy (if one wants renames to be
615    atomic, or that kind of thing).  If there is an error, print a message
616    and return 1.  On success, return 0.  */
617 int
618 RCS_setattic (RCSNode *rcs, int toattic)
619 {
620     char *newpath;
621     const char *p;
622     char *q;
623
624     /* Some systems aren't going to let us rename an open file.  */
625     rcsbuf_cache_close ();
626
627     /* Could make the pathname computations in this file, and probably
628        in other parts of rcs.c too, easier if the REPOS and FILE
629        arguments to RCS_parse got stashed in the RCSNode.  */
630
631     if (toattic)
632     {
633         mode_t omask;
634
635         if (rcs->flags & INATTIC)
636             return 0;
637
638         /* Example: rcs->path is "/foo/bar/baz,v".  */
639         newpath = xmalloc (strlen (rcs->path) + sizeof CVSATTIC + 5);
640         p = last_component (rcs->path);
641         strncpy (newpath, rcs->path, p - rcs->path);
642         strcpy (newpath + (p - rcs->path), CVSATTIC);
643
644         /* Create the Attic directory if it doesn't exist.  */
645         omask = umask (cvsumask);
646         if (CVS_MKDIR (newpath, 0777) < 0 && errno != EEXIST)
647             error (0, errno, "cannot make directory %s", newpath);
648         (void) umask (omask);
649
650         strcat (newpath, "/");
651         strcat (newpath, p);
652
653         if (CVS_RENAME (rcs->path, newpath) < 0)
654         {
655             int save_errno = errno;
656
657             /* The checks for isreadable look awfully fishy, but
658                I'm going to leave them here for now until I
659                can think harder about whether they take care of
660                some cases which should be handled somehow.  */
661
662             if (isreadable (rcs->path) || !isreadable (newpath))
663             {
664                 error (0, save_errno, "cannot rename %s to %s",
665                        rcs->path, newpath);
666                 free (newpath);
667                 return 1;
668             }
669         }
670     }
671     else
672     {
673         if (!(rcs->flags & INATTIC))
674             return 0;
675
676         newpath = xmalloc (strlen (rcs->path));
677
678         /* Example: rcs->path is "/foo/bar/Attic/baz,v".  */
679         p = last_component (rcs->path);
680         strncpy (newpath, rcs->path, p - rcs->path - 1);
681         newpath[p - rcs->path - 1] = '\0';
682         q = newpath + (p - rcs->path - 1) - (sizeof CVSATTIC - 1);
683         assert (strncmp (q, CVSATTIC, sizeof CVSATTIC - 1) == 0);
684         strcpy (q, p);
685
686         if (CVS_RENAME (rcs->path, newpath) < 0)
687         {
688             error (0, errno, "failed to move `%s' out of the attic",
689                    rcs->path);
690             free (newpath);
691             return 1;
692         }
693     }
694
695     free (rcs->path);
696     rcs->path = newpath;
697
698     return 0;
699 }
700
701 /*
702  * Fully parse the RCS file.  Store all keyword/value pairs, fetch the
703  * log messages for each revision, and fetch add and delete counts for
704  * each revision (we could fetch the entire text for each revision,
705  * but the only caller, log_fileproc, doesn't need that information,
706  * so we don't waste the memory required to store it).  The add and
707  * delete counts are stored on the OTHER field of the RCSVERSNODE
708  * structure, under the names ";add" and ";delete", so that we don't
709  * waste the memory space of extra fields in RCSVERSNODE for code
710  * which doesn't need this information.
711  */
712
713 void
714 RCS_fully_parse (RCSNode *rcs)
715 {
716     FILE *fp;
717     struct rcsbuffer rcsbuf;
718
719     RCS_reparsercsfile (rcs, &fp, &rcsbuf);
720
721     while (1)
722     {
723         char *key, *value;
724         Node *vers;
725         RCSVers *vnode;
726
727         /* Rather than try to keep track of how much information we
728            have read, just read to the end of the file.  */
729         if (!rcsbuf_getrevnum (&rcsbuf, &key))
730             break;
731
732         vers = findnode (rcs->versions, key);
733         if (vers == NULL)
734             error (1, 0,
735                    "mismatch in rcs file %s between deltas and deltatexts (%s)",
736                    rcs->path, key);
737
738         vnode = vers->data;
739
740         while (rcsbuf_getkey (&rcsbuf, &key, &value))
741         {
742             if (!STREQ (key, "text"))
743             {
744                 Node *kv;
745
746                 if (vnode->other == NULL)
747                     vnode->other = getlist ();
748                 kv = getnode ();
749                 kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
750                 kv->key = xstrdup (key);
751                 kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
752                                            (size_t *)NULL);
753                 if (addnode (vnode->other, kv) != 0)
754                 {
755                     error (0, 0,
756                            "\
757 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
758                            key, vnode->version, rcs->path);
759                     freenode (kv);
760                 }
761
762                 continue;
763             }
764
765             if (!STREQ (vnode->version, rcs->head))
766             {
767                 unsigned long add, del;
768                 char buf[50];
769                 Node *kv;
770
771                 /* This is a change text.  Store the add and delete
772                    counts.  */
773                 add = 0;
774                 del = 0;
775                 if (value != NULL)
776                 {
777                     size_t vallen;
778                     const char *cp;
779
780                     rcsbuf_valpolish (&rcsbuf, value, 0, &vallen);
781                     cp = value;
782                     while (cp < value + vallen)
783                     {
784                         char op;
785                         unsigned long count;
786
787                         op = *cp++;
788                         if (op != 'a' && op  != 'd')
789                             error (1, 0, "\
790 unrecognized operation '\\x%x' in %s",
791                                    op, rcs->path);
792                         (void) strtoul (cp, (char **) &cp, 10);
793                         if (*cp++ != ' ')
794                             error (1, 0, "space expected in %s revision %s",
795                                    rcs->path, vnode->version);
796                         count = strtoul (cp, (char **) &cp, 10);
797                         if (*cp++ != '\012')
798                             error (1, 0, "linefeed expected in %s revision %s",
799                                    rcs->path, vnode->version);
800
801                         if (op == 'd')
802                             del += count;
803                         else
804                         {
805                             add += count;
806                             while (count != 0)
807                             {
808                                 if (*cp == '\012')
809                                     --count;
810                                 else if (cp == value + vallen)
811                                 {
812                                     if (count != 1)
813                                         error (1, 0, "\
814 premature end of value in %s revision %s",
815                                                rcs->path, vnode->version);
816                                     else
817                                         break;
818                                 }
819                                 ++cp;
820                             }
821                         }
822                     }
823                 }
824
825                 sprintf (buf, "%lu", add);
826                 kv = getnode ();
827                 kv->type = RCSFIELD;
828                 kv->key = xstrdup (";add");
829                 kv->data = xstrdup (buf);
830                 if (addnode (vnode->other, kv) != 0)
831                 {
832                     error (0, 0,
833                            "\
834 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
835                            key, vnode->version, rcs->path);
836                     freenode (kv);
837                 }
838
839                 sprintf (buf, "%lu", del);
840                 kv = getnode ();
841                 kv->type = RCSFIELD;
842                 kv->key = xstrdup (";delete");
843                 kv->data = xstrdup (buf);
844                 if (addnode (vnode->other, kv) != 0)
845                 {
846                     error (0, 0,
847                            "\
848 warning: duplicate key `%s' in version `%s' of RCS file `%s'",
849                            key, vnode->version, rcs->path);
850                     freenode (kv);
851                 }
852             }
853
854             /* We have found the "text" key which ends the data for
855                this revision.  Break out of the loop and go on to the
856                next revision.  */
857             break;
858         }
859     }
860
861     rcsbuf_cache (rcs, &rcsbuf);
862 }
863
864
865
866 /*
867  * freercsnode - free up the info for an RCSNode
868  */
869 void
870 freercsnode (RCSNode **rnodep)
871 {
872     if (rnodep == NULL || *rnodep == NULL)
873         return;
874
875     ((*rnodep)->refcount)--;
876     if ((*rnodep)->refcount != 0)
877     {
878         *rnodep = (RCSNode *) NULL;
879         return;
880     }
881     free ((*rnodep)->path);
882     if ((*rnodep)->head != (char *) NULL)
883         free ((*rnodep)->head);
884     if ((*rnodep)->branch != (char *) NULL)
885         free ((*rnodep)->branch);
886     free_rcsnode_contents (*rnodep);
887     free ((char *) *rnodep);
888     *rnodep = (RCSNode *) NULL;
889 }
890
891 /*
892  * free_rcsnode_contents - free up the contents of an RCSNode without
893  * freeing the node itself, or the file name, or the head, or the
894  * path.  This returns the RCSNode to the state it is in immediately
895  * after a call to RCS_parse.
896  */
897 static void
898 free_rcsnode_contents (RCSNode *rnode)
899 {
900     dellist (&rnode->versions);
901     if (rnode->symbols != (List *) NULL)
902         dellist (&rnode->symbols);
903     if (rnode->symbols_data != (char *) NULL)
904         free (rnode->symbols_data);
905     if (rnode->expand != NULL)
906         free (rnode->expand);
907     if (rnode->other != (List *) NULL)
908         dellist (&rnode->other);
909     if (rnode->access != NULL)
910         free (rnode->access);
911     if (rnode->locks_data != NULL)
912         free (rnode->locks_data);
913     if (rnode->locks != (List *) NULL)
914         dellist (&rnode->locks);
915     if (rnode->comment != NULL)
916         free (rnode->comment);
917     if (rnode->desc != NULL)
918         free (rnode->desc);
919 }
920
921 /* free_rcsvers_contents -- free up the contents of an RCSVers node,
922    but also free the pointer to the node itself. */
923 /* Note: The `hardlinks' list is *not* freed, since it is merely a
924    pointer into the `hardlist' structure (defined in hardlink.c), and
925    that structure is freed elsewhere in the program. */
926
927 static void
928 free_rcsvers_contents (RCSVers *rnode)
929 {
930     if (rnode->branches != (List *) NULL)
931         dellist (&rnode->branches);
932     if (rnode->date != (char *) NULL)
933         free (rnode->date);
934     if (rnode->next != (char *) NULL)
935         free (rnode->next);
936     if (rnode->author != (char *) NULL)
937         free (rnode->author);
938     if (rnode->state != (char *) NULL)
939         free (rnode->state);
940     if (rnode->other != (List *) NULL)
941         dellist (&rnode->other);
942     if (rnode->other_delta != NULL)
943         dellist (&rnode->other_delta);
944     if (rnode->text != NULL)
945         freedeltatext (rnode->text);
946     free ((char *) rnode);
947 }
948
949 /*
950  * rcsvers_delproc - free up an RCSVers type node
951  */
952 static void
953 rcsvers_delproc (Node *p)
954 {
955     free_rcsvers_contents (p->data);
956 }
957 \f
958 /* These functions retrieve keys and values from an RCS file using a
959    buffer.  We use this somewhat complex approach because it turns out
960    that for many common operations, CVS spends most of its time
961    reading keys, so it's worth doing some fairly hairy optimization.  */
962
963 /* The number of bytes we try to read each time we need more data.  */
964
965 #define RCSBUF_BUFSIZE (8192)
966
967 /* The buffer we use to store data.  This grows as needed.  */
968
969 static char *rcsbuf_buffer = NULL;
970 static size_t rcsbuf_buffer_size = 0;
971
972 /* Whether rcsbuf_buffer is in use.  This is used as a sanity check.  */
973
974 static int rcsbuf_inuse;
975
976 /* Set up to start gathering keys and values from an RCS file.  This
977    initializes RCSBUF.  */
978
979 static void
980 rcsbuf_open (struct rcsbuffer *rcsbuf, FILE *fp, const char *filename, long unsigned int pos)
981 {
982     if (rcsbuf_inuse)
983         error (1, 0, "rcsbuf_open: internal error");
984     rcsbuf_inuse = 1;
985
986 #ifdef HAVE_MMAP
987     {
988         /* When we have mmap, it is much more efficient to let the system do the
989          * buffering and caching for us
990          */
991         struct stat fs;
992         size_t mmap_off = 0;
993
994         if ( fstat (fileno(fp), &fs) < 0 )
995             error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
996
997         if (pos)
998         {
999             size_t ps = getpagesize ();
1000             mmap_off = ( pos / ps ) * ps;
1001         }
1002
1003         /* Map private here since this particular buffer is read only */
1004         rcsbuf_buffer = mmap ( NULL, fs.st_size - mmap_off,
1005                                 PROT_READ | PROT_WRITE,
1006                                 MAP_PRIVATE, fileno(fp), mmap_off );
1007         if ( rcsbuf_buffer == NULL || rcsbuf_buffer == MAP_FAILED )
1008             error ( 1, errno, "Could not map memory to RCS archive %s", filename );
1009
1010         rcsbuf_buffer_size = fs.st_size - mmap_off;
1011         rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
1012         rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
1013         rcsbuf->pos = mmap_off;
1014     }
1015 #else /* HAVE_MMAP */
1016     if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
1017         expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
1018
1019     rcsbuf->ptr = rcsbuf_buffer;
1020     rcsbuf->ptrend = rcsbuf_buffer;
1021     rcsbuf->pos = pos;
1022 #endif /* HAVE_MMAP */
1023     rcsbuf->fp = fp;
1024     rcsbuf->filename = filename;
1025     rcsbuf->vlen = 0;
1026     rcsbuf->at_string = 0;
1027     rcsbuf->embedded_at = 0;
1028 }
1029
1030 /* Stop gathering keys from an RCS file.  */
1031
1032 static void
1033 rcsbuf_close (struct rcsbuffer *rcsbuf)
1034 {
1035     if (! rcsbuf_inuse)
1036         error (1, 0, "rcsbuf_close: internal error");
1037 #ifdef HAVE_MMAP
1038     munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
1039 #endif
1040     rcsbuf_inuse = 0;
1041 }
1042
1043 /* Read a key/value pair from an RCS file.  This sets *KEYP to point
1044    to the key, and *VALUEP to point to the value.  A missing or empty
1045    value is indicated by setting *VALUEP to NULL.
1046
1047    This function returns 1 on success, or 0 on EOF.  If there is an
1048    error reading the file, or an EOF in an unexpected location, it
1049    gives a fatal error.
1050
1051    This sets *KEYP and *VALUEP to point to storage managed by
1052    rcsbuf_getkey.  Moreover, *VALUEP has not been massaged from the
1053    RCS format: it may contain embedded whitespace and embedded '@'
1054    characters.  Call rcsbuf_valcopy or rcsbuf_valpolish to do
1055    appropriate massaging.  */
1056
1057 /* Note that the extreme hair in rcsbuf_getkey is because profiling
1058    statistics show that it was worth it. */
1059
1060 static int
1061 rcsbuf_getkey (struct rcsbuffer *rcsbuf, char **keyp, char **valp)
1062 {
1063     register const char * const my_spacetab = spacetab;
1064     register char *ptr, *ptrend;
1065     char c;
1066
1067 #define my_whitespace(c)        (my_spacetab[(unsigned char)c] != 0)
1068
1069     rcsbuf->vlen = 0;
1070     rcsbuf->at_string = 0;
1071     rcsbuf->embedded_at = 0;
1072
1073     ptr = rcsbuf->ptr;
1074     ptrend = rcsbuf->ptrend;
1075
1076     /* Sanity check.  */
1077     assert (ptr >= rcsbuf_buffer && ptr <= rcsbuf_buffer + rcsbuf_buffer_size);
1078     assert (ptrend >= rcsbuf_buffer && ptrend <= rcsbuf_buffer + rcsbuf_buffer_size);
1079
1080 #ifndef HAVE_MMAP
1081     /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
1082        buffer, move back to the start of the buffer.  This keeps the
1083        buffer from growing indefinitely.  */
1084     if (ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
1085     {
1086         int len;
1087
1088         len = ptrend - ptr;
1089
1090         /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
1091            at a time, so we can't have more bytes than that past PTR.  */
1092         assert (len <= RCSBUF_BUFSIZE);
1093
1094         /* Update the POS field, which holds the file offset of the
1095            first byte in the RCSBUF_BUFFER buffer.  */
1096         rcsbuf->pos += ptr - rcsbuf_buffer;
1097
1098         memcpy (rcsbuf_buffer, ptr, len);
1099         ptr = rcsbuf_buffer;
1100         ptrend = ptr + len;
1101         rcsbuf->ptrend = ptrend;
1102     }
1103 #endif /* HAVE_MMAP */
1104
1105     /* Skip leading whitespace.  */
1106
1107     while (1)
1108     {
1109         if (ptr >= ptrend)
1110         {
1111             ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
1112             if (ptr == NULL)
1113                 return 0;
1114             ptrend = rcsbuf->ptrend;
1115         }
1116
1117         c = *ptr;
1118         if (! my_whitespace (c))
1119             break;
1120
1121         ++ptr;
1122     }
1123
1124     /* We've found the start of the key.  */
1125
1126     *keyp = ptr;
1127
1128     if (c != ';')
1129     {
1130         while (1)
1131         {
1132             ++ptr;
1133             if (ptr >= ptrend)
1134             {
1135                 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
1136                 if (ptr == NULL)
1137                     error (1, 0, "EOF in key in RCS file %s",
1138                            rcsbuf->filename);
1139                 ptrend = rcsbuf->ptrend;
1140             }
1141             c = *ptr;
1142             if (c == ';' || my_whitespace (c))
1143                 break;
1144         }
1145     }
1146
1147     /* Here *KEYP points to the key in the buffer, C is the character
1148        we found at the of the key, and PTR points to the location in
1149        the buffer where we found C.  We must set *PTR to \0 in order
1150        to terminate the key.  If the key ended with ';', then there is
1151        no value.  */
1152
1153     *ptr = '\0';
1154     ++ptr;
1155
1156     if (c == ';')
1157     {
1158         *valp = NULL;
1159         rcsbuf->ptr = ptr;
1160         return 1;
1161     }
1162
1163     /* C must be whitespace.  Skip whitespace between the key and the
1164        value.  If we find ';' now, there is no value.  */
1165
1166     while (1)
1167     {
1168         if (ptr >= ptrend)
1169         {
1170             ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
1171             if (ptr == NULL)
1172                 error (1, 0, "EOF while looking for value in RCS file %s",
1173                        rcsbuf->filename);
1174             ptrend = rcsbuf->ptrend;
1175         }
1176         c = *ptr;
1177         if (c == ';')
1178         {
1179             *valp = NULL;
1180             rcsbuf->ptr = ptr + 1;
1181             return 1;
1182         }
1183         if (! my_whitespace (c))
1184             break;
1185         ++ptr;
1186     }
1187
1188     /* Now PTR points to the start of the value, and C is the first
1189        character of the value.  */
1190
1191     if (c != '@')
1192         *valp = ptr;
1193     else
1194     {
1195         char *pat;
1196         size_t vlen;
1197
1198         /* Optimize the common case of a value composed of a single
1199            '@' string.  */
1200
1201         rcsbuf->at_string = 1;
1202
1203         ++ptr;
1204
1205         *valp = ptr;
1206
1207         while (1)
1208         {
1209             while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
1210             {
1211                 /* Note that we pass PTREND as the PTR value to
1212                    rcsbuf_fill, so that we will wind up setting PTR to
1213                    the location corresponding to the old PTREND, so
1214                    that we don't search the same bytes again.  */
1215                 ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1216                 if (ptr == NULL)
1217                     error (1, 0,
1218                            "EOF while looking for end of string in RCS file %s",
1219                            rcsbuf->filename);
1220                 ptrend = rcsbuf->ptrend;
1221             }
1222
1223             /* Handle the special case of an '@' right at the end of
1224                the known bytes.  */
1225             if (pat + 1 >= ptrend)
1226             {
1227                 /* Note that we pass PAT, not PTR, here.  */
1228                 pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
1229                 if (pat == NULL)
1230                 {
1231                     /* EOF here is OK; it just means that the last
1232                        character of the file was an '@' terminating a
1233                        value for a key type which does not require a
1234                        trailing ';'.  */
1235                     pat = rcsbuf->ptrend - 1;
1236
1237                 }
1238                 ptrend = rcsbuf->ptrend;
1239
1240                 /* Note that the value of PTR is bogus here.  This is
1241                    OK, because we don't use it.  */
1242             }
1243
1244             if (pat + 1 >= ptrend || pat[1] != '@')
1245                 break;
1246
1247             /* We found an '@' pair in the string.  Keep looking.  */
1248             ++rcsbuf->embedded_at;
1249             ptr = pat + 2;
1250         }
1251
1252         /* Here PAT points to the final '@' in the string.  */
1253
1254         *pat = '\0';
1255
1256         vlen = pat - *valp;
1257         if (vlen == 0)
1258             *valp = NULL;
1259         rcsbuf->vlen = vlen;
1260
1261         ptr = pat + 1;
1262     }
1263
1264     /* Certain keywords only have a '@' string.  If there is no '@'
1265        string, then the old getrcskey function assumed that they had
1266        no value, and we do the same.  */
1267
1268     {
1269         char *k;
1270
1271         k = *keyp;
1272         if (STREQ (k, RCSDESC)
1273             || STREQ (k, "text")
1274             || STREQ (k, "log"))
1275         {
1276             if (c != '@')
1277                 *valp = NULL;
1278             rcsbuf->ptr = ptr;
1279             return 1;
1280         }
1281     }
1282
1283     /* If we've already gathered a '@' string, try to skip whitespace
1284        and find a ';'.  */
1285     if (c == '@')
1286     {
1287         while (1)
1288         {
1289             char n;
1290
1291             if (ptr >= ptrend)
1292             {
1293                 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
1294                 if (ptr == NULL)
1295                     error (1, 0, "EOF in value in RCS file %s",
1296                            rcsbuf->filename);
1297                 ptrend = rcsbuf->ptrend;
1298             }
1299             n = *ptr;
1300             if (n == ';')
1301             {
1302                 /* We're done.  We already set everything up for this
1303                    case above.  */
1304                 rcsbuf->ptr = ptr + 1;
1305                 return 1;
1306             }
1307             if (! my_whitespace (n))
1308                 break;
1309             ++ptr;
1310         }
1311
1312         /* The value extends past the '@' string.  We need to undo the
1313            '@' stripping done in the default case above.  This
1314            case never happens in a plain RCS file, but it can happen
1315            if user defined phrases are used.  */
1316         ((*valp)--)[rcsbuf->vlen++] = '@';
1317     }
1318
1319     /* Here we have a value which is not a simple '@' string.  We need
1320        to gather up everything until the next ';', including any '@'
1321        strings.  *VALP points to the start of the value.  If
1322        RCSBUF->VLEN is not zero, then we have already read an '@'
1323        string, and PTR points to the data following the '@' string.
1324        Otherwise, PTR points to the start of the value.  */
1325
1326     while (1)
1327     {
1328         char *start, *psemi, *pat;
1329
1330         /* Find the ';' which must end the value.  */
1331         start = ptr;
1332         while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
1333         {
1334             int slen;
1335
1336             /* Note that we pass PTREND as the PTR value to
1337                rcsbuf_fill, so that we will wind up setting PTR to the
1338                location corresponding to the old PTREND, so that we
1339                don't search the same bytes again.  */
1340             slen = start - *valp;
1341             ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1342             if (ptr == NULL)
1343                 error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
1344             start = *valp + slen;
1345             ptrend = rcsbuf->ptrend;
1346         }
1347
1348         /* See if there are any '@' strings in the value.  */
1349         pat = memchr (start, '@', psemi - start);
1350
1351         if (pat == NULL)
1352         {
1353             size_t vlen;
1354
1355             /* We're done with the value.  Trim any trailing
1356                whitespace.  */
1357
1358             rcsbuf->ptr = psemi + 1;
1359
1360             start = *valp;
1361             while (psemi > start && my_whitespace (psemi[-1]))
1362                 --psemi;
1363             *psemi = '\0';
1364
1365             vlen = psemi - start;
1366             if (vlen == 0)
1367                 *valp = NULL;
1368             rcsbuf->vlen = vlen;
1369
1370             return 1;
1371         }
1372
1373         /* We found an '@' string in the value.  We set RCSBUF->AT_STRING
1374            and RCSBUF->EMBEDDED_AT to indicate that we won't be able to
1375            compress whitespace correctly for this type of value.
1376            Since this type of value never arises in a normal RCS file,
1377            this should not be a big deal.  It means that if anybody
1378            adds a phrase which can have both an '@' string and regular
1379            text, they will have to handle whitespace compression
1380            themselves.  */
1381
1382         rcsbuf->at_string = 1;
1383         rcsbuf->embedded_at = -1;
1384
1385         ptr = pat + 1;
1386
1387         while (1)
1388         {
1389             while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
1390             {
1391                 /* Note that we pass PTREND as the PTR value to
1392                    rcsbuff_fill, so that we will wind up setting PTR
1393                    to the location corresponding to the old PTREND, so
1394                    that we don't search the same bytes again.  */
1395                 ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
1396                 if (ptr == NULL)
1397                     error (1, 0,
1398                            "EOF while looking for end of string in RCS file %s",
1399                            rcsbuf->filename);
1400                 ptrend = rcsbuf->ptrend;
1401             }
1402
1403             /* Handle the special case of an '@' right at the end of
1404                the known bytes.  */
1405             if (pat + 1 >= ptrend)
1406             {
1407                 ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
1408                 if (ptr == NULL)
1409                     error (1, 0, "EOF in value in RCS file %s",
1410                            rcsbuf->filename);
1411                 ptrend = rcsbuf->ptrend;
1412             }
1413
1414             if (pat[1] != '@')
1415                 break;
1416
1417             /* We found an '@' pair in the string.  Keep looking.  */
1418             ptr = pat + 2;
1419         }
1420
1421         /* Here PAT points to the final '@' in the string.  */
1422         ptr = pat + 1;
1423     }
1424
1425 #undef my_whitespace
1426 }
1427
1428 /* Read an RCS revision number from an RCS file.  This sets *REVP to
1429    point to the revision number; it will point to space that is
1430    managed by the rcsbuf functions, and is only good until the next
1431    call to rcsbuf_getkey or rcsbuf_getrevnum.
1432
1433    This function returns 1 on success, or 0 on EOF.  If there is an
1434    error reading the file, or an EOF in an unexpected location, it
1435    gives a fatal error.  */
1436
1437 static int
1438 rcsbuf_getrevnum (struct rcsbuffer *rcsbuf, char **revp)
1439 {
1440     char *ptr, *ptrend;
1441     char c;
1442
1443     ptr = rcsbuf->ptr;
1444     ptrend = rcsbuf->ptrend;
1445
1446     *revp = NULL;
1447
1448     /* Skip leading whitespace.  */
1449
1450     while (1)
1451     {
1452         if (ptr >= ptrend)
1453         {
1454             ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
1455             if (ptr == NULL)
1456                 return 0;
1457             ptrend = rcsbuf->ptrend;
1458         }
1459
1460         c = *ptr;
1461         if (! whitespace (c))
1462             break;
1463
1464         ++ptr;
1465     }
1466
1467     if (! isdigit ((unsigned char) c) && c != '.')
1468         error (1, 0,
1469                "\
1470 unexpected '\\x%x' reading revision number in RCS file %s",
1471                c, rcsbuf->filename);
1472
1473     *revp = ptr;
1474
1475     do
1476     {
1477         ++ptr;
1478         if (ptr >= ptrend)
1479         {
1480             ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
1481             if (ptr == NULL)
1482                 error (1, 0,
1483                        "unexpected EOF reading revision number in RCS file %s",
1484                        rcsbuf->filename);
1485             ptrend = rcsbuf->ptrend;
1486         }
1487
1488         c = *ptr;
1489     }
1490     while (isdigit ((unsigned char) c) || c == '.');
1491
1492     if (! whitespace (c))
1493         error (1, 0, "\
1494 unexpected '\\x%x' reading revision number in RCS file %s",
1495                c, rcsbuf->filename);
1496
1497     *ptr = '\0';
1498
1499     rcsbuf->ptr = ptr + 1;
1500
1501     return 1;
1502 }
1503
1504 /* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
1505    updating PTR and the PTREND field.  If KEYP and *KEYP are not NULL,
1506    then *KEYP points into the buffer, and must be adjusted if the
1507    buffer is changed.  Likewise for VALP.  Returns the new value of
1508    PTR, or NULL on error.  */
1509
1510 static char *
1511 rcsbuf_fill (rcsbuf, ptr, keyp, valp)
1512     struct rcsbuffer *rcsbuf;
1513     char *ptr;
1514     char **keyp;
1515     char **valp;
1516 {
1517 #ifdef HAVE_MMAP
1518     return NULL;
1519 #else /* HAVE_MMAP */
1520     int got;
1521
1522     if (rcsbuf->ptrend - rcsbuf_buffer + RCSBUF_BUFSIZE > rcsbuf_buffer_size)
1523     {
1524         int poff, peoff, koff, voff;
1525
1526         poff = ptr - rcsbuf_buffer;
1527         peoff = rcsbuf->ptrend - rcsbuf_buffer;
1528         koff = keyp == NULL ? 0 : *keyp - rcsbuf_buffer;
1529         voff = valp == NULL ? 0 : *valp - rcsbuf_buffer;
1530
1531         expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size,
1532                        rcsbuf_buffer_size + RCSBUF_BUFSIZE);
1533
1534         ptr = rcsbuf_buffer + poff;
1535         rcsbuf->ptrend = rcsbuf_buffer + peoff;
1536         if (keyp != NULL)
1537             *keyp = rcsbuf_buffer + koff;
1538         if (valp != NULL)
1539             *valp = rcsbuf_buffer + voff;
1540     }
1541
1542     got = fread (rcsbuf->ptrend, 1, RCSBUF_BUFSIZE, rcsbuf->fp);
1543     if (got == 0)
1544     {
1545         if (ferror (rcsbuf->fp))
1546             error (1, errno, "cannot read %s", rcsbuf->filename);
1547         return NULL;
1548     }
1549
1550     rcsbuf->ptrend += got;
1551
1552     return ptr;
1553 #endif /* HAVE_MMAP */
1554 }
1555
1556 /* Test whether the last value returned by rcsbuf_getkey is a composite
1557    value or not. */
1558    
1559 static int
1560 rcsbuf_valcmp (struct rcsbuffer *rcsbuf)
1561 {
1562     return rcsbuf->at_string && rcsbuf->embedded_at < 0;
1563 }
1564
1565 /* Copy the value VAL returned by rcsbuf_getkey into a memory buffer,
1566    returning the memory buffer.  Polish the value like
1567    rcsbuf_valpolish, q.v.  */
1568
1569 static char *
1570 rcsbuf_valcopy (struct rcsbuffer *rcsbuf, char *val, int polish, size_t *lenp)
1571 {
1572     size_t vlen;
1573     int embedded_at;
1574     char *ret;
1575
1576     if (val == NULL)
1577     {
1578         if (lenp != NULL)
1579             *lenp = 0;
1580         return NULL;
1581     }
1582
1583     vlen = rcsbuf->vlen;
1584     embedded_at = rcsbuf->embedded_at < 0 ? 0 : rcsbuf->embedded_at;
1585
1586     ret = xmalloc (vlen - embedded_at + 1);
1587
1588     if (rcsbuf->at_string ? embedded_at == 0 : ! polish)
1589     {
1590         /* No special action to take.  */
1591         memcpy (ret, val, vlen + 1);
1592         if (lenp != NULL)
1593             *lenp = vlen;
1594         return ret;
1595     }
1596
1597     rcsbuf_valpolish_internal (rcsbuf, ret, val, lenp);
1598     return ret;
1599 }
1600
1601 /* Polish the value VAL returned by rcsbuf_getkey.  The POLISH
1602    parameter is non-zero if multiple embedded whitespace characters
1603    should be compressed into a single whitespace character.  Note that
1604    leading and trailing whitespace was already removed by
1605    rcsbuf_getkey.  Within an '@' string, pairs of '@' characters are
1606    compressed into a single '@' character regardless of the value of
1607    POLISH.  If LENP is not NULL, set *LENP to the length of the value.  */
1608
1609 static void
1610 rcsbuf_valpolish (struct rcsbuffer *rcsbuf, char *val, int polish, size_t *lenp)
1611 {
1612     if (val == NULL)
1613     {
1614         if (lenp != NULL)
1615             *lenp= 0;
1616         return;
1617     }
1618
1619     if (rcsbuf->at_string ? rcsbuf->embedded_at == 0 : ! polish)
1620     {
1621         /* No special action to take.  */
1622         if (lenp != NULL)
1623             *lenp = rcsbuf->vlen;
1624         return;
1625     }
1626
1627     rcsbuf_valpolish_internal (rcsbuf, val, val, lenp);
1628 }
1629
1630 /* Internal polishing routine, called from rcsbuf_valcopy and
1631    rcsbuf_valpolish.  */
1632
1633 static void
1634 rcsbuf_valpolish_internal (struct rcsbuffer *rcsbuf, char *to, const char *from, size_t *lenp)
1635 {
1636     size_t len;
1637
1638     len = rcsbuf->vlen;
1639
1640     if (! rcsbuf->at_string)
1641     {
1642         char *orig_to;
1643         size_t clen;
1644
1645         orig_to = to;
1646
1647         for (clen = len; clen > 0; ++from, --clen)
1648         {
1649             char c;
1650
1651             c = *from;
1652             if (whitespace (c))
1653             {
1654                 /* Note that we know that clen can not drop to zero
1655                    while we have whitespace, because we know there is
1656                    no trailing whitespace.  */
1657                 while (whitespace (from[1]))
1658                 {
1659                     ++from;
1660                     --clen;
1661                 }
1662                 c = ' ';
1663             }
1664             *to++ = c;
1665         }
1666
1667         *to = '\0';
1668
1669         if (lenp != NULL)
1670             *lenp = to - orig_to;
1671     }
1672     else
1673     {
1674         const char *orig_from;
1675         char *orig_to;
1676         int embedded_at;
1677         size_t clen;
1678
1679         orig_from = from;
1680         orig_to = to;
1681
1682         embedded_at = rcsbuf->embedded_at;
1683         assert (embedded_at > 0);
1684
1685         if (lenp != NULL)
1686             *lenp = len - embedded_at;
1687
1688         for (clen = len; clen > 0; ++from, --clen)
1689         {
1690             char c;
1691
1692             c = *from;
1693             *to++ = c;
1694             if (c == '@')
1695             {
1696                 ++from;
1697
1698                 /* Sanity check.
1699                  *
1700                  * FIXME: I restored this to an abort from an assert based on
1701                  * advice from Larry Jones that asserts should not be used to
1702                  * confirm the validity of an RCS file...  This leaves two
1703                  * issues here: 1) I am uncertain that the fact that we will
1704                  * only find double '@'s hasn't already been confirmed; and:
1705                  * 2) If this is the proper place to spot the error in the RCS
1706                  * file, then we should print a much clearer error here for the
1707                  * user!!!!!!!
1708                  *
1709                  *      - DRP
1710                  */
1711                 if (*from != '@' || clen == 0)
1712                     abort ();
1713
1714                 --clen;
1715
1716                 --embedded_at;
1717                 if (embedded_at == 0)
1718                 {
1719                     /* We've found all the embedded '@' characters.
1720                        We can just memcpy the rest of the buffer after
1721                        this '@' character.  */
1722                     if (orig_to != orig_from)
1723                         memcpy (to, from + 1, clen - 1);
1724                     else
1725                         memmove (to, from + 1, clen - 1);
1726                     from += clen;
1727                     to += clen - 1;
1728                     break;
1729                 }
1730             }
1731         }
1732
1733         /* Sanity check.  */
1734         assert (from == orig_from + len
1735             && to == orig_to + (len - rcsbuf->embedded_at));
1736
1737         *to = '\0';
1738     }
1739 }
1740
1741 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1742
1743 /* Copy the next word from the value VALP returned by rcsbuf_getkey into a
1744    memory buffer, updating VALP and returning the memory buffer.  Return
1745    NULL when there are no more words. */
1746
1747 static char *
1748 rcsbuf_valword (rcsbuf, valp)
1749     struct rcsbuffer *rcsbuf;
1750     char **valp;
1751 {
1752     register const char * const my_spacetab = spacetab;
1753     register char *ptr, *pat;
1754     char c;
1755
1756 # define my_whitespace(c)       (my_spacetab[(unsigned char)c] != 0)
1757
1758     if (*valp == NULL)
1759         return NULL;
1760
1761     for (ptr = *valp; my_whitespace (*ptr); ++ptr) ;
1762     if (*ptr == '\0')
1763     {
1764         assert (ptr - *valp == rcsbuf->vlen);
1765         *valp = NULL;
1766         rcsbuf->vlen = 0;
1767         return NULL;
1768     }
1769
1770     /* PTR now points to the start of a value.  Find out whether it is
1771        a num, an id, a string or a colon. */
1772     c = *ptr;
1773     if (c == ':')
1774     {
1775         rcsbuf->vlen -= ++ptr - *valp;
1776         *valp = ptr;
1777         return xstrdup (":");
1778     }
1779
1780     if (c == '@')
1781     {
1782         int embedded_at = 0;
1783         size_t vlen;
1784
1785         pat = ++ptr;
1786         while ((pat = strchr (pat, '@')) != NULL)
1787         {
1788             if (pat[1] != '@')
1789                 break;
1790             ++embedded_at;
1791             pat += 2;
1792         }
1793
1794         /* Here PAT points to the final '@' in the string.  */
1795         *pat++ = '\0';
1796         assert (rcsbuf->at_string);
1797         vlen = rcsbuf->vlen - (pat - *valp);
1798         rcsbuf->vlen = pat - ptr - 1;
1799         rcsbuf->embedded_at = embedded_at;
1800         ptr = rcsbuf_valcopy (rcsbuf, ptr, 0, (size_t *) NULL);
1801         *valp = pat;
1802         rcsbuf->vlen = vlen;
1803         if (strchr (pat, '@') == NULL)
1804             rcsbuf->at_string = 0;
1805         else
1806             rcsbuf->embedded_at = -1;
1807         return ptr;
1808     }
1809
1810     /* *PTR is neither `:', `;' nor `@', so it should be the start of a num
1811        or an id.  Make sure it is not another special character. */
1812     if (c == '$' || c == '.' || c == ',')
1813     {
1814         error (1, 0, "invalid special character in RCS field in %s",
1815                rcsbuf->filename);
1816     }
1817
1818     pat = ptr;
1819     while (1)
1820     {
1821         /* Legitimate ID characters are digits, dots and any `graphic
1822            printing character that is not a special.' This test ought
1823            to do the trick. */
1824         c = *++pat;
1825         if (!isprint ((unsigned char) c) ||
1826             c == ';' || c == '$' || c == ',' || c == '@' || c == ':')
1827             break;
1828     }
1829
1830     /* PAT points to the last non-id character in this word, and C is
1831        the character in its memory cell.  Check to make sure that it
1832        is a legitimate word delimiter -- whitespace or end. */
1833     if (c != '\0' && !my_whitespace (c))
1834         error (1, 0, "invalid special character in RCS field in %s",
1835                rcsbuf->filename);
1836
1837     *pat = '\0';
1838     rcsbuf->vlen -= pat - *valp;
1839     *valp = pat;
1840     return xstrdup (ptr);
1841
1842 # undef my_whitespace
1843 }
1844
1845 #endif
1846
1847 /* Return the current position of an rcsbuf.  */
1848
1849 static off_t
1850 rcsbuf_ftello (struct rcsbuffer *rcsbuf)
1851 {
1852     return rcsbuf->pos + rcsbuf->ptr - rcsbuf_buffer;
1853 }
1854
1855 /* Return a pointer to any data buffered for RCSBUF, along with the
1856    length.  */
1857
1858 static void
1859 rcsbuf_get_buffered (struct rcsbuffer *rcsbuf, char **datap, size_t *lenp)
1860 {
1861     *datap = rcsbuf->ptr;
1862     *lenp = rcsbuf->ptrend - rcsbuf->ptr;
1863 }
1864
1865 /* CVS optimizes by quickly reading some header information from a
1866    file.  If it decides it needs to do more with the file, it reopens
1867    it.  We speed that up here by maintaining a cache of a single open
1868    file, to save the time it takes to reopen the file in the common
1869    case.  */
1870
1871 static RCSNode *cached_rcs;
1872 static struct rcsbuffer cached_rcsbuf;
1873
1874 /* Cache RCS and RCSBUF.  This takes responsibility for closing
1875    RCSBUF->FP.  */
1876
1877 static void
1878 rcsbuf_cache (RCSNode *rcs, struct rcsbuffer *rcsbuf)
1879 {
1880     if (cached_rcs != NULL)
1881         rcsbuf_cache_close ();
1882     cached_rcs = rcs;
1883     ++rcs->refcount;
1884     cached_rcsbuf = *rcsbuf;
1885 }
1886
1887 /* If there is anything in the cache, close it.  */
1888
1889 static void
1890 rcsbuf_cache_close (void)
1891 {
1892     if (cached_rcs != NULL)
1893     {
1894         rcsbuf_close (&cached_rcsbuf);
1895         if (fclose (cached_rcsbuf.fp) != 0)
1896             error (0, errno, "cannot close %s", cached_rcsbuf.filename);
1897         freercsnode (&cached_rcs);
1898         cached_rcs = NULL;
1899     }
1900 }
1901
1902 /* Open an rcsbuffer for RCS, getting it from the cache if possible.
1903    Set *FPP to the file, and *RCSBUFP to the rcsbuf.  The file should
1904    be put at position POS.  */
1905
1906 static void
1907 rcsbuf_cache_open (RCSNode *rcs, off_t pos, FILE **pfp,
1908                    struct rcsbuffer *prcsbuf)
1909 {
1910 #ifndef HAVE_MMAP
1911     if (cached_rcs == rcs)
1912     {
1913         if (rcsbuf_ftello (&cached_rcsbuf) != pos)
1914         {
1915             if (fseeko (cached_rcsbuf.fp, pos, SEEK_SET) != 0)
1916                 error (1, 0, "cannot fseeko RCS file %s",
1917                        cached_rcsbuf.filename);
1918             cached_rcsbuf.ptr = rcsbuf_buffer;
1919             cached_rcsbuf.ptrend = rcsbuf_buffer;
1920             cached_rcsbuf.pos = pos;
1921         }
1922         *pfp = cached_rcsbuf.fp;
1923
1924         /* When RCS_parse opens a file using fopen_case, it frees the
1925            filename which we cached in CACHED_RCSBUF and stores a new
1926            file name in RCS->PATH.  We avoid problems here by always
1927            copying the filename over.  FIXME: This is hackish.  */
1928         cached_rcsbuf.filename = rcs->path;
1929
1930         *prcsbuf = cached_rcsbuf;
1931
1932         cached_rcs = NULL;
1933
1934         /* Removing RCS from the cache removes a reference to it.  */
1935         --rcs->refcount;
1936         if (rcs->refcount <= 0)
1937             error (1, 0, "rcsbuf_cache_open: internal error");
1938     }
1939     else
1940     {
1941 #endif /* ifndef HAVE_MMAP */
1942         /* FIXME:  If these routines can be rewritten to not write to the
1943          * rcs file buffer, there would be a considerably larger memory savings
1944          * from using mmap since the shared file would never need be copied to
1945          * process memory.
1946          *
1947          * If this happens, cached mmapped buffers would be usable, but don't
1948          * forget to make sure rcs->pos < pos here...
1949          */
1950         if (cached_rcs != NULL)
1951             rcsbuf_cache_close ();
1952
1953         *pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
1954         if (*pfp == NULL)
1955             error (1, 0, "unable to reopen `%s'", rcs->path);
1956 #ifndef HAVE_MMAP
1957         if (pos != 0)
1958         {
1959             if (fseeko (*pfp, pos, SEEK_SET) != 0)
1960                 error (1, 0, "cannot fseeko RCS file %s", rcs->path);
1961         }
1962 #endif /* ifndef HAVE_MMAP */
1963         rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
1964 #ifndef HAVE_MMAP
1965     }
1966 #endif /* ifndef HAVE_MMAP */
1967 }
1968
1969 \f
1970 /*
1971  * process the symbols list of the rcs file
1972  */
1973 static void
1974 do_symbols (List *list, char *val)
1975 {
1976     Node *p;
1977     char *cp = val;
1978     char *tag, *rev;
1979
1980     for (;;)
1981     {
1982         /* skip leading whitespace */
1983         while (whitespace (*cp))
1984             cp++;
1985
1986         /* if we got to the end, we are done */
1987         if (*cp == '\0')
1988             break;
1989
1990         /* split it up into tag and rev */
1991         tag = cp;
1992         cp = strchr (cp, ':');
1993         *cp++ = '\0';
1994         rev = cp;
1995         while (!whitespace (*cp) && *cp != '\0')
1996             cp++;
1997         if (*cp != '\0')
1998             *cp++ = '\0';
1999
2000         /* make a new node and add it to the list */
2001         p = getnode ();
2002         p->key = xstrdup (tag);
2003         p->data = xstrdup (rev);
2004         (void) addnode (list, p);
2005     }
2006 }
2007
2008 /*
2009  * process the locks list of the rcs file
2010  * Like do_symbols, but hash entries are keyed backwards: i.e.
2011  * an entry like `user:rev' is keyed on REV rather than on USER.
2012  */
2013 static void
2014 do_locks (List *list, char *val)
2015 {
2016     Node *p;
2017     char *cp = val;
2018     char *user, *rev;
2019
2020     for (;;)
2021     {
2022         /* skip leading whitespace */
2023         while (whitespace (*cp))
2024             cp++;
2025
2026         /* if we got to the end, we are done */
2027         if (*cp == '\0')
2028             break;
2029
2030         /* split it up into user and rev */
2031         user = cp;
2032         cp = strchr (cp, ':');
2033         *cp++ = '\0';
2034         rev = cp;
2035         while (!whitespace (*cp) && *cp != '\0')
2036             cp++;
2037         if (*cp != '\0')
2038             *cp++ = '\0';
2039
2040         /* make a new node and add it to the list */
2041         p = getnode ();
2042         p->key = xstrdup (rev);
2043         p->data = xstrdup (user);
2044         (void) addnode (list, p);
2045     }
2046 }
2047
2048 /*
2049  * process the branches list of a revision delta
2050  */
2051 static void
2052 do_branches (List *list, char *val)
2053 {
2054     Node *p;
2055     char *cp = val;
2056     char *branch;
2057
2058     for (;;)
2059     {
2060         /* skip leading whitespace */
2061         while (whitespace (*cp))
2062             cp++;
2063
2064         /* if we got to the end, we are done */
2065         if (*cp == '\0')
2066             break;
2067
2068         /* find the end of this branch */
2069         branch = cp;
2070         while (!whitespace (*cp) && *cp != '\0')
2071             cp++;
2072         if (*cp != '\0')
2073             *cp++ = '\0';
2074
2075         /* make a new node and add it to the list */
2076         p = getnode ();
2077         p->key = xstrdup (branch);
2078         (void) addnode (list, p);
2079     }
2080 }
2081
2082
2083
2084 /*
2085  * Version Number
2086  * 
2087  * Returns the requested version number of the RCS file, satisfying tags and/or
2088  * dates, and walking branches, if necessary.
2089  * 
2090  * The result is returned; null-string if error.
2091  */
2092 char *
2093 RCS_getversion (RCSNode *rcs, const char *tag, const char *date,
2094                 int force_tag_match, int *simple_tag)
2095 {
2096     if (simple_tag != NULL)
2097         *simple_tag = 0;
2098
2099     /* make sure we have something to look at... */
2100     assert (rcs != NULL);
2101
2102     if (tag && date)
2103     {
2104         char *branch, *rev;
2105
2106         if (! RCS_nodeisbranch (rcs, tag))
2107         {
2108             /* We can't get a particular date if the tag is not a
2109                branch.  */
2110             return NULL;
2111         }
2112
2113         /* Work out the branch.  */
2114         if (! isdigit ((unsigned char) tag[0]))
2115             branch = RCS_whatbranch (rcs, tag);
2116         else
2117             branch = xstrdup (tag);
2118
2119         /* Fetch the revision of branch as of date.  */
2120         rev = RCS_getdatebranch (rcs, date, branch);
2121         free (branch);
2122         return (rev);
2123     }
2124     else if (tag)
2125         return RCS_gettag (rcs, tag, force_tag_match, simple_tag);
2126     else if (date)
2127         return RCS_getdate (rcs, date, force_tag_match);
2128     else
2129         return RCS_head (rcs);
2130
2131 }
2132
2133
2134
2135 /*
2136  * Get existing revision number corresponding to tag or revision.
2137  * Similar to RCS_gettag but less interpretation imposed.
2138  * For example:
2139  * -- If tag designates a magic branch, RCS_tag2rev
2140  *    returns the magic branch number.
2141  * -- If tag is a branch tag, returns the branch number, not
2142  *    the revision of the head of the branch.
2143  * If tag or revision is not valid or does not exist in file,
2144  * return NULL.
2145  */
2146 char *
2147 RCS_tag2rev (RCSNode *rcs, char *tag)
2148 {
2149     char *rev, *pa, *pb;
2150     int i;
2151
2152     assert (rcs != NULL);
2153
2154     if (rcs->flags & PARTIAL)
2155         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2156
2157     /* If a valid revision, try to look it up */
2158     if ( RCS_valid_rev (tag) )
2159     {
2160         /* Make a copy so we can scribble on it */
2161         rev =  xstrdup (tag);
2162
2163         /* If revision exists, return the copy */
2164         if (RCS_exist_rev (rcs, tag))
2165             return rev;
2166
2167         /* Nope, none such. If tag is not a branch we're done. */ 
2168         i = numdots (rev);
2169         if ((i & 1) == 1 )
2170         {
2171             pa = strrchr (rev, '.');
2172             if (i == 1 || *(pa-1) != RCS_MAGIC_BRANCH || *(pa-2) != '.')
2173             {
2174                 free (rev);
2175                 error (1, 0, "revision `%s' does not exist", tag);
2176             }
2177         }
2178
2179         /* Try for a real (that is, exists in the RCS deltas) branch
2180            (RCS_exist_rev just checks for real revisions and revisions
2181            which have tags pointing to them).  */
2182         pa = RCS_getbranch (rcs, rev, 1);
2183         if (pa != NULL)
2184         {
2185             free (pa);
2186             return rev;
2187         }
2188
2189        /* Tag is branch, but does not exist, try corresponding 
2190         * magic branch tag.
2191         *
2192         * FIXME: assumes all magic branches are of       
2193         * form "n.n.n ... .0.n".  I'll fix if somebody can
2194         * send me a method to get a magic branch tag with
2195         * the 0 in some other position -- <dan@gasboy.com>
2196         */ 
2197         pa = strrchr (rev, '.');
2198         pb = xmalloc (strlen (rev) + 3);
2199         *pa++ = 0;
2200         (void) sprintf (pb, "%s.%d.%s", rev, RCS_MAGIC_BRANCH, pa);
2201         free (rev);
2202         rev = pb;
2203         if (RCS_exist_rev (rcs, rev))
2204             return rev;
2205         error (1, 0, "revision `%s' does not exist", tag);
2206     }
2207
2208
2209     RCS_check_tag (tag); /* exit if not a valid tag */
2210
2211     /* If tag is "HEAD", special case to get head RCS revision */
2212     if (tag && STREQ (tag, TAG_HEAD))
2213         return (RCS_head (rcs));
2214
2215     /* If valid tag let translate_symtag say yea or nay. */
2216     rev = translate_symtag (rcs, tag);
2217
2218     if (rev)
2219         return rev;
2220
2221     /* Trust the caller to print warnings. */
2222     return NULL;
2223 }
2224
2225 /*
2226  * Find the revision for a specific tag.
2227  * If force_tag_match is set, return NULL if an exact match is not
2228  * possible otherwise return RCS_head ().  We are careful to look for
2229  * and handle "magic" revisions specially.
2230  * 
2231  * If the matched tag is a branch tag, find the head of the branch.
2232  * 
2233  * Returns pointer to newly malloc'd string, or NULL.
2234  */
2235 char *
2236 RCS_gettag (RCSNode *rcs, const char *symtag, int force_tag_match,
2237             int *simple_tag)
2238 {
2239     char *tag;
2240
2241     if (simple_tag != NULL)
2242         *simple_tag = 0;
2243
2244     /* make sure we have something to look at... */
2245     assert (rcs != NULL);
2246
2247     /* XXX this is probably not necessary, --jtc */
2248     if (rcs->flags & PARTIAL) 
2249         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2250
2251     /* If symtag is "HEAD", special case to get head RCS revision */
2252     if (symtag && STREQ (symtag, TAG_HEAD))
2253 #if 0 /* This #if 0 is only in the Cygnus code.  Why?  Death support?  */
2254         if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
2255             return ((char *) NULL);     /* head request for removed file */
2256         else
2257 #endif
2258             return RCS_head (rcs);
2259
2260     if (!isdigit ((unsigned char) symtag[0]))
2261     {
2262         char *version;
2263
2264         /* If we got a symbolic tag, resolve it to a numeric */
2265         version = translate_symtag (rcs, symtag);
2266         if (version != NULL)
2267         {
2268             int dots;
2269             char *magic, *branch, *cp;
2270
2271             tag = version;
2272
2273             /*
2274              * If this is a magic revision, we turn it into either its
2275              * physical branch equivalent (if one exists) or into
2276              * its base revision, which we assume exists.
2277              */
2278             dots = numdots (tag);
2279             if (dots > 2 && (dots & 1) != 0)
2280             {
2281                 branch = strrchr (tag, '.');
2282                 cp = branch++ - 1;
2283                 while (*cp != '.')
2284                     cp--;
2285
2286                 /* see if we have .magic-branch. (".0.") */
2287                 magic = xmalloc (strlen (tag) + 1);
2288                 (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2289                 if (strncmp (magic, cp, strlen (magic)) == 0)
2290                 {
2291                     /* it's magic.  See if the branch exists */
2292                     *cp = '\0';         /* turn it into a revision */
2293                     (void) sprintf (magic, "%s.%s", tag, branch);
2294                     branch = RCS_getbranch (rcs, magic, 1);
2295                     free (magic);
2296                     if (branch != NULL)
2297                     {
2298                         free (tag);
2299                         return branch;
2300                     }
2301                     return tag;
2302                 }
2303                 free (magic);
2304             }
2305         }
2306         else
2307         {
2308             /* The tag wasn't there, so return the head or NULL */
2309             if (force_tag_match)
2310                 return NULL;
2311             else
2312                 return RCS_head (rcs);
2313         }
2314     }
2315     else
2316         tag = xstrdup (symtag);
2317
2318     /* tag is always allocated and numeric now.  */
2319
2320     /*
2321      * numeric tag processing:
2322      *          1) revision number - just return it
2323      *          2) branch number   - find head of branch
2324      */
2325
2326     /* strip trailing dots */
2327     while (tag[strlen (tag) - 1] == '.')
2328         tag[strlen (tag) - 1] = '\0';
2329
2330     if ((numdots (tag) & 1) == 0)
2331     {
2332         char *branch;
2333
2334         /* we have a branch tag, so we need to walk the branch */
2335         branch = RCS_getbranch (rcs, tag, force_tag_match);
2336         free (tag);
2337         return branch;
2338     }
2339     else
2340     {
2341         Node *p;
2342
2343         /* we have a revision tag, so make sure it exists */
2344         p = findnode (rcs->versions, tag);
2345         if (p != NULL)
2346         {
2347             /* We have found a numeric revision for the revision tag.
2348                To support expanding the RCS keyword Name, if
2349                SIMPLE_TAG is not NULL, tell the the caller that this
2350                is a simple tag which co will recognize.  FIXME: Are
2351                there other cases in which we should set this?  In
2352                particular, what if we expand RCS keywords internally
2353                without calling co?  */
2354             if (simple_tag != NULL)
2355                 *simple_tag = 1;
2356             return tag;
2357         }
2358         else
2359         {
2360             /* The revision wasn't there, so return the head or NULL */
2361             free (tag);
2362             if (force_tag_match)
2363                 return NULL;
2364             else
2365                 return RCS_head (rcs);
2366         }
2367     }
2368 }
2369
2370 /*
2371  * Return a "magic" revision as a virtual branch off of REV for the RCS file.
2372  * A "magic" revision is one which is unique in the RCS file.  By unique, I
2373  * mean we return a revision which:
2374  *      - has a branch of 0 (see rcs.h RCS_MAGIC_BRANCH)
2375  *      - has a revision component which is not an existing branch off REV
2376  *      - has a revision component which is not an existing magic revision
2377  *      - is an even-numbered revision, to avoid conflicts with vendor branches
2378  * The first point is what makes it "magic".
2379  *
2380  * As an example, if we pass in 1.37 as REV, we will look for an existing
2381  * branch called 1.37.2.  If it did not exist, we would look for an
2382  * existing symbolic tag with a numeric part equal to 1.37.0.2.  If that
2383  * didn't exist, then we know that the 1.37.2 branch can be reserved by
2384  * creating a symbolic tag with 1.37.0.2 as the numeric part.
2385  *
2386  * This allows us to fork development with very little overhead -- just a
2387  * symbolic tag is used in the RCS file.  When a commit is done, a physical
2388  * branch is dynamically created to hold the new revision.
2389  *
2390  * Note: We assume that REV is an RCS revision and not a branch number.
2391  */
2392 static char *check_rev;
2393 char *
2394 RCS_magicrev (RCSNode *rcs, char *rev)
2395 {
2396     int rev_num;
2397     char *xrev, *test_branch, *local_branch_num;
2398
2399     xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
2400     check_rev = xrev;
2401
2402     local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM");
2403     if (local_branch_num)
2404     {
2405       rev_num = atoi(local_branch_num);
2406       if (rev_num < 2)
2407         rev_num = 2;
2408       else
2409         rev_num &= ~1;
2410     }
2411     else
2412       rev_num = 2;
2413
2414     /* only look at even numbered branches */
2415     for ( ; ; rev_num += 2)
2416     {
2417         /* see if the physical branch exists */
2418         (void) sprintf (xrev, "%s.%d", rev, rev_num);
2419         test_branch = RCS_getbranch (rcs, xrev, 1);
2420         if (test_branch != NULL)        /* it did, so keep looking */
2421         {
2422             free (test_branch);
2423             continue;
2424         }
2425
2426         /* now, create a "magic" revision */
2427         (void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
2428
2429         /* walk the symbols list to see if a magic one already exists */
2430         if (walklist (RCS_symbols(rcs), checkmagic_proc, NULL) != 0)
2431             continue;
2432
2433         /* we found a free magic branch.  Claim it as ours */
2434         return (xrev);
2435     }
2436 }
2437
2438 /*
2439  * walklist proc to look for a match in the symbols list.
2440  * Returns 0 if the symbol does not match, 1 if it does.
2441  */
2442 static int
2443 checkmagic_proc (Node *p, void *closure)
2444 {
2445     if (STREQ (check_rev, p->data))
2446         return (1);
2447     else
2448         return (0);
2449 }
2450
2451 /*
2452  * Given an RCSNode, returns non-zero if the specified revision number 
2453  * or symbolic tag resolves to a "branch" within the rcs file.
2454  *
2455  * FIXME: this is the same as RCS_nodeisbranch except for the special 
2456  *        case for handling a null rcsnode.
2457  */
2458 int
2459 RCS_isbranch (RCSNode *rcs, const char *rev)
2460 {
2461     /* numeric revisions are easy -- even number of dots is a branch */
2462     if (isdigit ((unsigned char) *rev))
2463         return ((numdots (rev) & 1) == 0);
2464
2465     /* assume a revision if you can't find the RCS info */
2466     if (rcs == NULL)
2467         return (0);
2468
2469     /* now, look for a match in the symbols list */
2470     return (RCS_nodeisbranch (rcs, rev));
2471 }
2472
2473 /*
2474  * Given an RCSNode, returns non-zero if the specified revision number
2475  * or symbolic tag resolves to a "branch" within the rcs file.  We do
2476  * take into account any magic branches as well.
2477  */
2478 int
2479 RCS_nodeisbranch (RCSNode *rcs, const char *rev)
2480 {
2481     int dots;
2482     char *version;
2483
2484     assert (rcs != NULL);
2485
2486     /* numeric revisions are easy -- even number of dots is a branch */
2487     if (isdigit ((unsigned char) *rev))
2488         return ((numdots (rev) & 1) == 0);
2489
2490     version = translate_symtag (rcs, rev);
2491     if (version == NULL)
2492         return (0);
2493     dots = numdots (version);
2494     if ((dots & 1) == 0)
2495     {
2496         free (version);
2497         return (1);
2498     }
2499
2500     /* got a symbolic tag match, but it's not a branch; see if it's magic */
2501     if (dots > 2)
2502     {
2503         char *magic;
2504         char *branch = strrchr (version, '.');
2505         char *cp = branch - 1;
2506         while (*cp != '.')
2507             cp--;
2508
2509         /* see if we have .magic-branch. (".0.") */
2510         magic = xmalloc (strlen (version) + 1);
2511         (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2512         if (strncmp (magic, cp, strlen (magic)) == 0)
2513         {
2514             free (magic);
2515             free (version);
2516             return (1);
2517         }
2518         free (magic);
2519     }
2520     free (version);
2521     return (0);
2522 }
2523
2524 /*
2525  * Returns a pointer to malloc'ed memory which contains the branch
2526  * for the specified *symbolic* tag.  Magic branches are handled correctly.
2527  */
2528 char *
2529 RCS_whatbranch (RCSNode *rcs, const char *rev)
2530 {
2531     char *version;
2532     int dots;
2533
2534     /* assume no branch if you can't find the RCS info */
2535     if (rcs == NULL)
2536         return ((char *) NULL);
2537
2538     /* now, look for a match in the symbols list */
2539     version = translate_symtag (rcs, rev);
2540     if (version == NULL)
2541         return ((char *) NULL);
2542     dots = numdots (version);
2543     if ((dots & 1) == 0)
2544         return (version);
2545
2546     /* got a symbolic tag match, but it's not a branch; see if it's magic */
2547     if (dots > 2)
2548     {
2549         char *magic;
2550         char *branch = strrchr (version, '.');
2551         char *cp = branch++ - 1;
2552         while (*cp != '.')
2553             cp--;
2554
2555         /* see if we have .magic-branch. (".0.") */
2556         magic = xmalloc (strlen (version) + 1);
2557         (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
2558         if (strncmp (magic, cp, strlen (magic)) == 0)
2559         {
2560             /* yep.  it's magic.  now, construct the real branch */
2561             *cp = '\0';                 /* turn it into a revision */
2562             (void) sprintf (magic, "%s.%s", version, branch);
2563             free (version);
2564             return (magic);
2565         }
2566         free (magic);
2567     }
2568     free (version);
2569     return ((char *) NULL);
2570 }
2571
2572 /*
2573  * Get the head of the specified branch.  If the branch does not exist,
2574  * return NULL or RCS_head depending on force_tag_match.
2575  * Returns NULL or a newly malloc'd string.
2576  */
2577 char *
2578 RCS_getbranch (RCSNode *rcs, const char *tag, int force_tag_match)
2579 {
2580     Node *p, *head;
2581     RCSVers *vn;
2582     char *xtag;
2583     char *nextvers;
2584     char *cp;
2585
2586     /* make sure we have something to look at... */
2587     assert (rcs != NULL);
2588
2589     if (rcs->flags & PARTIAL)
2590         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2591
2592     /* find out if the tag contains a dot, or is on the trunk */
2593     cp = strrchr (tag, '.');
2594
2595     /* trunk processing is the special case */
2596     if (cp == NULL)
2597     {
2598         xtag = xmalloc (strlen (tag) + 1 + 1);  /* +1 for an extra . */
2599         (void) strcpy (xtag, tag);
2600         (void) strcat (xtag, ".");
2601         for (cp = rcs->head; cp != NULL;)
2602         {
2603             if (strncmp (xtag, cp, strlen (xtag)) == 0)
2604                 break;
2605             p = findnode (rcs->versions, cp);
2606             if (p == NULL)
2607             {
2608                 free (xtag);
2609                 if (force_tag_match)
2610                     return (NULL);
2611                 else
2612                     return (RCS_head (rcs));
2613             }
2614             vn = p->data;
2615             cp = vn->next;
2616         }
2617         free (xtag);
2618         if (cp == NULL)
2619         {
2620             if (force_tag_match)
2621                 return (NULL);
2622             else
2623                 return (RCS_head (rcs));
2624         }
2625         return (xstrdup (cp));
2626     }
2627
2628     /* if it had a `.', terminate the string so we have the base revision */
2629     *cp = '\0';
2630
2631     /* look up the revision this branch is based on */
2632     p = findnode (rcs->versions, tag);
2633
2634     /* put the . back so we have the branch again */
2635     *cp = '.';
2636
2637     if (p == NULL)
2638     {
2639         /* if the base revision didn't exist, return head or NULL */
2640         if (force_tag_match)
2641             return (NULL);
2642         else
2643             return (RCS_head (rcs));
2644     }
2645
2646     /* find the first element of the branch we are looking for */
2647     vn = p->data;
2648     if (vn->branches == NULL)
2649         return (NULL);
2650     xtag = xmalloc (strlen (tag) + 1 + 1);      /* 1 for the extra '.' */
2651     (void) strcpy (xtag, tag);
2652     (void) strcat (xtag, ".");
2653     head = vn->branches->list;
2654     for (p = head->next; p != head; p = p->next)
2655         if (strncmp (p->key, xtag, strlen (xtag)) == 0)
2656             break;
2657     free (xtag);
2658
2659     if (p == head)
2660     {
2661         /* we didn't find a match so return head or NULL */
2662         if (force_tag_match)
2663             return (NULL);
2664         else
2665             return (RCS_head (rcs));
2666     }
2667
2668     /* now walk the next pointers of the branch */
2669     nextvers = p->key;
2670     do
2671     {
2672         p = findnode (rcs->versions, nextvers);
2673         if (p == NULL)
2674         {
2675             /* a link in the chain is missing - return head or NULL */
2676             if (force_tag_match)
2677                 return (NULL);
2678             else
2679                 return (RCS_head (rcs));
2680         }
2681         vn = p->data;
2682         nextvers = vn->next;
2683     } while (nextvers != NULL);
2684
2685     /* we have the version in our hand, so go for it */
2686     return (xstrdup (vn->version));
2687 }
2688
2689 /* Returns the head of the branch which REV is on.  REV can be a
2690    branch tag or non-branch tag; symbolic or numeric.
2691
2692    Returns a newly malloc'd string.  Returns NULL if a symbolic name
2693    isn't found.  */
2694
2695 char *
2696 RCS_branch_head (RCSNode *rcs, char *rev)
2697 {
2698     char *num;
2699     char *br;
2700     char *retval;
2701
2702     assert (rcs != NULL);
2703
2704     if (RCS_nodeisbranch (rcs, rev))
2705         return RCS_getbranch (rcs, rev, 1);
2706
2707     if (isdigit ((unsigned char) *rev))
2708         num = xstrdup (rev);
2709     else
2710     {
2711         num = translate_symtag (rcs, rev);
2712         if (num == NULL)
2713             return NULL;
2714     }
2715     br = truncate_revnum (num);
2716     retval = RCS_getbranch (rcs, br, 1);
2717     free (br);
2718     free (num);
2719     return retval;
2720 }
2721
2722 /* Get the branch point for a particular branch, that is the first
2723    revision on that branch.  For example, RCS_getbranchpoint (rcs,
2724    "1.3.2") will normally return "1.3.2.1".  TARGET may be either a
2725    branch number or a revision number; if a revnum, find the
2726    branchpoint of the branch to which TARGET belongs.
2727
2728    Return RCS_head if TARGET is on the trunk or if the root node could
2729    not be found (this is sort of backwards from our behavior on a branch;
2730    the rationale is that the return value is a revision from which you
2731    can start walking the next fields and end up at TARGET).
2732    Return NULL on error.  */
2733
2734 static char *
2735 RCS_getbranchpoint (RCSNode *rcs, char *target)
2736 {
2737     char *branch, *bp;
2738     Node *vp;
2739     RCSVers *rev;
2740     int dots, isrevnum, brlen;
2741
2742     dots = numdots (target);
2743     isrevnum = dots & 1;
2744
2745     if (dots == 1)
2746         /* TARGET is a trunk revision; return rcs->head. */
2747         return (RCS_head (rcs));
2748
2749     /* Get the revision number of the node at which TARGET's branch is
2750        rooted.  If TARGET is a branch number, lop off the last field;
2751        if it's a revision number, lop off the last *two* fields. */
2752     branch = xstrdup (target);
2753     bp = strrchr (branch, '.');
2754     if (bp == NULL)
2755         error (1, 0, "%s: confused revision number %s",
2756                rcs->path, target);
2757     if (isrevnum)
2758         while (*--bp != '.')
2759             ;
2760     *bp = '\0';
2761
2762     vp = findnode (rcs->versions, branch);
2763     if (vp == NULL)
2764     {   
2765         error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2766         return NULL;
2767     }
2768     rev = vp->data;
2769
2770     *bp++ = '.';
2771     while (*bp && *bp != '.')
2772         ++bp;
2773     brlen = bp - branch;
2774
2775     vp = rev->branches->list->next;
2776     while (vp != rev->branches->list)
2777     {
2778         /* BRANCH may be a genuine branch number, e.g. `1.1.3', or
2779            maybe a full revision number, e.g. `1.1.3.6'.  We have
2780            found our branch point if the first BRANCHLEN characters
2781            of the revision number match, *and* if the following
2782            character is a dot. */
2783         if (strncmp (vp->key, branch, brlen) == 0 && vp->key[brlen] == '.')
2784             break;
2785         vp = vp->next;
2786     }
2787
2788     free (branch);
2789     if (vp == rev->branches->list)
2790     {
2791         error (0, 0, "%s: can't find branch point %s", rcs->path, target);
2792         return NULL;
2793     }
2794     else
2795         return (xstrdup (vp->key));
2796 }
2797
2798 /*
2799  * Get the head of the RCS file.  If branch is set, this is the head of the
2800  * branch, otherwise the real head.
2801  * Returns NULL or a newly malloc'd string.
2802  */
2803 char *
2804 RCS_head (RCSNode *rcs)
2805 {
2806     /* make sure we have something to look at... */
2807     assert (rcs != NULL);
2808
2809     /*
2810      * NOTE: we call getbranch with force_tag_match set to avoid any
2811      * possibility of recursion
2812      */
2813     if (rcs->branch)
2814         return (RCS_getbranch (rcs, rcs->branch, 1));
2815     else
2816         return (xstrdup (rcs->head));
2817 }
2818
2819 /*
2820  * Get the most recent revision, based on the supplied date, but use some
2821  * funky stuff and follow the vendor branch maybe
2822  */
2823 char *
2824 RCS_getdate (RCSNode *rcs, const char *date, int force_tag_match)
2825 {
2826     char *cur_rev = NULL;
2827     char *retval = NULL;
2828     Node *p;
2829     RCSVers *vers = NULL;
2830
2831     /* make sure we have something to look at... */
2832     assert (rcs != NULL);
2833
2834     if (rcs->flags & PARTIAL)
2835         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2836
2837     /* if the head is on a branch, try the branch first */
2838     if (rcs->branch != NULL)
2839     {
2840         retval = RCS_getdatebranch (rcs, date, rcs->branch);
2841         if (retval != NULL)
2842             return (retval);
2843     }
2844
2845     /* otherwise if we have a trunk, try it */
2846     if (rcs->head)
2847     {
2848         p = findnode (rcs->versions, rcs->head);
2849         if (p == NULL)
2850         {
2851             error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
2852                    rcs->head);
2853         }
2854         while (p != NULL)
2855         {
2856             /* if the date of this one is before date, take it */
2857             vers = p->data;
2858             if (RCS_datecmp (vers->date, date) <= 0)
2859             {
2860                 cur_rev = vers->version;
2861                 break;
2862             }
2863
2864             /* if there is a next version, find the node */
2865             if (vers->next != NULL)
2866                 p = findnode (rcs->versions, vers->next);
2867             else
2868                 p = (Node *) NULL;
2869         }
2870     }
2871     else
2872         error (0, 0, "%s: no head revision", rcs->path);
2873
2874     /*
2875      * at this point, either we have the revision we want, or we have the
2876      * first revision on the trunk (1.1?) in our hands, or we've come up
2877      * completely empty
2878      */
2879
2880     /* if we found what we're looking for, and it's not 1.1 return it */
2881     if (cur_rev != NULL)
2882     {
2883         if (! STREQ (cur_rev, "1.1"))
2884             return (xstrdup (cur_rev));
2885
2886         /* This is 1.1;  if the date of 1.1 is not the same as that for the
2887            1.1.1.1 version, then return 1.1.  This happens when the first
2888            version of a file is created by a regular cvs add and commit,
2889            and there is a subsequent cvs import of the same file.  */
2890         p = findnode (rcs->versions, "1.1.1.1");
2891         if (p)
2892         {
2893             char *date_1_1 = vers->date;
2894
2895             vers = p->data;
2896             if (RCS_datecmp (vers->date, date_1_1) != 0)
2897                 return xstrdup ("1.1");
2898         }
2899     }
2900
2901     /* look on the vendor branch */
2902     retval = RCS_getdatebranch (rcs, date, CVSBRANCH);
2903
2904     /*
2905      * if we found a match, return it; otherwise, we return the first
2906      * revision on the trunk or NULL depending on force_tag_match and the
2907      * date of the first rev
2908      */
2909     if (retval != NULL)
2910         return (retval);
2911
2912     if (!force_tag_match ||
2913         (vers != NULL && RCS_datecmp (vers->date, date) <= 0))
2914         return xstrdup (vers->version);
2915     else
2916         return NULL;
2917 }
2918
2919
2920
2921 /*
2922  * Look up the last element on a branch that was put in before or on
2923  * the specified date and time (return the rev or NULL)
2924  */
2925 static char *
2926 RCS_getdatebranch (RCSNode *rcs, const char *date, const char *branch)
2927 {
2928     char *cur_rev = NULL;
2929     char *cp;
2930     char *xbranch, *xrev;
2931     Node *p;
2932     RCSVers *vers;
2933
2934     /* look up the first revision on the branch */
2935     xrev = xstrdup (branch);
2936     cp = strrchr (xrev, '.');
2937     if (cp == NULL)
2938     {
2939         free (xrev);
2940         return (NULL);
2941     }
2942     *cp = '\0';                         /* turn it into a revision */
2943
2944     assert (rcs != NULL);
2945
2946     if (rcs->flags & PARTIAL)
2947         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
2948
2949     p = findnode (rcs->versions, xrev);
2950     free (xrev);
2951     if (p == NULL)
2952         return (NULL);
2953     vers = p->data;
2954
2955     /* Tentatively use this revision, if it is early enough.  */
2956     if (RCS_datecmp (vers->date, date) <= 0)
2957         cur_rev = vers->version;
2958
2959     /* If no branches list, return now.  This is what happens if the branch
2960        is a (magic) branch with no revisions yet.  */
2961     if (vers->branches == NULL)
2962         return xstrdup (cur_rev);
2963
2964     /* walk the branches list looking for the branch number */
2965     xbranch = xmalloc (strlen (branch) + 1 + 1); /* +1 for the extra dot */
2966     (void) strcpy (xbranch, branch);
2967     (void) strcat (xbranch, ".");
2968     for (p = vers->branches->list->next; p != vers->branches->list; p = p->next)
2969         if (strncmp (p->key, xbranch, strlen (xbranch)) == 0)
2970             break;
2971     free (xbranch);
2972     if (p == vers->branches->list)
2973     {
2974         /* This is what happens if the branch is a (magic) branch with
2975            no revisions yet.  Similar to the case where vers->branches ==
2976            NULL, except here there was a another branch off the same
2977            branchpoint.  */
2978         return xstrdup (cur_rev);
2979     }
2980
2981     p = findnode (rcs->versions, p->key);
2982
2983     /* walk the next pointers until you find the end, or the date is too late */
2984     while (p != NULL)
2985     {
2986         vers = p->data;
2987         if (RCS_datecmp (vers->date, date) <= 0)
2988             cur_rev = vers->version;
2989         else
2990             break;
2991
2992         /* if there is a next version, find the node */
2993         if (vers->next != NULL)
2994             p = findnode (rcs->versions, vers->next);
2995         else
2996             p = (Node *) NULL;
2997     }
2998
2999     /* Return whatever we found, which may be NULL.  */
3000     return xstrdup (cur_rev);
3001 }
3002
3003
3004
3005 /*
3006  * Compare two dates in RCS format. Beware the change in format on January 1,
3007  * 2000, when years go from 2-digit to full format.
3008  */
3009 int
3010 RCS_datecmp (const char *date1, const char *date2)
3011 {
3012     int length_diff = strlen (date1) - strlen (date2);
3013
3014     return length_diff ? length_diff : strcmp (date1, date2);
3015 }
3016
3017
3018
3019 /* Look up revision REV in RCS and return the date specified for the
3020    revision minus FUDGE seconds (FUDGE will generally be one, so that the
3021    logically previous revision will be found later, or zero, if we want
3022    the exact date).
3023
3024    The return value is the date being returned as a time_t, or (time_t)-1
3025    on error (previously was documented as zero on error; I haven't checked
3026    the callers to make sure that they really check for (time_t)-1, but
3027    the latter is what this function really returns).  If DATE is non-NULL,
3028    then it must point to MAXDATELEN characters, and we store the same
3029    return value there in DATEFORM format.  */
3030 time_t
3031 RCS_getrevtime (RCSNode *rcs, const char *rev, char *date, int fudge)
3032 {
3033     char tdate[MAXDATELEN];
3034     struct tm xtm, *ftm;
3035     time_t revdate = 0;
3036     Node *p;
3037     RCSVers *vers;
3038
3039     /* make sure we have something to look at... */
3040     assert (rcs != NULL);
3041
3042     if (rcs->flags & PARTIAL)
3043         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3044
3045     /* look up the revision */
3046     p = findnode (rcs->versions, rev);
3047     if (p == NULL)
3048         return (-1);
3049     vers = p->data;
3050
3051     /* split up the date */
3052     if (sscanf (vers->date, SDATEFORM, &xtm.tm_year, &xtm.tm_mon,
3053                 &xtm.tm_mday, &xtm.tm_hour, &xtm.tm_min, &xtm.tm_sec) != 6)
3054         error (1, 0, "%s: invalid date for revision %s (%s)", rcs->path,
3055                rev, vers->date);
3056
3057     /* If the year is from 1900 to 1999, RCS files contain only two
3058        digits, and sscanf gives us a year from 0-99.  If the year is
3059        2000+, RCS files contain all four digits and we subtract 1900,
3060        because the tm_year field should contain years since 1900.  */
3061
3062     if (xtm.tm_year >= 100 && xtm.tm_year < 2000)
3063         error (0, 0, "%s: non-standard date format for revision %s (%s)",
3064                rcs->path, rev, vers->date);
3065     if (xtm.tm_year >= 1900)
3066         xtm.tm_year -= 1900;
3067
3068     /* put the date in a form getdate can grok */
3069     (void) sprintf (tdate, "%d/%d/%d GMT %d:%d:%d", xtm.tm_mon,
3070                     xtm.tm_mday, xtm.tm_year + 1900, xtm.tm_hour,
3071                     xtm.tm_min, xtm.tm_sec);
3072
3073     /* turn it into seconds since the epoch */
3074     revdate = get_date (tdate, (struct timeb *) NULL);
3075     if (revdate != (time_t) -1)
3076     {
3077         revdate -= fudge;               /* remove "fudge" seconds */
3078         if (date)
3079         {
3080             /* put an appropriate string into ``date'' if we were given one */
3081             ftm = gmtime (&revdate);
3082             (void) sprintf (date, DATEFORM,
3083                             ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
3084                             ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
3085                             ftm->tm_min, ftm->tm_sec);
3086         }
3087     }
3088     return revdate;
3089 }
3090
3091 List *
3092 RCS_getlocks (RCSNode *rcs)
3093 {
3094     assert(rcs != NULL);
3095
3096     if (rcs->flags & PARTIAL)
3097         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3098
3099     if (rcs->locks_data) {
3100         rcs->locks = getlist ();
3101         do_locks (rcs->locks, rcs->locks_data);
3102         free(rcs->locks_data);
3103         rcs->locks_data = NULL;
3104     }
3105
3106     return rcs->locks;
3107 }
3108
3109 List *
3110 RCS_symbols(RCSNode *rcs)
3111 {
3112     assert(rcs != NULL);
3113
3114     if (rcs->flags & PARTIAL)
3115         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3116
3117     if (rcs->symbols_data) {
3118         rcs->symbols = getlist ();
3119         do_symbols (rcs->symbols, rcs->symbols_data);
3120         free(rcs->symbols_data);
3121         rcs->symbols_data = NULL;
3122     }
3123
3124     return rcs->symbols;
3125 }
3126
3127 /*
3128  * Return the version associated with a particular symbolic tag.
3129  * Returns NULL or a newly malloc'd string.
3130  */
3131 static char *
3132 translate_symtag (RCSNode *rcs, const char *tag)
3133 {
3134     if (rcs->flags & PARTIAL)
3135         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3136
3137     if (rcs->symbols != NULL)
3138     {
3139         Node *p;
3140
3141         /* The symbols have already been converted into a list.  */
3142         p = findnode (rcs->symbols, tag);
3143         if (p == NULL)
3144             return NULL;
3145
3146         return xstrdup (p->data);
3147     }
3148
3149     if (rcs->symbols_data != NULL)
3150     {
3151         size_t len;
3152         char *cp;
3153
3154         /* Look through the RCS symbols information.  This is like
3155            do_symbols, but we don't add the information to a list.  In
3156            most cases, we will only be called once for this file, so
3157            generating the list is unnecessary overhead.  */
3158
3159         len = strlen (tag);
3160         cp = rcs->symbols_data;
3161         while ((cp = strchr (cp, tag[0])) != NULL)
3162         {
3163             if ((cp == rcs->symbols_data || whitespace (cp[-1]))
3164                 && strncmp (cp, tag, len) == 0
3165                 && cp[len] == ':')
3166             {
3167                 char *v, *r;
3168
3169                 /* We found the tag.  Return the version number.  */
3170
3171                 cp += len + 1;
3172                 v = cp;
3173                 while (! whitespace (*cp) && *cp != '\0')
3174                     ++cp;
3175                 r = xmalloc (cp - v + 1);
3176                 strncpy (r, v, cp - v);
3177                 r[cp - v] = '\0';
3178                 return r;
3179             }
3180
3181             while (! whitespace (*cp) && *cp != '\0')
3182                 ++cp;
3183             if (*cp == '\0')
3184                 break;
3185         }
3186     }
3187
3188     return NULL;
3189 }
3190
3191 /*
3192  * The argument ARG is the getopt remainder of the -k option specified on the
3193  * command line.  This function returns malloc'ed space that can be used
3194  * directly in calls to RCS V5, with the -k flag munged correctly.
3195  */
3196 char *
3197 RCS_check_kflag (const char *arg)
3198 {
3199     static const char *const  keyword_usage[] =
3200     {
3201       "%s %s: invalid RCS keyword expansion mode\n",
3202       "Valid expansion modes include:\n",
3203       "   -kkv\tGenerate keywords using the default form.\n",
3204       "   -kkvl\tLike -kkv, except locker's name inserted.\n",
3205       "   -kk\tGenerate only keyword names in keyword strings.\n",
3206       "   -kv\tGenerate only keyword values in keyword strings.\n",
3207       "   -ko\tGenerate the old keyword string (no changes from checked in file).\n",
3208       "   -kb\tGenerate binary file unmodified (merges not allowed) (RCS 5.7).\n",
3209       "(Specify the --help global option for a list of other help options)\n",
3210       NULL,
3211     };
3212     /* Big enough to hold any of the strings from kflags.  */
3213     char karg[10];
3214     char const *const *cpp = NULL;
3215
3216     if (arg)
3217     {
3218         for (cpp = kflags; *cpp != NULL; cpp++)
3219         {
3220             if (STREQ (arg, *cpp))
3221                 break;
3222         }
3223     }
3224
3225     if (arg == NULL || *cpp == NULL)
3226     {
3227         usage (keyword_usage);
3228     }
3229
3230     (void) sprintf (karg, "-k%s", *cpp);
3231     return (xstrdup (karg));
3232 }
3233
3234 /*
3235  * Do some consistency checks on the symbolic tag... These should equate
3236  * pretty close to what RCS checks, though I don't know for certain.
3237  */
3238 void
3239 RCS_check_tag (const char *tag)
3240 {
3241     char *invalid = "$,.:;@";           /* invalid RCS tag characters */
3242     const char *cp;
3243
3244     /*
3245      * The first character must be an alphabetic letter. The remaining
3246      * characters cannot be non-visible graphic characters, and must not be
3247      * in the set of "invalid" RCS identifier characters.
3248      */
3249     if (isalpha ((unsigned char) *tag))
3250     {
3251         for (cp = tag; *cp; cp++)
3252         {
3253             if (!isgraph ((unsigned char) *cp))
3254                 error (1, 0, "tag `%s' has non-visible graphic characters",
3255                        tag);
3256             if (strchr (invalid, *cp))
3257                 error (1, 0, "tag `%s' must not contain the characters `%s'",
3258                        tag, invalid);
3259         }
3260     }
3261     else
3262         error (1, 0, "tag `%s' must start with a letter", tag);
3263 }
3264
3265 /*
3266  * TRUE if argument has valid syntax for an RCS revision or 
3267  * branch number.  All characters must be digits or dots, first 
3268  * and last characters must be digits, and no two consecutive 
3269  * characters may be dots.
3270  *
3271  * Intended for classifying things, so this function doesn't 
3272  * call error.
3273  */
3274 int 
3275 RCS_valid_rev (char *rev)
3276 {
3277    char last, c;
3278    last = *rev++;
3279    if (!isdigit ((unsigned char) last))
3280        return 0;
3281    while ((c = *rev++))   /* Extra parens placate -Wall gcc option */
3282    {
3283        if (c == '.')
3284        {
3285            if (last == '.')
3286                return 0;
3287            continue;
3288        }
3289        last = c;
3290        if (!isdigit ((unsigned char) c))
3291            return 0;
3292    }
3293    if (!isdigit ((unsigned char) last))
3294        return 0;
3295    return 1;
3296 }
3297
3298 /*
3299  * Return true if RCS revision with TAG is a dead revision.
3300  */
3301 int
3302 RCS_isdead (RCSNode *rcs, const char *tag)
3303 {
3304     Node *p;
3305     RCSVers *version;
3306
3307     if (rcs->flags & PARTIAL)
3308         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
3309
3310     p = findnode (rcs->versions, tag);
3311     if (p == NULL)
3312         return (0);
3313
3314     version = p->data;
3315     return (version->dead);
3316 }
3317
3318 /* Return the RCS keyword expansion mode.  For example "b" for binary.
3319    Returns a pointer into storage which is allocated and freed along with
3320    the rest of the RCS information; the caller should not modify this
3321    storage.  Returns NULL if the RCS file does not specify a keyword
3322    expansion mode; for all other errors, die with a fatal error.  */
3323 char *
3324 RCS_getexpand (RCSNode *rcs)
3325 {
3326     /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3327        about RCS_reparsercsfile.  */
3328     assert (rcs != NULL);
3329     return rcs->expand;
3330 }
3331
3332
3333
3334 /* Set keyword expansion mode to EXPAND.  For example "b" for binary.  */
3335 void
3336 RCS_setexpand (RCSNode *rcs, const char *expand)
3337 {
3338     /* Since RCS_parsercsfile_i now reads expand, don't need to worry
3339        about RCS_reparsercsfile.  */
3340     assert (rcs != NULL);
3341     if (rcs->expand != NULL)
3342         free (rcs->expand);
3343     rcs->expand = xstrdup (expand);
3344 }
3345
3346
3347
3348 /* RCS keywords, and a matching enum.  */
3349 struct rcs_keyword
3350 {
3351     const char *string;
3352     size_t len;
3353     int expandit;
3354 };
3355 #define KEYWORD_INIT(s) (s), sizeof (s) - 1
3356 static struct rcs_keyword keywords[] =
3357 {
3358     { KEYWORD_INIT ("Author"), 1 },
3359     { KEYWORD_INIT ("Date"), 1 },
3360     { KEYWORD_INIT ("CVSHeader"), 1 },
3361     { KEYWORD_INIT ("Header"), 1 },
3362     { KEYWORD_INIT ("Id"), 1 },
3363     { KEYWORD_INIT ("Locker"), 1 },
3364     { KEYWORD_INIT ("Log"), 1 },
3365     { KEYWORD_INIT ("Name"), 1 },
3366     { KEYWORD_INIT ("RCSfile"), 1 },
3367     { KEYWORD_INIT ("Revision"), 1 },
3368     { KEYWORD_INIT ("Source"), 1 },
3369     { KEYWORD_INIT ("State"), 1 },
3370     { NULL, 0, 0 },             /* localid */
3371     { NULL, 0, 0 }
3372 };
3373 enum keyword
3374 {
3375     KEYWORD_AUTHOR = 0,
3376     KEYWORD_DATE,
3377     KEYWORD_CVSHEADER,
3378     KEYWORD_HEADER,
3379     KEYWORD_ID,
3380     KEYWORD_LOCKER,
3381     KEYWORD_LOG,
3382     KEYWORD_NAME,
3383     KEYWORD_RCSFILE,
3384     KEYWORD_REVISION,
3385     KEYWORD_SOURCE,
3386     KEYWORD_STATE,
3387     KEYWORD_LOCALID
3388 };
3389 enum keyword keyword_local = KEYWORD_ID;
3390
3391 /* Convert an RCS date string into a readable string.  This is like
3392    the RCS date2str function.  */
3393
3394 static char *
3395 printable_date (const char *rcs_date)
3396 {
3397     int year, mon, mday, hour, min, sec;
3398     char buf[100];
3399
3400     (void) sscanf (rcs_date, SDATEFORM, &year, &mon, &mday, &hour, &min,
3401                    &sec);
3402     if (year < 1900)
3403         year += 1900;
3404     sprintf (buf, "%04d/%02d/%02d %02d:%02d:%02d", year, mon, mday,
3405              hour, min, sec);
3406     return xstrdup (buf);
3407 }
3408
3409 /* Escape the characters in a string so that it can be included in an
3410    RCS value.  */
3411
3412 static char *
3413 escape_keyword_value (const char *value, int *free_value)
3414 {
3415     char *ret, *t;
3416     const char *s;
3417
3418     for (s = value; *s != '\0'; s++)
3419     {
3420         char c;
3421
3422         c = *s;
3423         if (c == '\t'
3424             || c == '\n'
3425             || c == '\\'
3426             || c == ' '
3427             || c == '$')
3428         {
3429             break;
3430         }
3431     }
3432
3433     if (*s == '\0')
3434     {
3435         *free_value = 0;
3436         return (char *) value;
3437     }
3438
3439     ret = xmalloc (strlen (value) * 4 + 1);
3440     *free_value = 1;
3441
3442     for (s = value, t = ret; *s != '\0'; s++, t++)
3443     {
3444         switch (*s)
3445         {
3446         default:
3447             *t = *s;
3448             break;
3449         case '\t':
3450             *t++ = '\\';
3451             *t = 't';
3452             break;
3453         case '\n':
3454             *t++ = '\\';
3455             *t = 'n';
3456             break;
3457         case '\\':
3458             *t++ = '\\';
3459             *t = '\\';
3460             break;
3461         case ' ':
3462             *t++ = '\\';
3463             *t++ = '0';
3464             *t++ = '4';
3465             *t = '0';
3466             break;
3467         case '$':
3468             *t++ = '\\';
3469             *t++ = '0';
3470             *t++ = '4';
3471             *t = '4';
3472             break;
3473         }
3474     }
3475
3476     *t = '\0';
3477
3478     return ret;
3479 }
3480
3481 /* Expand RCS keywords in the memory buffer BUF of length LEN.  This
3482    applies to file RCS and version VERS.  If NAME is not NULL, and is
3483    not a numeric revision, then it is the symbolic tag used for the
3484    checkout.  EXPAND indicates how to expand the keywords.  This
3485    function sets *RETBUF and *RETLEN to the new buffer and length.
3486    This function may modify the buffer BUF.  If BUF != *RETBUF, then
3487    RETBUF is a newly allocated buffer.  */
3488
3489 static void
3490 expand_keywords (RCSNode *rcs, RCSVers *ver, const char *name, const char *log, size_t loglen, enum kflag expand, char *buf, size_t len, char **retbuf, size_t *retlen)
3491 {
3492     struct expand_buffer
3493     {
3494         struct expand_buffer *next;
3495         char *data;
3496         size_t len;
3497         int free_data;
3498     } *ebufs = NULL;
3499     struct expand_buffer *ebuf_last = NULL;
3500     size_t ebuf_len = 0;
3501     char *locker;
3502     char *srch, *srch_next;
3503     size_t srch_len;
3504
3505     if (expand == KFLAG_O || expand == KFLAG_B)
3506     {
3507         *retbuf = buf;
3508         *retlen = len;
3509         return;
3510     }
3511
3512     /* If we are using -kkvl, dig out the locker information if any.  */
3513     locker = NULL;
3514     if (expand == KFLAG_KVL)
3515     {
3516         Node *lock;
3517         lock = findnode (RCS_getlocks(rcs), ver->version);
3518         if (lock != NULL)
3519             locker = xstrdup (lock->data);
3520     }
3521
3522     /* RCS keywords look like $STRING$ or $STRING: VALUE$.  */
3523     srch = buf;
3524     srch_len = len;
3525     while ((srch_next = memchr (srch, '$', srch_len)) != NULL)
3526     {
3527         char *s, *send;
3528         size_t slen;
3529         const struct rcs_keyword *keyword;
3530         enum keyword kw;
3531         char *value;
3532         int free_value;
3533         char *sub;
3534         size_t sublen;
3535
3536         srch_len -= (srch_next + 1) - srch;
3537         srch = srch_next + 1;
3538
3539         /* Look for the first non alphabetic character after the '$'.  */
3540         send = srch + srch_len;
3541         for (s = srch; s < send; s++)
3542             if (! isalpha ((unsigned char) *s))
3543                 break;
3544
3545         /* If the first non alphabetic character is not '$' or ':',
3546            then this is not an RCS keyword.  */
3547         if (s == send || (*s != '$' && *s != ':'))
3548             continue;
3549
3550         /* See if this is one of the keywords.  */
3551         slen = s - srch;
3552         for (keyword = keywords; keyword->string != NULL; keyword++)
3553         {
3554             if (keyword->expandit
3555                 && keyword->len == slen
3556                 && strncmp (keyword->string, srch, slen) == 0)
3557             {
3558                 break;
3559             }
3560         }
3561         if (keyword->string == NULL)
3562             continue;
3563
3564         kw = (enum keyword) (keyword - keywords);
3565
3566         /* If the keyword ends with a ':', then the old value consists
3567            of the characters up to the next '$'.  If there is no '$'
3568            before the end of the line, though, then this wasn't an RCS
3569            keyword after all.  */
3570         if (*s == ':')
3571         {
3572             for (; s < send; s++)
3573                 if (*s == '$' || *s == '\n')
3574                     break;
3575             if (s == send || *s != '$')
3576                 continue;
3577         }
3578
3579         /* At this point we must replace the string from SRCH to S
3580            with the expansion of the keyword KW.  */
3581
3582         /* Get the value to use.  */
3583         free_value = 0;
3584         if (expand == KFLAG_K)
3585             value = NULL;
3586         else
3587         {
3588             switch (kw)
3589             {
3590             default:
3591                 abort ();
3592
3593             case KEYWORD_AUTHOR:
3594                 value = ver->author;
3595                 break;
3596
3597             case KEYWORD_DATE:
3598                 value = printable_date (ver->date);
3599                 free_value = 1;
3600                 break;
3601
3602             case KEYWORD_CVSHEADER:
3603             case KEYWORD_HEADER:
3604             case KEYWORD_ID:
3605             case KEYWORD_LOCALID:
3606                 {
3607                     const char *path;
3608                     int free_path;
3609                     char *date;
3610                     char *old_path;
3611
3612                     old_path = NULL;
3613                     if (kw == KEYWORD_HEADER ||
3614                             (kw == KEYWORD_LOCALID &&
3615                              keyword_local == KEYWORD_HEADER))
3616                         path = rcs->path;
3617                     else if (kw == KEYWORD_CVSHEADER ||
3618                              (kw == KEYWORD_LOCALID &&
3619                               keyword_local == KEYWORD_CVSHEADER))
3620                         path = getfullCVSname(rcs->path, &old_path);
3621                     else
3622                         path = last_component (rcs->path);
3623                     path = escape_keyword_value (path, &free_path);
3624                     date = printable_date (ver->date);
3625                     value = xmalloc (strlen (path)
3626                                      + strlen (ver->version)
3627                                      + strlen (date)
3628                                      + strlen (ver->author)
3629                                      + strlen (ver->state)
3630                                      + (locker == NULL ? 0 : strlen (locker))
3631                                      + 20);
3632
3633                     sprintf (value, "%s %s %s %s %s%s%s",
3634                              path, ver->version, date, ver->author,
3635                              ver->state,
3636                              locker != NULL ? " " : "",
3637                              locker != NULL ? locker : "");
3638                     if (free_path)
3639                         /* If free_path is set then we know we allocated path
3640                          * and we can discard the const.
3641                          */
3642                         free ((char *)path);
3643                     if (old_path)
3644                         free (old_path);
3645                     free (date);
3646                     free_value = 1;
3647                 }
3648                 break;
3649
3650             case KEYWORD_LOCKER:
3651                 value = locker;
3652                 break;
3653
3654             case KEYWORD_LOG:
3655             case KEYWORD_RCSFILE:
3656                 value = escape_keyword_value (last_component (rcs->path),
3657                                               &free_value);
3658                 break;
3659
3660             case KEYWORD_NAME:
3661                 if (name != NULL && ! isdigit ((unsigned char) *name))
3662                     value = (char *) name;
3663                 else
3664                     value = NULL;
3665                 break;
3666
3667             case KEYWORD_REVISION:
3668                 value = ver->version;
3669                 break;
3670
3671             case KEYWORD_SOURCE:
3672                 value = escape_keyword_value (rcs->path, &free_value);
3673                 break;
3674
3675             case KEYWORD_STATE:
3676                 value = ver->state;
3677                 break;
3678             }
3679         }
3680
3681         sub = xmalloc (keyword->len
3682                        + (value == NULL ? 0 : strlen (value))
3683                        + 10);
3684         if (expand == KFLAG_V)
3685         {
3686             /* Decrement SRCH and increment S to remove the $
3687                characters.  */
3688             --srch;
3689             ++srch_len;
3690             ++s;
3691             sublen = 0;
3692         }
3693         else
3694         {
3695             strcpy (sub, keyword->string);
3696             sublen = strlen (keyword->string);
3697             if (expand != KFLAG_K)
3698             {
3699                 sub[sublen] = ':';
3700                 sub[sublen + 1] = ' ';
3701                 sublen += 2;
3702             }
3703         }
3704         if (value != NULL)
3705         {
3706             strcpy (sub + sublen, value);
3707             sublen += strlen (value);
3708         }
3709         if (expand != KFLAG_V && expand != KFLAG_K)
3710         {
3711             sub[sublen] = ' ';
3712             ++sublen;
3713             sub[sublen] = '\0';
3714         }
3715
3716         if (free_value)
3717             free (value);
3718
3719         /* The Log keyword requires special handling.  This behaviour
3720            is taken from RCS 5.7.  The special log message is what RCS
3721            uses for ci -k.  */
3722         if (kw == KEYWORD_LOG
3723             && (sizeof "checked in with -k by " <= loglen
3724                 || log == NULL
3725                 || strncmp (log, "checked in with -k by ",
3726                             sizeof "checked in with -k by " - 1) != 0))
3727         {
3728             char *start;
3729             char *leader;
3730             size_t leader_len, leader_sp_len;
3731             const char *logend;
3732             const char *snl;
3733             int cnl;
3734             char *date;
3735             const char *sl;
3736
3737             /* We are going to insert the trailing $ ourselves, before
3738                the log message, so we must remove it from S, if we
3739                haven't done so already.  */
3740             if (expand != KFLAG_V)
3741                 ++s;
3742
3743             /* CVS never has empty log messages, but old RCS files might.  */
3744             if (log == NULL)
3745                 log = "";
3746
3747             /* Find the start of the line.  */
3748             start = srch;
3749             while (start > buf && start[-1] != '\n')
3750                 --start;
3751
3752             /* Copy the start of the line to use as a comment leader.  */
3753             leader_len = srch - start;
3754             if (expand != KFLAG_V)
3755                 --leader_len;
3756             leader = xmalloc (leader_len);
3757             memcpy (leader, start, leader_len);
3758             leader_sp_len = leader_len;
3759             while (leader_sp_len > 0 && leader[leader_sp_len - 1] == ' ')
3760                 --leader_sp_len;
3761
3762             /* RCS does some checking for an old style of Log here,
3763                but we don't bother.  RCS issues a warning if it
3764                changes anything.  */
3765
3766             /* Count the number of newlines in the log message so that
3767                we know how many copies of the leader we will need.  */
3768             cnl = 0;
3769             logend = log + loglen;
3770             for (snl = log; snl < logend; snl++)
3771                 if (*snl == '\n')
3772                     ++cnl;
3773
3774             date = printable_date (ver->date);
3775             sub = xrealloc (sub,
3776                             (sublen
3777                              + sizeof "Revision"
3778                              + strlen (ver->version)
3779                              + strlen (date)
3780                              + strlen (ver->author)
3781                              + loglen
3782                              + (cnl + 2) * leader_len
3783                              + 20));
3784             if (expand != KFLAG_V)
3785             {
3786                 sub[sublen] = '$';
3787                 ++sublen;
3788             }
3789             sub[sublen] = '\n';
3790             ++sublen;
3791             memcpy (sub + sublen, leader, leader_len);
3792             sublen += leader_len;
3793             sprintf (sub + sublen, "Revision %s  %s  %s\n",
3794                      ver->version, date, ver->author);
3795             sublen += strlen (sub + sublen);
3796             free (date);
3797
3798             sl = log;
3799             while (sl < logend)
3800             {
3801                 if (*sl == '\n')
3802                 {
3803                     memcpy (sub + sublen, leader, leader_sp_len);
3804                     sublen += leader_sp_len;
3805                     sub[sublen] = '\n';
3806                     ++sublen;
3807                     ++sl;
3808                 }
3809                 else
3810                 {
3811                     const char *slnl;
3812
3813                     memcpy (sub + sublen, leader, leader_len);
3814                     sublen += leader_len;
3815                     for (slnl = sl; slnl < logend && *slnl != '\n'; ++slnl)
3816                         ;
3817                     if (slnl < logend)
3818                         ++slnl;
3819                     memcpy (sub + sublen, sl, slnl - sl);
3820                     sublen += slnl - sl;
3821                     sl = slnl;
3822                 }
3823             }
3824
3825             memcpy (sub + sublen, leader, leader_sp_len);
3826             sublen += leader_sp_len;
3827
3828             free (leader);
3829         }
3830
3831         /* Now SUB contains a string which is to replace the string
3832            from SRCH to S.  SUBLEN is the length of SUB.  */
3833
3834         if (srch + sublen == s)
3835         {
3836             memcpy (srch, sub, sublen);
3837             free (sub);
3838         }
3839         else
3840         {
3841             struct expand_buffer *ebuf;
3842
3843             /* We need to change the size of the buffer.  We build a
3844                list of expand_buffer structures.  Each expand_buffer
3845                structure represents a portion of the final output.  We
3846                concatenate them back into a single buffer when we are
3847                done.  This minimizes the number of potentially large
3848                buffer copies we must do.  */
3849
3850             if (ebufs == NULL)
3851             {
3852                 ebufs = (struct expand_buffer *) xmalloc (sizeof *ebuf);
3853                 ebufs->next = NULL;
3854                 ebufs->data = buf;
3855                 ebufs->free_data = 0;
3856                 ebuf_len = srch - buf;
3857                 ebufs->len = ebuf_len;
3858                 ebuf_last = ebufs;
3859             }
3860             else
3861             {
3862                 assert (srch >= ebuf_last->data);
3863                 assert (srch <= ebuf_last->data + ebuf_last->len);
3864                 ebuf_len -= ebuf_last->len - (srch - ebuf_last->data);
3865                 ebuf_last->len = srch - ebuf_last->data;
3866             }
3867
3868             ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
3869             ebuf->data = sub;
3870             ebuf->len = sublen;
3871             ebuf->free_data = 1;
3872             ebuf->next = NULL;
3873             ebuf_last->next = ebuf;
3874             ebuf_last = ebuf;
3875             ebuf_len += sublen;
3876
3877             ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
3878             ebuf->data = s;
3879             ebuf->len = srch_len - (s - srch);
3880             ebuf->free_data = 0;
3881             ebuf->next = NULL;
3882             ebuf_last->next = ebuf;
3883             ebuf_last = ebuf;
3884             ebuf_len += srch_len - (s - srch);
3885         }
3886
3887         srch_len -= (s - srch);
3888         srch = s;
3889     }
3890
3891     if (locker != NULL)
3892         free (locker);
3893
3894     if (ebufs == NULL)
3895     {
3896         *retbuf = buf;
3897         *retlen = len;
3898     }
3899     else
3900     {
3901         char *ret;
3902
3903         ret = xmalloc (ebuf_len);
3904         *retbuf = ret;
3905         *retlen = ebuf_len;
3906         while (ebufs != NULL)
3907         {
3908             struct expand_buffer *next;
3909
3910             memcpy (ret, ebufs->data, ebufs->len);
3911             ret += ebufs->len;
3912             if (ebufs->free_data)
3913                 free (ebufs->data);
3914             next = ebufs->next;
3915             free (ebufs);
3916             ebufs = next;
3917         }
3918     }
3919 }
3920
3921
3922
3923 /* Check out a revision from an RCS file.
3924
3925    If PFN is not NULL, then ignore WORKFILE and SOUT.  Call PFN zero
3926    or more times with the contents of the file.  CALLERDAT is passed,
3927    uninterpreted, to PFN.  (The current code will always call PFN
3928    exactly once for a non empty file; however, the current code
3929    assumes that it can hold the entire file contents in memory, which
3930    is not a good assumption, and might change in the future).
3931
3932    Otherwise, if WORKFILE is not NULL, check out the revision to
3933    WORKFILE.  However, if WORKFILE is not NULL, and noexec is set,
3934    then don't do anything.
3935
3936    Otherwise, if WORKFILE is NULL, check out the revision to SOUT.  If
3937    SOUT is RUN_TTY, then write the contents of the revision to
3938    standard output.  When using SOUT, the output is generally a
3939    temporary file; don't bother to get the file modes correct.
3940
3941    REV is the numeric revision to check out.  It may be NULL, which
3942    means to check out the head of the default branch.
3943
3944    If NAMETAG is not NULL, and is not a numeric revision, then it is
3945    the tag that should be used when expanding the RCS Name keyword.
3946
3947    OPTIONS is a string such as "-kb" or "-kv" for keyword expansion
3948    options.  It may be NULL to use the default expansion mode of the
3949    file, typically "-kkv".
3950
3951    On an error which prevented checking out the file, either print a
3952    nonfatal error and return 1, or give a fatal error.  On success,
3953    return 0.  */
3954
3955 /* This function mimics the behavior of `rcs co' almost exactly.  The
3956    chief difference is in its support for preserving file ownership,
3957    permissions, and special files across checkin and checkout -- see
3958    comments in RCS_checkin for some issues about this. -twp */
3959
3960 int
3961 RCS_checkout (RCSNode *rcs, const char *workfile, const char *rev,
3962               const char *nametag, const char *options, const char *sout,
3963               RCSCHECKOUTPROC pfn, void *callerdat)
3964 {
3965     int free_rev = 0;
3966     enum kflag expand;
3967     FILE *fp, *ofp;
3968     struct stat sb;
3969     struct rcsbuffer rcsbuf;
3970     char *key;
3971     char *value;
3972     size_t len;
3973     int free_value = 0;
3974     char *log = NULL;
3975     size_t loglen;
3976     Node *vp = NULL;
3977 #ifdef PRESERVE_PERMISSIONS_SUPPORT
3978     uid_t rcs_owner = (uid_t) -1;
3979     gid_t rcs_group = (gid_t) -1;
3980     mode_t rcs_mode;
3981     int change_rcs_owner_or_group = 0;
3982     int change_rcs_mode = 0;
3983     int special_file = 0;
3984     unsigned long devnum_long;
3985     dev_t devnum = 0;
3986 #endif
3987
3988     TRACE ( 1, "RCS_checkout (%s, %s, %s, %s, %s)",
3989             rcs->path,
3990             rev != NULL ? rev : "",
3991             nametag != NULL ? nametag : "",
3992             options != NULL ? options : "",
3993             (pfn != NULL ? "(function)"
3994               : (workfile != NULL ? workfile
3995                   : (sout != RUN_TTY ? sout
3996                       : "(stdout)" ) ) ) );
3997
3998     assert (rev == NULL || isdigit ((unsigned char) *rev));
3999
4000     if (noexec && workfile != NULL)
4001         return 0;
4002
4003     assert (sout == RUN_TTY || workfile == NULL);
4004     assert (pfn == NULL || (sout == RUN_TTY && workfile == NULL));
4005
4006     /* Some callers, such as Checkin or remove_file, will pass us a
4007        branch.  */
4008     if (rev != NULL && (numdots (rev) & 1) == 0)
4009     {
4010         rev = RCS_getbranch (rcs, rev, 1);
4011         if (rev == NULL)
4012             error (1, 0, "internal error: bad branch tag in checkout");
4013         free_rev = 1;
4014     }
4015
4016     if (rev == NULL || STREQ (rev, rcs->head))
4017     {
4018         int gothead;
4019
4020         /* We want the head revision.  Try to read it directly.  */
4021
4022         if (rcs->flags & PARTIAL)
4023             RCS_reparsercsfile (rcs, &fp, &rcsbuf);
4024         else
4025             rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf);
4026
4027         gothead = 0;
4028         if (! rcsbuf_getrevnum (&rcsbuf, &key))
4029             error (1, 0, "unexpected EOF reading %s", rcs->path);
4030         while (rcsbuf_getkey (&rcsbuf, &key, &value))
4031         {
4032             if (STREQ (key, "log"))
4033                 log = rcsbuf_valcopy (&rcsbuf, value, 0, &loglen);
4034             else if (STREQ (key, "text"))
4035             {
4036                 gothead = 1;
4037                 break;
4038             }
4039         }
4040
4041         if (! gothead)
4042         {
4043             error (0, 0, "internal error: cannot find head text");
4044             if (free_rev)
4045                 /* It's okay to discard the const when free_rev is set, because
4046                  * we know we allocated it in this function.
4047                  */
4048                 free ((char *)rev);
4049             return 1;
4050         }
4051
4052         rcsbuf_valpolish (&rcsbuf, value, 0, &len);
4053
4054         if (fstat (fileno (fp), &sb) < 0)
4055             error (1, errno, "cannot fstat %s", rcs->path);
4056
4057         rcsbuf_cache (rcs, &rcsbuf);
4058     }
4059     else
4060     {
4061         struct rcsbuffer *rcsbufp;
4062
4063         /* It isn't the head revision of the trunk.  We'll need to
4064            walk through the deltas.  */
4065
4066         fp = NULL;
4067         if (rcs->flags & PARTIAL)
4068             RCS_reparsercsfile (rcs, &fp, &rcsbuf);
4069
4070         if (fp == NULL)
4071         {
4072             /* If RCS_deltas didn't close the file, we could use fstat
4073                here too.  Probably should change it thusly....  */
4074             if( CVS_STAT( rcs->path, &sb ) < 0 )
4075                 error (1, errno, "cannot stat %s", rcs->path);
4076             rcsbufp = NULL;
4077         }
4078         else
4079         {
4080             if (fstat (fileno (fp), &sb) < 0)
4081                 error (1, errno, "cannot fstat %s", rcs->path);
4082             rcsbufp = &rcsbuf;
4083         }
4084
4085         RCS_deltas (rcs, fp, rcsbufp, rev, RCS_FETCH, &value, &len,
4086                     &log, &loglen);
4087         free_value = 1;
4088     }
4089
4090     /* If OPTIONS is NULL or the empty string, then the old code would
4091        invoke the RCS co program with no -k option, which means that
4092        co would use the string we have stored in rcs->expand.  */
4093     if ((options == NULL || options[0] == '\0') && rcs->expand == NULL)
4094         expand = KFLAG_KV;
4095     else
4096     {
4097         const char *ouroptions;
4098         const char * const *cpp;
4099
4100         if (options != NULL && options[0] != '\0')
4101         {
4102             assert (options[0] == '-' && options[1] == 'k');
4103             ouroptions = options + 2;
4104         }
4105         else
4106             ouroptions = rcs->expand;
4107
4108         for (cpp = kflags; *cpp != NULL; cpp++)
4109             if (STREQ (*cpp, ouroptions))
4110                 break;
4111
4112         if (*cpp != NULL)
4113             expand = (enum kflag) (cpp - kflags);
4114         else
4115         {
4116             error (0, 0,
4117                    "internal error: unsupported substitution string -k%s",
4118                    ouroptions);
4119             expand = KFLAG_KV;
4120         }
4121     }
4122
4123 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4124     /* Handle special files and permissions, if that is desired. */
4125     if (preserve_perms)
4126     {
4127         RCSVers *vers;
4128         Node *info;
4129
4130         vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4131         if (vp == NULL)
4132             error (1, 0, "internal error: no revision information for %s",
4133                    rev == NULL ? rcs->head : rev);
4134         vers = vp->data;
4135
4136         /* First we look for symlinks, which are simplest to handle. */
4137         info = findnode (vers->other_delta, "symlink");
4138         if (info != NULL)
4139         {
4140             char *dest;
4141
4142             if (pfn != NULL || (workfile == NULL && sout == RUN_TTY))
4143                 error (1, 0, "symbolic link %s:%s cannot be piped",
4144                        rcs->path, vers->version);
4145             if (workfile == NULL)
4146                 dest = sout;
4147             else
4148                 dest = workfile;
4149
4150             /* Remove `dest', just in case.  It's okay to get ENOENT here,
4151                since we just want the file not to be there.  (TODO: decide
4152                whether it should be considered an error for `dest' to exist
4153                at this point.  If so, the unlink call should be removed and
4154                `symlink' should signal the error. -twp) */
4155             if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
4156                 error (1, errno, "cannot remove %s", dest);
4157             if (symlink (info->data, dest) < 0)
4158                 error (1, errno, "cannot create symbolic link from %s to %s",
4159                        dest, (char *)info->data);
4160             if (free_value)
4161                 free (value);
4162             if (free_rev)
4163                 /* It's okay to discard the const when free_rev is set, because
4164                  * we know we allocated it in this function.
4165                  */
4166                 free ((char *)rev);
4167             return 0;
4168         }
4169
4170         /* Next, we look at this file's hardlinks field, and see whether
4171            it is linked to any other file that has been checked out.
4172            If so, we don't do anything else -- just link it to that file.
4173
4174            If we are checking out a file to a pipe or temporary storage,
4175            none of this should matter.  Hence the `workfile != NULL'
4176            wrapper around the whole thing. -twp */
4177
4178         if (workfile != NULL)
4179         {
4180             List *links = vers->hardlinks;
4181             if (links != NULL)
4182             {
4183                 Node *uptodate_link;
4184
4185                 /* For each file in the hardlinks field, check to see
4186                    if it exists, and if so, if it has been checked out
4187                    this iteration.  When walklist returns, uptodate_link
4188                    should point to a hardlist node representing a file
4189                    in `links' which has recently been checked out, or
4190                    NULL if no file in `links' has yet been checked out. */
4191
4192                 uptodate_link = NULL;
4193                 (void) walklist (links, find_checkedout_proc, &uptodate_link);
4194                 dellist (&links);
4195
4196                 /* If we've found a file that `workfile' is supposed to be
4197                    linked to, and it has been checked out since CVS was
4198                    invoked, then simply link workfile to that file and return.
4199
4200                    If one of these conditions is not met, then
4201                    workfile is the first one in its hardlink group to
4202                    be checked out, and we must continue with a full
4203                    checkout. */
4204
4205                 if (uptodate_link != NULL)
4206                 {
4207                     struct hardlink_info *hlinfo = uptodate_link->data;
4208
4209                     if (link (uptodate_link->key, workfile) < 0)
4210                         error (1, errno, "cannot link %s to %s",
4211                                workfile, uptodate_link->key);
4212                     hlinfo->checked_out = 1;    /* probably unnecessary */
4213                     if (free_value)
4214                         free (value);
4215                     if (free_rev)
4216                         /* It's okay to discard the const when free_rev is set,
4217                          * because we know we allocated it in this function.
4218                          */
4219                         free ((char *)rev);
4220                     return 0;
4221                 }
4222             }
4223         }
4224
4225         info = findnode (vers->other_delta, "owner");
4226         if (info != NULL)
4227         {
4228             change_rcs_owner_or_group = 1;
4229             rcs_owner = (uid_t) strtoul (info->data, NULL, 10);
4230         }
4231         info = findnode (vers->other_delta, "group");
4232         if (info != NULL)
4233         {
4234             change_rcs_owner_or_group = 1;
4235             rcs_group = (gid_t) strtoul (info->data, NULL, 10);
4236         }
4237         info = findnode (vers->other_delta, "permissions");
4238         if (info != NULL)
4239         {
4240             change_rcs_mode = 1;
4241             rcs_mode = (mode_t) strtoul (info->data, NULL, 8);
4242         }
4243         info = findnode (vers->other_delta, "special");
4244         if (info != NULL)
4245         {
4246             /* If the size of `devtype' changes, fix the sscanf call also */
4247             char devtype[16];
4248
4249             if (sscanf (info->data, "%15s %lu",
4250                         devtype, &devnum_long) < 2)
4251                 error (1, 0, "%s:%s has bad `special' newphrase %s",
4252                        workfile, vers->version, (char *)info->data);
4253             devnum = devnum_long;
4254             if (STREQ (devtype, "character"))
4255                 special_file = S_IFCHR;
4256             else if (STREQ (devtype, "block"))
4257                 special_file = S_IFBLK;
4258             else
4259                 error (0, 0, "%s is a special file of unsupported type `%s'",
4260                        workfile, (char *)info->data);
4261         }
4262     }
4263 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
4264
4265     if (expand != KFLAG_O && expand != KFLAG_B)
4266     {
4267         char *newvalue;
4268
4269         /* Don't fetch the delta node again if we already have it. */
4270         if (vp == NULL)
4271         {
4272             vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
4273             if (vp == NULL)
4274                 error (1, 0, "internal error: no revision information for %s",
4275                        rev == NULL ? rcs->head : rev);
4276         }
4277
4278         expand_keywords (rcs, vp->data, nametag, log, loglen,
4279                          expand, value, len, &newvalue, &len);
4280
4281         if (newvalue != value)
4282         {
4283             if (free_value)
4284                 free (value);
4285             value = newvalue;
4286             free_value = 1;
4287         }
4288     }
4289
4290     if (free_rev)
4291         /* It's okay to discard the const when free_rev is set, because
4292          * we know we allocated it in this function.
4293          */
4294         free ((char *)rev);
4295
4296     if (log != NULL)
4297     {
4298         free (log);
4299         log = NULL;
4300     }
4301
4302     if (pfn != NULL)
4303     {
4304 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4305         if (special_file)
4306             error (1, 0, "special file %s cannot be piped to anything",
4307                    rcs->path);
4308 #endif
4309         /* The PFN interface is very simple to implement right now, as
4310            we always have the entire file in memory.  */
4311         if (len != 0)
4312             pfn (callerdat, value, len);
4313     }
4314 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4315     else if (special_file)
4316     {
4317 # ifdef HAVE_MKNOD
4318         char *dest;
4319
4320         /* Can send either to WORKFILE or to SOUT, as long as SOUT is
4321            not RUN_TTY. */
4322         dest = workfile;
4323         if (dest == NULL)
4324         {
4325             if (sout == RUN_TTY)
4326                 error (1, 0, "special file %s cannot be written to stdout",
4327                        rcs->path);
4328             dest = sout;
4329         }
4330
4331         /* Unlink `dest', just in case.  It's okay if this provokes a
4332            ENOENT error. */
4333         if (CVS_UNLINK (dest) < 0 && existence_error (errno))
4334             error (1, errno, "cannot remove %s", dest);
4335         if (mknod (dest, special_file, devnum) < 0)
4336             error (1, errno, "could not create special file %s",
4337                    dest);
4338 # else
4339         error (1, 0,
4340 "cannot create %s: unable to create special files on this system",
4341 workfile);
4342 # endif
4343     }
4344 #endif
4345     else
4346     {
4347         /* Not a special file: write to WORKFILE or SOUT. */
4348         if (workfile == NULL)
4349         {
4350             if (sout == RUN_TTY)
4351                 ofp = stdout;
4352             else
4353             {
4354                 /* Symbolic links should be removed before replacement, so that
4355                    `fopen' doesn't follow the link and open the wrong file. */
4356                 if (islink (sout))
4357                     if (unlink_file (sout) < 0)
4358                         error (1, errno, "cannot remove %s", sout);
4359                 ofp = CVS_FOPEN (sout, expand == KFLAG_B ? "wb" : "w");
4360                 if (ofp == NULL)
4361                     error (1, errno, "cannot open %s", sout);
4362             }
4363         }
4364         else
4365         {
4366             /* Output is supposed to go to WORKFILE, so we should open that
4367                file.  Symbolic links should be removed first (see above). */
4368             if (islink (workfile))
4369                 if (unlink_file (workfile) < 0)
4370                     error (1, errno, "cannot remove %s", workfile);
4371
4372             ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
4373
4374             /* If the open failed because the existing workfile was not
4375                writable, try to chmod the file and retry the open.  */
4376             if (ofp == NULL && errno == EACCES
4377                 && isfile (workfile) && !iswritable (workfile))
4378             {
4379                 xchmod (workfile, 1);
4380                 ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
4381             }
4382
4383             if (ofp == NULL)
4384             {
4385                 error (0, errno, "cannot open %s", workfile);
4386                 if (free_value)
4387                     free (value);
4388                 return 1;
4389             }
4390         }
4391
4392         if (workfile == NULL && sout == RUN_TTY)
4393         {
4394             if (expand == KFLAG_B)
4395                 cvs_output_binary (value, len);
4396             else
4397             {
4398                 /* cvs_output requires the caller to check for zero
4399                    length.  */
4400                 if (len > 0)
4401                     cvs_output (value, len);
4402             }
4403         }
4404         else
4405         {
4406             /* NT 4.0 is said to have trouble writing 2099999 bytes
4407                (for example) in a single fwrite.  So break it down
4408                (there is no need to be writing that much at once
4409                anyway; it is possible that LARGEST_FWRITE should be
4410                somewhat larger for good performance, but for testing I
4411                want to start with a small value until/unless a bigger
4412                one proves useful).  */
4413 #define LARGEST_FWRITE 8192
4414             size_t nleft = len;
4415             size_t nstep = (len < LARGEST_FWRITE ? len : LARGEST_FWRITE);
4416             char *p = value;
4417
4418             while (nleft > 0)
4419             {
4420                 if (fwrite (p, 1, nstep, ofp) != nstep)
4421                 {
4422                     error (0, errno, "cannot write %s",
4423                            (workfile != NULL
4424                             ? workfile
4425                             : (sout != RUN_TTY ? sout : "stdout")));
4426                     if (free_value)
4427                         free (value);
4428                     return 1;
4429                 }
4430                 p += nstep;
4431                 nleft -= nstep;
4432                 if (nleft < nstep)
4433                     nstep = nleft;
4434             }
4435         }
4436     }
4437
4438     if (free_value)
4439         free (value);
4440
4441     if (workfile != NULL)
4442     {
4443         int ret;
4444
4445 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4446         if (!special_file && fclose (ofp) < 0)
4447         {
4448             error (0, errno, "cannot close %s", workfile);
4449             return 1;
4450         }
4451
4452         if (change_rcs_owner_or_group)
4453         {
4454             if (chown (workfile, rcs_owner, rcs_group) < 0)
4455                 error (0, errno, "could not change owner or group of %s",
4456                        workfile);
4457         }
4458
4459         ret = chmod (workfile,
4460                      change_rcs_mode
4461                      ? rcs_mode
4462                      : sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
4463 #else
4464         if (fclose (ofp) < 0)
4465         {
4466             error (0, errno, "cannot close %s", workfile);
4467             return 1;
4468         }
4469
4470         ret = chmod (workfile,
4471                      sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
4472 #endif
4473         if (ret < 0)
4474         {
4475             error (0, errno, "cannot change mode of file %s",
4476                    workfile);
4477         }
4478     }
4479     else if (sout != RUN_TTY)
4480     {
4481         if (
4482 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4483             !special_file &&
4484 #endif
4485             fclose (ofp) < 0)
4486         {
4487             error (0, errno, "cannot close %s", sout);
4488             return 1;
4489         }
4490     }
4491
4492 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4493     /* If we are in the business of preserving hardlinks, then
4494        mark this file as having been checked out. */
4495     if (preserve_perms && workfile != NULL)
4496         update_hardlink_info (workfile);
4497 #endif
4498
4499     return 0;
4500 }
4501
4502 static RCSVers *RCS_findlock_or_tip (RCSNode *rcs);
4503
4504 /* Find the delta currently locked by the user.  From the `ci' man page:
4505
4506         "If rev is omitted, ci tries to  derive  the  new  revision
4507          number  from  the  caller's  last lock.  If the caller has
4508          locked the tip revision of a branch, the new  revision  is
4509          appended  to  that  branch.   The  new  revision number is
4510          obtained by incrementing the tip revision number.  If  the
4511          caller  locked a non-tip revision, a new branch is started
4512          at that revision by incrementing the highest branch number
4513          at  that  revision.   The default initial branch and level
4514          numbers are 1.
4515
4516          If rev is omitted and the caller has no lock, but owns the
4517          file  and  locking is not set to strict, then the revision
4518          is appended to the default branch (normally the trunk; see
4519          the -b option of rcs(1))."
4520
4521    RCS_findlock_or_tip finds the unique revision locked by the caller
4522    and returns its delta node.  If the caller has not locked any
4523    revisions (and is permitted to commit to an unlocked delta, as
4524    described above), return the tip of the default branch. */
4525
4526 static RCSVers *
4527 RCS_findlock_or_tip (RCSNode *rcs)
4528 {
4529     char *user = getcaller();
4530     Node *lock, *p;
4531     List *locklist;
4532
4533     /* Find unique delta locked by caller. This code is very similar
4534        to the code in RCS_unlock -- perhaps it could be abstracted
4535        into a RCS_findlock function. */
4536     locklist = RCS_getlocks (rcs);
4537     lock = NULL;
4538     for (p = locklist->list->next; p != locklist->list; p = p->next)
4539     {
4540         if (STREQ (p->data, user))
4541         {
4542             if (lock != NULL)
4543             {
4544                 error (0, 0, "\
4545 %s: multiple revisions locked by %s; please specify one", rcs->path, user);
4546                 return NULL;
4547             }
4548             lock = p;
4549         }
4550     }
4551
4552     if (lock != NULL)
4553     {
4554         /* Found an old lock, but check that the revision still exists. */
4555         p = findnode (rcs->versions, lock->key);
4556         if (p == NULL)
4557         {
4558             error (0, 0, "%s: can't unlock nonexistent revision %s",
4559                    rcs->path,
4560                    lock->key);
4561             return NULL;
4562         }
4563         return p->data;
4564     }
4565
4566     /* No existing lock.  The RCS rule is that this is an error unless
4567        locking is nonstrict AND the file is owned by the current
4568        user.  Trying to determine the latter is a portability nightmare
4569        in the face of NT, VMS, AFS, and other systems with non-unix-like
4570        ideas of users and owners.  In the case of CVS, we should never get
4571        here (as long as the traditional behavior of making sure to call
4572        RCS_lock persists).  Anyway, we skip the RCS error checks
4573        and just return the default branch or head.  The reasoning is that
4574        those error checks are to make users lock before a checkin, and we do
4575        that in other ways if at all anyway (e.g. rcslock.pl).  */
4576
4577     p = findnode (rcs->versions, RCS_getbranch (rcs, rcs->branch, 0));
4578     return p->data;
4579 }
4580
4581 /* Revision number string, R, must contain a `.'.
4582    Return a newly-malloc'd copy of the prefix of R up
4583    to but not including the final `.'.  */
4584
4585 static char *
4586 truncate_revnum (const char *r)
4587 {
4588     size_t len;
4589     char *new_r;
4590     char *dot = strrchr (r, '.');
4591
4592     assert (dot);
4593     len = dot - r;
4594     new_r = xmalloc (len + 1);
4595     memcpy (new_r, r, len);
4596     *(new_r + len) = '\0';
4597     return new_r;
4598 }
4599
4600 /* Revision number string, R, must contain a `.'.
4601    R must be writable.  Replace the rightmost `.' in R with
4602    the NUL byte and return a pointer to that NUL byte.  */
4603
4604 static char *
4605 truncate_revnum_in_place (char *r)
4606 {
4607     char *dot = strrchr (r, '.');
4608     assert (dot);
4609     *dot = '\0';
4610     return dot;
4611 }
4612
4613 /* Revision number strings, R and S, must each contain a `.'.
4614    R and S must be writable and must have the same number of dots.
4615    Truncate R and S for the comparison, then restored them to their
4616    original state.
4617    Return the result (see compare_revnums) of comparing R and S
4618    ignoring differences in any component after the rightmost `.'.  */
4619
4620 static int
4621 compare_truncated_revnums (char *r, char *s)
4622 {
4623     char *r_dot = truncate_revnum_in_place (r);
4624     char *s_dot = truncate_revnum_in_place (s);
4625     int cmp;
4626
4627     assert (numdots (r) == numdots (s));
4628
4629     cmp = compare_revnums (r, s);
4630
4631     *r_dot = '.';
4632     *s_dot = '.';
4633
4634     return cmp;
4635 }
4636
4637 /* Return a malloc'd copy of the string representing the highest branch
4638    number on BRANCHNODE.  If there are no branches on BRANCHNODE, return NULL.
4639    FIXME: isn't the max rev always the last one?
4640    If so, we don't even need a loop.  */
4641
4642 static char *max_rev (const RCSVers *);
4643
4644 static char *
4645 max_rev (const RCSVers *branchnode)
4646 {
4647     Node *head;
4648     Node *bp;
4649     char *max;
4650
4651     if (branchnode->branches == NULL)
4652     {
4653         return NULL;
4654     }
4655
4656     max = NULL;
4657     head = branchnode->branches->list;
4658     for (bp = head->next; bp != head; bp = bp->next)
4659     {
4660         if (max == NULL || compare_truncated_revnums (max, bp->key) < 0)
4661         {
4662             max = bp->key;
4663         }
4664     }
4665     assert (max);
4666
4667     return truncate_revnum (max);
4668 }
4669
4670 /* Create BRANCH in RCS's delta tree.  BRANCH may be either a branch
4671    number or a revision number.  In the former case, create the branch
4672    with the specified number; in the latter case, create a new branch
4673    rooted at node BRANCH with a higher branch number than any others.
4674    Return the number of the tip node on the new branch. */
4675
4676 static char *
4677 RCS_addbranch (RCSNode *rcs, const char *branch)
4678 {
4679     char *branchpoint, *newrevnum;
4680     Node *nodep, *bp;
4681     Node *marker;
4682     RCSVers *branchnode;
4683
4684     /* Append to end by default.  */
4685     marker = NULL;
4686
4687     branchpoint = xstrdup (branch);
4688     if ((numdots (branchpoint) & 1) == 0)
4689     {
4690         truncate_revnum_in_place (branchpoint);
4691     }
4692
4693     /* Find the branch rooted at BRANCHPOINT. */
4694     nodep = findnode (rcs->versions, branchpoint);
4695     if (nodep == NULL)
4696     {
4697         error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
4698         free (branchpoint);
4699         return NULL;
4700     }
4701     free (branchpoint);
4702     branchnode = nodep->data;
4703
4704     /* If BRANCH was a full branch number, make sure it is higher than MAX. */
4705     if ((numdots (branch) & 1) == 1)
4706     {
4707         if (branchnode->branches == NULL)
4708         {
4709             /* We have to create the first branch on this node, which means
4710                appending ".2" to the revision number. */
4711             newrevnum = (char *) xmalloc (strlen (branch) + 3);
4712             strcpy (newrevnum, branch);
4713             strcat (newrevnum, ".2");
4714         }
4715         else
4716         {
4717             char *max = max_rev (branchnode);
4718             assert (max);
4719             newrevnum = increment_revnum (max);
4720             free (max);
4721         }
4722     }
4723     else
4724     {
4725         newrevnum = xstrdup (branch);
4726
4727         if (branchnode->branches != NULL)
4728         {
4729             Node *head;
4730             Node *bp;
4731
4732             /* Find the position of this new branch in the sorted list
4733                of branches.  */
4734             head = branchnode->branches->list;
4735             for (bp = head->next; bp != head; bp = bp->next)
4736             {
4737                 char *dot;
4738                 int found_pos;
4739
4740                 /* The existing list must be sorted on increasing revnum.  */
4741                 assert (bp->next == head
4742                         || compare_truncated_revnums (bp->key,
4743                                                       bp->next->key) < 0);
4744                 dot = truncate_revnum_in_place (bp->key);
4745                 found_pos = (compare_revnums (branch, bp->key) < 0);
4746                 *dot = '.';
4747
4748                 if (found_pos)
4749                 {
4750                     break;
4751                 }
4752             }
4753             marker = bp;
4754         }
4755     }
4756
4757     newrevnum = (char *) xrealloc (newrevnum, strlen (newrevnum) + 3);
4758     strcat (newrevnum, ".1");
4759
4760     /* Add this new revision number to BRANCHPOINT's branches list. */
4761     if (branchnode->branches == NULL)
4762         branchnode->branches = getlist();
4763     bp = getnode();
4764     bp->key = xstrdup (newrevnum);
4765
4766     /* Append to the end of the list by default, that is, just before
4767        the header node, `list'.  */
4768     if (marker == NULL)
4769         marker = branchnode->branches->list;
4770
4771     {
4772         int fail;
4773         fail = insert_before (branchnode->branches, marker, bp);
4774         assert (!fail);
4775     }
4776
4777     return newrevnum;
4778 }
4779
4780 /* Check in to RCSFILE with revision REV (which must be greater than
4781    the largest revision) and message MESSAGE (which is checked for
4782    validity).  If FLAGS & RCS_FLAGS_DEAD, check in a dead revision.
4783    If FLAGS & RCS_FLAGS_QUIET, tell ci to be quiet.  If FLAGS &
4784    RCS_FLAGS_MODTIME, use the working file's modification time for the
4785    checkin time.  WORKFILE is the working file to check in from, or
4786    NULL to use the usual RCS rules for deriving it from the RCSFILE.
4787    If FLAGS & RCS_FLAGS_KEEPFILE, don't unlink the working file;
4788    unlinking the working file is standard RCS behavior, but is rarely
4789    appropriate for CVS.
4790
4791    This function should almost exactly mimic the behavior of `rcs ci'.  The
4792    principal point of difference is the support here for preserving file
4793    ownership and permissions in the delta nodes.  This is not a clean
4794    solution -- precisely because it diverges from RCS's behavior -- but
4795    it doesn't seem feasible to do this anywhere else in the code. [-twp]
4796    
4797    Return value is -1 for error (and errno is set to indicate the
4798    error), positive for error (and an error message has been printed),
4799    or zero for success.  */
4800
4801 int
4802 RCS_checkin (RCSNode *rcs, const char *workfile_in, const char *message,
4803              const char *rev, int flags)
4804 {
4805     RCSVers *delta, *commitpt;
4806     Deltatext *dtext;
4807     Node *nodep;
4808     char *tmpfile, *changefile;
4809     char *diffopts;
4810     size_t bufsize;
4811     int status, checkin_quiet;
4812     struct tm *ftm;
4813     time_t modtime;
4814     int adding_branch = 0;
4815     char *workfile = xstrdup (workfile_in);
4816 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4817     struct stat sb;
4818 #endif
4819
4820     commitpt = NULL;
4821
4822     if (rcs->flags & PARTIAL)
4823         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
4824
4825     /* Get basename of working file.  Is there a library function to
4826        do this?  I couldn't find one. -twp */
4827     if (workfile == NULL)
4828     {
4829         char *p;
4830         int extlen = strlen (RCSEXT);
4831         workfile = xstrdup (last_component (rcs->path));
4832         p = workfile + (strlen (workfile) - extlen);
4833         assert (strncmp (p, RCSEXT, extlen) == 0);
4834         *p = '\0';
4835     }
4836
4837     /* If the filename is a symbolic link, follow it and replace it
4838        with the destination of the link.  We need to do this before
4839        calling rcs_internal_lockfile, or else we won't put the lock in
4840        the right place. */
4841     resolve_symlink (&(rcs->path));
4842
4843     checkin_quiet = flags & RCS_FLAGS_QUIET;
4844     if (!(checkin_quiet || really_quiet))
4845     {
4846         cvs_output (rcs->path, 0);
4847         cvs_output ("  <--  ", 7);
4848         cvs_output (workfile, 0);
4849         cvs_output ("\n", 1);
4850     }
4851
4852     /* Create new delta node. */
4853     delta = (RCSVers *) xmalloc (sizeof (RCSVers));
4854     memset (delta, 0, sizeof (RCSVers));
4855     delta->author = xstrdup (getcaller ());
4856     if (flags & RCS_FLAGS_MODTIME)
4857     {
4858         struct stat ws;
4859         if( CVS_STAT( workfile, &ws ) < 0 )
4860         {
4861             error (1, errno, "cannot stat %s", workfile);
4862         }
4863         modtime = ws.st_mtime;
4864     }
4865     else
4866         (void) time (&modtime);
4867     ftm = gmtime (&modtime);
4868     delta->date = (char *) xmalloc (MAXDATELEN);
4869     (void) sprintf (delta->date, DATEFORM,
4870                     ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
4871                     ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
4872                     ftm->tm_min, ftm->tm_sec);
4873     if (flags & RCS_FLAGS_DEAD)
4874     {
4875         delta->state = xstrdup (RCSDEAD);
4876         delta->dead = 1;
4877     }
4878     else
4879         delta->state = xstrdup ("Exp");
4880
4881 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4882     /* If permissions should be preserved on this project, then
4883        save the permission info. */
4884     if (preserve_perms)
4885     {
4886         Node *np;
4887         char buf[64];   /* static buffer should be safe: see usage. -twp */
4888
4889         delta->other_delta = getlist();
4890
4891         if (CVS_LSTAT (workfile, &sb) < 0)
4892             error (1, errno, "cannot lstat %s", workfile);
4893
4894         if (S_ISLNK (sb.st_mode))
4895         {
4896             np = getnode();
4897             np->type = RCSFIELD;
4898             np->key = xstrdup ("symlink");
4899             np->data = xreadlink (workfile);
4900             addnode (delta->other_delta, np);
4901         }
4902         else
4903         {
4904             (void) sprintf (buf, "%u", sb.st_uid);
4905             np = getnode();
4906             np->type = RCSFIELD;
4907             np->key = xstrdup ("owner");
4908             np->data = xstrdup (buf);
4909             addnode (delta->other_delta, np);
4910
4911             (void) sprintf (buf, "%u", sb.st_gid);
4912             np = getnode();
4913             np->type = RCSFIELD;
4914             np->key = xstrdup ("group");
4915             np->data = xstrdup (buf);
4916             addnode (delta->other_delta, np);
4917             
4918             (void) sprintf (buf, "%o", sb.st_mode & 07777);
4919             np = getnode();
4920             np->type = RCSFIELD;
4921             np->key = xstrdup ("permissions");
4922             np->data = xstrdup (buf);
4923             addnode (delta->other_delta, np);
4924
4925             /* Save device number. */
4926             switch (sb.st_mode & S_IFMT)
4927             {
4928                 case S_IFREG: break;
4929                 case S_IFCHR:
4930                 case S_IFBLK:
4931 # ifdef HAVE_STRUCT_STAT_ST_RDEV
4932                     np = getnode();
4933                     np->type = RCSFIELD;
4934                     np->key = xstrdup ("special");
4935                     sprintf (buf, "%s %lu",
4936                              ((sb.st_mode & S_IFMT) == S_IFCHR
4937                               ? "character" : "block"),
4938                              (unsigned long) sb.st_rdev);
4939                     np->data = xstrdup (buf);
4940                     addnode (delta->other_delta, np);
4941 # else
4942                     error (0, 0,
4943 "can't preserve %s: unable to save device files on this system",
4944 workfile);
4945 # endif
4946                     break;
4947
4948                 default:
4949                     error (0, 0, "special file %s has unknown type", workfile);
4950             }
4951
4952             /* Save hardlinks. */
4953             delta->hardlinks = list_linked_files_on_disk (workfile);
4954         }
4955     }
4956 #endif
4957
4958     /* Create a new deltatext node. */
4959     dtext = (Deltatext *) xmalloc (sizeof (Deltatext));
4960     memset (dtext, 0, sizeof (Deltatext));
4961
4962     dtext->log = make_message_rcsvalid (message);
4963
4964     /* If the delta tree is empty, then there's nothing to link the
4965        new delta into.  So make a new delta tree, snarf the working
4966        file contents, and just write the new RCS file. */
4967     if (rcs->head == NULL)
4968     {
4969         char *newrev;
4970         FILE *fout;
4971
4972         /* Figure out what the first revision number should be. */
4973         if (rev == NULL || *rev == '\0')
4974             newrev = xstrdup ("1.1");
4975         else if (numdots (rev) == 0)
4976         {
4977             newrev = (char *) xmalloc (strlen (rev) + 3);
4978             strcpy (newrev, rev);
4979             strcat (newrev, ".1");
4980         }
4981         else
4982             newrev = xstrdup (rev);
4983
4984         /* Don't need to xstrdup NEWREV because it's already dynamic, and
4985            not used for anything else.  (Don't need to free it, either.) */
4986         rcs->head = newrev;
4987         delta->version = xstrdup (newrev);
4988         nodep = getnode();
4989         nodep->type = RCSVERS;
4990         nodep->delproc = rcsvers_delproc;
4991         nodep->data = delta;
4992         nodep->key = delta->version;
4993         (void) addnode (rcs->versions, nodep);
4994
4995         dtext->version = xstrdup (newrev);
4996         bufsize = 0;
4997 #ifdef PRESERVE_PERMISSIONS_SUPPORT
4998         if (preserve_perms && !S_ISREG (sb.st_mode))
4999             /* Pretend file is empty.  */
5000             bufsize = 0;
5001         else
5002 #endif
5003         get_file (workfile, workfile,
5004                   rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5005                   &dtext->text, &bufsize, &dtext->len);
5006
5007         if (!(checkin_quiet || really_quiet))
5008         {
5009             cvs_output ("initial revision: ", 0);
5010             cvs_output (rcs->head, 0);
5011             cvs_output ("\n", 1);
5012         }
5013
5014         /* We are probably about to invalidate any cached file.  */
5015         rcsbuf_cache_close ();
5016
5017         fout = rcs_internal_lockfile (rcs->path);
5018         RCS_putadmin (rcs, fout);
5019         RCS_putdtree (rcs, rcs->head, fout);
5020         RCS_putdesc (rcs, fout);
5021         rcs->delta_pos = ftello (fout);
5022         if (rcs->delta_pos == -1)
5023             error (1, errno, "cannot ftello for %s", rcs->path);
5024         putdeltatext (fout, dtext);
5025         rcs_internal_unlockfile (fout, rcs->path);
5026
5027         if ((flags & RCS_FLAGS_KEEPFILE) == 0)
5028         {
5029             if (unlink_file (workfile) < 0)
5030                 /* FIXME-update-dir: message does not include update_dir.  */
5031                 error (0, errno, "cannot remove %s", workfile);
5032         }
5033
5034         status = 0;
5035         goto checkin_done;
5036     }
5037
5038     /* Derive a new revision number.  From the `ci' man page:
5039
5040          "If rev  is  a revision number, it must be higher than the
5041          latest one on the branch to which  rev  belongs,  or  must
5042          start a new branch.
5043
5044          If  rev is a branch rather than a revision number, the new
5045          revision is appended to that branch.  The level number  is
5046          obtained  by  incrementing the tip revision number of that
5047          branch.  If rev  indicates  a  non-existing  branch,  that
5048          branch  is  created  with  the  initial  revision numbered
5049          rev.1."
5050
5051        RCS_findlock_or_tip handles the case where REV is omitted.
5052        RCS 5.7 also permits REV to be "$" or to begin with a dot, but
5053        we do not address those cases -- every routine that calls
5054        RCS_checkin passes it a numeric revision. */
5055
5056     if (rev == NULL || *rev == '\0')
5057     {
5058         /* Figure out where the commit point is by looking for locks.
5059            If the commit point is at the tip of a branch (or is the
5060            head of the delta tree), then increment its revision number
5061            to obtain the new revnum.  Otherwise, start a new
5062            branch. */
5063         commitpt = RCS_findlock_or_tip (rcs);
5064         if (commitpt == NULL)
5065         {
5066             status = 1;
5067             goto checkin_done;
5068         }
5069         else if (commitpt->next == NULL
5070                  || STREQ (commitpt->version, rcs->head))
5071             delta->version = increment_revnum (commitpt->version);
5072         else
5073             delta->version = RCS_addbranch (rcs, commitpt->version);
5074     }
5075     else
5076     {
5077         /* REV is either a revision number or a branch number.  Find the
5078            tip of the target branch. */
5079         char *branch, *tip, *newrev, *p;
5080         int dots, isrevnum;
5081
5082         assert (isdigit ((unsigned char) *rev));
5083
5084         newrev = xstrdup (rev);
5085         dots = numdots (newrev);
5086         isrevnum = dots & 1;
5087
5088         branch = xstrdup (rev);
5089         if (isrevnum)
5090         {
5091             p = strrchr (branch, '.');
5092             *p = '\0';
5093         }
5094
5095         /* Find the tip of the target branch.  If we got a one- or two-digit
5096            revision number, this will be the head of the tree.  Exception:
5097            if rev is a single-field revision equal to the branch number of
5098            the trunk (usually "1") then we want to treat it like an ordinary
5099            branch revision. */
5100         if (dots == 0)
5101         {
5102             tip = xstrdup (rcs->head);
5103             if (atoi (tip) != atoi (branch))
5104             {
5105                 newrev = (char *) xrealloc (newrev, strlen (newrev) + 3);
5106                 strcat (newrev, ".1");
5107                 dots = isrevnum = 1;
5108             }
5109         }
5110         else if (dots == 1)
5111             tip = xstrdup (rcs->head);
5112         else
5113             tip = RCS_getbranch (rcs, branch, 1);
5114
5115         /* If the branch does not exist, and we were supplied an exact
5116            revision number, signal an error.  Otherwise, if we were
5117            given only a branch number, create it and set COMMITPT to
5118            the branch point. */
5119         if (tip == NULL)
5120         {
5121             if (isrevnum)
5122             {
5123                 error (0, 0, "%s: can't find branch point %s",
5124                        rcs->path, branch);
5125                 free (branch);
5126                 free (newrev);
5127                 status = 1;
5128                 goto checkin_done;
5129             }
5130             delta->version = RCS_addbranch (rcs, branch);
5131             if (!delta->version)
5132             {
5133                 free (branch);
5134                 free (newrev);
5135                 status = 1;
5136                 goto checkin_done;
5137             }
5138             adding_branch = 1;
5139             p = strrchr (branch, '.');
5140             *p = '\0';
5141             tip = xstrdup (branch);
5142         }
5143         else
5144         {
5145             if (isrevnum)
5146             {
5147                 /* NEWREV must be higher than TIP. */
5148                 if (compare_revnums (tip, newrev) >= 0)
5149                 {
5150                     error (0, 0,
5151                            "%s: revision %s too low; must be higher than %s",
5152                            rcs->path,
5153                            newrev, tip);
5154                     free (branch);
5155                     free (newrev);
5156                     free (tip);
5157                     status = 1;
5158                     goto checkin_done;
5159                 }
5160                 delta->version = xstrdup (newrev);
5161             }
5162             else
5163                 /* Just increment the tip number to get the new revision. */
5164                 delta->version = increment_revnum (tip);
5165         }
5166
5167         nodep = findnode (rcs->versions, tip);
5168         commitpt = nodep->data;
5169
5170         free (branch);
5171         free (newrev);
5172         free (tip);
5173     }
5174
5175     assert (delta->version != NULL);
5176
5177     /* If COMMITPT is locked by us, break the lock.  If it's locked
5178        by someone else, signal an error. */
5179     nodep = findnode (RCS_getlocks (rcs), commitpt->version);
5180     if (nodep != NULL)
5181     {
5182         if (! STREQ (nodep->data, delta->author))
5183         {
5184             /* If we are adding a branch, then leave the old lock around.
5185                That is sensible in the sense that when adding a branch,
5186                we don't need to use the lock to tell us where to check
5187                in.  It is fishy in the sense that if it is our own lock,
5188                we break it.  However, this is the RCS 5.7 behavior (at
5189                the end of addbranch in ci.c in RCS 5.7, it calls
5190                removelock only if it is our own lock, not someone
5191                else's).  */
5192
5193             if (!adding_branch)
5194             {
5195                 error (0, 0, "%s: revision %s locked by %s",
5196                        rcs->path,
5197                        nodep->key, (char *)nodep->data);
5198                 status = 1;
5199                 goto checkin_done;
5200             }
5201         }
5202         else
5203             delnode (nodep);
5204     }
5205
5206     dtext->version = xstrdup (delta->version);
5207
5208     /* Obtain the change text for the new delta.  If DELTA is to be the
5209        new head of the tree, then its change text should be the contents
5210        of the working file, and LEAFNODE's change text should be a diff.
5211        Else, DELTA's change text should be a diff between LEAFNODE and
5212        the working file. */
5213
5214     tmpfile = cvs_temp_name();
5215     status = RCS_checkout (rcs, NULL, commitpt->version, NULL,
5216                            ((rcs->expand != NULL
5217                              && STREQ (rcs->expand, "b"))
5218                             ? "-kb"
5219                             : "-ko"),
5220                            tmpfile,
5221                            (RCSCHECKOUTPROC)0, NULL);
5222     if (status != 0)
5223         error (1, 0,
5224                "could not check out revision %s of `%s'",
5225                commitpt->version, rcs->path);
5226
5227     bufsize = 0;
5228     changefile = cvs_temp_name();
5229
5230     /* Diff options should include --binary if the RCS file has -kb set
5231        in its `expand' field. */
5232     diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
5233                 ? "-a -n --binary"
5234                 : "-a -n");
5235
5236     if (STREQ (commitpt->version, rcs->head) &&
5237         numdots (delta->version) == 1)
5238     {
5239         /* If this revision is being inserted on the trunk, the change text
5240            for the new delta should be the contents of the working file ... */
5241         bufsize = 0;
5242 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5243         if (preserve_perms && !S_ISREG (sb.st_mode))
5244             /* Pretend file is empty.  */
5245             ;
5246         else
5247 #endif
5248         get_file (workfile, workfile,
5249                   rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5250                   &dtext->text, &bufsize, &dtext->len);
5251
5252         /* ... and the change text for the old delta should be a diff. */
5253         commitpt->text = (Deltatext *) xmalloc (sizeof (Deltatext));
5254         memset (commitpt->text, 0, sizeof (Deltatext));
5255
5256         bufsize = 0;
5257         switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
5258         {
5259             case 0:
5260             case 1:
5261                 break;
5262             case -1:
5263                 /* FIXME-update-dir: message does not include update_dir.  */
5264                 error (1, errno, "error diffing %s", workfile);
5265                 break;
5266             default:
5267                 /* FIXME-update-dir: message does not include update_dir.  */
5268                 error (1, 0, "error diffing %s", workfile);
5269                 break;
5270         }
5271
5272         /* OK, the text file case here is really dumb.  Logically
5273            speaking we want diff to read the files in text mode,
5274            convert them to the canonical form found in RCS files
5275            (which, we hope at least, is independent of OS--always
5276            bare linefeeds), and then work with change texts in that
5277            format.  However, diff_exec both generates change
5278            texts and produces output for user purposes (e.g. patch.c),
5279            and there is no way to distinguish between the two cases.
5280            So we actually implement the text file case by writing the
5281            change text as a text file, then reading it as a text file.
5282            This should cause no harm, but doesn't strike me as
5283            immensely clean.  */
5284         get_file (changefile, changefile,
5285                   rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5286                   &commitpt->text->text, &bufsize, &commitpt->text->len);
5287
5288         /* If COMMITPT->TEXT->TEXT is NULL, it means that CHANGEFILE
5289            was empty and that there are no differences between revisions.
5290            In that event, we want to force RCS_rewrite to write an empty
5291            string for COMMITPT's change text.  Leaving the change text
5292            field set NULL won't work, since that means "preserve the original
5293            change text for this delta." */
5294         if (commitpt->text->text == NULL)
5295         {
5296             commitpt->text->text = xstrdup ("");
5297             commitpt->text->len = 0;
5298         }
5299     }
5300     else
5301     {
5302         /* This file is not being inserted at the head, but on a side
5303            branch somewhere.  Make a diff from the previous revision
5304            to the working file. */
5305         switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
5306         {
5307             case 0:
5308             case 1:
5309                 break;
5310             case -1:
5311                 /* FIXME-update-dir: message does not include update_dir.  */
5312                 error (1, errno, "error diffing %s", workfile);
5313                 break;
5314             default:
5315                 /* FIXME-update-dir: message does not include update_dir.  */
5316                 error (1, 0, "error diffing %s", workfile);
5317                 break;
5318         }
5319         /* See the comment above, at the other get_file invocation,
5320            regarding binary vs. text.  */
5321         get_file (changefile, changefile, 
5322                   rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
5323                   &dtext->text, &bufsize,
5324                   &dtext->len);
5325         if (dtext->text == NULL)
5326         {
5327             dtext->text = xstrdup ("");
5328             dtext->len = 0;
5329         }
5330     }
5331
5332     /* Update DELTA linkage.  It is important not to do this before
5333        the very end of RCS_checkin; if an error arises that forces
5334        us to abort checking in, we must not have malformed deltas
5335        partially linked into the tree.
5336
5337        If DELTA and COMMITPT are on different branches, do nothing --
5338        DELTA is linked to the tree through COMMITPT->BRANCHES, and we
5339        don't want to change `next' pointers.
5340
5341        Otherwise, if the nodes are both on the trunk, link DELTA to
5342        COMMITPT; otherwise, link COMMITPT to DELTA. */
5343
5344     if (numdots (commitpt->version) == numdots (delta->version))
5345     {
5346         if (STREQ (commitpt->version, rcs->head))
5347         {
5348             delta->next = rcs->head;
5349             rcs->head = xstrdup (delta->version);
5350         }
5351         else
5352             commitpt->next = xstrdup (delta->version);
5353     }
5354
5355     /* Add DELTA to RCS->VERSIONS. */
5356     if (rcs->versions == NULL)
5357         rcs->versions = getlist();
5358     nodep = getnode();
5359     nodep->type = RCSVERS;
5360     nodep->delproc = rcsvers_delproc;
5361     nodep->data = delta;
5362     nodep->key = delta->version;
5363     (void) addnode (rcs->versions, nodep);
5364         
5365     /* Write the new RCS file, inserting the new delta at COMMITPT. */
5366     if (!(checkin_quiet || really_quiet))
5367     {
5368         cvs_output ("new revision: ", 14);
5369         cvs_output (delta->version, 0);
5370         cvs_output ("; previous revision: ", 21);
5371         cvs_output (commitpt->version, 0);
5372         cvs_output ("\n", 1);
5373     }
5374
5375     RCS_rewrite (rcs, dtext, commitpt->version);
5376
5377     if ((flags & RCS_FLAGS_KEEPFILE) == 0)
5378     {
5379         if (unlink_file (workfile) < 0)
5380             /* FIXME-update-dir: message does not include update_dir.  */
5381             error (1, errno, "cannot remove %s", workfile);
5382     }
5383     if (unlink_file (tmpfile) < 0)
5384         error (0, errno, "cannot remove %s", tmpfile);
5385     free (tmpfile);
5386     if (unlink_file (changefile) < 0)
5387         error (0, errno, "cannot remove %s", changefile);
5388     free (changefile);
5389
5390  checkin_done:
5391     free (workfile);
5392
5393     if (commitpt != NULL && commitpt->text != NULL)
5394     {
5395         freedeltatext (commitpt->text);
5396         commitpt->text = NULL;
5397     }
5398
5399     freedeltatext (dtext);
5400     if (status != 0)
5401         free_rcsvers_contents (delta);
5402
5403     return status;
5404 }
5405
5406
5407
5408 /* This structure is passed between RCS_cmp_file and cmp_file_buffer.  */
5409 struct cmp_file_data
5410 {
5411     const char *filename;
5412     FILE *fp;
5413     int different;
5414 };
5415
5416 /* Compare the contents of revision REV1 of RCS file RCS with the
5417    contents of REV2 if given, otherwise, compare with the contents of
5418    the file FILENAME.  OPTIONS is a string for the keyword
5419    expansion options.  Return 0 if the contents of the revision are
5420    the same as the contents of the file, 1 if they are different.  */
5421 int
5422 RCS_cmp_file (RCSNode *rcs, const char *rev1, char **rev1_cache,
5423               const char *rev2, const char *options, const char *filename)
5424 {
5425     int binary;
5426
5427     TRACE (TRACE_FUNCTION, "RCS_cmp_file( %s, %s, %s, %s, %s )",
5428            rcs->path ? rcs->path : "(null)",
5429            rev1 ? rev1 : "(null)", rev2 ? rev2 : "(null)",
5430            options ? options : "(null)", filename ? filename : "(null)");
5431
5432     if (options != NULL && options[0] != '\0')
5433         binary = STREQ (options, "-kb");
5434     else
5435     {
5436         char *expand;
5437
5438         expand = RCS_getexpand (rcs);
5439         if (expand != NULL && STREQ (expand, "b"))
5440             binary = 1;
5441         else
5442             binary = 0;
5443     }
5444
5445 #ifdef PRESERVE_PERMISSIONS_SUPPORT
5446     /* If CVS is to deal properly with special files (when
5447        PreservePermissions is on), the best way is to check out the
5448        revision to a temporary file and call `xcmp' on the two disk
5449        files.  xcmp needs to handle non-regular files properly anyway,
5450        so calling it simplifies RCS_cmp_file.  We *could* just yank
5451        the delta node out of the version tree and look for device
5452        numbers, but writing to disk and calling xcmp is a better
5453        abstraction (therefore probably more robust). -twp */
5454
5455     if (preserve_perms)
5456     {
5457         char *tmp;
5458         int retcode;
5459
5460         tmp = cvs_temp_name();
5461         retcode = RCS_checkout(rcs, NULL, rev, NULL, options, tmp, NULL, NULL);
5462         if (retcode != 0)
5463             return 1;
5464
5465         retcode = xcmp (tmp, filename);
5466         if (CVS_UNLINK (tmp) < 0)
5467             error (0, errno, "cannot remove %s", tmp);
5468         free (tmp);
5469         return retcode;
5470     }
5471     else
5472 #endif
5473     {
5474         FILE *fp;
5475         struct cmp_file_data data;
5476         const char *use_file1;
5477         char *tmpfile = NULL;
5478
5479         if (rev2 != NULL)
5480         {
5481             /* Open & cache rev1 */
5482             tmpfile = cvs_temp_name();
5483             if (RCS_checkout (rcs, NULL, rev1, NULL, options, tmpfile,
5484                               (RCSCHECKOUTPROC)0, NULL))
5485                 error (1, errno,
5486                        "cannot check out revision %s of %s",
5487                        rev1, rcs->path);
5488             use_file1 = tmpfile;
5489             if (rev1_cache != NULL)
5490                 *rev1_cache = tmpfile;
5491         }
5492         else
5493             use_file1 = filename;
5494
5495         fp = CVS_FOPEN (use_file1, binary ? FOPEN_BINARY_READ : "r");
5496         if (fp == NULL)
5497             /* FIXME-update-dir: should include update_dir in message.  */
5498             error (1, errno, "cannot open file %s for comparing", use_file1);
5499         
5500         data.filename = use_file1;
5501         data.fp = fp;
5502         data.different = 0;
5503         
5504         if (RCS_checkout (rcs, NULL, rev2 ? rev2 : rev1, NULL, options,
5505                           RUN_TTY, cmp_file_buffer, &data ))
5506                 error (1, errno,
5507                        "cannot check out revision %s of %s",
5508                        rev2 ? rev2 : rev1, rcs->path);
5509
5510         /* If we have not yet found a difference, make sure that we are at
5511            the end of the file.  */
5512         if (!data.different)
5513         {
5514             if (getc (fp) != EOF)
5515                 data.different = 1;
5516         }
5517         
5518         fclose (fp);
5519         if (rev1_cache == NULL && tmpfile)
5520         {
5521             if (CVS_UNLINK (tmpfile ) < 0)
5522                 error (0, errno, "cannot remove %s", tmpfile);
5523             free (tmpfile);
5524         }
5525
5526         return data.different;
5527     }
5528 }
5529
5530
5531
5532 /* This is a subroutine of RCS_cmp_file.  It is passed to
5533    RCS_checkout.  */
5534 #define CMP_BUF_SIZE (8 * 1024)
5535
5536 static void
5537 cmp_file_buffer (void *callerdat, const char *buffer, size_t len)
5538 {
5539     struct cmp_file_data *data = callerdat;
5540     char *filebuf;
5541
5542     /* If we've already found a difference, we don't need to check
5543        further.  */
5544     if (data->different)
5545         return;
5546
5547     filebuf = xmalloc (len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len);
5548
5549     while (len > 0)
5550     {
5551         size_t checklen;
5552
5553         checklen = len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len;
5554         if (fread (filebuf, 1, checklen, data->fp) != checklen)
5555         {
5556             if (ferror (data->fp))
5557                 error (1, errno, "cannot read file %s for comparing",
5558                        data->filename);
5559             data->different = 1;
5560             free (filebuf);
5561             return;
5562         }
5563
5564         if (memcmp (filebuf, buffer, checklen) != 0)
5565         {
5566             data->different = 1;
5567             free (filebuf);
5568             return;
5569         }
5570
5571         buffer += checklen;
5572         len -= checklen;
5573     }
5574
5575     free (filebuf);
5576 }
5577
5578
5579
5580 /* For RCS file RCS, make symbolic tag TAG point to revision REV.
5581    This validates that TAG is OK for a user to use.  Return value is
5582    -1 for error (and errno is set to indicate the error), positive for
5583    error (and an error message has been printed), or zero for success.  */
5584
5585 int
5586 RCS_settag (RCSNode *rcs, const char *tag, const char *rev)
5587 {
5588     List *symbols;
5589     Node *node;
5590
5591     if (rcs->flags & PARTIAL)
5592         RCS_reparsercsfile (rcs, NULL, NULL);
5593
5594     /* FIXME: This check should be moved to RCS_check_tag.  There is no
5595        reason for it to be here.  */
5596     if (STREQ (tag, TAG_BASE)
5597         || STREQ (tag, TAG_HEAD))
5598     {
5599         /* Print the name of the tag might be considered redundant
5600            with the caller, which also prints it.  Perhaps this helps
5601            clarify why the tag name is considered reserved, I don't
5602            know.  */
5603         error (0, 0, "Attempt to add reserved tag name %s", tag);
5604         return 1;
5605     }
5606
5607     /* A revision number of NULL means use the head or default branch.
5608        If rev is not NULL, it may be a symbolic tag or branch number;
5609        expand it to the correct numeric revision or branch head. */
5610     if (rev == NULL)
5611         rev = rcs->branch ? rcs->branch : rcs->head;
5612
5613     /* At this point rcs->symbol_data may not have been parsed.
5614        Calling RCS_symbols will force it to be parsed into a list
5615        which we can easily manipulate.  */
5616     symbols = RCS_symbols (rcs);
5617     if (symbols == NULL)
5618     {
5619         symbols = getlist ();
5620         rcs->symbols = symbols;
5621     }
5622     node = findnode (symbols, tag);
5623     if (node != NULL)
5624     {
5625         free (node->data);
5626         node->data = xstrdup (rev);
5627     }
5628     else
5629     {
5630         node = getnode ();
5631         node->key = xstrdup (tag);
5632         node->data = xstrdup (rev);
5633         (void)addnode_at_front (symbols, node);
5634     }
5635
5636     return 0;
5637 }
5638
5639
5640
5641 /* Delete the symbolic tag TAG from the RCS file RCS.  Return 0 if
5642    the tag was found (and removed), or 1 if it was not present.  (In
5643    either case, the tag will no longer be in RCS->SYMBOLS.) */
5644
5645 int
5646 RCS_deltag (RCSNode *rcs, const char *tag)
5647 {
5648     List *symbols;
5649     Node *node;
5650     if (rcs->flags & PARTIAL)
5651         RCS_reparsercsfile (rcs, NULL, NULL);
5652
5653     symbols = RCS_symbols (rcs);
5654     if (symbols == NULL)
5655         return 1;
5656
5657     node = findnode (symbols, tag);
5658     if (node == NULL)
5659         return 1;
5660
5661     delnode (node);
5662
5663     return 0;
5664 }
5665
5666
5667
5668 /* Set the default branch of RCS to REV.  */
5669 int
5670 RCS_setbranch (RCSNode *rcs, const char *rev)
5671 {
5672     if (rcs->flags & PARTIAL)
5673         RCS_reparsercsfile (rcs, NULL, NULL);
5674
5675     if (rev && ! *rev)
5676         rev = NULL;
5677
5678     if (rev == NULL && rcs->branch == NULL)
5679         return 0;
5680     if (rev != NULL && rcs->branch != NULL && STREQ (rev, rcs->branch))
5681         return 0;
5682
5683     if (rcs->branch != NULL)
5684         free (rcs->branch);
5685     rcs->branch = xstrdup (rev);
5686
5687     return 0;
5688 }
5689
5690
5691
5692 /* Lock revision REV.  LOCK_QUIET is 1 to suppress output.  FIXME:
5693    Most of the callers only call us because RCS_checkin still tends to
5694    like a lock (a relic of old behavior inherited from the RCS ci
5695    program).  If we clean this up, only "cvs admin -l" will still need
5696    to call RCS_lock.  */
5697
5698 /* FIXME-twp: if a lock owned by someone else is broken, should this
5699    send mail to the lock owner?  Prompt user?  It seems like such an
5700    obscure situation for CVS as almost not worth worrying much
5701    about. */
5702 int
5703 RCS_lock (RCSNode *rcs, const char *rev, int lock_quiet)
5704 {
5705     List *locks;
5706     Node *p;
5707     char *user;
5708     char *xrev = NULL;
5709
5710     if (rcs->flags & PARTIAL)
5711         RCS_reparsercsfile (rcs, NULL, NULL);
5712
5713     locks = RCS_getlocks (rcs);
5714     if (locks == NULL)
5715         locks = rcs->locks = getlist();
5716     user = getcaller();
5717
5718     /* A revision number of NULL means lock the head or default branch. */
5719     if (rev == NULL)
5720         xrev = RCS_head (rcs);
5721     else
5722         xrev = RCS_gettag (rcs, rev, 1, NULL);
5723
5724     /* Make sure that the desired revision exists.  Technically,
5725        we can update the locks list without even checking this,
5726        but RCS 5.7 did this.  And it can't hurt. */
5727     if (xrev == NULL || findnode (rcs->versions, xrev) == NULL)
5728     {
5729         if (!lock_quiet)
5730             error (0, 0, "%s: revision %s absent", rcs->path, rev);
5731         free (xrev);
5732         return 1;
5733     }
5734
5735     /* Is this rev already locked? */
5736     p = findnode (locks, xrev);
5737     if (p != NULL)
5738     {
5739         if (STREQ (p->data, user))
5740         {
5741             /* We already own the lock on this revision, so do nothing. */
5742             free (xrev);
5743             return 0;
5744         }
5745
5746 #if 0
5747         /* Well, first of all, "rev" below should be "xrev" to avoid
5748            core dumps.  But more importantly, should we really be
5749            breaking the lock unconditionally?  What CVS 1.9 does (via
5750            RCS) is to prompt "Revision 1.1 is already locked by fred.
5751            Do you want to break the lock? [ny](n): ".  Well, we don't
5752            want to interact with the user (certainly not at the
5753            server/protocol level, and probably not in the command-line
5754            client), but isn't it more sensible to give an error and
5755            let the user run "cvs admin -u" if they want to break the
5756            lock?  */
5757
5758         /* Break the lock. */       
5759         if (!lock_quiet)
5760         {
5761             cvs_output (rev, 0);
5762             cvs_output (" unlocked\n", 0);
5763         }
5764         delnode (p);
5765 #else
5766         error (1, 0, "Revision %s is already locked by %s",
5767                xrev, (char *)p->data);
5768 #endif
5769     }
5770
5771     /* Create a new lock. */
5772     p = getnode();
5773     p->key = xrev;      /* already xstrdupped */
5774     p->data = xstrdup (getcaller());
5775     (void)addnode_at_front (locks, p);
5776
5777     if (!lock_quiet)
5778     {
5779         cvs_output (xrev, 0);
5780         cvs_output (" locked\n", 0);
5781     }
5782
5783     return 0;
5784 }
5785
5786
5787
5788 /* Unlock revision REV.  UNLOCK_QUIET is 1 to suppress output.  FIXME:
5789    Like RCS_lock, this can become a no-op if we do the checkin
5790    ourselves.
5791
5792    If REV is not null and is locked by someone else, break their
5793    lock and notify them.  It is an open issue whether RCS_unlock
5794    queries the user about whether or not to break the lock. */
5795 int
5796 RCS_unlock (RCSNode *rcs, char *rev, int unlock_quiet)
5797 {
5798     Node *lock;
5799     List *locks;
5800     char *user;
5801     char *xrev = NULL;
5802
5803     user = getcaller();
5804     if (rcs->flags & PARTIAL)
5805         RCS_reparsercsfile (rcs, NULL, NULL);
5806
5807     /* If rev is NULL, unlock the revision held by the caller; if more
5808        than one, make the user specify the revision explicitly.  This
5809        differs from RCS which unlocks the latest revision (first in
5810        rcs->locks) held by the caller. */
5811     if (rev == NULL)
5812     {
5813         Node *p;
5814
5815         /* No-ops: attempts to unlock an empty tree or an unlocked file. */
5816         if (rcs->head == NULL)
5817         {
5818             if (!unlock_quiet)
5819                 cvs_outerr ("can't unlock an empty tree\n", 0);
5820             return 0;
5821         }
5822
5823         locks = RCS_getlocks (rcs);
5824         if (locks == NULL)
5825         {
5826             if (!unlock_quiet)
5827                 cvs_outerr ("No locks are set.\n", 0);
5828             return 0;
5829         }
5830
5831         lock = NULL;
5832         for (p = locks->list->next; p != locks->list; p = p->next)
5833         {
5834             if (STREQ (p->data, user))
5835             {
5836                 if (lock != NULL)
5837                 {
5838                     if (!unlock_quiet)
5839                         error (0, 0, "\
5840 %s: multiple revisions locked by %s; please specify one", rcs->path, user);
5841                     return 1;
5842                 }
5843                 lock = p;
5844             }
5845         }
5846         if (lock == NULL)
5847         {
5848             if (!unlock_quiet)
5849                 error (0, 0, "No locks are set for %s.\n", user);
5850             return 0;   /* no lock found, ergo nothing to do */
5851         }
5852         xrev = xstrdup (lock->key);
5853     }
5854     else
5855     {
5856         xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
5857         if (xrev == NULL)
5858         {
5859             error (0, 0, "%s: revision %s absent", rcs->path, rev);
5860             return 1;
5861         }
5862     }
5863
5864     lock = findnode (RCS_getlocks (rcs), xrev);
5865     if (lock == NULL)
5866     {
5867         /* This revision isn't locked. */
5868         free (xrev);
5869         return 0;
5870     }
5871
5872     if (! STREQ (lock->data, user))
5873     {
5874         /* If the revision is locked by someone else, notify
5875            them.  Note that this shouldn't ever happen if RCS_unlock
5876            is called with a NULL revision, since that means "whatever
5877            revision is currently locked by the caller." */
5878         char *repos, *workfile;
5879         if (!unlock_quiet)
5880             error (0, 0, "\
5881 %s: revision %s locked by %s; breaking lock", rcs->path, xrev, (char *)lock->data);
5882         repos = xstrdup (rcs->path);
5883         workfile = strrchr (repos, '/');
5884         *workfile++ = '\0';
5885         notify_do ('C', workfile, user, NULL, NULL, repos);
5886         free (repos);
5887     }
5888
5889     delnode (lock);
5890     if (!unlock_quiet)
5891     {
5892         cvs_output (xrev, 0);
5893         cvs_output (" unlocked\n", 0);
5894     }
5895
5896     free (xrev);
5897     return 0;
5898 }
5899
5900
5901
5902 /* Add USER to the access list of RCS.  Do nothing if already present.
5903    FIXME-twp: check syntax of USER to make sure it's a valid id. */
5904
5905 void
5906 RCS_addaccess (RCSNode *rcs, char *user)
5907 {
5908     char *access, *a;
5909
5910     if (rcs->flags & PARTIAL)
5911         RCS_reparsercsfile (rcs, NULL, NULL);
5912
5913     if (rcs->access == NULL)
5914         rcs->access = xstrdup (user);
5915     else
5916     {
5917         access = xstrdup (rcs->access);
5918         for (a = strtok (access, " "); a != NULL; a = strtok (NULL, " "))
5919         {
5920             if (STREQ (a, user))
5921             {
5922                 free (access);
5923                 return;
5924             }
5925         }
5926         free (access);
5927         rcs->access = (char *) xrealloc
5928             (rcs->access, strlen (rcs->access) + strlen (user) + 2);
5929         strcat (rcs->access, " ");
5930         strcat (rcs->access, user);
5931     }
5932 }
5933
5934
5935
5936 /* Remove USER from the access list of RCS. */
5937 void
5938 RCS_delaccess (RCSNode *rcs, char *user)
5939 {
5940     char *p, *s;
5941     int ulen;
5942
5943     if (rcs->flags & PARTIAL)
5944         RCS_reparsercsfile (rcs, NULL, NULL);
5945
5946     if (rcs->access == NULL)
5947         return;
5948
5949     if (user == NULL)
5950     {
5951         free (rcs->access);
5952         rcs->access = NULL;
5953         return;
5954     }
5955
5956     p = rcs->access;
5957     ulen = strlen (user);
5958     while (p != NULL)
5959     {
5960         if (strncmp (p, user, ulen) == 0 && (p[ulen] == '\0' || p[ulen] == ' '))
5961             break;
5962         p = strchr (p, ' ');
5963         if (p != NULL)
5964             ++p;
5965     }
5966
5967     if (p == NULL)
5968         return;
5969
5970     s = p + ulen;
5971     while (*s != '\0')
5972         *p++ = *s++;
5973     *p = '\0';
5974 }
5975
5976
5977
5978 char *
5979 RCS_getaccess (RCSNode *rcs)
5980 {
5981     if (rcs->flags & PARTIAL)
5982         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
5983
5984     return rcs->access;
5985 }
5986
5987
5988
5989 /* Return a nonzero value if the revision specified by ARG is found.  */
5990 static int
5991 findtag (Node *node, void *arg)
5992 {
5993     char *rev = arg;
5994
5995     if (STREQ (node->data, rev))
5996         return 1;
5997     else
5998         return 0;
5999 }
6000
6001
6002
6003 /* Delete revisions between REV1 and REV2.  The changes between the two
6004    revisions must be collapsed, and the result stored in the revision
6005    immediately preceding the lower one.  Return 0 for successful completion,
6006    1 otherwise.
6007
6008    Solution: check out the revision preceding REV1 and the revision
6009    following REV2.  Use call_diff to find aggregate diffs between
6010    these two revisions, and replace the delta text for the latter one
6011    with the new aggregate diff.  Alternatively, we could write a
6012    function that takes two change texts and combines them to produce a
6013    new change text, without checking out any revs or calling diff.  It
6014    would be hairy, but so, so cool.
6015
6016    If INCLUSIVE is set, then TAG1 and TAG2, if non-NULL, tell us to
6017    delete that revision as well (cvs admin -o tag1:tag2).  If clear,
6018    delete up to but not including that revision (cvs admin -o tag1::tag2).
6019    This does not affect TAG1 or TAG2 being NULL; the meaning of the start
6020    point in ::tag2 and :tag2 is the same and likewise for end points.  */
6021 int
6022 RCS_delete_revs (RCSNode *rcs, char *tag1, char *tag2, int inclusive)
6023 {
6024     char *next;
6025     Node *nodep;
6026     RCSVers *revp = NULL;
6027     RCSVers *beforep;
6028     int status, found;
6029     int save_noexec;
6030
6031     char *branchpoint = NULL;
6032     char *rev1 = NULL;
6033     char *rev2 = NULL;
6034     int rev1_inclusive = inclusive;
6035     int rev2_inclusive = inclusive;
6036     char *before = NULL;
6037     char *after = NULL;
6038     char *beforefile = NULL;
6039     char *afterfile = NULL;
6040     char *outfile = NULL;
6041
6042     if (tag1 == NULL && tag2 == NULL)
6043         return 0;
6044
6045     /* Assume error status until everything is finished. */
6046     status = 1;
6047
6048     /* Make sure both revisions exist. */
6049     if (tag1 != NULL)
6050     {
6051         rev1 = RCS_gettag (rcs, tag1, 1, NULL);
6052         if (rev1 == NULL || (nodep = findnode (rcs->versions, rev1)) == NULL)
6053         {
6054             error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag1);
6055             goto delrev_done;
6056         }
6057     }
6058     if (tag2 != NULL)
6059     {
6060         rev2 = RCS_gettag (rcs, tag2, 1, NULL);
6061         if (rev2 == NULL || (nodep = findnode (rcs->versions, rev2)) == NULL)
6062         {
6063             error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag2);
6064             goto delrev_done;
6065         }
6066     }
6067
6068     /* If rev1 is on the trunk and rev2 is NULL, rev2 should be
6069        RCS->HEAD.  (*Not* RCS_head(rcs), which may return rcs->branch
6070        instead.)  We need to check this special case early, in order
6071        to make sure that rev1 and rev2 get ordered correctly. */
6072     if (rev2 == NULL && numdots (rev1) == 1)
6073     {
6074         rev2 = xstrdup (rcs->head);
6075         rev2_inclusive = 1;
6076     }
6077
6078     if (rev2 == NULL)
6079         rev2_inclusive = 1;
6080
6081     if (rev1 != NULL && rev2 != NULL)
6082     {
6083         /* A range consisting of a branch number means the latest revision
6084            on that branch. */
6085         if (RCS_isbranch (rcs, rev1) && STREQ (rev1, rev2))
6086             rev1 = rev2 = RCS_getbranch (rcs, rev1, 0);
6087         else
6088         {
6089             /* Make sure REV1 and REV2 are ordered correctly (in the
6090                same order as the next field).  For revisions on the
6091                trunk, REV1 should be higher than REV2; for branches,
6092                REV1 should be lower.  */
6093             /* Shouldn't we just be giving an error in the case where
6094                the user specifies the revisions in the wrong order
6095                (that is, always swap on the trunk, never swap on a
6096                branch, in the non-error cases)?  It is not at all
6097                clear to me that users who specify -o 1.4:1.2 really
6098                meant to type -o 1.2:1.4, and the out of order usage
6099                has never been documented, either by cvs.texinfo or
6100                rcs(1).  */
6101             char *temp;
6102             int temp_inclusive;
6103             if (numdots (rev1) == 1)
6104             {
6105                 if (compare_revnums (rev1, rev2) <= 0)
6106                 {
6107                     temp = rev2;
6108                     rev2 = rev1;
6109                     rev1 = temp;
6110
6111                     temp_inclusive = rev2_inclusive;
6112                     rev2_inclusive = rev1_inclusive;
6113                     rev1_inclusive = temp_inclusive;
6114                 }
6115             }
6116             else if (compare_revnums (rev1, rev2) > 0)
6117             {
6118                 temp = rev2;
6119                 rev2 = rev1;
6120                 rev1 = temp;
6121
6122                 temp_inclusive = rev2_inclusive;
6123                 rev2_inclusive = rev1_inclusive;
6124                 rev1_inclusive = temp_inclusive;
6125             }
6126         }
6127     }
6128
6129     /* Basically the same thing; make sure that the ordering is what we
6130        need.  */
6131     if (rev1 == NULL)
6132     {
6133         assert (rev2 != NULL);
6134         if (numdots (rev2) == 1)
6135         {
6136             /* Swap rev1 and rev2.  */
6137             int temp_inclusive;
6138
6139             rev1 = rev2;
6140             rev2 = NULL;
6141
6142             temp_inclusive = rev2_inclusive;
6143             rev2_inclusive = rev1_inclusive;
6144             rev1_inclusive = temp_inclusive;
6145         }
6146     }
6147
6148     /* Put the revision number preceding the first one to delete into
6149        BEFORE (where "preceding" means according to the next field).
6150        If the first revision to delete is the first revision on its
6151        branch (e.g. 1.3.2.1), BEFORE should be the node on the trunk
6152        at which the branch is rooted.  If the first revision to delete
6153        is the head revision of the trunk, set BEFORE to NULL.
6154
6155        Note that because BEFORE may not be on the same branch as REV1,
6156        it is not very handy for navigating the revision tree.  It's
6157        most useful just for checking out the revision preceding REV1. */
6158     before = NULL;
6159     branchpoint = RCS_getbranchpoint (rcs, rev1 != NULL ? rev1 : rev2);
6160     if (rev1 == NULL)
6161     {
6162         rev1 = xstrdup (branchpoint);
6163         if (numdots (branchpoint) > 1)
6164         {
6165             char *bp;
6166             bp = strrchr (branchpoint, '.');
6167             while (*--bp != '.')
6168                 ;
6169             *bp = '\0';
6170             /* Note that this is exclusive, always, because the inclusive
6171                flag doesn't affect the meaning when rev1 == NULL.  */
6172             before = xstrdup (branchpoint);
6173             *bp = '.';
6174         }
6175     }
6176     else if (! STREQ (rev1, branchpoint))
6177     {
6178         /* Walk deltas from BRANCHPOINT on, looking for REV1. */
6179         nodep = findnode (rcs->versions, branchpoint);
6180         revp = nodep->data;
6181         while (revp->next != NULL && ! STREQ (revp->next, rev1))
6182         {
6183             revp = nodep->data;
6184             nodep = findnode (rcs->versions, revp->next);
6185         }
6186         if (revp->next == NULL)
6187         {
6188             error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, rev1);
6189             goto delrev_done;
6190         }
6191         if (rev1_inclusive)
6192             before = xstrdup (revp->version);
6193         else
6194         {
6195             before = rev1;
6196             nodep = findnode (rcs->versions, before);
6197             rev1 = xstrdup (((RCSVers *)nodep->data)->next);
6198         }
6199     }
6200     else if (!rev1_inclusive)
6201     {
6202         before = rev1;
6203         nodep = findnode (rcs->versions, before);
6204         rev1 = xstrdup (((RCSVers *)nodep->data)->next);
6205     }
6206     else if (numdots (branchpoint) > 1)
6207     {
6208         /* Example: rev1 is "1.3.2.1", branchpoint is "1.3.2.1".
6209            Set before to "1.3".  */
6210         char *bp;
6211         bp = strrchr (branchpoint, '.');
6212         while (*--bp != '.')
6213             ;
6214         *bp = '\0';
6215         before = xstrdup (branchpoint);
6216         *bp = '.';
6217     }
6218
6219     /* If any revision between REV1 and REV2 is locked or is a branch point,
6220        we can't delete that revision and must abort. */
6221     after = NULL;
6222     next = rev1;
6223     found = 0;
6224     while (!found && next != NULL)
6225     {
6226         nodep = findnode (rcs->versions, next);
6227         revp = nodep->data;
6228
6229         if (rev2 != NULL)
6230             found = STREQ (revp->version, rev2);
6231         next = revp->next;
6232
6233         if ((!found && next != NULL) || rev2_inclusive || rev2 == NULL)
6234         {
6235             if (findnode (RCS_getlocks (rcs), revp->version))
6236             {
6237                 error (0, 0, "%s: can't remove locked revision %s",
6238                        rcs->path,
6239                        revp->version);
6240                 goto delrev_done;
6241             }
6242             if (revp->branches != NULL)
6243             {
6244                 error (0, 0, "%s: can't remove branch point %s",
6245                        rcs->path,
6246                        revp->version);
6247                 goto delrev_done;
6248             }
6249
6250             /* Doing this only for the :: syntax is for compatibility.
6251                See cvs.texinfo for somewhat more discussion.  */
6252             if (!inclusive
6253                 && walklist (RCS_symbols (rcs), findtag, revp->version))
6254             {
6255                 /* We don't print which file this happens to on the theory
6256                    that the caller will print the name of the file in a
6257                    more useful fashion (fullname not rcs->path).  */
6258                 error (0, 0, "cannot remove revision %s because it has tags",
6259                        revp->version);
6260                 goto delrev_done;
6261             }
6262
6263             /* It's misleading to print the `deleting revision' output
6264                here, since we may not actually delete these revisions.
6265                But that's how RCS does it.  Bleah.  Someday this should be
6266                moved to the point where the revs are actually marked for
6267                deletion. -twp */
6268             cvs_output ("deleting revision ", 0);
6269             cvs_output (revp->version, 0);
6270             cvs_output ("\n", 1);
6271         }
6272     }
6273
6274     if (rev2 == NULL)
6275         ;
6276     else if (found)
6277     {
6278         if (rev2_inclusive)
6279             after = xstrdup (next);
6280         else
6281             after = xstrdup (revp->version);
6282     }
6283     else if (!inclusive)
6284     {
6285         /* In the case of an empty range, for example 1.2::1.2 or
6286            1.2::1.3, we want to just do nothing.  */
6287         status = 0;
6288         goto delrev_done;
6289     }
6290     else
6291     {
6292         /* This looks fishy in the cases where tag1 == NULL or tag2 == NULL.
6293            Are those cases really impossible?  */
6294         assert (tag1 != NULL);
6295         assert (tag2 != NULL);
6296
6297         error (0, 0, "%s: invalid revision range %s:%s", rcs->path,
6298                tag1, tag2);
6299         goto delrev_done;
6300     }
6301
6302     if (after == NULL && before == NULL)
6303     {
6304         /* The user is trying to delete all revisions.  While an
6305            RCS file without revisions makes sense to RCS (e.g. the
6306            state after "rcs -i"), CVS has never been able to cope with
6307            it.  So at least for now we just make this an error.
6308
6309            We don't include rcs->path in the message since "cvs admin"
6310            already printed "RCS file:" and the name.  */
6311         error (1, 0, "attempt to delete all revisions");
6312     }
6313
6314     /* The conditionals at this point get really hairy.  Here is the
6315        general idea:
6316
6317        IF before != NULL and after == NULL
6318          THEN don't check out any revisions, just delete them
6319        IF before == NULL and after != NULL
6320          THEN only check out after's revision, and use it for the new deltatext
6321        ELSE
6322          check out both revisions and diff -n them.  This could use
6323          RCS_exec_rcsdiff with some changes, like being able
6324          to suppress diagnostic messages and to direct output. */
6325
6326     if (after != NULL)
6327     {
6328         char *diffbuf;
6329         size_t bufsize, len;
6330
6331 #if defined (WOE32) && !defined (__CYGWIN32__)
6332         /* FIXME: This is an awful kludge, but at least until I have
6333            time to work on it a little more and test it, I'd rather
6334            give a fatal error than corrupt the file.  I think that we
6335            need to use "-kb" and "--binary" and "rb" to get_file
6336            (probably can do it always, not just for binary files, if
6337            we are consistent between the RCS_checkout and the diff).  */
6338         {
6339             char *expand = RCS_getexpand (rcs);
6340             if (expand != NULL && STREQ (expand, "b"))
6341                 error (1, 0,
6342                    "admin -o not implemented yet for binary on this system");
6343         }
6344 #endif /* WOE32 */
6345
6346         afterfile = cvs_temp_name();
6347         status = RCS_checkout (rcs, NULL, after, NULL, "-ko", afterfile,
6348                                (RCSCHECKOUTPROC)0, NULL);
6349         if (status > 0)
6350             goto delrev_done;
6351
6352         if (before == NULL)
6353         {
6354             /* We are deleting revisions from the head of the tree,
6355                so must create a new head. */
6356             diffbuf = NULL;
6357             bufsize = 0;
6358             get_file (afterfile, afterfile, "r", &diffbuf, &bufsize, &len);
6359
6360             save_noexec = noexec;
6361             noexec = 0;
6362             if (unlink_file (afterfile) < 0)
6363                 error (0, errno, "cannot remove %s", afterfile);
6364             noexec = save_noexec;
6365
6366             free (afterfile);
6367             afterfile = NULL;
6368
6369             free (rcs->head);
6370             rcs->head = xstrdup (after);
6371         }
6372         else
6373         {
6374             beforefile = cvs_temp_name();
6375             status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
6376                                    (RCSCHECKOUTPROC)0, NULL);
6377             if (status > 0)
6378                 goto delrev_done;
6379
6380             outfile = cvs_temp_name();
6381             status = diff_exec (beforefile, afterfile, NULL, NULL, "-an",
6382                                 outfile);
6383
6384             if (status == 2)
6385             {
6386                 /* Not sure we need this message; will diff_exec already
6387                    have printed an error?  */
6388                 error (0, 0, "%s: could not diff", rcs->path);
6389                 status = 1;
6390                 goto delrev_done;
6391             }
6392
6393             diffbuf = NULL;
6394             bufsize = 0;
6395             get_file (outfile, outfile, "r", &diffbuf, &bufsize, &len);
6396         }
6397
6398         /* Save the new change text in after's delta node. */
6399         nodep = findnode (rcs->versions, after);
6400         revp = nodep->data;
6401
6402         assert (revp->text == NULL);
6403
6404         revp->text = (Deltatext *) xmalloc (sizeof (Deltatext));
6405         memset ((Deltatext *) revp->text, 0, sizeof (Deltatext));
6406         revp->text->version = xstrdup (revp->version);
6407         revp->text->text = diffbuf;
6408         revp->text->len = len;
6409
6410         /* If DIFFBUF is NULL, it means that OUTFILE is empty and that
6411            there are no differences between the two revisions.  In that
6412            case, we want to force RCS_copydeltas to write an empty string
6413            for the new change text (leaving the text field set NULL
6414            means "preserve the original change text for this delta," so
6415            we don't want that). */
6416         if (revp->text->text == NULL)
6417             revp->text->text = xstrdup ("");
6418     }
6419
6420     /* Walk through the revisions (again) to mark each one as
6421        outdated.  (FIXME: would it be safe to use the `dead' field for
6422        this?  Doubtful.) */
6423     for (next = rev1;
6424          next != NULL && (after == NULL || ! STREQ (next, after));
6425          next = revp->next)
6426     {
6427         nodep = findnode (rcs->versions, next);
6428         revp = nodep->data;
6429         revp->outdated = 1;
6430     }
6431
6432     /* Update delta links.  If BEFORE == NULL, we're changing the
6433        head of the tree and don't need to update any `next' links. */
6434     if (before != NULL)
6435     {
6436         /* If REV1 is the first node on its branch, then BEFORE is its
6437            root node (on the trunk) and we have to update its branches
6438            list.  Otherwise, BEFORE is on the same branch as AFTER, and
6439            we can just change BEFORE's `next' field to point to AFTER.
6440            (This should be safe: since findnode manages its lists via
6441            the `hashnext' and `hashprev' fields, rather than `next' and
6442            `prev', mucking with `next' and `prev' should not corrupt the
6443            delta tree's internal structure.  Much. -twp) */
6444
6445         if (rev1 == NULL)
6446             /* beforep's ->next field already should be equal to after,
6447                which I think is always NULL in this case.  */
6448             ;
6449         else if (STREQ (rev1, branchpoint))
6450         {
6451             nodep = findnode (rcs->versions, before);
6452             revp = nodep->data;
6453             nodep = revp->branches->list->next;
6454             while (nodep != revp->branches->list &&
6455                    ! STREQ (nodep->key, rev1))
6456                 nodep = nodep->next;
6457             assert (nodep != revp->branches->list);
6458             if (after == NULL)
6459                 delnode (nodep);
6460             else
6461             {
6462                 free (nodep->key);
6463                 nodep->key = xstrdup (after);
6464             }
6465         }
6466         else
6467         {
6468             nodep = findnode (rcs->versions, before);
6469             beforep = nodep->data;
6470             free (beforep->next);
6471             beforep->next = xstrdup (after);
6472         }
6473     }
6474
6475     status = 0;
6476
6477  delrev_done:
6478     if (rev1 != NULL)
6479         free (rev1);
6480     if (rev2 != NULL)
6481         free (rev2);
6482     if (branchpoint != NULL)
6483         free (branchpoint);
6484     if (before != NULL)
6485         free (before);
6486     if (after != NULL)
6487         free (after);
6488
6489     save_noexec = noexec;
6490     noexec = 0;
6491     if (beforefile != NULL)
6492     {
6493         if (unlink_file (beforefile) < 0)
6494             error (0, errno, "cannot remove %s", beforefile);
6495         free (beforefile);
6496     }
6497     if (afterfile != NULL)
6498     {
6499         if (unlink_file (afterfile) < 0)
6500             error (0, errno, "cannot remove %s", afterfile);
6501         free (afterfile);
6502     }
6503     if (outfile != NULL)
6504     {
6505         if (unlink_file (outfile) < 0)
6506             error (0, errno, "cannot remove %s", outfile);
6507         free (outfile);
6508     }
6509     noexec = save_noexec;
6510
6511     return status;
6512 }
6513
6514
6515
6516 /*
6517  * TRUE if there exists a symbolic tag "tag" in file.
6518  */
6519 int 
6520 RCS_exist_tag (RCSNode *rcs, char *tag)
6521 {
6522
6523     assert (rcs != NULL);
6524
6525     if (findnode (RCS_symbols (rcs), tag))
6526     return 1;
6527     return 0;
6528
6529 }
6530
6531 /*
6532  * TRUE if RCS revision number "rev" exists.
6533  * This includes magic branch revisions, not found in rcs->versions, 
6534  * but only in rcs->symbols, requiring a list walk to find them.
6535  * Take advantage of list walk callback function already used by 
6536  * RCS_delete_revs, above.
6537  */
6538 int
6539 RCS_exist_rev (RCSNode *rcs, char *rev)
6540 {
6541
6542     assert (rcs != NULL);
6543
6544     if (rcs->flags & PARTIAL)
6545         RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
6546
6547     if (findnode(rcs->versions, rev) != 0)
6548         return 1;
6549
6550     if (walklist (RCS_symbols(rcs), findtag, rev) != 0)
6551         return 1;
6552
6553     return 0;
6554
6555 }
6556
6557 \f
6558 /* RCS_deltas and friends.  Processing of the deltas in RCS files.  */
6559
6560 struct line
6561 {
6562     /* Text of this line.  Part of the same malloc'd block as the struct
6563        line itself (we probably should use the "struct hack" (char text[1])
6564        and save ourselves sizeof (char *) bytes).  Does not include \n;
6565        instead has_newline indicates the presence or absence of \n.  */
6566     char *text;
6567     /* Length of this line, not counting \n if has_newline is true.  */
6568     size_t len;
6569     /* Version in which it was introduced.  */
6570     RCSVers *vers;
6571     /* Nonzero if this line ends with \n.  This will always be true
6572        except possibly for the last line.  */
6573     int has_newline;
6574     /* Number of pointers to this struct line.  */
6575     int refcount;
6576 };
6577
6578 struct linevector
6579 {
6580     /* How many lines in use for this linevector?  */
6581     unsigned int nlines;
6582     /* How many lines allocated for this linevector?  */
6583     unsigned int lines_alloced;
6584     /* Pointer to array containing a pointer to each line.  */
6585     struct line **vector;
6586 };
6587
6588 static void linevector_init (struct linevector *);
6589
6590 /* Initialize *VEC to be a linevector with no lines.  */
6591 static void
6592 linevector_init (struct linevector *vec)
6593 {
6594     vec->lines_alloced = 0;
6595     vec->nlines = 0;
6596     vec->vector = NULL;
6597 }
6598
6599 static int linevector_add (struct linevector *vec, const char *text,
6600                                   size_t len, RCSVers *vers,
6601                                   unsigned int pos);
6602
6603 /* Given some text TEXT, add each of its lines to VEC before line POS
6604    (where line 0 is the first line).  The last line in TEXT may or may
6605    not be \n terminated.
6606    Set the version for each of the new lines to VERS.  This
6607    function returns non-zero for success.  It returns zero if the line
6608    number is out of range.
6609
6610    Each of the lines in TEXT are copied to space which is managed with
6611    the linevector (and freed by linevector_free).  So the caller doesn't
6612    need to keep TEXT around after the call to this function.  */
6613 static int
6614 linevector_add (struct linevector *vec, const char *text, size_t len, RCSVers *vers, unsigned int pos)
6615 {
6616     const char *textend;
6617     unsigned int i;
6618     unsigned int nnew;
6619     const char *p;
6620     const char *nextline_text;
6621     size_t nextline_len;
6622     int nextline_newline;
6623     struct line *q;
6624
6625     if (len == 0)
6626         return 1;
6627
6628     textend = text + len;
6629
6630     /* Count the number of lines we will need to add.  */
6631     nnew = 1;
6632     for (p = text; p < textend; ++p)
6633         if (*p == '\n' && p + 1 < textend)
6634             ++nnew;
6635
6636     /* Expand VEC->VECTOR if needed.  */
6637     if (vec->nlines + nnew >= vec->lines_alloced)
6638     {
6639         if (vec->lines_alloced == 0)
6640             vec->lines_alloced = 10;
6641         while (vec->nlines + nnew >= vec->lines_alloced)
6642             vec->lines_alloced *= 2;
6643         vec->vector = xrealloc (vec->vector,
6644                                 vec->lines_alloced * sizeof (*vec->vector));
6645     }
6646
6647     /* Make room for the new lines in VEC->VECTOR.  */
6648     for (i = vec->nlines + nnew - 1; i >= pos + nnew; --i)
6649         vec->vector[i] = vec->vector[i - nnew];
6650
6651     if (pos > vec->nlines)
6652         return 0;
6653
6654     /* Actually add the lines, to VEC->VECTOR.  */
6655     i = pos;
6656     nextline_text = text;
6657     nextline_newline = 0;
6658     for (p = text; p < textend; ++p)
6659         if (*p == '\n')
6660         {
6661             nextline_newline = 1;
6662             if (p + 1 == textend)
6663                 /* If there are no characters beyond the last newline, we
6664                    don't consider it another line.  */
6665                 break;
6666             nextline_len = p - nextline_text;
6667             q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
6668             q->vers = vers;
6669             q->text = (char *)q + sizeof (struct line);
6670             q->len = nextline_len;
6671             q->has_newline = nextline_newline;
6672             q->refcount = 1;
6673             memcpy (q->text, nextline_text, nextline_len);
6674             vec->vector[i++] = q;
6675
6676             nextline_text = (char *)p + 1;
6677             nextline_newline = 0;
6678         }
6679     nextline_len = p - nextline_text;
6680     q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
6681     q->vers = vers;
6682     q->text = (char *)q + sizeof (struct line);
6683     q->len = nextline_len;
6684     q->has_newline = nextline_newline;
6685     q->refcount = 1;
6686     memcpy (q->text, nextline_text, nextline_len);
6687     vec->vector[i] = q;
6688
6689     vec->nlines += nnew;
6690
6691     return 1;
6692 }
6693
6694 static void linevector_delete (struct linevector *, unsigned int,
6695                                       unsigned int);
6696
6697 /* Remove NLINES lines from VEC at position POS (where line 0 is the
6698    first line).  */
6699 static void
6700 linevector_delete (struct linevector *vec, unsigned int pos, unsigned int nlines)
6701 {
6702     unsigned int i;
6703     unsigned int last;
6704
6705     last = vec->nlines - nlines;
6706     for (i = pos; i < pos + nlines; ++i)
6707     {
6708         if (--vec->vector[i]->refcount == 0)
6709             free (vec->vector[i]);
6710     }
6711     for (i = pos; i < last; ++i)
6712         vec->vector[i] = vec->vector[i + nlines];
6713     vec->nlines -= nlines;
6714 }
6715
6716 static void linevector_copy (struct linevector *, struct linevector *);
6717
6718 /* Copy FROM to TO, copying the vectors but not the lines pointed to.  */
6719 static void
6720 linevector_copy (struct linevector *to, struct linevector *from)
6721 {
6722     unsigned int ln;
6723
6724     for (ln = 0; ln < to->nlines; ++ln)
6725     {
6726         if (--to->vector[ln]->refcount == 0)
6727             free (to->vector[ln]);
6728     }
6729     if (from->nlines > to->lines_alloced)
6730     {
6731         if (to->lines_alloced == 0)
6732             to->lines_alloced = 10;
6733         while (from->nlines > to->lines_alloced)
6734             to->lines_alloced *= 2;
6735         to->vector = (struct line **)
6736             xrealloc (to->vector, to->lines_alloced * sizeof (*to->vector));
6737     }
6738     memcpy (to->vector, from->vector,
6739             from->nlines * sizeof (*to->vector));
6740     to->nlines = from->nlines;
6741     for (ln = 0; ln < to->nlines; ++ln)
6742         ++to->vector[ln]->refcount;
6743 }
6744
6745 static void linevector_free (struct linevector *);
6746
6747 /* Free storage associated with linevector.  */
6748 static void
6749 linevector_free (struct linevector *vec)
6750 {
6751     unsigned int ln;
6752
6753     if (vec->vector != NULL)
6754     {
6755         for (ln = 0; ln < vec->nlines; ++ln)
6756             if (--vec->vector[ln]->refcount == 0)
6757                 free (vec->vector[ln]);
6758
6759         free (vec->vector);
6760     }
6761 }
6762
6763 static char *month_printname (char *);
6764
6765 /* Given a textual string giving the month (1-12), terminated with any
6766    character not recognized by atoi, return the 3 character name to
6767    print it with.  I do not think it is a good idea to change these
6768    strings based on the locale; they are standard abbreviations (for
6769    example in rfc822 mail messages) which should be widely understood.
6770    Returns a pointer into static readonly storage.  */
6771 static char *
6772 month_printname (char *month)
6773 {
6774     static const char *const months[] =
6775       {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
6776          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
6777     int mnum;
6778
6779     mnum = atoi (month);
6780     if (mnum < 1 || mnum > 12)
6781         return "???";
6782     return (char *)months[mnum - 1];
6783 }
6784
6785 static int
6786 apply_rcs_changes (struct linevector *, const char *, size_t,
6787                           const char *, RCSVers *, RCSVers *);
6788
6789 /* Apply changes to the line vector LINES.  DIFFBUF is a buffer of
6790    length DIFFLEN holding the change text from an RCS file (the output
6791    of diff -n).  NAME is used in error messages.  The VERS field of
6792    any line added is set to ADDVERS.  The VERS field of any line
6793    deleted is set to DELVERS, unless DELVERS is NULL, in which case
6794    the VERS field of deleted lines is unchanged.  The function returns
6795    non-zero if the change text is applied successfully.  It returns
6796    zero if the change text does not appear to apply to LINES (e.g., a
6797    line number is invalid).  If the change text is improperly
6798    formatted (e.g., it is not the output of diff -n), the function
6799    calls error with a status of 1, causing the program to exit.  */
6800
6801 static int
6802 apply_rcs_changes (struct linevector *lines, const char *diffbuf, size_t difflen, const char *name, RCSVers *addvers, RCSVers *delvers)
6803 {
6804     const char *p;
6805     const char *q;
6806     int op;
6807     /* The RCS format throws us for a loop in that the deltafrags (if
6808        we define a deltafrag as an add or a delete) need to be applied
6809        in reverse order.  So we stick them into a linked list.  */
6810     struct deltafrag {
6811         enum {FRAG_ADD, FRAG_DELETE} type;
6812         unsigned long pos;
6813         unsigned long nlines;
6814         const char *new_lines;
6815         size_t len;
6816         struct deltafrag *next;
6817     };
6818     struct deltafrag *dfhead;
6819     struct deltafrag *df;
6820
6821     dfhead = NULL;
6822     for (p = diffbuf; p != NULL && p < diffbuf + difflen; )
6823     {
6824         op = *p++;
6825         if (op != 'a' && op != 'd')
6826             /* Can't just skip over the deltafrag, because the value
6827                of op determines the syntax.  */
6828             error (1, 0, "unrecognized operation '\\x%x' in %s",
6829                    op, name);
6830         df = (struct deltafrag *) xmalloc (sizeof (struct deltafrag));
6831         df->next = dfhead;
6832         dfhead = df;
6833         df->pos = strtoul (p, (char **) &q, 10);
6834
6835         if (p == q)
6836             error (1, 0, "number expected in %s", name);
6837         p = q;
6838         if (*p++ != ' ')
6839             error (1, 0, "space expected in %s", name);
6840         df->nlines = strtoul (p, (char **) &q, 10);
6841         if (p == q)
6842             error (1, 0, "number expected in %s", name);
6843         p = q;
6844         if (*p++ != '\012')
6845             error (1, 0, "linefeed expected in %s", name);
6846
6847         if (op == 'a')
6848         {
6849             unsigned int i;
6850
6851             df->type = FRAG_ADD;
6852             i = df->nlines;
6853             /* The text we want is the number of lines specified, or
6854                until the end of the value, whichever comes first (it
6855                will be the former except in the case where we are
6856                adding a line which does not end in newline).  */
6857             for (q = p; i != 0; ++q)
6858                 if (*q == '\n')
6859                     --i;
6860                 else if (q == diffbuf + difflen)
6861                 {
6862                     if (i != 1)
6863                         error (1, 0, "premature end of change in %s", name);
6864                     else
6865                         break;
6866                 }
6867
6868             /* Stash away a pointer to the text we are adding.  */
6869             df->new_lines = p;
6870             df->len = q - p;
6871
6872             p = q;
6873         }
6874         else
6875         {
6876             /* Correct for the fact that line numbers in RCS files
6877                start with 1.  */
6878             --df->pos;
6879
6880             assert (op == 'd');
6881             df->type = FRAG_DELETE;
6882         }
6883     }
6884
6885     for (df = dfhead; df != NULL;)
6886     {
6887         unsigned int ln;
6888
6889         switch (df->type)
6890         {
6891         case FRAG_ADD:
6892             if (! linevector_add (lines, df->new_lines, df->len, addvers,
6893                                   df->pos))
6894                 return 0;
6895             break;
6896         case FRAG_DELETE:
6897             if (df->pos > lines->nlines
6898                 || df->pos + df->nlines > lines->nlines)
6899                 return 0;
6900             if (delvers != NULL)
6901                 for (ln = df->pos; ln < df->pos + df->nlines; ++ln)
6902                     lines->vector[ln]->vers = delvers;
6903             linevector_delete (lines, df->pos, df->nlines);
6904             break;
6905         }
6906         df = df->next;
6907         free (dfhead);
6908         dfhead = df;
6909     }
6910
6911     return 1;
6912 }
6913
6914 /* Apply an RCS change text to a buffer.  The function name starts
6915    with rcs rather than RCS because this does not take an RCSNode
6916    argument.  NAME is used in error messages.  TEXTBUF is the text
6917    buffer to change, and TEXTLEN is the size.  DIFFBUF and DIFFLEN are
6918    the change buffer and size.  The new buffer is returned in *RETBUF
6919    and *RETLEN.  The new buffer is allocated by xmalloc.
6920
6921    Return 1 for success.  On failure, call error and return 0.  */
6922
6923 int
6924 rcs_change_text (const char *name, char *textbuf, size_t textlen, const char *diffbuf, size_t difflen, char **retbuf, size_t *retlen)
6925 {
6926     struct linevector lines;
6927     int ret;
6928
6929     *retbuf = NULL;
6930     *retlen = 0;
6931
6932     linevector_init (&lines);
6933
6934     if (! linevector_add (&lines, textbuf, textlen, NULL, 0))
6935         error (1, 0, "cannot initialize line vector");
6936
6937     if (! apply_rcs_changes (&lines, diffbuf, difflen, name, NULL, NULL))
6938     {
6939         error (0, 0, "invalid change text in %s", name);
6940         ret = 0;
6941     }
6942     else
6943     {
6944         char *p;
6945         size_t n;
6946         unsigned int ln;
6947
6948         n = 0;
6949         for (ln = 0; ln < lines.nlines; ++ln)
6950             /* 1 for \n */
6951             n += lines.vector[ln]->len + 1;
6952
6953         p = xmalloc (n);
6954         *retbuf = p;
6955
6956         for (ln = 0; ln < lines.nlines; ++ln)
6957         {
6958             memcpy (p, lines.vector[ln]->text, lines.vector[ln]->len);
6959             p += lines.vector[ln]->len;
6960             if (lines.vector[ln]->has_newline)
6961                 *p++ = '\n';
6962         }
6963
6964         *retlen = p - *retbuf;
6965         assert (*retlen <= n);
6966
6967         ret = 1;
6968     }
6969
6970     linevector_free (&lines);
6971
6972     return ret;
6973 }
6974
6975 /* Walk the deltas in RCS to get to revision VERSION.
6976
6977    If OP is RCS_ANNOTATE, then write annotations using cvs_output.
6978
6979    If OP is RCS_FETCH, then put the contents of VERSION into a
6980    newly-malloc'd array and put a pointer to it in *TEXT.  Each line
6981    is \n terminated; the caller is responsible for converting text
6982    files if desired.  The total length is put in *LEN.
6983
6984    If FP is non-NULL, it should be a file descriptor open to the file
6985    RCS with file position pointing to the deltas.  We close the file
6986    when we are done.
6987
6988    If LOG is non-NULL, then *LOG is set to the log message of VERSION,
6989    and *LOGLEN is set to the length of the log message.
6990
6991    On error, give a fatal error.  */
6992
6993 void
6994 RCS_deltas (RCSNode *rcs, FILE *fp, struct rcsbuffer *rcsbuf,
6995             const char *version, enum rcs_delta_op op, char **text,
6996             size_t *len, char **log, size_t *loglen)
6997 {
6998     struct rcsbuffer rcsbuf_local;
6999     char *branchversion;
7000     char *cpversion;
7001     char *key;
7002     char *value;
7003     size_t vallen;
7004     RCSVers *vers;
7005     RCSVers *prev_vers;
7006     RCSVers *trunk_vers;
7007     char *next;
7008     int ishead, isnext, isversion, onbranch;
7009     Node *node;
7010     struct linevector headlines;
7011     struct linevector curlines;
7012     struct linevector trunklines;
7013     int foundhead;
7014
7015     if (fp == NULL)
7016     {
7017         rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf_local);
7018         rcsbuf = &rcsbuf_local;
7019     }
7020
7021     ishead = 1;
7022     vers = NULL;
7023     prev_vers = NULL;
7024     trunk_vers = NULL;
7025     next = NULL;
7026     onbranch = 0;
7027     foundhead = 0;
7028
7029     linevector_init (&curlines);
7030     linevector_init (&headlines);
7031     linevector_init (&trunklines);
7032
7033     /* We set BRANCHVERSION to the version we are currently looking
7034        for.  Initially, this is the version on the trunk from which
7035        VERSION branches off.  If VERSION is not a branch, then
7036        BRANCHVERSION is just VERSION.  */
7037     branchversion = xstrdup (version);
7038     cpversion = strchr (branchversion, '.');
7039     if (cpversion != NULL)
7040         cpversion = strchr (cpversion + 1, '.');
7041     if (cpversion != NULL)
7042         *cpversion = '\0';
7043
7044     do {
7045         if (! rcsbuf_getrevnum (rcsbuf, &key))
7046             error (1, 0, "unexpected EOF reading RCS file %s", rcs->path);
7047
7048         if (next != NULL && ! STREQ (next, key))
7049         {
7050             /* This is not the next version we need.  It is a branch
7051                version which we want to ignore.  */
7052             isnext = 0;
7053             isversion = 0;
7054         }
7055         else
7056         {
7057             isnext = 1;
7058
7059             /* look up the revision */
7060             node = findnode (rcs->versions, key);
7061             if (node == NULL)
7062                 error (1, 0,
7063                        "mismatch in rcs file %s between deltas and deltatexts (%s)",
7064                        rcs->path, key);
7065
7066             /* Stash the previous version.  */
7067             prev_vers = vers;
7068
7069             vers = node->data;
7070             next = vers->next;
7071
7072             /* Compare key and trunkversion now, because key points to
7073                storage controlled by rcsbuf_getkey.  */
7074             if (STREQ (branchversion, key))
7075                 isversion = 1;
7076             else
7077                 isversion = 0;
7078         }
7079
7080         while (1)
7081         {
7082             if (! rcsbuf_getkey (rcsbuf, &key, &value))
7083                 error (1, 0, "%s does not appear to be a valid rcs file",
7084                        rcs->path);
7085
7086             if (log != NULL
7087                 && isversion
7088                 && STREQ (key, "log")
7089                 && STREQ (branchversion, version))
7090             {
7091                 *log = rcsbuf_valcopy (rcsbuf, value, 0, loglen);
7092             }
7093
7094             if (STREQ (key, "text"))
7095             {
7096                 rcsbuf_valpolish (rcsbuf, value, 0, &vallen);
7097                 if (ishead)
7098                 {
7099                     if (! linevector_add (&curlines, value, vallen, NULL, 0))
7100                         error (1, 0, "invalid rcs file %s", rcs->path);
7101
7102                     ishead = 0;
7103                 }
7104                 else if (isnext)
7105                 {
7106                     if (! apply_rcs_changes (&curlines, value, vallen,
7107                                              rcs->path,
7108                                              onbranch ? vers : NULL,
7109                                              onbranch ? NULL : prev_vers))
7110                         error (1, 0, "invalid change text in %s", rcs->path);
7111                 }
7112                 break;
7113             }
7114         }
7115
7116         if (isversion)
7117         {
7118             /* This is either the version we want, or it is the
7119                branchpoint to the version we want.  */
7120             if (STREQ (branchversion, version))
7121             {
7122                 /* This is the version we want.  */
7123                 linevector_copy (&headlines, &curlines);
7124                 foundhead = 1;
7125                 if (onbranch)
7126                 {
7127                     /* We have found this version by tracking up a
7128                        branch.  Restore back to the lines we saved
7129                        when we left the trunk, and continue tracking
7130                        down the trunk.  */
7131                     onbranch = 0;
7132                     vers = trunk_vers;
7133                     next = vers->next;
7134                     linevector_copy (&curlines, &trunklines);
7135                 }
7136             }
7137             else
7138             {
7139                 Node *p;
7140
7141                 /* We need to look up the branch.  */
7142                 onbranch = 1;
7143
7144                 if (numdots (branchversion) < 2)
7145                 {
7146                     unsigned int ln;
7147
7148                     /* We are leaving the trunk; save the current
7149                        lines so that we can restore them when we
7150                        continue tracking down the trunk.  */
7151                     trunk_vers = vers;
7152                     linevector_copy (&trunklines, &curlines);
7153
7154                     /* Reset the version information we have
7155                        accumulated so far.  It only applies to the
7156                        changes from the head to this version.  */
7157                     for (ln = 0; ln < curlines.nlines; ++ln)
7158                         curlines.vector[ln]->vers = NULL;
7159                 }
7160
7161                 /* The next version we want is the entry on
7162                    VERS->branches which matches this branch.  For
7163                    example, suppose VERSION is 1.21.4.3 and
7164                    BRANCHVERSION was 1.21.  Then we look for an entry
7165                    starting with "1.21.4" and we'll put it (probably
7166                    1.21.4.1) in NEXT.  We'll advance BRANCHVERSION by
7167                    two dots (in this example, to 1.21.4.3).  */
7168
7169                 if (vers->branches == NULL)
7170                     error (1, 0, "missing expected branches in %s",
7171                            rcs->path);
7172                 *cpversion = '.';
7173                 ++cpversion;
7174                 cpversion = strchr (cpversion, '.');
7175                 if (cpversion == NULL)
7176                     error (1, 0, "version number confusion in %s",
7177                            rcs->path);
7178                 for (p = vers->branches->list->next;
7179                      p != vers->branches->list;
7180                      p = p->next)
7181                     if (strncmp (p->key, branchversion,
7182                                  cpversion - branchversion) == 0)
7183                         break;
7184                 if (p == vers->branches->list)
7185                     error (1, 0, "missing expected branch in %s",
7186                            rcs->path);
7187
7188                 next = p->key;
7189
7190                 cpversion = strchr (cpversion + 1, '.');
7191                 if (cpversion != NULL)
7192                     *cpversion = '\0';
7193             }
7194         }
7195         if (op == RCS_FETCH && foundhead)
7196             break;
7197     } while (next != NULL);
7198
7199     free (branchversion);
7200
7201     rcsbuf_cache (rcs, rcsbuf);
7202
7203     if (! foundhead)
7204         error (1, 0, "could not find desired version %s in %s",
7205                version, rcs->path);
7206
7207     /* Now print out or return the data we have just computed.  */
7208     switch (op)
7209     {
7210         case RCS_ANNOTATE:
7211             {
7212                 unsigned int ln;
7213
7214                 for (ln = 0; ln < headlines.nlines; ++ln)
7215                 {
7216                     char buf[80];
7217                     /* Period which separates year from month in date.  */
7218                     char *ym;
7219                     /* Period which separates month from day in date.  */
7220                     char *md;
7221                     RCSVers *prvers;
7222
7223                     prvers = headlines.vector[ln]->vers;
7224                     if (prvers == NULL)
7225                         prvers = vers;
7226
7227                     sprintf (buf, "%-12s (%-8.8s ",
7228                              prvers->version,
7229                              prvers->author);
7230                     cvs_output (buf, 0);
7231
7232                     /* Now output the date.  */
7233                     ym = strchr (prvers->date, '.');
7234                     if (ym == NULL)
7235                     {
7236                         cvs_output ("??", 0);
7237                         cvs_output ("-???", 0);
7238                         cvs_output ("-??", 0);
7239                     }
7240                     else
7241                     {
7242                         md = strchr (ym + 1, '.');
7243                         if (md == NULL)
7244                             cvs_output ("??", 0);
7245                         else
7246                             cvs_output (md + 1, 2);
7247
7248                         cvs_output ("-", 1);
7249                         cvs_output (month_printname (ym + 1), 0);
7250                         cvs_output ("-", 1);
7251                         /* Only output the last two digits of the year.  Our output
7252                            lines are long enough as it is without printing the
7253                            century.  */
7254                         cvs_output (ym - 2, 2);
7255                     }
7256                     cvs_output ("): ", 0);
7257                     if (headlines.vector[ln]->len != 0)
7258                         cvs_output (headlines.vector[ln]->text,
7259                                     headlines.vector[ln]->len);
7260                     cvs_output ("\n", 1);
7261                 }
7262             }
7263             break;
7264         case RCS_FETCH:
7265             {
7266                 char *p;
7267                 size_t n;
7268                 unsigned int ln;
7269
7270                 assert (text != NULL);
7271                 assert (len != NULL);
7272
7273                 n = 0;
7274                 for (ln = 0; ln < headlines.nlines; ++ln)
7275                     /* 1 for \n */
7276                     n += headlines.vector[ln]->len + 1;
7277                 p = xmalloc (n);
7278                 *text = p;
7279                 for (ln = 0; ln < headlines.nlines; ++ln)
7280                 {
7281                     memcpy (p, headlines.vector[ln]->text,
7282                             headlines.vector[ln]->len);
7283                     p += headlines.vector[ln]->len;
7284                     if (headlines.vector[ln]->has_newline)
7285                         *p++ = '\n';
7286                 }
7287                 *len = p - *text;
7288                 assert (*len <= n);
7289             }
7290             break;
7291     }
7292
7293     linevector_free (&curlines);
7294     linevector_free (&headlines);
7295     linevector_free (&trunklines);
7296
7297     return;
7298 }
7299 \f
7300 /* Read the information for a single delta from the RCS buffer RCSBUF,
7301    whose name is RCSFILE.  *KEYP and *VALP are either NULL, or the
7302    first key/value pair to read, as set by rcsbuf_getkey. Return NULL
7303    if there are no more deltas.  Store the key/value pair which
7304    terminated the read in *KEYP and *VALP.  */
7305
7306 static RCSVers *
7307 getdelta (struct rcsbuffer *rcsbuf, char *rcsfile, char **keyp, char **valp)
7308 {
7309     RCSVers *vnode;
7310     char *key, *value, *cp;
7311     Node *kv;
7312
7313     /* Get revision number if it wasn't passed in. This uses
7314        rcsbuf_getkey because it doesn't croak when encountering
7315        unexpected input.  As a result, we have to play unholy games
7316        with `key' and `value'. */
7317     if (*keyp != NULL)
7318     {
7319         key = *keyp;
7320         value = *valp;
7321     }
7322     else
7323     {
7324         if (! rcsbuf_getkey (rcsbuf, &key, &value))
7325             error (1, 0, "%s: unexpected EOF", rcsfile);
7326     }
7327
7328     /* Make sure that it is a revision number and not a cabbage 
7329        or something. */
7330     for (cp = key;
7331          (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
7332          cp++)
7333         /* do nothing */ ;
7334     /* Note that when comparing with RCSDATE, we are not massaging
7335        VALUE from the string found in the RCS file.  This is OK since
7336        we know exactly what to expect.  */
7337     if (*cp != '\0' || strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) != 0)
7338     {
7339         *keyp = key;
7340         *valp = value;
7341         return NULL;
7342     }
7343
7344     vnode = (RCSVers *) xmalloc (sizeof (RCSVers));
7345     memset (vnode, 0, sizeof (RCSVers));
7346
7347     vnode->version = xstrdup (key);
7348
7349     /* Grab the value of the date from value.  Note that we are not
7350        massaging VALUE from the string found in the RCS file.  */
7351     cp = value + (sizeof RCSDATE) - 1;  /* skip the "date" keyword */
7352     while (whitespace (*cp))            /* take space off front of value */
7353         cp++;
7354
7355     vnode->date = xstrdup (cp);
7356
7357     /* Get author field.  */
7358     if (! rcsbuf_getkey (rcsbuf, &key, &value))
7359     {
7360         error (1, 0, "unexpected end of file reading %s", rcsfile);
7361     }
7362     if (! STREQ (key, "author"))
7363         error (1, 0, "\
7364 unable to parse %s; `author' not in the expected place", rcsfile);
7365     vnode->author = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7366
7367     /* Get state field.  */
7368     if (! rcsbuf_getkey (rcsbuf, &key, &value))
7369     {
7370         error (1, 0, "unexpected end of file reading %s", rcsfile);
7371     }
7372     if (! STREQ (key, "state"))
7373         error (1, 0, "\
7374 unable to parse %s; `state' not in the expected place", rcsfile);
7375     vnode->state = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7376     /* The value is optional, according to rcsfile(5).  */
7377     if (value != NULL && STREQ (value, RCSDEAD))
7378     {
7379         vnode->dead = 1;
7380     }
7381
7382     /* Note that "branches" and "next" are in fact mandatory, according
7383        to doc/RCSFILES.  */
7384
7385     /* fill in the branch list (if any branches exist) */
7386     if (! rcsbuf_getkey (rcsbuf, &key, &value))
7387     {
7388         error (1, 0, "unexpected end of file reading %s", rcsfile);
7389     }
7390     if (STREQ (key, RCSDESC))
7391     {
7392         *keyp = key;
7393         *valp = value;
7394         /* Probably could/should be a fatal error.  */
7395         error (0, 0, "warning: 'branches' keyword missing from %s", rcsfile);
7396         return vnode;
7397     }
7398     if (value != (char *) NULL)
7399     {
7400         vnode->branches = getlist ();
7401         /* Note that we are not massaging VALUE from the string found
7402            in the RCS file.  */
7403         do_branches (vnode->branches, value);
7404     }
7405
7406     /* fill in the next field if there is a next revision */
7407     if (! rcsbuf_getkey (rcsbuf, &key, &value))
7408     {
7409         error (1, 0, "unexpected end of file reading %s", rcsfile);
7410     }
7411     if (STREQ (key, RCSDESC))
7412     {
7413         *keyp = key;
7414         *valp = value;
7415         /* Probably could/should be a fatal error.  */
7416         error (0, 0, "warning: 'next' keyword missing from %s", rcsfile);
7417         return vnode;
7418     }
7419     if (value != (char *) NULL)
7420         vnode->next = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7421
7422     /*
7423      * XXX - this is where we put the symbolic link stuff???
7424      * (into newphrases in the deltas).
7425      */
7426     while (1)
7427     {
7428         if (! rcsbuf_getkey (rcsbuf, &key, &value))
7429             error (1, 0, "unexpected end of file reading %s", rcsfile);
7430
7431         /* The `desc' keyword is the end of the deltas. */
7432         if (strcmp (key, RCSDESC) == 0)
7433             break;
7434
7435 #ifdef PRESERVE_PERMISSIONS_SUPPORT
7436
7437         /* The `hardlinks' value is a group of words, which must
7438            be parsed separately and added as a list to vnode->hardlinks. */
7439         if (strcmp (key, "hardlinks") == 0)
7440         {
7441             char *word;
7442
7443             vnode->hardlinks = getlist();
7444             while ((word = rcsbuf_valword (rcsbuf, &value)) != NULL)
7445             {
7446                 Node *n = getnode();
7447                 n->key = word;
7448                 addnode (vnode->hardlinks, n);
7449             }
7450             continue;
7451         }
7452 #endif
7453
7454         /* Enable use of repositories created by certain obsolete
7455            versions of CVS.  This code should remain indefinately;
7456            there is no procedure for converting old repositories, and
7457            checking for it is harmless.  */
7458         if (STREQ (key, RCSDEAD))
7459         {
7460             vnode->dead = 1;
7461             if (vnode->state != NULL)
7462                 free (vnode->state);
7463             vnode->state = xstrdup (RCSDEAD);
7464             continue;
7465         }
7466         /* if we have a new revision number, we're done with this delta */
7467         for (cp = key;
7468              (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
7469              cp++)
7470             /* do nothing */ ;
7471         /* Note that when comparing with RCSDATE, we are not massaging
7472            VALUE from the string found in the RCS file.  This is OK
7473            since we know exactly what to expect.  */
7474         if (*cp == '\0' && strncmp (RCSDATE, value, strlen (RCSDATE)) == 0)
7475             break;
7476
7477         /* At this point, key and value represent a user-defined field
7478            in the delta node. */
7479         if (vnode->other_delta == NULL)
7480             vnode->other_delta = getlist ();
7481         kv = getnode ();
7482         kv->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
7483         kv->key = xstrdup (key);
7484         kv->data = rcsbuf_valcopy (rcsbuf, value, kv->type == RCSFIELD,
7485                                    (size_t *) NULL);
7486         if (addnode (vnode->other_delta, kv) != 0)
7487         {
7488             /* Complaining about duplicate keys in newphrases seems
7489                questionable, in that we don't know what they mean and
7490                doc/RCSFILES has no prohibition on several newphrases
7491                with the same key.  But we can't store more than one as
7492                long as we store them in a List *.  */
7493             error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
7494                    key, rcsfile);
7495             freenode (kv);
7496         }
7497     }
7498
7499     /* Return the key which caused us to fail back to the caller.  */
7500     *keyp = key;
7501     *valp = value;
7502
7503     return vnode;
7504 }
7505
7506 static void
7507 freedeltatext (Deltatext *d)
7508 {
7509     if (d->version != NULL)
7510         free (d->version);
7511     if (d->log != NULL)
7512         free (d->log);
7513     if (d->text != NULL)
7514         free (d->text);
7515     if (d->other != (List *) NULL)
7516         dellist (&d->other);
7517     free (d);
7518 }
7519
7520 static Deltatext *
7521 RCS_getdeltatext (RCSNode *rcs, FILE *fp, struct rcsbuffer *rcsbuf)
7522 {
7523     char *num;
7524     char *key, *value;
7525     Node *p;
7526     Deltatext *d;
7527
7528     /* Get the revision number. */
7529     if (! rcsbuf_getrevnum (rcsbuf, &num))
7530     {
7531         /* If num == NULL, it means we reached EOF naturally.  That's
7532            fine. */
7533         if (num == NULL)
7534             return NULL;
7535         else
7536             error (1, 0, "%s: unexpected EOF", rcs->path);
7537     }
7538
7539     p = findnode (rcs->versions, num);
7540     if (p == NULL)
7541         error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)",
7542                rcs->path, num);
7543
7544     d = (Deltatext *) xmalloc (sizeof (Deltatext));
7545     d->version = xstrdup (num);
7546
7547     /* Get the log message. */
7548     if (! rcsbuf_getkey (rcsbuf, &key, &value))
7549         error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
7550     if (! STREQ (key, "log"))
7551         error (1, 0, "%s, delta %s: expected `log', got `%s'",
7552                rcs->path, num, key);
7553     d->log = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
7554
7555     /* Get random newphrases. */
7556     d->other = getlist();
7557     while (1)
7558     {
7559         if (! rcsbuf_getkey (rcsbuf, &key, &value))
7560             error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
7561
7562         if (STREQ (key, "text"))
7563             break;
7564
7565         p = getnode();
7566         p->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
7567         p->key = xstrdup (key);
7568         p->data = rcsbuf_valcopy (rcsbuf, value, p->type == RCSFIELD,
7569                                   (size_t *) NULL);
7570         if (addnode (d->other, p) < 0)
7571         {
7572             error (0, 0, "warning: %s, delta %s: duplicate field `%s'",
7573                    rcs->path, num, key);
7574         }
7575     }
7576
7577     /* Get the change text. We already know that this key is `text'. */
7578     d->text = rcsbuf_valcopy (rcsbuf, value, 0, &d->len);
7579
7580     return d;
7581 }
7582
7583 /* RCS output functions, for writing RCS format files from RCSNode
7584    structures.
7585
7586    For most of this work, RCS 5.7 uses an `aprintf' function which aborts
7587    program upon error.  Instead, these functions check the output status
7588    of the stream right before closing it, and aborts if an error condition
7589    is found.  The RCS solution is probably the better one: it produces
7590    more overhead, but will produce a clearer diagnostic in the case of
7591    catastrophic error.  In either case, however, the repository will probably
7592    not get corrupted. */
7593
7594 static int
7595 putsymbol_proc (Node *symnode, void *fparg)
7596 {
7597     FILE *fp = (FILE *) fparg;
7598
7599     /* A fiddly optimization: this code used to just call fprintf, but
7600        in an old repository with hundreds of tags this can get called
7601        hundreds of thousands of times when doing a cvs tag.  Since
7602        tagging is a relatively common operation, and using putc and
7603        fputs is just as comprehensible, the change is worthwhile.  */
7604     putc ('\n', fp);
7605     putc ('\t', fp);
7606     fputs (symnode->key, fp);
7607     putc (':', fp);
7608     fputs (symnode->data, fp);
7609     return 0;
7610 }
7611
7612 static int putlock_proc (Node *, void *);
7613
7614 /* putlock_proc is like putsymbol_proc, but key and data are reversed. */
7615
7616 static int
7617 putlock_proc (Node *symnode, void *fp)
7618 {
7619     return fprintf ((FILE *) fp, "\n\t%s:%s", (char *)symnode->data, symnode->key);
7620 }
7621
7622 static int
7623 putrcsfield_proc (Node *node, void *vfp)
7624 {
7625     FILE *fp = (FILE *) vfp;
7626
7627     /* Some magic keys used internally by CVS start with `;'. Skip them. */
7628     if (node->key[0] == ';')
7629         return 0;
7630
7631     fprintf (fp, "\n%s\t", node->key);
7632     if (node->data != NULL)
7633     {
7634         /* If the field's value contains evil characters,
7635            it must be stringified. */
7636         /* FIXME: This does not quite get it right.  "7jk8f" is not a valid
7637            value for a value in a newpharse, according to doc/RCSFILES,
7638            because digits are not valid in an "id".  We might do OK by
7639            always writing strings (enclosed in @@).  Would be nice to
7640            explicitly mention this one way or another in doc/RCSFILES.
7641            A case where we are wrong in a much more clear-cut way is that
7642            we let through non-graphic characters such as whitespace and
7643            control characters.  */
7644
7645         if (node->type == RCSCMPFLD || strpbrk (node->data, "$,.:;@") == NULL)
7646             fputs (node->data, fp);
7647         else
7648         {
7649             putc ('@', fp);
7650             expand_at_signs (node->data, (off_t) strlen (node->data), fp);
7651             putc ('@', fp);
7652         }
7653     }
7654
7655     /* desc, log and text fields should not be terminated with semicolon;
7656        all other fields should be. */
7657     if (! STREQ (node->key, "desc") &&
7658         ! STREQ (node->key, "log") &&
7659         ! STREQ (node->key, "text"))
7660     {
7661         putc (';', fp);
7662     }
7663     return 0;
7664 }
7665
7666 #ifdef PRESERVE_PERMISSIONS_SUPPORT
7667
7668 /* Save a filename in a `hardlinks' RCS field.  NODE->KEY will contain
7669    a full pathname, but currently only basenames are stored in the RCS
7670    node.  Assume that the filename includes nasty characters and
7671    @-escape it. */
7672
7673 static int
7674 puthardlink_proc (node, vfp)
7675     Node *node;
7676     void *vfp;
7677 {
7678     FILE *fp = (FILE *) vfp;
7679     char *basename = strrchr (node->key, '/');
7680
7681     if (basename == NULL)
7682         basename = node->key;
7683     else
7684         ++basename;
7685
7686     putc ('\t', fp);
7687     putc ('@', fp);
7688     (void) expand_at_signs (basename, strlen (basename), fp);
7689     putc ('@', fp);
7690
7691     return 0;
7692 }
7693
7694 #endif
7695
7696 /* Output the admin node for RCS into stream FP. */
7697
7698 static void
7699 RCS_putadmin (RCSNode *rcs, FILE *fp)
7700 {
7701     fprintf (fp, "%s\t%s;\n", RCSHEAD, rcs->head ? rcs->head : "");
7702     if (rcs->branch)
7703         fprintf (fp, "%s\t%s;\n", RCSBRANCH, rcs->branch);
7704
7705     fputs ("access", fp);
7706     if (rcs->access)
7707     {
7708         char *p, *s;
7709         s = xstrdup (rcs->access);
7710         for (p = strtok (s, " \n\t"); p != NULL; p = strtok (NULL, " \n\t"))
7711             fprintf (fp, "\n\t%s", p);
7712         free (s);
7713     }
7714     fputs (";\n", fp);
7715
7716     fputs (RCSSYMBOLS, fp);
7717     /* If we haven't had to convert the symbols to a list yet, don't
7718        force a conversion now; just write out the string.  */
7719     if (rcs->symbols == NULL && rcs->symbols_data != NULL)
7720     {
7721         fputs ("\n\t", fp);
7722         fputs (rcs->symbols_data, fp);
7723     }
7724     else
7725         walklist (RCS_symbols (rcs), putsymbol_proc, (void *) fp);
7726     fputs (";\n", fp);
7727
7728     fputs ("locks", fp);
7729     if (rcs->locks_data)
7730         fprintf (fp, "\t%s", rcs->locks_data);
7731     else if (rcs->locks)
7732         walklist (rcs->locks, putlock_proc, (void *) fp);
7733     if (rcs->strict_locks)
7734         fprintf (fp, "; strict");
7735     fputs (";\n", fp);
7736
7737     if (rcs->comment)
7738     {
7739         fprintf (fp, "comment\t@");
7740         expand_at_signs (rcs->comment, (off_t) strlen (rcs->comment), fp);
7741         fputs ("@;\n", fp);
7742     }
7743     if (rcs->expand && ! STREQ (rcs->expand, "kv"))
7744         fprintf (fp, "%s\t@%s@;\n", RCSEXPAND, rcs->expand);
7745
7746     walklist (rcs->other, putrcsfield_proc, (void *) fp);
7747
7748     putc ('\n', fp);
7749 }
7750
7751 static void
7752 putdelta (RCSVers *vers, FILE *fp)
7753 {
7754     Node *bp, *start;
7755
7756     /* Skip if no revision was supplied, or if it is outdated (cvs admin -o) */
7757     if (vers == NULL || vers->outdated)
7758         return;
7759
7760     fprintf (fp, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
7761              vers->version,
7762              RCSDATE, vers->date,
7763              "author", vers->author,
7764              "state", vers->state ? vers->state : "");
7765
7766     if (vers->branches != NULL)
7767     {
7768         start = vers->branches->list;
7769         for (bp = start->next; bp != start; bp = bp->next)
7770             fprintf (fp, "\n\t%s", bp->key);
7771     }
7772
7773     fprintf (fp, ";\nnext\t%s;", vers->next ? vers->next : "");
7774
7775     walklist (vers->other_delta, putrcsfield_proc, fp);
7776
7777 #ifdef PRESERVE_PERMISSIONS_SUPPORT
7778     if (vers->hardlinks)
7779     {
7780         fprintf (fp, "\nhardlinks");
7781         walklist (vers->hardlinks, puthardlink_proc, fp);
7782         putc (';', fp);
7783     }
7784 #endif
7785     putc ('\n', fp);
7786 }
7787
7788 static void
7789 RCS_putdtree (RCSNode *rcs, char *rev, FILE *fp)
7790 {
7791     RCSVers *versp;
7792     Node *p, *branch;
7793
7794     if (rev == NULL)
7795         return;
7796
7797     /* Find the delta node for this revision. */
7798     p = findnode (rcs->versions, rev);
7799     if (p == NULL)
7800     {
7801         error (1, 0,
7802                "error parsing repository file %s, file may be corrupt.", 
7803                rcs->path);
7804     }
7805  
7806     versp = p->data;
7807
7808     /* Print the delta node and recurse on its `next' node.  This prints
7809        the trunk.  If there are any branches printed on this revision,
7810        print those trunks as well. */
7811     putdelta (versp, fp);
7812     RCS_putdtree (rcs, versp->next, fp);
7813     if (versp->branches != NULL)
7814     {
7815         branch = versp->branches->list;
7816         for (p = branch->next; p != branch; p = p->next)
7817             RCS_putdtree (rcs, p->key, fp);
7818     }
7819 }
7820
7821 static void
7822 RCS_putdesc (RCSNode *rcs, FILE *fp)
7823 {
7824     fprintf (fp, "\n\n%s\n@", RCSDESC);
7825     if (rcs->desc != NULL)
7826     {
7827         off_t len = (off_t) strlen (rcs->desc);
7828         if (len > 0)
7829         {
7830             expand_at_signs (rcs->desc, len, fp);
7831             if (rcs->desc[len-1] != '\n')
7832                 putc ('\n', fp);
7833         }
7834     }
7835     fputs ("@\n", fp);
7836 }
7837
7838 static void
7839 putdeltatext (FILE *fp, Deltatext *d)
7840 {
7841     fprintf (fp, "\n\n%s\nlog\n@", d->version);
7842     if (d->log != NULL)
7843     {
7844         int loglen = strlen (d->log);
7845         expand_at_signs (d->log, (off_t) loglen, fp);
7846         if (d->log[loglen-1] != '\n')
7847             putc ('\n', fp);
7848     }
7849     putc ('@', fp);
7850
7851     walklist (d->other, putrcsfield_proc, fp);
7852
7853     fputs ("\ntext\n@", fp);
7854     if (d->text != NULL)
7855         expand_at_signs (d->text, (off_t) d->len, fp);
7856     fputs ("@\n", fp);
7857 }
7858
7859 /* TODO: the whole mechanism for updating deltas is kludgey... more
7860    sensible would be to supply all the necessary info in a `newdeltatext'
7861    field for RCSVers nodes. -twp */
7862
7863 /* Copy delta text nodes from FIN to FOUT.  If NEWDTEXT is non-NULL, it
7864    is a new delta text node, and should be added to the tree at the
7865    node whose revision number is INSERTPT.  (Note that trunk nodes are
7866    written in decreasing order, and branch nodes are written in
7867    increasing order.) */
7868
7869 static void
7870 RCS_copydeltas (RCSNode *rcs, FILE *fin, struct rcsbuffer *rcsbufin, FILE *fout, Deltatext *newdtext, char *insertpt)
7871 {
7872     int actions;
7873     RCSVers *dadmin;
7874     Node *np;
7875     int insertbefore, found;
7876     char *bufrest;
7877     int nls;
7878     size_t buflen;
7879 #ifndef HAVE_MMAP
7880     char buf[8192];
7881     int got;
7882 #endif
7883
7884     /* Count the number of versions for which we have to do some
7885        special operation.  */
7886     actions = walklist (rcs->versions, count_delta_actions, (void *) NULL);
7887
7888     /* Make a note of whether NEWDTEXT should be inserted
7889        before or after its INSERTPT. */
7890     insertbefore = (newdtext != NULL && numdots (newdtext->version) == 1);
7891
7892     while (actions != 0 || newdtext != NULL)
7893     {
7894         Deltatext *dtext;
7895
7896         dtext = RCS_getdeltatext (rcs, fin, rcsbufin);
7897
7898         /* We shouldn't hit EOF here, because that would imply that
7899            some action was not taken, or that we could not insert
7900            NEWDTEXT.  */
7901         if (dtext == NULL)
7902             error (1, 0, "internal error: EOF too early in RCS_copydeltas");
7903
7904         found = (insertpt != NULL && STREQ (dtext->version, insertpt));
7905         if (found && insertbefore)
7906         {
7907             putdeltatext (fout, newdtext);
7908             newdtext = NULL;
7909             insertpt = NULL;
7910         }
7911
7912         np = findnode (rcs->versions, dtext->version);
7913         dadmin = np->data;
7914
7915         /* If this revision has been outdated, just skip it. */
7916         if (dadmin->outdated)
7917         {
7918             freedeltatext (dtext);
7919             --actions;
7920             continue;
7921         }
7922            
7923         /* Update the change text for this delta.  New change text
7924            data may come from cvs admin -m, cvs admin -o, or cvs ci. */
7925         if (dadmin->text != NULL)
7926         {
7927             if (dadmin->text->log != NULL || dadmin->text->text != NULL)
7928                 --actions;
7929             if (dadmin->text->log != NULL)
7930             {
7931                 free (dtext->log);
7932                 dtext->log = dadmin->text->log;
7933                 dadmin->text->log = NULL;
7934             }
7935             if (dadmin->text->text != NULL)
7936             {
7937                 free (dtext->text);
7938                 dtext->text = dadmin->text->text;
7939                 dtext->len = dadmin->text->len;
7940                 dadmin->text->text = NULL;
7941             }
7942         }
7943         putdeltatext (fout, dtext);
7944         freedeltatext (dtext);
7945
7946         if (found && !insertbefore)
7947         {
7948             putdeltatext (fout, newdtext);
7949             newdtext = NULL;
7950             insertpt = NULL;
7951         }
7952     }
7953
7954     /* Copy the rest of the file directly, without bothering to
7955        interpret it.  The caller will handle error checking by calling
7956        ferror.
7957
7958        We just wrote a newline to the file, either in putdeltatext or
7959        in the caller.  However, we may not have read the corresponding
7960        newline from the file, because rcsbuf_getkey returns as soon as
7961        it finds the end of the '@' string for the desc or text key.
7962        Therefore, we may read three newlines when we should really
7963        only write two, and we check for that case here.  This is not
7964        an semantically important issue; we only do it to make our RCS
7965        files look traditional.  */
7966
7967     nls = 3;
7968
7969     rcsbuf_get_buffered (rcsbufin, &bufrest, &buflen);
7970     if (buflen > 0)
7971     {
7972         if (bufrest[0] != '\n'
7973             || strncmp (bufrest, "\n\n\n", buflen < 3 ? buflen : 3) != 0)
7974         {
7975             nls = 0;
7976         }
7977         else
7978         {
7979             if (buflen < 3)
7980                 nls -= buflen;
7981             else
7982             {
7983                 ++bufrest;
7984                 --buflen;
7985                 nls = 0;
7986             }
7987         }
7988
7989         fwrite (bufrest, 1, buflen, fout);
7990     }
7991 #ifndef HAVE_MMAP
7992     /* This bit isn't necessary when using mmap since the entire file
7993      * will already be available via the RCS buffer.  Besides, the
7994      * mmap code doesn't always keep the file pointer up to date, so
7995      * this adds some data twice.
7996      */
7997     while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
7998     {
7999         if (nls > 0
8000             && got >= nls
8001             && buf[0] == '\n'
8002             && strncmp (buf, "\n\n\n", nls) == 0)
8003         {
8004             fwrite (buf + 1, 1, got - 1, fout);
8005         }
8006         else
8007         {
8008             fwrite (buf, 1, got, fout);
8009         }
8010
8011         nls = 0;
8012     }
8013 #endif /* HAVE_MMAP */
8014 }
8015
8016 /* A helper procedure for RCS_copydeltas.  This is called via walklist
8017    to count the number of RCS revisions for which some special action
8018    is required.  */
8019
8020 static int
8021 count_delta_actions (Node *np, void *ignore)
8022 {
8023     RCSVers *dadmin = np->data;
8024
8025     if (dadmin->outdated)
8026         return 1;
8027
8028     if (dadmin->text != NULL
8029         && (dadmin->text->log != NULL || dadmin->text->text != NULL))
8030     {
8031         return 1;
8032     }
8033
8034     return 0;
8035 }
8036
8037
8038
8039 /*
8040  * Clean up temporary files.
8041  *
8042  * NOTES
8043  *   This function needs to be reentrant since a call to exit() can cause a
8044  *   call to this function, which can then be interrupted by a signal, which
8045  *   can cause a second call to this function.
8046  *
8047  * RETURNS
8048  *   Nothing.
8049  */
8050 static void
8051 rcs_cleanup (void)
8052 {
8053     static short int never_run_again = 0;
8054
8055     TRACE (TRACE_FUNCTION, "rcs_cleanup()");
8056
8057     /* Since main_cleanup() always calls exit() (via error (1, ...)), we avoid
8058      * allowing this function to be called twice as an optimization.
8059      *
8060      * If we are already in a signal critical section, assume we were called
8061      * via the signal handler and set a flag which will prevent future calls.
8062      * The only time that we should get into one of these functions otherwise
8063      * while still in a critical section is if error(1,...) is called from a
8064      * critical section, in which case we are exiting and interrupts are
8065      * already being ignored.
8066      *
8067      * For Lock_Cleanup(), this is not a run_once variable since Lock_Cleanup()
8068      * can be called to clean up the current lock set multiple times by the
8069      * same run of a CVS command.
8070      *
8071      * For server_cleanup() and rcs_cleanup(), this is not a run_once variable
8072      * since a call to the cleanup function from atexit() could be interrupted
8073      * by the interrupt handler.
8074      */
8075     if (never_run_again) return;
8076     if (SIG_inCrSect()) never_run_again = 1;
8077
8078     /* FIXME: Do not perform buffered I/O from an interrupt handler like
8079      * this (via error).  However, I'm leaving the error-calling code there
8080      * in the hope that on the rare occasion the error call is actually made
8081      * (e.g., a fluky I/O error or permissions problem prevents the deletion
8082      * of a just-created file) reentrancy won't be an issue.
8083      */
8084
8085     /* Avoid being interrupted during calls which set globals to NULL.  This
8086      * avoids having interrupt handlers attempt to use these global variables
8087      * in inconsistent states.
8088      */
8089     SIG_beginCrSect();
8090     if (rcs_lockfile != NULL)
8091     {
8092         /* Use a tmp var since any of these functions could call exit, causing
8093          * us to be called a second time.
8094          */
8095         char *tmp = rcs_lockfile;
8096         rcs_lockfile = NULL;
8097         if (rcs_lockfd >= 0)
8098         {
8099             if (close (rcs_lockfd) != 0)
8100                 error (0, errno, "error closing lock file %s", tmp);
8101             rcs_lockfd = -1;
8102         }
8103
8104         /* Note that the checks for existence_error are because we can be
8105          * called from a signal handler, so we don't know whether the
8106          * files got created.
8107          */
8108         if (unlink_file (tmp) < 0
8109             && !existence_error (errno))
8110             error (0, errno, "cannot remove %s", tmp);
8111     }
8112     SIG_endCrSect();
8113 }
8114
8115
8116
8117 /* RCS_internal_lockfile and RCS_internal_unlockfile perform RCS-style
8118    locking on the specified RCSFILE: for a file called `foo,v', open
8119    for writing a file called `,foo,'.
8120
8121    Note that we what do here is quite different from what RCS does.
8122    RCS creates the ,foo, file before it reads the RCS file (if it
8123    knows that it will be writing later), so that it actually serves as
8124    a lock.  We don't; instead we rely on CVS writelocks.  This means
8125    that if someone is running RCS on the file at the same time they
8126    are running CVS on it, they might lose (we read the file,
8127    then RCS writes it, then we write it, clobbering the
8128    changes made by RCS).  I believe the current sentiment about this
8129    is "well, don't do that".
8130
8131    A concern has been expressed about whether adopting the RCS
8132    strategy would slow us down.  I don't think so, since we need to
8133    write the ,foo, file anyway (unless perhaps if O_EXCL is slower or
8134    something).
8135
8136    These do not perform quite the same function as the RCS -l option
8137    for locking files: they are intended to prevent competing RCS
8138    processes from stomping all over each other's laundry.  Hence,
8139    they are `internal' locking functions.
8140
8141    If there is an error, give a fatal error; if we return we always
8142    return a non-NULL value.  */
8143
8144 static FILE *
8145 rcs_internal_lockfile (char *rcsfile)
8146 {
8147     struct stat rstat;
8148     FILE *fp;
8149     static int first_call = 1;
8150
8151     if (first_call)
8152     {
8153         first_call = 0;
8154         /* Clean up if we get a signal or exit.  */
8155         cleanup_register (rcs_cleanup);
8156     }
8157
8158     /* Get the lock file name: `,file,' for RCS file `file,v'. */
8159     assert (rcs_lockfile == NULL);
8160     assert (rcs_lockfd < 0);
8161     rcs_lockfile = rcs_lockfilename (rcsfile);
8162
8163     /* Use the existing RCS file mode, or read-only if this is a new
8164        file.  (Really, this is a lie -- if this is a new file,
8165        RCS_checkin uses the permissions from the working copy.  For
8166        actually creating the file, we use 0444 as a safe default mode.) */
8167     if( CVS_STAT( rcsfile, &rstat ) < 0 )
8168     {
8169         if (existence_error (errno))
8170             rstat.st_mode = S_IRUSR | S_IRGRP | S_IROTH;
8171         else
8172             error (1, errno, "cannot stat %s", rcsfile);
8173     }
8174
8175     /* Try to open exclusively.  POSIX.1 guarantees that O_EXCL|O_CREAT
8176        guarantees an exclusive open.  According to the RCS source, with
8177        NFS v2 we must also throw in O_TRUNC and use an open mask that makes
8178        the file unwriteable.  For extensive justification, see the comments for
8179        rcswriteopen() in rcsedit.c, in RCS 5.7.  This is kind of pointless
8180        in the CVS case; see comment at the start of this file concerning
8181        general ,foo, file strategy.
8182
8183        There is some sentiment that with NFSv3 and such, that one can
8184        rely on O_EXCL these days.  This might be true for unix (I
8185        don't really know), but I am still pretty skeptical in the case
8186        of the non-unix systems.  */
8187     rcs_lockfd = open (rcs_lockfile,
8188                        OPEN_BINARY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
8189                        S_IRUSR | S_IRGRP | S_IROTH);
8190
8191     if (rcs_lockfd < 0)
8192     {
8193         error (1, errno, "could not open lock file `%s'", rcs_lockfile);
8194     }
8195
8196     /* Force the file permissions, and return a stream object. */
8197     /* Because we change the modes later, we don't worry about
8198        this in the non-HAVE_FCHMOD case.  */
8199 #ifdef HAVE_FCHMOD
8200     if (fchmod (rcs_lockfd, rstat.st_mode) < 0)
8201         error (1, errno, "cannot change mode for %s", rcs_lockfile);
8202 #endif
8203     fp = fdopen (rcs_lockfd, FOPEN_BINARY_WRITE);
8204     if (fp == NULL)
8205         error (1, errno, "cannot fdopen %s", rcs_lockfile);
8206
8207     return fp;
8208 }
8209
8210 static void
8211 rcs_internal_unlockfile (FILE *fp, char *rcsfile)
8212 {
8213     assert (rcs_lockfile != NULL);
8214     assert (rcs_lockfd >= 0);
8215
8216     /* Abort if we could not write everything successfully to LOCKFILE.
8217        This is not a great error-handling mechanism, but should prevent
8218        corrupting the repository. */
8219
8220     if (ferror (fp))
8221         /* Using errno here may well be misleanding since the most recent
8222            call that set errno may not have anything whatsoever to do with
8223            the error that set the flag, but it's better than nothing.  The
8224            real solution is to check each call to fprintf rather than waiting
8225            until the end like this.  */
8226         error (1, errno, "error writing to lock file %s", rcs_lockfile);
8227     if (fclose (fp) == EOF)
8228         error (1, errno, "error closing lock file %s", rcs_lockfile);
8229     rcs_lockfd = -1;
8230
8231     rename_file (rcs_lockfile, rcsfile);
8232
8233     {
8234         /* Use a temporary to make sure there's no interval
8235            (after rcs_lockfile has been freed but before it's set to NULL)
8236            during which the signal handler's use of rcs_lockfile would
8237            reference freed memory.  */
8238         char *tmp = rcs_lockfile;
8239         rcs_lockfile = NULL;
8240         free (tmp);
8241     }
8242 }
8243
8244 static char *
8245 rcs_lockfilename (const char *rcsfile)
8246 {
8247     char *lockfile, *lockp;
8248     const char *rcsbase, *rcsp, *rcsend;
8249     int rcslen;
8250
8251     /* Create the lockfile name. */
8252     rcslen = strlen (rcsfile);
8253     lockfile = (char *) xmalloc (rcslen + 10);
8254     rcsbase = last_component (rcsfile);
8255     rcsend = rcsfile + rcslen - sizeof(RCSEXT);
8256     for (lockp = lockfile, rcsp = rcsfile; rcsp < rcsbase; ++rcsp)
8257         *lockp++ = *rcsp;
8258     *lockp++ = ',';
8259     while (rcsp <= rcsend)
8260         *lockp++ = *rcsp++;
8261     *lockp++ = ',';
8262     *lockp = '\0';
8263
8264     return lockfile;
8265 }
8266
8267 /* Rewrite an RCS file.  The basic idea here is that the caller should
8268    first call RCS_reparsercsfile, then munge the data structures as
8269    desired (via RCS_delete_revs, RCS_settag, &c), then call RCS_rewrite.  */
8270
8271 void
8272 RCS_rewrite (RCSNode *rcs, Deltatext *newdtext, char *insertpt)
8273 {
8274     FILE *fin, *fout;
8275     struct rcsbuffer rcsbufin;
8276
8277     if (noexec)
8278         return;
8279
8280     /* Make sure we're operating on an actual file and not a symlink.  */
8281     resolve_symlink (&(rcs->path));
8282
8283     fout = rcs_internal_lockfile (rcs->path);
8284
8285     RCS_putadmin (rcs, fout);
8286     RCS_putdtree (rcs, rcs->head, fout);
8287     RCS_putdesc (rcs, fout);
8288
8289     /* Open the original RCS file and seek to the first delta text. */
8290     rcsbuf_cache_open (rcs, rcs->delta_pos, &fin, &rcsbufin);
8291
8292     /* Update delta_pos to the current position in the output file.
8293        Do NOT move these statements: they must be done after fin has
8294        been positioned at the old delta_pos, but before any delta
8295        texts have been written to fout.
8296      */
8297     rcs->delta_pos = ftello (fout);
8298     if (rcs->delta_pos == -1)
8299         error (1, errno, "cannot ftello in RCS file %s", rcs->path);
8300
8301     RCS_copydeltas (rcs, fin, &rcsbufin, fout, newdtext, insertpt);
8302
8303     /* We don't want to call rcsbuf_cache here, since we're about to
8304        delete the file.  */
8305     rcsbuf_close (&rcsbufin);
8306     if (ferror (fin))
8307         /* The only case in which using errno here would be meaningful
8308            is if we happen to have left errno unmolested since the call
8309            which produced the error (e.g. fread).  That is pretty
8310            fragile even if it happens to sometimes be true.  The real
8311            solution is to make sure that all the code which reads
8312            from fin checks for errors itself (some does, some doesn't).  */
8313         error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
8314     if (fclose (fin) < 0)
8315         error (0, errno, "warning: closing RCS file `%s'", rcs->path);
8316
8317     rcs_internal_unlockfile (fout, rcs->path);
8318 }
8319
8320 /* Abandon changes to an RCS file. */
8321
8322 void
8323 RCS_abandon (RCSNode *rcs)
8324 {
8325     free_rcsnode_contents (rcs);
8326     rcs->symbols_data = NULL;
8327     rcs->expand = NULL;
8328     rcs->access = NULL;
8329     rcs->locks_data = NULL;
8330     rcs->comment = NULL;
8331     rcs->desc = NULL;
8332     rcs->flags |= PARTIAL;
8333 }
8334
8335 /*
8336  * For a given file with full pathname PATH and revision number REV,
8337  * produce a file label suitable for passing to diff.  The default
8338  * file label as used by RCS 5.7 looks like this:
8339  *
8340  *      FILENAME <tab> YYYY/MM/DD <sp> HH:MM:SS <tab> REVNUM
8341  *
8342  * The date and time used are the revision's last checkin date and time.
8343  * If REV is NULL, use the working copy's mtime instead.
8344  *
8345  * /dev/null is not statted but assumed to have been created on the Epoch.
8346  * At least using the POSIX.2 definition of patch, this should cause creation
8347  * of files on platforms such as Windoze where the null IO device isn't named
8348  * /dev/null to be parsed by patch properly.
8349  */
8350 char *
8351 make_file_label (const char *path, const char *rev, RCSNode *rcs)
8352 {
8353     char datebuf[MAXDATELEN + 1];
8354     char *label;
8355
8356     label = (char *) xmalloc (strlen (path)
8357                               + (rev == NULL ? 0 : strlen (rev) + 1)
8358                               + MAXDATELEN
8359                               + 2);
8360
8361     if (rev)
8362     {
8363         char date[MAXDATELEN + 1];
8364         /* revs cannot be attached to /dev/null ... duh. */
8365         assert (strcmp(DEVNULL, path));
8366         RCS_getrevtime (rcs, rev, datebuf, 0);
8367         (void) date_to_internet (date, datebuf);
8368         (void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
8369     }
8370     else
8371     {
8372         struct stat sb;
8373         struct tm *wm;
8374
8375         if (strcmp(DEVNULL, path))
8376         {
8377             const char *file = last_component (path);
8378             if (CVS_STAT (file, &sb) < 0)
8379                 /* Assume that if the stat fails,then the later read for the
8380                  * diff will too.
8381                  */
8382                 error (1, errno, "could not get info for `%s'", path);
8383             wm = gmtime (&sb.st_mtime);
8384         }
8385         else
8386         {
8387             time_t t = 0;
8388             wm = gmtime(&t);
8389         }
8390
8391         (void) tm_to_internet (datebuf, wm);
8392         (void) sprintf (label, "-L%s\t%s", path, datebuf);
8393     }
8394     return label;
8395 }
8396
8397 void
8398 RCS_setlocalid (const char *arg)
8399 {
8400     char *copy, *next, *key;
8401
8402     copy = xstrdup(arg);
8403     next = copy;
8404     key = strtok(next, "=");
8405
8406     keywords[KEYWORD_LOCALID].string = xstrdup(key);
8407     keywords[KEYWORD_LOCALID].len = strlen(key);
8408     keywords[KEYWORD_LOCALID].expandit = 1;
8409
8410     /* options? */
8411     while ((key = strtok(NULL, ",")) != NULL) {
8412         if (!strcmp(key, keywords[KEYWORD_ID].string))
8413             keyword_local = KEYWORD_ID;
8414         else if (!strcmp(key, keywords[KEYWORD_HEADER].string))
8415             keyword_local = KEYWORD_HEADER;
8416         else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string))
8417             keyword_local = KEYWORD_CVSHEADER;
8418         else
8419             error(1, 0, "Unknown LocalId mode: %s", key);
8420     }
8421     free(copy);
8422 }
8423
8424 void
8425 RCS_setincexc (const char *arg)
8426 {
8427     char *key;
8428     char *copy, *next;
8429     int include = 0;
8430     struct rcs_keyword *keyword;
8431
8432     copy = xstrdup(arg);
8433     next = copy;
8434     switch (*next++) {
8435         case 'e':
8436             include = 0;
8437             break;
8438         case 'i':
8439             include = 1;
8440             break;
8441         default:
8442             free(copy);
8443             return;
8444     }
8445
8446     if (include)
8447         for (keyword = keywords; keyword->string != NULL; keyword++)
8448         {
8449             keyword->expandit = 0;
8450         }
8451
8452     key = strtok(next, ",");
8453     while (key) {
8454         for (keyword = keywords; keyword->string != NULL; keyword++) {
8455             if (strcmp (keyword->string, key) == 0)
8456                 keyword->expandit = include;
8457         }
8458         key = strtok(NULL, ",");
8459     }
8460     free(copy);
8461     return;
8462 }
8463
8464 #define ATTIC "/" CVSATTIC
8465 static char *
8466 getfullCVSname(char *CVSname, char **pathstore)
8467 {
8468     if (current_parsed_root->directory) {
8469         int rootlen;
8470         char *c = NULL;
8471         int alen = sizeof(ATTIC) - 1;
8472
8473         *pathstore = xstrdup(CVSname);
8474         if ((c = strrchr(*pathstore, '/')) != NULL) {
8475             if (c - *pathstore >= alen) {
8476                 if (!strncmp(c - alen, ATTIC, alen)) {
8477                     while (*c != '\0') {
8478                         *(c - alen) = *c;
8479                         c++;
8480                     }
8481                     *(c - alen) = '\0';
8482                 }
8483             }
8484         }
8485
8486         rootlen = strlen(current_parsed_root->directory);
8487         if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) &&
8488             (*pathstore)[rootlen] == '/')
8489             CVSname = (*pathstore + rootlen + 1);
8490         else
8491             CVSname = (*pathstore);
8492     }
8493     return CVSname;
8494 }