1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | #include <sys/stat.h> |
24 | |
25 | #include <dirent.h> |
26 | #include <err.h> |
27 | #include <errno.h> |
28 | #include <fcntl.h> |
29 | #include <fnmatch.h> |
30 | #include <paths.h> |
31 | #include <stdio.h> |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | #include <unistd.h> |
35 | #include <limits.h> |
36 | |
37 | #include "diff.h" |
38 | #include "xmalloc.h" |
39 | |
40 | static int selectfile(const struct dirent *); |
41 | static void diffit(struct dirent *, char *, size_t, char *, size_t, int); |
42 | |
43 | #define d_status d_type /* we need to store status for -l */ |
44 | |
45 | |
46 | |
47 | |
48 | void |
49 | diffdir(char *p1, char *p2, int flags) |
50 | { |
51 | struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL; |
52 | struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL; |
| 1 | 'edp2' declared without an initial value | |
|
53 | size_t dirlen1, dirlen2; |
54 | char path1[PATH_MAX], path2[PATH_MAX]; |
55 | int pos; |
56 | |
57 | dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1)); |
| 2 | | Assuming the condition is false | |
|
| |
58 | if (dirlen1 >= sizeof(path1) - 1) { |
| |
59 | warnc(ENAMETOOLONG, "%s", p1); |
60 | status |= 2; |
61 | return; |
62 | } |
63 | if (path1[dirlen1 - 1] != '/') { |
| 5 | | Assuming the condition is false | |
|
| |
64 | path1[dirlen1++] = '/'; |
65 | path1[dirlen1] = '\0'; |
66 | } |
67 | dirlen2 = strlcpy(path2, *p2 ? p2 : ".", sizeof(path2)); |
| 7 | | Assuming the condition is false | |
|
| |
68 | if (dirlen2 >= sizeof(path2) - 1) { |
| |
69 | warnc(ENAMETOOLONG, "%s", p2); |
70 | status |= 2; |
71 | return; |
72 | } |
73 | if (path2[dirlen2 - 1] != '/') { |
| 10 | | Assuming the condition is false | |
|
| |
74 | path2[dirlen2++] = '/'; |
75 | path2[dirlen2] = '\0'; |
76 | } |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | pos = scandir(path1, &dirp1, selectfile, alphasort); |
83 | if (pos == -1) { |
| 12 | | Assuming the condition is false | |
|
| |
84 | if (errno == ENOENT && (Nflag || Pflag)) { |
85 | pos = 0; |
86 | } else { |
87 | warn("%s", path1); |
88 | goto closem; |
89 | } |
90 | } |
91 | dp1 = dirp1; |
92 | edp1 = dirp1 + pos; |
93 | |
94 | pos = scandir(path2, &dirp2, selectfile, alphasort); |
95 | if (pos == -1) { |
| 14 | | Assuming the condition is true | |
|
| |
96 | if (errno == ENOENT && Nflag) { |
| 16 | | Assuming the condition is false | |
|
97 | pos = 0; |
98 | } else { |
99 | warn("%s", path2); |
100 | goto closem; |
| 17 | | Control jumps to line 154 | |
|
101 | } |
102 | } |
103 | dp2 = dirp2; |
104 | edp2 = dirp2 + pos; |
105 | |
106 | |
107 | |
108 | |
109 | if (start != NULL) { |
110 | while (dp1 != edp1 && strcmp((*dp1)->d_name, start) < 0) |
111 | dp1++; |
112 | while (dp2 != edp2 && strcmp((*dp2)->d_name, start) < 0) |
113 | dp2++; |
114 | } |
115 | |
116 | |
117 | |
118 | |
119 | while (dp1 != edp1 || dp2 != edp2) { |
120 | dent1 = dp1 != edp1 ? *dp1 : NULL; |
121 | dent2 = dp2 != edp2 ? *dp2 : NULL; |
122 | |
123 | pos = dent1 == NULL ? 1 : dent2 == NULL ? -1 : |
124 | strcmp(dent1->d_name, dent2->d_name); |
125 | if (pos == 0) { |
126 | |
127 | diffit(dent1, path1, dirlen1, path2, dirlen2, flags); |
128 | dp1++; |
129 | dp2++; |
130 | } else if (pos < 0) { |
131 | |
132 | if (Nflag) { |
133 | diffit(dent1, path1, dirlen1, path2, dirlen2, |
134 | flags); |
135 | } else { |
136 | print_only(path1, dirlen1, dent1->d_name); |
137 | status |= 1; |
138 | } |
139 | dp1++; |
140 | } else { |
141 | |
142 | if (Nflag || Pflag) { |
143 | diffit(dent2, path1, dirlen1, path2, dirlen2, |
144 | flags); |
145 | } else { |
146 | print_only(path2, dirlen2, dent2->d_name); |
147 | status |= 1; |
148 | } |
149 | dp2++; |
150 | } |
151 | } |
152 | |
153 | closem: |
154 | if (dirp1 != NULL) { |
| 18 | | Assuming 'dirp1' is equal to NULL | |
|
| |
155 | for (dp1 = dirp1; dp1 < edp1; dp1++) |
156 | free(*dp1); |
157 | free(dirp1); |
158 | } |
159 | if (dirp2 != NULL) { |
| 20 | | Assuming 'dirp2' is not equal to NULL | |
|
| |
160 | for (dp2 = dirp2; dp2 < edp2; dp2++) |
| 22 | | The right operand of '<' is a garbage value |
|
161 | free(*dp2); |
162 | free(dirp2); |
163 | } |
164 | } |
165 | |
166 | |
167 | |
168 | |
169 | static void |
170 | diffit(struct dirent *dp, char *path1, size_t plen1, char *path2, size_t plen2, |
171 | int flags) |
172 | { |
173 | flags |= D_HEADER; |
174 | strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1); |
175 | if (stat(path1, &stb1) != 0) { |
176 | if (!(Nflag || Pflag) || errno != ENOENT) { |
177 | warn("%s", path1); |
178 | return; |
179 | } |
180 | flags |= D_EMPTY1; |
181 | memset(&stb1, 0, sizeof(stb1)); |
182 | } |
183 | |
184 | strlcpy(path2 + plen2, dp->d_name, PATH_MAX - plen2); |
185 | if (stat(path2, &stb2) != 0) { |
186 | if (!Nflag || errno != ENOENT) { |
187 | warn("%s", path2); |
188 | return; |
189 | } |
190 | flags |= D_EMPTY2; |
191 | memset(&stb2, 0, sizeof(stb2)); |
192 | stb2.st_mode = stb1.st_mode; |
193 | } |
194 | if (stb1.st_mode == 0) |
195 | stb1.st_mode = stb2.st_mode; |
196 | |
197 | if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) { |
198 | if (rflag) |
199 | diffdir(path1, path2, flags); |
200 | else |
201 | printf("Common subdirectories: %s and %s\n", |
202 | path1, path2); |
203 | return; |
204 | } |
205 | if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode)) |
206 | dp->d_status = D_SKIPPED1; |
207 | else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode)) |
208 | dp->d_status = D_SKIPPED2; |
209 | else |
210 | dp->d_status = diffreg(path1, path2, flags); |
211 | print_status(dp->d_status, path1, path2, ""); |
212 | } |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | static int |
219 | selectfile(const struct dirent *dp) |
220 | { |
221 | struct excludes *excl; |
222 | |
223 | if (dp->d_fileno == 0) |
224 | return (0); |
225 | |
226 | |
227 | if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || |
228 | (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) |
229 | return (0); |
230 | |
231 | |
232 | for (excl = excludes_list; excl != NULL; excl = excl->next) |
233 | if (fnmatch(excl->pattern, dp->d_name, FNM_PATHNAME) == 0) |
234 | return (0); |
235 | |
236 | return (1); |
237 | } |