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>