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

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: 
                     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: 
1.1.2.4 ! misho      76:        if (!csDir1 || !list)
1.1.2.1   misho      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: 
1.1.2.3   misho      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(".");
1.1.2.1   misho      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);
1.1.2.4 ! misho     117:                if (lm & 1) {
1.1.2.1   misho     118:                        if (lstat(d.d_name, &sb) != -1) {
                    119:                                memset(szStr, 0, MAX_STR);
1.1.2.3   misho     120:                                strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
1.1.2.1   misho     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:                                }
1.1.2.3   misho     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);
1.1.2.1   misho     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: 
1.1.2.4 ! misho     164:        // if only 1 dir supplied and output filename is set, goto end
        !           165:        if (lm & 2 && !csDir2)
        !           166:                goto end;
        !           167:        ////
        !           168: 
1.1.2.1   misho     169:        // open dir 2 for diff ...
1.1.2.3   misho     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(".");
1.1.2.1   misho     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);
1.1.2.4 ! misho     215:                        if (lm & 1) {
1.1.2.2   misho     216:                                if (lstat(d.d_name, &sb) != -1) {
                    217:                                        memset(szStr, 0, MAX_STR);
1.1.2.3   misho     218:                                        strftime(szStr, MAX_STR, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
1.1.2.2   misho     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:                                        }
1.1.2.3   misho     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);
1.1.2.2   misho     252:                                }
                    253:                        }
1.1.2.1   misho     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;
1.1.2.4 ! misho     268: end:
1.1.2.1   misho     269:        *list = l;
                    270:        return n;
                    271: }
                    272: 
                    273: // ----------------------------------------------------
                    274: 
                    275: int
                    276: main(int argc, char **argv)
                    277: {
1.1.2.4 ! misho     278:        u_char *md[2] = { NULL, NULL };
        !           279:        char ch, szFName[MAXPATHLEN];
1.1.2.1   misho     280:        struct tagDirName *list;
                    281:        register int i;
1.1.2.4 ! misho     282:        FILE *f = stdout;
1.1.2.1   misho     283: 
1.1.2.4 ! misho     284:        while ((ch = getopt(argc, argv, "hlo:s")) != -1)
1.1.2.1   misho     285:                switch (ch) {
1.1.2.4 ! misho     286:                        case 'o':
        !           287:                                lm |= 2;
        !           288:                                strlcpy(szFName, optarg, MAXPATHLEN);
        !           289:                                break;
        !           290:                        case 's':
        !           291:                                lm |= 4;
        !           292:                                break;
1.1.2.1   misho     293:                        case 'l':
1.1.2.4 ! misho     294:                                lm |= 1;
1.1.2.1   misho     295:                                break;
                    296:                        case 'h':
                    297:                        default:
                    298:                                Usage();
                    299:                                return 127;
                    300:                }
                    301:        argc -= optind;
                    302:        argv += optind;
                    303: 
1.1.2.4 ! misho     304:        if (argc < 1 || (lm < 2 && argc < 2)) {
1.1.2.1   misho     305:                Usage();
                    306:                return 127;
                    307:        }
                    308:        // check for general differences
                    309:        if (calcDir(argv[0], &md[0]) == -1)
                    310:                return 127;
1.1.2.4 ! misho     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:                }
1.1.2.1   misho     328:        }
                    329: 
1.1.2.4 ! misho     330:        if (lm < 4 && cmpDir(argv[0], argc > 1 ? argv[1] : NULL, &list) == -1)
1.1.2.1   misho     331:                return 127;
                    332: 
1.1.2.4 ! misho     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:        }
1.1.2.1   misho     342:        for (i = 0; list[i].ch; i++)
1.1.2.4 ! misho     343:                fprintf(f, "%c  %s %s\n", list[i].ch, list[i].name, list[i].extra);
        !           344:        if (lm & 2)
        !           345:                fclose(f);
1.1.2.1   misho     346: 
1.1.2.4 ! misho     347:        printf("\nTotal count of elements = %d\n", i);
1.1.2.1   misho     348:        free(list);
                    349:        return 1;
                    350: }

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