forked from h2oai/jdupes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchecks.c
More file actions
158 lines (133 loc) · 4.95 KB
/
checks.c
File metadata and controls
158 lines (133 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* jdupes file check functions
* This file is part of jdupes; see jdupes.c for license information */
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <inttypes.h>
#include <libjodycode.h>
#include "likely_unlikely.h"
#ifndef NO_EXTFILTER
#include "extfilter.h"
#endif
#include "filestat.h"
#include "jdupes.h"
/***** End definitions, begin code *****/
/***** Add new functions here *****/
/* Check a pair of files for match exclusion conditions
* Returns:
* 0 if all condition checks pass
* -1 or 1 on compare result less/more
* -2 on an absolute exclusion condition met
* 2 on an absolute match condition met
* -3 on exclusion due to isolation
* -4 on exclusion due to same filesystem
* -5 on exclusion due to permissions */
int check_conditions(const file_t * const restrict file1, const file_t * const restrict file2)
{
if (unlikely(file1 == NULL || file2 == NULL || file1->d_name == NULL || file2->d_name == NULL)) jc_nullptr("check_conditions()");
LOUD(fprintf(stderr, "check_conditions('%s', '%s')\n", file1->d_name, file2->d_name);)
/* Exclude files that are not the same size */
if (file1->size > file2->size) {
LOUD(fprintf(stderr, "check_conditions: no match: size of file1 > file2 (%" PRIdMAX " > %" PRIdMAX ")\n",
(intmax_t)file1->size, (intmax_t)file2->size));
return -1;
}
if (file1->size < file2->size) {
LOUD(fprintf(stderr, "check_conditions: no match: size of file1 < file2 (%" PRIdMAX " < %"PRIdMAX ")\n",
(intmax_t)file1->size, (intmax_t)file2->size));
return 1;
}
#ifndef NO_USER_ORDER
/* Exclude based on -I/--isolate */
if (ISFLAG(flags, F_ISOLATE) && (file1->user_order == file2->user_order)) {
LOUD(fprintf(stderr, "check_conditions: files ignored: parameter isolation\n"));
return -3;
}
#endif /* NO_USER_ORDER */
/* Exclude based on -1/--one-file-system */
if (ISFLAG(flags, F_ONEFS) && (file1->device != file2->device)) {
LOUD(fprintf(stderr, "check_conditions: files ignored: not on same filesystem\n"));
return -4;
}
/* Exclude files by permissions if requested */
if (ISFLAG(flags, F_PERMISSIONS) &&
(file1->mode != file2->mode
#ifndef NO_PERMS
|| file1->uid != file2->uid
|| file1->gid != file2->gid
#endif
)) {
return -5;
LOUD(fprintf(stderr, "check_conditions: no match: permissions/ownership differ (-p on)\n"));
}
/* Hard link and symlink + '-s' check */
#ifndef NO_HARDLINKS
if ((file1->inode == file2->inode) && (file1->device == file2->device)) {
if (ISFLAG(flags, F_CONSIDERHARDLINKS)) {
LOUD(fprintf(stderr, "check_conditions: files match: hard/soft linked (-H on)\n"));
return 2;
} else {
LOUD(fprintf(stderr, "check_conditions: files ignored: hard/soft linked (-H off)\n"));
return -2;
}
}
#endif
/* Fall through: all checks passed */
LOUD(fprintf(stderr, "check_conditions: all condition checks passed\n"));
return 0;
}
/* Check for exclusion conditions for a single file (1 = fail) */
int check_singlefile(file_t * const restrict newfile)
{
char * restrict tp = tempname;
if (unlikely(newfile == NULL)) jc_nullptr("check_singlefile()");
LOUD(fprintf(stderr, "check_singlefile: checking '%s'\n", newfile->d_name));
/* Exclude hidden files if requested */
if (likely(ISFLAG(flags, F_EXCLUDEHIDDEN))) {
if (unlikely(newfile->d_name == NULL)) jc_nullptr("check_singlefile newfile->d_name");
strcpy(tp, newfile->d_name);
tp = basename(tp);
if (tp[0] == '.' && jc_streq(tp, ".") && jc_streq(tp, "..")) {
LOUD(fprintf(stderr, "check_singlefile: excluding hidden file (-A on)\n"));
return 1;
}
}
/* Get file information and check for validity */
const int i = getfilestats(newfile);
if (i || newfile->size == -1) {
LOUD(fprintf(stderr, "check_singlefile: excluding due to bad stat()\n"));
return 1;
}
if (!JC_S_ISREG(newfile->mode) && !JC_S_ISDIR(newfile->mode)) {
LOUD(fprintf(stderr, "check_singlefile: excluding non-regular file\n"));
return 1;
}
if (!JC_S_ISDIR(newfile->mode)) {
/* Exclude zero-length files if requested */
if (newfile->size == 0 && !ISFLAG(flags, F_INCLUDEEMPTY)) {
LOUD(fprintf(stderr, "check_singlefile: excluding zero-length empty file (-z not set)\n"));
return 1;
}
#ifndef NO_EXTFILTER
if (extfilter_exclude(newfile)) {
LOUD(fprintf(stderr, "check_singlefile: excluding based on an extfilter option\n"));
return 1;
}
#endif /* NO_EXTFILTER */
}
#ifdef ON_WINDOWS
/* Windows has a 1023 (+1) hard link limit. If we're hard linking,
* ignore all files that have hit this limit */
#ifndef NO_HARDLINKS
if (ISFLAG(a_flags, FA_HARDLINKFILES) && newfile->nlink >= 1024) {
#ifdef DEBUG
hll_exclude++;
#endif
LOUD(fprintf(stderr, "check_singlefile: excluding due to Windows 1024 hard link limit\n"));
return 1;
}
#endif /* NO_HARDLINKS */
#endif /* ON_WINDOWS */
LOUD(fprintf(stderr, "check_singlefile: all checks passed\n"));
return 0;
}