File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / dircmp.c
Revision 1.1.2.3: download - view: text, annotated - select for diffs - revision graph
Tue Jul 13 11:22:36 2010 UTC (14 years ago) by misho
Branches: tools1_0
final correction for cmp dirs

    1: #include "global.h"
    2: #include "dircmp.h"
    3: 
    4: 
    5: extern char compiled[], compiledby[], compilehost[];
    6: char lm;
    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"
   14: 		"  Syntax: dircmp [options] <dir> <cmp_dir>\n\n"
   15: 		"\t-l\t\tLong directory output ..."
   16: 		"\n", compiled, compiledby, compilehost);
   17: }
   18: 
   19: int
   20: calcDir(const char *csDir, u_char **md)
   21: {
   22: 	DIR *dir;
   23: 	struct dirent d, *pd;
   24: 	MD5_CTX ctx;
   25: 
   26: 	*md = malloc(MD5_DIGEST_LENGTH);
   27: 	if (!*md) {
   28: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   29: 		return -1;
   30: 	} else
   31: 		memset(*md, 0, MD5_DIGEST_LENGTH);
   32: 
   33: 	dir = opendir(csDir);
   34: 	if (!dir) {
   35: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   36: 		free(*md);
   37: 		return -1;
   38: 	}
   39: 
   40: 	MD5_Init(&ctx);
   41: 	while (!readdir_r(dir, &d, &pd) && pd) {
   42: 		if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
   43: 			continue;
   44: 		MD5_Update(&ctx, d.d_name, d.d_namlen);
   45: 	}
   46: 	MD5_Final(*md, &ctx);
   47: 
   48: 	closedir(dir);
   49: 	return 0;
   50: }
   51: 
   52: // -------------------------------------------------------------------
   53: 
   54: static int
   55: func_comp(struct tagDirName const *d1, struct tagDirName const *d2)
   56: {
   57: 	return d1->tag - d2->tag;
   58: }
   59: 
   60: int
   61: cmpDir(const char *csDir1, const char *csDir2, struct tagDirName **list)
   62: {
   63: 	struct tagDirName *l, *find;
   64: 	int n, cx;
   65: 	DIR *dir;
   66: 	struct dirent d, *pd;
   67: 	int tags[USHRT_MAX];
   68: 	register int i;
   69: 	u_short t;
   70: 	u_int hash;
   71: 	struct stat sb;
   72: 	char szStr[MAX_STR], szType[MAX_STR];
   73: 
   74: 	if (!csDir1 || !csDir2 || !list)
   75: 		return -1;
   76: 	else
   77: 		memset(tags, -1, sizeof tags);
   78: 
   79: 	l = malloc(sizeof(struct tagDirName));
   80: 	if (!l) {
   81: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   82: 		return -1;
   83: 	} else {
   84: 		n = 0;
   85: 		memset(l, 0, sizeof(struct tagDirName));
   86: 	}
   87: 
   88: 	if (chdir(csDir1) == -1) {
   89: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   90: 		free(l);
   91: 		return -1;
   92: 	}
   93: 	dir = opendir(".");
   94: 	if (!dir) {
   95: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   96: 		free(l);
   97: 		return -1;
   98: 	}
   99: 	while (!readdir_r(dir, &d, &pd) && pd) {
  100: 		if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
  101: 			continue;
  102: 
  103: 		l = realloc(l, sizeof(struct tagDirName) * (n + 2));
  104: 		if (!l) {
  105: 			printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  106: 			closedir(dir);
  107: 			return -1;
  108: 		} else
  109: 			memset(&l[n + 1], 0, sizeof(struct tagDirName));
  110: 
  111: 		l[n].ch = '<';
  112: 		l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
  113: 		l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen);
  114: 		strlcpy(l[n].name, d.d_name, MAXPATHLEN);
  115: 		if (lm) {
  116: 			if (lstat(d.d_name, &sb) != -1) {
  117: 				memset(szStr, 0, MAX_STR);
  118: 				strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  119: 				switch (d.d_type) {
  120: 					case DT_FIFO:
  121: 						strlcpy(szType, "fifo", MAX_STR);
  122: 						break;
  123: 					case DT_CHR:
  124: 						strlcpy(szType, "char", MAX_STR);
  125: 						break;
  126: 					case DT_DIR:
  127: 						strlcpy(szType, "dir", MAX_STR);
  128: 						break;
  129: 					case DT_BLK:
  130: 						strlcpy(szType, "block", MAX_STR);
  131: 						break;
  132: 					case DT_REG:
  133: 						strlcpy(szType, "file", MAX_STR);
  134: 						break;
  135: 					case DT_LNK:
  136: 						strlcpy(szType, "link", MAX_STR);
  137: 						break;
  138: 					case DT_SOCK:
  139: 						strlcpy(szType, "socket", MAX_STR);
  140: 						break;
  141: 					case DT_WHT:
  142: 						strlcpy(szType, "wht", MAX_STR);
  143: 						break;
  144: 					case DT_UNKNOWN:
  145: 					default:
  146: 						strlcpy(szType, "unknown", MAX_STR);
  147: 						break;
  148: 				}
  149: 				snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
  150: 						szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
  151: 						sb.st_mode & 0x1fff, sb.st_size, szStr);
  152: 			}
  153: 		}
  154: 
  155: 		n++;
  156: 	}
  157: 	closedir(dir);
  158: 	qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp);
  159: 	for (i = n - 1; i > -1; i--)
  160: 		tags[l[i].tag] = i;
  161: 
  162: 	// open dir 2 for diff ...
  163: 	if (chdir(csDir2) == -1) {
  164: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  165: 		free(l);
  166: 		return -1;
  167: 	}
  168: 	dir = opendir(".");
  169: 	if (!dir) {
  170: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  171: 		free(l);
  172: 		return -1;
  173: 	}
  174: 	while (!readdir_r(dir, &d, &pd) && pd) {
  175: 		if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
  176: 			continue;
  177: 		else {
  178: 			t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
  179: 			hash = crcAdler((u_char*) d.d_name, d.d_namlen);
  180: 		}
  181: 
  182: 		// search in index tags
  183: 		find = NULL;
  184: 		if (tags[t] != -1 && l[tags[t]].tag == t) {
  185: 			// search in sorted hashes
  186: 			for (i = 0; l[tags[t] + i].tag == t; i++)
  187: 				if (l[tags[t] + i].hash == hash) {
  188: 					// finded & marked for delete!
  189: 					find = &l[tags[t] + i];
  190: 					find->ch = '*';
  191: 					break;
  192: 				}
  193: 		}
  194: 		// element not find in dir1, added
  195: 		if (!find) {
  196: 			l = realloc(l, sizeof(struct tagDirName) * (n + 2));
  197: 			if (!l) {
  198: 				printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  199: 				closedir(dir);
  200: 				return -1;
  201: 			} else
  202: 				memset(&l[n + 1], 0, sizeof(struct tagDirName));
  203: 
  204: 			l[n].ch = '>';
  205: 			l[n].tag = t;
  206: 			l[n].hash = hash;
  207: 			strlcpy(l[n].name, d.d_name, MAXPATHLEN);
  208: 			if (lm) {
  209: 				if (lstat(d.d_name, &sb) != -1) {
  210: 					memset(szStr, 0, MAX_STR);
  211: 					strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  212: 					switch (d.d_type) {
  213: 						case DT_FIFO:
  214: 							strlcpy(szType, "fifo", MAX_STR);
  215: 							break;
  216: 						case DT_CHR:
  217: 							strlcpy(szType, "char", MAX_STR);
  218: 							break;
  219: 						case DT_DIR:
  220: 							strlcpy(szType, "dir", MAX_STR);
  221: 							break;
  222: 						case DT_BLK:
  223: 							strlcpy(szType, "block", MAX_STR);
  224: 							break;
  225: 						case DT_REG:
  226: 							strlcpy(szType, "file", MAX_STR);
  227: 							break;
  228: 						case DT_LNK:
  229: 							strlcpy(szType, "link", MAX_STR);
  230: 							break;
  231: 						case DT_SOCK:
  232: 							strlcpy(szType, "socket", MAX_STR);
  233: 							break;
  234: 						case DT_WHT:
  235: 							strlcpy(szType, "wht", MAX_STR);
  236: 							break;
  237: 						case DT_UNKNOWN:
  238: 						default:
  239: 							strlcpy(szType, "unknown", MAX_STR);
  240: 							break;
  241: 					}
  242: 					snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
  243: 							szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
  244: 							sb.st_mode & 0x1fff, sb.st_size, szStr);
  245: 				}
  246: 			}
  247: 
  248: 			n++;
  249: 		}
  250: 	}
  251: 	closedir(dir);
  252: 
  253: 	// delete equal elemets !!!
  254: 	for (i = cx = 0; i < n; i++)
  255: 		if (l[i].ch == '*') {
  256: 			memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName));
  257: 			cx++;
  258: 			i--;
  259: 		}
  260: 	n -= cx;
  261: 
  262: 	*list = l;
  263: 	return n;
  264: }
  265: 
  266: // ----------------------------------------------------
  267: 
  268: int
  269: main(int argc, char **argv)
  270: {
  271: 	u_char *md[2];
  272: 	char ch;
  273: 	struct tagDirName *list;
  274: 	register int i;
  275: 
  276: 	while ((ch = getopt(argc, argv, "hl")) != -1)
  277: 		switch (ch) {
  278: 			case 'l':
  279: 				lm = 1;
  280: 				break;
  281: 			case 'h':
  282: 			default:
  283: 				Usage();
  284: 				return 127;
  285: 		}
  286: 	argc -= optind;
  287: 	argv += optind;
  288: 
  289: 	if (argc < 2) {
  290: 		Usage();
  291: 		return 127;
  292: 	}
  293: 	// check for general differences
  294: 	if (calcDir(argv[0], &md[0]) == -1)
  295: 		return 127;
  296: 	if (calcDir(argv[1], &md[1]) == -1) {
  297: 		free(md[0]);
  298: 		return 127;
  299: 	}
  300: 	if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH)) {
  301: 		free(md[0]);
  302: 		free(md[1]);
  303: 		printf("Directory %s == %s\n\n", argv[0], argv[1]);
  304: 		return 0;
  305: 	} else {
  306: 		free(md[0]);
  307: 		free(md[1]);
  308: 		printf("Directory %s != %s ::\n\n", argv[0], argv[1]);
  309: 	}
  310: 
  311: 	if (cmpDir(argv[0], argv[1], &list) == -1)
  312: 		return 127;
  313: 
  314: 	for (i = 0; list[i].ch; i++)
  315: 		printf("%c  %s %s\n", list[i].ch, list[i].name, list[i].extra);
  316: 	printf("\nTotal count of elements = %d\n", i);
  317: 
  318: 	free(list);
  319: 	return 1;
  320: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>