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