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>