void cvs_repository_lock(const char *repo, int wantlock) { int i; uid_t myuid; struct stat st; char fpath[MAXPATHLEN]; struct passwd *pw; if (cvs_noexec == 1 || cvs_readonlyfs == 1) return; cvs_log(LP_TRACE, "cvs_repository_lock(%s, %d)", repo, wantlock); (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", repo, CVS_LOCK); myuid = getuid(); for (i = 0; i < CVS_LOCK_TRIES; i++) { if (cvs_quit) fatal("received signal %d", sig_received); if (stat(fpath, &st) == -1) break; if (st.st_uid == myuid) return; if ((pw = getpwuid(st.st_uid)) == NULL) fatal("cvs_repository_lock: %s", strerror(errno)); cvs_log(LP_NOTICE, "waiting for %s's lock in '%s'", pw->pw_name, repo); sleep(CVS_LOCK_SLEEP); } if (i == CVS_LOCK_TRIES) fatal("maximum wait time for lock inside '%s' reached", repo); if (wantlock == 0) return; if ((i = open(fpath, O_WRONLY|O_CREAT|O_TRUNC, 0755)) < 0) { if (errno == EEXIST) fatal("cvs_repository_lock: somebody beat us"); else fatal("cvs_repository_lock: %s: %s", fpath, strerror(errno)); } (void)close(i); worklist_add(fpath, &repo_locks); }
void cvs_import_local(struct cvs_file *cf) { int isnew; struct stat st; char repo[MAXPATHLEN]; cvs_log(LP_TRACE, "cvs_import_local(%s)", cf->file_path); cvs_file_classify(cf, cvs_directory_tag); if (cf->file_type == CVS_DIR) { if (!strcmp(cf->file_path, ".")) return; if (verbosity > 1) cvs_log(LP_NOTICE, "Importing %s", cf->file_path); if (cvs_noexec == 1) return; if (mkdir(cf->file_rpath, 0755) == -1 && errno != EEXIST) fatal("cvs_import_local: %s: %s", cf->file_rpath, strerror(errno)); return; } isnew = 1; (void)xsnprintf(repo, sizeof(repo), "%s/%s/%s/%s%s", current_cvsroot->cr_dir, cf->file_wd, CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT); if (cf->file_rcs != NULL || stat(repo, &st) != -1) isnew = 0; if (isnew == 1) import_new(cf); else import_update(cf); }
void cvs_repository_unlock(const char *repo) { char fpath[MAXPATHLEN]; cvs_log(LP_TRACE, "cvs_repository_unlock(%s)", repo); (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", repo, CVS_LOCK); /* XXX - this ok? */ worklist_run(&repo_locks, worklist_unlink); }
void cvs_cleanup(void) { cvs_log(LP_TRACE, "cvs_cleanup: removing locks"); worklist_run(&repo_locks, worklist_unlink); cvs_log(LP_TRACE, "cvs_cleanup: removing temp files"); worklist_run(&temp_files, worklist_unlink); if (cvs_server_path != NULL) { if (cvs_rmdir(cvs_server_path) == -1) cvs_log(LP_ERR, "warning: failed to remove server directory: %s", cvs_server_path); xfree(cvs_server_path); cvs_server_path = NULL; } if (current_list != NULL) cvs_ent_close(current_list, ENT_SYNC); }
static int expand_var(BUF *buf, const char *var) { struct passwd *pw; const char *val; if (*var == '=') { if ((val = cvs_var_get(++var)) == NULL) { cvs_log(LP_ERR, "no such user variable ${=%s}", var); return (1); } buf_puts(buf, val); } else { if (strcmp(var, "CVSEDITOR") == 0 || strcmp(var, "EDITOR") == 0 || strcmp(var, "VISUAL") == 0) buf_puts(buf, cvs_editor); else if (strcmp(var, "CVSROOT") == 0) buf_puts(buf, current_cvsroot->cr_dir); else if (strcmp(var, "USER") == 0) { pw = getpwuid(geteuid()); if (pw == NULL) { cvs_log(LP_ERR, "unable to retrieve " "caller ID"); return (1); } buf_puts(buf, pw->pw_name); } else if (strcmp(var, "RCSBIN") == 0) { cvs_log(LP_ERR, "RCSBIN internal variable is no " "longer supported"); return (1); } else { cvs_log(LP_ERR, "no such internal variable $%s", var); return (1); } } return (0); }
/* * cvs_var_set() * * Set the value of the variable <var> to <val>. If there is no such variable, * a new entry is created, otherwise the old value is overwritten. * Returns 0 on success, or -1 on failure. */ int cvs_var_set(const char *var, const char *val) { const char *cp; struct cvs_var *vp; if (var == NULL || *var == '\0') { cvs_log(LP_ERR, "no variable name"); return (-1); } /* sanity check on the name */ for (cp = var; *cp != '\0'; cp++) if (!isalnum((unsigned char)*cp) && (*cp != '_')) { cvs_log(LP_ERR, "variable name `%s' contains invalid characters", var); return (-1); } TAILQ_FOREACH(vp, &cvs_variables, cv_link) if (strcmp(vp->cv_name, var) == 0) break; if (vp == NULL) { vp = xcalloc(1, sizeof(*vp)); vp->cv_name = xstrdup(var); TAILQ_INSERT_TAIL(&cvs_variables, vp, cv_link); } else /* free the previous value */ xfree(vp->cv_val); vp->cv_val = xstrdup(val); return (0); }
void cvs_add_local(struct cvs_file *cf) { cvs_log(LP_TRACE, "cvs_add_local(%s)", cf->file_path); if (cvs_cmdop != CVS_OP_CHECKOUT && cvs_cmdop != CVS_OP_UPDATE) cvs_file_classify(cf, cvs_directory_tag); /* dont use `cvs add *' */ if (strcmp(cf->file_name, ".") == 0 || strcmp(cf->file_name, "..") == 0 || strcmp(cf->file_name, CVS_PATH_CVSDIR) == 0) { if (verbosity > 1) cvs_log(LP_ERR, "cannot add special file `%s'; skipping", cf->file_name); return; } if (cf->file_type == CVS_DIR) add_directory(cf); else add_file(cf); }
void cvs_server_static_directory(char *data) { FILE *fp; char fpath[MAXPATHLEN]; (void)xsnprintf(fpath, MAXPATHLEN, "%s/%s", server_currentdir, CVS_PATH_STATICENTRIES); if ((fp = fopen(fpath, "w+")) == NULL) { cvs_log(LP_ERRNO, "%s", fpath); return; } (void)fclose(fp); }
void cvs_server_send_response(char *fmt, ...) { int i; va_list ap; char *data; va_start(ap, fmt); i = vasprintf(&data, fmt, ap); va_end(ap); if (i == -1) fatal("cvs_server_send_response: could not allocate memory"); cvs_log(LP_TRACE, "%s", data); cvs_remote_output(data); xfree(data); }
void cvs_server_sticky(char *data) { FILE *fp; char tagpath[MAXPATHLEN]; if (data == NULL) fatal("Missing argument for Sticky"); (void)xsnprintf(tagpath, MAXPATHLEN, "%s/%s", server_currentdir, CVS_PATH_TAG); if ((fp = fopen(tagpath, "w+")) == NULL) { cvs_log(LP_ERRNO, "%s", tagpath); return; } (void)fprintf(fp, "%s\n", data); (void)fclose(fp); }
/* * cvsroot_get() * * Get the CVSROOT information for a specific directory <dir>. The * value is taken from one of 3 possible sources (in order of precedence): * * 1) the `-d' command-line option * 2) the CVS/Root file found in checked-out trees * 3) the CVSROOT environment variable */ struct cvsroot * cvsroot_get(const char *dir) { char rootpath[MAXPATHLEN], *rootstr, line[128]; FILE *fp; if (cvs_rootstr != NULL) return cvsroot_parse(cvs_rootstr); if (cvs_server_active == 1) return cvsroot_parse(dir); if (cvs_cmdop == CVS_OP_IMPORT) return NULL; (void)xsnprintf(rootpath, MAXPATHLEN, "%s/%s", dir, CVS_PATH_ROOTSPEC); if ((fp = fopen(rootpath, "r")) == NULL) { if (errno == ENOENT) { /* try env as a last resort */ if ((rootstr = getenv("CVSROOT")) != NULL) return cvsroot_parse(rootstr); else return (NULL); } else { fatal("cvsroot_get: fopen: `%s': %s", CVS_PATH_ROOTSPEC, strerror(errno)); } } if (fgets(line, (int)sizeof(line), fp) == NULL) fatal("cvsroot_get: fgets: `%s'", CVS_PATH_ROOTSPEC); (void)fclose(fp); line[strcspn(line, "\n")] = '\0'; if (line[0] == '\0') cvs_log(LP_ERR, "empty %s file", CVS_PATH_ROOTSPEC); return cvsroot_parse(line); }
int config_parse_line(char *line, int lineno) { struct rlimit rl; const char *errstr; char *val, *opt, *ep; opt = line; if ((val = strrchr(opt, '=')) == NULL) fatal("cvs_parse_configfile: bad option '%s'", opt); *(val++) = '\0'; if (!strcmp(opt, "tag")) { free(cvs_tagname); cvs_tagname = xstrdup(val); } else if (!strcmp(opt, "umask")) { cvs_umask = strtol(val, &ep, 8); if (val == ep || *ep != '\0') fatal("cvs_parse_configfile: umask %s is " "invalid", val); if (cvs_umask < 0 || cvs_umask > 07777) fatal("cvs_parse_configfile: umask %s is " "invalid", val); } else if (!strcmp(opt, "dlimit")) { if (getrlimit(RLIMIT_DATA, &rl) != -1) { rl.rlim_cur = (int)strtonum(val, 0, INT_MAX, &errstr); if (errstr != NULL) fatal("cvs_parse_configfile: %s: %s", val, errstr); rl.rlim_cur = rl.rlim_cur * 1024; (void)setrlimit(RLIMIT_DATA, &rl); } } else { cvs_log(LP_ERR, "ignoring unknown option '%s'", opt); } return (0); }
void cvs_add_remote(struct cvs_file *cf) { char path[MAXPATHLEN]; cvs_log(LP_TRACE, "cvs_add_remote(%s)", cf->file_path); cvs_file_classify(cf, cvs_directory_tag); if (cf->file_type == CVS_DIR) { cvs_get_repository_path(cf->file_wd, path, MAXPATHLEN); if (strlcat(path, "/", sizeof(path)) >= sizeof(path)) fatal("cvs_add_remote: truncation"); if (strlcat(path, cf->file_path, sizeof(path)) >= sizeof(path)) fatal("cvs_add_remote: truncation"); cvs_client_send_request("Directory %s\n%s", cf->file_path, path); add_directory(cf); } else { cvs_client_sendfile(cf); } }
/* * Write the contents of the buffer <b> to the file whose path is given in * <path>. If the file does not exist, it is created with mode <mode>. */ int buf_write(BUF *b, const char *path, mode_t mode) { int fd; open: if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) == -1) { if (errno == EACCES && unlink(path) != -1) goto open; else fatal("open: `%s': %s", path, strerror(errno)); } if (buf_write_fd(b, fd) == -1) { (void)unlink(path); fatal("buf_write: buf_write_fd: `%s'", path); } if (fchmod(fd, mode) < 0) cvs_log(LP_ERR, "permissions not set on file %s", path); (void)close(fd); return (0); }
int cvs_import(int argc, char **argv) { int i, ch; char repo[MAXPATHLEN], *arg = "."; struct cvs_recursion cr; struct trigger_list *line_list; while ((ch = getopt(argc, argv, cvs_cmd_import.cmd_opts)) != -1) { switch (ch) { case 'b': import_branch = optarg; break; case 'd': dflag = 1; break; case 'k': koptstr = optarg; kflag = rcs_kflag_get(koptstr); if (RCS_KWEXP_INVAL(kflag)) { cvs_log(LP_ERR, "invalid RCS keyword expansion mode"); fatal("%s", cvs_cmd_import.cmd_synopsis); } break; case 'm': logmsg = optarg; break; default: fatal("%s", cvs_cmd_import.cmd_synopsis); break; } } argc -= optind; argv += optind; if (argc < 3) fatal("%s", cvs_cmd_import.cmd_synopsis); import_repository = argv[0]; vendor_tag = argv[1]; argc -= 2; argv += 2; release_tags = argv; tagcount = argc; if (!rcs_sym_check(vendor_tag)) fatal("invalid symbol: %s", vendor_tag); for (i = 0; i < tagcount; i++) { if (!rcs_sym_check(release_tags[i])) fatal("invalid symbol: %s", release_tags[i]); } if (logmsg == NULL) { if (cvs_server_active) fatal("no log message specified"); else logmsg = cvs_logmsg_create(NULL, NULL, NULL, NULL); } if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_connect_to_server(); cvs_client_send_request("Argument -b%s", IMPORT_DEFAULT_BRANCH); if (kflag) cvs_client_send_request("Argument -k%s", koptstr); cvs_client_send_logmsg(logmsg); cvs_client_send_request("Argument %s", import_repository); cvs_client_send_request("Argument %s", vendor_tag); for (i = 0; i < tagcount; i++) cvs_client_send_request("Argument %s", release_tags[i]); cr.enterdir = NULL; cr.leavedir = NULL; cr.fileproc = cvs_client_sendfile; cr.flags = CR_RECURSE_DIRS; cvs_file_run(1, &arg, &cr); cvs_client_senddir("."); cvs_client_send_request("import"); cvs_client_get_responses(); return (0); } if (cvs_logmsg_verify(logmsg)) return (0); (void)xsnprintf(repo, sizeof(repo), "%s/%s", current_cvsroot->cr_dir, import_repository); import_loginfo(import_repository); if (cvs_noexec != 1) cvs_mkdir(repo, 0755); cr.enterdir = NULL; cr.leavedir = NULL; cr.fileproc = cvs_import_local; cr.flags = CR_RECURSE_DIRS; cvs_file_run(1, &arg, &cr); if (import_conflicts != 0) { import_printf("\n%d conflicts created by this import.\n\n", import_conflicts); import_printf("Use the following command to help the merge:\n"); import_printf("\topencvs checkout "); import_printf("-j%s:yesterday -j%s %s\n\n", vendor_tag, vendor_tag, import_repository); } else { import_printf("\nNo conflicts created by this import.\n\n"); } loginfo = buf_release(logbuf); logbuf = NULL; line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO, import_repository); if (line_list != NULL) { cvs_trigger_handle(CVS_TRIGGER_LOGINFO, import_repository, loginfo, line_list, NULL); cvs_trigger_freelist(line_list); } xfree(loginfo); return (0); }
static void import_update(struct cvs_file *cf) { int ret; BUF *b1, *b2, *d; char branch[CVS_REV_BUFSZ]; RCSNUM *newrev, *rev, *brev; cvs_log(LP_TRACE, "import_update(%s)", cf->file_path); if (cf->file_rcs->rf_head == NULL) fatal("no head revision in RCS file for `%s'", cf->file_path); if ((rev = rcs_translate_tag(import_branch, cf->file_rcs)) == NULL) fatal("import_update: could not translate tag `%s'", import_branch); if ((brev = rcsnum_parse(import_branch)) == NULL) fatal("import_update: rcsnum_parse failed"); b1 = rcs_rev_getbuf(cf->file_rcs, rev, RCS_KWEXP_NONE); b2 = buf_load_fd(cf->fd); ret = buf_differ(b1, b2); buf_free(b1); buf_free(b2); if (ret == 0) { import_tag(cf, brev, rev); rcsnum_free(brev); if (cvs_noexec != 1) rcs_write(cf->file_rcs); import_printf("U %s/%s\n", import_repository, cf->file_path); return; } if (cf->file_rcs->rf_branch != NULL) rcsnum_tostr(cf->file_rcs->rf_branch, branch, sizeof(branch)); if (cf->file_rcs->rf_branch == NULL || cf->in_attic == 1 || strcmp(branch, import_branch)) { import_conflicts++; import_printf("C %s/%s\n", import_repository, cf->file_path); } else { import_printf("U %s/%s\n", import_repository, cf->file_path); } if (cvs_noexec == 1) return; d = import_get_rcsdiff(cf, rev); newrev = rcsnum_inc(rev); if (rcs_rev_add(cf->file_rcs, newrev, logmsg, -1, NULL) == -1) fatal("import_update: failed to add new revision"); if (rcs_deltatext_set(cf->file_rcs, newrev, d) == -1) fatal("import_update: failed to set deltatext"); import_tag(cf, brev, newrev); if (kflag) rcs_kwexp_set(cf->file_rcs, kflag); rcsnum_free(brev); rcs_write(cf->file_rcs); }
static void import_new(struct cvs_file *cf) { int i; BUF *bp; mode_t mode; time_t tstamp; struct stat st; struct rcs_branch *brp; struct rcs_delta *rdp; RCSNUM *branch, *brev; tstamp = -1; cvs_log(LP_TRACE, "import_new(%s)", cf->file_name); if (cvs_noexec == 1) { import_printf("N %s/%s\n", import_repository, cf->file_path); return; } if (fstat(cf->fd, &st) == -1) fatal("import_new: %s", strerror(errno)); mode = st.st_mode; if (dflag == 1) tstamp = st.st_mtime; if ((branch = rcsnum_parse(import_branch)) == NULL) fatal("import_new: failed to parse branch"); bp = buf_load_fd(cf->fd); if ((brev = rcsnum_brtorev(branch)) == NULL) fatal("import_new: failed to get first branch revision"); cf->repo_fd = open(cf->file_rpath, O_CREAT | O_RDONLY); if (cf->repo_fd < 0) fatal("import_new: %s: %s", cf->file_rpath, strerror(errno)); cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, RCS_CREATE, (mode & ~(S_IWUSR | S_IWGRP | S_IWOTH))); if (cf->file_rcs == NULL) fatal("import_new: failed to create RCS file for %s", cf->file_path); rcs_branch_set(cf->file_rcs, branch); if (rcs_sym_add(cf->file_rcs, vendor_tag, branch) == -1) fatal("import_new: failed to add vendor tag"); for (i = 0; i < tagcount; i++) { if (rcs_sym_add(cf->file_rcs, release_tags[i], brev) == -1) fatal("import_new: failed to add release tag"); } if (rcs_rev_add(cf->file_rcs, brev, logmsg, tstamp, NULL) == -1) fatal("import_new: failed to create first branch revision"); if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, "Initial revision", tstamp, NULL) == -1) fatal("import_new: failed to create first revision"); if ((rdp = rcs_findrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL) fatal("import_new: cannot find newly added revision"); brp = xmalloc(sizeof(*brp)); brp->rb_num = rcsnum_alloc(); rcsnum_cpy(brev, brp->rb_num, 0); TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list); if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, bp) == -1) fatal("import_new: failed to set deltatext"); if (kflag) rcs_kwexp_set(cf->file_rcs, kflag); rcs_write(cf->file_rcs); import_printf("N %s/%s\n", import_repository, cf->file_path); rcsnum_free(branch); rcsnum_free(brev); }
int cvs_add(int argc, char **argv) { int ch; int flags; struct cvs_recursion cr; flags = CR_REPO; while ((ch = getopt(argc, argv, cvs_cmd_add.cmd_opts)) != -1) { switch (ch) { case 'k': kflag = rcs_kflag_get(optarg); if (RCS_KWEXP_INVAL(kflag)) { cvs_log(LP_ERR, "invalid RCS keyword expansion mode"); fatal("%s", cvs_cmd_add.cmd_synopsis); } (void)xsnprintf(kbuf, sizeof(kbuf), "-k%s", optarg); break; case 'm': logmsg = optarg; break; default: fatal("%s", cvs_cmd_add.cmd_synopsis); } } argc -= optind; argv += optind; if (argc == 0) fatal("%s", cvs_cmd_add.cmd_synopsis); cr.enterdir = NULL; cr.leavedir = NULL; if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_connect_to_server(); cr.fileproc = cvs_add_remote; flags = 0; if (kflag) cvs_client_send_request("Argument %s", kbuf); if (logmsg != NULL) cvs_client_send_logmsg(logmsg); } else { if (logmsg != NULL && cvs_logmsg_verify(logmsg)) return (0); cr.fileproc = cvs_add_local; } cr.flags = flags; cvs_file_run(argc, argv, &cr); if (added_files != 0) { cvs_log(LP_NOTICE, "use '%s commit' to add %s " "permanently", __progname, (added_files == 1) ? "this file" : "these files"); } if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_senddir("."); cvs_client_send_files(argv, argc); cvs_client_send_request("add"); cvs_client_get_responses(); if (server_response == SERVER_OK) { cr.fileproc = cvs_add_entry; cvs_file_run(argc, argv, &cr); } } return (0); }
void cvs_admin_local(struct cvs_file *cf) { int i; RCSNUM *rev; cvs_log(LP_TRACE, "cvs_admin_local(%s)", cf->file_path); cvs_file_classify(cf, cvs_directory_tag); if (cf->file_type == CVS_DIR) { if (verbosity > 1) cvs_log(LP_NOTICE, "Administrating %s", cf->file_name); return; } if (cf->file_ent == NULL) return; else if (cf->file_status == FILE_ADDED) { cvs_log(LP_ERR, "cannot admin newly added file `%s'", cf->file_name); return; } if (cf->file_rcs == NULL) { cvs_log(LP_ERR, "lost RCS file for `%s'", cf->file_path); return; } if (verbosity > 0) cvs_printf("RCS file: %s\n", cf->file_rcs->rf_path); if (oldfilename != NULL) { struct cvs_file *ocf; struct rcs_access *acp; int ofd; char *d, *f, fpath[MAXPATHLEN], repo[MAXPATHLEN]; if ((f = basename(oldfilename)) == NULL) fatal("cvs_admin_local: basename failed"); if ((d = dirname(oldfilename)) == NULL) fatal("cvs_admin_local: dirname failed"); cvs_get_repository_path(d, repo, MAXPATHLEN); (void)xsnprintf(fpath, MAXPATHLEN, "%s/%s", repo, f); if (strlcat(fpath, RCS_FILE_EXT, MAXPATHLEN) >= MAXPATHLEN) fatal("cvs_admin_local: truncation"); if ((ofd = open(fpath, O_RDONLY)) == -1) fatal("cvs_admin_local: open: `%s': %s", fpath, strerror(errno)); /* XXX: S_ISREG() check instead of blindly using CVS_FILE? */ ocf = cvs_file_get_cf(d, f, oldfilename, ofd, CVS_FILE, 0); ocf->file_rcs = rcs_open(fpath, ofd, RCS_READ, 0444); if (ocf->file_rcs == NULL) fatal("cvs_admin_local: rcs_open failed"); TAILQ_FOREACH(acp, &(ocf->file_rcs->rf_access), ra_list) rcs_access_add(cf->file_rcs, acp->ra_name); cvs_file_free(ocf); } if (alist != NULL) { struct cvs_argvector *aargv; aargv = cvs_strsplit(alist, ","); for (i = 0; aargv->argv[i] != NULL; i++) rcs_access_add(cf->file_rcs, aargv->argv[i]); cvs_argv_destroy(aargv); } if (comment != NULL) rcs_comment_set(cf->file_rcs, comment); if (elist != NULL) { struct cvs_argvector *eargv; eargv = cvs_strsplit(elist, ","); for (i = 0; eargv->argv[i] != NULL; i++) rcs_access_remove(cf->file_rcs, eargv->argv[i]); cvs_argv_destroy(eargv); } else if (runflags & ADM_EFLAG) { struct rcs_access *rap; while (!TAILQ_EMPTY(&(cf->file_rcs->rf_access))) { rap = TAILQ_FIRST(&(cf->file_rcs->rf_access)); TAILQ_REMOVE(&(cf->file_rcs->rf_access), rap, ra_list); xfree(rap->ra_name); xfree(rap); } /* no synced anymore */ cf->file_rcs->rf_flags &= ~RCS_SYNCED; } /* Default `-kv' is accepted here. */ if (kflag) { if (cf->file_rcs->rf_expand == NULL || strcmp(cf->file_rcs->rf_expand, koptstr) != 0) rcs_kwexp_set(cf->file_rcs, kflag); } if (logstr != NULL) { if ((logmsg = strchr(logstr, ':')) == NULL) { cvs_log(LP_ERR, "missing log message"); return; } *logmsg++ = '\0'; if ((rev = rcsnum_parse(logstr)) == NULL) { cvs_log(LP_ERR, "`%s' bad revision number", logstr); return; } if (rcs_rev_setlog(cf->file_rcs, rev, logmsg) < 0) { cvs_log(LP_ERR, "failed to set logmsg for `%s' to `%s'", logstr, logmsg); rcsnum_free(rev); return; } rcsnum_free(rev); } if (orange != NULL) { struct rcs_delta *rdp, *nrdp; char b[CVS_REV_BUFSZ]; cvs_revision_select(cf->file_rcs, orange); for (rdp = TAILQ_FIRST(&(cf->file_rcs->rf_delta)); rdp != NULL; rdp = nrdp) { nrdp = TAILQ_NEXT(rdp, rd_list); /* * Delete selected revisions. */ if (rdp->rd_flags & RCS_RD_SELECT) { rcsnum_tostr(rdp->rd_num, b, sizeof(b)); if (verbosity > 0) cvs_printf("deleting revision %s\n", b); (void)rcs_rev_remove(cf->file_rcs, rdp->rd_num); } } } if (state != NULL) { if (staterevstr != NULL) { if ((rev = rcsnum_parse(staterevstr)) == NULL) { cvs_log(LP_ERR, "`%s' bad revision number", staterevstr); return; } } else if (cf->file_rcs->rf_head != NULL) { rev = rcsnum_alloc(); rcsnum_cpy(cf->file_rcs->rf_head, rev, 0); } else { cvs_log(LP_ERR, "head revision missing"); return; } (void)rcs_state_set(cf->file_rcs, rev, state); rcsnum_free(rev); } if (lkmode != RCS_LOCK_INVAL) (void)rcs_lock_setmode(cf->file_rcs, lkmode); rcs_write(cf->file_rcs); if (verbosity > 0) cvs_printf("done\n"); }
static char * parse_cmd(int type, char *cmd, const char *repo, struct file_info_list *file_info) { int expanded = 0; char argbuf[2] = { '\0', '\0' }; char *allowed_args, *default_args, *args, *file, *p, *q = NULL; size_t pos; BUF *buf; switch (type) { case CVS_TRIGGER_COMMITINFO: allowed_args = "prsS{}"; default_args = " %p/%r %S"; file = CVS_PATH_COMMITINFO; break; case CVS_TRIGGER_LOGINFO: allowed_args = "prsSvVt{}"; default_args = NULL; file = CVS_PATH_LOGINFO; break; case CVS_TRIGGER_VERIFYMSG: allowed_args = "l"; default_args = " %l"; file = CVS_PATH_VERIFYMSG; break; case CVS_TRIGGER_TAGINFO: allowed_args = "btoprsSvV{}"; default_args = " %t %o %p/%r %{sv}"; file = CVS_PATH_TAGINFO; break; default: return (NULL); } /* before doing any stuff, check if the command starts with % */ for (p = cmd; *p != '%' && !isspace((unsigned char)*p) && *p != '\0'; p++) ; if (*p == '%') return (NULL); buf = buf_alloc(1024); p = cmd; again: for (; *p != '\0'; p++) { if ((pos = strcspn(p, "$%")) != 0) { buf_append(buf, p, pos); p += pos; } q = NULL; if (*p == '\0') break; if (*p++ == '$') { if (*p == '{') { pos = strcspn(++p, "}"); if (p[pos] == '\0') goto bad; } else { for (pos = 0; isalpha(p[pos]); pos++) ; if (pos == 0) { cvs_log(LP_ERR, "unrecognized variable syntax"); goto bad; } } q = xmalloc(pos + 1); memcpy(q, p, pos); q[pos] = '\0'; if (expand_var(buf, q)) goto bad; p += pos - (*(p - 1) == '{' ? 0 : 1); } else { switch (*p) { case '\0': goto bad; case '{': if (strchr(allowed_args, '{') == NULL) goto bad; pos = strcspn(++p, "}"); if (p[pos] == '\0') goto bad; q = xmalloc(pos + 1); memcpy(q, p, pos); q[pos] = '\0'; args = q; p += pos; break; default: argbuf[0] = *p; args = argbuf; break; } if (expand_args(buf, file_info, repo, allowed_args, args)) goto bad; expanded = 1; } free(q); } if (!expanded && default_args != NULL) { p = default_args; expanded = 1; goto again; } buf_putc(buf, '\0'); return (buf_release(buf)); bad: free(q); cvs_log(LP_NOTICE, "%s contains malformed command '%s'", file, cmd); buf_free(buf); return (NULL); }
void cvs_history_add(int type, struct cvs_file *cf, const char *argument) { BUF *buf; FILE *fp; RCSNUM *hrev; size_t len; int fd; char *cwd, *p, *rev; char revbuf[CVS_REV_BUFSZ], repo[MAXPATHLEN], fpath[MAXPATHLEN]; char timebuf[CVS_TIME_BUFSZ]; struct tm datetm; if (cvs_nolog == 1) return; if (cvs_cmdop == CVS_OP_CHECKOUT || cvs_cmdop == CVS_OP_EXPORT) { if (type != CVS_HISTORY_CHECKOUT && type != CVS_HISTORY_EXPORT) return; } cvs_log(LP_TRACE, "cvs_history_add(`%c', `%s', `%s')", historytab[type], (cf != NULL) ? cf->file_name : "", argument); /* construct repository field */ if (cvs_cmdop != CVS_OP_CHECKOUT && cvs_cmdop != CVS_OP_EXPORT) { cvs_get_repository_name((cf != NULL) ? cf->file_wd : ".", repo, sizeof(repo)); } else { cvs_get_repository_name(argument, repo, sizeof(repo)); } if (cvs_server_active == 1) { cwd = "<remote>"; } else { if (getcwd(fpath, sizeof(fpath)) == NULL) fatal("cvs_history_add: getcwd: %s", strerror(errno)); p = fpath; if (cvs_cmdop == CVS_OP_CHECKOUT || cvs_cmdop == CVS_OP_EXPORT) { if (strlcat(fpath, "/", sizeof(fpath)) >= sizeof(fpath) || strlcat(fpath, argument, sizeof(fpath)) >= sizeof(fpath)) fatal("cvs_history_add: string truncation"); } if (cvs_homedir != NULL && cvs_homedir[0] != '\0') { len = strlen(cvs_homedir); if (strncmp(cvs_homedir, fpath, len) == 0 && fpath[len] == '/') { p += len - 1; *p = '~'; } } history_compress(p, repo); cwd = xstrdup(p); } /* construct revision field */ revbuf[0] = '\0'; rev = revbuf; switch (type) { case CVS_HISTORY_TAG: strlcpy(revbuf, argument, sizeof(revbuf)); break; case CVS_HISTORY_CHECKOUT: case CVS_HISTORY_EXPORT: /* * cvs_buf_alloc uses xcalloc(), so we are safe even * if neither cvs_specified_tag nor cvs_specified_date * have been supplied. */ buf = cvs_buf_alloc(128); if (cvs_specified_tag != NULL) { cvs_buf_puts(buf, cvs_specified_tag); if (cvs_specified_date != -1) cvs_buf_putc(buf, ':'); } if (cvs_specified_date != -1) { gmtime_r(&cvs_specified_date, &datetm); strftime(timebuf, sizeof(timebuf), "%Y.%m.%d.%H.%M.%S", &datetm); cvs_buf_puts(buf, timebuf); } rev = cvs_buf_release(buf); break; case CVS_HISTORY_UPDATE_MERGED: case CVS_HISTORY_UPDATE_MERGED_ERR: case CVS_HISTORY_COMMIT_MODIFIED: case CVS_HISTORY_COMMIT_ADDED: case CVS_HISTORY_COMMIT_REMOVED: case CVS_HISTORY_UPDATE_CO: if ((hrev = rcs_head_get(cf->file_rcs)) == NULL) fatal("cvs_history_add: rcs_head_get failed"); rcsnum_tostr(hrev, revbuf, sizeof(revbuf)); rcsnum_free(hrev); break; } (void)xsnprintf(fpath, sizeof(fpath), "%s/%s", current_cvsroot->cr_dir, CVS_PATH_HISTORY); if ((fd = open(fpath, O_WRONLY|O_APPEND)) == -1) { if (errno != ENOENT) cvs_log(LP_ERR, "failed to open history file"); } else { if ((fp = fdopen(fd, "a")) != NULL) { fprintf(fp, "%c%x|%s|%s|%s|%s|%s\n", historytab[type], time(NULL), getlogin(), cwd, repo, rev, (cf != NULL) ? cf->file_name : argument); (void)fclose(fp); } else { cvs_log(LP_ERR, "failed to add entry to history file"); (void)close(fd); } } if (rev != revbuf) xfree(rev); if (cvs_server_active != 1) xfree(cwd); }
void cvs_parse_configfile(void) { cvs_log(LP_TRACE, "cvs_parse_configfile()"); cvs_read_config(CVS_PATH_CONFIG, config_parse_line); }
void cvs_add_tobranch(struct cvs_file *cf, char *tag) { BUF *bp; char attic[MAXPATHLEN], repo[MAXPATHLEN]; char *msg; struct stat st; RCSNUM *branch; cvs_log(LP_TRACE, "cvs_add_tobranch(%s)", cf->file_name); if (cvs_noexec == 1) return; if (fstat(cf->fd, &st) == -1) fatal("cvs_add_tobranch: %s", strerror(errno)); cvs_get_repository_path(cf->file_wd, repo, MAXPATHLEN); (void)xsnprintf(attic, MAXPATHLEN, "%s/%s", repo, CVS_PATH_ATTIC); if (mkdir(attic, 0755) == -1 && errno != EEXIST) fatal("cvs_add_tobranch: failed to create Attic"); (void)xsnprintf(attic, MAXPATHLEN, "%s/%s/%s%s", repo, CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT); xfree(cf->file_rpath); cf->file_rpath = xstrdup(attic); cf->repo_fd = open(cf->file_rpath, O_CREAT|O_RDONLY); if (cf->repo_fd < 0) fatal("cvs_add_tobranch: %s: %s", cf->file_rpath, strerror(errno)); cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, RCS_CREATE|RCS_WRITE, 0444); if (cf->file_rcs == NULL) fatal("cvs_add_tobranch: failed to create RCS file for %s", cf->file_path); if ((branch = rcsnum_parse("1.1.2")) == NULL) fatal("cvs_add_tobranch: failed to parse branch"); if (rcs_sym_add(cf->file_rcs, tag, branch) == -1) fatal("cvs_add_tobranch: failed to add vendor tag"); (void)xasprintf(&msg, "file %s was initially added on branch %s.", cf->file_name, tag); if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, msg, -1, NULL) == -1) fatal("cvs_add_tobranch: failed to create first branch " "revision"); xfree(msg); if (rcs_findrev(cf->file_rcs, cf->file_rcs->rf_head) == NULL) fatal("cvs_add_tobranch: cannot find newly added revision"); bp = buf_alloc(1); if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, bp) == -1) fatal("cvs_add_tobranch: failed to set deltatext"); rcs_comment_set(cf->file_rcs, " * "); if (rcs_state_set(cf->file_rcs, cf->file_rcs->rf_head, RCS_STATE_DEAD) == -1) fatal("cvs_add_tobranch: failed to set state"); }
static void add_directory(struct cvs_file *cf) { int added, nb; struct stat st; CVSENTRIES *entlist; char *date, entry[MAXPATHLEN], msg[1024], repo[MAXPATHLEN], *tag, *p; struct file_info_list files_info; struct file_info *fi; struct trigger_list *line_list; cvs_log(LP_TRACE, "add_directory(%s)", cf->file_path); (void)xsnprintf(entry, MAXPATHLEN, "%s%s", cf->file_rpath, RCS_FILE_EXT); added = 1; if (stat(entry, &st) != -1) { cvs_log(LP_NOTICE, "cannot add directory %s: " "a file with that name already exists", cf->file_path); added = 0; } else { /* Let's see if we have any per-directory tags first. */ cvs_parse_tagfile(cf->file_wd, &tag, &date, &nb); (void)xsnprintf(entry, MAXPATHLEN, "%s/%s", cf->file_path, CVS_PATH_CVSDIR); if (cvs_server_active) { if (mkdir(cf->file_rpath, 0755) == -1 && errno != EEXIST) fatal("add_directory: %s: %s", cf->file_rpath, strerror(errno)); } else if (stat(entry, &st) != -1) { if (!S_ISDIR(st.st_mode)) { cvs_log(LP_ERR, "%s exists but is not " "directory", entry); } else { cvs_log(LP_NOTICE, "%s already exists", entry); } added = 0; } else if (cvs_noexec != 1) { if (mkdir(cf->file_rpath, 0755) == -1 && errno != EEXIST) fatal("add_directory: %s: %s", cf->file_rpath, strerror(errno)); cvs_get_repository_name(cf->file_wd, repo, MAXPATHLEN); (void)xsnprintf(entry, MAXPATHLEN, "%s/%s", repo, cf->file_name); cvs_mkadmin(cf->file_path, current_cvsroot->cr_dir, entry, tag, date); p = xmalloc(CVS_ENT_MAXLINELEN); cvs_ent_line_str(cf->file_name, NULL, NULL, NULL, NULL, 1, 0, p, CVS_ENT_MAXLINELEN); entlist = cvs_ent_open(cf->file_wd); cvs_ent_add(entlist, p); xfree(p); } } if (added == 1 && current_cvsroot->cr_method == CVS_METHOD_LOCAL) { (void)xsnprintf(msg, sizeof(msg), "Directory %s added to the repository", cf->file_rpath); if (tag != NULL) { (void)strlcat(msg, "\n--> Using per-directory sticky tag ", sizeof(msg)); (void)strlcat(msg, tag, sizeof(msg)); } if (date != NULL) { (void)strlcat(msg, "\n--> Using per-directory sticky date ", sizeof(msg)); (void)strlcat(msg, date, sizeof(msg)); } cvs_printf("%s\n", msg); if (tag != NULL) xfree(tag); if (date != NULL) xfree(date); cvs_get_repository_name(cf->file_path, repo, MAXPATHLEN); line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO, repo); if (line_list != NULL) { TAILQ_INIT(&files_info); fi = xcalloc(1, sizeof(*fi)); fi->file_path = xstrdup(cf->file_path); TAILQ_INSERT_TAIL(&files_info, fi, flist); cvs_add_loginfo(repo); cvs_trigger_handle(CVS_TRIGGER_LOGINFO, repo, loginfo, line_list, &files_info); cvs_trigger_freeinfo(&files_info); cvs_trigger_freelist(line_list); if (loginfo != NULL) xfree(loginfo); } } cf->file_status = FILE_SKIP; }
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; }
void cvs_annotate_local(struct cvs_file *cf) { int i; char date[10], rnum[13], *p; RCSNUM *bnum, *rev; struct rcs_line *line; struct rcs_line **alines; cvs_log(LP_TRACE, "cvs_annotate_local(%s)", cf->file_path); cvs_file_classify(cf, cvs_directory_tag); if (cf->file_rcs == NULL || cf->file_rcs->rf_head == NULL) return; if (cvs_specified_tag != NULL) { if ((rev = rcs_translate_tag(cvs_specified_tag, cf->file_rcs)) == NULL) { if (!force_head) /* Stick at weird GNU cvs, ignore error. */ return; /* -f is not allowed for unknown symbols */ rev = rcsnum_parse(cvs_specified_tag); if (rev == NULL) fatal("no such tag %s", cvs_specified_tag); rcsnum_free(rev); rev = rcsnum_alloc(); rcsnum_cpy(cf->file_rcs->rf_head, rev, 0); } /* * If this is a revision in a branch, we have to go first * from HEAD to branch, then down to 1.1. After that, take * annotated branch and go up to branch revision. This must * be done this way due to different handling of "a" and * "d" in rcs file for annotation. */ if (!RCSNUM_ISBRANCHREV(rev)) { bnum = rev; } else { bnum = rcsnum_alloc(); rcsnum_cpy(rev, bnum, 2); } rcs_rev_getlines(cf->file_rcs, bnum, &alines); /* * Go into branch and receive annotations for branch revision, * with inverted "a" and "d" meaning. */ if (bnum != rev) { rcs_annotate_getlines(cf->file_rcs, rev, &alines); rcsnum_free(bnum); } rcsnum_free(rev); } else { rcs_rev_getlines(cf->file_rcs, (cvs_specified_date != -1 || cvs_directory_date != -1) ? cf->file_rcsrev : cf->file_rcs->rf_head, &alines); } /* Stick at weird GNU cvs, ignore error. */ if (alines == NULL) return; cvs_log(LP_RCS, "Annotations for %s", cf->file_path); cvs_log(LP_RCS, "***************"); for (i = 0; alines[i] != NULL; i++) { line = alines[i]; rcsnum_tostr(line->l_delta->rd_num, rnum, sizeof(rnum)); strftime(date, sizeof(date), "%d-%b-%y", &(line->l_delta->rd_date)); if (line->l_len && line->l_line[line->l_len - 1] == '\n') line->l_line[line->l_len - 1] = '\0'; else { p = xmalloc(line->l_len + 1); memcpy(p, line->l_line, line->l_len); p[line->l_len] = '\0'; if (line->l_needsfree) xfree(line->l_line); line->l_line = p; line->l_len++; line->l_needsfree = 1; } cvs_printf("%-12.12s (%-8.8s %s): %s\n", rnum, line->l_delta->rd_author, date, line->l_line); if (line->l_needsfree) xfree(line->l_line); xfree(line); } xfree(alines); }
struct trigger_list * cvs_trigger_getlines(char * file, char * repo) { FILE *fp; int allow_all, lineno, match = 0; size_t len; regex_t preg; struct trigger_list *list; struct trigger_line *tline; char fpath[PATH_MAX]; char *currentline, *defaultline = NULL, *nline, *p, *q, *regex; if (strcmp(file, CVS_PATH_EDITINFO) == 0 || strcmp(file, CVS_PATH_VERIFYMSG) == 0) allow_all = 0; else allow_all = 1; (void)xsnprintf(fpath, PATH_MAX, "%s/%s", current_cvsroot->cr_dir, file); if ((fp = fopen(fpath, "r")) == NULL) { if (errno != ENOENT) cvs_log(LP_ERRNO, "cvs_trigger_getlines: %s", file); return (NULL); } list = xmalloc(sizeof(*list)); TAILQ_INIT(list); lineno = 0; nline = NULL; while ((currentline = fgetln(fp, &len)) != NULL) { if (currentline[len - 1] == '\n') { currentline[len - 1] = '\0'; } else { nline = xmalloc(len + 1); memcpy(nline, currentline, len); nline[len] = '\0'; currentline = nline; } lineno++; for (p = currentline; isspace((unsigned char)*p); p++) ; if (*p == '\0' || *p == '#') continue; for (q = p; !isspace((unsigned char)*q) && *q != '\0'; q++) ; if (*q == '\0') goto bad; *q++ = '\0'; regex = p; for (; isspace((unsigned char)*q); q++) ; if (*q == '\0') goto bad; if (strcmp(regex, "ALL") == 0 && allow_all) { tline = xmalloc(sizeof(*tline)); tline->line = xstrdup(q); TAILQ_INSERT_TAIL(list, tline, flist); } else if (defaultline == NULL && !match && strcmp(regex, "DEFAULT") == 0) { defaultline = xstrdup(q); } else if (!match) { if (regcomp(&preg, regex, REG_NOSUB|REG_EXTENDED)) goto bad; if (regexec(&preg, repo, 0, NULL, 0) != REG_NOMATCH) { match = 1; tline = xmalloc(sizeof(*tline)); tline->line = xstrdup(q); TAILQ_INSERT_HEAD(list, tline, flist); } regfree(&preg); } } free(nline); if (defaultline != NULL) { if (!match) { tline = xmalloc(sizeof(*tline)); tline->line = defaultline; TAILQ_INSERT_HEAD(list, tline, flist); } else free(defaultline); } (void)fclose(fp); if (TAILQ_EMPTY(list)) { free(list); list = NULL; } return (list); bad: cvs_log(LP_NOTICE, "%s: malformed line %d", file, lineno); free(defaultline); cvs_trigger_freelist(list); (void)fclose(fp); return (NULL); }
int cvs_diff(int argc, char **argv) { int ch, flags; char *arg = "."; const char *errstr; struct cvs_recursion cr; flags = CR_RECURSE_DIRS; strlcpy(diffargs, cvs_cmdop == CVS_OP_DIFF ? "diff" : "rdiff", sizeof(diffargs)); while ((ch = getopt(argc, argv, cvs_cmdop == CVS_OP_DIFF ? cvs_cmd_diff.cmd_opts : cvs_cmd_rdiff.cmd_opts)) != -1) { switch (ch) { case 'a': strlcat(diffargs, " -a", sizeof(diffargs)); dflags |= D_FORCEASCII; break; case 'b': strlcat(diffargs, " -b", sizeof(diffargs)); dflags |= D_FOLDBLANKS; break; case 'c': strlcat(diffargs, " -c", sizeof(diffargs)); diff_format = D_CONTEXT; break; case 'C': diff_context = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) fatal("context lines %s: %s", errstr, optarg); strlcat(diffargs, " -C ", sizeof(diffargs)); strlcat(diffargs, optarg, sizeof(diffargs)); diff_format = D_CONTEXT; break; case 'd': strlcat(diffargs, " -d", sizeof(diffargs)); dflags |= D_MINIMAL; break; case 'D': if (date1 == -1 && rev1 == NULL) { if ((date1 = date_parse(optarg)) == -1) fatal("invalid date: %s", optarg); dateflag1 = optarg; } else if (date2 == -1 && rev2 == NULL) { if ((date2 = date_parse(optarg)) == -1) fatal("invalid date: %s", optarg); dateflag2 = optarg; } else { fatal("no more than 2 revisions/dates can" " be specified"); } break; case 'f': force_head = 1; break; case 'i': strlcat(diffargs, " -i", sizeof(diffargs)); dflags |= D_IGNORECASE; break; case 'k': koptstr = optarg; kflag = rcs_kflag_get(koptstr); if (RCS_KWEXP_INVAL(kflag)) { cvs_log(LP_ERR, "invalid RCS keyword expansion mode"); fatal("%s", cvs_cmdop == CVS_OP_DIFF ? cvs_cmd_diff.cmd_synopsis : cvs_cmd_rdiff.cmd_synopsis); } break; case 'l': flags &= ~CR_RECURSE_DIRS; break; case 'n': strlcat(diffargs, " -n", sizeof(diffargs)); diff_format = D_RCSDIFF; break; case 'N': strlcat(diffargs, " -N", sizeof(diffargs)); Nflag = 1; break; case 'p': strlcat(diffargs, " -p", sizeof(diffargs)); dflags |= D_PROTOTYPE; break; case 'R': flags |= CR_RECURSE_DIRS; break; case 'r': if (date1 == -1 && rev1 == NULL) { rev1 = optarg; } else if (date2 == -1 && rev2 == NULL) { rev2 = optarg; } else { fatal("no more than 2 revisions/dates can" " be specified"); } break; case 't': strlcat(diffargs, " -t", sizeof(diffargs)); dflags |= D_EXPANDTABS; break; case 'u': strlcat(diffargs, " -u", sizeof(diffargs)); diff_format = D_UNIFIED; break; case 'U': diff_context = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) fatal("context lines %s: %s", errstr, optarg); strlcat(diffargs, " -U ", sizeof(diffargs)); strlcat(diffargs, optarg, sizeof(diffargs)); diff_format = D_UNIFIED; break; case 'V': fatal("the -V option is obsolete " "and should not be used"); case 'w': strlcat(diffargs, " -w", sizeof(diffargs)); dflags |= D_IGNOREBLANKS; break; default: fatal("%s", cvs_cmdop == CVS_OP_DIFF ? cvs_cmd_diff.cmd_synopsis : cvs_cmd_rdiff.cmd_synopsis); } } argc -= optind; argv += optind; cr.enterdir = NULL; cr.leavedir = NULL; if (cvs_cmdop == CVS_OP_RDIFF) { if (rev1 == NULL && rev2 == NULL && dateflag1 == NULL && dateflag2 == NULL) fatal("must specify at least one revision/date!"); if (!argc) fatal("%s", cvs_cmd_rdiff.cmd_synopsis); if (!diff_format) { strlcat(diffargs, " -c", sizeof(diffargs)); diff_format = D_CONTEXT; } flags |= CR_REPO; } if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_connect_to_server(); cr.fileproc = cvs_client_sendfile; if (!(flags & CR_RECURSE_DIRS)) cvs_client_send_request("Argument -l"); if (kflag) cvs_client_send_request("Argument -k%s", koptstr); switch (diff_format) { case D_CONTEXT: if (cvs_cmdop == CVS_OP_RDIFF) cvs_client_send_request("Argument -c"); else { cvs_client_send_request("Argument -C %d", diff_context); } break; case D_RCSDIFF: cvs_client_send_request("Argument -n"); break; case D_UNIFIED: if (cvs_cmdop == CVS_OP_RDIFF || diff_context == 3) cvs_client_send_request("Argument -u"); else { cvs_client_send_request("Argument -U %d", diff_context); } break; default: break; } if (Nflag == 1) cvs_client_send_request("Argument -N"); if (dflags & D_PROTOTYPE) cvs_client_send_request("Argument -p"); if (rev1 != NULL) cvs_client_send_request("Argument -r%s", rev1); if (rev2 != NULL) cvs_client_send_request("Argument -r%s", rev2); if (dateflag1 != NULL) cvs_client_send_request("Argument -D%s", dateflag1); if (dateflag2 != NULL) cvs_client_send_request("Argument -D%s", dateflag2); } else { if (cvs_cmdop == CVS_OP_RDIFF && chdir(current_cvsroot->cr_dir) == -1) fatal("cvs_diff: %s", strerror(errno)); cr.fileproc = cvs_diff_local; } cr.flags = flags; diff_rev1 = diff_rev2 = NULL; if (cvs_cmdop == CVS_OP_DIFF || current_cvsroot->cr_method == CVS_METHOD_LOCAL) { if (argc > 0) cvs_file_run(argc, argv, &cr); else cvs_file_run(1, &arg, &cr); } if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_send_files(argv, argc); cvs_client_senddir("."); cvs_client_send_request((cvs_cmdop == CVS_OP_RDIFF) ? "rdiff" : "diff"); cvs_client_get_responses(); } return (0); }
int cvs_admin(int argc, char **argv) { int ch; int flags; char *statestr; struct cvs_recursion cr; flags = CR_RECURSE_DIRS; alist = comment = elist = logmsg = logstr = NULL; oldfilename = orange = state = statestr = NULL; while ((ch = getopt(argc, argv, cvs_cmd_admin.cmd_opts)) != -1) { switch (ch) { case 'A': oldfilename = optarg; break; case 'a': alist = optarg; break; case 'b': break; case 'c': comment = optarg; break; case 'e': elist = optarg; runflags |= ADM_EFLAG; break; case 'I': break; case 'k': koptstr = optarg; kflag = rcs_kflag_get(koptstr); if (RCS_KWEXP_INVAL(kflag)) { cvs_log(LP_ERR, "invalid RCS keyword expansion mode"); fatal("%s", cvs_cmd_admin.cmd_synopsis); } break; case 'L': if (lkmode == RCS_LOCK_LOOSE) { cvs_log(LP_ERR, "-L and -U are incompatible"); fatal("%s", cvs_cmd_admin.cmd_synopsis); } lkmode = RCS_LOCK_STRICT; break; case 'l': break; case 'm': logstr = optarg; break; case 'N': break; case 'n': break; case 'o': orange = optarg; break; case 'q': verbosity = 0; break; case 's': statestr = optarg; break; case 't': break; case 'U': if (lkmode == RCS_LOCK_STRICT) { cvs_log(LP_ERR, "-U and -L are incompatible"); fatal("%s", cvs_cmd_admin.cmd_synopsis); } lkmode = RCS_LOCK_LOOSE; break; case 'u': break; default: fatal("%s", cvs_cmd_admin.cmd_synopsis); } } argc -= optind; argv += optind; if (argc == 0) fatal("%s", cvs_cmd_admin.cmd_synopsis); cr.enterdir = NULL; cr.leavedir = NULL; if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_connect_to_server(); cr.fileproc = cvs_client_sendfile; if (oldfilename != NULL) cvs_client_send_request("Argument -A%s", oldfilename); if (alist != NULL) cvs_client_send_request("Argument -a%s", alist); if (comment != NULL) cvs_client_send_request("Argument -c%s", comment); if (runflags & ADM_EFLAG) cvs_client_send_request("Argument -e%s", (elist != NULL) ? elist : ""); if (koptstr != NULL) cvs_client_send_request("Argument -k%s", koptstr); if (lkmode == RCS_LOCK_STRICT) cvs_client_send_request("Argument -L"); else if (lkmode == RCS_LOCK_LOOSE) cvs_client_send_request("Argument -U"); if (logstr != NULL) cvs_client_send_logmsg(logstr); if (orange != NULL) cvs_client_send_request("Argument -o%s", orange); if (statestr != NULL) cvs_client_send_request("Argument -s%s", statestr); if (verbosity == 0) cvs_client_send_request("Argument -q"); } else { if (statestr != NULL) { if ((staterevstr = strchr(statestr, ':')) != NULL) *staterevstr++ = '\0'; state = statestr; if (rcs_state_check(state) < 0) { cvs_log(LP_ERR, "invalid state `%s'", state); state = NULL; } } flags |= CR_REPO; cr.fileproc = cvs_admin_local; } cr.flags = flags; cvs_file_run(argc, argv, &cr); if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { cvs_client_send_files(argv, argc); cvs_client_senddir("."); cvs_client_send_request("admin"); cvs_client_get_responses(); } return (0); }
static void add_file(struct cvs_file *cf) { int nb, stop; char revbuf[CVS_REV_BUFSZ]; RCSNUM *head = NULL; char *tag; cvs_parse_tagfile(cf->file_wd, &tag, NULL, &nb); if (nb) { cvs_log(LP_ERR, "cannot add file on non-branch tag %s", tag); return; } if (cf->file_rcs != NULL) { head = rcs_head_get(cf->file_rcs); if (head == NULL) { cvs_log(LP_NOTICE, "no head revision in RCS file for " "%s", cf->file_path); } rcsnum_tostr(head, revbuf, sizeof(revbuf)); } stop = 0; switch (cf->file_status) { case FILE_ADDED: case FILE_CHECKOUT: if (verbosity > 1) cvs_log(LP_NOTICE, "%s has already been entered", cf->file_path); stop = 1; break; case FILE_REMOVED: if (cf->file_rcs == NULL) { cvs_log(LP_NOTICE, "cannot resurrect %s; " "RCS file removed by second party", cf->file_name); } else if (!(cf->file_flags & FILE_ON_DISK)) { add_entry(cf); /* Restore the file. */ cvs_checkout_file(cf, head, NULL, 0); cvs_printf("U %s\n", cf->file_path); cvs_log(LP_NOTICE, "%s, version %s, resurrected", cf->file_name, revbuf); cf->file_status = FILE_UPTODATE; } stop = 1; break; case FILE_CONFLICT: case FILE_LOST: case FILE_MODIFIED: case FILE_UPTODATE: if (cf->file_rcs != NULL && cf->file_rcs->rf_dead == 0) { cvs_log(LP_NOTICE, "%s already exists, with version " "number %s", cf->file_path, revbuf); stop = 1; } break; case FILE_UNKNOWN: if (cf->file_rcs != NULL && cf->file_rcs->rf_dead == 1) { cvs_log(LP_NOTICE, "re-adding file %s " "(instead of dead revision %s)", cf->file_path, revbuf); added_files++; } else if (cf->file_flags & FILE_ON_DISK) { cvs_log(LP_NOTICE, "scheduling file '%s' for addition", cf->file_path); added_files++; } else { stop = 1; } break; default: break; } if (head != NULL) rcsnum_free(head); if (stop == 1) return; add_entry(cf); }