/* * free up a Vers_TS struct */ void freevers_ts (Vers_TS **versp) { if ((*versp)->srcfile) freercsnode (&((*versp)->srcfile)); if ((*versp)->vn_user) free ((*versp)->vn_user); if ((*versp)->vn_rcs) free ((*versp)->vn_rcs); if ((*versp)->vn_tag) free ((*versp)->vn_tag); if ((*versp)->ts_user) free ((*versp)->ts_user); if ((*versp)->ts_rcs) free ((*versp)->ts_rcs); if ((*versp)->options) free ((*versp)->options); if ((*versp)->tag) free ((*versp)->tag); if ((*versp)->date) free ((*versp)->date); if ((*versp)->ts_conflict) free ((*versp)->ts_conflict); free ((char *) *versp); *versp = NULL; }
static int checkout_file (const char *file, const char *directory, const char *temp, mode_t *mode) { char *rcs; RCSNode *rcsnode; int retcode = 0; if (noexec) return 0; rcs = (char*)xmalloc (strlen (file) + strlen(directory) + 5); sprintf(rcs,"%s/%s%s",directory,file,RCSEXT); if (!isfile (rcs)) { xfree (rcs); return (1); } rcsnode = RCS_parsercsfile (rcs); if(rcsnode) retcode = RCS_checkout (rcsnode, NULL, NULL, NULL, "b", (char*)temp, (RCSCHECKOUTPROC) NULL, (void *) NULL, mode); if (rcsnode && retcode != 0) { /* Probably not necessary (?); RCS_checkout already printed a message. */ error (0, 0, "failed to check out %s file", file); } freercsnode (&rcsnode); xfree (rcs); return (retcode); }
int diff (int argc, char **argv) { char tmp[50]; int c, err = 0; int local = 0; int which; int option_index; is_rcs = (strcmp (command_name, "rcsfile") == 0); if (argc == -1) usage (diff_usage); have_rev1_label = have_rev2_label = 0; /* * Note that we catch all the valid arguments here, so that we can * intercept the -r arguments for doing revision diffs; and -l/-R for a * non-recursive/recursive diff. */ /* Clean out our global variables (multiroot can call us multiple times and the server can too, if the client sends several diff commands). */ if (opts == NULL) { opts_allocated = 1; opts = (char*)xmalloc (opts_allocated); } opts[0] = '\0'; diff_rev1 = NULL; diff_rev2 = NULL; diff_date1 = NULL; diff_date2 = NULL; optind = 0; while ((c = getopt_long (argc, argv, "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:", longopts, &option_index)) != -1) { switch (c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': case 'i': case 'n': case 'p': case 's': case 't': case 'u': case 'w': case 'y': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'B': case 'H': case 'T': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); break; case 'L': if (have_rev1_label++) if (have_rev2_label++) { error (0, 0, "extra -L arguments ignored"); break; } allocate_and_strcat (&opts, &opts_allocated, " -L"); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 'C': case 'F': case 'I': case 'U': case 'V': case 'W': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 131: /* --ifdef. */ allocate_and_strcat (&opts, &opts_allocated, " --ifdef="); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 129: case 130: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: allocate_and_strcat (&opts, &opts_allocated, " --"); allocate_and_strcat (&opts, &opts_allocated, longopts[option_index].name); if (longopts[option_index].has_arg == 1 || (longopts[option_index].has_arg == 2 && optarg != NULL)) { allocate_and_strcat (&opts, &opts_allocated, "="); allocate_and_strcat (&opts, &opts_allocated, optarg); } break; case 'R': local = 0; break; case 'l': local = 1; break; case 'k': if (options) xfree (options); options = RCS_check_kflag (optarg,true,true); break; case 'r': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_rev2 = optarg; else diff_rev1 = optarg; break; case 'D': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_date2 = Make_Date (optarg); else diff_date1 = Make_Date (optarg); break; case 'N': empty_files = 1; break; case '?': default: usage (diff_usage); break; } } argc -= optind; argv += optind; /* make sure options is non-null */ if (!options) options = xstrdup (""); if (!is_rcs && current_parsed_root->isremote) { if (local) send_arg("-l"); if (empty_files) send_arg("-N"); send_option_string (opts); if (options[0] != '\0') option_with_arg ("-k", options); if (diff_rev1) option_with_arg ("-r", diff_rev1); if (diff_date1) client_senddate (diff_date1); if (diff_rev2) option_with_arg ("-r", diff_rev2); if (diff_date2) client_senddate (diff_date2); send_arg("--"); /* Send the current files unless diffing two revs from the archive */ if (diff_rev2 == NULL && diff_date2 == NULL) send_files (argc, argv, local, 0, 0); else send_files (argc, argv, local, 0, SEND_NO_CONTENTS); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("diff\n", 0); err = get_responses_and_close (); xfree (options); options = NULL; return (err); } if(is_rcs) { int n; if(!argc) usage(diff_usage); for(n=0; n<argc; n++) { struct file_info finfo = {0}; const char *name; char *tmp = find_rcs_filename(argv[n]); if(!tmp) error(1,ENOENT,"%s",argv[n]); finfo.fullname=fullpathname(tmp, &name); finfo.file = xstrdup(name); char *ff = xstrdup(finfo.fullname); finfo.update_dir = ff; ff[(name-finfo.fullname)-1]='\0'; finfo.rcs = RCS_fopen(finfo.fullname); if(finfo.rcs) { ff = (char*)finfo.fullname; ff[strlen(finfo.fullname)-2]='\0'; ff = (char*)finfo.file; ff[strlen(finfo.file)-2]='\0'; err+=diff_fileproc(NULL,&finfo); freercsnode(&finfo.rcs); } else { error(1,ENOENT,"%s",tmp); err++; } xfree(finfo.fullname); xfree(finfo.file); xfree(finfo.update_dir); xfree(tmp); } } else { if (diff_rev1 != NULL) tag_check_valid (diff_rev1, argc, argv, local, 0, ""); if (diff_rev2 != NULL) tag_check_valid (diff_rev2, argc, argv, local, 0, ""); which = W_LOCAL; if (diff_rev1 != NULL || diff_date1 != NULL) which |= W_REPOS; /* start the recursion processor */ err = start_recursion (diff_fileproc, diff_filesdoneproc, (PREDIRENTPROC) NULL, diff_dirproc, diff_dirleaveproc, NULL, argc, argv, local, which, 0, 1, (char *) NULL, NULL, 1, verify_read, diff_rev1); } /* clean up */ xfree (options); options = NULL; if (diff_date1 != NULL) xfree (diff_date1); if (diff_date2 != NULL) xfree (diff_date2); return (err); }
/* * Process each of the files in the list with the callback proc */ static int do_file_proc (Node *p, void *closure) { struct frame_and_file *frfile = (struct frame_and_file *)closure; struct file_info *finfo = frfile->finfo; int ret; Entnode *e; const char *mapped_name; const char *mapped_file_repository = NULL; if(!current_parsed_root->isremote) mapped_name = map_filename(finfo->virtual_repository, p->key, &mapped_file_repository); else mapped_name = xstrdup(p->key); finfo->file = p->key; finfo->mapped_file = mapped_name; char *ff = (char*)xmalloc (strlen (finfo->file) + strlen (finfo->update_dir) + 2); finfo->fullname = ff; ff[0] = '\0'; if (finfo->update_dir[0] != '\0') { strcat (ff, finfo->update_dir); strcat (ff, "/"); } strcat (ff, finfo->file); if (frfile->frame->dosrcs && mapped_file_repository) { finfo->rcs = RCS_parse (finfo->mapped_file, mapped_file_repository); /* OK, without W_LOCAL the error handling becomes relatively simple. The file names came from readdir() on the repository and so we know any ENOENT is an error (e.g. symlink pointing to nothing). Now, the logic could be simpler - since we got the name from readdir, we could just be calling RCS_parsercsfile. */ if (finfo->rcs == NULL && !(frfile->frame->which & W_LOCAL)) { error (0, 0, "could not read RCS file for %s", fn_root(finfo->fullname)); xfree (finfo->fullname); cvs_flushout (); return 0; } } else finfo->rcs = (RCSNode *) NULL; p = findnode_fn(finfo->entries,finfo->file); if(p) { const char *message; const char *v_type; e = (Entnode *)p->data; if (! verify_access(frfile->frame->permproc, finfo->repository, finfo->file, finfo->update_dir, e->tag, &message, &v_type)) { if(e->tag && !quiet && !(frfile->frame->which&W_QUIET)) error (0, 0, "User %s is unable to %s %s/%s on branch/tag %s",CVS_Username,v_type,finfo->update_dir,finfo->file,e->tag); else if(!quiet && !(frfile->frame->which&W_QUIET)) error (0, 0, "User %s is unable to %s %s/%s",CVS_Username,v_type,finfo->update_dir,finfo->file); if(message && !quiet && !(frfile->frame->which&W_QUIET)) error (0, 0, "%s", message); ret = 1; } else ret = frfile->frame->fileproc (frfile->frame->callerdat, finfo); } else ret = frfile->frame->fileproc (frfile->frame->callerdat, finfo); freercsnode(&finfo->rcs); xfree (finfo->fullname); xfree (mapped_name); xfree (mapped_file_repository); /* Allow the user to monitor progress with tail -f. Doing this once per file should be no big deal, but we don't want the performance hit of flushing on every line like previous versions of CVS. */ cvs_flushout (); return (ret); }