1 /* Clean up working files. */
3 /* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
4 Distributed under license by the Free Software Foundation, Inc.
6 This file is part of RCS.
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Report problems and direct all questions to:
25 rcs-bugs@cs.purdue.edu
32 static int get_directory P((char const*,char***));
35 static int unlock P((struct hshentry *));
36 static void cleanup P((void));
39 static int exitstatus;
41 mainProg(rcscleanId, "rcsclean", "$FreeBSD$")
43 static char const usage[] =
44 "\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
46 static struct buf revision;
50 int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
52 struct hshentries *deltas;
53 struct hshentry *delta;
65 argc = getRCSINIT(argc, argv, &newargv);
70 argc = get_directory(".", &newargv);
74 faterror("no pathnames specified");
78 if (!*a || *a++ != '-')
84 if ((expmode = str2expmode(a)) < 0)
99 warn("redefinition of revision number");
112 goto handle_revision;
115 setRCSversion(*argv);
128 error("unknown option: %s%s", *argv, usage);
132 dounlock = perform & unlockflag;
137 for (; 0 < argc; cleanup(), ++argv, --argc) {
144 dounlock ? rcswriteopen : rcsreadopen,
147 (workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
151 if (same_file(RCSstat, workstat, 0)) {
152 rcserror("RCS file is the same as working file %s.",
162 if (!fexpandsym(rev, &revision, workptr))
166 switch (unlockflag ? findlock(false,&delta) : 0) {
170 p = Dbranch ? Dbranch : "";
177 deltas = 0; /* Keep lint happy. */
178 if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
181 waslocked = delta && delta->lockedby;
182 locker_expansion = unlock(delta);
183 unlocked = locker_expansion & unlockflag;
184 if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
187 if (unlocked && !checkaccesslist())
190 if (dorewrite(dounlock, unlocked) != 0)
197 Expand == KEYVAL_EXPAND &&
198 WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
200 Expand = KEYVALLOCK_EXPAND;
205 !delta ? workstat.st_size!=0 :
208 buildrevision(deltas, delta, (FILE*)0, false),
214 if (quietflag < unlocked)
215 aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
217 if (perform & unlocked) {
218 if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
219 if (donerewrite(true,
220 Ttimeflag ? RCSstat.st_mtime : (time_t)-1
226 aprintf(stdout, "rm -f %s\n", workname);
228 if (perform && un_link(workname) != 0)
236 exitmain(exitstatus);
242 if (nerror) exitstatus = EXIT_FAILURE;
251 # define exiterr rcscleanExit
264 struct hshentry *delta;
266 register struct rcslock **al, *l;
268 if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
269 for (al = &Locks; (l = *al); al = &l->nextlock)
270 if (l->delta == delta) {
280 get_directory(dirname, aargv)
284 * Put a vector of all DIRNAME's directory entries names into *AARGV.
285 * Ignore names of RCS files.
286 * Yield the number of entries found. Terminate the vector with 0.
287 * Allocate the storage for the vector and entry names.
288 * Do not sort the names. Do not include '.' and '..'.
291 int i, entries = 0, entries_max = 64;
292 size_t chars = 0, chars_max = 1024;
293 size_t *offset = tnalloc(size_t, entries_max);
294 char *a = tnalloc(char, chars_max), **p;
298 if (!(d = opendir(dirname)))
300 while ((errno = 0, e = readdir(d))) {
301 char const *en = e->d_name;
302 size_t s = strlen(en) + 1;
303 if (en[0]=='.' && (!en[1] || (en[1]=='.' && !en[2])))
307 while (chars_max < s + chars)
308 a = trealloc(char, a, chars_max<<=1);
309 if (entries == entries_max)
310 offset = trealloc(size_t, offset, entries_max<<=1);
311 offset[entries++] = chars;
312 VOID strcpy(a+chars, en);
316 # define close_directory(d) (closedir(d), 0)
318 # define close_directory(d) closedir(d)
320 if (errno || close_directory(d) != 0)
323 a = trealloc(char, a, chars);
326 *aargv = p = tnalloc(char*, entries+1);
327 for (i=0; i<entries; i++)
328 *p++ = a + offset[i];