Annotation of embedtools/src/dircmp.c, revision 1.1.2.5
1.1.2.1 misho 1: #include "global.h"
2: #include "dircmp.h"
3:
4:
5: extern char compiled[], compiledby[], compilehost[];
1.1.2.2 misho 6: char lm;
1.1.2.1 misho 7:
8:
9: static void
10: Usage()
11: {
12: printf( "-= DirCmp =- Tool for compare directories and show differences\n"
13: "=== %s === %s@%s ===\n\n"
1.1.2.4 misho 14: " Syntax: dircmp [options] <dir> [<cmp_dir>]\n\n"
15: "\t-l\t\tLong directory output ...\n"
16: "\t-s\t\tCompare dir from stdin list\n"
17: "\t-o <filename>\tOutput diff to filename\n"
1.1.2.1 misho 18: "\n", compiled, compiledby, compilehost);
19: }
20:
21: int
22: calcDir(const char *csDir, u_char **md)
23: {
24: DIR *dir;
25: struct dirent d, *pd;
26: MD5_CTX ctx;
27:
28: *md = malloc(MD5_DIGEST_LENGTH);
29: if (!*md) {
30: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
31: return -1;
32: } else
33: memset(*md, 0, MD5_DIGEST_LENGTH);
34:
35: dir = opendir(csDir);
36: if (!dir) {
37: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
38: free(*md);
39: return -1;
40: }
41:
42: MD5_Init(&ctx);
43: while (!readdir_r(dir, &d, &pd) && pd) {
44: if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
45: continue;
46: MD5_Update(&ctx, d.d_name, d.d_namlen);
47: }
48: MD5_Final(*md, &ctx);
49:
50: closedir(dir);
51: return 0;
52: }
53:
54: // -------------------------------------------------------------------
55:
56: static int
57: func_comp(struct tagDirName const *d1, struct tagDirName const *d2)
58: {
59: return d1->tag - d2->tag;
60: }
61:
1.1.2.5 ! misho 62: static struct tagDirName *
! 63: find_tag(int const * __restrict tags, struct tagDirName const * __restrict l, u_short t, u_int hash)
! 64: {
! 65: struct tagDirName *find = NULL;
! 66: register int i;
! 67:
! 68: // search in index tags
! 69: if (tags[t] != -1 && l[tags[t]].tag == t) {
! 70: // search in sorted hashes
! 71: for (i = 0; l[tags[t] + i].tag == t; i++)
! 72: if (l[tags[t] + i].hash == hash) {
! 73: // finded & marked for delete!
! 74: find = (struct tagDirName*) &l[tags[t] + i];
! 75: find->ch = '*';
! 76: break;
! 77: }
! 78: }
! 79:
! 80: return find;
! 81: }
! 82:
1.1.2.1 misho 83: int
84: cmpDir(const char *csDir1, const char *csDir2, struct tagDirName **list)
85: {
86: struct tagDirName *l, *find;
87: int n, cx;
88: DIR *dir;
89: struct dirent d, *pd;
90: int tags[USHRT_MAX];
91: register int i;
92: u_short t;
93: u_int hash;
94: struct stat sb;
1.1.2.5 ! misho 95: char szLine[MAX_STR], szStr[MAX_STR], szType[MAX_STR], *str, *pbrk;
! 96: FILE *f = stdin;
1.1.2.1 misho 97:
1.1.2.4 misho 98: if (!csDir1 || !list)
1.1.2.1 misho 99: return -1;
100: else
101: memset(tags, -1, sizeof tags);
102:
103: l = malloc(sizeof(struct tagDirName));
104: if (!l) {
105: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
106: return -1;
107: } else {
108: n = 0;
109: memset(l, 0, sizeof(struct tagDirName));
110: }
111:
1.1.2.3 misho 112: if (chdir(csDir1) == -1) {
113: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
114: free(l);
115: return -1;
116: }
117: dir = opendir(".");
1.1.2.1 misho 118: if (!dir) {
119: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
120: free(l);
121: return -1;
122: }
123: while (!readdir_r(dir, &d, &pd) && pd) {
124: if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
125: continue;
126:
127: l = realloc(l, sizeof(struct tagDirName) * (n + 2));
128: if (!l) {
129: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
130: closedir(dir);
131: return -1;
132: } else
133: memset(&l[n + 1], 0, sizeof(struct tagDirName));
134:
135: l[n].ch = '<';
136: l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
137: l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen);
138: strlcpy(l[n].name, d.d_name, MAXPATHLEN);
1.1.2.4 misho 139: if (lm & 1) {
1.1.2.1 misho 140: if (lstat(d.d_name, &sb) != -1) {
141: memset(szStr, 0, MAX_STR);
1.1.2.3 misho 142: strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
1.1.2.1 misho 143: switch (d.d_type) {
144: case DT_FIFO:
145: strlcpy(szType, "fifo", MAX_STR);
146: break;
147: case DT_CHR:
148: strlcpy(szType, "char", MAX_STR);
149: break;
150: case DT_DIR:
151: strlcpy(szType, "dir", MAX_STR);
152: break;
153: case DT_BLK:
154: strlcpy(szType, "block", MAX_STR);
155: break;
156: case DT_REG:
157: strlcpy(szType, "file", MAX_STR);
158: break;
159: case DT_LNK:
160: strlcpy(szType, "link", MAX_STR);
161: break;
162: case DT_SOCK:
163: strlcpy(szType, "socket", MAX_STR);
164: break;
165: case DT_WHT:
166: strlcpy(szType, "wht", MAX_STR);
167: break;
168: case DT_UNKNOWN:
169: default:
170: strlcpy(szType, "unknown", MAX_STR);
171: break;
172: }
1.1.2.3 misho 173: snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s",
174: szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid,
175: sb.st_mode & 0x1fff, sb.st_size, szStr);
1.1.2.1 misho 176: }
177: }
178:
179: n++;
180: }
181: closedir(dir);
182: qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp);
183: for (i = n - 1; i > -1; i--)
184: tags[l[i].tag] = i;
185:
1.1.2.4 misho 186: // if only 1 dir supplied and output filename is set, goto end
187: if (lm & 2 && !csDir2)
188: goto end;
1.1.2.5 ! misho 189: //
! 190: if (lm & 4) {
! 191: if (strcmp(csDir2, "-")) {
! 192: f = fopen(csDir2, "r");
! 193: if (!f) {
! 194: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
! 195: free(l);
! 196: return -1;
! 197: }
! 198: }
! 199: while (fgets(szLine, MAX_STR, f)) {
! 200: if (!*szLine || *szLine == '#')
! 201: continue;
! 202:
! 203: str = strtok_r(szLine, " \t", &pbrk);
! 204: if (!str)
! 205: continue;
! 206: str = strtok_r(NULL, " \t", &pbrk);
! 207: if (!str)
! 208: continue;
! 209: else {
! 210: i = strlen(str);
! 211: t = crcFletcher16((u_short*) str, i / 2 + i % 2);
! 212: hash = crcAdler((u_char*) str, i);
! 213: }
! 214:
! 215: find = find_tag(tags, l, t, hash);
! 216: // element not find in dir1, added
! 217: if (!find) {
! 218: l = realloc(l, sizeof(struct tagDirName) * (n + 2));
! 219: if (!l) {
! 220: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
! 221: closedir(dir);
! 222: return -1;
! 223: } else
! 224: memset(&l[n + 1], 0, sizeof(struct tagDirName));
! 225:
! 226: l[n].ch = '>';
! 227: l[n].tag = t;
! 228: l[n].hash = hash;
! 229: strlcpy(l[n].name, str, MAXPATHLEN);
! 230: if (lm & 1 && (str = strtok_r(NULL, "\r\n", &pbrk)))
! 231: strlcpy(l[n].extra, str, MAX_STR);
! 232:
! 233: n++;
! 234: }
! 235: }
! 236: if (strcmp(csDir2, "-"))
! 237: fclose(f);
! 238:
! 239: goto delel;
! 240: }
1.1.2.4 misho 241: ////
242:
1.1.2.1 misho 243: // open dir 2 for diff ...
1.1.2.3 misho 244: if (chdir(csDir2) == -1) {
245: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
246: free(l);
247: return -1;
248: }
249: dir = opendir(".");
1.1.2.1 misho 250: if (!dir) {
251: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
252: free(l);
253: return -1;
254: }
255: while (!readdir_r(dir, &d, &pd) && pd) {
256: if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
257: continue;
258: else {
259: t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
260: hash = crcAdler((u_char*) d.d_name, d.d_namlen);
261: }
262:
1.1.2.5 ! misho 263: find = find_tag(tags, l, t, hash);
1.1.2.1 misho 264: // element not find in dir1, added
265: if (!find) {
266: l = realloc(l, sizeof(struct tagDirName) * (n + 2));
267: if (!l) {
268: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
269: closedir(dir);
270: return -1;
271: } else
272: memset(&l[n + 1], 0, sizeof(struct tagDirName));
273:
274: l[n].ch = '>';
275: l[n].tag = t;
276: l[n].hash = hash;
277: strlcpy(l[n].name, d.d_name, MAXPATHLEN);
1.1.2.4 misho 278: if (lm & 1) {
1.1.2.2 misho 279: if (lstat(d.d_name, &sb) != -1) {
280: memset(szStr, 0, MAX_STR);
1.1.2.3 misho 281: strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
1.1.2.2 misho 282: switch (d.d_type) {
283: case DT_FIFO:
284: strlcpy(szType, "fifo", MAX_STR);
285: break;
286: case DT_CHR:
287: strlcpy(szType, "char", MAX_STR);
288: break;
289: case DT_DIR:
290: strlcpy(szType, "dir", MAX_STR);
291: break;
292: case DT_BLK:
293: strlcpy(szType, "block", MAX_STR);
294: break;
295: case DT_REG:
296: strlcpy(szType, "file", MAX_STR);
297: break;
298: case DT_LNK:
299: strlcpy(szType, "link", MAX_STR);
300: break;
301: case DT_SOCK:
302: strlcpy(szType, "socket", MAX_STR);
303: break;
304: case DT_WHT:
305: strlcpy(szType, "wht", MAX_STR);
306: break;
307: case DT_UNKNOWN:
308: default:
309: strlcpy(szType, "unknown", MAX_STR);
310: break;
311: }
1.1.2.3 misho 312: snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s",
313: szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid,
314: sb.st_mode & 0x1fff, sb.st_size, szStr);
1.1.2.2 misho 315: }
316: }
1.1.2.1 misho 317:
318: n++;
319: }
320: }
321: closedir(dir);
1.1.2.5 ! misho 322: delel:
1.1.2.1 misho 323: // delete equal elemets !!!
324: for (i = cx = 0; i < n; i++)
325: if (l[i].ch == '*') {
326: memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName));
327: cx++;
328: i--;
329: }
330: n -= cx;
1.1.2.4 misho 331: end:
1.1.2.1 misho 332: *list = l;
333: return n;
334: }
335:
336: // ----------------------------------------------------
337:
338: int
339: main(int argc, char **argv)
340: {
1.1.2.4 misho 341: u_char *md[2] = { NULL, NULL };
342: char ch, szFName[MAXPATHLEN];
1.1.2.1 misho 343: struct tagDirName *list;
344: register int i;
1.1.2.4 misho 345: FILE *f = stdout;
1.1.2.1 misho 346:
1.1.2.4 misho 347: while ((ch = getopt(argc, argv, "hlo:s")) != -1)
1.1.2.1 misho 348: switch (ch) {
1.1.2.4 misho 349: case 'o':
350: lm |= 2;
351: strlcpy(szFName, optarg, MAXPATHLEN);
352: break;
353: case 's':
354: lm |= 4;
355: break;
1.1.2.1 misho 356: case 'l':
1.1.2.4 misho 357: lm |= 1;
1.1.2.1 misho 358: break;
359: case 'h':
360: default:
361: Usage();
362: return 127;
363: }
364: argc -= optind;
365: argv += optind;
366:
1.1.2.5 ! misho 367: if (!argc || (!(lm & 2) && argc < 2)) {
1.1.2.1 misho 368: Usage();
369: return 127;
370: }
371: // check for general differences
372: if (calcDir(argv[0], &md[0]) == -1)
373: return 127;
1.1.2.4 misho 374: if (argc > 1 && lm < 4) {
375: if (calcDir(argv[1], &md[1]) == -1) {
376: free(md[0]);
377: return 127;
378: }
379: if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH)) {
380: free(md[0]);
381: if (md[1])
382: free(md[1]);
383: printf("Directory %s == %s\n\n", argv[0], argv[1]);
384: return 0;
385: } else {
386: free(md[0]);
387: if (md[1])
388: free(md[1]);
389: printf("Directory %s != %s ::\n\n", argv[0], argv[1]);
390: }
1.1.2.1 misho 391: }
392:
1.1.2.5 ! misho 393: if (cmpDir(argv[0], argc > 1 ? argv[1] : NULL, &list) == -1)
1.1.2.1 misho 394: return 127;
395:
1.1.2.5 ! misho 396: if (lm & 2 && strcmp(szFName, "-")) {
1.1.2.4 misho 397: f = fopen(szFName, "w");
398: if (!f) {
399: printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
400: if (list)
401: free(list);
402: return 0;
403: }
404: }
1.1.2.1 misho 405: for (i = 0; list[i].ch; i++)
1.1.2.4 misho 406: fprintf(f, "%c %s %s\n", list[i].ch, list[i].name, list[i].extra);
407: if (lm & 2)
408: fclose(f);
1.1.2.1 misho 409:
1.1.2.4 misho 410: printf("\nTotal count of elements = %d\n", i);
1.1.2.1 misho 411: free(list);
412: return 1;
413: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>