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