static int rcsdiff_file(RCSFILE *file, RCSNUM *rev, const char *filename, int dflags) { int ret, fd; time_t t; struct stat st; char *path1, *path2; BUF *b1, *b2; char rbuf[RCS_REV_BUFSZ]; struct tm *tb; struct timeval tv[2], tv2[2]; memset(&tv, 0, sizeof(tv)); memset(&tv2, 0, sizeof(tv2)); ret = D_ERROR; b1 = b2 = NULL; diff_rev1 = rev; diff_rev2 = NULL; path1 = path2 = NULL; if ((fd = open(filename, O_RDONLY)) == -1) { warn("%s", filename); goto out; } rcsnum_tostr(rev, rbuf, sizeof(rbuf)); if (!quiet) { fprintf(stderr, "retrieving revision %s\n", rbuf); fprintf(stderr, "%s -r%s %s\n", diffargs, rbuf, filename); } if ((b1 = rcs_getrev(file, rev)) == NULL) { warnx("failed to retrieve revision %s", rbuf); goto out; } b1 = rcs_kwexp_buf(b1, file, rev); tv[0].tv_sec = (long)rcs_rev_getdate(file, rev); tv[1].tv_sec = tv[0].tv_sec; if ((b2 = buf_load(filename)) == NULL) { warnx("failed to load file: `%s'", filename); goto out; } /* XXX - GNU uses GMT */ if (fstat(fd, &st) == -1) err(D_ERROR, "%s", filename); tb = gmtime(&st.st_mtime); t = mktime(tb); tv2[0].tv_sec = t; tv2[1].tv_sec = t; (void)xasprintf(&path1, "%s/diff1.XXXXXXXXXX", rcs_tmpdir); buf_write_stmp(b1, path1); buf_free(b1); b1 = NULL; if (utimes(path1, (const struct timeval *)&tv) < 0) warn("utimes"); (void)xasprintf(&path2, "%s/diff2.XXXXXXXXXX", rcs_tmpdir); buf_write_stmp(b2, path2); buf_free(b2); b2 = NULL; if (utimes(path2, (const struct timeval *)&tv2) < 0) warn("utimes"); ret = diffreg(path1, path2, NULL, dflags); out: if (fd != -1) (void)close(fd); if (b1 != NULL) buf_free(b1); if (b2 != NULL) buf_free(b2); if (path1 != NULL) xfree(path1); if (path2 != NULL) xfree(path2); return (ret); }
static int rcsdiff_rev(RCSFILE *file, RCSNUM *rev1, RCSNUM *rev2, int dflags) { struct timeval tv[2], tv2[2]; BUF *b1, *b2; int ret; char *path1, *path2, rbuf1[RCS_REV_BUFSZ], rbuf2[RCS_REV_BUFSZ]; ret = D_ERROR; b1 = b2 = NULL; memset(&tv, 0, sizeof(tv)); memset(&tv2, 0, sizeof(tv2)); diff_rev1 = rev1; diff_rev2 = rev2; path1 = path2 = NULL; rcsnum_tostr(rev1, rbuf1, sizeof(rbuf1)); if (!quiet) fprintf(stderr, "retrieving revision %s\n", rbuf1); if ((b1 = rcs_getrev(file, rev1)) == NULL) { warnx("failed to retrieve revision %s", rbuf1); goto out; } b1 = rcs_kwexp_buf(b1, file, rev1); tv[0].tv_sec = (long)rcs_rev_getdate(file, rev1); tv[1].tv_sec = tv[0].tv_sec; rcsnum_tostr(rev2, rbuf2, sizeof(rbuf2)); if (!quiet) fprintf(stderr, "retrieving revision %s\n", rbuf2); if ((b2 = rcs_getrev(file, rev2)) == NULL) { warnx("failed to retrieve revision %s", rbuf2); goto out; } b2 = rcs_kwexp_buf(b2, file, rev2); tv2[0].tv_sec = (long)rcs_rev_getdate(file, rev2); tv2[1].tv_sec = tv2[0].tv_sec; if (!quiet) fprintf(stderr, "%s -r%s -r%s\n", diffargs, rbuf1, rbuf2); (void)xasprintf(&path1, "%s/diff1.XXXXXXXXXX", rcs_tmpdir); buf_write_stmp(b1, path1); buf_free(b1); b1 = NULL; if (utimes(path1, (const struct timeval *)&tv) < 0) warn("utimes"); (void)xasprintf(&path2, "%s/diff2.XXXXXXXXXX", rcs_tmpdir); buf_write_stmp(b2, path2); buf_free(b2); b2 = NULL; if (utimes(path2, (const struct timeval *)&tv2) < 0) warn("utimes"); ret = diffreg(path1, path2, NULL, dflags); out: if (b1 != NULL) buf_free(b1); if (b2 != NULL) buf_free(b2); if (path1 != NULL) xfree(path1); if (path2 != NULL) xfree(path2); return (ret); }
void cvs_diff_local(struct cvs_file *cf) { BUF *b1; int fd1, fd2; struct stat st; struct timespec tv[2], tv2[2]; struct tm datetm; char rbuf[CVS_REV_BUFSZ], tbuf[CVS_TIME_BUFSZ], *p1, *p2; b1 = NULL; fd1 = fd2 = -1; p1 = p2 = NULL; cvs_log(LP_TRACE, "cvs_diff_local(%s)", cf->file_path); if (cf->file_type == CVS_DIR) { if (verbosity > 1) cvs_log(LP_ERR, "Diffing inside %s", cf->file_path); return; } cvs_file_classify(cf, cvs_directory_tag); if (cvs_cmdop == CVS_OP_DIFF) { if (cf->file_ent == NULL) { cvs_log(LP_ERR, "I know nothing about %s", cf->file_path); return; } switch (cf->file_ent->ce_status) { case CVS_ENT_ADDED: if (Nflag == 0) { cvs_log(LP_ERR, "%s is a new entry, no " "comparison available", cf->file_path); return; } if (!(cf->file_flags & FILE_ON_DISK)) { cvs_log(LP_ERR, "cannot find %s", cf->file_path); return; } break; case CVS_ENT_REMOVED: if (Nflag == 0) { cvs_log(LP_ERR, "%s was removed, no " "comparison available", cf->file_path); return; } if (cf->file_rcs == NULL) { cvs_log(LP_ERR, "cannot find RCS file for %s", cf->file_path); return; } break; default: if (!(cf->file_flags & FILE_ON_DISK)) { cvs_printf("? %s\n", cf->file_path); return; } if (cf->file_rcs == NULL) { cvs_log(LP_ERR, "cannot find RCS file for %s", cf->file_path); return; } break; } } if (cf->file_status == FILE_UPTODATE && rev1 == NULL && rev2 == NULL && date1 == -1 && date2 == -1) return; if (cf->file_rcs != NULL && cf->file_rcs->rf_head == NULL) { cvs_log(LP_ERR, "no head revision in RCS file for %s\n", cf->file_path); return; } if (kflag && cf->file_rcs != NULL) rcs_kwexp_set(cf->file_rcs, kflag); if (cf->file_rcs == NULL) diff_rev1 = NULL; else if (rev1 != NULL || date1 != -1) { cvs_specified_date = date1; diff_rev1 = rcs_translate_tag(rev1, cf->file_rcs); if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_DIFF) { if (rev1 != NULL) { cvs_log(LP_ERR, "tag %s not in file %s", rev1, cf->file_path); goto cleanup; } else if (Nflag) { diff_rev1 = NULL; } else { gmtime_r(&cvs_specified_date, &datetm); strftime(tbuf, sizeof(tbuf), "%Y.%m.%d.%H.%M.%S", &datetm); cvs_log(LP_ERR, "no revision for date %s in " "file %s", tbuf, cf->file_path); goto cleanup; } } else if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_RDIFF && force_head) { /* -f is not allowed for unknown symbols */ if ((diff_rev1 = rcsnum_parse(rev1)) == NULL) fatal("no such tag %s", rev1); rcsnum_free(diff_rev1); diff_rev1 = cf->file_rcs->rf_head; } cvs_specified_date = -1; } else if (cvs_cmdop == CVS_OP_DIFF) { if (cf->file_ent->ce_status == CVS_ENT_ADDED) diff_rev1 = NULL; else diff_rev1 = cf->file_ent->ce_rev; } if (cf->file_rcs == NULL) diff_rev2 = NULL; else if (rev2 != NULL || date2 != -1) { cvs_specified_date = date2; diff_rev2 = rcs_translate_tag(rev2, cf->file_rcs); if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_DIFF) { if (rev2 != NULL) { cvs_log(LP_ERR, "tag %s not in file %s", rev2, cf->file_path); goto cleanup; } else if (Nflag) { diff_rev2 = NULL; } else { gmtime_r(&cvs_specified_date, &datetm); strftime(tbuf, sizeof(tbuf), "%Y.%m.%d.%H.%M.%S", &datetm); cvs_log(LP_ERR, "no revision for date %s in " "file %s", tbuf, cf->file_path); goto cleanup; } } else if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_RDIFF && force_head) { /* -f is not allowed for unknown symbols */ if ((diff_rev2 = rcsnum_parse(rev2)) == NULL) fatal("no such tag %s", rev2); rcsnum_free(diff_rev2); diff_rev2 = cf->file_rcs->rf_head; } cvs_specified_date = -1; } else if (cvs_cmdop == CVS_OP_RDIFF) diff_rev2 = cf->file_rcs->rf_head; else if (cf->file_ent->ce_status == CVS_ENT_REMOVED) diff_rev2 = NULL; if (diff_rev1 != NULL && diff_rev2 != NULL && rcsnum_cmp(diff_rev1, diff_rev2, 0) == 0) goto cleanup; switch (cvs_cmdop) { case CVS_OP_DIFF: if (cf->file_status == FILE_UPTODATE) { if (diff_rev2 == NULL && !rcsnum_cmp(diff_rev1, cf->file_rcsrev, 0)) goto cleanup; } break; case CVS_OP_RDIFF: if (diff_rev1 == NULL && diff_rev2 == NULL) goto cleanup; break; } cvs_printf("Index: %s\n", cf->file_path); if (cvs_cmdop == CVS_OP_DIFF) cvs_printf("%s\nRCS file: %s\n", RCS_DIFF_DIV, cf->file_rcs != NULL ? cf->file_rpath : cf->file_path); if (diff_rev1 != NULL) { if (cvs_cmdop == CVS_OP_DIFF && diff_rev1 != NULL) { (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf)); cvs_printf("retrieving revision %s\n", rbuf); } tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev1); tv[0].tv_nsec = 0; tv[1] = tv[0]; (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); fd1 = rcs_rev_write_stmp(cf->file_rcs, diff_rev1, p1, 0); if (futimens(fd1, tv) == -1) fatal("cvs_diff_local: futimens failed"); } if (diff_rev2 != NULL) { if (cvs_cmdop == CVS_OP_DIFF && rev2 != NULL) { (void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf)); cvs_printf("retrieving revision %s\n", rbuf); } tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2); tv2[0].tv_nsec = 0; tv2[1] = tv2[0]; (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); fd2 = rcs_rev_write_stmp(cf->file_rcs, diff_rev2, p2, 0); if (futimens(fd2, tv2) == -1) fatal("cvs_diff_local: futimens failed"); } else if (cvs_cmdop == CVS_OP_DIFF && (cf->file_flags & FILE_ON_DISK) && cf->file_ent->ce_status != CVS_ENT_REMOVED) { (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); if (cvs_server_active == 1 && cf->fd == -1) { tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, cf->file_ent->ce_rev); tv2[0].tv_nsec = 0; tv2[1] = tv2[0]; fd2 = rcs_rev_write_stmp(cf->file_rcs, cf->file_ent->ce_rev, p2, 0); if (futimens(fd2, tv2) == -1) fatal("cvs_diff_local: futimens failed"); } else { if (fstat(cf->fd, &st) == -1) fatal("fstat failed %s", strerror(errno)); b1 = buf_load_fd(cf->fd); tv2[0].tv_sec = st.st_mtime; tv2[0].tv_nsec = 0; tv2[1] = tv2[0]; fd2 = buf_write_stmp(b1, p2, tv2); buf_free(b1); } } switch (cvs_cmdop) { case CVS_OP_DIFF: cvs_printf("%s", diffargs); if (rev1 != NULL && diff_rev1 != NULL) { (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf)); cvs_printf(" -r%s", rbuf); if (rev2 != NULL && diff_rev2 != NULL) { (void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf)); cvs_printf(" -r%s", rbuf); } } if (diff_rev2 == NULL) cvs_printf(" %s", cf->file_path); cvs_printf("\n"); break; case CVS_OP_RDIFF: cvs_printf("diff "); switch (diff_format) { case D_CONTEXT: cvs_printf("-c "); break; case D_RCSDIFF: cvs_printf("-n "); break; case D_UNIFIED: cvs_printf("-u "); break; default: break; } if (diff_rev1 == NULL) { cvs_printf("%s ", CVS_PATH_DEVNULL); } else { (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf)); cvs_printf("%s:%s ", cf->file_path, rbuf); } if (diff_rev2 == NULL) { cvs_printf("%s:removed\n", cf->file_path); } else { (void)rcsnum_tostr(diff_rev2 != NULL ? diff_rev2 : cf->file_rcs->rf_head, rbuf, sizeof(rbuf)); cvs_printf("%s:%s\n", cf->file_path, rbuf); } break; } if (fd1 == -1) { if ((fd1 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1) fatal("cannot open %s", CVS_PATH_DEVNULL); } if (fd2 == -1) { if ((fd2 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1) fatal("cannot open %s", CVS_PATH_DEVNULL); } if (diffreg(p1 != NULL ? cf->file_path : CVS_PATH_DEVNULL, p2 != NULL ? cf->file_path : CVS_PATH_DEVNULL, fd1, fd2, NULL, dflags) == D_ERROR) fatal("cvs_diff_local: failed to get RCS patch"); close(fd1); close(fd2); worklist_run(&temp_files, worklist_unlink); if (p1 != NULL) xfree(p1); if (p2 != NULL) xfree(p2); cleanup: if (diff_rev1 != NULL && (cf->file_rcs == NULL || diff_rev1 != cf->file_rcs->rf_head) && (cf->file_ent == NULL || diff_rev1 != cf->file_ent->ce_rev)) xfree(diff_rev1); diff_rev1 = NULL; if (diff_rev2 != NULL && (cf->file_rcs == NULL || diff_rev2 != cf->file_rcs->rf_head)) xfree(diff_rev2); diff_rev2 = NULL; }