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

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

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