static char *rcsid = "$Id$"; /* * $Log$ */ /* generate a list of all files on the server * accept a list of all files in the TSM library * compare the two lists of files * output the differences... files on the server not in the library */ #include #include #include #include #include /* global variables */ int smtp; /* send a message to a socket */ void msg(char *s) { (void) send(smtp, s, strlen(s), 0); (void) send(smtp, "\r\n", 2, 0); } /* simple error routing */ void err(char *msg) { (void) fprintf(stderr, "dsmcmp: %s\n", msg); (void) exit(1); } /* comparison function for qsort */ int linesCompare(const void *a, const void *b) { return strcmp(*((char **) a), *((char **) b)); } /* get a list of files from the library */ char **getTSMFiles(int *n) { char cmd[1024], fn[1024], path[1024], *p; int nlines, i; char **lines; char *host; FILE *fp; /* get a temporary filename */ (void) strcpy(fn, tmpnam((char *) NULL)); (void) unlink(fn); /* execute dsmc to get a list of filesets in TSM */ if(_chdrive(3)) { err("trying to find dsmc: unable to change to C: drive"); } if(chdir("/program files/tivoli/tsm/baclient")) { err("unable to cd to \\program files\\tivoli\\tsm\\baclient"); } if((host = getenv("COMPUTERNAME")) == (char *) NULL) { err("unable to read environment variable COMPUTERNAME"); } (void) sprintf(cmd, "dsmc.exe query files -virtualnodename=%s -password=%s", host, host); if((fp = _popen(cmd, "r")) == (FILE *) NULL) { (void) sprintf(path, "unable to execute '%s'", cmd); err(path); } while(fgets(path, sizeof(path) - 1, fp)) { if(strchr(path, '\n')) { *(strchr(path, '\n')) = '\0'; } msg(path); /* parse out the fileset name */ if(!strchr(path, '\\')) { continue; } (void) strcpy(path, strchr(path, '\\')); if(strchr(path, '\n')) { *(strchr(path, '\n')) = '\0'; } /* for each fileset, get a list of files in tsm */ (void) sprintf(cmd, "dsmc.exe query backup %s\\ -virtualnodename=%s -password=%s -su=yes -filesonly >> %s", path, host, host, fn); (void) system(cmd); } (void) fclose(fp); /* open the temporary file of TSM files */ if((fp = fopen(fn, "r")) == (FILE *) NULL) { err("unable to read temporary file of TSM files"); } /* how many files found? */ nlines = 0; while(fgets(path, sizeof(path) - 1, fp)) { if(strchr(path, '\\')) { nlines++; } } /* read the lines into memory */ (void) fseek(fp, 0, SEEK_SET); /* rewind to beginning of file */ if((lines = (char **) malloc(sizeof(char*) * nlines)) == (char **) NULL) { err("unable to allocate memory for local files"); } i = 0; while(fgets(path, sizeof(path) - 1, fp)) { if(!strchr(path, '\\')) { /* if the line does not have a '\', skip it */ continue; } if(!strstr(path, host)) { /* if the line does not have the hostname, skip it */ continue; } (void) strcpy(path, strchr(path, '\\')); /* remove all but the filepath */ if((p = strchr(path, '$')) != (char *) NULL) { *p = ':'; (void) strcpy(path, p - 1); } if(strchr(path, '\n')) { /* remove the newline */ *(strchr(path, '\n')) = '\0'; } lines[i++] = strdup(path); } (void) fclose(fp); nlines = i; /* sort the lines */ qsort(lines, nlines, sizeof(char *), linesCompare); /* remove the temporary file */ (void) unlink(fn); *n = nlines; return (char **) lines; } /* get a list of all local files */ void findFiles(FILE *fp, char drive, char *fn) { HANDLE h; WIN32_FIND_DATA finddata; char dir[1024]; (void) strcpy(dir, fn); (void) strcat(dir, "\\*.*"); h = FindFirstFile(dir, &finddata); if(h == INVALID_HANDLE_VALUE) { (void) printf("error %d\n", GetLastError()); } do { if(!strcmp(finddata.cFileName, ".") || !strcmp(finddata.cFileName, "..")) { continue; } if(finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { char path[1024]; (void) strcpy(path, dir); if(strchr(path, '*')) { *(strchr(path, '*')) = '\0'; } (void) strcat(path, finddata.cFileName); findFiles(fp, drive, path); } else { char path[1024]; (void) strcpy(path, dir); if(strchr(path, '*')) { *(strchr(path, '*')) = '\0'; } (void) strcat(path, finddata.cFileName); (void) fprintf(fp, "%c:%s\n", drive, path); } } while(FindNextFile(h, &finddata)); FindClose(h); } /* return a list of all local files */ char **getLocalFiles(int *n) { FILE *fp; int i, nlines; char path[1024], fn[1024]; char **lines; (void) strcpy(fn, tmpnam((char *) NULL)); if((fp = fopen(fn, "w+")) == (FILE *) NULL) { err("unable to create temporary file for local files"); } for(i = 3; i < 27; i++) { if(_chdrive(i)) { continue; } *path = '\0'; findFiles(fp, (char) ('a' + i - 1), path); } /* how many files found? */ (void) fseek(fp, 0, SEEK_SET); /* rewind to beginning of file */ nlines = 0; while(fgets(path, sizeof(path) - 1, fp)) { nlines++; } /* read the lines into memory */ (void) fseek(fp, 0, SEEK_SET); /* rewind to beginning of file */ if((lines = (char **) malloc(sizeof(char*) * nlines)) == (char **) NULL) { err("unable to allocate memory for local files"); } i = 0; while(fgets(path, sizeof(path) - 1, fp)) { if(strchr(path, '\n')) { *(strchr(path, '\n')) = '\0'; } lines[i++] = strdup(path); } (void) fclose(fp); /* sort the lines */ qsort(lines, nlines, sizeof(char *), linesCompare); /* remove the temporary file */ (void) unlink(fn); *n = nlines; return (char **) lines; } /* parse the dsm.opt file */ void parseDSMFile(char *fn) { } /* compare the TSM list and local list */ /* initially I'm using a brute force algorithm, this could be a *lot* nicer */ void compareLists(char **lfiles, int nlfiles, char **rfiles, int nrfiles) { int i, j, nfound; char buf[1024]; nfound = 0; for(i = 0; i < nlfiles; i++) { for(j = 0; j < nrfiles; j++) { if(lfiles[i] && !strcmp(lfiles[i], rfiles[j])) { (void) free(lfiles[i]); lfiles[i] = (char *) NULL; nfound++; break; } } } /* statistics */ msg(""); msg("File statistics:"); (void) sprintf(buf, "\t Found: %20d", nfound); msg(buf); (void) sprintf(buf, "\tNot Found: %20d", nlfiles - nfound); msg(buf); /* files */ msg("\nLocal files not existing in TSM library:"); for(i = 0; i < nlfiles; i++) { if(lfiles[i]) { msg(lfiles[i]); } } } int main(int argc, char **argv) { char **lfiles, **rfiles, buf[1024]; int nlfiles, nrfiles; WORD versionRequested; WSADATA wsadata; char *host = argv[1]; int port = 25; int s; SOCKADDR_IN sin; LPHOSTENT hp; /* connect to a smtp server, close stdout/stderr, reopen them to the smtp server */ versionRequested = MAKEWORD(2, 2); if(WSAStartup(versionRequested, &wsadata)) { err("error starting sockets"); } /* connect to the host */ if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) { err("invalid socket"); } if((hp = gethostbyname(host)) == (LPHOSTENT) NULL) { err("could not get host entry"); } sin.sin_family = AF_INET; sin.sin_addr = *((LPIN_ADDR)*hp->h_addr_list); sin.sin_port = htons(port); if((connect(s, &sin, sizeof(sin))) == SOCKET_ERROR) { err("unable to connect to server"); } /* convert stdout/stderr to the socket */ smtp = s; /* tell the smtp server whom to send to */ (void) sprintf(buf, "HELO %s", getenv("COMPUTERNAME")); msg(buf); (void) _sleep(3000); (void) sprintf(buf, "mail from: dsmcmp@%s", getenv("COMPUTERNAME")); msg(buf); (void) _sleep(3000); msg("rcpt to: tsmadmin@DOMAIN"); (void) _sleep(3000); msg("data"); (void) _sleep(3000); (void) sprintf(buf, "Subject: Local files not in TSM on server %s\n\n", getenv("COMPUTERNAME")); msg(buf); if(_chdrive(3)) { err("trying to find dsmc: unable to change to C: drive\n"); } if(chdir("/")) { err("unable to cd to \\\n"); } lfiles = getLocalFiles(&nlfiles); rfiles = getTSMFiles(&nrfiles); compareLists(lfiles, nlfiles, rfiles, nrfiles); /* stop sending the email */ msg("."); (void) _sleep(3); msg("quit"); (void) _sleep(3); /* close sockets */ closesocket(s); (void) WSACleanup(); return 0; }