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

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

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