Bug Summary

File:src/usr.bin/cvs/update.c
Warning:line 413, column 8
Access to field 'ce_conflict' results in a dereference of a null pointer (loaded from field 'file_ent')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name update.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/cvs/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/cvs -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/cvs/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/cvs/update.c
1/* $OpenBSD: update.c,v 1.176 2017/06/01 08:08:24 joris 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 <dirent.h>
21#include <errno(*__errno()).h>
22#include <fcntl.h>
23#include <stdint.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include "cvs.h"
29#include "diff.h"
30#include "remote.h"
31
32int prune_dirs = 0;
33int print_stdout = 0;
34int build_dirs = 0;
35int reset_option = 0;
36int reset_tag = 0;
37int backup_local_changes = 0;
38char *cvs_specified_tag = NULL((void *)0);
39char *cvs_join_rev1 = NULL((void *)0);
40char *cvs_join_rev2 = NULL((void *)0);
41
42static char *koptstr;
43static char *dateflag = NULL((void *)0);
44static int Aflag = 0;
45
46static void update_clear_conflict(struct cvs_file *);
47static void update_join_file(struct cvs_file *);
48
49extern CVSENTRIES *current_list;
50
51struct cvs_cmd cvs_cmd_update = {
52 CVS_OP_UPDATE24, CVS_USE_WDIR0x01, "update",
53 { "up", "upd" },
54 "Bring work tree in sync with repository",
55 "[-ACdflPpR] [-D date | -r rev] [-I ign] [-j rev] [-k mode] "
56 "[-t id] ...",
57 "ACD:dfI:j:k:lPpQqRr:t:u",
58 NULL((void *)0),
59 cvs_update
60};
61
62int
63cvs_update(int argc, char **argv)
64{
65 int ch;
66 char *arg = ".";
67 int flags;
68 struct cvs_recursion cr;
69
70 flags = CR_RECURSE_DIRS0x01;
71
72 while ((ch = getopt(argc, argv, cvs_cmd_update.cmd_opts)) != -1) {
73 switch (ch) {
74 case 'A':
75 Aflag = 1;
76 if (koptstr == NULL((void *)0))
77 reset_option = 1;
78 if (cvs_specified_tag == NULL((void *)0))
79 reset_tag = 1;
80 break;
81 case 'C':
82 backup_local_changes = 1;
83 break;
84 case 'D':
85 dateflag = optarg;
86 if ((cvs_specified_date = date_parse(dateflag)) == -1)
87 fatal("invalid date: %s", dateflag);
88 reset_tag = 0;
89 break;
90 case 'd':
91 build_dirs = 1;
92 break;
93 case 'f':
94 break;
95 case 'I':
96 break;
97 case 'j':
98 if (cvs_join_rev1 == NULL((void *)0))
99 cvs_join_rev1 = optarg;
100 else if (cvs_join_rev2 == NULL((void *)0))
101 cvs_join_rev2 = optarg;
102 else
103 fatal("too many -j options");
104 break;
105 case 'k':
106 reset_option = 0;
107 koptstr = optarg;
108 kflag = rcs_kflag_get(koptstr);
109 if (RCS_KWEXP_INVAL(kflag)((kflag & 0x20) || ((kflag & 0x10) && (kflag &
~0x10)))
) {
110 cvs_log(LP_ERR1,
111 "invalid RCS keyword expansion mode");
112 fatal("%s", cvs_cmd_update.cmd_synopsis);
113 }
114 break;
115 case 'l':
116 flags &= ~CR_RECURSE_DIRS0x01;
117 break;
118 case 'P':
119 prune_dirs = 1;
120 break;
121 case 'p':
122 print_stdout = 1;
123 cvs_noexec = 1;
124 break;
125 case 'Q':
126 case 'q':
127 break;
128 case 'R':
129 flags |= CR_RECURSE_DIRS0x01;
130 break;
131 case 'r':
132 reset_tag = 0;
133 cvs_specified_tag = optarg;
134 break;
135 case 'u':
136 break;
137 default:
138 fatal("%s", cvs_cmd_update.cmd_synopsis);
139 }
140 }
141
142 argc -= optind;
143 argv += optind;
144
145 if (cvsroot_is_local()) {
146 cr.enterdir = cvs_update_enterdir;
147 cr.leavedir = prune_dirs ? cvs_update_leavedir : NULL((void *)0);
148 cr.fileproc = cvs_update_local;
149 flags |= CR_REPO0x04;
150 } else {
151 cvs_client_connect_to_server();
152 if (Aflag)
153 cvs_client_send_request("Argument -A");
154 if (dateflag != NULL((void *)0))
155 cvs_client_send_request("Argument -D%s", dateflag);
156 if (build_dirs)
157 cvs_client_send_request("Argument -d");
158 if (kflag)
159 cvs_client_send_request("Argument -k%s", koptstr);
160 if (!(flags & CR_RECURSE_DIRS0x01))
161 cvs_client_send_request("Argument -l");
162 if (prune_dirs)
163 cvs_client_send_request("Argument -P");
164 if (print_stdout)
165 cvs_client_send_request("Argument -p");
166
167 if (cvs_specified_tag != NULL((void *)0))
168 cvs_client_send_request("Argument -r%s",
169 cvs_specified_tag);
170
171 cr.enterdir = NULL((void *)0);
172 cr.leavedir = NULL((void *)0);
173 cr.fileproc = cvs_client_sendfile;
174 }
175
176 cr.flags = flags;
177
178 if (argc > 0)
179 cvs_file_run(argc, argv, &cr);
180 else
181 cvs_file_run(1, &arg, &cr);
182
183 if (cvsroot_is_remote()) {
184 cvs_client_send_files(argv, argc);
185 cvs_client_senddir(".");
186 cvs_client_send_request("update");
187 cvs_client_get_responses();
188 }
189
190 return (0);
191}
192
193void
194cvs_update_enterdir(struct cvs_file *cf)
195{
196 CVSENTRIES *entlist;
197 char *dirtag, *entry, fpath[PATH_MAX1024];
198
199 cvs_log(LP_TRACE4, "cvs_update_enterdir(%s)", cf->file_path);
200
201 cvs_file_classify(cf, NULL((void *)0));
202
203 if (cf->file_status == DIR_CREATE12 && build_dirs == 1) {
204 cvs_parse_tagfile(cf->file_wd, &dirtag, NULL((void *)0), NULL((void *)0));
205 cvs_mkpath(cf->file_path, cvs_specified_tag != NULL((void *)0) ?
206 cvs_specified_tag : dirtag);
207 free(dirtag);
208
209 if ((cf->fd = open(cf->file_path, O_RDONLY0x0000)) == -1)
210 fatal("cvs_update_enterdir: `%s': %s",
211 cf->file_path, strerror(errno(*__errno())));
212
213 if (cvs_server_active == 1 && cvs_cmdop != CVS_OP_CHECKOUT4)
214 cvs_server_clear_sticky(cf->file_path);
215
216 if (cvs_cmdop != CVS_OP_EXPORT9) {
217 (void)xasprintf(&entry, "D/%s////", cf->file_name);
218
219 entlist = cvs_ent_open(cf->file_wd);
220 cvs_ent_add(entlist, entry);
221 free(entry);
222 }
223 } else if ((cf->file_status == DIR_CREATE12 && build_dirs == 0) ||
224 cf->file_status == FILE_UNKNOWN0) {
225 cf->file_status = FILE_SKIP100;
226 } else if (reset_tag) {
227 (void)xsnprintf(fpath, PATH_MAX1024, "%s/%s",
228 cf->file_path, CVS_PATH_TAG"CVS" "/Tag");
229 (void)unlink(fpath);
230 } else {
231 if (cvs_specified_tag != NULL((void *)0) || cvs_specified_date != -1)
232 cvs_write_tagfile(cf->file_path,
233 cvs_specified_tag, NULL((void *)0));
234 }
235}
236
237void
238cvs_update_leavedir(struct cvs_file *cf)
239{
240 int nbytes;
241 int isempty;
242 size_t bufsize;
243 struct stat st;
244 struct dirent *dp;
245 char *buf, *ebuf, *cp;
246 CVSENTRIES *entlist;
247
248 cvs_log(LP_TRACE4, "cvs_update_leavedir(%s)", cf->file_path);
249
250 if (cvs_server_active == 1 && !strcmp(cf->file_name, "."))
251 return;
252
253 entlist = cvs_ent_open(cf->file_path);
254 if (!TAILQ_EMPTY(&(entlist->cef_ent))(((&(entlist->cef_ent))->tqh_first) == ((void *)0))) {
255 isempty = 0;
256 goto prune_it;
257 }
258
259 if (fstat(cf->fd, &st) == -1)
260 fatal("cvs_update_leavedir: %s", strerror(errno(*__errno())));
261
262 if ((uintmax_t)st.st_size > SIZE_MAX0xffffffffffffffffUL)
263 fatal("cvs_update_leavedir: %s: file size too big",
264 cf->file_name);
265
266 bufsize = (st.st_size > st.st_blksize) ? st.st_size : st.st_blksize;
267
268 isempty = 1;
269 buf = xmalloc(bufsize);
270
271 if (lseek(cf->fd, 0, SEEK_SET0) == -1)
272 fatal("cvs_update_leavedir: %s", strerror(errno(*__errno())));
273
274 while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) {
275 ebuf = buf + nbytes;
276 cp = buf;
277
278 while (cp < ebuf) {
279 dp = (struct dirent *)cp;
280 if (!strcmp(dp->d_name, ".") ||
281 !strcmp(dp->d_name, "..") ||
282 dp->d_fileno == 0) {
283 cp += dp->d_reclen;
284 continue;
285 }
286
287 if (strcmp(dp->d_name, CVS_PATH_CVSDIR"CVS"))
288 isempty = 0;
289
290 if (isempty == 0)
291 break;
292
293 cp += dp->d_reclen;
294 }
295 }
296
297 if (nbytes == -1)
298 fatal("cvs_update_leavedir: %s", strerror(errno(*__errno())));
299
300 free(buf);
301
302prune_it:
303 if ((isempty == 1 && prune_dirs == 1) ||
304 (cvs_server_active == 1 && cvs_cmdop == CVS_OP_CHECKOUT4)) {
305 /* XXX */
306 cvs_rmdir(cf->file_path);
307
308 if (cvs_server_active == 0 && cvs_cmdop != CVS_OP_EXPORT9) {
309 entlist = cvs_ent_open(cf->file_wd);
310 cvs_ent_remove(entlist, cf->file_name);
311 }
312 }
313}
314
315void
316cvs_update_local(struct cvs_file *cf)
317{
318 CVSENTRIES *entlist;
319 int ent_kflag, rcs_kflag, ret, flags;
320 char *tag, rbuf[CVS_REV_BUFSZ32];
321
322 cvs_log(LP_TRACE4, "cvs_update_local(%s)", cf->file_path);
323
324 if (cf->file_type == CVS_DIR1) {
1
Assuming field 'file_type' is not equal to CVS_DIR
2
Taking false branch
325 if (cf->file_status == FILE_SKIP100) {
326 if (cvs_cmdop == CVS_OP_EXPORT9 && verbosity > 0)
327 cvs_printf("? %s\n", cf->file_path);
328 return;
329 }
330
331 if (cf->file_status != FILE_UNKNOWN0 &&
332 verbosity > 1)
333 cvs_log(LP_ERR1, "Updating %s", cf->file_path);
334 return;
335 }
336
337 flags = 0;
338 if (cvs_specified_tag != NULL((void *)0))
3
Assuming 'cvs_specified_tag' is equal to NULL
4
Taking false branch
339 tag = cvs_specified_tag;
340 else
341 tag = cvs_directory_tag;
342
343 cvs_file_classify(cf, tag);
5
Value assigned to field 'file_ent'
344
345 if (kflag && cf->file_rcs != NULL((void *)0))
6
Assuming 'kflag' is 0
346 rcs_kwexp_set(cf->file_rcs, kflag);
347
348 if ((cf->file_status == FILE_UPTODATE4 ||
7
Assuming field 'file_status' is not equal to FILE_UPTODATE
349 cf->file_status == FILE_MODIFIED3) && cf->file_ent != NULL((void *)0) &&
8
Assuming field 'file_status' is equal to FILE_MODIFIED
9
Assuming field 'file_ent' is equal to NULL
350 cf->file_ent->ce_tag != NULL((void *)0) && reset_tag) {
351 if (cf->file_status == FILE_MODIFIED3)
352 cf->file_status = FILE_MERGE7;
353 else
354 cf->file_status = FILE_CHECKOUT6;
355
356 if ((cf->file_rcsrev = rcs_head_get(cf->file_rcs)) == NULL((void *)0))
357 fatal("no head revision in RCS file for %s",
358 cf->file_path);
359
360 /* might be a bit overkill */
361 if (cvs_server_active == 1)
362 cvs_server_clear_sticky(cf->file_wd);
363 }
364
365 if (print_stdout) {
10
Assuming 'print_stdout' is 0
11
Taking false branch
366 if (cf->file_status != FILE_UNKNOWN0 && cf->file_rcs != NULL((void *)0) &&
367 cf->file_rcsrev != NULL((void *)0) && !cf->file_rcs->rf_dead &&
368 (cf->file_flags & FILE_HAS_TAG0x01)) {
369 rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
370 if (verbosity > 1) {
371 cvs_log(LP_RCS5, RCS_DIFF_DIV"===================================================================");
372 cvs_log(LP_RCS5, "Checking out %s",
373 cf->file_path);
374 cvs_log(LP_RCS5, "RCS: %s", cf->file_rpath);
375 cvs_log(LP_RCS5, "VERS: %s", rbuf);
376 cvs_log(LP_RCS5, "***************");
377 }
378 cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_DUMP0x04);
379 }
380 return;
381 }
382
383 if (cf->file_ent
11.1
Field 'file_ent' is equal to NULL
!= NULL((void *)0)) {
12
Taking false branch
384 if (cf->file_ent->ce_opts == NULL((void *)0)) {
385 if (kflag)
386 cf->file_status = FILE_CHECKOUT6;
387 } else if (cf->file_rcs != NULL((void *)0)) {
388 if (strlen(cf->file_ent->ce_opts) < 3)
389 fatal("malformed option for file %s",
390 cf->file_path);
391
392 ent_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2);
393 rcs_kflag = rcs_kwexp_get(cf->file_rcs);
394
395 if ((kflag && (kflag != ent_kflag)) ||
396 (reset_option && (ent_kflag != rcs_kflag)))
397 cf->file_status = FILE_CHECKOUT6;
398 }
399 }
400
401 switch (cf->file_status) {
13
Control jumps to 'case 3:' at line 405
402 case FILE_UNKNOWN0:
403 cvs_printf("? %s\n", cf->file_path);
404 break;
405 case FILE_MODIFIED3:
406 if (backup_local_changes) {
14
Assuming 'backup_local_changes' is 0
15
Taking false branch
407 cvs_backup_file(cf);
408
409 cvs_checkout_file(cf, cf->file_rcsrev, NULL((void *)0), flags);
410 cvs_printf("U %s\n", cf->file_path);
411 } else {
412 ret = update_has_conflict_markers(cf);
16
Calling 'update_has_conflict_markers'
19
Returning from 'update_has_conflict_markers'
413 if (cf->file_ent->ce_conflict != NULL((void *)0) && ret == 1)
20
Access to field 'ce_conflict' results in a dereference of a null pointer (loaded from field 'file_ent')
414 cvs_printf("C %s\n", cf->file_path);
415 else {
416 if (cf->file_ent->ce_conflict != NULL((void *)0) && ret == 0)
417 update_clear_conflict(cf);
418 cvs_printf("M %s\n", cf->file_path);
419 }
420 }
421 break;
422 case FILE_ADDED1:
423 cvs_printf("A %s\n", cf->file_path);
424 break;
425 case FILE_REMOVED2:
426 cvs_printf("R %s\n", cf->file_path);
427 break;
428 case FILE_CONFLICT10:
429 cvs_printf("C %s\n", cf->file_path);
430 break;
431 case FILE_LOST5:
432 case FILE_CHECKOUT6:
433 case FILE_PATCH8:
434 if (!reset_tag && (tag != NULL((void *)0) || cvs_specified_date != -1 ||
435 cvs_directory_date != -1 || (cf->file_ent != NULL((void *)0) &&
436 cf->file_ent->ce_tag != NULL((void *)0))))
437 flags = CO_SETSTICKY0x02;
438
439 if (cf->file_flags & FILE_ON_DISK0x08 && (cf->file_ent == NULL((void *)0) ||
440 cf->file_ent->ce_type == CVS_ENT_NONE0)) {
441 cvs_log(LP_ERR1, "move away %s; it is in the way",
442 cf->file_path);
443 cvs_printf("C %s\n", cf->file_path);
444 } else {
445 cvs_checkout_file(cf, cf->file_rcsrev, tag, flags);
446 cvs_printf("U %s\n", cf->file_path);
447 cvs_history_add(CVS_HISTORY_UPDATE_CO5, cf, NULL((void *)0));
448 }
449 break;
450 case FILE_MERGE7:
451 d3rev1 = cf->file_ent->ce_rev;
452 d3rev2 = cf->file_rcsrev;
453 cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_MERGE0x01);
454
455 if (diff3_conflicts != 0) {
456 cvs_printf("C %s\n", cf->file_path);
457 cvs_history_add(CVS_HISTORY_UPDATE_MERGED_ERR7,
458 cf, NULL((void *)0));
459 } else {
460 update_clear_conflict(cf);
461 cvs_printf("M %s\n", cf->file_path);
462 cvs_history_add(CVS_HISTORY_UPDATE_MERGED6, cf, NULL((void *)0));
463 }
464 break;
465 case FILE_UNLINK11:
466 (void)unlink(cf->file_path);
467 case FILE_REMOVE_ENTRY9:
468 entlist = cvs_ent_open(cf->file_wd);
469 cvs_ent_remove(entlist, cf->file_name);
470 cvs_history_add(CVS_HISTORY_UPDATE_REMOVE4, cf, NULL((void *)0));
471
472 if (cvs_server_active == 1)
473 cvs_checkout_file(cf, cf->file_rcsrev, tag, CO_REMOVE0x10);
474 break;
475 case FILE_UPTODATE4:
476 if (cvs_cmdop != CVS_OP_UPDATE24)
477 break;
478
479 if (reset_tag != 1 && reset_option != 1 &&
480 cvs_specified_tag == NULL((void *)0) && cvs_specified_date == -1)
481 break;
482
483 if (cf->file_rcs->rf_dead != 1 &&
484 (cf->file_flags & FILE_HAS_TAG0x01))
485 cvs_checkout_file(cf, cf->file_rcsrev,
486 tag, CO_SETSTICKY0x02);
487 break;
488 default:
489 break;
490 }
491
492 if (cvs_join_rev1 != NULL((void *)0))
493 update_join_file(cf);
494}
495
496static void
497update_clear_conflict(struct cvs_file *cf)
498{
499 CVSENTRIES *entlist;
500 char *entry, revbuf[CVS_REV_BUFSZ32];
501 char sticky[CVS_ENT_MAXLINELEN1024], opt[4];
502
503 cvs_log(LP_TRACE4, "update_clear_conflict(%s)", cf->file_path);
504
505 rcsnum_tostr(cf->file_rcsrev, revbuf, sizeof(revbuf));
506
507 sticky[0] = '\0';
508 if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_tag != NULL((void *)0))
509 (void)xsnprintf(sticky, sizeof(sticky), "T%s",
510 cf->file_ent->ce_tag);
511
512 opt[0] = '\0';
513 if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_opts != NULL((void *)0))
514 strlcpy(opt, cf->file_ent->ce_opts, sizeof(opt));
515
516 entry = xmalloc(CVS_ENT_MAXLINELEN1024);
517 cvs_ent_line_str(cf->file_name, revbuf, "Result of merge",
518 opt[0] != '\0' ? opt : "", sticky, 0, 0,
519 entry, CVS_ENT_MAXLINELEN1024);
520
521 entlist = cvs_ent_open(cf->file_wd);
522 cvs_ent_add(entlist, entry);
523 free(entry);
524}
525
526/*
527 * XXX - this is the way GNU cvs checks for outstanding conflicts
528 * in a file after a merge. It is a very very bad approach and
529 * should be looked at once opencvs is working decently.
530 */
531int
532update_has_conflict_markers(struct cvs_file *cf)
533{
534 BUF *bp;
535 int conflict;
536 char *content;
537 struct rcs_line *lp;
538 struct rcs_lines *lines;
539 size_t len;
540
541 cvs_log(LP_TRACE4, "update_has_conflict_markers(%s)", cf->file_path);
542
543 if (!(cf->file_flags & FILE_ON_DISK0x08) || cf->file_ent == NULL((void *)0))
17
Assuming the condition is true
544 return (0);
18
Returning without writing to 'cf->file_ent'
545
546 bp = buf_load_fd(cf->fd);
547
548 buf_putc(bp, '\0');
549 len = buf_len(bp);
550 content = buf_release(bp);
551 if ((lines = cvs_splitlines(content, len)) == NULL((void *)0))
552 fatal("update_has_conflict_markers: failed to split lines");
553
554 conflict = 0;
555 TAILQ_FOREACH(lp, &(lines->l_lines), l_list)for((lp) = ((&(lines->l_lines))->tqh_first); (lp) !=
((void *)0); (lp) = ((lp)->l_list.tqe_next))
{
556 if (lp->l_line == NULL((void *)0))
557 continue;
558
559 if (!strncmp(lp->l_line, RCS_CONFLICT_MARKER1"<<<<<<< ",
560 sizeof(RCS_CONFLICT_MARKER1"<<<<<<< ") - 1) ||
561 !strncmp(lp->l_line, RCS_CONFLICT_MARKER2">>>>>>> ",
562 sizeof(RCS_CONFLICT_MARKER2">>>>>>> ") - 1) ||
563 !strncmp(lp->l_line, RCS_CONFLICT_MARKER3"=======\n",
564 sizeof(RCS_CONFLICT_MARKER3"=======\n") - 1)) {
565 conflict = 1;
566 break;
567 }
568 }
569
570 cvs_freelines(lines);
571 free(content);
572 return (conflict);
573}
574
575void
576update_join_file(struct cvs_file *cf)
577{
578 time_t told;
579 RCSNUM *rev1, *rev2;
580 const char *state1, *state2;
581 char rbuf[CVS_REV_BUFSZ32], *jrev1, *jrev2, *p;
582
583 rev1 = rev2 = NULL((void *)0);
584 jrev1 = jrev2 = NULL((void *)0);
585
586 jrev1 = xstrdup(cvs_join_rev1);
587 if (cvs_join_rev2 != NULL((void *)0))
588 jrev2 = xstrdup(cvs_join_rev2);
589
590 if (jrev2 == NULL((void *)0)) {
591 jrev2 = jrev1;
592 jrev1 = NULL((void *)0);
593 }
594
595 told = cvs_specified_date;
596
597 if ((p = strchr(jrev2, ':')) != NULL((void *)0)) {
598 (*p++) = '\0';
599 if ((cvs_specified_date = date_parse(p)) == -1) {
600 cvs_printf("invalid date: %s", p);
601 goto out;
602 }
603 }
604
605 rev2 = rcs_translate_tag(jrev2, cf->file_rcs);
606 cvs_specified_date = told;
607
608 if (jrev1 != NULL((void *)0)) {
609 if ((p = strchr(jrev1, ':')) != NULL((void *)0)) {
610 (*p++) = '\0';
611 if ((cvs_specified_date = date_parse(p)) == -1) {
612 cvs_printf("invalid date: %s", p);
613 goto out;
614 }
615 }
616
617 rev1 = rcs_translate_tag(jrev1, cf->file_rcs);
618 cvs_specified_date = told;
619 } else {
620 if (rev2 == NULL((void *)0))
621 goto out;
622
623 rev1 = rcsnum_alloc();
624 rcsnum_cpy(cf->file_rcsrev, rev1, 0);
625 }
626
627 state1 = state2 = RCS_STATE_DEAD"dead";
628
629 if (rev1 != NULL((void *)0))
630 state1 = rcs_state_get(cf->file_rcs, rev1);
631 if (rev2 != NULL((void *)0))
632 state2 = rcs_state_get(cf->file_rcs, rev2);
633
634 if (rev2 == NULL((void *)0) || !strcmp(state2, RCS_STATE_DEAD"dead")) {
635 if (rev1 == NULL((void *)0) || !strcmp(state1, RCS_STATE_DEAD"dead"))
636 goto out;
637
638 if (cf->file_status == FILE_REMOVED2 ||
639 cf->file_rcs->rf_dead == 1)
640 goto out;
641
642 if (cf->file_status == FILE_MODIFIED3 ||
643 cf->file_status == FILE_ADDED1)
644 goto out;
645
646 (void)unlink(cf->file_path);
647 (void)close(cf->fd);
648 cf->fd = -1;
649 cvs_remove_local(cf);
650 goto out;
651 }
652
653 if (cf->file_ent != NULL((void *)0)) {
654 if (!rcsnum_cmp(cf->file_ent->ce_rev, rev2, 0))
655 goto out;
656 }
657
658 if (cf->file_rcsrev == NULL((void *)0)) {
659 cvs_printf("non-mergable file: %s has no head revision!\n",
660 cf->file_path);
661 goto out;
662 }
663
664 if (rev1 == NULL((void *)0) || !strcmp(state1, RCS_STATE_DEAD"dead")) {
665 if (cf->file_flags & FILE_ON_DISK0x08) {
666 cvs_printf("%s exists but has been added in %s\n",
667 cf->file_path, jrev2);
668 } else {
669 cvs_printf("A %s\n", cf->file_path);
670 cvs_checkout_file(cf, cf->file_rcsrev, NULL((void *)0), 0);
671 cvs_add_local(cf);
672 }
673 goto out;
674 }
675
676 if (!rcsnum_cmp(rev1, rev2, 0))
677 goto out;
678
679 if (!(cf->file_flags & FILE_ON_DISK0x08)) {
680 cvs_printf("%s does not exist but is present in %s\n",
681 cf->file_path, jrev2);
682 goto out;
683 }
684
685 if (rcs_kwexp_get(cf->file_rcs) & RCS_KWEXP_NONE0x01) {
686 cvs_printf("non-mergable file: %s needs merge!\n",
687 cf->file_path);
688 goto out;
689 }
690
691 cvs_printf("joining ");
692 rcsnum_tostr(rev1, rbuf, sizeof(rbuf));
693 cvs_printf("%s ", rbuf);
694
695 rcsnum_tostr(rev2, rbuf, sizeof(rbuf));
696 cvs_printf("%s ", rbuf);
697
698 rcsnum_tostr(cf->file_rcsrev, rbuf, sizeof(rbuf));
699 cvs_printf("into %s (%s)\n", cf->file_path, rbuf);
700
701 d3rev1 = rev1;
702 d3rev2 = rev2;
703 cvs_checkout_file(cf, cf->file_rcsrev, NULL((void *)0), CO_MERGE0x01);
704
705 if (diff3_conflicts == 0)
706 update_clear_conflict(cf);
707
708out:
709 free(rev1);
710 free(rev2);
711 free(jrev1);
712 free(jrev2);
713}
714
715void
716cvs_backup_file(struct cvs_file *cf)
717{
718 char backup_name[PATH_MAX1024];
719 char revstr[RCSNUM_MAXSTR64];
720
721 if (cf->file_status == FILE_ADDED1)
722 (void)xsnprintf(revstr, sizeof(revstr), "0");
723 else
724 rcsnum_tostr(cf->file_ent->ce_rev, revstr, sizeof(revstr));
725
726 (void)xsnprintf(backup_name, PATH_MAX1024, "%s/.#%s.%s",
727 cf->file_wd, cf->file_name, revstr);
728
729 cvs_file_copy(cf->file_path, backup_name);
730
731 (void)xsnprintf(backup_name, PATH_MAX1024, ".#%s.%s",
732 cf->file_name, revstr);
733 cvs_printf("(Locally modified %s moved to %s)\n",
734 cf->file_name, backup_name);
735}