char * getwd(char *pathname) { DIR *dp; struct dirent *d; extern int errno; struct stat st_root, st_cur, st_next, st_dotdot; char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2]; char *pathptr, *nextpathptr, *cur_name_add; /* find the inode of root */ if (stat("/", &st_root) == -1) { (void)sprintf(pathname, "getwd: Cannot stat \"/\" (%s)", strerror(errno)); return (NULL); } pathbuf[MAXPATHLEN - 1] = '\0'; pathptr = &pathbuf[MAXPATHLEN - 1]; nextpathbuf[MAXPATHLEN - 1] = '\0'; cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1]; /* find the inode of the current directory */ if (lstat(".", &st_cur) == -1) { (void)sprintf(pathname, "getwd: Cannot stat \".\" (%s)", strerror(errno)); return (NULL); } nextpathptr = strrcpy(nextpathptr, "../"); /* Descend to root */ for (;;) { /* look if we found root yet */ if (st_cur.st_ino == st_root.st_ino && DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) { (void)strcpy(pathname, *pathptr != '/' ? "/" : pathptr); return (pathname); } /* open the parent directory */ if (stat(nextpathptr, &st_dotdot) == -1) { (void)sprintf(pathname, "getwd: Cannot stat directory \"%s\" (%s)", nextpathptr, strerror(errno)); return (NULL); } if ((dp = opendir(nextpathptr)) == NULL) { (void)sprintf(pathname, "getwd: Cannot open directory \"%s\" (%s)", nextpathptr, strerror(errno)); return (NULL); } /* look in the parent for the entry with the same inode */ if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) { /* Parent has same device. No need to stat every member */ for (d = readdir(dp); d != NULL; d = readdir(dp)) if (d->d_fileno == st_cur.st_ino) break; } else { /* * Parent has a different device. This is a mount point so we * need to stat every member */ for (d = readdir(dp); d != NULL; d = readdir(dp)) { if (ISDOT(d->d_name) || ISDOTDOT(d->d_name)) continue; (void)strcpy(cur_name_add, d->d_name); if (lstat(nextpathptr, &st_next) == -1) { (void)sprintf(pathname, "getwd: Cannot stat \"%s\" (%s)", d->d_name, strerror(errno)); (void)closedir(dp); return (NULL); } /* check if we found it yet */ if (st_next.st_ino == st_cur.st_ino && DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev)) break; } } if (d == NULL) { (void)sprintf(pathname, "getwd: Cannot find \".\" in \"..\""); (void)closedir(dp); return (NULL); } st_cur = st_dotdot; pathptr = strrcpy(pathptr, d->d_name); pathptr = strrcpy(pathptr, "/"); nextpathptr = strrcpy(nextpathptr, "../"); (void)closedir(dp); *cur_name_add = '\0'; } } /* end getwd */
void move_infected(const char *filename, const struct optstruct *opt) { char *movedir, *movefilename, *tmp, numext[4 + 1]; struct stat fstat, mfstat; int n, len, movefilename_size; struct utimbuf ubuf; if(!(movedir = getargl(opt, "move"))) { /* Should never reach here */ mprintf("@getargc() returned NULL\n", filename); notmoved++; return; } if(access(movedir, W_OK|X_OK) == -1) { mprintf("@error moving file '%s': cannot write to '%s': %s\n", filename, movedir, strerror(errno)); notmoved++; return; } if(stat(filename, &fstat) == -1) { mprintf("@Can't stat file %s\n", filename); mprintf("Try to run clamdscan with clamd privileges\n"); notmoved++; return; } if(!(tmp = strrchr(filename, '/'))) tmp = (char *) filename; movefilename_size = sizeof(char) * (strlen(movedir) + strlen(tmp) + sizeof(numext) + 2); if(!(movefilename = mmalloc(movefilename_size))) { mprintf("@Memory allocation error\n"); exit(2); } if(!(strrcpy(movefilename, movedir))) { mprintf("@strrcpy() returned NULL\n"); notmoved++; free(movefilename); return; } strcat(movefilename, "/"); if(!(strcat(movefilename, tmp))) { mprintf("@strcat() returned NULL\n"); notmoved++; free(movefilename); return; } if(!stat(movefilename, &mfstat)) { if(fstat.st_ino == mfstat.st_ino) { /* It's the same file*/ mprintf("File excluded '%s'\n", filename); logg("File excluded '%s'\n", filename); notmoved++; free(movefilename); return; } else { /* file exists - try to append an ordinal number to the * quranatined file in an attempt not to overwrite existing * files in quarantine */ len = strlen(movefilename); n = 0; do { /* reset the movefilename to it's initial value by * truncating to the original filename length */ movefilename[len] = 0; /* append .XXX */ sprintf(numext, ".%03d", n++); strcat(movefilename, numext); } while(!stat(movefilename, &mfstat) && (n < 1000)); } } if(rename(filename, movefilename) == -1) { if(filecopy(filename, movefilename) == -1) { mprintf("@cannot move '%s' to '%s': %s\n", filename, movefilename, strerror(errno)); notmoved++; free(movefilename); return; } chmod(movefilename, fstat.st_mode); chown(movefilename, fstat.st_uid, fstat.st_gid); ubuf.actime = fstat.st_atime; ubuf.modtime = fstat.st_mtime; utime(movefilename, &ubuf); if(unlink(filename)) { mprintf("@cannot unlink '%s': %s\n", filename, strerror(errno)); notremoved++; free(movefilename); return; } } mprintf("%s: moved to '%s'\n", filename, movefilename); logg("%s: moved to '%s'\n", filename, movefilename); free(movefilename); }