Bug Summary

File:src/usr.bin/cvs/commit.c
Warning:line 561, column 20
Access to field 'rf_head' results in a dereference of a null pointer (loaded from field 'file_rcs')

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 commit.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/commit.c
1/* $OpenBSD: commit.c,v 1.160 2019/06/28 13:35:00 deraadt Exp $ */
2/*
3 * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
4 * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/stat.h>
20
21#include <errno(*__errno()).h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include "cvs.h"
28#include "diff.h"
29#include "remote.h"
30
31void cvs_commit_local(struct cvs_file *);
32void cvs_commit_check_files(struct cvs_file *);
33void cvs_commit_loginfo(char *);
34void cvs_commit_lock_dirs(struct cvs_file *);
35
36static BUF *commit_diff(struct cvs_file *, RCSNUM *, int);
37static void commit_desc_set(struct cvs_file *);
38
39struct file_info_list files_info;
40struct trigger_list *line_list;
41
42struct cvs_flisthead files_affected;
43struct cvs_flisthead files_added;
44struct cvs_flisthead files_removed;
45struct cvs_flisthead files_modified;
46
47char *logmsg = NULL((void *)0);
48char *loginfo = NULL((void *)0);
49
50static int conflicts_found;
51
52struct cvs_cmd cvs_cmd_commit = {
53 CVS_OP_COMMIT5, CVS_USE_WDIR0x01, "commit",
54 { "ci", "com" },
55 "Check files into the repository",
56 "[-flR] [-F logfile | -m msg] [-r rev] ...",
57 "F:flm:Rr:",
58 NULL((void *)0),
59 cvs_commit
60};
61
62int
63cvs_commit(int argc, char **argv)
64{
65 int flags;
66 int ch, Fflag, mflag;
67 struct module_checkout *mc;
68 struct cvs_recursion cr;
69 struct cvs_filelist *l;
70 struct file_info *fi;
71 char *arg = ".", repo[PATH_MAX1024];
72
73 flags = CR_RECURSE_DIRS0x01;
74 Fflag = mflag = 0;
75
76 while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) {
77 switch (ch) {
78 case 'F':
79 /* free previously assigned value */
80 free(logmsg);
81 logmsg = cvs_logmsg_read(optarg);
82 Fflag = 1;
83 break;
84 case 'f':
85 break;
86 case 'l':
87 flags &= ~CR_RECURSE_DIRS0x01;
88 break;
89 case 'm':
90 /* free previously assigned value */
91 free(logmsg);
92 logmsg = xstrdup(optarg);
93 mflag = 1;
94 break;
95 case 'R':
96 flags |= CR_RECURSE_DIRS0x01;
97 break;
98 case 'r':
99 break;
100 default:
101 fatal("%s", cvs_cmd_commit.cmd_synopsis);
102 }
103 }
104
105 argc -= optind;
106 argv += optind;
107
108 /* -F and -m are mutually exclusive */
109 if (Fflag && mflag)
110 fatal("cannot specify both a log file and a message");
111
112 RB_INIT(&files_affected)do { (&files_affected)->rbh_root = ((void *)0); } while
(0)
;
113 RB_INIT(&files_added)do { (&files_added)->rbh_root = ((void *)0); } while (
0)
;
114 RB_INIT(&files_removed)do { (&files_removed)->rbh_root = ((void *)0); } while
(0)
;
115 RB_INIT(&files_modified)do { (&files_modified)->rbh_root = ((void *)0); } while
(0)
;
116
117 TAILQ_INIT(&files_info)do { (&files_info)->tqh_first = ((void *)0); (&files_info
)->tqh_last = &(&files_info)->tqh_first; } while
(0)
;
118 conflicts_found = 0;
119
120 cr.enterdir = NULL((void *)0);
121 cr.leavedir = NULL((void *)0);
122 cr.fileproc = cvs_commit_check_files;
123 cr.flags = flags;
124
125 if (argc > 0)
126 cvs_file_run(argc, argv, &cr);
127 else
128 cvs_file_run(1, &arg, &cr);
129
130 if (conflicts_found != 0)
131 fatal("%d conflicts found, please correct these first",
132 conflicts_found);
133
134 if (RB_EMPTY(&files_affected)((&files_affected)->rbh_root == ((void *)0)))
135 return (0);
136
137 if (cvsroot_is_remote()) {
138 if (logmsg == NULL((void *)0)) {
139 logmsg = cvs_logmsg_create(NULL((void *)0), &files_added,
140 &files_removed, &files_modified);
141 if (logmsg == NULL((void *)0))
142 fatal("This shouldnt happen, honestly!");
143 }
144 cvs_client_connect_to_server();
145 cr.fileproc = cvs_client_sendfile;
146
147 if (argc > 0)
148 cvs_file_run(argc, argv, &cr);
149 else
150 cvs_file_run(1, &arg, &cr);
151
152 if (!(flags & CR_RECURSE_DIRS0x01))
153 cvs_client_send_request("Argument -l");
154
155 cvs_client_send_logmsg(logmsg);
156 cvs_client_send_files(argv, argc);
157 cvs_client_senddir(".");
158 cvs_client_send_request("ci");
159 cvs_client_get_responses();
160 } else {
161 cvs_get_repository_name(".", repo, PATH_MAX1024);
162
163 line_list = cvs_trigger_getlines(CVS_PATH_COMMITINFO"CVSROOT" "/commitinfo", repo);
164 if (line_list != NULL((void *)0)) {
165 RB_FOREACH(l, cvs_flisthead, &files_affected)for ((l) = cvs_flisthead_RB_MINMAX(&files_affected, -1); (
l) != ((void *)0); (l) = cvs_flisthead_RB_NEXT(l))
{
166 fi = xcalloc(1, sizeof(*fi));
167 fi->file_path = xstrdup(l->file_path);
168 TAILQ_INSERT_TAIL(&files_info, fi,do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev
= (&files_info)->tqh_last; *(&files_info)->tqh_last
= (fi); (&files_info)->tqh_last = &(fi)->flist
.tqe_next; } while (0)
169 flist)do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev
= (&files_info)->tqh_last; *(&files_info)->tqh_last
= (fi); (&files_info)->tqh_last = &(fi)->flist
.tqe_next; } while (0)
;
170 }
171
172 if (cvs_trigger_handle(CVS_TRIGGER_COMMITINFO1,
173 repo, NULL((void *)0), line_list, &files_info)) {
174 cvs_log(LP_ERR1,
175 "Pre-commit check failed");
176 cvs_trigger_freelist(line_list);
177 goto end;
178 }
179
180 cvs_trigger_freelist(line_list);
181 cvs_trigger_freeinfo(&files_info);
182 }
183
184 if (cvs_server_active) {
185 if (logmsg == NULL((void *)0))
186 fatal("no log message specified");
187 } else if (logmsg == NULL((void *)0)) {
188 logmsg = cvs_logmsg_create(NULL((void *)0), &files_added,
189 &files_removed, &files_modified);
190 if (logmsg == NULL((void *)0))
191 fatal("This shouldnt happen, honestly!");
192 }
193
194 if (cvs_logmsg_verify(logmsg))
195 goto end;
196
197 cr.fileproc = cvs_commit_lock_dirs;
198 cvs_file_walklist(&files_affected, &cr);
199
200 line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO"CVSROOT" "/loginfo", repo);
201
202 cr.fileproc = cvs_commit_local;
203 cvs_file_walklist(&files_affected, &cr);
204
205 if (line_list != NULL((void *)0)) {
206 cvs_commit_loginfo(repo);
207
208 cvs_trigger_handle(CVS_TRIGGER_LOGINFO2, repo,
209 loginfo, line_list, &files_info);
210
211 free(loginfo);
212 cvs_trigger_freelist(line_list);
213 cvs_trigger_freeinfo(&files_info);
214 }
215
216 mc = cvs_module_lookup(repo);
217 if (mc->mc_prog != NULL((void *)0) &&
218 (mc->mc_flags & MODULE_RUN_ON_COMMIT0x08))
219 cvs_exec(mc->mc_prog, NULL((void *)0), 0);
220 }
221
222end:
223 cvs_trigger_freeinfo(&files_info);
224 free(logmsg);
225 return (0);
226}
227
228void
229cvs_commit_loginfo(char *repo)
230{
231 BUF *buf;
232 char pwd[PATH_MAX1024];
233 struct cvs_filelist *cf;
234
235 if (getcwd(pwd, sizeof(pwd)) == NULL((void *)0))
236 fatal("Can't get working directory");
237
238 buf = buf_alloc(1024);
239
240 cvs_trigger_loginfo_header(buf, repo);
241
242 if (!RB_EMPTY(&files_added)((&files_added)->rbh_root == ((void *)0))) {
243 buf_puts(buf, "Added Files:");
244
245 RB_FOREACH(cf, cvs_flisthead, &files_added)for ((cf) = cvs_flisthead_RB_MINMAX(&files_added, -1); (cf
) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf))
{
246 buf_putc(buf, '\n');
247 buf_putc(buf, '\t');
248 buf_puts(buf, cf->file_path);
249 }
250
251 buf_putc(buf, '\n');
252 }
253
254 if (!RB_EMPTY(&files_modified)((&files_modified)->rbh_root == ((void *)0))) {
255 buf_puts(buf, "Modified Files:");
256
257 RB_FOREACH(cf, cvs_flisthead, &files_modified)for ((cf) = cvs_flisthead_RB_MINMAX(&files_modified, -1);
(cf) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf))
{
258 buf_putc(buf, '\n');
259 buf_putc(buf, '\t');
260 buf_puts(buf, cf->file_path);
261 }
262
263 buf_putc(buf, '\n');
264 }
265
266 if (!RB_EMPTY(&files_removed)((&files_removed)->rbh_root == ((void *)0))) {
267 buf_puts(buf, "Removed Files:");
268
269 RB_FOREACH(cf, cvs_flisthead, &files_removed)for ((cf) = cvs_flisthead_RB_MINMAX(&files_removed, -1); (
cf) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf))
{
270 buf_putc(buf, '\n');
271 buf_putc(buf, '\t');
272 buf_puts(buf, cf->file_path);
273 }
274
275 buf_putc(buf, '\n');
276 }
277
278 buf_puts(buf, "Log Message:\n");
279
280 buf_puts(buf, logmsg);
281
282 buf_putc(buf, '\n');
283 buf_putc(buf, '\0');
284
285 loginfo = buf_release(buf);
286}
287
288void
289cvs_commit_lock_dirs(struct cvs_file *cf)
290{
291 char repo[PATH_MAX1024];
292
293 cvs_get_repository_path(cf->file_wd, repo, sizeof(repo));
294 cvs_log(LP_TRACE4, "cvs_commit_lock_dirs: %s", repo);
295
296 /* locks stay in place until we are fully done and exit */
297 cvs_repository_lock(repo, 1);
298}
299
300void
301cvs_commit_check_files(struct cvs_file *cf)
302{
303 char *tag;
304 RCSNUM *branch, *brev;
305
306 branch = brev = NULL((void *)0);
307
308 cvs_log(LP_TRACE4, "cvs_commit_check_files(%s)", cf->file_path);
309
310 if (cvsroot_is_remote())
311 cvs_remote_classify_file(cf);
312 else
313 cvs_file_classify(cf, cvs_directory_tag);
314
315 if (cf->file_type == CVS_DIR1) {
316 if (verbosity > 1)
317 cvs_log(LP_NOTICE0, "Examining %s", cf->file_path);
318 return;
319 }
320
321 if (cf->file_status == FILE_UPTODATE4)
322 return;
323
324 if (cf->file_status == FILE_MERGE7 ||
325 cf->file_status == FILE_PATCH8 ||
326 cf->file_status == FILE_CHECKOUT6 ||
327 cf->file_status == FILE_LOST5 ||
328 cf->file_status == FILE_UNLINK11) {
329 cvs_log(LP_ERR1, "conflict: %s is not up-to-date",
330 cf->file_path);
331 conflicts_found++;
332 return;
333 }
334
335 if (cf->file_status == FILE_CONFLICT10 &&
336 cf->file_ent->ce_conflict != NULL((void *)0)) {
337 cvs_log(LP_ERR1, "conflict: unresolved conflicts in %s from "
338 "merging, please fix these first", cf->file_path);
339 conflicts_found++;
340 return;
341 }
342
343 if (cf->file_status == FILE_MODIFIED3 &&
344 cf->file_ent->ce_conflict != NULL((void *)0) &&
345 update_has_conflict_markers(cf)) {
346 cvs_log(LP_ERR1, "warning: file %s seems to still contain "
347 "conflict indicators", cf->file_path);
348 }
349
350 if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_date != -1) {
351 cvs_log(LP_ERR1, "conflict: cannot commit to sticky date for %s",
352 cf->file_path);
353 conflicts_found++;
354 return;
355 }
356
357 if (cvsroot_is_local()) {
358 tag = cvs_directory_tag;
359 if (cf->file_ent != NULL((void *)0))
360 tag = cf->file_ent->ce_tag;
361
362 if (tag != NULL((void *)0) && cf->file_rcs != NULL((void *)0)) {
363 brev = rcs_sym_getrev(cf->file_rcs, tag);
364 if (brev != NULL((void *)0)) {
365 if (!RCSNUM_ISBRANCH(brev)((brev)->rn_len % 2)) {
366 cvs_log(LP_ERR1, "sticky tag %s is not "
367 "a branch for file %s", tag,
368 cf->file_path);
369 conflicts_found++;
370 }
371 }
372 }
373 }
374
375 free(branch);
376 free(brev);
377
378 if (cf->file_status != FILE_ADDED1 &&
379 cf->file_status != FILE_REMOVED2 &&
380 cf->file_status != FILE_MODIFIED3)
381 return;
382
383 cvs_file_get(cf->file_path, 0, &files_affected, CVS_FILE2);
384
385 switch (cf->file_status) {
386 case FILE_ADDED1:
387 cvs_file_get(cf->file_path, 0, &files_added, CVS_FILE2);
388 break;
389 case FILE_REMOVED2:
390 cvs_file_get(cf->file_path, 0, &files_removed, CVS_FILE2);
391 break;
392 case FILE_MODIFIED3:
393 cvs_file_get(cf->file_path, 0, &files_modified, CVS_FILE2);
394 break;
395 }
396}
397
398void
399cvs_commit_local(struct cvs_file *cf)
400{
401 char *tag;
402 BUF *b, *d;
403 int onbranch, isnew, histtype, branchadded;
404 RCSNUM *nrev, *crev, *rrev, *brev;
405 int openflags, rcsflags;
406 char rbuf[CVS_REV_BUFSZ32], nbuf[CVS_REV_BUFSZ32];
407 CVSENTRIES *entlist;
408 char attic[PATH_MAX1024], repo[PATH_MAX1024], rcsfile[PATH_MAX1024];
409 struct file_info *fi;
410
411 cvs_log(LP_TRACE4, "cvs_commit_local(%s)", cf->file_path);
412 cvs_file_classify(cf, cvs_directory_tag);
413
414 if (cvs_noexec == 1)
1
Assuming 'cvs_noexec' is not equal to 1
2
Taking false branch
415 return;
416
417 if (cf->file_type != CVS_FILE2)
3
Assuming field 'file_type' is equal to CVS_FILE
4
Taking false branch
418 fatal("cvs_commit_local: '%s' is not a file", cf->file_path);
419
420 tag = cvs_directory_tag;
421 if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_tag != NULL((void *)0))
5
Assuming field 'file_ent' is equal to NULL
422 tag = cf->file_ent->ce_tag;
423
424 branchadded = 0;
425 switch (cf->file_status) {
6
Control jumps to 'case 1:' at line 426
426 case FILE_ADDED1:
427 if (cf->file_rcs == NULL((void *)0) && tag != NULL((void *)0)) {
7
Assuming field 'file_rcs' is equal to NULL
8
Assuming 'tag' is not equal to NULL
9
Taking true branch
428 branchadded = 1;
429 cvs_add_tobranch(cf, tag);
10
Value assigned to field 'file_rcs'
430 }
431 break;
11
Execution continues on line 445
432 case FILE_MODIFIED3:
433 case FILE_REMOVED2:
434 if (cf->file_rcs == NULL((void *)0)) {
435 cvs_log(LP_ERR1, "RCS file for %s got lost",
436 cf->file_path);
437 return;
438 }
439 break;
440 default:
441 cvs_log(LP_ERR1, "skipping bogus file `%s'", cf->file_path);
442 return;
443 }
444
445 onbranch = 0;
446 nrev = RCS_HEAD_REV((RCSNUM *)(-1));
447 crev = NULL((void *)0);
448 rrev = NULL((void *)0);
449 d = NULL((void *)0);
450
451 if (cf->file_rcs != NULL((void *)0) && cf->file_rcs->rf_branch != NULL((void *)0)) {
12
Assuming field 'file_rcs' is equal to NULL
452 free(cf->file_rcs->rf_branch);
453 cf->file_rcs->rf_branch = NULL((void *)0);
454 }
455
456 if (cf->file_rcs
12.1
Field 'file_rcs' is equal to NULL
!= NULL((void *)0)) {
13
Taking false branch
457 rrev = rcs_head_get(cf->file_rcs);
458 crev = rcs_head_get(cf->file_rcs);
459 if (crev == NULL((void *)0) || rrev == NULL((void *)0))
460 fatal("no head revision in RCS file for %s",
461 cf->file_path);
462
463 if (tag != NULL((void *)0)) {
464 free(crev);
465 free(rrev);
466 brev = rcs_sym_getrev(cf->file_rcs, tag);
467 crev = rcs_translate_tag(tag, cf->file_rcs);
468 if (brev == NULL((void *)0) || crev == NULL((void *)0)) {
469 fatal("failed to resolve existing tag: %s",
470 tag);
471 }
472
473 rrev = rcsnum_alloc();
474 rcsnum_cpy(brev, rrev, brev->rn_len - 1);
475
476 if (RCSNUM_ISBRANCHREV(crev)(!((crev)->rn_len % 2) && ((crev)->rn_len >=
4))
&&
477 rcsnum_cmp(crev, rrev, 0)) {
478 nrev = rcsnum_alloc();
479 rcsnum_cpy(crev, nrev, 0);
480 rcsnum_inc(nrev);
481 } else if (!RCSNUM_ISBRANCH(crev)((crev)->rn_len % 2)) {
482 nrev = rcsnum_brtorev(brev);
483 if (nrev == NULL((void *)0))
484 fatal("failed to create branch rev");
485 } else {
486 fatal("this isnt suppose to happen, honestly");
487 }
488
489 free(brev);
490 free(rrev);
491 rrev = rcsnum_branch_root(nrev);
492
493 /* branch stuff was checked in cvs_commit_check_files */
494 onbranch = 1;
495 }
496
497 rcsnum_tostr(crev, rbuf, sizeof(rbuf));
498 } else {
499 strlcpy(rbuf, "Non-existent", sizeof(rbuf));
500 }
501
502 free(rrev);
503 isnew = 0;
504 if (cf->file_status == FILE_ADDED1) {
14
Assuming field 'file_status' is not equal to FILE_ADDED
15
Taking false branch
505 isnew = 1;
506 rcsflags = RCS_CREATE(1<<2);
507 openflags = O_CREAT0x0200 | O_RDONLY0x0000;
508 if (cf->file_rcs != NULL((void *)0)) {
509 if (!onbranch) {
510 if (cf->in_attic == 0)
511 cvs_log(LP_ERR1, "warning: expected %s "
512 "to be in the Attic",
513 cf->file_path);
514
515 if (cf->file_rcs->rf_dead == 0)
516 cvs_log(LP_ERR1, "warning: expected %s "
517 "to be dead", cf->file_path);
518
519 cvs_get_repository_path(cf->file_wd, repo,
520 PATH_MAX1024);
521 (void)xsnprintf(rcsfile, PATH_MAX1024, "%s/%s%s",
522 repo, cf->file_name, RCS_FILE_EXT",v");
523
524 if (rename(cf->file_rpath, rcsfile) == -1)
525 fatal("cvs_commit_local: failed to "
526 "move %s outside the Attic: %s",
527 cf->file_path, strerror(errno(*__errno())));
528
529 free(cf->file_rpath);
530 cf->file_rpath = xstrdup(rcsfile);
531 isnew = 0;
532 }
533
534 rcsflags = RCS_READ(1<<0) | RCS_PARSE_FULLY(1<<3);
535 openflags = O_RDONLY0x0000;
536 rcs_close(cf->file_rcs);
537 }
538
539 cf->repo_fd = open(cf->file_rpath, openflags);
540 if (cf->repo_fd == -1)
541 fatal("cvs_commit_local: %s", strerror(errno(*__errno())));
542
543 cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd,
544 rcsflags, 0444);
545 if (cf->file_rcs == NULL((void *)0))
546 fatal("cvs_commit_local: failed to create RCS file "
547 "for %s", cf->file_path);
548
549 commit_desc_set(cf);
550
551 if (branchadded)
552 strlcpy(rbuf, "Non-existent", sizeof(rbuf));
553 }
554
555 if (verbosity > 1) {
16
Assuming 'verbosity' is <= 1
17
Taking false branch
556 cvs_printf("Checking in %s:\n", cf->file_path);
557 cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path);
558 cvs_printf("old revision: %s; ", rbuf);
559 }
560
561 if (isnew
17.1
'isnew' is equal to 0
== 0 && cf->file_rcs->rf_head == NULL((void *)0))
18
Access to field 'rf_head' results in a dereference of a null pointer (loaded from field 'file_rcs')
562 fatal("no head revision in RCS file for %s", cf->file_path);
563
564 if (isnew == 0 && onbranch == 0)
565 d = commit_diff(cf, cf->file_rcs->rf_head, 0);
566
567 if (cf->file_status == FILE_REMOVED2) {
568 b = rcs_rev_getbuf(cf->file_rcs, crev, 0);
569 } else if (onbranch == 1) {
570 b = commit_diff(cf, crev, 1);
571 } else {
572 b = buf_load_fd(cf->fd);
573 }
574
575 if (isnew == 0 && onbranch == 0) {
576 if (rcs_deltatext_set(cf->file_rcs, crev, d) == -1)
577 fatal("cvs_commit_local: failed to set delta");
578 }
579
580 if (rcs_rev_add(cf->file_rcs, nrev, logmsg, -1, NULL((void *)0)) == -1)
581 fatal("cvs_commit_local: failed to add new revision");
582
583 if (nrev == RCS_HEAD_REV((RCSNUM *)(-1)))
584 nrev = cf->file_rcs->rf_head;
585
586 if (rcs_deltatext_set(cf->file_rcs, nrev, b) == -1)
587 fatal("cvs_commit_local: failed to set new HEAD delta");
588
589 if (cf->file_status == FILE_REMOVED2) {
590 if (rcs_state_set(cf->file_rcs, nrev, RCS_STATE_DEAD"dead") == -1)
591 fatal("cvs_commit_local: failed to set state");
592 }
593
594 if (cf->file_status == FILE_ADDED1 && cf->file_ent->ce_opts != NULL((void *)0)) {
595 int cf_kflag;
596
597 cf_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2);
598 rcs_kwexp_set(cf->file_rcs, cf_kflag);
599 }
600
601 rcs_write(cf->file_rcs);
602
603 if (cf->file_status == FILE_REMOVED2) {
604 strlcpy(nbuf, "Removed", sizeof(nbuf));
605 } else if (cf->file_status == FILE_ADDED1) {
606 if (cf->file_rcs->rf_dead == 1)
607 strlcpy(nbuf, "Initial Revision", sizeof(nbuf));
608 else
609 rcsnum_tostr(nrev, nbuf, sizeof(nbuf));
610 } else if (cf->file_status == FILE_MODIFIED3) {
611 rcsnum_tostr(nrev, nbuf, sizeof(nbuf));
612 }
613
614 if (verbosity > 1)
615 cvs_printf("new revision: %s\n", nbuf);
616
617 (void)unlink(cf->file_path);
618 (void)close(cf->fd);
619 cf->fd = -1;
620
621 if (cf->file_status != FILE_REMOVED2) {
622 cvs_checkout_file(cf, nrev, NULL((void *)0), CO_COMMIT0x08);
623 } else {
624 entlist = cvs_ent_open(cf->file_wd);
625 cvs_ent_remove(entlist, cf->file_name);
626
627 cvs_get_repository_path(cf->file_wd, repo, PATH_MAX1024);
628
629 (void)xsnprintf(attic, PATH_MAX1024, "%s/%s",
630 repo, CVS_PATH_ATTIC"Attic");
631
632 if (mkdir(attic, 0755) == -1 && errno(*__errno()) != EEXIST17)
633 fatal("cvs_commit_local: failed to create Attic");
634
635 (void)xsnprintf(attic, PATH_MAX1024, "%s/%s/%s%s", repo,
636 CVS_PATH_ATTIC"Attic", cf->file_name, RCS_FILE_EXT",v");
637
638 if (rename(cf->file_rpath, attic) == -1)
639 fatal("cvs_commit_local: failed to move %s to Attic",
640 cf->file_path);
641
642 if (cvs_server_active == 1)
643 cvs_server_update_entry("Remove-entry", cf);
644 }
645
646 if (verbosity > 1)
647 cvs_printf("done\n");
648 else {
649 cvs_log(LP_NOTICE0, "checking in '%s'; revision %s -> %s",
650 cf->file_path, rbuf, nbuf);
651 }
652
653 if (line_list != NULL((void *)0)) {
654 fi = xcalloc(1, sizeof(*fi));
655 fi->file_path = xstrdup(cf->file_path);
656 fi->crevstr = xstrdup(rbuf);
657 fi->nrevstr = xstrdup(nbuf);
658 if (tag != NULL((void *)0))
659 fi->tag_new = xstrdup(tag);
660 TAILQ_INSERT_TAIL(&files_info, fi, flist)do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev
= (&files_info)->tqh_last; *(&files_info)->tqh_last
= (fi); (&files_info)->tqh_last = &(fi)->flist
.tqe_next; } while (0)
;
661 }
662
663 switch (cf->file_status) {
664 case FILE_MODIFIED3:
665 histtype = CVS_HISTORY_COMMIT_MODIFIED8;
666 break;
667 case FILE_ADDED1:
668 histtype = CVS_HISTORY_COMMIT_ADDED9;
669 break;
670 case FILE_REMOVED2:
671 histtype = CVS_HISTORY_COMMIT_REMOVED10;
672 break;
673 default:
674 histtype = -1;
675 break;
676 }
677
678 free(crev);
679
680 if (histtype != -1)
681 cvs_history_add(histtype, cf, NULL((void *)0));
682 else
683 cvs_log(LP_NOTICE0, "histtype was -1 for %s", cf->file_path);
684}
685
686static BUF *
687commit_diff(struct cvs_file *cf, RCSNUM *rev, int reverse)
688{
689 int fd1, fd2, d;
690 char *p1, *p2;
691 BUF *b;
692
693 (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
694
695 if (cf->file_status == FILE_MODIFIED3 ||
696 cf->file_status == FILE_ADDED1) {
697 b = buf_load_fd(cf->fd);
698 fd1 = buf_write_stmp(b, p1, NULL((void *)0));
699 buf_free(b);
700 } else {
701 fd1 = rcs_rev_write_stmp(cf->file_rcs, rev, p1, 0);
702 }
703
704 (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
705 fd2 = rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE0x01);
706
707 b = buf_alloc(128);
708
709 diff_format = D_RCSDIFF5;
710
711 if (reverse == 1)
712 d = diffreg(p2, p1, fd2, fd1, b, D_FORCEASCII0x01);
713 else
714 d = diffreg(p1, p2, fd1, fd2, b, D_FORCEASCII0x01);
715 if (d == D_ERROR7)
716 fatal("commit_diff: failed to get RCS patch");
717
718 close(fd1);
719 close(fd2);
720
721 free(p1);
722 free(p2);
723
724 return (b);
725}
726
727static void
728commit_desc_set(struct cvs_file *cf)
729{
730 BUF *bp;
731 int fd;
732 char desc_path[PATH_MAX1024], *desc;
733
734 (void)xsnprintf(desc_path, PATH_MAX1024, "%s/%s/%s%s",
735 cf->file_wd, CVS_PATH_CVSDIR"CVS", cf->file_name, CVS_DESCR_FILE_EXT",t");
736
737 if ((fd = open(desc_path, O_RDONLY0x0000)) == -1)
738 return;
739
740 bp = buf_load_fd(fd);
741 buf_putc(bp, '\0');
742 desc = buf_release(bp);
743
744 rcs_desc_set(cf->file_rcs, desc);
745
746 (void)close(fd);
747 (void)cvs_unlink(desc_path);
748
749 free(desc);
750}