📄 co.c
字号:
/* Copyright (C) 1982, 1988, 1989 Walter Tichy Copyright 1990, 1991 by Paul Eggert Distributed under license by the Free Software Foundation, Inc.This file is part of RCS.RCS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.RCS is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with RCS; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.Report problems and direct all questions to: rcs-bugs@cs.purdue.edu*//* * RCS checkout operation *//***************************************************************************** * check out revisions from RCS files ***************************************************************************** *//* $Log: co.c,v $ * Revision 5.9 1991/10/07 17:32:46 eggert * ci -u src/RCS/co.c,v src/co.c <<\. * -k affects just working file, not RCS file. * * Revision 5.8 1991/08/19 03:13:55 eggert * Warn before removing somebody else's file. * Add -M. Fix co -j bugs. Tune. * * Revision 5.7 1991/04/21 11:58:15 eggert * Ensure that working file is newer than RCS file after co -[lu]. * Add -x, RCSINIT, MS-DOS support. * * Revision 5.6 1990/12/04 05:18:38 eggert * Don't checkaccesslist() unless necessary. * Use -I for prompts and -q for diagnostics. * * Revision 5.5 1990/11/01 05:03:26 eggert * Fix -j. Add -I. * * Revision 5.4 1990/10/04 06:30:11 eggert * Accumulate exit status across files. * * Revision 5.3 1990/09/11 02:41:09 eggert * co -kv yields a readonly working file. * * Revision 5.2 1990/09/04 08:02:13 eggert * Standardize yes-or-no procedure. * * Revision 5.0 1990/08/22 08:10:02 eggert * Permit multiple locks by same user. Add setuid support. * Remove compile-time limits; use malloc instead. * Permit dates past 1999/12/31. Switch to GMT. * Make lock and temp files faster and safer. * Ansify and Posixate. Add -k, -V. Remove snooping. Tune. * * Revision 4.7 89/05/01 15:11:41 narten * changed copyright header to reflect current distribution rules * * Revision 4.6 88/08/09 19:12:15 eggert * Fix "co -d" core dump; rawdate wasn't always initialized. * Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint * * Revision 4.5 87/12/18 11:35:40 narten * lint cleanups (from Guy Harris) * * Revision 4.4 87/10/18 10:20:53 narten * Updating version numbers changes relative to 1.1, are actually * relative to 4.2 * * Revision 1.3 87/09/24 13:58:30 narten * Sources now pass through lint (if you ignore printf/sprintf/fprintf * warnings) * * Revision 1.2 87/03/27 14:21:38 jenkins * Port to suns * * Revision 4.2 83/12/05 13:39:48 wft * made rewriteflag external. * * Revision 4.1 83/05/10 16:52:55 wft * Added option -u and -f. * Added handling of default branch. * Replaced getpwuid() with getcaller(). * Removed calls to stat(); now done by pairfilenames(). * Changed and renamed rmoldfile() to rmworkfile(). * Replaced catchints() calls with restoreints(), unlink()--link() with rename(); * * Revision 3.7 83/02/15 15:27:07 wft * Added call to fastcopy() to copy remainder of RCS file. * * Revision 3.6 83/01/15 14:37:50 wft * Added ignoring of interrupts while RCS file is renamed; this avoids * deletion of RCS files during the unlink/link window. * * Revision 3.5 82/12/08 21:40:11 wft * changed processing of -d to use DATEFORM; removed actual from * call to preparejoin; re-fixed printing of done at the end. * * Revision 3.4 82/12/04 18:40:00 wft * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. * Fixed printing of "done". * * Revision 3.3 82/11/28 22:23:11 wft * Replaced getlogin() with getpwuid(), flcose() with ffclose(), * %02d with %.2d, mode generation for working file with WORKMODE. * Fixed nil printing. Fixed -j combined with -l and -p, and exit * for non-existing revisions in preparejoin(). * * Revision 3.2 82/10/18 20:47:21 wft * Mode of working file is now maintained even for co -l, but write permission * is removed. * The working file inherits its mode from the RCS file, plus write permission * for the owner. The write permission is not given if locking is strict and * co does not lock. * An existing working file without write permission is deleted automatically. * Otherwise, co asks (empty answer: abort co). * Call to getfullRCSname() added, check for write error added, call * for getlogin() fixed. * * Revision 3.1 82/10/13 16:01:30 wft * fixed type of variables receiving from getc() (char -> int). * removed unused variables. */#include "rcsbase.h"static char const *getancestor P((char const*,char const*));static int buildjoin P((char const*));static int preparejoin P((void));static int rmlock P((struct hshentry const*));static int rmworkfile P((void));static void cleanup P((void));static char const quietarg[] = "-q";static char const *expandarg, *join, *suffixarg, *versionarg;static char const *joinlist[joinlength]; /* revisions to be joined */static FILE *neworkptr;static int exitstatus;static int forceflag;static int lastjoin; /* index of last element in joinlist */static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */static int mtimeflag;static struct hshentries *gendeltas; /* deltas to be generated */static struct hshentry *targetdelta; /* final delta to be generated */static struct stat workstat;mainProg(coId, "co", "$Id: co.c,v 5.9 1991/10/07 17:32:46 eggert Exp $"){ static char const cmdusage[] = "\nco usage: co -{flpqru}[rev] -ddate -jjoinlist -sstate -w[login] -Vn file ..."; char *a, **newargv; char const *author, *date, *rev, *state; char const *joinfilename, *newdate, *neworkfilename; int changelock; /* 1 if a lock has been changed, -1 if error */ int expmode, r, tostdout, workstatstat; struct buf numericrev; /* expanded revision number */ char finaldate[datesize]; setrid(); author = date = rev = state = nil; bufautobegin(&numericrev); expmode = -1; suffixes = X_DEFAULT; tostdout = false; argc = getRCSINIT(argc, argv, &newargv); argv = newargv; while (a = *++argv, 0<--argc && *a++=='-') { switch (*a++) { case 'r': revno: if (*a) { if (rev) warn("redefinition of revision number"); rev = a; } break; case 'f': forceflag=true; goto revno; case 'l': if (lockflag < 0) { warn("-l overrides -u."); } lockflag = 1; goto revno; case 'u': if (0 < lockflag) { warn("-l overrides -u."); } lockflag = -1; goto revno; case 'p': tostdout = true; goto revno; case 'I': interactiveflag = true; goto revno; case 'q': quietflag=true; goto revno; case 'd': if (date) redefined('d'); str2date(a, finaldate); date=finaldate; break; case 'j': if (*a) { if (join) redefined('j'); join = a; } break; case 'M': mtimeflag = true; goto revno; case 's': if (*a) { if (state) redefined('s'); state = a; } break; case 'w': if (author) redefined('w'); if (*a) author = a; else author = getcaller(); break; case 'x': suffixarg = *argv; suffixes = a; break; case 'V': versionarg = *argv; setRCSversion(versionarg); break; case 'k': /* set keyword expand mode */ expandarg = *argv; if (0 <= expmode) redefined('k'); if (0 <= (expmode = str2expmode(a))) break; /* fall into */ default: faterror("unknown option: %s%s", *argv, cmdusage); }; } /* end of option processing */ if (argc<1) faterror("no input file%s", cmdusage); if (tostdout)# if text_equals_binary_stdio || text_work_stdio workstdout = stdout;# else if (!(workstdout = fdopen(STDOUT_FILENO, FOPEN_W_WORK))) efaterror("stdout");# endif /* now handle all filenames */ do { ffree(); if (pairfilenames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0) continue; /* now RCSfilename contains the name of the RCS file, and finptr * points at it. workfilename contains the name of the working file. * Also, RCSstat has been set. */ diagnose("%s --> %s\n", RCSfilename,tostdout?"stdout":workfilename); workstatstat = -1; if (tostdout) { neworkfilename = 0; neworkptr = workstdout; } else { workstatstat = stat(workfilename, &workstat); neworkfilename = makedirtemp(workfilename, 1); if (!(neworkptr = fopen(neworkfilename, FOPEN_W_WORK))) { if (errno == EACCES) error("%s: parent directory isn't writable", workfilename ); else eerror(neworkfilename); continue; } } gettree(); /* reads in the delta tree */ if (Head==nil) { /* no revisions; create empty file */ diagnose("no revisions present; generating empty revision 0.0\n"); Ozclose(&fcopy); if (workstatstat == 0) if (!rmworkfile()) continue; changelock = 0; newdate = 0; /* Can't reserve a delta, so don't call addlock */ } else { if (rev!=nil) { /* expand symbolic revision number */ if (!expandsym(rev, &numericrev)) continue; } else switch (lockflag<0 ? findlock(false,&targetdelta) : 0) { default: continue; case 0: bufscpy(&numericrev, Dbranch?Dbranch:""); break; case 1: bufscpy(&numericrev, targetdelta->num); break; } /* get numbers of deltas to be generated */ if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas))) continue; /* check reservations */ changelock = lockflag < 0 ? rmlock(targetdelta) : lockflag == 0 ? 0 : addlock(targetdelta); if ( changelock < 0 || changelock && !checkaccesslist() || !dorewrite(lockflag, changelock) ) continue; if (0 <= expmode) Expand = expmode; if (0 < lockflag && Expand == VAL_EXPAND) { error("cannot combine -kv and -l"); continue; } if (join && !preparejoin()) continue; diagnose("revision %s%s\n",targetdelta->num, 0<lockflag ? " (locked)" : lockflag<0 ? " (unlocked)" : ""); /* Prepare to remove old working file if necessary. */ if (workstatstat == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -