update lintian overrides
[alioth/cvs.git] / src / import.c
1 /*
2  * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3  *
4  * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5  *                                  and others.
6  *
7  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8  * Portions Copyright (C) 1989-1992, Brian Berliner
9  * 
10  * You may distribute under the terms of the GNU General Public License as
11  * specified in the README file that comes with the CVS source distribution.
12  * 
13  * "import" checks in the vendor release located in the current directory into
14  * the CVS source repository.  The CVS vendor branch support is utilized.
15  * 
16  * At least three arguments are expected to follow the options:
17  *      repository      Where the source belongs relative to the CVSROOT
18  *      VendorTag       Vendor's major tag
19  *      VendorReleTag   Tag for this particular release
20  *
21  * Additional arguments specify more Vendor Release Tags.
22  */
23
24 #include "cvs.h"
25 #include "lstat.h"
26 #include "save-cwd.h"
27
28 static const char *get_comment (const char *user);
29 static int add_rev (char *message, RCSNode *rcs, char *vfile,
30                           char *vers);
31 static int add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc,
32                      char *targv[]);
33 static int import_descend (char *message, char *vtag, int targc, char *targv[]);
34 static int import_descend_dir (char *message, char *dir, char *vtag,
35                                int targc, char *targv[]);
36 static int process_import_file (char *message, char *vfile, char *vtag,
37                                 int targc, char *targv[]);
38 static int update_rcs_file (char *message, char *vfile, char *vtag, int targc,
39                             char *targv[], int inattic);
40 #ifdef PRESERVE_PERMISSIONS_SUPPORT
41 static int preserve_initial_permissions (FILE *fprcs, const char *userfile,
42                                          mode_t file_type, struct stat *sbp);
43 #endif
44 static int expand_and_copy_contents (FILE *fprcs, mode_t file_type,
45                                      const char *user, FILE *fpuser);
46 static void add_log (int ch, char *fname);
47
48 static int repos_len;
49 static char *vhead;
50 static char *vbranch;
51 static FILE *logfp;
52 static char *repository;
53 static int conflicts;
54 static int use_file_modtime;
55 static char *keyword_opt = NULL;
56 static bool killnew;
57
58 static const char *const import_usage[] =
59 {
60     "Usage: %s %s [-dX] [-k subst] [-I ign] [-m msg] [-b branch]\n",
61     "    [-W spec] repository vendor-tag release-tags...\n",
62     "\t-d\tUse the file's modification time as the time of import.\n",
63     "\t-X\tWhen importing new files, mark their trunk revisions as dead.\n",
64     "\t-k sub\tSet default RCS keyword substitution mode.\n",
65     "\t-I ign\tMore files to ignore (! to reset).\n",
66     "\t-b bra\tVendor branch id.\n",
67     "\t-m msg\tLog message.\n",
68     "\t-W spec\tWrappers specification line.\n",
69     "(Specify the --help global option for a list of other help options)\n",
70     NULL
71 };
72
73 int
74 import (int argc, char **argv)
75 {
76     char *message = NULL;
77     char *tmpfile;
78     char *cp;
79     int i, c, msglen, err;
80     List *ulist;
81     Node *p;
82     struct logfile_info *li;
83
84     if (argc == -1)
85         usage (import_usage);
86
87     /* Force -X behaviour or not based on the CVS repository
88        CVSROOT/config setting.  */
89 #ifdef CLIENT_SUPPORT
90     killnew = !current_parsed_root->isremote
91               && config->ImportNewFilesToVendorBranchOnly;
92 #else /* !CLIENT_SUPPORT */
93     killnew = config->ImportNewFilesToVendorBranchOnly;
94 #endif /* CLIENT_SUPPORT */
95
96
97     ign_setup ();
98     wrap_setup ();
99
100     vbranch = xstrdup (CVSBRANCH);
101     optind = 0;
102     while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:X")) != -1)
103     {
104         switch (c)
105         {
106             case 'Q':
107             case 'q':
108                 /* The CVS 1.5 client sends these options (in addition to
109                    Global_option requests), so we must ignore them.  */
110                 if (!server_active)
111                     error (1, 0,
112                            "-q or -Q must be specified before \"%s\"",
113                            cvs_cmd_name);
114                 break;
115             case 'd':
116                 if (server_active)
117                 {
118                     /* CVS 1.10 and older clients will send this, but it
119                        doesn't do any good.  So tell the user we can't
120                        cope, rather than silently losing.  */
121                     error (0, 0,
122                            "warning: not setting the time of import from the file");
123                     error (0, 0, "due to client limitations");
124                 }
125                 use_file_modtime = 1;
126                 break;
127             case 'b':
128                 free (vbranch);
129                 vbranch = xstrdup (optarg);
130                 break;
131             case 'm':
132 #ifdef FORCE_USE_EDITOR
133                 use_editor = 1;
134 #else
135                 use_editor = 0;
136 #endif
137                 if (message) free (message);
138                 message = xstrdup (optarg);
139                 break;
140             case 'I':
141                 ign_add (optarg, 0);
142                 break;
143             case 'k':
144                 /* RCS_check_kflag returns strings of the form -kxx.  We
145                    only use it for validation, so we can free the value
146                    as soon as it is returned. */
147                 free (RCS_check_kflag (optarg));
148                 keyword_opt = optarg;
149                 break;
150             case 'W':
151                 wrap_add (optarg, 0);
152                 break;
153             case 'X':
154                 killnew = true;
155                 break;
156             case '?':
157             default:
158                 usage (import_usage);
159                 break;
160         }
161     }
162     argc -= optind;
163     argv += optind;
164     if (argc < 3)
165         usage (import_usage);
166
167     /* This is for handling the Checkin-time request.  It might seem a
168        bit odd to enable the use_file_modtime code even in the case
169        where Checkin-time was not sent for a particular file.  The
170        effect is that we use the time of upload, rather than the time
171        when we call RCS_checkin.  Since those times are both during
172        CVS's run, that seems OK, and it is easier to implement than
173        putting the "was Checkin-time sent" flag in CVS/Entries or some
174        such place.  */
175
176     if (server_active)
177         use_file_modtime = 1;
178
179     /* Don't allow "CVS" as any directory in module path.
180      *
181      * Could abstract this to valid_module_path, but I don't think we'll need
182      * to call it from anywhere else.
183      */
184     if ((cp = strstr (argv[0], "CVS")) &&   /* path contains "CVS" AND ... */
185         ((cp == argv[0]) || ISSLASH (*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */
186         ((*(cp+3) == '\0') || ISSLASH (*(cp+3))) /* /CVS$/ OR m#CVS/# */
187        )
188     {
189         error (0, 0,
190                "The word `CVS' is reserved by CVS and may not be used");
191         error (1, 0, "as a directory in a path or as a file name.");
192     }
193
194     for (i = 1; i < argc; i++)          /* check the tags for validity */
195     {
196         int j;
197
198         RCS_check_tag (argv[i]);
199         for (j = 1; j < i; j++)
200             if (strcmp (argv[j], argv[i]) == 0)
201                 error (1, 0, "tag `%s' was specified more than once", argv[i]);
202     }
203
204     if (ISABSOLUTE (argv[0]) || pathname_levels (argv[0]) > 0)
205         /* It is somewhere between a security hole and "unexpected" to
206            let the client start mucking around outside the cvsroot
207            (wouldn't get the right CVSROOT configuration, &c).  */
208         error (1, 0, "directory %s not relative within the repository",
209                argv[0]);
210
211     if (current_parsed_root == NULL)
212     {
213         error (0, 0, "missing CVSROOT environment variable\n");
214         error (1, 0, "Set it or specify the '-d' option to %s.",
215                program_name);
216     }
217     repository = Xasprintf ("%s/%s", current_parsed_root->directory, argv[0]);
218     repos_len = strlen (current_parsed_root->directory);
219
220     /*
221      * Consistency checks on the specified vendor branch.  It must be
222      * composed of only numbers and dots ('.').  Also, for now we only
223      * support branching to a single level, so the specified vendor branch
224      * must only have two dots in it (like "1.1.1").
225      */
226     {
227         regex_t pat;
228         int ret = regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$",
229                            REG_EXTENDED);
230         assert (!ret);
231         if (regexec (&pat, vbranch, 0, NULL, 0))
232         {
233             error (1, 0,
234 "Only numeric branch specifications with two dots are\n"
235 "supported by import, not `%s'.  For example: `1.1.1'.",
236                    vbranch);
237         }
238         regfree (&pat);
239     }
240
241     /*
242      * If you use even vendor branches, something evil[TM] can happen.
243      */
244     {
245         regex_t pat;
246         assert (!regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[0-9]*[13579]$",
247                           REG_EXTENDED));
248         if (regexec (&pat, vbranch, 0, NULL, 0))
249         {
250             error (0, 0,
251                    "warning: you are using an even vendor branch, which can\n"
252                    "lead to problems: '%s'.  Use an odd branch such as '1.1.3' instead.",
253                    vbranch);
254         }
255         regfree (&pat);
256     }
257
258     /* Set vhead to the branch's parent.  */
259     vhead = xstrdup (vbranch);
260     cp = strrchr (vhead, '.');
261     *cp = '\0';
262
263 #ifdef CLIENT_SUPPORT
264     if (current_parsed_root->isremote)
265     {
266         /* For rationale behind calling start_server before do_editor, see
267            commit.c  */
268         start_server ();
269     }
270 #endif
271
272     if (!server_active && use_editor)
273     {
274         do_editor (NULL, &message,
275                    current_parsed_root->isremote ? NULL : repository,
276                    NULL);
277     }
278     msglen = message == NULL ? 0 : strlen (message);
279     if (msglen == 0 || message[msglen - 1] != '\n')
280     {
281         char *nm = xmalloc (msglen + 2);
282         *nm = '\0';
283         if (message != NULL)
284         {
285             (void) strcpy (nm, message);
286             free (message);
287         }
288         (void) strcat (nm + msglen, "\n");
289         message = nm;
290     }
291
292 #ifdef CLIENT_SUPPORT
293     if (current_parsed_root->isremote)
294     {
295         int err;
296
297         if (vbranch[0] != '\0')
298             option_with_arg ("-b", vbranch);
299         option_with_arg ("-m", message ? message : "");
300         if (keyword_opt != NULL)
301             option_with_arg ("-k", keyword_opt);
302         if (killnew)
303             send_arg ("-X");
304         /* The only ignore processing which takes place on the server side
305            is the CVSROOT/cvsignore file.  But if the user specified -I !,
306            the documented behavior is to not process said file.  */
307         if (ign_inhibit_server)
308         {
309             send_arg ("-I");
310             send_arg ("!");
311         }
312         wrap_send ();
313
314         {
315             int i;
316             for (i = 0; i < argc; ++i)
317                 send_arg (argv[i]);
318         }
319
320         logfp = stdin;
321         client_import_setup (repository);
322         err = import_descend (message, argv[1], argc - 2, argv + 2);
323         client_import_done ();
324         if (message)
325             free (message);
326         free (repository);
327         free (vbranch);
328         free (vhead);
329         send_to_server ("import\012", 0);
330         err += get_responses_and_close ();
331         logmsg_cleanup(err);
332         return err;
333     }
334 #endif
335
336     if (!safe_location (NULL))
337     {
338         error (1, 0, "attempt to import the repository");
339     }
340
341     ulist = getlist ();
342     p = getnode ();
343     p->type = UPDATE;
344     p->delproc = update_delproc;
345     p->key = xstrdup ("- Imported sources");
346     li = xmalloc (sizeof (struct logfile_info));
347     li->type = T_TITLE;
348     li->tag = xstrdup (vbranch);
349     li->rev_old = li->rev_new = NULL;
350     p->data = li;
351     (void) addnode (ulist, p);
352     do_verify (&message, repository, ulist);
353
354     /*
355      * Make all newly created directories writable.  Should really use a more
356      * sophisticated security mechanism here.
357      */
358     (void) umask (cvsumask);
359     make_directories (repository);
360
361     /* Create the logfile that will be logged upon completion */
362     if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
363         error (1, errno, "cannot create temporary file `%s'", tmpfile);
364     /* On systems where we can unlink an open file, do so, so it will go
365        away no matter how we exit.  FIXME-maybe: Should be checking for
366        errors but I'm not sure which error(s) we get if we are on a system
367        where one can't unlink open files.  */
368     (void) CVS_UNLINK (tmpfile);
369     (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
370     (void) fprintf (logfp, "Release Tags:\t");
371     for (i = 2; i < argc; i++)
372         (void) fprintf (logfp, "%s\n\t\t", argv[i]);
373     (void) fprintf (logfp, "\n");
374
375     /* Just Do It.  */
376     err = import_descend (message, argv[1], argc - 2, argv + 2);
377     if (conflicts || killnew)
378     {
379         if (!really_quiet)
380         {
381             char buf[20];
382
383             cvs_output_tagged ("+importmergecmd", NULL);
384             cvs_output_tagged ("newline", NULL);
385             if (conflicts)
386                 sprintf (buf, "%d", conflicts);
387             else
388                 strcpy (buf, "No");
389             cvs_output_tagged ("conflicts", buf);
390             cvs_output_tagged ("text", " conflicts created by this import.");
391             cvs_output_tagged ("newline", NULL);
392             cvs_output_tagged ("text",
393                                "Use the following command to help the merge:");
394             cvs_output_tagged ("newline", NULL);
395             cvs_output_tagged ("newline", NULL);
396             cvs_output_tagged ("text", "\t");
397             cvs_output_tagged ("text", program_name);
398             if (CVSroot_cmdline != NULL)
399             {
400                 cvs_output_tagged ("text", " -d ");
401                 cvs_output_tagged ("text", CVSroot_cmdline);
402             }
403             cvs_output_tagged ("text", " checkout -j");
404             cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
405             cvs_output_tagged ("text", " -j");
406             cvs_output_tagged ("mergetag2", argv[2]);
407             cvs_output_tagged ("text", " ");
408             cvs_output_tagged ("repository", argv[0]);
409             cvs_output_tagged ("newline", NULL);
410             cvs_output_tagged ("newline", NULL);
411             cvs_output_tagged ("-importmergecmd", NULL);
412         }
413
414         /* FIXME: I'm not sure whether we need to put this information
415            into the loginfo.  If we do, then note that it does not
416            report any required -d option.  There is no particularly
417            clean way to tell the server about the -d option used by
418            the client.  */
419         if (conflicts)
420             (void) fprintf (logfp, "\n%d", conflicts);
421         else
422             (void) fprintf (logfp, "\nNo");
423         (void) fprintf (logfp, " conflicts created by this import.\n");
424         (void) fprintf (logfp,
425                         "Use the following command to help the merge:\n\n");
426         (void) fprintf (logfp, "\t%s checkout ", program_name);
427         (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
428                         argv[1], argv[1], argv[0]);
429     }
430     else
431     {
432         if (!really_quiet)
433             cvs_output ("\nNo conflicts created by this import\n\n", 0);
434         (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
435     }
436
437     /*
438      * Write out the logfile and clean up.
439      */
440     Update_Logfile (repository, message, logfp, ulist);
441     dellist (&ulist);
442     if (fclose (logfp) < 0)
443         error (0, errno, "error closing %s", tmpfile);
444
445     /* Make sure the temporary file goes away, even on systems that don't let
446        you delete a file that's in use.  */
447     if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
448         error (0, errno, "cannot remove %s", tmpfile);
449     free (tmpfile);
450
451     if (message)
452         free (message);
453     free (repository);
454     free (vbranch);
455     free (vhead);
456
457     logmsg_cleanup(err);
458     return err;
459 }
460
461 /* Process all the files in ".", then descend into other directories.
462    Returns 0 for success, or >0 on error (in which case a message
463    will have been printed).  */
464 static int
465 import_descend (char *message, char *vtag, int targc, char **targv)
466 {
467     DIR *dirp;
468     struct dirent *dp;
469     int err = 0;
470     List *dirlist = NULL;
471
472     /* first, load up any per-directory ignore lists */
473     ign_add_file (CVSDOTIGNORE, 1);
474     wrap_add_file (CVSDOTWRAPPER, 1);
475
476     if (!current_parsed_root->isremote)
477         lock_dir_for_write (repository);
478
479     if ((dirp = CVS_OPENDIR (".")) == NULL)
480     {
481         error (0, errno, "cannot open directory");
482         err++;
483     }
484     else
485     {
486         errno = 0;
487         while ((dp = CVS_READDIR (dirp)) != NULL)
488         {
489             if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
490                 goto one_more_time_boys;
491
492             /* CVS directories are created in the temp directory by
493                server.c because it doesn't special-case import.  So
494                don't print a message about them, regardless of -I!.  */
495             if (server_active && strcmp (dp->d_name, CVSADM) == 0)
496                 goto one_more_time_boys;
497
498             if (ign_name (dp->d_name))
499             {
500                 add_log ('I', dp->d_name);
501                 goto one_more_time_boys;
502             }
503
504             if (
505 #ifdef DT_DIR
506                 (dp->d_type == DT_DIR
507                  || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
508 #else
509                 isdir (dp->d_name)
510 #endif
511                 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
512                 )
513             {
514                 Node *n;
515
516                 if (dirlist == NULL)
517                     dirlist = getlist ();
518
519                 n = getnode ();
520                 n->key = xstrdup (dp->d_name);
521                 addnode (dirlist, n);
522             }
523             else if (
524 #ifdef DT_DIR
525                      dp->d_type == DT_LNK
526                      || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
527 #else
528                      islink (dp->d_name)
529 #endif
530                      )
531             {
532                 add_log ('L', dp->d_name);
533                 err++;
534             }
535             else
536             {
537 #ifdef CLIENT_SUPPORT
538                 if (current_parsed_root->isremote)
539                     err += client_process_import_file (message, dp->d_name,
540                                                        vtag, targc, targv,
541                                                        repository,
542                                                        keyword_opt != NULL &&
543                                                        keyword_opt[0] == 'b',
544                                                        use_file_modtime);
545                 else
546 #endif
547                     err += process_import_file (message, dp->d_name,
548                                                 vtag, targc, targv);
549             }
550         one_more_time_boys:
551             errno = 0;
552         }
553         if (errno != 0)
554         {
555             error (0, errno, "cannot read directory");
556             ++err;
557         }
558         (void) CVS_CLOSEDIR (dirp);
559     }
560
561     if (!current_parsed_root->isremote)
562         Simple_Lock_Cleanup ();
563
564     if (dirlist != NULL)
565     {
566         Node *head, *p;
567
568         head = dirlist->list;
569         for (p = head->next; p != head; p = p->next)
570         {
571             err += import_descend_dir (message, p->key, vtag, targc, targv);
572         }
573
574         dellist (&dirlist);
575     }
576
577     return err;
578 }
579
580 /*
581  * Process the argument import file.
582  */
583 static int
584 process_import_file (char *message, char *vfile, char *vtag, int targc,
585                      char **targv)
586 {
587     char *rcs;
588     int inattic = 0;
589
590     rcs = Xasprintf ("%s/%s%s", repository, vfile, RCSEXT);
591     if (!isfile (rcs))
592     {
593         char *attic_name;
594
595         attic_name = xmalloc (strlen (repository) + strlen (vfile) +
596                               sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
597         (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
598                         vfile, RCSEXT);
599         if (!isfile (attic_name))
600         {
601             int retval;
602             char *free_opt = NULL;
603             char *our_opt = keyword_opt;
604
605             /* If marking newly-imported files as dead, they must be
606                created in the attic!  */
607             if (!killnew)
608                 free (attic_name);
609             else 
610             {
611                 free (rcs);
612                 rcs = attic_name;
613
614                 /* Attempt to make the Attic directory, in case it
615                    does not exist.  */
616                 (void) sprintf (rcs, "%s/%s", repository, CVSATTIC);
617                 if (noexec == 0 && CVS_MKDIR (rcs, 0777 ) != 0 && errno != EEXIST)
618                     error (1, errno, "cannot make directory `%s'", rcs);
619
620                 /* Note that the above clobbered the path name, so we
621                    recreate it here.  */
622                 (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC,
623                                 vfile, RCSEXT);
624             }
625
626             /*
627              * A new import source file; it doesn't exist as a ,v within the
628              * repository nor in the Attic -- create it anew.
629              */
630             add_log ('N', vfile);
631
632 #ifdef SERVER_SUPPORT
633             /* The most reliable information on whether the file is binary
634                is what the client told us.  That is because if the client had
635                the wrong idea about binaryness, it corrupted the file, so
636                we might as well believe the client.  */
637             if (server_active)
638             {
639                 Node *node;
640                 List *entries;
641
642                 /* Reading all the entries for each file is fairly silly, and
643                    probably slow.  But I am too lazy at the moment to do
644                    anything else.  */
645                 entries = Entries_Open (0, NULL);
646                 node = findnode_fn (entries, vfile);
647                 if (node != NULL)
648                 {
649                     Entnode *entdata = node->data;
650
651                     if (entdata->type == ENT_FILE)
652                     {
653                         assert (entdata->options[0] == '-'
654                                 && entdata->options[1] == 'k');
655                         our_opt = xstrdup (entdata->options + 2);
656                         free_opt = our_opt;
657                     }
658                 }
659                 Entries_Close (entries);
660             }
661 #endif
662
663             retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
664                                    vbranch, vtag, targc, targv,
665                                    NULL, 0, logfp, killnew);
666             if (free_opt != NULL)
667                 free (free_opt);
668             free (rcs);
669             return retval;
670         }
671         free (attic_name);
672         inattic = 1;
673     }
674
675     free (rcs);
676     /*
677      * an rcs file exists. have to do things the official, slow, way.
678      */
679     return update_rcs_file (message, vfile, vtag, targc, targv, inattic);
680 }
681
682 /*
683  * The RCS file exists; update it by adding the new import file to the
684  * (possibly already existing) vendor branch.
685  */
686 static int
687 update_rcs_file (char *message, char *vfile, char *vtag, int targc,
688                  char **targv, int inattic)
689 {
690     Vers_TS *vers;
691     int letter;
692     char *tocvsPath;
693     char *expand;
694     struct file_info finfo;
695
696     memset (&finfo, 0, sizeof finfo);
697     finfo.file = vfile;
698     /* Not used, so don't worry about it.  */
699     finfo.update_dir = NULL;
700     finfo.fullname = finfo.file;
701     finfo.repository = repository;
702     finfo.entries = NULL;
703     finfo.rcs = NULL;
704     vers = Version_TS (&finfo, NULL, vbranch, NULL, 1, 0);
705     if (vers->vn_rcs != NULL
706         && !RCS_isdead (vers->srcfile, vers->vn_rcs))
707     {
708         int different;
709
710         /*
711          * The rcs file does have a revision on the vendor branch. Compare
712          * this revision with the import file; if they match exactly, there
713          * is no need to install the new import file as a new revision to the
714          * branch.  Just tag the revision with the new import tags.
715          * 
716          * This is to try to cut down the number of "C" conflict messages for
717          * locally modified import source files.
718          */
719         tocvsPath = wrap_tocvs_process_file (vfile);
720         /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
721            not NULL?  */
722         expand = (vers->srcfile->expand != NULL
723                   && vers->srcfile->expand[0] == 'b') ? "-kb" : "-ko";
724         different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, NULL,
725                                   NULL, expand, vfile);
726         if (tocvsPath)
727             if (unlink_file_dir (tocvsPath) < 0)
728                 error (0, errno, "cannot remove %s", tocvsPath);
729
730         if (!different)
731         {
732             int retval = 0;
733
734             /*
735              * The two files are identical.  Just update the tags, print the
736              * "U", signifying that the file has changed, but needs no
737              * attention, and we're done.
738              */
739             if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
740                 retval = 1;
741             add_log ('U', vfile);
742             freevers_ts (&vers);
743             return retval;
744         }
745     }
746
747     /* We may have failed to parse the RCS file; check just in case */
748     if (vers->srcfile == NULL ||
749         add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
750         add_tags (vers->srcfile, vfile, vtag, targc, targv))
751     {
752         freevers_ts (&vers);
753         return 1;
754     }
755
756     if (vers->srcfile->branch == NULL || inattic ||
757         strcmp (vers->srcfile->branch, vbranch) != 0)
758     {
759         conflicts++;
760         letter = 'C';
761     }
762     else
763         letter = 'U';
764     add_log (letter, vfile);
765
766     freevers_ts (&vers);
767     return 0;
768 }
769
770 /*
771  * Add the revision to the vendor branch
772  */
773 static int
774 add_rev (char *message, RCSNode *rcs, char *vfile, char *vers)
775 {
776     int locked, status, ierrno;
777     char *tocvsPath;
778
779     if (noexec)
780         return 0;
781
782     locked = 0;
783     if (vers != NULL)
784     {
785         /* Before RCS_lock existed, we were directing stdout, as well as
786            stderr, from the RCS command, to DEVNULL.  I wouldn't guess that
787            was necessary, but I don't know for sure.  */
788         /* Earlier versions of this function printed a `fork failed' error
789            when RCS_lock returned an error code.  That's not appropriate
790            now that RCS_lock is librarified, but should the error text be
791            preserved? */
792         if (RCS_lock (rcs, vbranch, 1) != 0)
793             return 1;
794         locked = 1;
795         RCS_rewrite (rcs, NULL, NULL);
796     }
797     tocvsPath = wrap_tocvs_process_file (vfile);
798
799     status = RCS_checkin (rcs, NULL, tocvsPath == NULL ? vfile : tocvsPath,
800                           message, vbranch, 0,
801                           (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
802                            | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
803     ierrno = errno;
804
805     if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
806         error (0, errno, "cannot remove %s", tocvsPath);
807
808     if (status)
809     {
810         if (!noexec)
811         {
812             fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
813                       "ERROR: Check-in of %s failed", rcs->path);
814             error (0, status == -1 ? ierrno : 0,
815                    "ERROR: Check-in of %s failed", rcs->path);
816         }
817         if (locked)
818         {
819             (void) RCS_unlock (rcs, vbranch, 0);
820             RCS_rewrite (rcs, NULL, NULL);
821         }
822         return 1;
823     }
824     return 0;
825 }
826
827 /*
828  * Add the vendor branch tag and all the specified import release tags to the
829  * RCS file.  The vendor branch tag goes on the branch root (1.1.1) while the
830  * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
831  * 1.1.1.2, ...).
832  */
833 static int
834 add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc, char **targv)
835 {
836     int i, ierrno;
837     Vers_TS *vers;
838     int retcode = 0;
839     struct file_info finfo;
840
841     if (noexec)
842         return 0;
843
844     if ((retcode = RCS_settag (rcs, vtag, vbranch)) != 0)
845     {
846         ierrno = errno;
847         fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
848                   "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
849         error (0, retcode == -1 ? ierrno : 0,
850                "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
851         return 1;
852     }
853     RCS_rewrite (rcs, NULL, NULL);
854
855     memset (&finfo, 0, sizeof finfo);
856     finfo.file = vfile;
857     /* Not used, so don't worry about it.  */
858     finfo.update_dir = NULL;
859     finfo.fullname = finfo.file;
860     finfo.repository = repository;
861     finfo.entries = NULL;
862     finfo.rcs = NULL;
863     vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
864     for (i = 0; i < targc; i++)
865     {
866         if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
867             RCS_rewrite (rcs, NULL, NULL);
868         else
869         {
870             ierrno = errno;
871             fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
872                       "WARNING: Couldn't add tag %s to %s", targv[i],
873                       rcs->path);
874             error (0, retcode == -1 ? ierrno : 0,
875                    "WARNING: Couldn't add tag %s to %s", targv[i],
876                    rcs->path);
877         }
878     }
879     freevers_ts (&vers);
880     return 0;
881 }
882
883 /*
884  * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
885  */
886 struct compair
887 {
888     const char *suffix;
889     const char *comlead;
890 };
891
892 static const struct compair comtable[] =
893 {
894
895 /*
896  * comtable pairs each filename suffix with a comment leader. The comment
897  * leader is placed before each line generated by the $Log keyword. This
898  * table is used to guess the proper comment leader from the working file's
899  * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
900  * languages without multiline comments; for others they are optional.
901  *
902  * I believe that the comment leader is unused if you are using RCS 5.7, which
903  * decides what leader to use based on the text surrounding the $Log keyword
904  * rather than a specified comment leader.
905  */
906     {"a", "-- "},                       /* Ada           */
907     {"ada", "-- "},
908     {"adb", "-- "},
909     {"asm", ";; "},                     /* assembler (MS-DOS) */
910     {"ads", "-- "},                     /* Ada           */
911     {"bas", "' "},                      /* Visual Basic code */
912     {"bat", ":: "},                     /* batch (MS-DOS) */
913     {"body", "-- "},                    /* Ada           */
914     {"c", " * "},                       /* C             */
915     {"c++", "// "},                     /* C++ in all its infinite guises */
916     {"cc", "// "},
917     {"cpp", "// "},
918     {"cxx", "// "},
919     {"m", "// "},                       /* Objective-C */
920     {"cl", ";;; "},                     /* Common Lisp   */
921     {"cmd", ":: "},                     /* command (OS/2) */
922     {"cmf", "c "},                      /* CM Fortran    */
923     {"cs", " * "},                      /* C*            */
924     {"csh", "# "},                      /* shell         */
925     {"dlg", " * "},                     /* MS Windows dialog file */
926     {"e", "# "},                        /* efl           */
927     {"epsf", "% "},                     /* encapsulated postscript */
928     {"epsi", "% "},                     /* encapsulated postscript */
929     {"el", "; "},                       /* Emacs Lisp    */
930     {"f", "c "},                        /* Fortran       */
931     {"for", "c "},
932     {"frm", "' "},                      /* Visual Basic form */
933     {"h", " * "},                       /* C-header      */
934     {"hh", "// "},                      /* C++ header    */
935     {"hpp", "// "},
936     {"hxx", "// "},
937     {"in", "# "},                       /* for Makefile.in */
938     {"l", " * "},                       /* lex (conflict between lex and
939                                          * franzlisp) */
940     {"mac", ";; "},                     /* macro (DEC-10, MS-DOS, PDP-11,
941                                          * VMS, etc) */
942     {"mak", "# "},                      /* makefile, e.g. Visual C++ */
943     {"me", ".\\\" "},                   /* me-macros    t/nroff  */
944     {"ml", "; "},                       /* mocklisp      */
945     {"mm", ".\\\" "},                   /* mm-macros    t/nroff  */
946     {"ms", ".\\\" "},                   /* ms-macros    t/nroff  */
947     {"man", ".\\\" "},                  /* man-macros   t/nroff  */
948     {"1", ".\\\" "},                    /* feeble attempt at man pages... */
949     {"2", ".\\\" "},
950     {"3", ".\\\" "},
951     {"4", ".\\\" "},
952     {"5", ".\\\" "},
953     {"6", ".\\\" "},
954     {"7", ".\\\" "},
955     {"8", ".\\\" "},
956     {"9", ".\\\" "},
957     {"p", " * "},                       /* pascal        */
958     {"pas", " * "},
959     {"pl", "# "},                       /* perl (conflict with Prolog) */
960     {"ps", "% "},                       /* postscript    */
961     {"psw", "% "},                      /* postscript wrap */
962     {"pswm", "% "},                     /* postscript wrap */
963     {"r", "# "},                        /* ratfor        */
964     {"rc", " * "},                      /* Microsoft Windows resource file */
965     {"red", "% "},                      /* psl/rlisp     */
966 #ifdef sparc
967     {"s", "! "},                        /* assembler     */
968 #endif
969 #ifdef mc68000
970     {"s", "| "},                        /* assembler     */
971 #endif
972 #ifdef pdp11
973     {"s", "/ "},                        /* assembler     */
974 #endif
975 #ifdef vax
976     {"s", "# "},                        /* assembler     */
977 #endif
978 #ifdef __ksr__
979     {"s", "# "},                        /* assembler     */
980     {"S", "# "},                        /* Macro assembler */
981 #endif
982     {"sh", "# "},                       /* shell         */
983     {"sl", "% "},                       /* psl           */
984     {"spec", "-- "},                    /* Ada           */
985     {"tex", "% "},                      /* tex           */
986     {"y", " * "},                       /* yacc          */
987     {"ye", " * "},                      /* yacc-efl      */
988     {"yr", " * "},                      /* yacc-ratfor   */
989     {"", "# "},                         /* default for empty suffix      */
990     {NULL, "# "}                        /* default for unknown suffix;   */
991 /* must always be last           */
992 };
993
994
995
996 static const char *
997 get_comment (const char *user)
998 {
999     char *cp, *suffix;
1000     char *suffix_path;
1001     int i;
1002     const char *retval;
1003
1004     suffix_path = xmalloc (strlen (user) + 5);
1005     cp = strrchr (user, '.');
1006     if (cp != NULL)
1007     {
1008         cp++;
1009
1010         /*
1011          * Convert to lower-case, since we are not concerned about the
1012          * case-ness of the suffix.
1013          */
1014         (void) strcpy (suffix_path, cp);
1015         for (cp = suffix_path; *cp; cp++)
1016             if (isupper ((unsigned char) *cp))
1017                 *cp = tolower (*cp);
1018         suffix = suffix_path;
1019     }
1020     else
1021         suffix = "";                    /* will use the default */
1022     for (i = 0;; i++)
1023     {
1024         if (comtable[i].suffix == NULL)
1025         {
1026             /* Default.  Note we'll always hit this case before we
1027                ever return NULL.  */
1028             retval = comtable[i].comlead;
1029             break;
1030         }
1031         if (strcmp (suffix, comtable[i].suffix) == 0)
1032         {
1033             retval = comtable[i].comlead;
1034             break;
1035         }
1036     }
1037     free (suffix_path);
1038     return retval;
1039 }
1040
1041 /* Create a new RCS file from scratch.
1042  *
1043  * This probably should be moved to rcs.c now that it is called from
1044  * places outside import.c.
1045  *
1046  * INPUTS
1047  *   message    Log message for the addition.  Not used if add_vhead == NULL.
1048  *   rcs        Filename of the RCS file to create.  Note that if 'do_killnew'
1049  *              is set, this file should be in the Attic directory, and the
1050  *              Attic directory must already exist.
1051  *   user       Filename of the file to serve as the contents of the initial
1052  *              revision.  Even if add_vhead is NULL, we use this to determine
1053  *              the modes to give the new RCS file.
1054  *   add_vhead  Revision number of head that we are adding.  Normally 1.1 but
1055  *              could be another revision as long as ADD_VBRANCH is a branch
1056  *              from it.  If NULL, then just add an empty file without any
1057  *              revisions (similar to the one created by "rcs -i").
1058  *   key_opt    Keyword expansion mode, e.g., "b" for binary.  NULL means the
1059  *              default behavior.
1060  *   add_vbranch
1061  *              Vendor branch to import to, or NULL if none.  If non-NULL, then
1062  *              vtag should also be non-NULL.
1063  *   vtag
1064  *   targc      Number of elements in TARGV.
1065  *   targv      The list of tags to attached to this imported revision.
1066  *   desctext   If non-NULL, description for the file.  If NULL, the
1067  *              description will be empty.
1068  *   desclen    The number of bytes in desctext.
1069  *   add_logfp  Write errors to here as well as via error (), or NULL if we
1070  *              should use only error ().
1071  *   do_killnew Mark newly-imported files as being dead on the trunk, i.e.,
1072  *              as being imported only to the vendor branch.
1073  *
1074  * RETURNS
1075  *   Return value is 0 for success, or nonzero for failure (in which
1076  *   case an error message will have already been printed).
1077  */
1078 int
1079 add_rcs_file (const char *message, const char *rcs, const char *user,
1080               const char *add_vhead, const char *key_opt,
1081               const char *add_vbranch, const char *vtag, int targc,
1082               char **targv, const char *desctext, size_t desclen,
1083               FILE *add_logfp, bool do_killnew)
1084 {
1085     FILE *fprcs, *fpuser;
1086     struct stat sb;
1087     struct tm *ftm;
1088     time_t now;
1089     char altdate1[MAXDATELEN];
1090     char *author;
1091     int i, ierrno, err = 0;
1092     mode_t mode;
1093     char *tocvsPath;
1094     const char *userfile;
1095     char *free_opt = NULL;
1096     mode_t file_type;
1097     char *dead_revision = NULL;
1098
1099     if (noexec)
1100         return 0;
1101
1102     if (do_killnew)
1103     {
1104         char *last_place;
1105         int last_number;
1106
1107         /* If we are marking the newly imported file as dead, we must
1108            have a head revision.  */
1109         if (add_vhead == NULL)
1110             error (1, 0, "killing new file attempted when no head revision is being added");
1111
1112         /* One extra byte for NUL, plus one for carry generated by adding
1113            one to the last number in the add_vhead revision.  */
1114         dead_revision = xmalloc (strlen (add_vhead) + 2);
1115         strcpy (dead_revision, add_vhead);
1116
1117         /* Find the loacation of the last number, which we will increment
1118            and overwrite.  Note that this handles single numbers (w/o
1119            dots), which is probably unnecessary.  */
1120         if ((last_place = strrchr (dead_revision, '.')) != NULL)
1121             last_place++;
1122         else
1123             last_place = dead_revision;
1124         last_number = atoi (last_place);
1125         if (++last_number <= 0)
1126           error (1, 0, "invalid revision number %s", add_vhead);
1127         sprintf (last_place, "%d", last_number);
1128     }
1129
1130     /* Note that as the code stands now, the -k option overrides any
1131        settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1132        whatever).  Some have suggested this should be the other way
1133        around.  As far as I know the documentation doesn't say one way
1134        or the other.  Before making a change of this sort, should think
1135        about what is best, document it (in cvs.texinfo and NEWS), &c.  */
1136
1137     if (key_opt == NULL)
1138     {
1139         if (wrap_name_has (user, WRAP_RCSOPTION))
1140         {
1141             key_opt = free_opt = wrap_rcsoption (user, 0);
1142         }
1143     }
1144
1145     tocvsPath = wrap_tocvs_process_file (user);
1146     userfile = (tocvsPath == NULL ? user : tocvsPath);
1147
1148     /* Opening in text mode is probably never the right thing for the
1149        server (because the protocol encodes text files in a fashion
1150        which does not depend on what the client or server OS is, as
1151        documented in cvsclient.texi), but as long as the server just
1152        runs on unix it is a moot point.  */
1153
1154     /* If PreservePermissions is set, then make sure that the file
1155        is a plain file before trying to open it.  Longstanding (although
1156        often unpopular) CVS behavior has been to follow symlinks, so we
1157        maintain that behavior if PreservePermissions is not on.
1158
1159        NOTE: this error message used to be `cannot fstat', but is now
1160        `cannot lstat'.  I don't see a way around this, since we must
1161        stat the file before opening it. -twp */
1162
1163     if (lstat (userfile, &sb) < 0)
1164     {
1165         /* not fatal, continue import */
1166         if (add_logfp != NULL)
1167             fperrmsg (add_logfp, 0, errno,
1168                           "ERROR: cannot lstat file %s", userfile);
1169         error (0, errno, "cannot lstat file %s", userfile);
1170         goto read_error;
1171     }
1172     file_type = sb.st_mode & S_IFMT;
1173
1174     fpuser = NULL;
1175     if (
1176 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1177         !config->preserve_perms ||
1178 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1179         file_type == S_IFREG)
1180     {
1181         fpuser = CVS_FOPEN (userfile,
1182                             ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1183                              ? "rb"
1184                              : "r")
1185             );
1186         if (fpuser == NULL)
1187         {
1188             /* not fatal, continue import */
1189             if (add_logfp != NULL)
1190                 fperrmsg (add_logfp, 0, errno,
1191                           "ERROR: cannot read file %s", userfile);
1192             error (0, errno, "ERROR: cannot read file %s", userfile);
1193             goto read_error;
1194         }
1195     }
1196
1197     fprcs = CVS_FOPEN (rcs, "w+b");
1198     if (fprcs == NULL)
1199     {
1200         ierrno = errno;
1201         goto write_error_noclose;
1202     }
1203
1204     /*
1205      * putadmin()
1206      */
1207     if (add_vhead != NULL)
1208     {
1209         if (fprintf (fprcs, "head     %s;\012",
1210                      do_killnew ? dead_revision : add_vhead) < 0)
1211             goto write_error;
1212     }
1213     else
1214     {
1215         if (fprintf (fprcs, "head     ;\012") < 0)
1216             goto write_error;
1217     }
1218
1219     /* This sets the default branch.  If using the 'do_killnew' functionality,
1220        where imports don't show up until merged, no default branch should
1221        be set.  */
1222     if (add_vbranch != NULL && ! do_killnew)
1223     {
1224         if (fprintf (fprcs, "branch   %s;\012", add_vbranch) < 0)
1225             goto write_error;
1226     }
1227     if (fprintf (fprcs, "access   ;\012") < 0 ||
1228         fprintf (fprcs, "symbols  ") < 0)
1229     {
1230         goto write_error;
1231     }
1232
1233     for (i = targc - 1; i >= 0; i--)
1234     {
1235         /* RCS writes the symbols backwards */
1236         assert (add_vbranch != NULL);
1237         if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1238             goto write_error;
1239     }
1240
1241     if (add_vbranch != NULL)
1242     {
1243         if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1244             goto write_error;
1245     }
1246     if (fprintf (fprcs, ";\012") < 0)
1247         goto write_error;
1248
1249     if (fprintf (fprcs, "locks    ; strict;\012") < 0 ||
1250         /* XXX - make sure @@ processing works in the RCS file */
1251         fprintf (fprcs, "comment  @%s@;\012", get_comment (user)) < 0)
1252     {
1253         goto write_error;
1254     }
1255
1256     if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1257     {
1258         if (fprintf (fprcs, "expand   @%s@;\012", key_opt) < 0)
1259         {
1260             goto write_error;
1261         }
1262     }
1263
1264     if (fprintf (fprcs, "\012") < 0)
1265       goto write_error;
1266
1267     /* Write the revision(s), with the date and author and so on
1268        (that is "delta" rather than "deltatext" from rcsfile(5)).  */
1269
1270     if (use_file_modtime)
1271         now = sb.st_mtime;
1272     else
1273         (void) time (&now);
1274     ftm = gmtime (&now);
1275     (void) sprintf (altdate1, DATEFORM,
1276                     (long)ftm->tm_year + (ftm->tm_year < 100 ? 0L : 1900L),
1277                     ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1278                     ftm->tm_min, ftm->tm_sec);
1279     author = getcaller ();
1280
1281     if (do_killnew)
1282     {
1283         if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1284         fprintf (fprcs, "date     %s;  author %s;  state %s;\012",
1285                  altdate1, author, RCSDEAD) < 0)
1286         goto write_error;
1287
1288         if (fprintf (fprcs, "branches;\012") < 0)
1289             goto write_error;
1290         if (fprintf (fprcs, "next    %s;\012", add_vhead) < 0)
1291             goto write_error;
1292
1293         if (fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1294             goto write_error;
1295
1296 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1297         /* Store initial permissions if necessary. */
1298         if (config->preserve_perms)
1299         {
1300             if (preserve_initial_permissions (fprcs, userfile,
1301                                               file_type, sbp))
1302                 goto write_error;
1303         }
1304 #endif
1305     }
1306
1307     if (add_vhead != NULL)
1308     {
1309         if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1310         fprintf (fprcs, "date     %s;  author %s;  state Exp;\012",
1311                  altdate1, author) < 0)
1312         goto write_error;
1313
1314         if (fprintf (fprcs, "branches") < 0)
1315             goto write_error;
1316         if (add_vbranch != NULL)
1317         {
1318             if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1319                 goto write_error;
1320         }
1321         if (fprintf (fprcs, ";\012") < 0)
1322             goto write_error;
1323
1324         if (fprintf (fprcs, "next     ;\012") < 0)
1325             goto write_error;
1326
1327         if (fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1328             goto write_error;
1329
1330 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1331         /* Store initial permissions if necessary. */
1332         if (config->preserve_perms)
1333         {
1334             if (preserve_initial_permissions (fprcs, userfile,
1335                                               file_type, sbp))
1336                 goto write_error;
1337         }
1338 #endif
1339
1340         if (add_vbranch != NULL)
1341         {
1342             if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1343                 fprintf (fprcs, "date     %s;  author %s;  state Exp;\012",
1344                          altdate1, author) < 0 ||
1345                 fprintf (fprcs, "branches ;\012") < 0 ||
1346                 fprintf (fprcs, "next     ;\012") < 0 ||
1347                 fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1348                 goto write_error;
1349
1350 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1351             /* Store initial permissions if necessary. */
1352             if (config->preserve_perms)
1353             {
1354                 if (preserve_initial_permissions (fprcs, userfile,
1355                                                   file_type, sbp))
1356                     goto write_error;
1357             }
1358 #endif
1359
1360             if (fprintf (fprcs, "\012") < 0)
1361                 goto write_error;
1362         }
1363     }
1364
1365     /* Now write the description (possibly empty).  */
1366     if (fprintf (fprcs, "\012desc\012") < 0 ||
1367         fprintf (fprcs, "@") < 0)
1368         goto write_error;
1369     if (desctext != NULL)
1370     {
1371         /* The use of off_t not size_t for the second argument is very
1372            strange, since we are dealing with something which definitely
1373            fits in memory.  */
1374         if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1375             goto write_error;
1376     }
1377     if (fprintf (fprcs, "@\012\012\012") < 0)
1378         goto write_error;
1379
1380     /* Now write the log messages and contents for the revision(s) (that
1381        is, "deltatext" rather than "delta" from rcsfile(5)).  */
1382
1383     if (do_killnew)
1384     {
1385         if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1386             fprintf (fprcs, "log\012@") < 0)
1387             goto write_error;
1388         if (fprintf (fprcs, "Revision %s was added on the vendor branch.\012",
1389                      add_vhead) < 0)
1390             goto write_error;
1391         if (fprintf (fprcs, "@\012") < 0 ||
1392             fprintf (fprcs, "text\012@") < 0)
1393         {
1394             goto write_error;
1395         }
1396
1397         /* Now copy over the contents of the file, expanding at signs.  */
1398         if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1399             goto write_error;
1400
1401         if (fprintf (fprcs, "@\012\012") < 0)
1402             goto write_error;
1403     }
1404
1405     if (add_vhead != NULL)
1406     {
1407         if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1408             fprintf (fprcs, "log\012@") < 0)
1409             goto write_error;
1410         if (add_vbranch != NULL)
1411         {
1412             /* We are going to put the log message in the revision on the
1413                branch.  So putting it here too seems kind of redundant, I
1414                guess (and that is what CVS has always done, anyway).  */
1415             if (fprintf (fprcs, "Initial revision\012") < 0)
1416                 goto write_error;
1417         }
1418         else
1419         {
1420             if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1421                 goto write_error;
1422         }
1423         if (fprintf (fprcs, "@\012") < 0 ||
1424             fprintf (fprcs, "text\012@") < 0)
1425         {
1426             goto write_error;
1427         }
1428
1429         /* Now copy over the contents of the file, expanding at signs.
1430          * If config->preserve_perms is set, do this only for regular files.
1431          */
1432         if (!do_killnew)
1433         {
1434             /* Now copy over the contents of the file, expanding at signs,
1435                if not done as part of do_killnew handling above.  */
1436             if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1437                 goto write_error;
1438         }
1439
1440         if (fprintf (fprcs, "@\012\012") < 0)
1441             goto write_error;
1442
1443         if (add_vbranch != NULL)
1444         {
1445             if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1446                 fprintf (fprcs, "log\012@") < 0 ||
1447                 expand_at_signs (message,
1448                                  (off_t) strlen (message), fprcs) < 0 ||
1449                 fprintf (fprcs, "@\012text\012") < 0 ||
1450                 fprintf (fprcs, "@@\012") < 0)
1451                 goto write_error;
1452         }
1453     }
1454
1455     if (fclose (fprcs) == EOF)
1456     {
1457         ierrno = errno;
1458         goto write_error_noclose;
1459     }
1460     /* Close fpuser only if we opened it to begin with. */
1461     if (fpuser != NULL)
1462     {
1463         if (fclose (fpuser) < 0)
1464             error (0, errno, "cannot close %s", user);
1465     }
1466
1467     /*
1468      * Fix the modes on the RCS files.  The user modes of the original
1469      * user file are propagated to the group and other modes as allowed
1470      * by the repository umask, except that all write permissions are
1471      * turned off.
1472      */
1473     mode = (sb.st_mode |
1474             (sb.st_mode & S_IRWXU) >> 3 |
1475             (sb.st_mode & S_IRWXU) >> 6) &
1476            ~cvsumask &
1477            ~(S_IWRITE | S_IWGRP | S_IWOTH);
1478     if (chmod (rcs, mode) < 0)
1479     {
1480         ierrno = errno;
1481         if (add_logfp != NULL)
1482             fperrmsg (add_logfp, 0, ierrno,
1483                       "WARNING: cannot change mode of file %s", rcs);
1484         error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1485         err++;
1486     }
1487     if (tocvsPath)
1488         if (unlink_file_dir (tocvsPath) < 0)
1489                 error (0, errno, "cannot remove %s", tocvsPath);
1490     if (free_opt != NULL)
1491         free (free_opt);
1492     return err;
1493
1494 write_error:
1495     ierrno = errno;
1496     if (fclose (fprcs) < 0)
1497         error (0, errno, "cannot close %s", rcs);
1498 write_error_noclose:
1499     if (fclose (fpuser) < 0)
1500         error (0, errno, "cannot close %s", user);
1501     if (add_logfp != NULL)
1502         fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1503     error (0, ierrno, "ERROR: cannot write file %s", rcs);
1504     if (ierrno == ENOSPC)
1505     {
1506         if (CVS_UNLINK (rcs) < 0)
1507             error (0, errno, "cannot remove %s", rcs);
1508         if (add_logfp != NULL)
1509             fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1510         error (1, 0, "ERROR: out of space - aborting");
1511     }
1512 read_error:
1513     if (tocvsPath)
1514         if (unlink_file_dir (tocvsPath) < 0)
1515             error (0, errno, "cannot remove %s", tocvsPath);
1516
1517     if (free_opt != NULL)
1518         free (free_opt);
1519
1520     return err + 1;
1521 }
1522
1523 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1524 /* Write file permissions and symlink information for a file being
1525  * added into its RCS file.
1526  *
1527  * INPUTS
1528  *   fprcs      FILE pointer for the (newly-created) RCS file.  Permisisons
1529  *              and symlink information should be written here.
1530  *   userfile   Filename of the file being added.  (Used to read symbolic
1531  *              link contents, for symlinks.)
1532  *   file_type  File type of userfile, extracted from sbp->st_mode.
1533  *   sbp        'stat' information for userfile.
1534  *
1535  * RETURNS
1536  *   Return value is 0 for success, or nonzero for failure (in which case
1537  *   no error message has yet been printed).
1538  */
1539 static int
1540 preserve_initial_permissions (fprcs, userfile, file_type, sbp)
1541     FILE *fprcs;
1542     const char *userfile;
1543     mode_t file_type;
1544     struct stat *sbp;
1545 {
1546     if (file_type == S_IFLNK)
1547     {
1548         char *link = Xreadlink (userfile, sbp->st_size);
1549         if (fprintf (fprcs, "symlink\t@") < 0 ||
1550             expand_at_signs (link, strlen (link), fprcs) < 0 ||
1551             fprintf (fprcs, "@;\012") < 0)
1552             goto write_error;
1553         free (link);
1554     }
1555     else
1556     {
1557         if (fprintf (fprcs, "owner\t%u;\012", sbp->st_uid) < 0)
1558             goto write_error;
1559         if (fprintf (fprcs, "group\t%u;\012", sbp->st_gid) < 0)
1560             goto write_error;
1561         if (fprintf (fprcs, "permissions\t%o;\012",
1562                      sbp->st_mode & 07777) < 0)
1563             goto write_error;
1564         switch (file_type)
1565         {
1566             case S_IFREG: break;
1567             case S_IFCHR:
1568             case S_IFBLK:
1569 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1570                 if (fprintf (fprcs, "special\t%s %lu;\012",
1571                              (file_type == S_IFCHR
1572                               ? "character"
1573                               : "block"),
1574                              (unsigned long) sbp->st_rdev) < 0)
1575                     goto write_error;
1576 #else
1577                 error (0, 0,
1578 "can't import %s: unable to import device files on this system",
1579 userfile);
1580 #endif
1581                 break;
1582             default:
1583                 error (0, 0,
1584                        "can't import %s: unknown kind of special file",
1585                        userfile);
1586         }
1587     }
1588     return 0;
1589
1590 write_error:
1591     return 1;
1592 }
1593 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1594
1595 /* Copy file contents into an RCS file, expanding at signs.
1596  *
1597  * If config->preserve_perms is set, nothing is copied if the source is not
1598  * a regular file.
1599  *
1600  * INPUTS
1601  *   fprcs      FILE pointer for the (newly-created) RCS file.  The expanded
1602  *              contents should be written here.
1603  *   file_type  File type of the data source.  No data is copied if
1604  *              preserve_permissions is set and the source is not a
1605  *              regular file.
1606  *   user       Filename of the data source (used to print error messages).
1607  *   fpuser     FILE pointer for the data source, whose data is being
1608  *              copied into the RCS file.
1609  *
1610  * RETURNS
1611  *   Return value is 0 for success, or nonzero for failure (in which case
1612  *   no error message has yet been printed).
1613  */
1614 static int
1615 expand_and_copy_contents (fprcs, file_type, user, fpuser)
1616     FILE *fprcs, *fpuser;
1617     mode_t file_type;
1618     const char *user;
1619 {
1620     if (
1621 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1622         !config->preserve_perms ||
1623 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1624         file_type == S_IFREG)
1625     {
1626         char buf[8192];
1627         unsigned int len;
1628
1629         while (1)
1630         {
1631             len = fread (buf, 1, sizeof buf, fpuser);
1632             if (len == 0)
1633             {
1634                 if (ferror (fpuser))
1635                     error (1, errno, "cannot read file %s for copying",
1636                            user);
1637                 break;
1638             }
1639             if (expand_at_signs (buf, len, fprcs) < 0)
1640                 goto write_error;
1641         }
1642     }
1643     return 0;
1644
1645 write_error:
1646     return 1;
1647 }
1648
1649 /*
1650  * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1651  * signs.  If an error occurs, return a negative value and set errno
1652  * to indicate the error.  If not, return a nonnegative value.
1653  */
1654 int
1655 expand_at_signs (const char *buf, size_t size, FILE *fp)
1656 {
1657     register const char *cp, *next;
1658
1659     cp = buf;
1660     while ((next = memchr (cp, '@', size)) != NULL)
1661     {
1662         size_t len = ++next - cp;
1663         if (fwrite (cp, 1, len, fp) != len)
1664             return EOF;
1665         if (putc ('@', fp) == EOF)
1666             return EOF;
1667         cp = next;
1668         size -= len;
1669     }
1670
1671     if (fwrite (cp, 1, size, fp) != size)
1672         return EOF;
1673
1674     return 1;
1675 }
1676
1677 /*
1678  * Write an update message to (potentially) the screen and the log file.
1679  */
1680 static void
1681 add_log (int ch, char *fname)
1682 {
1683     if (!really_quiet)                  /* write to terminal */
1684     {
1685         char buf[2];
1686         buf[0] = ch;
1687         buf[1] = ' ';
1688         cvs_output (buf, 2);
1689         if (repos_len)
1690         {
1691             cvs_output (repository + repos_len + 1, 0);
1692             cvs_output ("/", 1);
1693         }
1694         else if (repository[0] != '\0')
1695         {
1696             cvs_output (repository, 0);
1697             cvs_output ("/", 1);
1698         }
1699         cvs_output (fname, 0);
1700         cvs_output ("\n", 1);
1701     }
1702
1703     if (repos_len)                      /* write to logfile */
1704         (void) fprintf (logfp, "%c %s/%s\n", ch,
1705                         repository + repos_len + 1, fname);
1706     else if (repository[0])
1707         (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1708     else
1709         (void) fprintf (logfp, "%c %s\n", ch, fname);
1710 }
1711
1712 /*
1713  * This is the recursive function that walks the argument directory looking
1714  * for sub-directories that have CVS administration files in them and updates
1715  * them recursively.
1716  * 
1717  * Note that we do not follow symbolic links here, which is a feature!
1718  */
1719 static int
1720 import_descend_dir (char *message, char *dir, char *vtag, int targc,
1721                     char **targv)
1722 {
1723     struct saved_cwd cwd;
1724     char *cp;
1725     int ierrno, err;
1726     char *rcs = NULL;
1727
1728     if (islink (dir))
1729         return 0;
1730     if (save_cwd (&cwd))
1731     {
1732         fperrmsg (logfp, 0, errno, "Failed to save current directory.");
1733         return 1;
1734     }
1735
1736     /* Concatenate DIR to the end of REPOSITORY.  */
1737     if (repository[0] == '\0')
1738     {
1739         char *new = xstrdup (dir);
1740         free (repository);
1741         repository = new;
1742     }
1743     else
1744     {
1745         char *new = Xasprintf ("%s/%s", repository, dir);
1746         free (repository);
1747         repository = new;
1748     }
1749
1750     if (!quiet && !current_parsed_root->isremote)
1751         error (0, 0, "Importing %s", repository);
1752
1753     if (CVS_CHDIR (dir) < 0)
1754     {
1755         ierrno = errno;
1756         fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1757         error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1758         err = 1;
1759         goto out;
1760     }
1761     if (!current_parsed_root->isremote && !isdir (repository))
1762     {
1763         rcs = Xasprintf ("%s%s", repository, RCSEXT);
1764         if (isfile (repository) || isfile (rcs))
1765         {
1766             fperrmsg (logfp, 0, 0,
1767                       "ERROR: %s is a file, should be a directory!",
1768                       repository);
1769             error (0, 0, "ERROR: %s is a file, should be a directory!",
1770                    repository);
1771             err = 1;
1772             goto out;
1773         }
1774         if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1775         {
1776             ierrno = errno;
1777             fperrmsg (logfp, 0, ierrno,
1778                       "ERROR: cannot mkdir %s -- not added", repository);
1779             error (0, ierrno,
1780                    "ERROR: cannot mkdir %s -- not added", repository);
1781             err = 1;
1782             goto out;
1783         }
1784     }
1785     err = import_descend (message, vtag, targc, targv);
1786   out:
1787     if (rcs != NULL)
1788         free (rcs);
1789     if ((cp = strrchr (repository, '/')) != NULL)
1790         *cp = '\0';
1791     else
1792         repository[0] = '\0';
1793     if (restore_cwd (&cwd))
1794         error (1, errno, "Failed to restore current directory, `%s'.",
1795                cwd.name);
1796     free_cwd (&cwd);
1797     return err;
1798 }