wrap and sort CLEANFILES
[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 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 for example: '1.1.3' or '1.1.5'.",
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     char *suffix, *comlead;
889 };
890
891 static const struct compair comtable[] =
892 {
893
894 /*
895  * comtable pairs each filename suffix with a comment leader. The comment
896  * leader is placed before each line generated by the $Log keyword. This
897  * table is used to guess the proper comment leader from the working file's
898  * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
899  * languages without multiline comments; for others they are optional.
900  *
901  * I believe that the comment leader is unused if you are using RCS 5.7, which
902  * decides what leader to use based on the text surrounding the $Log keyword
903  * rather than a specified comment leader.
904  */
905     {"a", "-- "},                       /* Ada           */
906     {"ada", "-- "},
907     {"adb", "-- "},
908     {"asm", ";; "},                     /* assembler (MS-DOS) */
909     {"ads", "-- "},                     /* Ada           */
910     {"bas", "' "},                      /* Visual Basic code */
911     {"bat", ":: "},                     /* batch (MS-DOS) */
912     {"body", "-- "},                    /* Ada           */
913     {"c", " * "},                       /* C             */
914     {"c++", "// "},                     /* C++ in all its infinite guises */
915     {"cc", "// "},
916     {"cpp", "// "},
917     {"cxx", "// "},
918     {"m", "// "},                       /* Objective-C */
919     {"cl", ";;; "},                     /* Common Lisp   */
920     {"cmd", ":: "},                     /* command (OS/2) */
921     {"cmf", "c "},                      /* CM Fortran    */
922     {"cs", " * "},                      /* C*            */
923     {"csh", "# "},                      /* shell         */
924     {"dlg", " * "},                     /* MS Windows dialog file */
925     {"e", "# "},                        /* efl           */
926     {"epsf", "% "},                     /* encapsulated postscript */
927     {"epsi", "% "},                     /* encapsulated postscript */
928     {"el", "; "},                       /* Emacs Lisp    */
929     {"f", "c "},                        /* Fortran       */
930     {"for", "c "},
931     {"frm", "' "},                      /* Visual Basic form */
932     {"h", " * "},                       /* C-header      */
933     {"hh", "// "},                      /* C++ header    */
934     {"hpp", "// "},
935     {"hxx", "// "},
936     {"in", "# "},                       /* for Makefile.in */
937     {"l", " * "},                       /* lex (conflict between lex and
938                                          * franzlisp) */
939     {"mac", ";; "},                     /* macro (DEC-10, MS-DOS, PDP-11,
940                                          * VMS, etc) */
941     {"mak", "# "},                      /* makefile, e.g. Visual C++ */
942     {"me", ".\\\" "},                   /* me-macros    t/nroff  */
943     {"ml", "; "},                       /* mocklisp      */
944     {"mm", ".\\\" "},                   /* mm-macros    t/nroff  */
945     {"ms", ".\\\" "},                   /* ms-macros    t/nroff  */
946     {"man", ".\\\" "},                  /* man-macros   t/nroff  */
947     {"1", ".\\\" "},                    /* feeble attempt at man pages... */
948     {"2", ".\\\" "},
949     {"3", ".\\\" "},
950     {"4", ".\\\" "},
951     {"5", ".\\\" "},
952     {"6", ".\\\" "},
953     {"7", ".\\\" "},
954     {"8", ".\\\" "},
955     {"9", ".\\\" "},
956     {"p", " * "},                       /* pascal        */
957     {"pas", " * "},
958     {"pl", "# "},                       /* perl (conflict with Prolog) */
959     {"ps", "% "},                       /* postscript    */
960     {"psw", "% "},                      /* postscript wrap */
961     {"pswm", "% "},                     /* postscript wrap */
962     {"r", "# "},                        /* ratfor        */
963     {"rc", " * "},                      /* Microsoft Windows resource file */
964     {"red", "% "},                      /* psl/rlisp     */
965 #ifdef sparc
966     {"s", "! "},                        /* assembler     */
967 #endif
968 #ifdef mc68000
969     {"s", "| "},                        /* assembler     */
970 #endif
971 #ifdef pdp11
972     {"s", "/ "},                        /* assembler     */
973 #endif
974 #ifdef vax
975     {"s", "# "},                        /* assembler     */
976 #endif
977 #ifdef __ksr__
978     {"s", "# "},                        /* assembler     */
979     {"S", "# "},                        /* Macro assembler */
980 #endif
981     {"sh", "# "},                       /* shell         */
982     {"sl", "% "},                       /* psl           */
983     {"spec", "-- "},                    /* Ada           */
984     {"tex", "% "},                      /* tex           */
985     {"y", " * "},                       /* yacc          */
986     {"ye", " * "},                      /* yacc-efl      */
987     {"yr", " * "},                      /* yacc-ratfor   */
988     {"", "# "},                         /* default for empty suffix      */
989     {NULL, "# "}                        /* default for unknown suffix;   */
990 /* must always be last           */
991 };
992
993
994
995 static char *
996 get_comment (const char *user)
997 {
998     char *cp, *suffix;
999     char *suffix_path;
1000     int i;
1001     char *retval;
1002
1003     suffix_path = xmalloc (strlen (user) + 5);
1004     cp = strrchr (user, '.');
1005     if (cp != NULL)
1006     {
1007         cp++;
1008
1009         /*
1010          * Convert to lower-case, since we are not concerned about the
1011          * case-ness of the suffix.
1012          */
1013         (void) strcpy (suffix_path, cp);
1014         for (cp = suffix_path; *cp; cp++)
1015             if (isupper ((unsigned char) *cp))
1016                 *cp = tolower (*cp);
1017         suffix = suffix_path;
1018     }
1019     else
1020         suffix = "";                    /* will use the default */
1021     for (i = 0;; i++)
1022     {
1023         if (comtable[i].suffix == NULL)
1024         {
1025             /* Default.  Note we'll always hit this case before we
1026                ever return NULL.  */
1027             retval = comtable[i].comlead;
1028             break;
1029         }
1030         if (strcmp (suffix, comtable[i].suffix) == 0)
1031         {
1032             retval = comtable[i].comlead;
1033             break;
1034         }
1035     }
1036     free (suffix_path);
1037     return retval;
1038 }
1039
1040 /* Create a new RCS file from scratch.
1041  *
1042  * This probably should be moved to rcs.c now that it is called from
1043  * places outside import.c.
1044  *
1045  * INPUTS
1046  *   message    Log message for the addition.  Not used if add_vhead == NULL.
1047  *   rcs        Filename of the RCS file to create.  Note that if 'do_killnew'
1048  *              is set, this file should be in the Attic directory, and the
1049  *              Attic directory must already exist.
1050  *   user       Filename of the file to serve as the contents of the initial
1051  *              revision.  Even if add_vhead is NULL, we use this to determine
1052  *              the modes to give the new RCS file.
1053  *   add_vhead  Revision number of head that we are adding.  Normally 1.1 but
1054  *              could be another revision as long as ADD_VBRANCH is a branch
1055  *              from it.  If NULL, then just add an empty file without any
1056  *              revisions (similar to the one created by "rcs -i").
1057  *   key_opt    Keyword expansion mode, e.g., "b" for binary.  NULL means the
1058  *              default behavior.
1059  *   add_vbranch
1060  *              Vendor branch to import to, or NULL if none.  If non-NULL, then
1061  *              vtag should also be non-NULL.
1062  *   vtag
1063  *   targc      Number of elements in TARGV.
1064  *   targv      The list of tags to attached to this imported revision.
1065  *   desctext   If non-NULL, description for the file.  If NULL, the
1066  *              description will be empty.
1067  *   desclen    The number of bytes in desctext.
1068  *   add_logfp  Write errors to here as well as via error (), or NULL if we
1069  *              should use only error ().
1070  *   do_killnew Mark newly-imported files as being dead on the trunk, i.e.,
1071  *              as being imported only to the vendor branch.
1072  *
1073  * RETURNS
1074  *   Return value is 0 for success, or nonzero for failure (in which
1075  *   case an error message will have already been printed).
1076  */
1077 int
1078 add_rcs_file (const char *message, const char *rcs, const char *user,
1079               const char *add_vhead, const char *key_opt,
1080               const char *add_vbranch, const char *vtag, int targc,
1081               char **targv, const char *desctext, size_t desclen,
1082               FILE *add_logfp, bool do_killnew)
1083 {
1084     FILE *fprcs, *fpuser;
1085     struct stat sb;
1086     struct tm *ftm;
1087     time_t now;
1088     char altdate1[MAXDATELEN];
1089     char *author;
1090     int i, ierrno, err = 0;
1091     mode_t mode;
1092     char *tocvsPath;
1093     const char *userfile;
1094     char *free_opt = NULL;
1095     mode_t file_type;
1096     char *dead_revision = NULL;
1097
1098     if (noexec)
1099         return 0;
1100
1101     if (do_killnew)
1102     {
1103         char *last_place;
1104         int last_number;
1105
1106         /* If we are marking the newly imported file as dead, we must
1107            have a head revision.  */
1108         if (add_vhead == NULL)
1109             error (1, 0, "killing new file attempted when no head revision is being added");
1110
1111         /* One extra byte for NUL, plus one for carry generated by adding
1112            one to the last number in the add_vhead revision.  */
1113         dead_revision = xmalloc (strlen (add_vhead) + 2);
1114         strcpy (dead_revision, add_vhead);
1115
1116         /* Find the loacation of the last number, which we will increment
1117            and overwrite.  Note that this handles single numbers (w/o
1118            dots), which is probably unnecessary.  */
1119         if ((last_place = strrchr (dead_revision, '.')) != NULL)
1120             last_place++;
1121         else
1122             last_place = dead_revision;
1123         last_number = atoi (last_place);
1124         if (++last_number <= 0)
1125           error (1, 0, "invalid revision number %s", add_vhead);
1126         sprintf (last_place, "%d", last_number);
1127     }
1128
1129     /* Note that as the code stands now, the -k option overrides any
1130        settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1131        whatever).  Some have suggested this should be the other way
1132        around.  As far as I know the documentation doesn't say one way
1133        or the other.  Before making a change of this sort, should think
1134        about what is best, document it (in cvs.texinfo and NEWS), &c.  */
1135
1136     if (key_opt == NULL)
1137     {
1138         if (wrap_name_has (user, WRAP_RCSOPTION))
1139         {
1140             key_opt = free_opt = wrap_rcsoption (user, 0);
1141         }
1142     }
1143
1144     tocvsPath = wrap_tocvs_process_file (user);
1145     userfile = (tocvsPath == NULL ? user : tocvsPath);
1146
1147     /* Opening in text mode is probably never the right thing for the
1148        server (because the protocol encodes text files in a fashion
1149        which does not depend on what the client or server OS is, as
1150        documented in cvsclient.texi), but as long as the server just
1151        runs on unix it is a moot point.  */
1152
1153     /* If PreservePermissions is set, then make sure that the file
1154        is a plain file before trying to open it.  Longstanding (although
1155        often unpopular) CVS behavior has been to follow symlinks, so we
1156        maintain that behavior if PreservePermissions is not on.
1157
1158        NOTE: this error message used to be `cannot fstat', but is now
1159        `cannot lstat'.  I don't see a way around this, since we must
1160        stat the file before opening it. -twp */
1161
1162     if (lstat (userfile, &sb) < 0)
1163     {
1164         /* not fatal, continue import */
1165         if (add_logfp != NULL)
1166             fperrmsg (add_logfp, 0, errno,
1167                           "ERROR: cannot lstat file %s", userfile);
1168         error (0, errno, "cannot lstat file %s", userfile);
1169         goto read_error;
1170     }
1171     file_type = sb.st_mode & S_IFMT;
1172
1173     fpuser = NULL;
1174     if (
1175 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1176         !config->preserve_perms ||
1177 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1178         file_type == S_IFREG)
1179     {
1180         fpuser = CVS_FOPEN (userfile,
1181                             ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1182                              ? "rb"
1183                              : "r")
1184             );
1185         if (fpuser == NULL)
1186         {
1187             /* not fatal, continue import */
1188             if (add_logfp != NULL)
1189                 fperrmsg (add_logfp, 0, errno,
1190                           "ERROR: cannot read file %s", userfile);
1191             error (0, errno, "ERROR: cannot read file %s", userfile);
1192             goto read_error;
1193         }
1194     }
1195
1196     fprcs = CVS_FOPEN (rcs, "w+b");
1197     if (fprcs == NULL)
1198     {
1199         ierrno = errno;
1200         goto write_error_noclose;
1201     }
1202
1203     /*
1204      * putadmin()
1205      */
1206     if (add_vhead != NULL)
1207     {
1208         if (fprintf (fprcs, "head     %s;\012",
1209                      do_killnew ? dead_revision : add_vhead) < 0)
1210             goto write_error;
1211     }
1212     else
1213     {
1214         if (fprintf (fprcs, "head     ;\012") < 0)
1215             goto write_error;
1216     }
1217
1218     /* This sets the default branch.  If using the 'do_killnew' functionality,
1219        where imports don't show up until merged, no default branch should
1220        be set.  */
1221     if (add_vbranch != NULL && ! do_killnew)
1222     {
1223         if (fprintf (fprcs, "branch   %s;\012", add_vbranch) < 0)
1224             goto write_error;
1225     }
1226     if (fprintf (fprcs, "access   ;\012") < 0 ||
1227         fprintf (fprcs, "symbols  ") < 0)
1228     {
1229         goto write_error;
1230     }
1231
1232     for (i = targc - 1; i >= 0; i--)
1233     {
1234         /* RCS writes the symbols backwards */
1235         assert (add_vbranch != NULL);
1236         if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1237             goto write_error;
1238     }
1239
1240     if (add_vbranch != NULL)
1241     {
1242         if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1243             goto write_error;
1244     }
1245     if (fprintf (fprcs, ";\012") < 0)
1246         goto write_error;
1247
1248     if (fprintf (fprcs, "locks    ; strict;\012") < 0 ||
1249         /* XXX - make sure @@ processing works in the RCS file */
1250         fprintf (fprcs, "comment  @%s@;\012", get_comment (user)) < 0)
1251     {
1252         goto write_error;
1253     }
1254
1255     if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1256     {
1257         if (fprintf (fprcs, "expand   @%s@;\012", key_opt) < 0)
1258         {
1259             goto write_error;
1260         }
1261     }
1262
1263     if (fprintf (fprcs, "\012") < 0)
1264       goto write_error;
1265
1266     /* Write the revision(s), with the date and author and so on
1267        (that is "delta" rather than "deltatext" from rcsfile(5)).  */
1268
1269     if (use_file_modtime)
1270         now = sb.st_mtime;
1271     else
1272         (void) time (&now);
1273     ftm = gmtime (&now);
1274     (void) sprintf (altdate1, DATEFORM,
1275                     (long)ftm->tm_year + (ftm->tm_year < 100 ? 0L : 1900L),
1276                     ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1277                     ftm->tm_min, ftm->tm_sec);
1278     author = getcaller ();
1279
1280     if (do_killnew)
1281     {
1282         if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1283         fprintf (fprcs, "date     %s;  author %s;  state %s;\012",
1284                  altdate1, author, RCSDEAD) < 0)
1285         goto write_error;
1286
1287         if (fprintf (fprcs, "branches;\012") < 0)
1288             goto write_error;
1289         if (fprintf (fprcs, "next    %s;\012", add_vhead) < 0)
1290             goto write_error;
1291
1292         if (fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1293             goto write_error;
1294
1295 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1296         /* Store initial permissions if necessary. */
1297         if (config->preserve_perms)
1298         {
1299             if (preserve_initial_permissions (fprcs, userfile,
1300                                               file_type, sbp))
1301                 goto write_error;
1302         }
1303 #endif
1304     }
1305
1306     if (add_vhead != NULL)
1307     {
1308         if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1309         fprintf (fprcs, "date     %s;  author %s;  state Exp;\012",
1310                  altdate1, author) < 0)
1311         goto write_error;
1312
1313         if (fprintf (fprcs, "branches") < 0)
1314             goto write_error;
1315         if (add_vbranch != NULL)
1316         {
1317             if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1318                 goto write_error;
1319         }
1320         if (fprintf (fprcs, ";\012") < 0)
1321             goto write_error;
1322
1323         if (fprintf (fprcs, "next     ;\012") < 0)
1324             goto write_error;
1325
1326         if (fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1327             goto write_error;
1328
1329 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1330         /* Store initial permissions if necessary. */
1331         if (config->preserve_perms)
1332         {
1333             if (preserve_initial_permissions (fprcs, userfile,
1334                                               file_type, sbp))
1335                 goto write_error;
1336         }
1337 #endif
1338
1339         if (add_vbranch != NULL)
1340         {
1341             if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1342                 fprintf (fprcs, "date     %s;  author %s;  state Exp;\012",
1343                          altdate1, author) < 0 ||
1344                 fprintf (fprcs, "branches ;\012") < 0 ||
1345                 fprintf (fprcs, "next     ;\012") < 0 ||
1346                 fprintf (fprcs, "commitid        %s;\012", global_session_id) < 0)
1347                 goto write_error;
1348
1349 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1350             /* Store initial permissions if necessary. */
1351             if (config->preserve_perms)
1352             {
1353                 if (preserve_initial_permissions (fprcs, userfile,
1354                                                   file_type, sbp))
1355                     goto write_error;
1356             }
1357 #endif
1358
1359             if (fprintf (fprcs, "\012") < 0)
1360                 goto write_error;
1361         }
1362     }
1363
1364     /* Now write the description (possibly empty).  */
1365     if (fprintf (fprcs, "\012desc\012") < 0 ||
1366         fprintf (fprcs, "@") < 0)
1367         goto write_error;
1368     if (desctext != NULL)
1369     {
1370         /* The use of off_t not size_t for the second argument is very
1371            strange, since we are dealing with something which definitely
1372            fits in memory.  */
1373         if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1374             goto write_error;
1375     }
1376     if (fprintf (fprcs, "@\012\012\012") < 0)
1377         goto write_error;
1378
1379     /* Now write the log messages and contents for the revision(s) (that
1380        is, "deltatext" rather than "delta" from rcsfile(5)).  */
1381
1382     if (do_killnew)
1383     {
1384         if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1385             fprintf (fprcs, "log\012@") < 0)
1386             goto write_error;
1387         if (fprintf (fprcs, "Revision %s was added on the vendor branch.\012",
1388                      add_vhead) < 0)
1389             goto write_error;
1390         if (fprintf (fprcs, "@\012") < 0 ||
1391             fprintf (fprcs, "text\012@") < 0)
1392         {
1393             goto write_error;
1394         }
1395
1396         /* Now copy over the contents of the file, expanding at signs.  */
1397         if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1398             goto write_error;
1399
1400         if (fprintf (fprcs, "@\012\012") < 0)
1401             goto write_error;
1402     }
1403
1404     if (add_vhead != NULL)
1405     {
1406         if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1407             fprintf (fprcs, "log\012@") < 0)
1408             goto write_error;
1409         if (add_vbranch != NULL)
1410         {
1411             /* We are going to put the log message in the revision on the
1412                branch.  So putting it here too seems kind of redundant, I
1413                guess (and that is what CVS has always done, anyway).  */
1414             if (fprintf (fprcs, "Initial revision\012") < 0)
1415                 goto write_error;
1416         }
1417         else
1418         {
1419             if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1420                 goto write_error;
1421         }
1422         if (fprintf (fprcs, "@\012") < 0 ||
1423             fprintf (fprcs, "text\012@") < 0)
1424         {
1425             goto write_error;
1426         }
1427
1428         /* Now copy over the contents of the file, expanding at signs.
1429          * If config->preserve_perms is set, do this only for regular files.
1430          */
1431         if (!do_killnew)
1432         {
1433             /* Now copy over the contents of the file, expanding at signs,
1434                if not done as part of do_killnew handling above.  */
1435             if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1436                 goto write_error;
1437         }
1438
1439         if (fprintf (fprcs, "@\012\012") < 0)
1440             goto write_error;
1441
1442         if (add_vbranch != NULL)
1443         {
1444             if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1445                 fprintf (fprcs, "log\012@") < 0 ||
1446                 expand_at_signs (message,
1447                                  (off_t) strlen (message), fprcs) < 0 ||
1448                 fprintf (fprcs, "@\012text\012") < 0 ||
1449                 fprintf (fprcs, "@@\012") < 0)
1450                 goto write_error;
1451         }
1452     }
1453
1454     if (fclose (fprcs) == EOF)
1455     {
1456         ierrno = errno;
1457         goto write_error_noclose;
1458     }
1459     /* Close fpuser only if we opened it to begin with. */
1460     if (fpuser != NULL)
1461     {
1462         if (fclose (fpuser) < 0)
1463             error (0, errno, "cannot close %s", user);
1464     }
1465
1466     /*
1467      * Fix the modes on the RCS files.  The user modes of the original
1468      * user file are propagated to the group and other modes as allowed
1469      * by the repository umask, except that all write permissions are
1470      * turned off.
1471      */
1472     mode = (sb.st_mode |
1473             (sb.st_mode & S_IRWXU) >> 3 |
1474             (sb.st_mode & S_IRWXU) >> 6) &
1475            ~cvsumask &
1476            ~(S_IWRITE | S_IWGRP | S_IWOTH);
1477     if (chmod (rcs, mode) < 0)
1478     {
1479         ierrno = errno;
1480         if (add_logfp != NULL)
1481             fperrmsg (add_logfp, 0, ierrno,
1482                       "WARNING: cannot change mode of file %s", rcs);
1483         error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1484         err++;
1485     }
1486     if (tocvsPath)
1487         if (unlink_file_dir (tocvsPath) < 0)
1488                 error (0, errno, "cannot remove %s", tocvsPath);
1489     if (free_opt != NULL)
1490         free (free_opt);
1491     return err;
1492
1493 write_error:
1494     ierrno = errno;
1495     if (fclose (fprcs) < 0)
1496         error (0, errno, "cannot close %s", rcs);
1497 write_error_noclose:
1498     if (fclose (fpuser) < 0)
1499         error (0, errno, "cannot close %s", user);
1500     if (add_logfp != NULL)
1501         fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1502     error (0, ierrno, "ERROR: cannot write file %s", rcs);
1503     if (ierrno == ENOSPC)
1504     {
1505         if (CVS_UNLINK (rcs) < 0)
1506             error (0, errno, "cannot remove %s", rcs);
1507         if (add_logfp != NULL)
1508             fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1509         error (1, 0, "ERROR: out of space - aborting");
1510     }
1511 read_error:
1512     if (tocvsPath)
1513         if (unlink_file_dir (tocvsPath) < 0)
1514             error (0, errno, "cannot remove %s", tocvsPath);
1515
1516     if (free_opt != NULL)
1517         free (free_opt);
1518
1519     return err + 1;
1520 }
1521
1522 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1523 /* Write file permissions and symlink information for a file being
1524  * added into its RCS file.
1525  *
1526  * INPUTS
1527  *   fprcs      FILE pointer for the (newly-created) RCS file.  Permisisons
1528  *              and symlink information should be written here.
1529  *   userfile   Filename of the file being added.  (Used to read symbolic
1530  *              link contents, for symlinks.)
1531  *   file_type  File type of userfile, extracted from sbp->st_mode.
1532  *   sbp        'stat' information for userfile.
1533  *
1534  * RETURNS
1535  *   Return value is 0 for success, or nonzero for failure (in which case
1536  *   no error message has yet been printed).
1537  */
1538 static int
1539 preserve_initial_permissions (fprcs, userfile, file_type, sbp)
1540     FILE *fprcs;
1541     const char *userfile;
1542     mode_t file_type;
1543     struct stat *sbp;
1544 {
1545     if (file_type == S_IFLNK)
1546     {
1547         char *link = Xreadlink (userfile, sbp->st_size);
1548         if (fprintf (fprcs, "symlink\t@") < 0 ||
1549             expand_at_signs (link, strlen (link), fprcs) < 0 ||
1550             fprintf (fprcs, "@;\012") < 0)
1551             goto write_error;
1552         free (link);
1553     }
1554     else
1555     {
1556         if (fprintf (fprcs, "owner\t%u;\012", sbp->st_uid) < 0)
1557             goto write_error;
1558         if (fprintf (fprcs, "group\t%u;\012", sbp->st_gid) < 0)
1559             goto write_error;
1560         if (fprintf (fprcs, "permissions\t%o;\012",
1561                      sbp->st_mode & 07777) < 0)
1562             goto write_error;
1563         switch (file_type)
1564         {
1565             case S_IFREG: break;
1566             case S_IFCHR:
1567             case S_IFBLK:
1568 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1569                 if (fprintf (fprcs, "special\t%s %lu;\012",
1570                              (file_type == S_IFCHR
1571                               ? "character"
1572                               : "block"),
1573                              (unsigned long) sbp->st_rdev) < 0)
1574                     goto write_error;
1575 #else
1576                 error (0, 0,
1577 "can't import %s: unable to import device files on this system",
1578 userfile);
1579 #endif
1580                 break;
1581             default:
1582                 error (0, 0,
1583                        "can't import %s: unknown kind of special file",
1584                        userfile);
1585         }
1586     }
1587     return 0;
1588
1589 write_error:
1590     return 1;
1591 }
1592 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1593
1594 /* Copy file contents into an RCS file, expanding at signs.
1595  *
1596  * If config->preserve_perms is set, nothing is copied if the source is not
1597  * a regular file.
1598  *
1599  * INPUTS
1600  *   fprcs      FILE pointer for the (newly-created) RCS file.  The expanded
1601  *              contents should be written here.
1602  *   file_type  File type of the data source.  No data is copied if
1603  *              preserve_permissions is set and the source is not a
1604  *              regular file.
1605  *   user       Filename of the data source (used to print error messages).
1606  *   fpuser     FILE pointer for the data source, whose data is being
1607  *              copied into the RCS file.
1608  *
1609  * RETURNS
1610  *   Return value is 0 for success, or nonzero for failure (in which case
1611  *   no error message has yet been printed).
1612  */
1613 static int
1614 expand_and_copy_contents (fprcs, file_type, user, fpuser)
1615     FILE *fprcs, *fpuser;
1616     mode_t file_type;
1617     const char *user;
1618 {
1619     if (
1620 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1621         !config->preserve_perms ||
1622 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1623         file_type == S_IFREG)
1624     {
1625         char buf[8192];
1626         unsigned int len;
1627
1628         while (1)
1629         {
1630             len = fread (buf, 1, sizeof buf, fpuser);
1631             if (len == 0)
1632             {
1633                 if (ferror (fpuser))
1634                     error (1, errno, "cannot read file %s for copying",
1635                            user);
1636                 break;
1637             }
1638             if (expand_at_signs (buf, len, fprcs) < 0)
1639                 goto write_error;
1640         }
1641     }
1642     return 0;
1643
1644 write_error:
1645     return 1;
1646 }
1647
1648 /*
1649  * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1650  * signs.  If an error occurs, return a negative value and set errno
1651  * to indicate the error.  If not, return a nonnegative value.
1652  */
1653 int
1654 expand_at_signs (const char *buf, size_t size, FILE *fp)
1655 {
1656     register const char *cp, *next;
1657
1658     cp = buf;
1659     while ((next = memchr (cp, '@', size)) != NULL)
1660     {
1661         size_t len = ++next - cp;
1662         if (fwrite (cp, 1, len, fp) != len)
1663             return EOF;
1664         if (putc ('@', fp) == EOF)
1665             return EOF;
1666         cp = next;
1667         size -= len;
1668     }
1669
1670     if (fwrite (cp, 1, size, fp) != size)
1671         return EOF;
1672
1673     return 1;
1674 }
1675
1676 /*
1677  * Write an update message to (potentially) the screen and the log file.
1678  */
1679 static void
1680 add_log (int ch, char *fname)
1681 {
1682     if (!really_quiet)                  /* write to terminal */
1683     {
1684         char buf[2];
1685         buf[0] = ch;
1686         buf[1] = ' ';
1687         cvs_output (buf, 2);
1688         if (repos_len)
1689         {
1690             cvs_output (repository + repos_len + 1, 0);
1691             cvs_output ("/", 1);
1692         }
1693         else if (repository[0] != '\0')
1694         {
1695             cvs_output (repository, 0);
1696             cvs_output ("/", 1);
1697         }
1698         cvs_output (fname, 0);
1699         cvs_output ("\n", 1);
1700     }
1701
1702     if (repos_len)                      /* write to logfile */
1703         (void) fprintf (logfp, "%c %s/%s\n", ch,
1704                         repository + repos_len + 1, fname);
1705     else if (repository[0])
1706         (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1707     else
1708         (void) fprintf (logfp, "%c %s\n", ch, fname);
1709 }
1710
1711 /*
1712  * This is the recursive function that walks the argument directory looking
1713  * for sub-directories that have CVS administration files in them and updates
1714  * them recursively.
1715  * 
1716  * Note that we do not follow symbolic links here, which is a feature!
1717  */
1718 static int
1719 import_descend_dir (char *message, char *dir, char *vtag, int targc,
1720                     char **targv)
1721 {
1722     struct saved_cwd cwd;
1723     char *cp;
1724     int ierrno, err;
1725     char *rcs = NULL;
1726
1727     if (islink (dir))
1728         return 0;
1729     if (save_cwd (&cwd))
1730     {
1731         fperrmsg (logfp, 0, errno, "Failed to save current directory.");
1732         return 1;
1733     }
1734
1735     /* Concatenate DIR to the end of REPOSITORY.  */
1736     if (repository[0] == '\0')
1737     {
1738         char *new = xstrdup (dir);
1739         free (repository);
1740         repository = new;
1741     }
1742     else
1743     {
1744         char *new = Xasprintf ("%s/%s", repository, dir);
1745         free (repository);
1746         repository = new;
1747     }
1748
1749     if (!quiet && !current_parsed_root->isremote)
1750         error (0, 0, "Importing %s", repository);
1751
1752     if (CVS_CHDIR (dir) < 0)
1753     {
1754         ierrno = errno;
1755         fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1756         error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1757         err = 1;
1758         goto out;
1759     }
1760     if (!current_parsed_root->isremote && !isdir (repository))
1761     {
1762         rcs = Xasprintf ("%s%s", repository, RCSEXT);
1763         if (isfile (repository) || isfile (rcs))
1764         {
1765             fperrmsg (logfp, 0, 0,
1766                       "ERROR: %s is a file, should be a directory!",
1767                       repository);
1768             error (0, 0, "ERROR: %s is a file, should be a directory!",
1769                    repository);
1770             err = 1;
1771             goto out;
1772         }
1773         if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1774         {
1775             ierrno = errno;
1776             fperrmsg (logfp, 0, ierrno,
1777                       "ERROR: cannot mkdir %s -- not added", repository);
1778             error (0, ierrno,
1779                    "ERROR: cannot mkdir %s -- not added", repository);
1780             err = 1;
1781             goto out;
1782         }
1783     }
1784     err = import_descend (message, vtag, targc, targv);
1785   out:
1786     if (rcs != NULL)
1787         free (rcs);
1788     if ((cp = strrchr (repository, '/')) != NULL)
1789         *cp = '\0';
1790     else
1791         repository[0] = '\0';
1792     if (restore_cwd (&cwd))
1793         error (1, errno, "Failed to restore current directory, `%s'.",
1794                cwd.name);
1795     free_cwd (&cwd);
1796     return err;
1797 }