GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: file.c,v 1.273 2017/06/01 08:38:56 joris Exp $ */ |
||
2 |
/* |
||
3 |
* Copyright (c) 2006 Joris Vink <joris@openbsd.org> |
||
4 |
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> |
||
5 |
* All rights reserved. |
||
6 |
* |
||
7 |
* Redistribution and use in source and binary forms, with or without |
||
8 |
* modification, are permitted provided that the following conditions |
||
9 |
* are met: |
||
10 |
* |
||
11 |
* 1. Redistributions of source code must retain the above copyright |
||
12 |
* notice, this list of conditions and the following disclaimer. |
||
13 |
* 2. The name of the author may not be used to endorse or promote products |
||
14 |
* derived from this software without specific prior written permission. |
||
15 |
* |
||
16 |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||
17 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
18 |
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
||
19 |
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||
20 |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||
21 |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
||
22 |
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
||
23 |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
||
24 |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||
25 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 |
*/ |
||
27 |
|||
28 |
#include <sys/types.h> |
||
29 |
#include <sys/mman.h> |
||
30 |
#include <sys/stat.h> |
||
31 |
#include <sys/time.h> |
||
32 |
|||
33 |
#include <dirent.h> |
||
34 |
#include <errno.h> |
||
35 |
#include <fcntl.h> |
||
36 |
#include <fnmatch.h> |
||
37 |
#include <libgen.h> |
||
38 |
#include <stdint.h> |
||
39 |
#include <stdlib.h> |
||
40 |
#include <string.h> |
||
41 |
#include <unistd.h> |
||
42 |
|||
43 |
#include "atomicio.h" |
||
44 |
#include "cvs.h" |
||
45 |
#include "remote.h" |
||
46 |
|||
47 |
#define CVS_IGN_STATIC 0x01 /* pattern is static, no need to glob */ |
||
48 |
|||
49 |
#define CVS_CHAR_ISMETA(c) ((c == '*') || (c == '?') || (c == '[')) |
||
50 |
|||
51 |
extern int print_stdout; |
||
52 |
extern int build_dirs; |
||
53 |
|||
54 |
/* |
||
55 |
* Standard patterns to ignore. |
||
56 |
*/ |
||
57 |
static const char *cvs_ign_std[] = { |
||
58 |
".", |
||
59 |
"..", |
||
60 |
"*.o", |
||
61 |
"*.a", |
||
62 |
"*.bak", |
||
63 |
"*.orig", |
||
64 |
"*.rej", |
||
65 |
"*.old", |
||
66 |
"*.exe", |
||
67 |
"*.depend", |
||
68 |
"*.obj", |
||
69 |
"*.elc", |
||
70 |
"*.ln", |
||
71 |
"*.olb", |
||
72 |
"CVS", |
||
73 |
"core", |
||
74 |
"cvslog*", |
||
75 |
"*.core", |
||
76 |
".#*", |
||
77 |
"*~", |
||
78 |
"_$*", |
||
79 |
"*$", |
||
80 |
}; |
||
81 |
|||
82 |
char *cvs_directory_tag = NULL; |
||
83 |
struct ignore_head cvs_ign_pats; |
||
84 |
struct ignore_head dir_ign_pats; |
||
85 |
struct ignore_head checkout_ign_pats; |
||
86 |
|||
87 |
✓✓✓✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✓✗✗ ✗✗✗✓ ✗✓✓✓ ✗✓✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✓ ✓✓✓✓ ✓✓✓✓ ✓✗✓✓ ✓✓✓✓ ✓✓✗✗ ✗✗✗✗ ✓✓✗✓ ✓✓✓✓ ✓✓✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✓✗ |
9617 |
RB_GENERATE(cvs_flisthead, cvs_filelist, flist, cvs_filelist_cmp); |
88 |
|||
89 |
void |
||
90 |
cvs_file_init(void) |
||
91 |
{ |
||
92 |
int i; |
||
93 |
FILE *ifp; |
||
94 |
82 |
char path[PATH_MAX], buf[MAXNAMLEN]; |
|
95 |
|||
96 |
41 |
TAILQ_INIT(&cvs_ign_pats); |
|
97 |
41 |
TAILQ_INIT(&dir_ign_pats); |
|
98 |
41 |
TAILQ_INIT(&checkout_ign_pats); |
|
99 |
|||
100 |
/* standard patterns to ignore */ |
||
101 |
✓✓ | 1886 |
for (i = 0; i < (int)(sizeof(cvs_ign_std)/sizeof(char *)); i++) |
102 |
902 |
cvs_file_ignore(cvs_ign_std[i], &cvs_ign_pats); |
|
103 |
|||
104 |
✗✓ | 41 |
if (cvs_homedir == NULL) |
105 |
return; |
||
106 |
|||
107 |
/* read the cvsignore file in the user's home directory, if any */ |
||
108 |
41 |
(void)xsnprintf(path, PATH_MAX, "%s/.cvsignore", cvs_homedir); |
|
109 |
|||
110 |
41 |
ifp = fopen(path, "r"); |
|
111 |
✓✗ | 41 |
if (ifp == NULL) { |
112 |
✗✓ | 41 |
if (errno != ENOENT) |
113 |
cvs_log(LP_ERRNO, |
||
114 |
"failed to open user's cvsignore file `%s'", path); |
||
115 |
} else { |
||
116 |
while (fgets(buf, MAXNAMLEN, ifp) != NULL) { |
||
117 |
buf[strcspn(buf, "\n")] = '\0'; |
||
118 |
if (buf[0] == '\0') |
||
119 |
continue; |
||
120 |
|||
121 |
cvs_file_ignore(buf, &cvs_ign_pats); |
||
122 |
} |
||
123 |
|||
124 |
(void)fclose(ifp); |
||
125 |
} |
||
126 |
82 |
} |
|
127 |
|||
128 |
void |
||
129 |
cvs_file_ignore(const char *pat, struct ignore_head *list) |
||
130 |
{ |
||
131 |
char *cp; |
||
132 |
size_t len; |
||
133 |
struct cvs_ignpat *ip; |
||
134 |
|||
135 |
1804 |
ip = xmalloc(sizeof(*ip)); |
|
136 |
902 |
len = strlcpy(ip->ip_pat, pat, sizeof(ip->ip_pat)); |
|
137 |
✗✓ | 902 |
if (len >= sizeof(ip->ip_pat)) |
138 |
fatal("cvs_file_ignore: truncation of pattern '%s'", pat); |
||
139 |
|||
140 |
/* check if we will need globbing for that pattern */ |
||
141 |
902 |
ip->ip_flags = CVS_IGN_STATIC; |
|
142 |
✓✓ | 3444 |
for (cp = ip->ip_pat; *cp != '\0'; cp++) { |
143 |
✓✓✓✗ ✗✓ |
3198 |
if (CVS_CHAR_ISMETA(*cp)) { |
144 |
738 |
ip->ip_flags &= ~CVS_IGN_STATIC; |
|
145 |
738 |
break; |
|
146 |
} |
||
147 |
} |
||
148 |
|||
149 |
902 |
TAILQ_INSERT_TAIL(list, ip, ip_list); |
|
150 |
902 |
} |
|
151 |
|||
152 |
int |
||
153 |
cvs_file_chkign(const char *file) |
||
154 |
{ |
||
155 |
int flags; |
||
156 |
struct cvs_ignpat *ip; |
||
157 |
|||
158 |
flags = FNM_PERIOD; |
||
159 |
✗✓ | 118 |
if (cvs_nocase) |
160 |
flags |= FNM_CASEFOLD; |
||
161 |
|||
162 |
✓✓ | 2714 |
TAILQ_FOREACH(ip, &cvs_ign_pats, ip_list) { |
163 |
✓✓ | 1298 |
if (ip->ip_flags & CVS_IGN_STATIC) { |
164 |
✗✓ | 236 |
if (cvs_file_cmpname(file, ip->ip_pat) == 0) |
165 |
return (1); |
||
166 |
✗✓ | 1062 |
} else if (fnmatch(ip->ip_pat, file, flags) == 0) |
167 |
return (1); |
||
168 |
} |
||
169 |
|||
170 |
✗✓ | 118 |
TAILQ_FOREACH(ip, &dir_ign_pats, ip_list) { |
171 |
if (ip->ip_flags & CVS_IGN_STATIC) { |
||
172 |
if (cvs_file_cmpname(file, ip->ip_pat) == 0) |
||
173 |
return (1); |
||
174 |
} else if (fnmatch(ip->ip_pat, file, flags) == 0) |
||
175 |
return (1); |
||
176 |
} |
||
177 |
|||
178 |
✗✓ | 118 |
TAILQ_FOREACH(ip, &checkout_ign_pats, ip_list) { |
179 |
if (ip->ip_flags & CVS_IGN_STATIC) { |
||
180 |
if (cvs_file_cmpname(file, ip->ip_pat) == 0) |
||
181 |
return (1); |
||
182 |
} else if (fnmatch(ip->ip_pat, file, flags) == 0) |
||
183 |
return (1); |
||
184 |
} |
||
185 |
|||
186 |
59 |
return (0); |
|
187 |
59 |
} |
|
188 |
|||
189 |
void |
||
190 |
cvs_file_run(int argc, char **argv, struct cvs_recursion *cr) |
||
191 |
{ |
||
192 |
int i; |
||
193 |
64 |
struct cvs_flisthead fl; |
|
194 |
|||
195 |
32 |
RB_INIT(&fl); |
|
196 |
|||
197 |
✓✓ | 128 |
for (i = 0; i < argc; i++) { |
198 |
✓✗✗✓ |
96 |
STRIP_SLASH(argv[i]); |
199 |
32 |
cvs_file_get(argv[i], FILE_USER_SUPPLIED, &fl, 0); |
|
200 |
} |
||
201 |
|||
202 |
32 |
cvs_file_walklist(&fl, cr); |
|
203 |
32 |
cvs_file_freelist(&fl); |
|
204 |
32 |
} |
|
205 |
|||
206 |
struct cvs_filelist * |
||
207 |
cvs_file_get(char *name, int flags, struct cvs_flisthead *fl, int type) |
||
208 |
{ |
||
209 |
char *p; |
||
210 |
494 |
struct cvs_filelist *l, find; |
|
211 |
|||
212 |
✓✓✓✓ |
1206 |
for (p = name; p[0] == '.' && p[1] == '/';) |
213 |
112 |
p += 2; |
|
214 |
|||
215 |
247 |
find.file_path = p; |
|
216 |
247 |
l = RB_FIND(cvs_flisthead, fl, &find); |
|
217 |
✓✓ | 247 |
if (l != NULL) |
218 |
86 |
return (l); |
|
219 |
|||
220 |
161 |
l = xmalloc(sizeof(*l)); |
|
221 |
161 |
l->file_path = xstrdup(p); |
|
222 |
161 |
l->flags = flags; |
|
223 |
161 |
l->type = type; |
|
224 |
|||
225 |
161 |
RB_INSERT(cvs_flisthead, fl, l); |
|
226 |
161 |
return (l); |
|
227 |
247 |
} |
|
228 |
|||
229 |
struct cvs_file * |
||
230 |
cvs_file_get_cf(const char *d, const char *f, const char *fpath, int fd, |
||
231 |
int type, int flags) |
||
232 |
{ |
||
233 |
const char *p; |
||
234 |
struct cvs_file *cf; |
||
235 |
|||
236 |
✓✓✗✓ |
452 |
for (p = fpath; p[0] == '.' && p[1] == '/';) |
237 |
p += 2; |
||
238 |
|||
239 |
145 |
cf = xcalloc(1, sizeof(*cf)); |
|
240 |
|||
241 |
145 |
cf->file_name = xstrdup(f); |
|
242 |
145 |
cf->file_wd = xstrdup(d); |
|
243 |
145 |
cf->file_path = xstrdup(p); |
|
244 |
145 |
cf->fd = fd; |
|
245 |
145 |
cf->repo_fd = -1; |
|
246 |
145 |
cf->file_type = type; |
|
247 |
145 |
cf->file_status = 0; |
|
248 |
145 |
cf->file_flags = flags; |
|
249 |
145 |
cf->in_attic = 0; |
|
250 |
145 |
cf->file_ent = NULL; |
|
251 |
|||
252 |
✓✓ | 145 |
if (cf->fd != -1) |
253 |
102 |
cf->file_flags |= FILE_ON_DISK; |
|
254 |
|||
255 |
✗✓ | 145 |
if (cvsroot_is_remote() || cvs_server_active == 1) |
256 |
cvs_validate_directory(cf->file_path); |
||
257 |
|||
258 |
145 |
return (cf); |
|
259 |
} |
||
260 |
|||
261 |
void |
||
262 |
cvs_file_walklist(struct cvs_flisthead *fl, struct cvs_recursion *cr) |
||
263 |
{ |
||
264 |
int fd, type; |
||
265 |
296 |
struct stat st; |
|
266 |
struct cvs_file *cf; |
||
267 |
struct cvs_filelist *l, *nxt; |
||
268 |
148 |
char *d, *f, repo[PATH_MAX], fpath[PATH_MAX]; |
|
269 |
|||
270 |
✓✓ | 584 |
for (l = RB_MIN(cvs_flisthead, fl); l != NULL; l = nxt) { |
271 |
✗✓ | 145 |
if (cvs_quit) |
272 |
fatal("received signal %d", sig_received); |
||
273 |
|||
274 |
145 |
cvs_log(LP_TRACE, "cvs_file_walklist: element '%s'", |
|
275 |
145 |
l->file_path); |
|
276 |
|||
277 |
✗✓ | 145 |
if ((f = basename(l->file_path)) == NULL) |
278 |
fatal("cvs_file_walklist: basename failed"); |
||
279 |
✗✓ | 145 |
if ((d = dirname(l->file_path)) == NULL) |
280 |
fatal("cvs_file_walklist: dirname failed"); |
||
281 |
|||
282 |
145 |
type = l->type; |
|
283 |
✓✓ | 145 |
if ((fd = open(l->file_path, O_RDONLY)) != -1) { |
284 |
✓✓ | 102 |
if (type == 0) { |
285 |
✗✓ | 30 |
if (fstat(fd, &st) == -1) { |
286 |
cvs_log(LP_ERRNO, "%s", l->file_path); |
||
287 |
(void)close(fd); |
||
288 |
goto next; |
||
289 |
} |
||
290 |
|||
291 |
✓✓ | 30 |
if (S_ISDIR(st.st_mode)) |
292 |
21 |
type = CVS_DIR; |
|
293 |
✓✗ | 9 |
else if (S_ISREG(st.st_mode)) |
294 |
type = CVS_FILE; |
||
295 |
else { |
||
296 |
cvs_log(LP_ERR, |
||
297 |
"ignoring bad file type for %s", |
||
298 |
l->file_path); |
||
299 |
(void)close(fd); |
||
300 |
goto next; |
||
301 |
} |
||
302 |
} |
||
303 |
✓✗ | 43 |
} else if (cvsroot_is_local()) { |
304 |
/* |
||
305 |
* During checkout -p, do not use any locally |
||
306 |
* available directories. |
||
307 |
*/ |
||
308 |
✓✓ | 43 |
if ((cmdp->cmd_flags & CVS_USE_WDIR) && |
309 |
✓✗ | 33 |
(cvs_cmdop != CVS_OP_CHECKOUT || !print_stdout)) |
310 |
✗✓ | 33 |
if (stat(d, &st) == -1) { |
311 |
cvs_log(LP_ERRNO, "%s", d); |
||
312 |
goto next; |
||
313 |
} |
||
314 |
|||
315 |
43 |
cvs_get_repository_path(d, repo, PATH_MAX); |
|
316 |
43 |
(void)xsnprintf(fpath, PATH_MAX, "%s/%s", |
|
317 |
repo, f); |
||
318 |
|||
319 |
✓✓ | 43 |
if ((fd = open(fpath, O_RDONLY)) == -1) { |
320 |
37 |
strlcat(fpath, RCS_FILE_EXT, PATH_MAX); |
|
321 |
37 |
fd = open(fpath, O_RDONLY); |
|
322 |
37 |
} |
|
323 |
|||
324 |
✓✓ | 43 |
if (fd != -1 && type == 0) { |
325 |
✗✓ | 2 |
if (fstat(fd, &st) == -1) |
326 |
fatal("cvs_file_walklist: %s: %s", |
||
327 |
fpath, strerror(errno)); |
||
328 |
|||
329 |
✗✓ | 2 |
if (S_ISDIR(st.st_mode)) |
330 |
type = CVS_DIR; |
||
331 |
✓✗ | 2 |
else if (S_ISREG(st.st_mode)) |
332 |
type = CVS_FILE; |
||
333 |
else { |
||
334 |
cvs_log(LP_ERR, |
||
335 |
"ignoring bad file type for %s", |
||
336 |
l->file_path); |
||
337 |
(void)close(fd); |
||
338 |
goto next; |
||
339 |
} |
||
340 |
|||
341 |
/* this file is not in our working copy yet */ |
||
342 |
2 |
(void)close(fd); |
|
343 |
fd = -1; |
||
344 |
✓✗ | 43 |
} else if (fd != -1) { |
345 |
41 |
close(fd); |
|
346 |
fd = -1; |
||
347 |
41 |
} |
|
348 |
} |
||
349 |
|||
350 |
145 |
cf = cvs_file_get_cf(d, f, l->file_path, fd, type, l->flags); |
|
351 |
✓✓ | 145 |
if (cf->file_type == CVS_DIR) { |
352 |
44 |
cvs_file_walkdir(cf, cr); |
|
353 |
44 |
} else { |
|
354 |
✓✓ | 101 |
if (l->flags & FILE_USER_SUPPLIED) { |
355 |
11 |
cvs_parse_tagfile(cf->file_wd, |
|
356 |
&cvs_directory_tag, NULL, NULL); |
||
357 |
|||
358 |
✗✓ | 22 |
if (cvs_directory_tag == NULL && |
359 |
11 |
cvs_specified_tag != NULL) |
|
360 |
cvs_directory_tag = |
||
361 |
xstrdup(cvs_specified_tag); |
||
362 |
|||
363 |
✓✗ | 11 |
if (cvsroot_is_local()) { |
364 |
22 |
cvs_get_repository_path(cf->file_wd, |
|
365 |
11 |
repo, PATH_MAX); |
|
366 |
11 |
cvs_repository_lock(repo, |
|
367 |
11 |
(cmdp->cmd_flags & CVS_LOCK_REPO)); |
|
368 |
11 |
} |
|
369 |
} |
||
370 |
|||
371 |
✓✗ | 101 |
if (cr->fileproc != NULL) |
372 |
101 |
cr->fileproc(cf); |
|
373 |
|||
374 |
✓✓ | 100 |
if (l->flags & FILE_USER_SUPPLIED) { |
375 |
✓✗✗✓ |
20 |
if (cvsroot_is_local() && |
376 |
10 |
(cmdp->cmd_flags & CVS_LOCK_REPO)) { |
|
377 |
cvs_repository_unlock(repo); |
||
378 |
} |
||
379 |
10 |
free(cvs_directory_tag); |
|
380 |
10 |
cvs_directory_tag = NULL; |
|
381 |
10 |
} |
|
382 |
} |
||
383 |
|||
384 |
144 |
cvs_file_free(cf); |
|
385 |
|||
386 |
next: |
||
387 |
144 |
nxt = RB_NEXT(cvs_flisthead, fl, l); |
|
388 |
} |
||
389 |
147 |
} |
|
390 |
|||
391 |
void |
||
392 |
cvs_file_walkdir(struct cvs_file *cf, struct cvs_recursion *cr) |
||
393 |
{ |
||
394 |
int l, type; |
||
395 |
FILE *fp; |
||
396 |
int nbytes; |
||
397 |
size_t bufsize; |
||
398 |
88 |
struct stat st; |
|
399 |
struct dirent *dp; |
||
400 |
struct cvs_ent *ent; |
||
401 |
struct cvs_ignpat *ip; |
||
402 |
struct cvs_ent_line *line; |
||
403 |
44 |
struct cvs_flisthead fl, dl; |
|
404 |
CVSENTRIES *entlist; |
||
405 |
44 |
char *buf, *ebuf, *cp, repo[PATH_MAX], fpath[PATH_MAX]; |
|
406 |
|||
407 |
44 |
cvs_log(LP_TRACE, "cvs_file_walkdir(%s)", cf->file_path); |
|
408 |
|||
409 |
✓✓ | 44 |
if (cr->enterdir != NULL) |
410 |
16 |
cr->enterdir(cf); |
|
411 |
|||
412 |
✓✗ | 44 |
if (cr->fileproc != NULL) |
413 |
44 |
cr->fileproc(cf); |
|
414 |
|||
415 |
✓✓ | 44 |
if (cf->file_status == FILE_SKIP) |
416 |
1 |
return; |
|
417 |
|||
418 |
/* |
||
419 |
* If this is a repository-only command, do not touch any |
||
420 |
* locally available directories or try to create them. |
||
421 |
*/ |
||
422 |
✓✓ | 43 |
if (!(cmdp->cmd_flags & CVS_USE_WDIR)) { |
423 |
6 |
RB_INIT(&fl); |
|
424 |
6 |
RB_INIT(&dl); |
|
425 |
6 |
goto walkrepo; |
|
426 |
} |
||
427 |
|||
428 |
/* |
||
429 |
* If we do not have an admin directory inside here, dont bother, |
||
430 |
* unless we are running export or import. |
||
431 |
*/ |
||
432 |
37 |
(void)xsnprintf(fpath, PATH_MAX, "%s/%s", cf->file_path, |
|
433 |
CVS_PATH_CVSDIR); |
||
434 |
|||
435 |
37 |
l = stat(fpath, &st); |
|
436 |
✓✓✗✓ |
72 |
if (cvs_cmdop != CVS_OP_EXPORT && cvs_cmdop != CVS_OP_IMPORT && |
437 |
✓✗✓✗ |
105 |
(l == -1 || (l == 0 && !S_ISDIR(st.st_mode)))) { |
438 |
return; |
||
439 |
} |
||
440 |
|||
441 |
37 |
cvs_parse_tagfile(cf->file_path, &cvs_directory_tag, NULL, NULL); |
|
442 |
|||
443 |
/* |
||
444 |
* check for a local .cvsignore file |
||
445 |
*/ |
||
446 |
37 |
(void)xsnprintf(fpath, PATH_MAX, "%s/.cvsignore", cf->file_path); |
|
447 |
|||
448 |
✗✓ | 37 |
if ((fp = fopen(fpath, "r")) != NULL) { |
449 |
while (fgets(fpath, PATH_MAX, fp) != NULL) { |
||
450 |
fpath[strcspn(fpath, "\n")] = '\0'; |
||
451 |
if (fpath[0] == '\0') |
||
452 |
continue; |
||
453 |
|||
454 |
cvs_file_ignore(fpath, &dir_ign_pats); |
||
455 |
} |
||
456 |
|||
457 |
(void)fclose(fp); |
||
458 |
} |
||
459 |
|||
460 |
✗✓ | 37 |
if (fstat(cf->fd, &st) == -1) |
461 |
fatal("cvs_file_walkdir: %s %s", cf->file_path, |
||
462 |
strerror(errno)); |
||
463 |
|||
464 |
✗✓ | 37 |
if ((uintmax_t)st.st_size > SIZE_MAX) |
465 |
fatal("cvs_file_walkdir: %s: file size too big", cf->file_name); |
||
466 |
|||
467 |
37 |
bufsize = (st.st_size > st.st_blksize) ? st.st_size : st.st_blksize; |
|
468 |
|||
469 |
37 |
buf = xmalloc(bufsize); |
|
470 |
37 |
RB_INIT(&fl); |
|
471 |
37 |
RB_INIT(&dl); |
|
472 |
|||
473 |
✓✓ | 111 |
while ((nbytes = getdents(cf->fd, buf, bufsize)) > 0) { |
474 |
37 |
ebuf = buf + nbytes; |
|
475 |
cp = buf; |
||
476 |
|||
477 |
✓✓ | 301 |
while (cp < ebuf) { |
478 |
168 |
dp = (struct dirent *)cp; |
|
479 |
✓✓✗✓ |
227 |
if (!strcmp(dp->d_name, ".") || |
480 |
✓✓ | 131 |
!strcmp(dp->d_name, "..") || |
481 |
✓✓ | 94 |
!strcmp(dp->d_name, CVS_PATH_CVSDIR) || |
482 |
59 |
dp->d_fileno == 0) { |
|
483 |
109 |
cp += dp->d_reclen; |
|
484 |
109 |
continue; |
|
485 |
} |
||
486 |
|||
487 |
59 |
(void)xsnprintf(fpath, PATH_MAX, "%s/%s", |
|
488 |
59 |
cf->file_path, dp->d_name); |
|
489 |
|||
490 |
✗✓ | 177 |
if (cvs_file_chkign(dp->d_name) && |
491 |
59 |
cvs_cmdop != CVS_OP_RLOG && |
|
492 |
59 |
cvs_cmdop != CVS_OP_RTAG) { |
|
493 |
if (cvs_cmdop == CVS_OP_IMPORT) |
||
494 |
cvs_import_ignored(fpath); |
||
495 |
cp += dp->d_reclen; |
||
496 |
continue; |
||
497 |
} |
||
498 |
|||
499 |
/* |
||
500 |
* nfs and afs will show d_type as DT_UNKNOWN |
||
501 |
* for files and/or directories so when we encounter |
||
502 |
* this we call lstat() on the path to be sure. |
||
503 |
*/ |
||
504 |
✗✓ | 59 |
if (dp->d_type == DT_UNKNOWN) { |
505 |
if (lstat(fpath, &st) == -1) |
||
506 |
fatal("'%s': %s", fpath, |
||
507 |
strerror(errno)); |
||
508 |
|||
509 |
switch (st.st_mode & S_IFMT) { |
||
510 |
case S_IFDIR: |
||
511 |
type = CVS_DIR; |
||
512 |
break; |
||
513 |
case S_IFREG: |
||
514 |
type = CVS_FILE; |
||
515 |
break; |
||
516 |
default: |
||
517 |
type = FILE_SKIP; |
||
518 |
break; |
||
519 |
} |
||
520 |
} else { |
||
521 |
✓✓✗ | 59 |
switch (dp->d_type) { |
522 |
case DT_DIR: |
||
523 |
type = CVS_DIR; |
||
524 |
14 |
break; |
|
525 |
case DT_REG: |
||
526 |
type = CVS_FILE; |
||
527 |
45 |
break; |
|
528 |
default: |
||
529 |
type = FILE_SKIP; |
||
530 |
break; |
||
531 |
} |
||
532 |
} |
||
533 |
|||
534 |
✗✓ | 59 |
if (type == FILE_SKIP) { |
535 |
if (verbosity > 1) { |
||
536 |
cvs_log(LP_NOTICE, "ignoring `%s'", |
||
537 |
dp->d_name); |
||
538 |
} |
||
539 |
cp += dp->d_reclen; |
||
540 |
continue; |
||
541 |
} |
||
542 |
|||
543 |
✓✓✗ | 59 |
switch (type) { |
544 |
case CVS_DIR: |
||
545 |
✓✗ | 14 |
if (cr->flags & CR_RECURSE_DIRS) |
546 |
14 |
cvs_file_get(fpath, 0, &dl, CVS_DIR); |
|
547 |
break; |
||
548 |
case CVS_FILE: |
||
549 |
45 |
cvs_file_get(fpath, 0, &fl, CVS_FILE); |
|
550 |
45 |
break; |
|
551 |
default: |
||
552 |
fatal("type %d unknown, shouldn't happen", |
||
553 |
type); |
||
554 |
} |
||
555 |
|||
556 |
59 |
cp += dp->d_reclen; |
|
557 |
} |
||
558 |
} |
||
559 |
|||
560 |
✗✓ | 37 |
if (nbytes == -1) |
561 |
fatal("cvs_file_walkdir: %s %s", cf->file_path, |
||
562 |
strerror(errno)); |
||
563 |
|||
564 |
37 |
free(buf); |
|
565 |
|||
566 |
✗✓ | 74 |
while ((ip = TAILQ_FIRST(&dir_ign_pats)) != NULL) { |
567 |
TAILQ_REMOVE(&dir_ign_pats, ip, ip_list); |
||
568 |
free(ip); |
||
569 |
} |
||
570 |
|||
571 |
37 |
entlist = cvs_ent_open(cf->file_path); |
|
572 |
✓✓ | 192 |
TAILQ_FOREACH(line, &(entlist->cef_ent), entries_list) { |
573 |
59 |
ent = cvs_ent_parse(line->buf); |
|
574 |
|||
575 |
118 |
(void)xsnprintf(fpath, PATH_MAX, "%s/%s", cf->file_path, |
|
576 |
59 |
ent->ce_name); |
|
577 |
|||
578 |
✗✓✗✗ |
59 |
if (!(cr->flags & CR_RECURSE_DIRS) && |
579 |
ent->ce_type == CVS_ENT_DIR) |
||
580 |
continue; |
||
581 |
✓✓ | 59 |
if (ent->ce_type == CVS_ENT_DIR) |
582 |
14 |
cvs_file_get(fpath, 0, &dl, CVS_DIR); |
|
583 |
✓✗ | 45 |
else if (ent->ce_type == CVS_ENT_FILE) |
584 |
45 |
cvs_file_get(fpath, 0, &fl, CVS_FILE); |
|
585 |
|||
586 |
59 |
cvs_ent_free(ent); |
|
587 |
59 |
} |
|
588 |
|||
589 |
walkrepo: |
||
590 |
✓✗ | 43 |
if (cvsroot_is_local()) { |
591 |
43 |
cvs_get_repository_path(cf->file_path, repo, PATH_MAX); |
|
592 |
43 |
cvs_repository_lock(repo, (cmdp->cmd_flags & CVS_LOCK_REPO)); |
|
593 |
43 |
} |
|
594 |
|||
595 |
✓✓ | 43 |
if (cr->flags & CR_REPO) { |
596 |
26 |
xsnprintf(fpath, sizeof(fpath), "%s/%s", cf->file_path, |
|
597 |
CVS_PATH_STATICENTRIES); |
||
598 |
|||
599 |
✓✓ | 26 |
if (!(cmdp->cmd_flags & CVS_USE_WDIR) || |
600 |
✓✗ | 20 |
stat(fpath, &st) == -1 || build_dirs == 1) |
601 |
52 |
cvs_repository_getdir(repo, cf->file_path, &fl, &dl, |
|
602 |
26 |
(cr->flags & CR_RECURSE_DIRS) ? |
|
603 |
REPOSITORY_DODIRS : 0); |
||
604 |
} |
||
605 |
|||
606 |
43 |
cvs_file_walklist(&fl, cr); |
|
607 |
43 |
cvs_file_freelist(&fl); |
|
608 |
|||
609 |
✓✗✓✓ |
86 |
if (cvsroot_is_local() && (cmdp->cmd_flags & CVS_LOCK_REPO)) |
610 |
10 |
cvs_repository_unlock(repo); |
|
611 |
|||
612 |
✓✓✓✗ |
51 |
if (cvs_directory_tag != NULL && cmdp->cmd_flags & CVS_USE_WDIR) { |
613 |
8 |
cvs_write_tagfile(cf->file_path, cvs_directory_tag, NULL); |
|
614 |
8 |
free(cvs_directory_tag); |
|
615 |
8 |
cvs_directory_tag = NULL; |
|
616 |
8 |
} |
|
617 |
|||
618 |
43 |
cvs_file_walklist(&dl, cr); |
|
619 |
43 |
cvs_file_freelist(&dl); |
|
620 |
|||
621 |
✓✓ | 43 |
if (cr->leavedir != NULL) |
622 |
1 |
cr->leavedir(cf); |
|
623 |
87 |
} |
|
624 |
|||
625 |
void |
||
626 |
cvs_file_freelist(struct cvs_flisthead *fl) |
||
627 |
{ |
||
628 |
struct cvs_filelist *f, *nxt; |
||
629 |
|||
630 |
✓✓ | 691 |
for (f = RB_MIN(cvs_flisthead, fl); f != NULL; f = nxt) { |
631 |
134 |
nxt = RB_NEXT(cvs_flisthead, fl, f); |
|
632 |
134 |
RB_REMOVE(cvs_flisthead, fl, f); |
|
633 |
134 |
free(f->file_path); |
|
634 |
134 |
free(f); |
|
635 |
} |
||
636 |
141 |
} |
|
637 |
|||
638 |
void |
||
639 |
cvs_file_classify(struct cvs_file *cf, const char *tag) |
||
640 |
{ |
||
641 |
size_t len; |
||
642 |
274 |
struct stat st; |
|
643 |
BUF *b1, *b2; |
||
644 |
int server_has_file, notag; |
||
645 |
int rflags, ismodified, rcsdead; |
||
646 |
CVSENTRIES *entlist = NULL; |
||
647 |
const char *state; |
||
648 |
137 |
char repo[PATH_MAX], rcsfile[PATH_MAX]; |
|
649 |
|||
650 |
274 |
cvs_log(LP_TRACE, "cvs_file_classify(%s, %s)", cf->file_path, |
|
651 |
137 |
(tag != NULL) ? tag : "none"); |
|
652 |
|||
653 |
✓✓ | 137 |
if (!strcmp(cf->file_path, ".")) { |
654 |
16 |
cf->file_status = FILE_UPTODATE; |
|
655 |
16 |
return; |
|
656 |
} |
||
657 |
|||
658 |
121 |
cvs_get_repository_path(cf->file_wd, repo, PATH_MAX); |
|
659 |
242 |
(void)xsnprintf(rcsfile, PATH_MAX, "%s/%s", |
|
660 |
121 |
repo, cf->file_name); |
|
661 |
|||
662 |
✓✓ | 121 |
if (cf->file_type == CVS_FILE) { |
663 |
95 |
len = strlcat(rcsfile, RCS_FILE_EXT, PATH_MAX); |
|
664 |
✗✓ | 95 |
if (len >= PATH_MAX) |
665 |
fatal("cvs_file_classify: truncation"); |
||
666 |
} |
||
667 |
|||
668 |
121 |
cf->file_rpath = xstrdup(rcsfile); |
|
669 |
|||
670 |
✓✓ | 121 |
if (cmdp->cmd_flags & CVS_USE_WDIR) { |
671 |
105 |
entlist = cvs_ent_open(cf->file_wd); |
|
672 |
105 |
cf->file_ent = cvs_ent_get(entlist, cf->file_name); |
|
673 |
105 |
} else |
|
674 |
cf->file_ent = NULL; |
||
675 |
|||
676 |
✓✓ | 121 |
if (cf->file_ent != NULL) { |
677 |
✓✓ | 69 |
if (cvs_specified_tag == NULL) |
678 |
58 |
tag = cf->file_ent->ce_tag; |
|
679 |
|||
680 |
✓✓ | 69 |
if (cf->file_flags & FILE_ON_DISK && |
681 |
✓✓ | 66 |
cf->file_ent->ce_type == CVS_ENT_FILE && |
682 |
✗✓ | 53 |
cf->file_type == CVS_DIR && tag != NULL) { |
683 |
cf->file_status = FILE_SKIP; |
||
684 |
return; |
||
685 |
} |
||
686 |
|||
687 |
✓✓ | 69 |
if (cf->file_flags & FILE_ON_DISK && |
688 |
✓✓ | 66 |
cf->file_ent->ce_type == CVS_ENT_DIR && |
689 |
✗✓ | 13 |
cf->file_type == CVS_FILE && tag != NULL) { |
690 |
cf->file_status = FILE_SKIP; |
||
691 |
return; |
||
692 |
} |
||
693 |
|||
694 |
✗✓✗✗ |
69 |
if (cf->file_flags & FILE_INSIDE_ATTIC && |
695 |
cf->file_ent->ce_type == CVS_ENT_DIR && |
||
696 |
cf->file_type != CVS_DIR) { |
||
697 |
cf->file_status = FILE_SKIP; |
||
698 |
return; |
||
699 |
} |
||
700 |
|||
701 |
✓✓✗✓ |
82 |
if (cf->file_flags & FILE_ON_DISK && |
702 |
✓✓ | 66 |
cf->file_ent->ce_type == CVS_ENT_DIR && |
703 |
13 |
cf->file_type != CVS_DIR) |
|
704 |
fatal("%s is supposed to be a directory, but it is not", |
||
705 |
cf->file_path); |
||
706 |
✓✓✗✓ |
122 |
if (cf->file_flags & FILE_ON_DISK && |
707 |
✓✓ | 66 |
cf->file_ent->ce_type == CVS_ENT_FILE && |
708 |
53 |
cf->file_type != CVS_FILE) |
|
709 |
fatal("%s is supposed to be a file, but it is not", |
||
710 |
cf->file_path); |
||
711 |
} |
||
712 |
|||
713 |
✓✓ | 121 |
if (cf->file_type == CVS_DIR) { |
714 |
✓✓ | 26 |
if (!(cmdp->cmd_flags & CVS_USE_WDIR)) |
715 |
cf->file_status = FILE_UPTODATE; |
||
716 |
✓✓✓✗ |
26 |
else if (cf->fd == -1 && stat(rcsfile, &st) != -1) |
717 |
6 |
cf->file_status = DIR_CREATE; |
|
718 |
28 |
else if (cf->file_ent != NULL || cvs_cmdop == CVS_OP_RLOG || |
|
719 |
14 |
cvs_cmdop == CVS_OP_RTAG) |
|
720 |
cf->file_status = FILE_UPTODATE; |
||
721 |
else |
||
722 |
cf->file_status = FILE_UNKNOWN; |
||
723 |
|||
724 |
26 |
return; |
|
725 |
} |
||
726 |
|||
727 |
rflags = RCS_READ; |
||
728 |
✗✗✓✗ ✗✗✓✓ |
131 |
switch (cvs_cmdop) { |
729 |
case CVS_OP_COMMIT: |
||
730 |
case CVS_OP_TAG: |
||
731 |
case CVS_OP_RTAG: |
||
732 |
rflags = RCS_WRITE; |
||
733 |
29 |
break; |
|
734 |
case CVS_OP_ADMIN: |
||
735 |
case CVS_OP_IMPORT: |
||
736 |
case CVS_OP_LOG: |
||
737 |
case CVS_OP_RLOG: |
||
738 |
rflags |= RCS_PARSE_FULLY; |
||
739 |
7 |
break; |
|
740 |
default: |
||
741 |
break; |
||
742 |
} |
||
743 |
|||
744 |
95 |
cf->repo_fd = open(cf->file_rpath, O_RDONLY); |
|
745 |
✓✓ | 95 |
if (cf->repo_fd != -1) { |
746 |
85 |
cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, rflags); |
|
747 |
✗✓ | 85 |
if (cf->file_rcs == NULL) |
748 |
fatal("cvs_file_classify: failed to parse RCS"); |
||
749 |
} else { |
||
750 |
10 |
(void)xsnprintf(rcsfile, PATH_MAX, "%s/%s/%s%s", |
|
751 |
10 |
repo, CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT); |
|
752 |
|||
753 |
10 |
cf->repo_fd = open(rcsfile, O_RDONLY); |
|
754 |
✗✓ | 10 |
if (cf->repo_fd != -1) { |
755 |
free(cf->file_rpath); |
||
756 |
cf->file_rpath = xstrdup(rcsfile); |
||
757 |
cf->file_rcs = rcs_open(cf->file_rpath, |
||
758 |
cf->repo_fd, rflags); |
||
759 |
if (cf->file_rcs == NULL) |
||
760 |
fatal("cvs_file_classify: failed to parse RCS"); |
||
761 |
cf->in_attic = 1; |
||
762 |
} else { |
||
763 |
10 |
cf->file_rcs = NULL; |
|
764 |
} |
||
765 |
} |
||
766 |
|||
767 |
notag = 0; |
||
768 |
95 |
cf->file_flags |= FILE_HAS_TAG; |
|
769 |
✓✓✓✗ |
129 |
if (tag != NULL && cf->file_rcs != NULL) { |
770 |
✓✓ | 68 |
if ((cf->file_rcsrev = rcs_translate_tag(tag, cf->file_rcs)) |
771 |
34 |
== NULL) { |
|
772 |
2 |
cf->file_rcsrev = rcs_translate_tag(NULL, cf->file_rcs); |
|
773 |
✓✗ | 2 |
if (cf->file_rcsrev != NULL) { |
774 |
notag = 1; |
||
775 |
2 |
cf->file_flags &= ~FILE_HAS_TAG; |
|
776 |
2 |
} |
|
777 |
} |
||
778 |
✓✓✗✓ |
96 |
} else if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL) { |
779 |
cf->file_rcsrev = rcsnum_alloc(); |
||
780 |
rcsnum_cpy(cf->file_ent->ce_rev, cf->file_rcsrev, 0); |
||
781 |
✓✓ | 61 |
} else if (cf->file_rcs != NULL) { |
782 |
51 |
cf->file_rcsrev = rcs_translate_tag(NULL, cf->file_rcs); |
|
783 |
51 |
} else { |
|
784 |
cf->file_rcsrev = NULL; |
||
785 |
} |
||
786 |
|||
787 |
ismodified = rcsdead = 0; |
||
788 |
✓✓✓✓ |
153 |
if ((cf->file_flags & FILE_ON_DISK) && cf->file_ent != NULL) { |
789 |
✗✓ | 53 |
if (fstat(cf->fd, &st) == -1) |
790 |
fatal("cvs_file_classify: %s", strerror(errno)); |
||
791 |
|||
792 |
✓✓ | 53 |
if (st.st_mtime != cf->file_ent->ce_mtime) |
793 |
14 |
ismodified = 1; |
|
794 |
} |
||
795 |
|||
796 |
server_has_file = 0; |
||
797 |
✗✓✗✗ ✗✗ |
95 |
if (cvs_server_active == 1 && cf->file_ent != NULL && |
798 |
cf->file_ent->ce_mtime == CVS_SERVER_UPTODATE) { |
||
799 |
server_has_file = 1; |
||
800 |
ismodified = 0; |
||
801 |
} |
||
802 |
|||
803 |
✓✗✓✓ |
190 |
if ((server_has_file == 1) || (cf->fd != -1)) |
804 |
58 |
cf->file_flags |= FILE_ON_DISK; |
|
805 |
|||
806 |
✓✓✓✗ |
103 |
if (ismodified == 1 && |
807 |
✓✗✓✓ |
28 |
(cf->file_flags & FILE_ON_DISK) && cf->file_rcs != NULL && |
808 |
✓✗✓✗ |
16 |
cf->file_ent != NULL && !RCSNUM_ISBRANCH(cf->file_ent->ce_rev) && |
809 |
8 |
cf->file_ent->ce_status != CVS_ENT_ADDED) { |
|
810 |
8 |
b1 = rcs_rev_getbuf(cf->file_rcs, cf->file_ent->ce_rev, 0); |
|
811 |
8 |
b2 = buf_load_fd(cf->fd); |
|
812 |
|||
813 |
✓✗ | 8 |
if (buf_differ(b1, b2)) |
814 |
8 |
ismodified = 1; |
|
815 |
else |
||
816 |
ismodified = 0; |
||
817 |
8 |
buf_free(b1); |
|
818 |
8 |
buf_free(b2); |
|
819 |
8 |
} |
|
820 |
|||
821 |
✓✓✓✗ ✓✗ |
265 |
if (cf->file_rcs != NULL && cf->file_rcsrev != NULL && |
822 |
85 |
!RCSNUM_ISBRANCH(cf->file_rcsrev)) { |
|
823 |
85 |
state = rcs_state_get(cf->file_rcs, cf->file_rcsrev); |
|
824 |
✗✓ | 85 |
if (state == NULL) |
825 |
fatal("failed to get state for HEAD for %s", |
||
826 |
cf->file_path); |
||
827 |
✗✓ | 85 |
if (!strcmp(state, RCS_STATE_DEAD)) |
828 |
rcsdead = 1; |
||
829 |
|||
830 |
✓✓✗✗ |
170 |
if (cvs_specified_date == -1 && cvs_directory_date == -1 && |
831 |
✗✓ | 136 |
tag == NULL && cf->in_attic && |
832 |
!RCSNUM_ISBRANCHREV(cf->file_rcsrev)) |
||
833 |
rcsdead = 1; |
||
834 |
|||
835 |
85 |
cf->file_rcs->rf_dead = rcsdead; |
|
836 |
85 |
} |
|
837 |
|||
838 |
/* |
||
839 |
* 10 Sin |
||
840 |
* 20 Goto hell |
||
841 |
* (I welcome you if-else hell) |
||
842 |
*/ |
||
843 |
✓✓ | 95 |
if (cf->file_ent == NULL) { |
844 |
✓✓ | 39 |
if (cf->file_rcs == NULL) { |
845 |
✗✓ | 4 |
if (!(cf->file_flags & FILE_ON_DISK)) { |
846 |
cvs_log(LP_NOTICE, |
||
847 |
"nothing known about '%s'", |
||
848 |
cf->file_path); |
||
849 |
} |
||
850 |
|||
851 |
cf->file_status = FILE_UNKNOWN; |
||
852 |
✓✗✓✓ |
74 |
} else if (rcsdead == 1 || !(cf->file_flags & FILE_HAS_TAG)) { |
853 |
✓✗ | 2 |
if (!(cf->file_flags & FILE_ON_DISK)) { |
854 |
cf->file_status = FILE_UPTODATE; |
||
855 |
✗✗ | 2 |
} else if (cvs_cmdop != CVS_OP_ADD) { |
856 |
cf->file_status = FILE_UNKNOWN; |
||
857 |
} |
||
858 |
✓✗✓✗ |
66 |
} else if (notag == 0 && cf->file_rcsrev != NULL) { |
859 |
cf->file_status = FILE_CHECKOUT; |
||
860 |
33 |
} else { |
|
861 |
cf->file_status = FILE_UPTODATE; |
||
862 |
} |
||
863 |
|||
864 |
39 |
return; |
|
865 |
} |
||
866 |
|||
867 |
✓✓✓✗ ✓ |
112 |
switch (cf->file_ent->ce_status) { |
868 |
case CVS_ENT_ADDED: |
||
869 |
✗✓ | 6 |
if (!(cf->file_flags & FILE_ON_DISK)) { |
870 |
if (cvs_cmdop != CVS_OP_REMOVE) { |
||
871 |
cvs_log(LP_NOTICE, |
||
872 |
"warning: new-born %s has disappeared", |
||
873 |
cf->file_path); |
||
874 |
} |
||
875 |
cf->file_status = FILE_REMOVE_ENTRY; |
||
876 |
✗✓✗✗ |
6 |
} else if (cf->file_rcs == NULL || rcsdead == 1 || |
877 |
!(cf->file_flags & FILE_HAS_TAG)) { |
||
878 |
cf->file_status = FILE_ADDED; |
||
879 |
6 |
} else { |
|
880 |
cvs_log(LP_NOTICE, |
||
881 |
"conflict: %s already created by others", |
||
882 |
cf->file_path); |
||
883 |
cf->file_status = FILE_CONFLICT; |
||
884 |
} |
||
885 |
6 |
break; |
|
886 |
case CVS_ENT_REMOVED: |
||
887 |
✗✓ | 2 |
if (cf->file_flags & FILE_ON_DISK) { |
888 |
cvs_log(LP_NOTICE, |
||
889 |
"%s should be removed but is still there", |
||
890 |
cf->file_path); |
||
891 |
cf->file_status = FILE_REMOVED; |
||
892 |
✓✗ | 2 |
} else if (cf->file_rcs == NULL || rcsdead == 1) { |
893 |
cf->file_status = FILE_REMOVE_ENTRY; |
||
894 |
} else { |
||
895 |
4 |
if (rcsnum_differ(cf->file_ent->ce_rev, |
|
896 |
✗✓ | 4 |
cf->file_rcsrev) && cvs_cmdop != CVS_OP_ADD) { |
897 |
cvs_log(LP_NOTICE, |
||
898 |
"conflict: removed %s was modified" |
||
899 |
" by a second party", |
||
900 |
cf->file_path); |
||
901 |
cf->file_status = FILE_CONFLICT; |
||
902 |
} else { |
||
903 |
cf->file_status = FILE_REMOVED; |
||
904 |
} |
||
905 |
} |
||
906 |
2 |
break; |
|
907 |
case CVS_ENT_REG: |
||
908 |
✓✗✓✗ |
144 |
if (cf->file_rcs == NULL || cf->file_rcsrev == NULL || |
909 |
✓✓✓✗ |
102 |
rcsdead == 1 || (reset_tag == 1 && cf->in_attic == 1) || |
910 |
✗✓ | 48 |
(notag == 1 && tag != NULL)) { |
911 |
if (!(cf->file_flags & FILE_ON_DISK)) { |
||
912 |
cvs_log(LP_NOTICE, |
||
913 |
"warning: %s's entry exists but" |
||
914 |
" is no longer in the repository," |
||
915 |
" removing entry", |
||
916 |
cf->file_path); |
||
917 |
cf->file_status = FILE_REMOVE_ENTRY; |
||
918 |
} else { |
||
919 |
if (ismodified) { |
||
920 |
cvs_log(LP_NOTICE, |
||
921 |
"conflict: %s is no longer " |
||
922 |
"in the repository but is " |
||
923 |
"locally modified", |
||
924 |
cf->file_path); |
||
925 |
if (cvs_cmdop == CVS_OP_COMMIT) |
||
926 |
cf->file_status = FILE_UNLINK; |
||
927 |
else |
||
928 |
cf->file_status = FILE_CONFLICT; |
||
929 |
} else if (cvs_cmdop != CVS_OP_IMPORT) { |
||
930 |
cvs_log(LP_NOTICE, |
||
931 |
"%s is no longer in the " |
||
932 |
"repository", |
||
933 |
cf->file_path); |
||
934 |
|||
935 |
cf->file_status = FILE_UNLINK; |
||
936 |
} |
||
937 |
} |
||
938 |
✗✓ | 48 |
} else if (cf->file_rcsrev == NULL) { |
939 |
cf->file_status = FILE_UNLINK; |
||
940 |
} else { |
||
941 |
✓✓ | 48 |
if (!(cf->file_flags & FILE_ON_DISK)) { |
942 |
✗✓ | 1 |
if (cvs_cmdop != CVS_OP_REMOVE) { |
943 |
cvs_log(LP_NOTICE, |
||
944 |
"warning: %s was lost", |
||
945 |
cf->file_path); |
||
946 |
} |
||
947 |
1 |
cf->file_status = FILE_LOST; |
|
948 |
1 |
} else { |
|
949 |
47 |
if (ismodified == 1) |
|
950 |
cf->file_status = FILE_MODIFIED; |
||
951 |
else |
||
952 |
cf->file_status = FILE_UPTODATE; |
||
953 |
✓✓ | 94 |
if (rcsnum_differ(cf->file_ent->ce_rev, |
954 |
47 |
cf->file_rcsrev)) { |
|
955 |
1 |
if (cf->file_status == FILE_MODIFIED) |
|
956 |
cf->file_status = FILE_MERGE; |
||
957 |
else |
||
958 |
cf->file_status = FILE_PATCH; |
||
959 |
1 |
} |
|
960 |
} |
||
961 |
} |
||
962 |
break; |
||
963 |
case CVS_ENT_UNKNOWN: |
||
964 |
if (cvs_server_active != 1) |
||
965 |
fatal("server-side questionable in local mode?"); |
||
966 |
cf->file_status = FILE_UNKNOWN; |
||
967 |
break; |
||
968 |
default: |
||
969 |
break; |
||
970 |
} |
||
971 |
193 |
} |
|
972 |
|||
973 |
void |
||
974 |
cvs_file_free(struct cvs_file *cf) |
||
975 |
{ |
||
976 |
288 |
free(cf->file_name); |
|
977 |
144 |
free(cf->file_wd); |
|
978 |
144 |
free(cf->file_path); |
|
979 |
144 |
free(cf->file_rcsrev); |
|
980 |
144 |
free(cf->file_rpath); |
|
981 |
✓✓ | 144 |
if (cf->file_ent != NULL) |
982 |
87 |
cvs_ent_free(cf->file_ent); |
|
983 |
✓✓ | 144 |
if (cf->file_rcs != NULL) |
984 |
88 |
rcs_close(cf->file_rcs); |
|
985 |
✓✓ | 144 |
if (cf->fd != -1) |
986 |
128 |
(void)close(cf->fd); |
|
987 |
✓✓ | 144 |
if (cf->repo_fd != -1) |
988 |
88 |
(void)close(cf->repo_fd); |
|
989 |
144 |
free(cf); |
|
990 |
144 |
} |
|
991 |
|||
992 |
int |
||
993 |
cvs_file_cmpname(const char *name1, const char *name2) |
||
994 |
{ |
||
995 |
✓✗ | 944 |
return (cvs_nocase == 0) ? (strcmp(name1, name2)) : |
996 |
(strcasecmp(name1, name2)); |
||
997 |
} |
||
998 |
|||
999 |
int |
||
1000 |
cvs_file_cmp(const char *file1, const char *file2) |
||
1001 |
{ |
||
1002 |
struct stat stb1, stb2; |
||
1003 |
int fd1, fd2, ret; |
||
1004 |
|||
1005 |
ret = 0; |
||
1006 |
|||
1007 |
if ((fd1 = open(file1, O_RDONLY|O_NOFOLLOW, 0)) == -1) |
||
1008 |
fatal("cvs_file_cmp: open: `%s': %s", file1, strerror(errno)); |
||
1009 |
if ((fd2 = open(file2, O_RDONLY|O_NOFOLLOW, 0)) == -1) |
||
1010 |
fatal("cvs_file_cmp: open: `%s': %s", file2, strerror(errno)); |
||
1011 |
|||
1012 |
if (fstat(fd1, &stb1) == -1) |
||
1013 |
fatal("cvs_file_cmp: `%s': %s", file1, strerror(errno)); |
||
1014 |
if (fstat(fd2, &stb2) == -1) |
||
1015 |
fatal("cvs_file_cmp: `%s': %s", file2, strerror(errno)); |
||
1016 |
|||
1017 |
if (stb1.st_size != stb2.st_size || |
||
1018 |
(stb1.st_mode & S_IFMT) != (stb2.st_mode & S_IFMT)) { |
||
1019 |
ret = 1; |
||
1020 |
goto out; |
||
1021 |
} |
||
1022 |
|||
1023 |
if (S_ISBLK(stb1.st_mode) || S_ISCHR(stb1.st_mode)) { |
||
1024 |
if (stb1.st_rdev != stb2.st_rdev) |
||
1025 |
ret = 1; |
||
1026 |
goto out; |
||
1027 |
} |
||
1028 |
|||
1029 |
if (S_ISREG(stb1.st_mode)) { |
||
1030 |
void *p1, *p2; |
||
1031 |
|||
1032 |
if ((uintmax_t)stb1.st_size > SIZE_MAX) { |
||
1033 |
ret = 1; |
||
1034 |
goto out; |
||
1035 |
} |
||
1036 |
|||
1037 |
if ((p1 = mmap(NULL, stb1.st_size, PROT_READ, |
||
1038 |
MAP_FILE, fd1, (off_t)0)) == MAP_FAILED) |
||
1039 |
fatal("cvs_file_cmp: mmap failed"); |
||
1040 |
|||
1041 |
if ((p2 = mmap(NULL, stb1.st_size, PROT_READ, |
||
1042 |
MAP_FILE, fd2, (off_t)0)) == MAP_FAILED) |
||
1043 |
fatal("cvs_file_cmp: mmap failed"); |
||
1044 |
|||
1045 |
madvise(p1, stb1.st_size, MADV_SEQUENTIAL); |
||
1046 |
madvise(p2, stb1.st_size, MADV_SEQUENTIAL); |
||
1047 |
|||
1048 |
ret = memcmp(p1, p2, stb1.st_size); |
||
1049 |
|||
1050 |
(void)munmap(p1, stb1.st_size); |
||
1051 |
(void)munmap(p2, stb1.st_size); |
||
1052 |
} |
||
1053 |
|||
1054 |
out: |
||
1055 |
(void)close(fd1); |
||
1056 |
(void)close(fd2); |
||
1057 |
|||
1058 |
return (ret); |
||
1059 |
} |
||
1060 |
|||
1061 |
int |
||
1062 |
cvs_file_copy(const char *from, const char *to) |
||
1063 |
{ |
||
1064 |
struct stat st; |
||
1065 |
struct timeval tv[2]; |
||
1066 |
time_t atime, mtime; |
||
1067 |
int src, dst, ret; |
||
1068 |
|||
1069 |
ret = 0; |
||
1070 |
|||
1071 |
cvs_log(LP_TRACE, "cvs_file_copy(%s,%s)", from, to); |
||
1072 |
|||
1073 |
if (cvs_noexec == 1) |
||
1074 |
return (0); |
||
1075 |
|||
1076 |
if ((src = open(from, O_RDONLY, 0)) == -1) |
||
1077 |
fatal("cvs_file_copy: open: `%s': %s", from, strerror(errno)); |
||
1078 |
|||
1079 |
if (fstat(src, &st) == -1) |
||
1080 |
fatal("cvs_file_copy: `%s': %s", from, strerror(errno)); |
||
1081 |
|||
1082 |
atime = st.st_atimespec.tv_sec; |
||
1083 |
mtime = st.st_mtimespec.tv_sec; |
||
1084 |
|||
1085 |
if (S_ISREG(st.st_mode)) { |
||
1086 |
char *p; |
||
1087 |
int saved_errno; |
||
1088 |
|||
1089 |
if ((uintmax_t)st.st_size > SIZE_MAX) { |
||
1090 |
ret = -1; |
||
1091 |
goto out; |
||
1092 |
} |
||
1093 |
|||
1094 |
if ((dst = open(to, O_CREAT|O_TRUNC|O_WRONLY, |
||
1095 |
st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) == -1) |
||
1096 |
fatal("cvs_file_copy: open `%s': %s", |
||
1097 |
to, strerror(errno)); |
||
1098 |
|||
1099 |
if ((p = mmap(NULL, st.st_size, PROT_READ, |
||
1100 |
MAP_FILE, src, (off_t)0)) == MAP_FAILED) { |
||
1101 |
saved_errno = errno; |
||
1102 |
(void)unlink(to); |
||
1103 |
fatal("cvs_file_copy: mmap: %s", strerror(saved_errno)); |
||
1104 |
} |
||
1105 |
|||
1106 |
madvise(p, st.st_size, MADV_SEQUENTIAL); |
||
1107 |
|||
1108 |
if (atomicio(vwrite, dst, p, st.st_size) != (size_t)st.st_size) { |
||
1109 |
saved_errno = errno; |
||
1110 |
(void)unlink(to); |
||
1111 |
fatal("cvs_file_copy: `%s': %s", from, |
||
1112 |
strerror(saved_errno)); |
||
1113 |
} |
||
1114 |
|||
1115 |
(void)munmap(p, st.st_size); |
||
1116 |
|||
1117 |
tv[0].tv_sec = atime; |
||
1118 |
tv[1].tv_sec = mtime; |
||
1119 |
|||
1120 |
if (futimes(dst, tv) == -1) { |
||
1121 |
saved_errno = errno; |
||
1122 |
(void)unlink(to); |
||
1123 |
fatal("cvs_file_copy: futimes: %s", |
||
1124 |
strerror(saved_errno)); |
||
1125 |
} |
||
1126 |
(void)close(dst); |
||
1127 |
} |
||
1128 |
out: |
||
1129 |
(void)close(src); |
||
1130 |
|||
1131 |
return (ret); |
||
1132 |
} |
||
1133 |
|||
1134 |
int |
||
1135 |
cvs_filelist_cmp(struct cvs_filelist *f1, struct cvs_filelist *f2) |
||
1136 |
{ |
||
1137 |
338 |
return (strcmp(f1->file_path, f2->file_path)); |
|
1138 |
} |
Generated by: GCOVR (Version 3.3) |