GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: rcsprog.c,v 1.161 2016/07/04 01:39:12 millert Exp $ */ |
||
2 |
/* |
||
3 |
* Copyright (c) 2005 Jean-Francois Brousseau <jfb@openbsd.org> |
||
4 |
* All rights reserved. |
||
5 |
* |
||
6 |
* Redistribution and use in source and binary forms, with or without |
||
7 |
* modification, are permitted provided that the following conditions |
||
8 |
* are met: |
||
9 |
* |
||
10 |
* 1. Redistributions of source code must retain the above copyright |
||
11 |
* notice, this list of conditions and the following disclaimer. |
||
12 |
* 2. The name of the author may not be used to endorse or promote products |
||
13 |
* derived from this software without specific prior written permission. |
||
14 |
* |
||
15 |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||
16 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
17 |
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
||
18 |
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||
19 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||
20 |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||
21 |
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||
22 |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||
23 |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||
24 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
25 |
*/ |
||
26 |
|||
27 |
#include <sys/stat.h> |
||
28 |
|||
29 |
#include <err.h> |
||
30 |
#include <signal.h> |
||
31 |
#include <stdio.h> |
||
32 |
#include <stdlib.h> |
||
33 |
#include <string.h> |
||
34 |
#include <unistd.h> |
||
35 |
|||
36 |
#include "rcsprog.h" |
||
37 |
|||
38 |
#define RCSPROG_OPTSTRING "A:a:b::c:e::Iik:Ll::m:Mn:N:o:qt::TUu::Vx::z::" |
||
39 |
|||
40 |
const char rcs_version[] = "OpenRCS 4.5"; |
||
41 |
|||
42 |
int rcsflags; |
||
43 |
int rcs_optind; |
||
44 |
char *rcs_optarg; |
||
45 |
char *rcs_suffixes = RCS_DEFAULT_SUFFIX; |
||
46 |
char *rcs_tmpdir = RCS_TMPDIR_DEFAULT; |
||
47 |
|||
48 |
struct rcs_prog { |
||
49 |
char *prog_name; |
||
50 |
int (*prog_hdlr)(int, char **); |
||
51 |
void (*prog_usage)(void); |
||
52 |
} programs[] = { |
||
53 |
{ "rcs", rcs_main, rcs_usage }, |
||
54 |
{ "ci", checkin_main, checkin_usage }, |
||
55 |
{ "co", checkout_main, checkout_usage }, |
||
56 |
{ "rcsclean", rcsclean_main, rcsclean_usage }, |
||
57 |
{ "rcsdiff", rcsdiff_main, rcsdiff_usage }, |
||
58 |
{ "rcsmerge", rcsmerge_main, rcsmerge_usage }, |
||
59 |
{ "rlog", rlog_main, rlog_usage }, |
||
60 |
{ "ident", ident_main, ident_usage }, |
||
61 |
{ "merge", merge_main, merge_usage }, |
||
62 |
}; |
||
63 |
|||
64 |
struct wklhead temp_files; |
||
65 |
|||
66 |
void sighdlr(int); |
||
67 |
static void rcs_attach_symbol(RCSFILE *, const char *); |
||
68 |
|||
69 |
/* ARGSUSED */ |
||
70 |
void |
||
71 |
sighdlr(int sig) |
||
72 |
{ |
||
73 |
worklist_clean(&temp_files, worklist_unlink); |
||
74 |
_exit(1); |
||
75 |
} |
||
76 |
|||
77 |
int |
||
78 |
build_cmd(char ***cmd_argv, char **argv, int argc) |
||
79 |
{ |
||
80 |
int cmd_argc, i, cur; |
||
81 |
356 |
char *cp, *rcsinit, *linebuf, *lp; |
|
82 |
|||
83 |
✓✓ | 178 |
if ((rcsinit = getenv("RCSINIT")) == NULL) { |
84 |
177 |
*cmd_argv = argv; |
|
85 |
177 |
return argc; |
|
86 |
} |
||
87 |
|||
88 |
1 |
cur = argc + 2; |
|
89 |
cmd_argc = 0; |
||
90 |
1 |
*cmd_argv = xcalloc(cur, sizeof(char *)); |
|
91 |
1 |
(*cmd_argv)[cmd_argc++] = argv[0]; |
|
92 |
|||
93 |
1 |
linebuf = xstrdup(rcsinit); |
|
94 |
✓✓ | 4 |
for (lp = linebuf; lp != NULL;) { |
95 |
1 |
cp = strsep(&lp, " \t\b\f\n\r\t\v"); |
|
96 |
✓✗ | 1 |
if (cp == NULL) |
97 |
break; |
||
98 |
✗✓ | 1 |
if (*cp == '\0') |
99 |
continue; |
||
100 |
|||
101 |
✗✓ | 1 |
if (cmd_argc == cur) { |
102 |
cur += 8; |
||
103 |
*cmd_argv = xreallocarray(*cmd_argv, cur, |
||
104 |
sizeof(char *)); |
||
105 |
} |
||
106 |
|||
107 |
1 |
(*cmd_argv)[cmd_argc++] = cp; |
|
108 |
} |
||
109 |
|||
110 |
✗✓ | 1 |
if (cmd_argc + argc > cur) { |
111 |
cur = cmd_argc + argc + 1; |
||
112 |
*cmd_argv = xreallocarray(*cmd_argv, cur, |
||
113 |
sizeof(char *)); |
||
114 |
} |
||
115 |
|||
116 |
✓✓ | 6 |
for (i = 1; i < argc; i++) |
117 |
2 |
(*cmd_argv)[cmd_argc++] = argv[i]; |
|
118 |
|||
119 |
1 |
(*cmd_argv)[cmd_argc] = NULL; |
|
120 |
|||
121 |
1 |
return cmd_argc; |
|
122 |
178 |
} |
|
123 |
|||
124 |
int |
||
125 |
main(int argc, char **argv) |
||
126 |
{ |
||
127 |
u_int i; |
||
128 |
356 |
char **cmd_argv; |
|
129 |
int ret, cmd_argc; |
||
130 |
|||
131 |
✗✓ | 178 |
if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1) |
132 |
err(2, "pledge"); |
||
133 |
|||
134 |
ret = -1; |
||
135 |
178 |
rcs_optind = 1; |
|
136 |
178 |
SLIST_INIT(&temp_files); |
|
137 |
|||
138 |
178 |
cmd_argc = build_cmd(&cmd_argv, argv, argc); |
|
139 |
|||
140 |
178 |
if ((rcs_tmpdir = getenv("TMPDIR")) == NULL) |
|
141 |
178 |
rcs_tmpdir = RCS_TMPDIR_DEFAULT; |
|
142 |
|||
143 |
178 |
signal(SIGHUP, sighdlr); |
|
144 |
178 |
signal(SIGINT, sighdlr); |
|
145 |
178 |
signal(SIGQUIT, sighdlr); |
|
146 |
178 |
signal(SIGABRT, sighdlr); |
|
147 |
178 |
signal(SIGALRM, sighdlr); |
|
148 |
178 |
signal(SIGTERM, sighdlr); |
|
149 |
|||
150 |
✓✗ | 1102 |
for (i = 0; i < (sizeof(programs)/sizeof(programs[0])); i++) |
151 |
✓✓ | 551 |
if (strcmp(__progname, programs[i].prog_name) == 0) { |
152 |
178 |
usage = programs[i].prog_usage; |
|
153 |
178 |
ret = programs[i].prog_hdlr(cmd_argc, cmd_argv); |
|
154 |
178 |
break; |
|
155 |
} |
||
156 |
|||
157 |
/* clean up temporary files */ |
||
158 |
worklist_run(&temp_files, worklist_unlink); |
||
159 |
|||
160 |
exit(ret); |
||
161 |
} |
||
162 |
|||
163 |
|||
164 |
__dead void |
||
165 |
rcs_usage(void) |
||
166 |
{ |
||
167 |
fprintf(stderr, |
||
168 |
"usage: rcs [-IiLqTUV] [-Aoldfile] [-ausers] [-b[rev]]\n" |
||
169 |
" [-cstring] [-e[users]] [-kmode] [-l[rev]] [-mrev:msg]\n" |
||
170 |
" [-orev] [-t[str]] [-u[rev]] [-xsuffixes] file ...\n"); |
||
171 |
|||
172 |
exit(1); |
||
173 |
} |
||
174 |
|||
175 |
/* |
||
176 |
* rcs_main() |
||
177 |
* |
||
178 |
* Handler for the `rcs' program. |
||
179 |
* Returns 0 on success, or >0 on error. |
||
180 |
*/ |
||
181 |
int |
||
182 |
rcs_main(int argc, char **argv) |
||
183 |
{ |
||
184 |
int fd; |
||
185 |
int i, j, ch, flags, kflag, lkmode; |
||
186 |
const char *nflag, *oldfilename, *orange; |
||
187 |
58 |
char fpath[PATH_MAX]; |
|
188 |
char *logstr, *logmsg, *descfile; |
||
189 |
char *alist, *comment, *elist, *lrev, *urev; |
||
190 |
mode_t fmode; |
||
191 |
RCSFILE *file; |
||
192 |
RCSNUM *logrev; |
||
193 |
struct rcs_access *acp; |
||
194 |
time_t rcs_mtime = -1; |
||
195 |
|||
196 |
kflag = RCS_KWEXP_ERR; |
||
197 |
lkmode = RCS_LOCK_INVAL; |
||
198 |
fmode = S_IRUSR|S_IRGRP|S_IROTH; |
||
199 |
flags = RCS_RDWR|RCS_PARSE_FULLY; |
||
200 |
lrev = urev = descfile = NULL; |
||
201 |
logstr = alist = comment = elist = NULL; |
||
202 |
nflag = oldfilename = orange = NULL; |
||
203 |
|||
204 |
/* match GNU */ |
||
205 |
✓✗✗✓ |
58 |
if (1 < argc && argv[1][0] != '-') |
206 |
warnx("warning: No options were given; " |
||
207 |
"this usage is obsolescent."); |
||
208 |
|||
209 |
✓✓ | 92 |
while ((ch = rcs_getopt(argc, argv, RCSPROG_OPTSTRING)) != -1) { |
210 |
✗✓✓✓ ✗✓✗✓ ✗✗✓✓ ✗✗✓✓ ✓✗✗✓ ✗✗✗ |
126 |
switch (ch) { |
211 |
case 'A': |
||
212 |
1 |
oldfilename = rcs_optarg; |
|
213 |
1 |
rcsflags |= CO_ACLAPPEND; |
|
214 |
1 |
break; |
|
215 |
case 'a': |
||
216 |
3 |
alist = rcs_optarg; |
|
217 |
3 |
break; |
|
218 |
case 'c': |
||
219 |
comment = rcs_optarg; |
||
220 |
break; |
||
221 |
case 'e': |
||
222 |
1 |
elist = rcs_optarg; |
|
223 |
1 |
rcsflags |= RCSPROG_EFLAG; |
|
224 |
1 |
break; |
|
225 |
case 'I': |
||
226 |
rcsflags |= INTERACTIVE; |
||
227 |
break; |
||
228 |
case 'i': |
||
229 |
10 |
flags |= RCS_CREATE; |
|
230 |
10 |
break; |
|
231 |
case 'k': |
||
232 |
kflag = rcs_kflag_get(rcs_optarg); |
||
233 |
if (RCS_KWEXP_INVAL(kflag)) { |
||
234 |
warnx("invalid RCS keyword substitution mode"); |
||
235 |
(usage)(); |
||
236 |
} |
||
237 |
break; |
||
238 |
case 'L': |
||
239 |
if (lkmode == RCS_LOCK_LOOSE) |
||
240 |
warnx("-U overridden by -L"); |
||
241 |
lkmode = RCS_LOCK_STRICT; |
||
242 |
break; |
||
243 |
case 'l': |
||
244 |
✗✓ | 6 |
if (rcsflags & RCSPROG_UFLAG) |
245 |
warnx("-u overridden by -l"); |
||
246 |
6 |
lrev = rcs_optarg; |
|
247 |
6 |
rcsflags &= ~RCSPROG_UFLAG; |
|
248 |
6 |
rcsflags |= RCSPROG_LFLAG; |
|
249 |
6 |
break; |
|
250 |
case 'm': |
||
251 |
2 |
free(logstr); |
|
252 |
2 |
logstr = xstrdup(rcs_optarg); |
|
253 |
2 |
break; |
|
254 |
case 'M': |
||
255 |
/* ignore for the moment */ |
||
256 |
break; |
||
257 |
case 'n': |
||
258 |
nflag = rcs_optarg; |
||
259 |
break; |
||
260 |
case 'N': |
||
261 |
nflag = rcs_optarg; |
||
262 |
rcsflags |= RCSPROG_NFLAG; |
||
263 |
break; |
||
264 |
case 'o': |
||
265 |
1 |
orange = rcs_optarg; |
|
266 |
1 |
break; |
|
267 |
case 'q': |
||
268 |
29 |
rcsflags |= QUIET; |
|
269 |
29 |
break; |
|
270 |
case 't': |
||
271 |
5 |
descfile = rcs_optarg; |
|
272 |
5 |
rcsflags |= DESCRIPTION; |
|
273 |
5 |
break; |
|
274 |
case 'T': |
||
275 |
rcsflags |= PRESERVETIME; |
||
276 |
break; |
||
277 |
case 'U': |
||
278 |
if (lkmode == RCS_LOCK_STRICT) |
||
279 |
warnx("-L overridden by -U"); |
||
280 |
lkmode = RCS_LOCK_LOOSE; |
||
281 |
break; |
||
282 |
case 'u': |
||
283 |
✗✓ | 5 |
if (rcsflags & RCSPROG_LFLAG) |
284 |
warnx("-l overridden by -u"); |
||
285 |
5 |
urev = rcs_optarg; |
|
286 |
5 |
rcsflags &= ~RCSPROG_LFLAG; |
|
287 |
5 |
rcsflags |= RCSPROG_UFLAG; |
|
288 |
5 |
break; |
|
289 |
case 'V': |
||
290 |
printf("%s\n", rcs_version); |
||
291 |
exit(0); |
||
292 |
case 'x': |
||
293 |
/* Use blank extension if none given. */ |
||
294 |
rcs_suffixes = rcs_optarg ? rcs_optarg : ""; |
||
295 |
break; |
||
296 |
case 'z': |
||
297 |
/* |
||
298 |
* kept for compatibility |
||
299 |
*/ |
||
300 |
break; |
||
301 |
default: |
||
302 |
(usage)(); |
||
303 |
} |
||
304 |
} |
||
305 |
|||
306 |
29 |
argc -= rcs_optind; |
|
307 |
29 |
argv += rcs_optind; |
|
308 |
|||
309 |
✗✓ | 29 |
if (argc == 0) { |
310 |
warnx("no input file"); |
||
311 |
(usage)(); |
||
312 |
} |
||
313 |
|||
314 |
✓✓ | 112 |
for (i = 0; i < argc; i++) { |
315 |
29 |
fd = rcs_choosefile(argv[i], fpath, sizeof(fpath)); |
|
316 |
✓✓✗✓ |
39 |
if (fd < 0 && !(flags & RCS_CREATE)) { |
317 |
warn("%s", fpath); |
||
318 |
continue; |
||
319 |
} |
||
320 |
|||
321 |
✗✓ | 29 |
if (!(rcsflags & QUIET)) |
322 |
(void)fprintf(stderr, "RCS file: %s\n", fpath); |
||
323 |
|||
324 |
✗✓ | 29 |
if ((file = rcs_open(fpath, fd, flags, fmode)) == NULL) { |
325 |
close(fd); |
||
326 |
continue; |
||
327 |
} |
||
328 |
|||
329 |
✓✓ | 29 |
if (rcsflags & DESCRIPTION) { |
330 |
✗✓ | 5 |
if (rcs_set_description(file, descfile, rcsflags) == -1) { |
331 |
warn("%s", descfile); |
||
332 |
rcs_close(file); |
||
333 |
continue; |
||
334 |
} |
||
335 |
} |
||
336 |
✓✓ | 24 |
else if (flags & RCS_CREATE) { |
337 |
✗✓ | 5 |
if (rcs_set_description(file, NULL, rcsflags) == -1) { |
338 |
warn("stdin"); |
||
339 |
rcs_close(file); |
||
340 |
continue; |
||
341 |
} |
||
342 |
} |
||
343 |
|||
344 |
✗✓ | 29 |
if (rcsflags & PRESERVETIME) |
345 |
rcs_mtime = rcs_get_mtime(file); |
||
346 |
|||
347 |
✗✓ | 29 |
if (nflag != NULL) |
348 |
rcs_attach_symbol(file, nflag); |
||
349 |
|||
350 |
✓✓ | 29 |
if (logstr != NULL) { |
351 |
✗✓ | 2 |
if ((logmsg = strchr(logstr, ':')) == NULL) { |
352 |
warnx("missing log message"); |
||
353 |
rcs_close(file); |
||
354 |
continue; |
||
355 |
} |
||
356 |
|||
357 |
2 |
*logmsg++ = '\0'; |
|
358 |
✗✓ | 2 |
if ((logrev = rcsnum_parse(logstr)) == NULL) { |
359 |
warnx("`%s' bad revision number", logstr); |
||
360 |
rcs_close(file); |
||
361 |
continue; |
||
362 |
} |
||
363 |
|||
364 |
✗✓ | 2 |
if (rcs_rev_setlog(file, logrev, logmsg) < 0) { |
365 |
warnx("failed to set logmsg for `%s' to `%s'", |
||
366 |
logstr, logmsg); |
||
367 |
rcs_close(file); |
||
368 |
rcsnum_free(logrev); |
||
369 |
continue; |
||
370 |
} |
||
371 |
|||
372 |
2 |
rcsnum_free(logrev); |
|
373 |
2 |
} |
|
374 |
|||
375 |
/* entries to add from <oldfile> */ |
||
376 |
✓✓ | 29 |
if (rcsflags & CO_ACLAPPEND) { |
377 |
RCSFILE *oldfile; |
||
378 |
int ofd; |
||
379 |
1 |
char ofpath[PATH_MAX]; |
|
380 |
|||
381 |
1 |
ofd = rcs_choosefile(oldfilename, ofpath, sizeof(ofpath)); |
|
382 |
✗✓ | 1 |
if (ofd < 0) { |
383 |
if (!(flags & RCS_CREATE)) |
||
384 |
warn("%s", ofpath); |
||
385 |
exit(1); |
||
386 |
} |
||
387 |
✗✓ | 1 |
if ((oldfile = rcs_open(ofpath, ofd, RCS_READ)) == NULL) |
388 |
exit(1); |
||
389 |
|||
390 |
✓✓ | 8 |
TAILQ_FOREACH(acp, &(oldfile->rf_access), ra_list) |
391 |
3 |
rcs_access_add(file, acp->ra_name); |
|
392 |
|||
393 |
1 |
rcs_close(oldfile); |
|
394 |
1 |
(void)close(ofd); |
|
395 |
1 |
} |
|
396 |
|||
397 |
/* entries to add to the access list */ |
||
398 |
✓✓ | 29 |
if (alist != NULL) { |
399 |
struct rcs_argvector *aargv; |
||
400 |
|||
401 |
3 |
aargv = rcs_strsplit(alist, ","); |
|
402 |
✓✓ | 24 |
for (j = 0; aargv->argv[j] != NULL; j++) |
403 |
9 |
rcs_access_add(file, aargv->argv[j]); |
|
404 |
|||
405 |
3 |
rcs_argv_destroy(aargv); |
|
406 |
3 |
} |
|
407 |
|||
408 |
✗✓ | 29 |
if (comment != NULL) |
409 |
rcs_comment_set(file, comment); |
||
410 |
|||
411 |
✓✓ | 29 |
if (elist != NULL) { |
412 |
struct rcs_argvector *eargv; |
||
413 |
|||
414 |
1 |
eargv = rcs_strsplit(elist, ","); |
|
415 |
✓✓ | 8 |
for (j = 0; eargv->argv[j] != NULL; j++) |
416 |
3 |
rcs_access_remove(file, eargv->argv[j]); |
|
417 |
|||
418 |
1 |
rcs_argv_destroy(eargv); |
|
419 |
✗✓ | 29 |
} else if (rcsflags & RCSPROG_EFLAG) { |
420 |
struct rcs_access *rap; |
||
421 |
|||
422 |
/* XXX rcs_access_remove(file, NULL); ?? */ |
||
423 |
while (!TAILQ_EMPTY(&(file->rf_access))) { |
||
424 |
rap = TAILQ_FIRST(&(file->rf_access)); |
||
425 |
TAILQ_REMOVE(&(file->rf_access), rap, ra_list); |
||
426 |
free(rap->ra_name); |
||
427 |
free(rap); |
||
428 |
} |
||
429 |
/* not synced anymore */ |
||
430 |
file->rf_flags &= ~RCS_SYNCED; |
||
431 |
} |
||
432 |
|||
433 |
29 |
rcs_kwexp_set(file, kflag); |
|
434 |
|||
435 |
✗✓ | 29 |
if (lkmode != RCS_LOCK_INVAL) |
436 |
(void)rcs_lock_setmode(file, lkmode); |
||
437 |
|||
438 |
✓✓ | 29 |
if (rcsflags & RCSPROG_LFLAG) { |
439 |
RCSNUM *rev; |
||
440 |
const char *username; |
||
441 |
6 |
char rev_str[RCS_REV_BUFSZ]; |
|
442 |
|||
443 |
✗✓ | 6 |
if (file->rf_head == NULL) { |
444 |
warnx("%s contains no revisions", fpath); |
||
445 |
rcs_close(file); |
||
446 |
continue; |
||
447 |
} |
||
448 |
|||
449 |
✗✓ | 6 |
if ((username = getlogin()) == NULL) |
450 |
err(1, "getlogin"); |
||
451 |
✓✓ | 6 |
if (lrev == NULL) { |
452 |
3 |
rev = rcsnum_alloc(); |
|
453 |
3 |
rcsnum_cpy(file->rf_head, rev, 0); |
|
454 |
✗✓ | 6 |
} else if ((rev = rcsnum_parse(lrev)) == NULL) { |
455 |
warnx("unable to unlock file"); |
||
456 |
rcs_close(file); |
||
457 |
continue; |
||
458 |
} |
||
459 |
6 |
rcsnum_tostr(rev, rev_str, sizeof(rev_str)); |
|
460 |
/* Make sure revision exists. */ |
||
461 |
✓✓ | 6 |
if (rcs_findrev(file, rev) == NULL) |
462 |
errx(1, "%s: cannot lock nonexisting " |
||
463 |
"revision %s", fpath, rev_str); |
||
464 |
✓✓✗✓ |
9 |
if (rcs_lock_add(file, username, rev) != -1 && |
465 |
4 |
!(rcsflags & QUIET)) |
|
466 |
(void)fprintf(stderr, "%s locked\n", rev_str); |
||
467 |
5 |
rcsnum_free(rev); |
|
468 |
✓✗ | 10 |
} |
469 |
|||
470 |
✓✓ | 28 |
if (rcsflags & RCSPROG_UFLAG) { |
471 |
RCSNUM *rev; |
||
472 |
const char *username; |
||
473 |
5 |
char rev_str[RCS_REV_BUFSZ]; |
|
474 |
|||
475 |
✗✓ | 5 |
if (file->rf_head == NULL) { |
476 |
warnx("%s contains no revisions", fpath); |
||
477 |
rcs_close(file); |
||
478 |
continue; |
||
479 |
} |
||
480 |
|||
481 |
✗✓ | 5 |
if ((username = getlogin()) == NULL) |
482 |
err(1, "getlogin"); |
||
483 |
✓✓ | 5 |
if (urev == NULL) { |
484 |
2 |
rev = rcsnum_alloc(); |
|
485 |
2 |
rcsnum_cpy(file->rf_head, rev, 0); |
|
486 |
✗✓ | 5 |
} else if ((rev = rcsnum_parse(urev)) == NULL) { |
487 |
warnx("unable to unlock file"); |
||
488 |
rcs_close(file); |
||
489 |
continue; |
||
490 |
} |
||
491 |
5 |
rcsnum_tostr(rev, rev_str, sizeof(rev_str)); |
|
492 |
/* Make sure revision exists. */ |
||
493 |
✓✓ | 5 |
if (rcs_findrev(file, rev) == NULL) |
494 |
errx(1, "%s: cannot unlock nonexisting " |
||
495 |
"revision %s", fpath, rev_str); |
||
496 |
✓✓✗✓ |
5 |
if (rcs_lock_remove(file, username, rev) == -1 && |
497 |
1 |
!(rcsflags & QUIET)) |
|
498 |
warnx("%s: warning: No locks are set.", fpath); |
||
499 |
else { |
||
500 |
✗✓ | 4 |
if (!(rcsflags & QUIET)) |
501 |
(void)fprintf(stderr, |
||
502 |
"%s unlocked\n", rev_str); |
||
503 |
} |
||
504 |
4 |
rcsnum_free(rev); |
|
505 |
✓✗ | 8 |
} |
506 |
|||
507 |
✓✓ | 27 |
if (orange != NULL) { |
508 |
struct rcs_delta *rdp, *nrdp; |
||
509 |
1 |
char b[RCS_REV_BUFSZ]; |
|
510 |
|||
511 |
1 |
rcs_rev_select(file, orange); |
|
512 |
✓✓ | 14 |
for (rdp = TAILQ_FIRST(&(file->rf_delta)); |
513 |
7 |
rdp != NULL; rdp = nrdp) { |
|
514 |
6 |
nrdp = TAILQ_NEXT(rdp, rd_list); |
|
515 |
|||
516 |
/* |
||
517 |
* Delete selected revisions. |
||
518 |
*/ |
||
519 |
✓✓ | 6 |
if (rdp->rd_flags & RCS_RD_SELECT) { |
520 |
3 |
rcsnum_tostr(rdp->rd_num, b, sizeof(b)); |
|
521 |
✗✓ | 3 |
if (!(rcsflags & QUIET)) { |
522 |
(void)fprintf(stderr, "deleting" |
||
523 |
" revision %s\n", b); |
||
524 |
} |
||
525 |
3 |
(void)rcs_rev_remove(file, rdp->rd_num); |
|
526 |
3 |
} |
|
527 |
} |
||
528 |
1 |
} |
|
529 |
|||
530 |
27 |
rcs_write(file); |
|
531 |
|||
532 |
✗✓ | 27 |
if (rcsflags & PRESERVETIME) |
533 |
rcs_set_mtime(file, rcs_mtime); |
||
534 |
|||
535 |
27 |
rcs_close(file); |
|
536 |
|||
537 |
✗✓ | 27 |
if (!(rcsflags & QUIET)) |
538 |
(void)fprintf(stderr, "done\n"); |
||
539 |
} |
||
540 |
|||
541 |
27 |
return (0); |
|
542 |
27 |
} |
|
543 |
|||
544 |
static void |
||
545 |
rcs_attach_symbol(RCSFILE *file, const char *symname) |
||
546 |
{ |
||
547 |
char *rnum; |
||
548 |
RCSNUM *rev; |
||
549 |
char rbuf[RCS_REV_BUFSZ]; |
||
550 |
int rm; |
||
551 |
|||
552 |
rm = 0; |
||
553 |
rev = NULL; |
||
554 |
if ((rnum = strrchr(symname, ':')) != NULL) { |
||
555 |
if (rnum[1] == '\0') |
||
556 |
rev = file->rf_head; |
||
557 |
*(rnum++) = '\0'; |
||
558 |
} else { |
||
559 |
rm = 1; |
||
560 |
} |
||
561 |
|||
562 |
if (rev == NULL && rm != 1) { |
||
563 |
if ((rev = rcsnum_parse(rnum)) == NULL) |
||
564 |
errx(1, "bad revision %s", rnum); |
||
565 |
} |
||
566 |
|||
567 |
if (rcsflags & RCSPROG_NFLAG) |
||
568 |
rm = 1; |
||
569 |
|||
570 |
if (rm == 1) { |
||
571 |
if (rcs_sym_remove(file, symname) < 0) { |
||
572 |
if (rcs_errno == RCS_ERR_NOENT && |
||
573 |
!(rcsflags & RCSPROG_NFLAG)) |
||
574 |
warnx("cannot delete nonexisting symbol %s", |
||
575 |
symname); |
||
576 |
} else { |
||
577 |
if (rcsflags & RCSPROG_NFLAG) |
||
578 |
rm = 0; |
||
579 |
} |
||
580 |
} |
||
581 |
|||
582 |
if (rm == 0) { |
||
583 |
if (rcs_sym_add(file, symname, rev) < 0 && |
||
584 |
rcs_errno == RCS_ERR_DUPENT) { |
||
585 |
rcsnum_tostr(rcs_sym_getrev(file, symname), |
||
586 |
rbuf, sizeof(rbuf)); |
||
587 |
errx(1, "symbolic name %s already bound to %s", |
||
588 |
symname, rbuf); |
||
589 |
} |
||
590 |
} |
||
591 |
} |
Generated by: GCOVR (Version 3.3) |