Annotation of embedtools/src/dircmp.c, revision 1.1.2.2

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"
                     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:        dir = opendir(csDir1);
                     89:        if (!dir) {
                     90:                printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
                     91:                free(l);
                     92:                return -1;
                     93:        }
                     94:        while (!readdir_r(dir, &d, &pd) && pd) {
                     95:                if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
                     96:                        continue;
                     97: 
                     98:                l = realloc(l, sizeof(struct tagDirName) * (n + 2));
                     99:                if (!l) {
                    100:                        printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
                    101:                        closedir(dir);
                    102:                        return -1;
                    103:                } else
                    104:                        memset(&l[n + 1], 0, sizeof(struct tagDirName));
                    105: 
                    106:                l[n].ch = '<';
                    107:                l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
                    108:                l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen);
                    109:                strlcpy(l[n].name, d.d_name, MAXPATHLEN);
1.1.2.2 ! misho     110:                if (lm) {
1.1.2.1   misho     111:                        if (lstat(d.d_name, &sb) != -1) {
                    112:                                memset(szStr, 0, MAX_STR);
1.1.2.2 ! misho     113:                                strftime(szStr, MAX_STR, "%y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
1.1.2.1   misho     114:                                switch (d.d_type) {
                    115:                                        case DT_FIFO:
                    116:                                                strlcpy(szType, "fifo", MAX_STR);
                    117:                                                break;
                    118:                                        case DT_CHR:
                    119:                                                strlcpy(szType, "char", MAX_STR);
                    120:                                                break;
                    121:                                        case DT_DIR:
                    122:                                                strlcpy(szType, "dir", MAX_STR);
                    123:                                                break;
                    124:                                        case DT_BLK:
                    125:                                                strlcpy(szType, "block", MAX_STR);
                    126:                                                break;
                    127:                                        case DT_REG:
                    128:                                                strlcpy(szType, "file", MAX_STR);
                    129:                                                break;
                    130:                                        case DT_LNK:
                    131:                                                strlcpy(szType, "link", MAX_STR);
                    132:                                                break;
                    133:                                        case DT_SOCK:
                    134:                                                strlcpy(szType, "socket", MAX_STR);
                    135:                                                break;
                    136:                                        case DT_WHT:
                    137:                                                strlcpy(szType, "wht", MAX_STR);
                    138:                                                break;
                    139:                                        case DT_UNKNOWN:
                    140:                                        default:
                    141:                                                strlcpy(szType, "unknown", MAX_STR);
                    142:                                                break;
                    143:                                }
                    144:                                snprintf(l[n].extra, MAX_STR, "%s links=%d %d:%d perm=0%o size=%llu %s\n", szType, 
1.1.2.2 ! misho     145:                                                sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_mode & 0x1fff, 
        !           146:                                                sb.st_size, szStr);
1.1.2.1   misho     147:                        }
                    148:                }
                    149: 
                    150:                n++;
                    151:        }
                    152:        closedir(dir);
                    153:        qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp);
                    154:        for (i = n - 1; i > -1; i--)
                    155:                tags[l[i].tag] = i;
                    156: 
                    157:        // open dir 2 for diff ...
                    158:        dir = opendir(csDir2);
                    159:        if (!dir) {
                    160:                printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
                    161:                free(l);
                    162:                return -1;
                    163:        }
                    164:        while (!readdir_r(dir, &d, &pd) && pd) {
                    165:                if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
                    166:                        continue;
                    167:                else {
                    168:                        t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
                    169:                        hash = crcAdler((u_char*) d.d_name, d.d_namlen);
                    170:                }
                    171: 
                    172:                // search in index tags
                    173:                find = NULL;
                    174:                if (tags[t] != -1 && l[tags[t]].tag == t) {
                    175:                        // search in sorted hashes
                    176:                        for (i = 0; l[tags[t] + i].tag == t; i++)
                    177:                                if (l[tags[t] + i].hash == hash) {
                    178:                                        // finded & marked for delete!
                    179:                                        find = &l[tags[t] + i];
                    180:                                        find->ch = '*';
                    181:                                        break;
                    182:                                }
                    183:                }
                    184:                // element not find in dir1, added
                    185:                if (!find) {
                    186:                        l = realloc(l, sizeof(struct tagDirName) * (n + 2));
                    187:                        if (!l) {
                    188:                                printf("Error:: %s(%d) #%d - %s\n", __func__, __LINE__, errno, strerror(errno));
                    189:                                closedir(dir);
                    190:                                return -1;
                    191:                        } else
                    192:                                memset(&l[n + 1], 0, sizeof(struct tagDirName));
                    193: 
                    194:                        l[n].ch = '>';
                    195:                        l[n].tag = t;
                    196:                        l[n].hash = hash;
                    197:                        strlcpy(l[n].name, d.d_name, MAXPATHLEN);
1.1.2.2 ! misho     198:                        if (lm) {
        !           199:                                if (lstat(d.d_name, &sb) != -1) {
        !           200:                                        memset(szStr, 0, MAX_STR);
        !           201:                                        strftime(szStr, MAX_STR, "%y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
        !           202:                                        switch (d.d_type) {
        !           203:                                                case DT_FIFO:
        !           204:                                                        strlcpy(szType, "fifo", MAX_STR);
        !           205:                                                        break;
        !           206:                                                case DT_CHR:
        !           207:                                                        strlcpy(szType, "char", MAX_STR);
        !           208:                                                        break;
        !           209:                                                case DT_DIR:
        !           210:                                                        strlcpy(szType, "dir", MAX_STR);
        !           211:                                                        break;
        !           212:                                                case DT_BLK:
        !           213:                                                        strlcpy(szType, "block", MAX_STR);
        !           214:                                                        break;
        !           215:                                                case DT_REG:
        !           216:                                                        strlcpy(szType, "file", MAX_STR);
        !           217:                                                        break;
        !           218:                                                case DT_LNK:
        !           219:                                                        strlcpy(szType, "link", MAX_STR);
        !           220:                                                        break;
        !           221:                                                case DT_SOCK:
        !           222:                                                        strlcpy(szType, "socket", MAX_STR);
        !           223:                                                        break;
        !           224:                                                case DT_WHT:
        !           225:                                                        strlcpy(szType, "wht", MAX_STR);
        !           226:                                                        break;
        !           227:                                                case DT_UNKNOWN:
        !           228:                                                default:
        !           229:                                                        strlcpy(szType, "unknown", MAX_STR);
        !           230:                                                        break;
        !           231:                                        }
        !           232:                                        snprintf(l[n].extra, MAX_STR, "%s links=%d %d:%d perm=0%o size=%llu %s\n", szType, 
        !           233:                                                        sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_mode & 0x1fff, 
        !           234:                                                        sb.st_size, szStr);
        !           235:                                }
        !           236:                        }
1.1.2.1   misho     237: 
                    238:                        n++;
                    239:                }
                    240:        }
                    241:        closedir(dir);
                    242: 
                    243:        // delete equal elemets !!!
                    244:        for (i = cx = 0; i < n; i++)
                    245:                if (l[i].ch == '*') {
                    246:                        memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName));
                    247:                        cx++;
                    248:                        i--;
                    249:                }
                    250:        n -= cx;
                    251: 
                    252:        *list = l;
                    253:        return n;
                    254: }
                    255: 
                    256: // ----------------------------------------------------
                    257: 
                    258: int
                    259: main(int argc, char **argv)
                    260: {
                    261:        u_char *md[2];
                    262:        char ch;
                    263:        struct tagDirName *list;
                    264:        register int i;
                    265: 
                    266:        while ((ch = getopt(argc, argv, "hl")) != -1)
                    267:                switch (ch) {
                    268:                        case 'l':
1.1.2.2 ! misho     269:                                lm = 1;
1.1.2.1   misho     270:                                break;
                    271:                        case 'h':
                    272:                        default:
                    273:                                Usage();
                    274:                                return 127;
                    275:                }
                    276:        argc -= optind;
                    277:        argv += optind;
                    278: 
                    279:        if (argc < 2) {
                    280:                Usage();
                    281:                return 127;
                    282:        }
                    283:        // check for general differences
                    284:        if (calcDir(argv[0], &md[0]) == -1)
                    285:                return 127;
                    286:        if (calcDir(argv[1], &md[1]) == -1) {
                    287:                free(md[0]);
                    288:                return 127;
                    289:        }
                    290:        if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH)) {
                    291:                free(md[0]);
                    292:                free(md[1]);
                    293:                printf("Directory %s == %s\n\n", argv[0], argv[1]);
                    294:                return 0;
                    295:        } else {
                    296:                free(md[0]);
                    297:                free(md[1]);
                    298:                printf("Directory %s != %s ::\n\n", argv[0], argv[1]);
                    299:        }
                    300: 
                    301:        if (cmpDir(argv[0], argv[1], &list) == -1)
                    302:                return 127;
                    303: 
                    304:        for (i = 0; list[i].ch; i++)
                    305:                printf("%c  %s %s\n", list[i].ch, list[i].name, list[i].extra);
                    306:        printf("\nTotal count of elements = %d\n", i);
                    307: 
                    308:        free(list);
                    309:        return 1;
                    310: }

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