Annotation of libaitsync/src/dir.c, revision 1.1.2.1

1.1.2.1 ! misho       1: /*************************************************************************
        !             2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
        !             3: *  by Michael Pounov <misho@openbsd-bg.org>
        !             4: *
        !             5: * $Author: misho $
        !             6: * $Id: aitsync.h,v 1.1.1.1.2.1 2010/03/24 16:31:27 misho Exp $
        !             7: *
        !             8: *************************************************************************/
        !             9: #include "global.h"
        !            10: 
        !            11: 
        !            12: static int
        !            13: func_comp(struct tagDirName const *d1, struct tagDirName const *d2)
        !            14: {
        !            15:        return d1->tag - d2->tag;
        !            16: }
        !            17: 
        !            18: static struct tagDirName *
        !            19: find_tag(int const * __restrict tags, struct tagDirName const * __restrict l, u_short t, u_int hash)
        !            20: {
        !            21:        struct tagDirName *find = NULL;
        !            22:        register int i;
        !            23: 
        !            24:        // search in index tags
        !            25:        if (tags[t] != -1 && l[tags[t]].tag == t) {
        !            26:                // search in sorted hashes
        !            27:                for (i = 0; l[tags[t] + i].tag == t; i++)
        !            28:                        if (l[tags[t] + i].hash == hash) {
        !            29:                                // finded & marked for delete!
        !            30:                                find = (struct tagDirName*) &l[tags[t] + i];
        !            31:                                find->ch = '*';
        !            32:                                break;
        !            33:                        }
        !            34:        }
        !            35: 
        !            36:        return find;
        !            37: }
        !            38: 
        !            39: static int *
        !            40: create_tags()
        !            41: {
        !            42:        int *tags;
        !            43: 
        !            44:        tags = calloc(TABLESIZ, sizeof(int));
        !            45:        if (!tags) {
        !            46:                SETERR;
        !            47:        } else
        !            48:                memset(tags, -1, TABLESIZ * sizeof(int));
        !            49: 
        !            50:        return tags;
        !            51: }
        !            52: 
        !            53: static int
        !            54: create_diridx(const char *csDir, int lm, int *tags, struct tagDirName **list)
        !            55: {
        !            56:        struct tagDirName *l = *list;
        !            57:        DIR *dir;
        !            58:        struct dirent d, *pd;
        !            59:        int n;
        !            60:        char szStr[STRSIZ], szType[STRSIZ];
        !            61:        struct stat sb;
        !            62:        register int i;
        !            63: 
        !            64:        l = malloc(sizeof(struct tagDirName));
        !            65:        if (!l) {
        !            66:                SETERR;
        !            67:                *list = NULL;
        !            68:                return -1;
        !            69:        } else {
        !            70:                n = 0;
        !            71:                memset(l, 0, sizeof(struct tagDirName));
        !            72:        }
        !            73: 
        !            74:        if (chdir(csDir) == -1) {
        !            75:                SETERR;
        !            76:                free(l);
        !            77:                *list = NULL;
        !            78:                return -1;
        !            79:        }
        !            80:        dir = opendir(".");
        !            81:        if (!dir) {
        !            82:                SETERR;
        !            83:                free(l);
        !            84:                *list = NULL;
        !            85:                return -1;
        !            86:        }
        !            87:        while (!readdir_r(dir, &d, &pd) && pd) {
        !            88:                if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
        !            89:                        continue;
        !            90: 
        !            91:                l = realloc(l, sizeof(struct tagDirName) * (n + 2));
        !            92:                if (!l) {
        !            93:                        SETERR;
        !            94:                        free(l);
        !            95:                        *list = NULL;
        !            96:                        closedir(dir);
        !            97:                        return -1;
        !            98:                } else
        !            99:                        memset(&l[n + 1], 0, sizeof(struct tagDirName));
        !           100: 
        !           101:                l[n].ch = '<';
        !           102:                l[n].tag = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
        !           103:                l[n].hash = crcAdler((u_char*) d.d_name, d.d_namlen);
        !           104:                strlcpy(l[n].name, d.d_name, MAXPATHLEN);
        !           105:                if (lm & 1) {
        !           106:                        if (lstat(d.d_name, &sb) != -1) {
        !           107:                                memset(szStr, 0, STRSIZ);
        !           108:                                strftime(szStr, STRSIZ, "%Y-%m-%d %H:%M:%S", localtime((time_t*) &sb.st_mtim));
        !           109:                                switch (d.d_type) {
        !           110:                                        case DT_FIFO:
        !           111:                                                strlcpy(szType, "fifo", STRSIZ);
        !           112:                                                break;
        !           113:                                        case DT_CHR:
        !           114:                                                strlcpy(szType, "char", STRSIZ);
        !           115:                                                break;
        !           116:                                        case DT_DIR:
        !           117:                                                strlcpy(szType, "dir", STRSIZ);
        !           118:                                                break;
        !           119:                                        case DT_BLK:
        !           120:                                                strlcpy(szType, "block", STRSIZ);
        !           121:                                                break;
        !           122:                                        case DT_REG:
        !           123:                                                strlcpy(szType, "file", STRSIZ);
        !           124:                                                break;
        !           125:                                        case DT_LNK:
        !           126:                                                strlcpy(szType, "link", STRSIZ);
        !           127:                                                break;
        !           128:                                        case DT_SOCK:
        !           129:                                                strlcpy(szType, "socket", STRSIZ);
        !           130:                                                break;
        !           131:                                        case DT_WHT:
        !           132:                                                strlcpy(szType, "wht", STRSIZ);
        !           133:                                                break;
        !           134:                                        case DT_UNKNOWN:
        !           135:                                        default:
        !           136:                                                strlcpy(szType, "unknown", STRSIZ);
        !           137:                                                break;
        !           138:                                }
        !           139:                                snprintf(l[n].extra, STRSIZ, "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
        !           140:                                                szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
        !           141:                                                sb.st_mode & 0x1fff, sb.st_size, szStr);
        !           142:                        }
        !           143:                }
        !           144: 
        !           145:                n++;
        !           146:        }
        !           147:        closedir(dir);
        !           148: 
        !           149:        qsort(l, n, sizeof(struct tagDirName), (int (*)(const void*, const void*)) func_comp);
        !           150:        for (i = n - 1; i > -1; i--)
        !           151:                tags[l[i].tag] = i;
        !           152: 
        !           153:        *list = l;
        !           154:        return n;
        !           155: }
        !           156: 
        !           157: // ------------------------------------------------------
        !           158: 
        !           159: /*
        !           160:  * sync_dirCSum() Calculate checksum of directory
        !           161:  * @csDir = Directory
        !           162:  * @md = Message digest allocated memory, must be free after use!
        !           163:  * return: -1 error or !=-1 ok
        !           164:  */
        !           165: int
        !           166: sync_dirCSum(const char *csDir, u_char **md)
        !           167: {
        !           168:        DIR *dir;
        !           169:        struct dirent d, *pd;
        !           170:        MD5_CTX ctx;
        !           171:        register int ret = 0;
        !           172: 
        !           173:        *md = malloc(MD5_DIGEST_LENGTH);
        !           174:        if (!*md) {
        !           175:                SETERR;
        !           176:                return -1;
        !           177:        } else
        !           178:                memset(*md, 0, MD5_DIGEST_LENGTH);
        !           179: 
        !           180:        dir = opendir(csDir);
        !           181:        if (!dir) {
        !           182:                SETERR;
        !           183:                free(*md);
        !           184:                return -1;
        !           185:        }
        !           186: 
        !           187:        MD5_Init(&ctx);
        !           188:        while (!readdir_r(dir, &d, &pd) && pd) {
        !           189:                if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
        !           190:                        continue;
        !           191:                MD5_Update(&ctx, d.d_name, d.d_namlen);
        !           192:                ret++;
        !           193:        }
        !           194:        MD5_Final(*md, &ctx);
        !           195: 
        !           196:        closedir(dir);
        !           197:        return ret;
        !           198: }
        !           199: 
        !           200: /*
        !           201:  * sync_dircmp() Compare directories
        !           202:  * @csDir1 = Directory 1
        !           203:  * @csDir2 = Directory 2
        !           204:  * return: -1 error, 0 is equal or 1 different
        !           205:  */
        !           206: int
        !           207: sync_dircmp(const char *csDir1, const char *csDir2)
        !           208: {
        !           209:        u_char *md[2] = { NULL, NULL };
        !           210:        int ret = -1;
        !           211: 
        !           212:        if (!csDir1 || !csDir2)
        !           213:                return ret;
        !           214: 
        !           215:        if (sync_dirCSum(csDir1, &md[0]) == -1)
        !           216:                return ret;
        !           217:        if (sync_dirCSum(csDir2, &md[1]) == -1) {
        !           218:                free(md[0]);
        !           219:                return ret;
        !           220:        }
        !           221: 
        !           222:        if (!memcmp(md[0], md[1], MD5_DIGEST_LENGTH))
        !           223:                ret = 0;
        !           224:        else
        !           225:                ret = 1;
        !           226: 
        !           227:        free(md[1]);
        !           228:        free(md[0]);
        !           229:        return ret;
        !           230: }
        !           231: 
        !           232: /*
        !           233:  * sync_dircmpList() Compare directories or directory and file list
        !           234:  * @csDir1 = Directory 1
        !           235:  * @csDir2 = Directory 2 or File list, if "-" get input from console
        !           236:  * @lm = Long mode options, 1 long output
        !           237:  * @list = Output diff list, after use must be free!
        !           238:  * return: -1 error, 0 is equal or >0 count of returned list items
        !           239:  */
        !           240: int
        !           241: sync_dircmpList(const char *csDir1, const char *csDir2, int lm, struct tagDirName **list)
        !           242: {
        !           243:        struct tagDirName *l, *find;
        !           244:        int n, cx;
        !           245:        DIR *dir;
        !           246:        FILE *f = stdin;
        !           247:        struct dirent d, *pd;
        !           248:        int *tags;
        !           249:        register int i;
        !           250:        u_short t;
        !           251:        u_int hash;
        !           252:        struct stat sb;
        !           253:        char szLine[STRSIZ], szStr[STRSIZ], szType[STRSIZ], *str, *pbrk;
        !           254: 
        !           255:        if (!csDir1 || !list || !(tags = create_tags()))
        !           256:                return -1;
        !           257: 
        !           258:        n = create_diridx(csDir1, lm, tags, &l);
        !           259:        if (n == -1 || !csDir2) {
        !           260:                *list = l;
        !           261:                return n;
        !           262:        }
        !           263: 
        !           264:        if (!lstat(csDir2, &sb) && S_ISDIR(sb.st_mode)) {
        !           265:                if (chdir(csDir2) == -1) {
        !           266:                        SETERR;
        !           267:                        free(l);
        !           268:                        return -1;
        !           269:                }
        !           270:                dir = opendir(".");
        !           271:                if (!dir) {
        !           272:                        SETERR;
        !           273:                        free(l);
        !           274:                        return -1;
        !           275:                }
        !           276:                while (!readdir_r(dir, &d, &pd) && pd) {
        !           277:                        if (d.d_type == DT_DIR && (!strcmp(d.d_name, ".") || !strcmp(d.d_name, "..")))
        !           278:                                continue;
        !           279:                        else {
        !           280:                                t = crcFletcher16((u_short*) d.d_name, d.d_namlen / 2 + d.d_namlen % 2);
        !           281:                                hash = crcAdler((u_char*) d.d_name, d.d_namlen);
        !           282:                        }
        !           283: 
        !           284:                        find = find_tag(tags, l, t, hash);
        !           285:                        // element not find in dir1, added
        !           286:                        if (!find) {
        !           287:                                l = realloc(l, sizeof(struct tagDirName) * (n + 2));
        !           288:                                if (!l) {
        !           289:                                        SETERR;
        !           290:                                        closedir(dir);
        !           291:                                        return -1;
        !           292:                                } else
        !           293:                                        memset(&l[n + 1], 0, sizeof(struct tagDirName));
        !           294: 
        !           295:                                l[n].ch = '>';
        !           296:                                l[n].tag = t;
        !           297:                                l[n].hash = hash;
        !           298:                                strlcpy(l[n].name, d.d_name, MAXPATHLEN);
        !           299:                                if (lm & 1) {
        !           300:                                        if (lstat(d.d_name, &sb) != -1) {
        !           301:                                                memset(szStr, 0, STRSIZ);
        !           302:                                                strftime(szStr, STRSIZ, "%Y-%m-%d %H:%M:%S", 
        !           303:                                                                localtime((time_t*) &sb.st_mtim));
        !           304:                                                switch (d.d_type) {
        !           305:                                                        case DT_FIFO:
        !           306:                                                                strlcpy(szType, "fifo", STRSIZ);
        !           307:                                                                break;
        !           308:                                                        case DT_CHR:
        !           309:                                                                strlcpy(szType, "char", STRSIZ);
        !           310:                                                                break;
        !           311:                                                        case DT_DIR:
        !           312:                                                                strlcpy(szType, "dir", STRSIZ);
        !           313:                                                                break;
        !           314:                                                        case DT_BLK:
        !           315:                                                                strlcpy(szType, "block", STRSIZ);
        !           316:                                                                break;
        !           317:                                                        case DT_REG:
        !           318:                                                                strlcpy(szType, "file", STRSIZ);
        !           319:                                                                break;
        !           320:                                                        case DT_LNK:
        !           321:                                                                strlcpy(szType, "link", STRSIZ);
        !           322:                                                                break;
        !           323:                                                        case DT_SOCK:
        !           324:                                                                strlcpy(szType, "socket", STRSIZ);
        !           325:                                                                break;
        !           326:                                                        case DT_WHT:
        !           327:                                                                strlcpy(szType, "wht", STRSIZ);
        !           328:                                                                break;
        !           329:                                                        case DT_UNKNOWN:
        !           330:                                                        default:
        !           331:                                                                strlcpy(szType, "unknown", STRSIZ);
        !           332:                                                                break;
        !           333:                                                }
        !           334:                                                snprintf(l[n].extra, STRSIZ, 
        !           335:                                                                "%s links=%d inode=%u %d:%d perm=0%o size=%llu %s", 
        !           336:                                                                szType, sb.st_nlink, sb.st_ino, sb.st_uid, sb.st_gid, 
        !           337:                                                                sb.st_mode & 0x1fff, sb.st_size, szStr);
        !           338:                                        }
        !           339:                                }
        !           340: 
        !           341:                                n++;
        !           342:                        }
        !           343:                }
        !           344:                closedir(dir);
        !           345:        } else {
        !           346:                if (strcmp(csDir2, "-")) {
        !           347:                        f = fopen(csDir2, "r");
        !           348:                        if (!f) {
        !           349:                                SETERR;
        !           350:                                free(l);
        !           351:                                return -1;
        !           352:                        }
        !           353:                }
        !           354:                while (fgets(szLine, STRSIZ, f)) {
        !           355:                        if (!*szLine || *szLine == '#')
        !           356:                                continue;
        !           357: 
        !           358:                        str = strtok_r(szLine, " \t", &pbrk);
        !           359:                        if (!str)
        !           360:                                continue;
        !           361:                        str = strtok_r(NULL, " \t", &pbrk);
        !           362:                        if (!str)
        !           363:                                continue;
        !           364:                        else {
        !           365:                                i = strlen(str);
        !           366:                                t = crcFletcher16((u_short*) str, i / 2 + i % 2);
        !           367:                                hash = crcAdler((u_char*) str, i);
        !           368:                        }
        !           369: 
        !           370:                        find = find_tag(tags, l, t, hash);
        !           371:                        // element not find in dir1, added
        !           372:                        if (!find) {
        !           373:                                l = realloc(l, sizeof(struct tagDirName) * (n + 2));
        !           374:                                if (!l) {
        !           375:                                        SETERR;
        !           376:                                        if (strcmp(csDir2, "-"))
        !           377:                                                fclose(f);
        !           378:                                        return -1;
        !           379:                                } else
        !           380:                                        memset(&l[n + 1], 0, sizeof(struct tagDirName));
        !           381: 
        !           382:                                l[n].ch = '>';
        !           383:                                l[n].tag = t;
        !           384:                                l[n].hash = hash;
        !           385:                                strlcpy(l[n].name, str, MAXPATHLEN);
        !           386:                                if (lm & 1 && (str = strtok_r(NULL, "\r\n", &pbrk)))
        !           387:                                        strlcpy(l[n].extra, str, STRSIZ);
        !           388: 
        !           389:                                n++;
        !           390:                        }
        !           391:                }
        !           392:                if (strcmp(csDir2, "-"))
        !           393:                        fclose(f);
        !           394:        }
        !           395: 
        !           396:        // delete equal elemets !!!
        !           397:        for (i = cx = 0; i < n; i++)
        !           398:                if (l[i].ch == '*') {
        !           399:                        memmove(&l[i], &l[i + 1], (n - i + 1) * sizeof(struct tagDirName));
        !           400:                        cx++;
        !           401:                        i--;
        !           402:                }
        !           403:        n -= cx;
        !           404: 
        !           405:        *list = l;
        !           406:        return n;
        !           407: }

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