File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / dircmp.c
Revision 1.1.2.4: download - view: text, annotated - select for diffs - revision graph
Tue Jul 13 11:49:49 2010 UTC (14 years ago) by misho
Branches: tools1_0
added output 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: int
   63: cmpDir(const char *csDir1, const char *csDir2, struct tagDirName **list)
   64: {
   65: 	struct tagDirName *l, *find;
   66: 	int n, cx;
   67: 	DIR *dir;
   68: 	struct dirent d, *pd;
   69: 	int tags[USHRT_MAX];
   70: 	register int i;
   71: 	u_short t;
   72: 	u_int hash;
   73: 	struct stat sb;
   74: 	char szStr[MAX_STR], szType[MAX_STR];
   75: 
   76: 	if (!csDir1 || !list)
   77: 		return -1;
   78: 	else
   79: 		memset(tags, -1, sizeof tags);
   80: 
   81: 	l = malloc(sizeof(struct tagDirName));
   82: 	if (!l) {
   83: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   84: 		return -1;
   85: 	} else {
   86: 		n = 0;
   87: 		memset(l, 0, sizeof(struct tagDirName));
   88: 	}
   89: 
   90: 	if (chdir(csDir1) == -1) {
   91: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   92: 		free(l);
   93: 		return -1;
   94: 	}
   95: 	dir = opendir(".");
   96: 	if (!dir) {
   97: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
   98: 		free(l);
   99: 		return -1;
  100: 	}
  101: 	while (!readdir_r(dir, &d, &pd) && pd) {
  102: 		if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
  103: 			continue;
  104: 
  105: 		l = realloc(l, sizeof(struct tagDirName) * (n + 2));
  106: 		if (!l) {
  107: 			printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  108: 			closedir(dir);
  109: 			return -1;
  110: 		} else
  111: 			memset(&l[n + 1], 0, sizeof(struct tagDirName));
  112: 
  113: 		l[n].ch = '<';
  114: 		l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
  115: 		l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen);
  116: 		strlcpy(l[n].name, d.d_name, MAXPATHLEN);
  117: 		if (lm & 1) {
  118: 			if (lstat(d.d_name, &sb) != -1) {
  119: 				memset(szStr, 0, MAX_STR);
  120: 				strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  121: 				switch (d.d_type) {
  122: 					case DT_FIFO:
  123: 						strlcpy(szType, "fifo", MAX_STR);
  124: 						break;
  125: 					case DT_CHR:
  126: 						strlcpy(szType, "char", MAX_STR);
  127: 						break;
  128: 					case DT_DIR:
  129: 						strlcpy(szType, "dir", MAX_STR);
  130: 						break;
  131: 					case DT_BLK:
  132: 						strlcpy(szType, "block", MAX_STR);
  133: 						break;
  134: 					case DT_REG:
  135: 						strlcpy(szType, "file", MAX_STR);
  136: 						break;
  137: 					case DT_LNK:
  138: 						strlcpy(szType, "link", MAX_STR);
  139: 						break;
  140: 					case DT_SOCK:
  141: 						strlcpy(szType, "socket", MAX_STR);
  142: 						break;
  143: 					case DT_WHT:
  144: 						strlcpy(szType, "wht", MAX_STR);
  145: 						break;
  146: 					case DT_UNKNOWN:
  147: 					default:
  148: 						strlcpy(szType, "unknown", MAX_STR);
  149: 						break;
  150: 				}
  151: 				snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
  152: 						szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
  153: 						sb.st_mode & 0x1fff, sb.st_size, szStr);
  154: 			}
  155: 		}
  156: 
  157: 		n++;
  158: 	}
  159: 	closedir(dir);
  160: 	qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp);
  161: 	for (i = n - 1; i > -1; i--)
  162: 		tags[l[i].tag] = i;
  163: 
  164: 	// if only 1 dir supplied and output filename is set, goto end
  165: 	if (lm & 2 && !csDir2)
  166: 		goto end;
  167: 	////
  168: 
  169: 	// open dir 2 for diff ...
  170: 	if (chdir(csDir2) == -1) {
  171: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  172: 		free(l);
  173: 		return -1;
  174: 	}
  175: 	dir = opendir(".");
  176: 	if (!dir) {
  177: 		printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  178: 		free(l);
  179: 		return -1;
  180: 	}
  181: 	while (!readdir_r(dir, &d, &pd) && pd) {
  182: 		if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
  183: 			continue;
  184: 		else {
  185: 			t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
  186: 			hash = crcAdler((u_char*) d.d_name, d.d_namlen);
  187: 		}
  188: 
  189: 		// search in index tags
  190: 		find = NULL;
  191: 		if (tags[t] != -1 && l[tags[t]].tag == t) {
  192: 			// search in sorted hashes
  193: 			for (i = 0; l[tags[t] + i].tag == t; i++)
  194: 				if (l[tags[t] + i].hash == hash) {
  195: 					// finded & marked for delete!
  196: 					find = &l[tags[t] + i];
  197: 					find->ch = '*';
  198: 					break;
  199: 				}
  200: 		}
  201: 		// element not find in dir1, added
  202: 		if (!find) {
  203: 			l = realloc(l, sizeof(struct tagDirName) * (n + 2));
  204: 			if (!l) {
  205: 				printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  206: 				closedir(dir);
  207: 				return -1;
  208: 			} else
  209: 				memset(&l[n + 1], 0, sizeof(struct tagDirName));
  210: 
  211: 			l[n].ch = '>';
  212: 			l[n].tag = t;
  213: 			l[n].hash = hash;
  214: 			strlcpy(l[n].name, d.d_name, MAXPATHLEN);
  215: 			if (lm & 1) {
  216: 				if (lstat(d.d_name, &sb) != -1) {
  217: 					memset(szStr, 0, MAX_STR);
  218: 					strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
  219: 					switch (d.d_type) {
  220: 						case DT_FIFO:
  221: 							strlcpy(szType, "fifo", MAX_STR);
  222: 							break;
  223: 						case DT_CHR:
  224: 							strlcpy(szType, "char", MAX_STR);
  225: 							break;
  226: 						case DT_DIR:
  227: 							strlcpy(szType, "dir", MAX_STR);
  228: 							break;
  229: 						case DT_BLK:
  230: 							strlcpy(szType, "block", MAX_STR);
  231: 							break;
  232: 						case DT_REG:
  233: 							strlcpy(szType, "file", MAX_STR);
  234: 							break;
  235: 						case DT_LNK:
  236: 							strlcpy(szType, "link", MAX_STR);
  237: 							break;
  238: 						case DT_SOCK:
  239: 							strlcpy(szType, "socket", MAX_STR);
  240: 							break;
  241: 						case DT_WHT:
  242: 							strlcpy(szType, "wht", MAX_STR);
  243: 							break;
  244: 						case DT_UNKNOWN:
  245: 						default:
  246: 							strlcpy(szType, "unknown", MAX_STR);
  247: 							break;
  248: 					}
  249: 					snprintf(l[n].extra, MAX_STR, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
  250: 							szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
  251: 							sb.st_mode & 0x1fff, sb.st_size, szStr);
  252: 				}
  253: 			}
  254: 
  255: 			n++;
  256: 		}
  257: 	}
  258: 	closedir(dir);
  259: 
  260: 	// delete equal elemets !!!
  261: 	for (i = cx = 0; i < n; i++)
  262: 		if (l[i].ch == '*') {
  263: 			memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName));
  264: 			cx++;
  265: 			i--;
  266: 		}
  267: 	n -= cx;
  268: end:
  269: 	*list = l;
  270: 	return n;
  271: }
  272: 
  273: // ----------------------------------------------------
  274: 
  275: int
  276: main(int argc, char **argv)
  277: {
  278: 	u_char *md[2] = { NULL, NULL };
  279: 	char ch, szFName[MAXPATHLEN];
  280: 	struct tagDirName *list;
  281: 	register int i;
  282: 	FILE *f = stdout;
  283: 
  284: 	while ((ch = getopt(argc, argv, "hlo:s")) != -1)
  285: 		switch (ch) {
  286: 			case 'o':
  287: 				lm |= 2;
  288: 				strlcpy(szFName, optarg, MAXPATHLEN);
  289: 				break;
  290: 			case 's':
  291: 				lm |= 4;
  292: 				break;
  293: 			case 'l':
  294: 				lm |= 1;
  295: 				break;
  296: 			case 'h':
  297: 			default:
  298: 				Usage();
  299: 				return 127;
  300: 		}
  301: 	argc -= optind;
  302: 	argv += optind;
  303: 
  304: 	if (argc < 1 || (lm < 2 && argc < 2)) {
  305: 		Usage();
  306: 		return 127;
  307: 	}
  308: 	// check for general differences
  309: 	if (calcDir(argv[0], &md[0]) == -1)
  310: 		return 127;
  311: 	if (argc > 1 && lm < 4) {
  312: 	       	if (calcDir(argv[1], &md[1]) == -1) {
  313: 			free(md[0]);
  314: 			return 127;
  315: 		}
  316: 		if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH)) {
  317: 			free(md[0]);
  318: 			if (md[1])
  319: 				free(md[1]);
  320: 			printf("Directory %s == %s\n\n", argv[0], argv[1]);
  321: 			return 0;
  322: 		} else {
  323: 			free(md[0]);
  324: 			if (md[1])
  325: 				free(md[1]);
  326: 			printf("Directory %s != %s ::\n\n", argv[0], argv[1]);
  327: 		}
  328: 	}
  329: 
  330: 	if (lm < 4 && cmpDir(argv[0], argc > 1 ? argv[1] : NULL, &list) == -1)
  331: 		return 127;
  332: 
  333: 	if (lm & 2) {
  334: 		f = fopen(szFName, "w");
  335: 		if (!f) {
  336: 			printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
  337: 			if (list)
  338: 				free(list);
  339: 			return 0;
  340: 		}
  341: 	}
  342: 	for (i = 0; list[i].ch; i++)
  343: 		fprintf(f, "%c  %s %s\n", list[i].ch, list[i].name, list[i].extra);
  344: 	if (lm & 2)
  345: 		fclose(f);
  346: 
  347: 	printf("\nTotal count of elements = %d\n", i);
  348: 	free(list);
  349: 	return 1;
  350: }

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