--- embedtools/src/dircmp.c 2010/07/13 09:35:01 1.1.2.1 +++ embedtools/src/dircmp.c 2010/07/13 15:21:04 1.1.2.7 @@ -1,9 +1,15 @@ +/************************************************************************* + * (C) 2010 AITNET - Sofia/Bulgaria - + * by Michael Pounov + * + * $Author: misho $ + * $Id: dircmp.c,v 1.1.2.7 2010/07/13 15:21:04 misho Exp $ + * + *************************************************************************/ #include "global.h" -#include "dircmp.h" extern char compiled[], compiledby[], compilehost[]; -char l; static void @@ -11,222 +17,30 @@ Usage() { printf( "-= DirCmp =- Tool for compare directories and show differences\n" "=== %s === %s@%s ===\n\n" - " Syntax: dircmp [options] \n\n" - "\t-l\t\tLong directory output ..." + " Syntax: dircmp [options] []\n\n" + "\t-l\t\tLong directory output ...\n" + "\t-o \tOutput diff to filename\n" "\n", compiled, compiledby, compilehost); } int -calcDir(const char *csDir, u_char **md) -{ - DIR *dir; - struct dirent d, *pd; - MD5_CTX ctx; - - *md = malloc(MD5_DIGEST_LENGTH); - if (!*md) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - return -1; - } else - memset(*md, 0, MD5_DIGEST_LENGTH); - - dir = opendir(csDir); - if (!dir) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - free(*md); - return -1; - } - - MD5_Init(&ctx); - while (!readdir_r(dir, &d, &pd) && pd) { - if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, ".."))) - continue; - MD5_Update(&ctx, d.d_name, d.d_namlen); - } - MD5_Final(*md, &ctx); - - closedir(dir); - return 0; -} - -// ------------------------------------------------------------------- - -static int -func_comp(struct tagDirName const *d1, struct tagDirName const *d2) -{ - return d1->tag - d2->tag; -} - -int -cmpDir(const char *csDir1, const char *csDir2, struct tagDirName **list) -{ - struct tagDirName *l, *find; - int n, cx; - DIR *dir; - struct dirent d, *pd; - int tags[USHRT_MAX]; - register int i; - u_short t; - u_int hash; - struct stat sb; - char szStr[MAX_STR], szType[MAX_STR]; - - if (!csDir1 || !csDir2 || !list) - return -1; - else - memset(tags, -1, sizeof tags); - - l = malloc(sizeof(struct tagDirName)); - if (!l) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - return -1; - } else { - n = 0; - memset(l, 0, sizeof(struct tagDirName)); - } - - dir = opendir(csDir1); - if (!dir) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - free(l); - return -1; - } - while (!readdir_r(dir, &d, &pd) && pd) { - if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, ".."))) - continue; - - l = realloc(l, sizeof(struct tagDirName) * (n + 2)); - if (!l) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - closedir(dir); - return -1; - } else - memset(&l[n + 1], 0, sizeof(struct tagDirName)); - - l[n].ch = '<'; - l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2); - l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen); - strlcpy(l[n].name, d.d_name, MAXPATHLEN); - if (l) { - if (lstat(d.d_name, &sb) != -1) { - memset(szStr, 0, MAX_STR); - strftime(szStr, MAX_STR, "%y-%m-%d %H:%M:%S", localtime(&sb.st_mtim)); - switch (d.d_type) { - case DT_FIFO: - strlcpy(szType, "fifo", MAX_STR); - break; - case DT_CHR: - strlcpy(szType, "char", MAX_STR); - break; - case DT_DIR: - strlcpy(szType, "dir", MAX_STR); - break; - case DT_BLK: - strlcpy(szType, "block", MAX_STR); - break; - case DT_REG: - strlcpy(szType, "file", MAX_STR); - break; - case DT_LNK: - strlcpy(szType, "link", MAX_STR); - break; - case DT_SOCK: - strlcpy(szType, "socket", MAX_STR); - break; - case DT_WHT: - strlcpy(szType, "wht", MAX_STR); - break; - case DT_UNKNOWN: - default: - strlcpy(szType, "unknown", MAX_STR); - break; - } - snprintf(l[n].extra, MAX_STR, "%s links=%d %d:%d perm=0%o size=%llu %s\n", szType, - sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_mode, sb.st_size, szStr); - } - } - - n++; - } - closedir(dir); - qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp); - for (i = n - 1; i > -1; i--) - tags[l[i].tag] = i; - - // open dir 2 for diff ... - dir = opendir(csDir2); - if (!dir) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - free(l); - return -1; - } - while (!readdir_r(dir, &d, &pd) && pd) { - if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, ".."))) - continue; - else { - t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2); - hash = crcAdler((u_char*) d.d_name, d.d_namlen); - } - - // search in index tags - find = NULL; - if (tags[t] != -1 && l[tags[t]].tag == t) { - // search in sorted hashes - for (i = 0; l[tags[t] + i].tag == t; i++) - if (l[tags[t] + i].hash == hash) { - // finded & marked for delete! - find = &l[tags[t] + i]; - find->ch = '*'; - break; - } - } - // element not find in dir1, added - if (!find) { - l = realloc(l, sizeof(struct tagDirName) * (n + 2)); - if (!l) { - printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); - closedir(dir); - return -1; - } else - memset(&l[n + 1], 0, sizeof(struct tagDirName)); - - l[n].ch = '>'; - l[n].tag = t; - l[n].hash = hash; - strlcpy(l[n].name, d.d_name, MAXPATHLEN); - - n++; - } - } - closedir(dir); - - // delete equal elemets !!! - for (i = cx = 0; i < n; i++) - if (l[i].ch == '*') { - memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName)); - cx++; - i--; - } - n -= cx; - - *list = l; - return n; -} - -// ---------------------------------------------------- - -int main(int argc, char **argv) { - u_char *md[2]; - char ch; + char ch, szFName[MAXPATHLEN]; + int lm = 0; struct tagDirName *list; register int i; + FILE *f = stdout; + struct stat sb; - while ((ch = getopt(argc, argv, "hl")) != -1) + while ((ch = getopt(argc, argv, "hlo:")) != -1) switch (ch) { + case 'o': + lm |= 2; + strlcpy(szFName, optarg, MAXPATHLEN); + break; case 'l': - l = 1; + lm |= 1; break; case 'h': default: @@ -236,35 +50,48 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (argc < 2) { + if (!argc || (!(lm & 2) && argc < 2)) { Usage(); return 127; } // check for general differences - if (calcDir(argv[0], &md[0]) == -1) - return 127; - if (calcDir(argv[1], &md[1]) == -1) { - free(md[0]); - return 127; + if (argc > 1) { + if (lstat(argv[1], &sb) == -1) { + printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); + return 127; + } + + if (S_ISDIR(sb.st_mode)) + switch (sync_dircmp(argv[0], argv[1])) { + case -1: + printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); + return 127; + case 0: + printf("Directory %s == %s\n\n", argv[0], argv[1]); + return 0; + case 1: + printf("Directory %s != %s ::\n\n", argv[0], argv[1]); + } } - if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH)) { - free(md[0]); - free(md[1]); - printf("Directory %s == %s\n\n", argv[0], argv[1]); - return 0; - } else { - free(md[0]); - free(md[1]); - printf("Directory %s != %s ::\n\n", argv[0], argv[1]); - } - if (cmpDir(argv[0], argv[1], &list) == -1) + if (sync_dircmpList(argv[0], argc > 1 ? argv[1] : NULL, lm, &list) == -1) return 127; + if (lm & 2 && strcmp(szFName, "-")) { + f = fopen(szFName, "w"); + if (!f) { + printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno)); + if (list) + free(list); + return 0; + } + } for (i = 0; list[i].ch; i++) - printf("%c %s %s\n", list[i].ch, list[i].name, list[i].extra); - printf("\nTotal count of elements = %d\n", i); + fprintf(f, "%c %s %s\n", list[i].ch, list[i].name, list[i].extra); + if (lm & 2) + fclose(f); + printf("\nTotal count of elements = %d\n", i); free(list); return 1; }