| File: | src/usr.bin/cvs/import.c |
| Warning: | line 399, column 6 Access to field 'rf_head' results in a dereference of a null pointer (loaded from field 'file_rcs') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: import.c,v 1.109 2019/06/28 13:35:00 deraadt Exp $ */ | |||
| 2 | /* | |||
| 3 | * Copyright (c) 2006 Joris Vink <joris@openbsd.org> | |||
| 4 | * | |||
| 5 | * Permission to use, copy, modify, and distribute this software for any | |||
| 6 | * purpose with or without fee is hereby granted, provided that the above | |||
| 7 | * copyright notice and this permission notice appear in all copies. | |||
| 8 | * | |||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| 16 | */ | |||
| 17 | ||||
| 18 | #include <sys/stat.h> | |||
| 19 | ||||
| 20 | #include <errno(*__errno()).h> | |||
| 21 | #include <fcntl.h> | |||
| 22 | #include <stdlib.h> | |||
| 23 | #include <string.h> | |||
| 24 | #include <unistd.h> | |||
| 25 | ||||
| 26 | #include "cvs.h" | |||
| 27 | #include "diff.h" | |||
| 28 | #include "remote.h" | |||
| 29 | ||||
| 30 | void cvs_import_local(struct cvs_file *); | |||
| 31 | ||||
| 32 | static void import_loginfo(char *); | |||
| 33 | static void import_new(struct cvs_file *); | |||
| 34 | static void import_printf(const char *, ...) | |||
| 35 | __attribute__((format(printf, 1, 2))); | |||
| 36 | static void import_update(struct cvs_file *); | |||
| 37 | static void import_tag(struct cvs_file *, RCSNUM *, RCSNUM *); | |||
| 38 | static BUF *import_get_rcsdiff(struct cvs_file *, RCSNUM *); | |||
| 39 | ||||
| 40 | #define IMPORT_DEFAULT_BRANCH"1.1.1" "1.1.1" | |||
| 41 | ||||
| 42 | extern char *loginfo; | |||
| 43 | extern char *logmsg; | |||
| 44 | ||||
| 45 | static char *import_branch = IMPORT_DEFAULT_BRANCH"1.1.1"; | |||
| 46 | static char *vendor_tag = NULL((void *)0); | |||
| 47 | static char **release_tags; | |||
| 48 | static char *koptstr; | |||
| 49 | static int dflag = 0; | |||
| 50 | static int tagcount = 0; | |||
| 51 | static BUF *logbuf; | |||
| 52 | ||||
| 53 | char *import_repository = NULL((void *)0); | |||
| 54 | int import_conflicts = 0; | |||
| 55 | ||||
| 56 | struct cvs_cmd cvs_cmd_import = { | |||
| 57 | CVS_OP_IMPORT11, CVS_USE_WDIR0x01, "import", | |||
| 58 | { "im", "imp" }, | |||
| 59 | "Import sources into CVS, using vendor branches", | |||
| 60 | "[-b branch] [-d] [-k mode] [-m message] " | |||
| 61 | "repository vendor-tag release-tags", | |||
| 62 | "b:dk:m:", | |||
| 63 | NULL((void *)0), | |||
| 64 | cvs_import | |||
| 65 | }; | |||
| 66 | ||||
| 67 | int | |||
| 68 | cvs_import(int argc, char **argv) | |||
| 69 | { | |||
| 70 | int i, ch; | |||
| 71 | char repo[PATH_MAX1024], *arg = "."; | |||
| 72 | struct cvs_recursion cr; | |||
| 73 | struct trigger_list *line_list; | |||
| 74 | ||||
| 75 | while ((ch = getopt(argc, argv, cvs_cmd_import.cmd_opts)) != -1) { | |||
| 76 | switch (ch) { | |||
| 77 | case 'b': | |||
| 78 | import_branch = optarg; | |||
| 79 | break; | |||
| 80 | case 'd': | |||
| 81 | dflag = 1; | |||
| 82 | break; | |||
| 83 | case 'k': | |||
| 84 | koptstr = optarg; | |||
| 85 | kflag = rcs_kflag_get(koptstr); | |||
| 86 | if (RCS_KWEXP_INVAL(kflag)((kflag & 0x20) || ((kflag & 0x10) && (kflag & ~0x10)))) { | |||
| 87 | cvs_log(LP_ERR1, | |||
| 88 | "invalid RCS keyword expansion mode"); | |||
| 89 | fatal("%s", cvs_cmd_import.cmd_synopsis); | |||
| 90 | } | |||
| 91 | break; | |||
| 92 | case 'm': | |||
| 93 | logmsg = optarg; | |||
| 94 | break; | |||
| 95 | default: | |||
| 96 | fatal("%s", cvs_cmd_import.cmd_synopsis); | |||
| 97 | break; | |||
| 98 | } | |||
| 99 | } | |||
| 100 | ||||
| 101 | argc -= optind; | |||
| 102 | argv += optind; | |||
| 103 | ||||
| 104 | if (argc < 3) | |||
| 105 | fatal("%s", cvs_cmd_import.cmd_synopsis); | |||
| 106 | ||||
| 107 | import_repository = argv[0]; | |||
| 108 | vendor_tag = argv[1]; | |||
| 109 | argc -= 2; | |||
| 110 | argv += 2; | |||
| 111 | ||||
| 112 | release_tags = argv; | |||
| 113 | tagcount = argc; | |||
| 114 | ||||
| 115 | if (!rcs_sym_check(vendor_tag)) | |||
| 116 | fatal("invalid symbol: %s", vendor_tag); | |||
| 117 | ||||
| 118 | for (i = 0; i < tagcount; i++) { | |||
| 119 | if (!rcs_sym_check(release_tags[i])) | |||
| 120 | fatal("invalid symbol: %s", release_tags[i]); | |||
| 121 | } | |||
| 122 | ||||
| 123 | if (logmsg == NULL((void *)0)) { | |||
| 124 | if (cvs_server_active) | |||
| 125 | fatal("no log message specified"); | |||
| 126 | else | |||
| 127 | logmsg = cvs_logmsg_create(NULL((void *)0), NULL((void *)0), NULL((void *)0), NULL((void *)0)); | |||
| 128 | } | |||
| 129 | ||||
| 130 | if (cvsroot_is_remote()) { | |||
| 131 | cvs_client_connect_to_server(); | |||
| 132 | ||||
| 133 | cvs_client_send_request("Argument -b%s", IMPORT_DEFAULT_BRANCH"1.1.1"); | |||
| 134 | ||||
| 135 | if (kflag) | |||
| 136 | cvs_client_send_request("Argument -k%s", koptstr); | |||
| 137 | ||||
| 138 | cvs_client_send_logmsg(logmsg); | |||
| 139 | cvs_client_send_request("Argument %s", import_repository); | |||
| 140 | cvs_client_send_request("Argument %s", vendor_tag); | |||
| 141 | for (i = 0; i < tagcount; i++) | |||
| 142 | cvs_client_send_request("Argument %s", release_tags[i]); | |||
| 143 | ||||
| 144 | cr.enterdir = NULL((void *)0); | |||
| 145 | cr.leavedir = NULL((void *)0); | |||
| 146 | cr.fileproc = cvs_client_sendfile; | |||
| 147 | cr.flags = CR_RECURSE_DIRS0x01; | |||
| 148 | ||||
| 149 | cvs_file_run(1, &arg, &cr); | |||
| 150 | cvs_client_senddir("."); | |||
| 151 | cvs_client_send_request("import"); | |||
| 152 | ||||
| 153 | cvs_client_get_responses(); | |||
| 154 | return (0); | |||
| 155 | } | |||
| 156 | ||||
| 157 | if (cvs_logmsg_verify(logmsg)) | |||
| 158 | return (0); | |||
| 159 | ||||
| 160 | (void)xsnprintf(repo, sizeof(repo), "%s/%s", | |||
| 161 | current_cvsroot->cr_dir, import_repository); | |||
| 162 | ||||
| 163 | import_loginfo(import_repository); | |||
| 164 | ||||
| 165 | if (cvs_noexec != 1) | |||
| 166 | cvs_mkdir(repo, 0755); | |||
| 167 | ||||
| 168 | cr.enterdir = NULL((void *)0); | |||
| 169 | cr.leavedir = NULL((void *)0); | |||
| 170 | cr.fileproc = cvs_import_local; | |||
| 171 | cr.flags = CR_RECURSE_DIRS0x01; | |||
| 172 | cvs_file_run(1, &arg, &cr); | |||
| 173 | ||||
| 174 | if (import_conflicts != 0) { | |||
| 175 | import_printf("\n%d conflicts created by this import.\n\n", | |||
| 176 | import_conflicts); | |||
| 177 | import_printf("Use the following command to help the merge:\n"); | |||
| 178 | import_printf("\topencvs checkout "); | |||
| 179 | import_printf("-j%s:yesterday -j%s %s\n\n", vendor_tag, | |||
| 180 | vendor_tag, import_repository); | |||
| 181 | } else { | |||
| 182 | import_printf("\nNo conflicts created by this import.\n\n"); | |||
| 183 | } | |||
| 184 | ||||
| 185 | loginfo = buf_release(logbuf); | |||
| 186 | logbuf = NULL((void *)0); | |||
| 187 | ||||
| 188 | line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO"CVSROOT" "/loginfo", import_repository); | |||
| 189 | if (line_list != NULL((void *)0)) { | |||
| 190 | cvs_trigger_handle(CVS_TRIGGER_LOGINFO2, import_repository, | |||
| 191 | loginfo, line_list, NULL((void *)0)); | |||
| 192 | cvs_trigger_freelist(line_list); | |||
| 193 | } | |||
| 194 | ||||
| 195 | free(loginfo); | |||
| 196 | return (0); | |||
| 197 | } | |||
| 198 | ||||
| 199 | static void | |||
| 200 | import_printf(const char *fmt, ...) | |||
| 201 | { | |||
| 202 | char *str; | |||
| 203 | va_list vap; | |||
| 204 | ||||
| 205 | va_start(vap, fmt)__builtin_va_start((vap), fmt); | |||
| 206 | if (vasprintf(&str, fmt, vap) == -1) | |||
| 207 | fatal("import_printf: could not allocate memory"); | |||
| 208 | va_end(vap)__builtin_va_end((vap)); | |||
| 209 | ||||
| 210 | cvs_printf("%s", str); | |||
| 211 | buf_puts(logbuf, str); | |||
| 212 | ||||
| 213 | free(str); | |||
| 214 | } | |||
| 215 | ||||
| 216 | void | |||
| 217 | cvs_import_ignored(const char *path) | |||
| 218 | { | |||
| 219 | const char *p; | |||
| 220 | ||||
| 221 | for (p = path; p[0] == '.' && p[1] == '/';) | |||
| 222 | p += 2; | |||
| 223 | ||||
| 224 | import_printf("I %s/%s\n", import_repository, p); | |||
| 225 | } | |||
| 226 | ||||
| 227 | void | |||
| 228 | cvs_import_local(struct cvs_file *cf) | |||
| 229 | { | |||
| 230 | int isnew; | |||
| 231 | struct stat st; | |||
| 232 | char repo[PATH_MAX1024]; | |||
| 233 | ||||
| 234 | cvs_log(LP_TRACE4, "cvs_import_local(%s)", cf->file_path); | |||
| 235 | ||||
| 236 | cvs_file_classify(cf, cvs_directory_tag); | |||
| ||||
| 237 | ||||
| 238 | if (cf->file_type == CVS_DIR1) { | |||
| 239 | if (!strcmp(cf->file_path, ".")) | |||
| 240 | return; | |||
| 241 | ||||
| 242 | if (verbosity > 1) | |||
| 243 | cvs_log(LP_NOTICE0, "Importing %s", cf->file_path); | |||
| 244 | ||||
| 245 | if (cvs_noexec == 1) | |||
| 246 | return; | |||
| 247 | ||||
| 248 | if (mkdir(cf->file_rpath, 0755) == -1 && errno(*__errno()) != EEXIST17) | |||
| 249 | fatal("cvs_import_local: %s: %s", cf->file_rpath, | |||
| 250 | strerror(errno(*__errno()))); | |||
| 251 | ||||
| 252 | return; | |||
| 253 | } | |||
| 254 | ||||
| 255 | isnew = 1; | |||
| 256 | (void)xsnprintf(repo, sizeof(repo), "%s/%s/%s/%s%s", | |||
| 257 | current_cvsroot->cr_dir, cf->file_wd, CVS_PATH_ATTIC"Attic", | |||
| 258 | cf->file_name, RCS_FILE_EXT",v"); | |||
| 259 | ||||
| 260 | if (cf->file_rcs != NULL((void *)0) || stat(repo, &st) != -1) | |||
| 261 | isnew = 0; | |||
| 262 | ||||
| 263 | if (isnew
| |||
| 264 | import_new(cf); | |||
| 265 | else | |||
| 266 | import_update(cf); | |||
| 267 | } | |||
| 268 | ||||
| 269 | static void | |||
| 270 | import_loginfo(char *repo) | |||
| 271 | { | |||
| 272 | int i; | |||
| 273 | char pwd[PATH_MAX1024]; | |||
| 274 | ||||
| 275 | if (getcwd(pwd, sizeof(pwd)) == NULL((void *)0)) | |||
| 276 | fatal("Can't get working directory"); | |||
| 277 | ||||
| 278 | logbuf = buf_alloc(1024); | |||
| 279 | cvs_trigger_loginfo_header(logbuf, repo); | |||
| 280 | ||||
| 281 | buf_puts(logbuf, "Log Message:\n"); | |||
| 282 | buf_puts(logbuf, logmsg); | |||
| 283 | if (logmsg[0] != '\0' && logmsg[strlen(logmsg) - 1] != '\n') | |||
| 284 | buf_putc(logbuf, '\n'); | |||
| 285 | buf_putc(logbuf, '\n'); | |||
| 286 | ||||
| 287 | buf_puts(logbuf, "Status:\n\n"); | |||
| 288 | ||||
| 289 | buf_puts(logbuf, "Vendor Tag:\t"); | |||
| 290 | buf_puts(logbuf, vendor_tag); | |||
| 291 | buf_putc(logbuf, '\n'); | |||
| 292 | buf_puts(logbuf, "Release Tags:\t"); | |||
| 293 | ||||
| 294 | for (i = 0; i < tagcount ; i++) { | |||
| 295 | buf_puts(logbuf, "\t\t"); | |||
| 296 | buf_puts(logbuf, release_tags[i]); | |||
| 297 | buf_putc(logbuf, '\n'); | |||
| 298 | } | |||
| 299 | buf_putc(logbuf, '\n'); | |||
| 300 | buf_putc(logbuf, '\n'); | |||
| 301 | } | |||
| 302 | ||||
| 303 | static void | |||
| 304 | import_new(struct cvs_file *cf) | |||
| 305 | { | |||
| 306 | int i; | |||
| 307 | BUF *bp; | |||
| 308 | mode_t mode; | |||
| 309 | time_t tstamp; | |||
| 310 | struct stat st; | |||
| 311 | struct rcs_branch *brp; | |||
| 312 | struct rcs_delta *rdp; | |||
| 313 | RCSNUM *branch, *brev; | |||
| 314 | ||||
| 315 | tstamp = -1; | |||
| 316 | ||||
| 317 | cvs_log(LP_TRACE4, "import_new(%s)", cf->file_name); | |||
| 318 | ||||
| 319 | if (cvs_noexec == 1) { | |||
| 320 | import_printf("N %s/%s\n", import_repository, cf->file_path); | |||
| 321 | return; | |||
| 322 | } | |||
| 323 | ||||
| 324 | if (fstat(cf->fd, &st) == -1) | |||
| 325 | fatal("import_new: %s", strerror(errno(*__errno()))); | |||
| 326 | ||||
| 327 | mode = st.st_mode; | |||
| 328 | ||||
| 329 | if (dflag == 1) | |||
| 330 | tstamp = st.st_mtimest_mtim.tv_sec; | |||
| 331 | ||||
| 332 | if ((branch = rcsnum_parse(import_branch)) == NULL((void *)0)) | |||
| 333 | fatal("import_new: failed to parse branch"); | |||
| 334 | ||||
| 335 | bp = buf_load_fd(cf->fd); | |||
| 336 | ||||
| 337 | if ((brev = rcsnum_brtorev(branch)) == NULL((void *)0)) | |||
| 338 | fatal("import_new: failed to get first branch revision"); | |||
| 339 | ||||
| 340 | cf->repo_fd = open(cf->file_rpath, O_CREAT0x0200 | O_RDONLY0x0000); | |||
| 341 | if (cf->repo_fd == -1) | |||
| 342 | fatal("import_new: %s: %s", cf->file_rpath, strerror(errno(*__errno()))); | |||
| 343 | ||||
| 344 | cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, RCS_CREATE(1<<2), | |||
| 345 | (mode & ~(S_IWUSR0000200 | S_IWGRP0000020 | S_IWOTH0000002))); | |||
| 346 | if (cf->file_rcs == NULL((void *)0)) | |||
| 347 | fatal("import_new: failed to create RCS file for %s", | |||
| 348 | cf->file_path); | |||
| 349 | ||||
| 350 | rcs_branch_set(cf->file_rcs, branch); | |||
| 351 | ||||
| 352 | if (rcs_sym_add(cf->file_rcs, vendor_tag, branch) == -1) | |||
| 353 | fatal("import_new: failed to add vendor tag"); | |||
| 354 | ||||
| 355 | for (i = 0; i < tagcount; i++) { | |||
| 356 | if (rcs_sym_add(cf->file_rcs, release_tags[i], brev) == -1) | |||
| 357 | fatal("import_new: failed to add release tag"); | |||
| 358 | } | |||
| 359 | ||||
| 360 | if (rcs_rev_add(cf->file_rcs, brev, logmsg, tstamp, NULL((void *)0)) == -1) | |||
| 361 | fatal("import_new: failed to create first branch revision"); | |||
| 362 | ||||
| 363 | if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV((RCSNUM *)(-1)), "Initial revision", | |||
| 364 | tstamp, NULL((void *)0)) == -1) | |||
| 365 | fatal("import_new: failed to create first revision"); | |||
| 366 | ||||
| 367 | if ((rdp = rcs_findrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL((void *)0)) | |||
| 368 | fatal("import_new: cannot find newly added revision"); | |||
| 369 | ||||
| 370 | brp = xmalloc(sizeof(*brp)); | |||
| 371 | brp->rb_num = rcsnum_alloc(); | |||
| 372 | rcsnum_cpy(brev, brp->rb_num, 0); | |||
| 373 | TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list)do { (brp)->rb_list.tqe_next = ((void *)0); (brp)->rb_list .tqe_prev = (&(rdp->rd_branches))->tqh_last; *(& (rdp->rd_branches))->tqh_last = (brp); (&(rdp->rd_branches ))->tqh_last = &(brp)->rb_list.tqe_next; } while (0 ); | |||
| 374 | ||||
| 375 | if (rcs_deltatext_set(cf->file_rcs, | |||
| 376 | cf->file_rcs->rf_head, bp) == -1) | |||
| 377 | fatal("import_new: failed to set deltatext"); | |||
| 378 | ||||
| 379 | if (kflag) | |||
| 380 | rcs_kwexp_set(cf->file_rcs, kflag); | |||
| 381 | ||||
| 382 | rcs_write(cf->file_rcs); | |||
| 383 | import_printf("N %s/%s\n", import_repository, cf->file_path); | |||
| 384 | ||||
| 385 | free(branch); | |||
| 386 | free(brev); | |||
| 387 | } | |||
| 388 | ||||
| 389 | static void | |||
| 390 | import_update(struct cvs_file *cf) | |||
| 391 | { | |||
| 392 | int ret; | |||
| 393 | BUF *b1, *b2, *d; | |||
| 394 | char branch[CVS_REV_BUFSZ32]; | |||
| 395 | RCSNUM *newrev, *rev, *brev; | |||
| 396 | ||||
| 397 | cvs_log(LP_TRACE4, "import_update(%s)", cf->file_path); | |||
| 398 | ||||
| 399 | if (cf->file_rcs->rf_head == NULL((void *)0)) | |||
| ||||
| 400 | fatal("no head revision in RCS file for `%s'", cf->file_path); | |||
| 401 | ||||
| 402 | if ((rev = rcs_translate_tag(import_branch, cf->file_rcs)) == NULL((void *)0)) | |||
| 403 | fatal("import_update: could not translate tag `%s'", | |||
| 404 | import_branch); | |||
| 405 | ||||
| 406 | if ((brev = rcsnum_parse(import_branch)) == NULL((void *)0)) | |||
| 407 | fatal("import_update: rcsnum_parse failed"); | |||
| 408 | ||||
| 409 | b1 = rcs_rev_getbuf(cf->file_rcs, rev, RCS_KWEXP_NONE0x01); | |||
| 410 | b2 = buf_load_fd(cf->fd); | |||
| 411 | ||||
| 412 | ret = buf_differ(b1, b2); | |||
| 413 | buf_free(b1); | |||
| 414 | buf_free(b2); | |||
| 415 | if (ret == 0) { | |||
| 416 | import_tag(cf, brev, rev); | |||
| 417 | free(brev); | |||
| 418 | if (cvs_noexec != 1) | |||
| 419 | rcs_write(cf->file_rcs); | |||
| 420 | import_printf("U %s/%s\n", import_repository, cf->file_path); | |||
| 421 | return; | |||
| 422 | } | |||
| 423 | ||||
| 424 | if (cf->file_rcs->rf_branch != NULL((void *)0)) | |||
| 425 | rcsnum_tostr(cf->file_rcs->rf_branch, branch, sizeof(branch)); | |||
| 426 | ||||
| 427 | if (cf->file_rcs->rf_branch == NULL((void *)0) || cf->in_attic == 1 || | |||
| 428 | strcmp(branch, import_branch)) { | |||
| 429 | import_conflicts++; | |||
| 430 | import_printf("C %s/%s\n", import_repository, cf->file_path); | |||
| 431 | } else { | |||
| 432 | import_printf("U %s/%s\n", import_repository, cf->file_path); | |||
| 433 | } | |||
| 434 | ||||
| 435 | if (cvs_noexec == 1) | |||
| 436 | return; | |||
| 437 | ||||
| 438 | d = import_get_rcsdiff(cf, rev); | |||
| 439 | newrev = rcsnum_inc(rev); | |||
| 440 | ||||
| 441 | if (rcs_rev_add(cf->file_rcs, newrev, logmsg, -1, NULL((void *)0)) == -1) | |||
| 442 | fatal("import_update: failed to add new revision"); | |||
| 443 | ||||
| 444 | if (rcs_deltatext_set(cf->file_rcs, newrev, d) == -1) | |||
| 445 | fatal("import_update: failed to set deltatext"); | |||
| 446 | ||||
| 447 | import_tag(cf, brev, newrev); | |||
| 448 | ||||
| 449 | if (kflag) | |||
| 450 | rcs_kwexp_set(cf->file_rcs, kflag); | |||
| 451 | ||||
| 452 | free(brev); | |||
| 453 | rcs_write(cf->file_rcs); | |||
| 454 | } | |||
| 455 | ||||
| 456 | static void | |||
| 457 | import_tag(struct cvs_file *cf, RCSNUM *branch, RCSNUM *newrev) | |||
| 458 | { | |||
| 459 | int i; | |||
| 460 | ||||
| 461 | if (cvs_noexec != 1) { | |||
| 462 | rcs_sym_add(cf->file_rcs, vendor_tag, branch); | |||
| 463 | ||||
| 464 | for (i = 0; i < tagcount; i++) | |||
| 465 | rcs_sym_add(cf->file_rcs, release_tags[i], newrev); | |||
| 466 | } | |||
| 467 | } | |||
| 468 | ||||
| 469 | static BUF * | |||
| 470 | import_get_rcsdiff(struct cvs_file *cf, RCSNUM *rev) | |||
| 471 | { | |||
| 472 | char *p1, *p2; | |||
| 473 | BUF *b1, *b2; | |||
| 474 | int fd1, fd2; | |||
| 475 | ||||
| 476 | b2 = buf_alloc(128); | |||
| 477 | ||||
| 478 | b1 = buf_load_fd(cf->fd); | |||
| 479 | ||||
| 480 | (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); | |||
| 481 | fd1 = buf_write_stmp(b1, p1, NULL((void *)0)); | |||
| 482 | buf_free(b1); | |||
| 483 | ||||
| 484 | (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); | |||
| 485 | fd2 = rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE0x01); | |||
| 486 | ||||
| 487 | diff_format = D_RCSDIFF5; | |||
| 488 | if (diffreg(p2, p1, fd2, fd1, b2, D_FORCEASCII0x01) == D_ERROR7) | |||
| 489 | fatal("import_get_rcsdiff: failed to get RCS patch"); | |||
| 490 | ||||
| 491 | close(fd1); | |||
| 492 | close(fd2); | |||
| 493 | ||||
| 494 | (void)unlink(p1); | |||
| 495 | (void)unlink(p2); | |||
| 496 | ||||
| 497 | free(p1); | |||
| 498 | free(p2); | |||
| 499 | ||||
| 500 | return (b2); | |||
| 501 | } |