File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / dircmp.c
Revision 1.1.2.5: download - view: text, annotated - select for diffs - revision graph
Tue Jul 13 12:38:23 2010 UTC (14 years ago) by misho
Branches: tools1_0
added input list mode

    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 ...\n"
   16: 		"\t-s\t\tCompare dir from stdin list\n"
   17: 		"\t-o <filename>\tOutput diff to filename\n"
   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: 
   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: 
   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;
   95: 	char szLine[MAX_STR], szStr[MAX_STR], szType[MAX_STR], *str, *pbrk;
   96: 	FILE *f = stdin;
   97: 
   98: 	if (!csDir1 || !list)
   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: 
  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(".");
  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);
  139: 		if (lm & 1) {
  140: 			if (lstat(d.d_name, &sb) != -1) {
  141: 				memset(szStr, 0, MAX_STR);
  142: 				strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  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: 				}
  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);
  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: 
  186: 	// if only 1 dir supplied and output filename is set, goto end
  187: 	if (lm & 2 && !csDir2)
  188: 		goto end;
  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: 	}
  241: 	////
  242: 
  243: 	// open dir 2 for diff ...
  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(".");
  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: 
  263: 		find = find_tag(tags, l, t, hash);
  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);
  278: 			if (lm & 1) {
  279: 				if (lstat(d.d_name, &sb) != -1) {
  280: 					memset(szStr, 0, MAX_STR);
  281: 					strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  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: 					}
  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);
  315: 				}
  316: 			}
  317: 
  318: 			n++;
  319: 		}
  320: 	}
  321: 	closedir(dir);
  322: delel:
  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;
  331: end:
  332: 	*list = l;
  333: 	return n;
  334: }
  335: 
  336: // ----------------------------------------------------
  337: 
  338: int
  339: main(int argc, char **argv)
  340: {
  341: 	u_char *md[2] = { NULL, NULL };
  342: 	char ch, szFName[MAXPATHLEN];
  343: 	struct tagDirName *list;
  344: 	register int i;
  345: 	FILE *f = stdout;
  346: 
  347: 	while ((ch = getopt(argc, argv, "hlo:s")) != -1)
  348: 		switch (ch) {
  349: 			case 'o':
  350: 				lm |= 2;
  351: 				strlcpy(szFName, optarg, MAXPATHLEN);
  352: 				break;
  353: 			case 's':
  354: 				lm |= 4;
  355: 				break;
  356: 			case 'l':
  357: 				lm |= 1;
  358: 				break;
  359: 			case 'h':
  360: 			default:
  361: 				Usage();
  362: 				return 127;
  363: 		}
  364: 	argc -= optind;
  365: 	argv += optind;
  366: 
  367: 	if (!argc || (!(lm & 2) && argc < 2)) {
  368: 		Usage();
  369: 		return 127;
  370: 	}
  371: 	// check for general differences
  372: 	if (calcDir(argv[0], &md[0]) == -1)
  373: 		return 127;
  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: 		}
  391: 	}
  392: 
  393: 	if (cmpDir(argv[0], argc > 1 ? argv[1] : NULL, &list) == -1)
  394: 		return 127;
  395: 
  396: 	if (lm & 2 && strcmp(szFName, "-")) {
  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: 	}
  405: 	for (i = 0; list[i].ch; i++)
  406: 		fprintf(f, "%c  %s %s\n", list[i].ch, list[i].name, list[i].extra);
  407: 	if (lm & 2)
  408: 		fclose(f);
  409: 
  410: 	printf("\nTotal count of elements = %d\n", i);
  411: 	free(list);
  412: 	return 1;
  413: }

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