1 /* $NetBSD: rcsclean.c,v 1.4 1996/10/15 07:00:38 veego Exp $ */
3 /* Clean up working files. */
5 /* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
6 Distributed under license by the Free Software Foundation, Inc.
8 This file is part of RCS.
10 RCS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 RCS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with RCS; see the file COPYING.
22 If not, write to the Free Software Foundation,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 Report problems and direct all questions to:
27 rcs-bugs@cs.purdue.edu
34 static int get_directory
P((char const*,char***));
37 static int unlock
P((struct hshentry
*));
38 static void cleanup
P((void));
41 static int exitstatus
;
43 mainProg(rcscleanId
, "rcsclean", "Id: rcsclean.c,v 5.9 1995/06/16 06:19:24 eggert Exp")
45 static char const usage
[] =
46 "\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
48 static struct buf revision
;
52 int dounlock
, expmode
, perform
, unlocked
, unlockflag
, waslocked
;
54 struct hshentries
*deltas
;
55 struct hshentry
*delta
;
67 argc
= getRCSINIT(argc
, argv
, &newargv
);
72 argc
= get_directory(".", &newargv
);
76 faterror("no pathnames specified");
80 if (!*a
|| *a
++ != '-')
86 if ((expmode
= str2expmode(a
)) < 0)
101 warn("redefinition of revision number");
114 goto handle_revision
;
117 setRCSversion(*argv
);
130 error("unknown option: %s%s", *argv
, usage
);
134 dounlock
= perform
& unlockflag
;
139 for (; 0 < argc
; cleanup(), ++argv
, --argc
) {
146 dounlock
? rcswriteopen
: rcsreadopen
,
149 (workptr
= Iopen(workname
, FOPEN_R_WORK
, &workstat
))
153 if (same_file(RCSstat
, workstat
, 0)) {
154 rcserror("RCS file is the same as working file %s.",
164 if (!fexpandsym(rev
, &revision
, workptr
))
168 switch (unlockflag
? findlock(false,&delta
) : 0) {
172 p
= Dbranch
? Dbranch
: "";
179 deltas
= 0; /* Keep lint happy. */
180 if (p
&& !(delta
= genrevs(p
,(char*)0,(char*)0,(char*)0,&deltas
)))
183 waslocked
= delta
&& delta
->lockedby
;
184 locker_expansion
= unlock(delta
);
185 unlocked
= locker_expansion
& unlockflag
;
186 if (unlocked
<waslocked
&& workstat
.st_mode
&(S_IWUSR
|S_IWGRP
|S_IWOTH
))
189 if (unlocked
&& !checkaccesslist())
192 if (dorewrite(dounlock
, unlocked
) != 0)
199 Expand
== KEYVAL_EXPAND
&&
200 WORKMODE(RCSstat
.st_mode
,true) == workstat
.st_mode
202 Expand
= KEYVALLOCK_EXPAND
;
207 !delta
? workstat
.st_size
!=0 :
210 buildrevision(deltas
, delta
, (FILE*)0, false),
216 if (quietflag
< unlocked
)
217 aprintf(stdout
, "rcs -u%s %s\n", delta
->num
, RCSname
);
219 if (perform
& unlocked
) {
220 if_advise_access(deltas
->first
!= delta
, finptr
, MADV_SEQUENTIAL
);
221 if (donerewrite(true,
222 Ttimeflag
? RCSstat
.st_mtime
: (time_t)-1
228 aprintf(stdout
, "rm -f %s\n", workname
);
230 if (perform
&& un_link(workname
) != 0)
238 exitmain(exitstatus
);
244 if (nerror
) exitstatus
= EXIT_FAILURE
;
253 # define exiterr rcscleanExit
266 struct hshentry
*delta
;
268 register struct rcslock
**al
, *l
;
270 if (delta
&& delta
->lockedby
&& strcmp(getcaller(),delta
->lockedby
)==0)
271 for (al
= &Locks
; (l
= *al
); al
= &l
->nextlock
)
272 if (l
->delta
== delta
) {
282 get_directory(dirname
, aargv
)
286 * Put a vector of all DIRNAME's directory entries names into *AARGV.
287 * Ignore names of RCS files.
288 * Yield the number of entries found. Terminate the vector with 0.
289 * Allocate the storage for the vector and entry names.
290 * Do not sort the names. Do not include '.' and '..'.
293 int i
, entries
= 0, entries_max
= 64;
294 size_t chars
= 0, chars_max
= 1024;
295 size_t *offset
= tnalloc(size_t, entries_max
);
296 char *a
= tnalloc(char, chars_max
), **p
;
300 if (!(d
= opendir(dirname
)))
302 while ((errno
= 0, e
= readdir(d
))) {
303 char const *en
= e
->d_name
;
304 size_t s
= strlen(en
) + 1;
305 if (en
[0]=='.' && (!en
[1] || (en
[1]=='.' && !en
[2])))
309 while (chars_max
< s
+ chars
)
310 a
= trealloc(char, a
, chars_max
<<=1);
311 if (entries
== entries_max
)
312 offset
= trealloc(size_t, offset
, entries_max
<<=1);
313 offset
[entries
++] = chars
;
314 VOID
strcpy(a
+chars
, en
);
318 # define close_directory(d) (closedir(d), 0)
320 # define close_directory(d) closedir(d)
322 if (errno
|| close_directory(d
) != 0)
325 a
= trealloc(char, a
, chars
);
330 *aargv
= p
= tnalloc(char*, entries
+1);
332 for (i
=0; i
<entries
; i
++)
333 *p
++ = a
+ offset
[i
];