void showusers(int n, int mode, char *ucomp, char raw) { char status [20]; char online [20]; char *filename = 0; char realfile [512]; char bar [20]; struct timeval tstop; double mb_xfered = 0; double speed , pct = 0; double my_filesize = 0; int mask; int noshow; char maskchar; int i , x, m; unsigned hours; unsigned char minutes; unsigned seconds; gettimeofday(&tstop, (struct timezone *)0); if (!strncasecmp(count_hidden, "false", 5)) chidden = 0; for (x = 0; x < n; x++) { if (!user[x].procid) continue; maskchar = ' '; mask = noshow = 0; if (strcomp(husers, user[x].username) || strcomp(hgroups, get_g_name(user[x].groupid))) { if (showall) maskchar = '*'; else noshow++; } if (noshow == 0 && strlen(mpaths)) { if (maskchar == ' ' && matchpath(mpaths, user[x].currentdir)) { if (showall) maskchar = '*'; else mask++; } } if (strplen(user[x].status) > 5) filename = malloc(strplen(user[x].status) - 5 + 1); else filename = malloc(1); if ((!strncasecmp(user[x].status, "STOR ", 5) || !strncasecmp(user[x].status, "APPE ", 5)) && user[x].bytes_xfer) { speed = user[x].bytes_xfer / 1024. / ((tstop.tv_sec - user[x].tstart.tv_sec) * 1. + (tstop.tv_usec - user[x].tstart.tv_usec) / 1000000.); if (debug) { printf("DEBUG SPEED INFO: username = %s\nDEBUG SPEED INFO: time spent = %.2f seconds\nDEBUG SPEED INFO: transfered = %.0f KB\nDEBUG SPEED INFO: speed = %.2f KB/s\n", user[x].username, ((tstop.tv_sec - user[x].tstart.tv_sec) * 1. + (tstop.tv_usec - user[x].tstart.tv_usec) / 1000000.), (double)(user[x].bytes_xfer / 1024.), speed); } if ((!noshow && !mask && !(maskchar == '*')) || chidden) { total_up_speed += speed; uploads++; } if (!mask) { pct = -1; m = strplen(user[x].status) - 5; if (m < 15 || raw) sprintf(filename, "%.*s", m, user[x].status + 5); else sprintf(filename, "%.15s", user[x].status + m - 10); strcpy(bar, "?->"); if (!raw) if (speed > threshold) { speed = (speed / 1024.0); sprintf(status, "Up: %7.2fMB/s", speed); } else { sprintf(status, "Up: %7.0fKB/s", speed); } else if (raw == 1) sprintf(status, "\"UP\" \"%.0f\"", speed); else sprintf(status, "upld|%.0f", speed); mb_xfered = user[x].bytes_xfer * 1.0 / 1024 / 1024; } } else if ((!strncasecmp(user[x].status, "RETR ", 5) && user[x].bytes_xfer)) { mb_xfered = 0; sprintf(realfile, "%s", user[x].currentdir); /* * Dirty way to get around the fact that the buffered * reading will change user[x].currentdir to not * include filename once it's done reading the entire * file "to memory". This means user[x].currentdir in * fact will be _currentdir_ and this cannot tell us * a true filesize since it's calculated from * filesize(/site/incoming/path) - w/o filename :( */ my_filesize = filesize(realfile); if (my_filesize < user[x].bytes_xfer) { my_filesize = user[x].bytes_xfer; } pct = (user[x].bytes_xfer * 1. / my_filesize) * 100; i = 15 * user[x].bytes_xfer * 1. / my_filesize; i = (i > 15 ? 15 : i); bar[i] = 0; for (m = 0; m < i; m++) bar[m] = 'x'; speed = user[x].bytes_xfer / 1024. / ((tstop.tv_sec - user[x].tstart.tv_sec) * 1. + (tstop.tv_usec - user[x].tstart.tv_usec) / 1000000.); if (debug) { printf("DEBUG SPEED INFO: username = %s\nDEBUG SPEED INFO: time spent = %.2f seconds\nDEBUG SPEED INFO: transfered = %.0f KB\nDEBUG SPEED INFO: speed = %.2f KB/s\n", user[x].username, ((tstop.tv_sec - user[x].tstart.tv_sec) * 1. + (tstop.tv_usec - user[x].tstart.tv_usec) / 1000000.), (double)(user[x].bytes_xfer / 1024.), speed); } if ((!noshow && !mask && !(maskchar == '*')) || chidden) { total_dn_speed += speed; downloads++; } m = strplen(user[x].status) - 5; if (!mask) { if (m < 15 || raw) sprintf(filename, "%.*s", m, user[x].status + 5); else sprintf(filename, "%.15s", user[x].status + m - 10); if (!raw) if (speed > threshold) { speed = (speed / 1024.0); sprintf(status, "Dn: %7.2fMB/s", speed); } else { sprintf(status, "Dn: %7.0fKB/s", speed); } else if (raw == 1) sprintf(status, "\"DN\" \"%.1f\"", speed); else sprintf(status, "dnld|%.1f", speed); } } else { pct = *bar = *filename = hours = minutes = mb_xfered = 0; seconds = tstop.tv_sec - user[x].tstart.tv_sec; while (seconds >= 3600) { hours++; seconds -= 3600; } while (seconds >= 60) { minutes++; seconds -= 60; } if ((!noshow && !mask && !(maskchar == '*')) || chidden) { if ((int)seconds > idle_barrier) idlers++; else browsers++; } if (!raw) sprintf(status, "Idle: %02d:%02d:%02d", hours, minutes, seconds); else if (raw == 1) sprintf(status, "\"ID\" \"%d\"", (hours * 60 * 60) + (minutes * 60) + seconds); else sprintf(status, "idle|%02d:%02d:%02d", hours, minutes, seconds); } hours = minutes = 0; seconds = tstop.tv_sec - user[x].login_time; while (seconds >= 3600) { hours++; seconds -= 3600; } while (seconds >= 60) { minutes++; seconds -= 60; } sprintf(online, "%02d:%02d:%02d", hours, minutes, seconds); if (mode == 0 && raw != 3 ) { if (!raw && (showall || (!noshow && !mask && !(maskchar == '*')))) { if (mb_xfered) printf("|%1c%-16.16s/%-10.10s | %-15s | XFER: %13.1fMB |\n", maskchar, user[x].username, get_g_name(user[x].groupid), status, mb_xfered); else printf("|%1c%-16.16s/%-10.10s | %-15s | %3.0f%%: %-15.15s |\n", maskchar, user[x].username, get_g_name(user[x].groupid), status, pct, bar); printf("| %-27.27s | since %8.8s | file: %-15.15s |\n", user[x].tagline, online, filename); printf("+-----------------------------------------------------------------------+\n"); } else if (raw == 1 && (showall || (!noshow && !mask && !(maskchar == '*')))) { /* * Maskeduser / Username / GroupName / Status * / TagLine / Online / Filename / Part * up/down-loaded / Current dir / PID */ printf("\"USER\" \"%1c\" \"%s\" \"%s\" %s \"%s\" \"%s\" \"%s\" \"%.1f%s\" \"%s\" \"%d\"\n", maskchar, user[x].username, get_g_name(user[x].groupid), status, user[x].tagline, online, filename, (pct >= 0 ? pct : mb_xfered), (pct >= 0 ? "%" : "MB"), user[x].currentdir, user[x].procid); } else if (showall || (!noshow && !mask && !(maskchar == '*'))) { printf("%s|%s|%s|%s|%s\n", user[x].username, get_g_name(user[x].groupid), user[x].tagline, status, filename); } if ((!noshow && !mask && !(maskchar == '*')) || chidden) { onlineusers++; } } else if (raw == 3) { if ((!noshow && !mask && !(maskchar == '*')) || chidden) { onlineusers++; } } else if (user[x].username && !strcmp(ucomp, user[x].username)) { #ifdef _WITH_ALTWHO if (!raw && (showall || (!noshow && !mask && !(maskchar == '*')))) { if (mb_xfered) printf("%s : %1c%s/%s has xfered %.1fMB of %s and has been online for %8.8s.\n", status, maskchar, user[x].username, get_g_name(user[x].groupid), mb_xfered, filename, online); else if (strcmp(filename, "")) printf("%s : %1c%s/%s has xfered %.0f%% of %s and has been online for %8.8s.\n", status, maskchar, user[x].username, get_g_name(user[x].groupid), pct, filename, online); else printf("%s : %1c%s/%s has been online for %8.8s.\n", status, maskchar, user[x].username, get_g_name(user[x].groupid), online); } else if (raw == 1 && (showall || (!noshow && !mask && !(maskchar == '*')))) { printf("\"USER\" \"%1c\" \"%s\" \"%s\" %s \"%s\" \"%s\" \"%s\" \"%.1f%s\" \"%s\" \"%d\"\n", maskchar, user[x].username, get_g_name(user[x].groupid), status, user[x].tagline, online, filename, (pct >= 0 ? pct : mb_xfered), (pct >= 0 ? "%" : "MB"), user[x].currentdir, user[x].procid); } else if (showall || (!noshow && !mask && !(maskchar == '*'))) { printf("%s|%s|%s|%s|%s\n", user[x].username, get_g_name(user[x].groupid), user[x].tagline, status, filename); } #else if (!onlineusers) { if (!raw && (showall || (!noshow && !mask && !(maskchar == '*')))) printf("\002%s\002 - %s", user[x].username, status); else if (raw == 1 && (showall || (!noshow && !mask && !(maskchar == '*')))) printf("\"USER\" \"%s\" %s", user[x].username, status); else if (showall || (!noshow && !mask && !(maskchar == '*'))) printf("\002%s\002 - %s", user[x].username, status); } else { if (!raw && (showall || (!noshow && !mask && !(maskchar == '*')))) printf(" - %s", status); else if (raw == 1 && (showall || (!noshow && !mask && !(maskchar == '*')))) printf("\"USER\" \"\" %s", status); else if (showall || (!noshow && !mask && !(maskchar == '*'))) printf(" - %s", status); } #endif if (!noshow && !mask && !(maskchar == '*')) onlineusers++; else if (chidden) onlineusers++; } free(filename); } }
int main(int argc, char *argv[]) { int n, l, complete_type = 0, not_allowed = 0, argv_mode = 0; #ifdef USING_GLFTPD int gnum = 0, unum = 0; char myflags[20]; #endif char *ext, exec[4096], *complete_bar = 0, *inc_point[2]; unsigned int crc; struct stat fileinfo; uid_t f_uid; gid_t f_gid; double temp_time = 0; DIR *dir, *parent; struct dirent *dp; long loc; time_t timenow; #if (test_for_password || extract_nfo || zip_clean) off_t tempstream; #endif short rescan_quick = rescan_default_to_quick; char one_name[NAME_MAX]; char *temp_p = NULL; int chdir_allowed = 0, argnum = 0; GLOBAL g; #if (enable_rescan_script) char target[PATH_MAX+NAME_MAX]; #endif #if ( program_uid > 0 ) setegid(program_gid); seteuid(program_uid); #endif umask(0666 & 000); d_log("rescan: PZS-NG (rescan v2) %s debug log.\n", ng_version); d_log("rescan: Rescan executed by: (uid/gid) %d/%d\n", geteuid(), getegid()); #ifdef _ALT_MAX d_log("rescan: PATH_MAX not found - using predefined settings! Please report to the devs!\n"); #endif d_log("rescan: Allocating memory for variables\n"); g.ui = ng_realloc2(g.ui, sizeof(*g.ui) * 30, 1, 1, 1); g.gi = ng_realloc2(g.gi, sizeof(*g.gi) * 30, 1, 1, 1); bzero(one_name, NAME_MAX); #ifdef USING_GLFTPD if (getenv("FLAGS")) { strlcpy(myflags, getenv("FLAGS"), sizeof(myflags)); n = strlen(myflags); while (n > 0) { --n; l = strlen(rescan_chdir_flags); while(l > 0) { --l; if (myflags[n] == rescan_chdir_flags[l]) chdir_allowed = 1; } } } if (!geteuid()) chdir_allowed = 1; #endif /* With glftpd we can use env vars, rest of the world: commandline. */ #ifndef USING_GLFTPD if (argc < 7) { print_syntax(chdir_allowed); ng_free(g.ui); ng_free(g.gi); return 0; } argnum = 6; if (chdir(argv[5]) != 0) { printf("Could not chdir to <cwd = '%s'>, ftpd agnostic mode: %s\n", argv[5], strerror(errno)); d_log("rescan: Could not chdir to <cwd = '%s'>, ftpd agnostic mode: %s\n", argv[5], strerror(errno)); ng_free(g.ui); ng_free(g.gi); return 1; } #else argnum = 1; #endif while ((argnum < argc) && argc > 1) { if (!strncasecmp(argv[argnum], "--quick", 7)) rescan_quick = TRUE; else if (!strncasecmp(argv[argnum], "--normal", 8)) rescan_quick = FALSE; else if (!strncasecmp(argv[argnum], "--dir=", 6) && (strlen(argv[argnum]) > 7) && chdir_allowed) { temp_p = argv[argnum] + 6; if ((!matchpath(nocheck_dirs, temp_p)) && (matchpath(zip_dirs, temp_p) || matchpath(sfv_dirs, temp_p)) && !matchpath(group_dirs, temp_p)) { if (chdir(temp_p)) { d_log("rescan: Failed to chdir() to %s : %s\n", temp_p, strerror(errno)); not_allowed = 1; } } else { printf("Not allowed to chdir() to %s\n", temp_p); ng_free(g.ui); ng_free(g.gi); return 1; } printf("PZS-NG Rescan %s: Rescanning %s\n", ng_version, temp_p); argv_mode = 1; } else if (!strncasecmp(argv[argnum], "--chroot=", 9) && (strlen(argv[argnum]) > 10) && chdir_allowed) { if (temp_p == NULL) { temp_p = argv[argnum] + 9; if (chroot(temp_p) == -1) { d_log("rescan: Failed to chroot() to %s : %s\n", temp_p, strerror(errno)); not_allowed = 1; } } else { temp_p = argv[argnum] + 9; printf("Not allowed to chroot() to %s\n", temp_p); ng_free(g.ui); ng_free(g.gi); return 1; } printf("PZS-NG Rescan %s: Chroot'ing to %s\n", ng_version, temp_p); argv_mode = 1; } else if (!strncasecmp(argv[argnum], "--help", 6) || !strncasecmp(argv[argnum], "/?", 2) || !strncasecmp(argv[argnum], "--?", 3)) { print_syntax(chdir_allowed); ng_free(g.ui); ng_free(g.gi); return 0; } else { strlcpy(one_name, argv[argnum], sizeof(one_name)); rescan_quick = FALSE; printf("PZS-NG Rescan %s: Rescanning in FILE mode\n", ng_version); if (one_name[strlen(one_name) - 1] == '*') { one_name[strlen(one_name) - 1] = '\0'; } else if (!fileexists(one_name)) { d_log("PZS-NG Rescan: No file named '%s' exists.\n", one_name); one_name[0] = '\0'; not_allowed = 1; } argv_mode = 1; } argnum++; } if (one_name[0] == '\0') { if (rescan_quick == TRUE) { printf("PZS-NG Rescan %s: Rescanning in QUICK mode.\n", ng_version); } else { printf("PZS-NG Rescan %s: Rescanning in NORMAL mode.\n", ng_version); } } printf("PZS-NG Rescan %s: Use --help for options.\n\n", ng_version); if (not_allowed) { ng_free(g.ui); ng_free(g.gi); return 1; } if (!getcwd(g.l.path, PATH_MAX)) { d_log("rescan: getcwd() failed: %s\n", strerror(errno)); } if (subcomp(g.l.path, g.l.basepath) && (g.l.basepath[0] == '\0')) strlcpy(g.l.basepath, g.l.path, sizeof(g.l.basepath)); if (strncmp(g.l.path, g.l.basepath, PATH_MAX)) d_log("rescan: We are in subdir of %s\n", g.l.basepath); strlcpy(g.v.misc.current_path, g.l.path, sizeof(g.v.misc.current_path)); strlcpy(g.v.misc.basepath, g.l.basepath, sizeof(g.v.misc.basepath)); if ((matchpath(nocheck_dirs, g.l.path) && !rescan_nocheck_dirs_allowed) || (matchpath(group_dirs, g.l.path) && argv_mode) || (!matchpath(nocheck_dirs, g.l.path) && !matchpath(zip_dirs, g.l.path) && !matchpath(sfv_dirs, g.l.path) && !matchpath(group_dirs, g.l.path)) || insampledir(g.l.path)) { d_log("rescan: Dir matched with nocheck_dirs/sample_list, or is not in the zip/sfv/group-dirs.\n"); d_log("rescan: Freeing memory, and exiting.\n"); printf("Notice: Unable to rescan this dir - check config.\n\n"); ng_free(g.ui); ng_free(g.gi); return 0; } g.v.misc.slowest_user[0] = ULONG_MAX; bzero(&g.v.total, sizeof(struct race_total)); g.v.misc.fastest_user[0] = 0; g.v.misc.release_type = RTYPE_NULL; g.v.misc.write_log = 0; #ifdef USING_GLFTPD if (getenv("SECTION") == NULL) { sprintf(g.v.sectionname, "DEFAULT"); } else { snprintf(g.v.sectionname, sizeof(g.v.sectionname), "%s", getenv("SECTION")); } #else snprintf(g.v.sectionname, sizeof(g.v.sectionname), argv[4]); #endif g.l.length_path = (int)strlen(g.l.path); g.l.length_zipdatadir = sizeof(storage); n = g.l.length_path + g.l.length_zipdatadir + 11; g.l.race = ng_realloc2(g.l.race, n, 1, 1, 1); g.l.sfv = ng_realloc2(g.l.sfv, n - 1, 1, 1, 1); g.l.sfvbackup = ng_realloc2(g.l.sfvbackup, n + 1, 1, 1, 1); g.l.leader = ng_realloc2(g.l.leader, n - 2, 1, 1, 1); g.l.sfv_incomplete = 0; getrelname(&g); #ifdef USING_GLFTPD gnum = buffer_groups(GROUPFILE, 0); unum = buffer_users(PASSWDFILE, 0); #endif sprintf(g.l.sfv, storage "/%s/sfvdata", g.l.path); sprintf(g.l.sfvbackup, storage "/%s/sfvbackup", g.l.path); sprintf(g.l.leader, storage "/%s/leader", g.l.path); sprintf(g.l.race, storage "/%s/racedata", g.l.path); d_log("rescan: Creating directory to store racedata in\n"); maketempdir(g.l.path); d_log("rescan: Locking release\n"); while (1) { if ((l = create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 3, 0))) { d_log("rescan: Failed to lock release.\n"); if (l == 1) { d_log("rescan: version mismatch. Exiting.\n"); printf("Error. You need to rm -fR ftp-data/pzs-ng/* before rescan will work.\n"); /* */ ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } if (l == PROGTYPE_POSTDEL) { n = (signed int)g.v.data_incrementor; d_log("rescan: Detected postdel running - sleeping for one second.\n"); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; usleep(1000000); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; if ( n == (signed int)g.v.data_incrementor) { d_log("rescan: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 2, g.v.data_queue)) { d_log("rescan: Failed to force a lock.\n"); d_log("rescan: Exiting with error.\n"); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } break; } } else { for (l = 0; l <= max_seconds_wait_for_lock * 10; ++l) { d_log("rescan: sleeping for .1 second before trying to get a lock (queue: %d).\n", g.v.data_queue); usleep(100000); if (!create_lock(&g.v, g.l.path, PROGTYPE_RESCAN, 0, g.v.data_queue)) break; } if (l >= max_seconds_wait_for_lock * 10) { d_log("rescan: Failed to get lock. Will not force unlock.\n"); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(EXIT_FAILURE); } } } usleep(10000); if (update_lock(&g.v, 1, 0) != -1) break; } move_progress_bar(1, &g.v, g.ui, g.gi); if (g.l.incomplete) unlink(g.l.incomplete); if (del_completebar) removecomplete(); dir = opendir("."); parent = opendir(".."); if (!((rescan_quick && findfileext(dir, ".sfv")) || *one_name)) { if (g.l.sfv) unlink(g.l.sfv); if (g.l.race) unlink(g.l.race); } printf("Rescanning files...\n"); if (findfileext(dir, ".zip")) { if (!fileexists(unzip_bin)) { printf("rescan: ERROR! Not able to check zip-files - %s does not exist!\n", unzip_bin); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); exit(EXIT_FAILURE); } else { crc = 0; rewinddir(dir); timenow = time(NULL); while ((dp = readdir(dir))) { ext = find_last_of(dp->d_name, "."); if (*ext == '.') ext++; if (!strcasecmp(ext, "zip")) { stat(dp->d_name, &fileinfo); f_uid = fileinfo.st_uid; f_gid = fileinfo.st_gid; if ((timenow == fileinfo.st_ctime) && (fileinfo.st_mode & 0111)) { d_log("rescan.c: Seems this file (%s) is in the process of being uploaded. Ignoring for now.\n", dp->d_name); continue; } #ifdef USING_GLFTPD strlcpy(g.v.user.name, get_u_name(f_uid), sizeof(g.v.user.name)); strlcpy(g.v.user.group, get_g_name(f_gid), sizeof(g.v.user.group)); #else strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif strlcpy(g.v.file.name, dp->d_name, sizeof(g.v.file.name)); g.v.file.speed = 2005 * 1024; g.v.file.size = fileinfo.st_size; g.v.total.start_time = 0; #if (test_for_password || extract_nfo) tempstream = telldir(dir); if ((!findfileextcount(dir, ".nfo") || findfileextcount(dir, ".zip")) && !mkdir(".unzipped", 0777)) snprintf(exec, sizeof(exec), "%s -qqjo \"%s\" -d .unzipped 2>.delme", unzip_bin, g.v.file.name); else snprintf(exec, sizeof(exec), "%s -qqt \"%s\" 2>.delme", unzip_bin, g.v.file.name); seekdir(dir, tempstream); #else snprintf(exec, sizeof(exec), "%s -qqt \"%s\" 2>.delme", unzip_bin, g.v.file.name); #endif if (system(exec) == 0 || (allow_error2_in_unzip == TRUE && errno < 3 )) { writerace(g.l.race, &g.v, crc, F_CHECKED); } else { writerace(g.l.race, &g.v, crc, F_BAD); if (g.v.file.name) unlink(g.v.file.name); removedir(".unzipped"); continue; } #if (test_for_password || extract_nfo || zip_clean) tempstream = telldir(dir); if ((!findfileextcount(dir, ".nfo") || findfileextcount(dir, ".zip")) && check_zipfile(".unzipped", g.v.file.name, findfileextcount(dir, ".nfo"))) { d_log("rescan: File %s is password protected.\n", g.v.file.name); writerace(g.l.race, &g.v, crc, F_BAD); if (g.v.file.name) unlink(g.v.file.name); seekdir(dir, tempstream); continue; } seekdir(dir, tempstream); #endif if (!fileexists("file_id.diz")) { snprintf(exec, sizeof(exec), "%s -qqjnCLL \"%s\" file_id.diz 2>.delme", unzip_bin, g.v.file.name); if (execute(exec) != 0) { d_log("rescan: No file_id.diz found (#%d): %s\n", errno, strerror(errno)); } else { if (fileexists("file_id.diz.bad")) { loc = findfile(dir, "file_id.diz.bad"); seekdir(dir, loc); dp = readdir(dir); unlink(dp->d_name); } if (chmod("file_id.diz", 0666)) d_log("rescan: Failed to chmod %s: %s\n", "file_id.diz", strerror(errno)); } } } } if (fileexists(".delme")) unlink(".delme"); g.v.total.files = read_diz(); if (!g.v.total.files) { g.v.total.files = 1; unlink("file_id.diz"); } g.v.total.files_missing = g.v.total.files; readrace(g.l.race, &g.v, g.ui, g.gi); sortstats(&g.v, g.ui, g.gi); if (g.v.total.files_missing < 0) { g.v.total.files -= g.v.total.files_missing; g.v.total.files_missing = 0; } buffer_progress_bar(&g.v); if (g.v.total.files_missing == 0) { complete(&g, complete_type); createstatusbar(convert(&g.v, g.ui, g.gi, zip_completebar)); #if (chmod_completebar) if (!matchpath(group_dirs, g.l.path)) { if (chmod_each(convert(&g.v, g.ui, g.gi, zip_completebar), 0222)) d_log("rescan: Failed to chmod a statusbar: %s\n", strerror(errno)); } #endif } else { if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } } move_progress_bar(0, &g.v, g.ui, g.gi); } if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("rescan: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } } } } } } else if ((temp_p = findfileext(dir, ".sfv")) || (create_missing_sfv && file_count(dir))) { if (!temp_p && create_missing_sfv && file_count(dir)) { d_log("rescan: No sfv found - creating one.\n"); make_sfv(g.l.path); if (!(temp_p = findfileext(dir, ".sfv"))) { d_log("rescan: Freeing memory, removing lock and exiting.\n"); unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); unlink(g.l.race); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); return 0; } } #if ( create_missing_sfv_link == TRUE ) d_log("rescan: Removing missing-sfv indicator (if any)\n"); unlink(g.l.sfv_incomplete); #endif strlcpy(g.v.file.name, temp_p, sizeof(g.v.file.name)); maketempdir(g.l.path); stat(g.v.file.name, &fileinfo); if (copysfv(g.v.file.name, g.l.sfv, &g.v)) { printf("Found invalid entries in SFV - Exiting.\n"); while ((dp = readdir(dir))) { ext = find_last_of(dp->d_name, "-"); if (!strcasecmp(ext, "-missing")) unlink(dp->d_name); } d_log("rescan: Freeing memory, removing lock and exiting\n"); unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); unlink(g.l.race); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); return 0; } g.v.total.start_time = 0; rewinddir(dir); while ((dp = readdir(dir))) { if (*one_name && strncasecmp(one_name, dp->d_name, strlen(one_name))) continue; l = (int)strlen(dp->d_name); ext = find_last_of(dp->d_name, ".-"); if (*ext == '.') ext++; if (!update_lock(&g.v, 1, 0)) { d_log("rescan: Another process wants the lock - will comply and remove lock, then exit.\n"); closedir(dir); closedir(parent); ng_free(g.ui); ng_free(g.gi); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); ng_free(g.l.race); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif remove_lock(&g.v); exit(EXIT_FAILURE); } if ( !strcomp(ignored_types, ext) && (!(strcomp(allowed_types, ext) && !matchpath(allowed_types_exemption_dirs, g.l.path))) && strcasecmp("sfv", ext) && strcasecmp("nfo", ext) && strcasecmp("bad", ext) && strcasecmp("-missing", ext) && strncmp(dp->d_name, ".", 1) ) { stat(dp->d_name, &fileinfo); if (S_ISDIR(fileinfo.st_mode)) continue; if (ignore_zero_sized_on_rescan && !fileinfo.st_size) continue; f_uid = fileinfo.st_uid; f_gid = fileinfo.st_gid; #ifdef USING_GLFTPD strlcpy(g.v.user.name, get_u_name(f_uid), sizeof(g.v.user.name)); strlcpy(g.v.user.group, get_g_name(f_gid), sizeof(g.v.user.group)); #else strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif strlcpy(g.v.file.name, dp->d_name, sizeof(g.v.file.name)); g.v.file.speed = 2005 * 1024; g.v.file.size = fileinfo.st_size; temp_time = fileinfo.st_mtime; if (g.v.total.start_time == 0) g.v.total.start_time = temp_time; else g.v.total.start_time = (g.v.total.start_time < temp_time ? g.v.total.start_time : temp_time); g.v.total.stop_time = (temp_time > g.v.total.stop_time ? temp_time : g.v.total.stop_time); /* Hide users in group_dirs */ if (matchpath(group_dirs, g.l.path) && (hide_group_uploaders == TRUE)) { d_log("rescan: Hiding user in group-dir:\n"); if ((int)strlen(hide_gname) > 0) { snprintf(g.v.user.group, sizeof(g.v.user.group), "%s", hide_gname); d_log("rescan: Changing groupname\n"); } if ((int)strlen(hide_uname) > 0) { snprintf(g.v.user.name, sizeof(g.v.user.name), "%s", hide_uname); d_log("rescan: Changing username\n"); } #if (show_users_in_group_dirs == FALSE) if ((int)strlen(hide_uname) == 0) { d_log("rescan: Making username = groupname\n"); snprintf(g.v.user.name, sizeof(g.v.user.name), "%s", g.v.user.group); } #endif } if (!rescan_quick || (g.l.race && !match_file(g.l.race, dp->d_name))) crc = calc_crc32(dp->d_name); else crc = 1; if (!S_ISDIR(fileinfo.st_mode)) { if (g.v.file.name) unlink_missing(g.v.file.name); if (l > 44) { if (crc == 1) printf("\nFile: %s CHECKED", dp->d_name + l - 44); else printf("\nFile: %s %.8x", dp->d_name + l - 44, crc); } else { if (crc == 1) printf("\nFile: %-44s CHECKED", dp->d_name); else printf("\nFile: %-44s %.8x", dp->d_name, crc); } } if(fflush(stdout)) d_log("rescan: ERROR: %s\n", strerror(errno)); if (!rescan_quick || (g.l.race && !match_file(g.l.race, dp->d_name)) || !fileexists(dp->d_name)) writerace(g.l.race, &g.v, crc, F_NOTCHECKED); } } printf("\n"); testfiles(&g.l, &g.v, 1); printf("\n"); readsfv(g.l.sfv, &g.v, 0); readrace(g.l.race, &g.v, g.ui, g.gi); sortstats(&g.v, g.ui, g.gi); buffer_progress_bar(&g.v); if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("rescan: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("rescan: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_nfo()) { d_log("rescan: create_incomplete_nfo() returned something\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #if (create_missing_sample_link) if (g.l.sample_incomplete) { if (findfileextsub(dir) || matchpartialdirname(missing_sample_check_ignore_list, g.v.misc.release_name, missing_sample_check_ignore_dividers)) { d_log("rescan: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else if (matchpath(check_for_missing_sample_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("rescan: Creating missing-sample indicator %s.\n", g.l.sample_incomplete); if (create_incomplete_sample()) { d_log("rescan: create_incomplete_sample() returned something\n"); } } else { if (findfileextsubp(dir)) { d_log("rescan: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else { d_log("rescan: Creating missing-sample indicator (base) %s.\n", g.l.sample_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_sample()) { d_log("rescan: create_incomplete_sample() returned something\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #endif if (g.v.misc.release_type == RTYPE_AUDIO) { get_audio_info(findfileextfromlist(dir, audio_types), &g.v.audio); /* Sort if we're not in a group-dir/nosort-dir. */ if (!matchpath(group_dirs, g.l.path) && !matchpath(audio_nosort_dirs, g.l.path)) { printf(" Resorting release.\n"); audioSort(&g.v.audio, g.l.link_source, g.l.link_target); } } if ((g.v.total.files_missing == 0) && (g.v.total.files > 0)) { switch (g.v.misc.release_type) { case RTYPE_RAR: complete_bar = rar_completebar; break; case RTYPE_OTHER: complete_bar = other_completebar; break; case RTYPE_AUDIO: complete_bar = audio_completebar; #if ( create_m3u == TRUE ) n = snprintf(exec, sizeof(exec), "%s", findfileext(dir, ".sfv")); strcpy(exec + n - 3, "m3u"); create_indexfile(g.l.race, &g.v, exec); #endif break; case RTYPE_VIDEO: complete_bar = video_completebar; break; } complete(&g, complete_type); if (complete_bar) { createstatusbar(convert(&g.v, g.ui, g.gi, complete_bar)); #if (chmod_completebar) if (!matchpath(group_dirs, g.l.path)) { if (chmod_each(convert(&g.v, g.ui, g.gi, complete_bar), 0222)) d_log("rescan: Failed to chmod a statusbar: %s\n", strerror(errno)); } #endif } #if (enable_rescan_script) d_log("rescan: Executing rescan_script script\n"); if (!fileexists(rescan_script)) { d_log("rescan: Warning - rescan_script (%s) - file does not exist!\n", rescan_script); } else { snprintf(target, sizeof(target), rescan_script " \"%s\"", g.v.file.name); if (execute(target) != 0) d_log("rescan: Failed to execute rescan_script: %s\n", strerror(errno)); } #endif } else { if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } } move_progress_bar(0, &g.v, g.ui, g.gi); } } else { int empty = 1; #if (create_missing_sfv_link == TRUE) if ((!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) && g.l.sfv_incomplete && !matchpath(nocheck_dirs, g.l.path) && !matchpath(allowed_types_exemption_dirs, g.l.path)) { rewinddir(dir); while ((dp = readdir(dir))) { stat(dp->d_name, &fileinfo); if (S_ISREG(fileinfo.st_mode)) { ext = find_last_of(dp->d_name, "."); if (*ext == '.') ext++; if (*ext && get_filetype(&g, ext) == 3) { d_log("rescan: Creating missing-sfv indicator %s.\n", g.l.sfv_incomplete); if (create_incomplete_sfv()) d_log("rescan: create_incomplete_sfv() returned something.\n"); empty = 0; break; } } } } #endif if (empty && mark_empty_dirs_as_incomplete_on_rescan) { if (create_incomplete()) { d_log("rescan: create_incomplete() returned something\n"); } printf(" Empty dir - marking as incomplete.\n"); } } printf(" Passed : %i\n", (int)g.v.total.files - (int)g.v.total.files_missing); printf(" Failed : %i\n", (int)g.v.total.files_bad); printf(" Missing: %i\n", (int)g.v.total.files_missing); printf(" Total : %i\n", (int)g.v.total.files); if (g.v.total.files && !g.v.total.files_missing) { g.v.misc.data_completed = 1; } else { g.v.misc.data_completed = 0; } d_log("rescan: Freeing memory and removing lock.\n"); closedir(dir); closedir(parent); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); remove_lock(&g.v); updatestats_free(&g); #ifdef USING_GLFTPD buffer_groups(GROUPFILE, gnum); buffer_users(PASSWDFILE, unum); #endif exit(0); }
/* * Modified : 01.20.2002 Author : Dark0n3 * * Description : Parses file entries from sfv file and store them in a file. * * Todo : Add dupefile remover. * * Totally rewritten by js on 08.02.2005 */ int copysfv(const char *source, const char *target, struct VARS *raceI) { int infd, outfd, i, retval = 0; short int music, rars, video, others, type; char *ptr, fbuf[2048]; FILE *insfv; DIR *dir; SFVDATA sd; //#if ( sfv_dupecheck == TRUE ) int skip = 0; SFVDATA tempsd; //#endif #if ( sfv_cleanup == TRUE ) int tmpfd; char crctmp[16]; if ((tmpfd = open(".tmpsfv", O_CREAT | O_TRUNC | O_RDWR, 0644)) == -1) d_log("copysfv: open(.tmpsfv): %s\n", strerror(errno)); #endif if ((infd = open(source, O_RDONLY)) == -1) { d_log("copysfv: open(%s): %s\n", source, strerror(errno)); remove_lock(raceI); exit(EXIT_FAILURE); } if ((outfd = open(target, O_CREAT | O_TRUNC | O_RDWR, 0666)) == -1) { d_log("copysfv: open(%s): %s\n", target, strerror(errno)); remove_lock(raceI); exit(EXIT_FAILURE); } video = music = rars = others = type = 0; dir = opendir("."); if (!update_lock(raceI, 1, 0)) { d_log("copysfv: Lock is suggested removed. Will comply and exit\n"); remove_lock(raceI); exit(EXIT_FAILURE); } if ((insfv = fdopen(infd, "r")) == NULL) { d_log("copysfv: Unable to fdopen %s: %s\n", source, strerror(errno)); remove_lock(raceI); exit(EXIT_FAILURE); } while ((fgets(fbuf, sizeof(fbuf), insfv))) { /* remove comment */ if ((ptr = find_first_of(fbuf, ";"))) *ptr = '\0'; tailstrip_chars(fbuf, WHITESPACE_STR); ptr = prestrip_chars(fbuf, WHITESPACE_STR); if (ptr != fbuf) d_log("copysfv: prestripped whitespaces (%d chars)\n", ptr - fbuf); if (strlen(ptr) == 0) continue; #if (sfv_cleanup_lowercase == TRUE) for (; *ptr; ptr++) *ptr = tolower(*ptr); #endif sd.crc32 = 0; bzero(sd.fname, sizeof(sd.fname)); if ((ptr = find_last_of(fbuf, " \t"))) { /* pass the " \t" */ ptr++; /* what we have now is hopefully a crc */ for (i = 0; isxdigit(*ptr) != 0; i++) ptr++; ptr -= i; if (i > 8 || i < 6) { /* we didn't get an 8 digit crc number */ #if (sfv_cleanup == TRUE) /* do stuff */ d_log("copysfv: We did not get a 8 digit crc number for %s - trying to continue anyway\n", sd.fname); #else retval = 1; goto END; #endif } else { sd.crc32 = hexstrtodec(ptr); /* cut off crc string */ *ptr = '\0'; /* nobody should be stupid enough to have spaces * at the end of the file name */ tailstrip_chars(fbuf, WHITESPACE_STR); } } else { /* we have a filename only. */ #if (sfv_cleanup == TRUE) /* do stuff */ d_log("copysfv: We did not find a crc number for %s - trying to continue anyway\n", sd.fname); #else retval = 1; goto END; #endif } /* we assume what's left is a filename */ ptr = prestrip_chars(fbuf, WHITESPACE_STR); if (ptr != fbuf) d_log("copysfv: prestripped whitespaces (%d chars)\n", ptr - fbuf); #if (allow_slash_in_sfv == TRUE) if (ptr != find_last_of(ptr, "/")) { ptr = find_last_of(ptr, "/") + 1; d_log("copysfv: found '/' in filename - adjusting.\n"); } if (ptr != find_last_of(ptr, "\\")) { ptr = find_last_of(ptr, "\\") + 1; d_log("copysfv: found '\\' in filename - adjusting.\n"); } #endif if (strlen(ptr) > 0 && strlen(ptr) < NAME_MAX-9 ) { strlcpy(sd.fname, ptr, NAME_MAX-9); if (sd.fname != find_last_of(sd.fname, "\t") || sd.fname != find_last_of(sd.fname, "\\") || sd.fname != find_last_of(sd.fname, "/")) { d_log("copysfv: found '/', '\\' or <TAB> as part of filename in sfv - logging file as bad.\n"); retval = 1; break; } if (sd.crc32 == 0) { #if (sfv_calc_single_fname == TRUE || create_missing_sfv == TRUE) sd.crc32 = match_lenient(dir, sd.fname); d_log("copysfv: Got filename (%s) without crc, calculated to %X.\n", sd.fname, sd.crc32); #else d_log("copysfv: Got filename (%s) without crc - ignoring file.\n", sd.fname); continue; #endif } /* get file extension */ ptr = find_last_of(fbuf, "."); if (*ptr == '.') ptr++; if (!strcomp(ignored_types, ptr) && !(strcomp(allowed_types, ptr) && !matchpath(allowed_types_exemption_dirs, raceI->misc.current_path)) && !strcomp("sfv", ptr) && !strcomp("nfo", ptr)) { skip = 0; //#if ( sfv_dupecheck == TRUE ) /* read from sfvdata - no parsing */ lseek(outfd, 0L, SEEK_SET); while (read(outfd, &tempsd, sizeof(SFVDATA))) // if (!strcmp(sd.fname, tempsd.fname) || (sd.crc32 == tempsd.crc32 && sd.crc32)) if (!strcmp(sd.fname, tempsd.fname)) skip = 1; lseek(outfd, 0L, SEEK_END); #if ( sfv_dupecheck == TRUE ) if (skip) continue; #endif d_log("copysfv: File in sfv: '%s' (%x)\n", sd.fname, sd.crc32); #if ( sfv_cleanup == TRUE ) /* write good stuff to .tmpsfv */ if (tmpfd != -1) { sprintf(crctmp, "%.8x", sd.crc32); if (write(tmpfd, sd.fname, strlen(sd.fname)) != (int)strlen(sd.fname)) d_log("copysfv: write failed: %s\n", strerror(errno)); if (write(tmpfd, " ", 1) != 1) d_log("copysfv: write failed: %s\n", strerror(errno)); if (write(tmpfd, crctmp, 8) != 8) d_log("copysfv: write failed: %s\n", strerror(errno)); #if (sfv_cleanup_crlf == TRUE ) if (write(tmpfd, "\r", 1) != 1) d_log("copysfv: write failed: %s\n", strerror(errno)); #endif if (write(tmpfd, "\n", 1) != 1) d_log("copysfv: write failed: %s\n", strerror(errno)); } #endif if (strcomp(audio_types, ptr)) music++; else if (israr(ptr)) rars++; else if (strcomp(video_types, ptr)) video++; else others++; #if ( create_missing_files == TRUE ) if (!findfile(dir, sd.fname) && !(matchpath(allowed_types_exemption_dirs, raceI->misc.current_path) && strcomp(allowed_types, ptr))) create_missing(sd.fname, raceI); #endif if (write(outfd, &sd, sizeof(SFVDATA)) != sizeof(SFVDATA)) d_log("copysfv: write failed: %s\n", strerror(errno)); } } } if (music > rars) { if (video > music) type = (video >= others ? 4 : 2); else type = (music >= others ? 3 : 2); } else { if (video > rars) type = (video >= others ? 4 : 2); else type = (rars >= others ? 1 : 2); } #if ( sfv_cleanup == FALSE ) END: #endif close(infd); #if ( sfv_cleanup == TRUE ) if (tmpfd != -1) { close(tmpfd); unlink(source); rename(".tmpsfv", source); #ifdef USING_EBFTPD if (ebftpd_chown(source, raceI->user.uid, raceI->user.gid) < 0) d_log("copysfv: ebftpd_chown(%s,%i,%i): %s\n", source, raceI->user.uid, raceI->user.gid, strerror(errno)); #endif } #endif closedir(dir); close(outfd); if (!update_lock(raceI, 1, type)) { d_log("copysfv: Lock is suggested removed. Will comply and exit\n"); remove_lock(raceI); exit(EXIT_FAILURE); } raceI->data_type = type; return retval; }
int main(int argc, char **argv) { char fileext[4]; char *name_p = 0; char *temp_p; char *target = NULL; char *fname; #ifdef USING_GLFTPD char *env_user, *env_group; #else char dirname[PATH_MAX]; #endif char *inc_point[2]; int n, m, ftype = 0; unsigned char empty_dir = 0; unsigned char _incomplete = 0; GLOBAL g; DIR *dir, *parent; #ifdef USING_GLFTPD if (argc == 1) { d_log("postdel: no param specified\n"); return 0; } if ((int)strlen(argv[1]) < 6 || strncmp(argv[1], "DELE ", 5)) { printf("pzs-ng postdel script.\n"); printf(" - this is supposed to be run from glftpd.\n"); printf(" - if you wish to run it yourself from chroot, \n"); printf(" - use /bin/postdel \"DELE <filename>\"\n"); printf(" - thank you. (remember the quotes!)\n"); return 0; } fname = argv[1] + 5; /* This way we simply skip the required * 'DELE'-part of the argument (so we get * filename) */ #else if (argc < 6) { printf("[running in ftpd-agnostic mode]\n"); printf("Missing arguments! Syntax:\n"); printf(" %s <user> <group> <tagline> <section> <filepath>\n", argv[0]); return 0; } fname = strrchr(argv[5], '/'); if (fname == NULL) { fname = argv[5]; strcpy(dirname, "./"); } else { strlcpy(dirname, argv[5], fname - argv[5] + 1); fname++; } chdir(dirname); d_log("postdel: Got a 'DELE %s' in '%s'\n", fname, dirname); #endif d_log("postdel: Project-ZS Next Generation (pzs-ng) %s debug log for postdel.\n", ng_version); d_log("postdel: Postdel executed by: (uid/gid) %d/%d\n", geteuid(), getegid()); #ifdef _ALT_MAX d_log("postdel: PATH_MAX not found - using predefined settings! Please report to the devs!\n"); #endif #ifdef USING_GLFTPD d_log("postdel: Reading user name from env\n"); if ((env_user = getenv("USER")) == NULL) { d_log("postdel: postdel: Could not find environment variable 'USER', setting value to 'Nobody'\n"); env_user = "******"; } d_log("postdel: Reading group name from env\n"); if ((env_group = getenv("GROUP")) == NULL) { d_log("postdel: Could not find environment variable 'GROUP', setting value to 'NoGroup'\n"); env_group = "NoGroup"; } #endif #if ( program_uid > 0 ) d_log("postdel: Trying to change effective gid\n"); setegid(program_gid); d_log("postdel: Trying to change effective uid\n"); seteuid(program_uid); #endif if (!strcmp(fname, "debug")) d_log("postdel: Reading directory structure\n"); dir = opendir("."); parent = opendir(".."); if (fileexists(fname)) { d_log("postdel: File (%s) still exists\n", fname); #if (remove_dot_debug_on_delete == TRUE) if (strcmp(fname, "debug")) unlink(fname); #endif closedir(dir); closedir(parent); return 0; } umask(0666 & 000); d_log("postdel: Clearing arrays\n"); bzero(&g.v.total, sizeof(struct race_total)); g.v.misc.slowest_user[0] = ULONG_MAX; g.v.misc.fastest_user[0] = 0; #ifdef USING_GLFTPD /* YARR; THE PAIN OF MAGIC NUMBERS! */ d_log("postdel: Copying env/predefined username to g.v. (%s)\n", env_user); strlcpy(g.v.user.name, env_user, sizeof(g.v.user.name)); d_log("postdel: Copying env/predefined groupname to g.v. (%s)\n", env_group); strlcpy(g.v.user.group, env_group, sizeof(g.v.user.group)); #else d_log("postdel: Copying argv[1] (username) to g.v. (%s)\n", argv[1]); strlcpy(g.v.user.name, argv[1], sizeof(g.v.user.name)); d_log("postdel: Copying argv[2] (groupname) to g.v. (%s)\n", argv[2]); strlcpy(g.v.user.group, argv[2], sizeof(g.v.user.group)); #endif d_log("postdel: File to remove is: %s\n", fname); if (!*g.v.user.group) memcpy(g.v.user.group, "NoGroup", 8); d_log("postdel: Allocating memory for variables\n"); g.ui = ng_realloc2(g.ui, sizeof(struct USERINFO *) * 30, 1, 1, 1); g.gi = ng_realloc2(g.gi,sizeof(struct GROUPINFO *) * 30, 1, 1, 1); if (!getcwd(g.l.path, PATH_MAX)) { d_log("postdel: Failed to getcwd(): %s\n", strerror(errno)); } if (subcomp(g.l.path, g.l.basepath) && (g.l.basepath[0] == '\0')) strlcpy(g.l.basepath, g.l.path, PATH_MAX); if (strncmp(g.l.path, g.l.basepath, PATH_MAX)) d_log("postdel: We are in subdir of %s\n", g.l.basepath); strncpy(g.v.misc.current_path, g.l.path, sizeof(g.v.misc.current_path)); strncpy(g.v.misc.basepath, g.l.basepath, sizeof(g.v.misc.basepath)); d_log("postdel: Creating directory to store racedata in\n"); maketempdir(g.l.path); d_log("postdel: Locking release\n"); while(1) { if ((m = create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 3, 0))) { d_log("postdel: Failed to lock release.\n"); if (m == 1) { d_log("postdel: version mismatch. Exiting.\n"); exit(EXIT_FAILURE); } if (m == PROGTYPE_RESCAN) { d_log("postdel: Detected rescan running - will try to make it quit.\n"); update_lock(&g.v, 0, 0); } if (m == PROGTYPE_POSTDEL) { n = (signed int)g.v.data_incrementor; d_log("postdel: Detected postdel running - sleeping for one second.\n"); if (!create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue)) break; usleep(1000000); if (!create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue)) break; if ( n == (signed int)g.v.data_incrementor) { d_log("postdel: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 2, g.v.data_queue)) { d_log("postdel: Failed to force a lock.\n"); d_log("postdel: Exiting with error.\n"); exit(EXIT_FAILURE); } break; } } else { for ( n = 0; n <= max_seconds_wait_for_lock * 10; n++) { d_log("postdel: sleeping for .1 second before trying to get a lock.\n"); usleep(100000); if (!(m = create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 0, g.v.data_queue))) break; } if (n >= max_seconds_wait_for_lock * 10) { if (m == PROGTYPE_RESCAN) { d_log("postdel: Failed to get lock. Forcing unlock.\n"); if (create_lock(&g.v, g.l.path, PROGTYPE_POSTDEL, 2, g.v.data_queue)) d_log("postdel: Failed to force a lock.\n"); } else d_log("postdel: Failed to get a lock.\n"); if (!g.v.data_in_use && !ignore_lock_timeout) { d_log("postdel: Exiting with error.\n"); exit(EXIT_FAILURE); } } } rewinddir(dir); rewinddir(parent); } usleep(10000); if (update_lock(&g.v, 1, 0) != -1) break; } g.l.race = ng_realloc(g.l.race, n = (int)strlen(g.l.path) + 12 + sizeof(storage), 1, 1, &g.v, 1); g.l.sfv = ng_realloc(g.l.sfv, n, 1, 1, &g.v, 1); g.l.sfvbackup = ng_realloc(g.l.sfvbackup, n, 1, 1, &g.v, 1); g.l.leader = ng_realloc(g.l.leader, n, 1, 1, &g.v, 1); target = ng_realloc(target, 4096, 1, 1, &g.v, 1); if (getenv("SECTION") == NULL) sprintf(g.v.sectionname, "DEFAULT"); else snprintf(g.v.sectionname, 127, "%s", getenv("SECTION")); d_log("postdel: Copying data &g.l into memory\n"); strlcpy(g.v.file.name, fname, NAME_MAX); sprintf(g.l.sfv, storage "/%s/sfvdata", g.l.path); sprintf(g.l.sfvbackup, storage "/%s/sfvbackup", g.l.path); sprintf(g.l.leader, storage "/%s/leader", g.l.path); sprintf(g.l.race, storage "/%s/racedata", g.l.path); g.l.sfv_incomplete = 0; d_log("postdel: Caching release name\n"); getrelname(&g); d_log("postdel: DEBUG 0: incomplete: '%s', path: '%s'\n", g.l.incomplete, g.l.path); if ((matchpath(nocheck_dirs, g.l.path) && rescan_nocheck_dirs_allowed == FALSE) || (!matchpath(zip_dirs, g.l.path) && !matchpath(sfv_dirs, g.l.path) && !matchpath(group_dirs, g.l.path))) { d_log("postdel: Dir matched with nocheck_dirs, or is not in the zip/sfv/group-dirs\n"); d_log("postdel: Freeing memory, removing lock and exiting\n"); ng_free(g.ui); ng_free(g.gi); if (fileexists(g.l.race)) unlink(g.l.race); if (fileexists(g.l.sfv)) unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (fileexists(g.l.leader)) unlink(g.l.leader); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); if (remove_dot_debug_on_delete) unlink(".debug"); remove_lock(&g.v); return 0; } d_log("postdel: Parsing file extension from filename...\n"); temp_p = find_last_of(g.v.file.name, "."); if (*temp_p != '.') { d_log("postdel: Got: no extension\n"); temp_p = name_p; } else { d_log("postdel: Got: %s\n", temp_p); temp_p++; } name_p++; if (temp_p) { while ((signed)strlen(temp_p) - 4 > 0) temp_p++; snprintf(fileext, 4, "%s", temp_p); } else *fileext = '\0'; g.v.misc.release_type = read_headdata(&g.v); switch (get_filetype_postdel(&g, fileext)) { case 0: ftype = g.v.misc.release_type; d_log("postdel: File type is: ZIP\n"); if (matchpath(zip_dirs, g.l.path)) { if (matchpath(group_dirs, g.l.path)) { g.v.misc.write_log = 0; } else { g.v.misc.write_log = 1; } } else if (matchpath(sfv_dirs, g.l.path) && strict_path_match) { if (matchpath(group_dirs, g.l.path)) { g.v.misc.write_log = 0; } else { d_log("postdel: Directory matched with sfv_dirs\n"); break; } } if (!fileexists("file_id.diz")) { temp_p = findfileext(dir, ".zip"); if (temp_p != NULL) { d_log("postdel: file_id.diz does not exist, trying to extract it from %s\n", temp_p); sprintf(target, "%s -qqjnCLL \"%s\" file_id.diz", unzip_bin, temp_p); execute(target); if (chmod("file_id.diz", 0666)) d_log("postdel: Failed to chmod %s: %s\n", "file_id.diz", strerror(errno)); } } d_log("postdel: Reading diskcount from diz\n"); // g.v.total.files = read_diz("file_id.diz"); g.v.total.files = read_diz(); if (g.v.total.files == 0) { d_log("postdel: Could not get diskcount from diz\n"); g.v.total.files = 1; } g.v.total.files_missing = g.v.total.files; d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); d_log("postdel: Removing old complete bar, if any\n"); removecomplete(g.v.misc.release_type); if (g.v.total.files_missing < 0) { g.v.total.files -= g.v.total.files_missing; g.v.total.files_missing = 0; } if (!g.v.total.files_missing) { d_log("postdel: Creating complete bar\n"); createstatusbar(convert(&g.v, g.ui, g.gi, zip_completebar)); } else if (g.v.total.files_missing < g.v.total.files) { if (g.v.total.files_missing == 1) { d_log("postdel: Writing INCOMPLETE to %s\n", log); writelog(&g, convert(&g.v, g.ui, g.gi, incompletemsg), general_incomplete_type); } _incomplete = 1; } else { empty_dir = 1; } remove_from_race(g.l.race, g.v.file.name, &g.v); break; case 1: /* SFV */ ftype = g.v.misc.release_type; d_log("postdel: Reading file count from sfvdata\n"); readsfv(g.l.sfv, &g.v, 0); if (fileexists(g.l.race)) { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); } d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); if (g.v.total.files_missing == g.v.total.files) { empty_dir = 1; } d_log("postdel: SFV was removed - removing progressbar/completebar and -missing pointers.\n"); removecomplete(g.v.misc.release_type); d_log("postdel: removing files created\n"); if (fileexists(g.l.sfv)) { delete_sfv(g.l.sfv, &g.v); unlink(g.l.sfv); } if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (g.l.nfo_incomplete) unlink(g.l.nfo_incomplete); if (g.l.sample_incomplete) unlink(g.l.sample_incomplete); if (g.l.incomplete) unlink(g.l.incomplete); d_log("postdel: removing progressbar, if any\n"); g.v.misc.release_type = ftype; move_progress_bar(1, &g.v, g.ui, g.gi); break; case 3: ftype = g.v.misc.release_type; d_log("postdel: Removing old complete bar, if any\n"); removecomplete(g.v.misc.release_type); g.v.misc.write_log = matchpath(sfv_dirs, g.l.path) > 0 ? 1 - matchpath(group_dirs, g.l.path) : 0; if (fileexists(g.l.race)) { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); } else { empty_dir = 1; } if (fileexists(g.l.sfv)) { #if ( create_missing_files == TRUE ) #if ( sfv_cleanup_lowercase == TRUE ) strtolower(g.v.file.name); #endif create_missing(g.v.file.name); #endif d_log("postdel: Reading file count from SFV\n"); readsfv(g.l.sfv, &g.v, 0); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); } d_log("postdel: g.v.total.files_missing=%d, g.v.total.files=%d\n", g.v.total.files_missing, g.v.total.files); if (g.v.total.files_missing < g.v.total.files) { if (g.v.total.files_missing == 1) { d_log("postdel: Writing INCOMPLETE to %s\n", log); writelog(&g, convert(&g.v, g.ui, g.gi, incompletemsg), general_incomplete_type); } _incomplete = 1; } else { d_log("postdel: Removing old race data\n"); unlink(g.l.race); if (findfileext(dir, ".sfv") == NULL) { empty_dir = 1; } else { _incomplete = 1; } } remove_from_race(g.l.race, g.v.file.name, &g.v); break; case 4: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) empty_dir = 1; break; case 255: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) empty_dir = 1; break; case 2: ftype = g.v.misc.release_type; if (!fileexists(g.l.race)) { empty_dir = 1; } else { d_log("postdel: Reading race data from file to memory\n"); readrace(g.l.race, &g.v, g.ui, g.gi); d_log("postdel: Caching progress bar\n"); buffer_progress_bar(&g.v); if (g.v.total.files_missing == g.v.total.files) empty_dir = 1; } break; } if (empty_dir == 1 && !findfileext(dir, ".sfv")) { d_log("postdel: Removing all files and directories created by zipscript\n"); removecomplete(g.v.misc.release_type); if (fileexists(g.l.sfv)) delete_sfv(g.l.sfv, &g.v); if (g.l.nfo_incomplete) unlink(g.l.nfo_incomplete); if (g.l.incomplete) unlink(g.l.incomplete); if (fileexists("file_id.diz")) unlink("file_id.diz"); if (fileexists(g.l.race)) unlink(g.l.race); if (fileexists(g.l.sfv)) unlink(g.l.sfv); if (fileexists(g.l.sfvbackup)) unlink(g.l.sfvbackup); if (fileexists(g.l.leader)) unlink(g.l.leader); g.v.misc.release_type = ftype; move_progress_bar(1, &g.v, g.ui, g.gi); #if (remove_dot_files_on_delete == TRUE) removedotfiles(dir); #endif } if (_incomplete == 1 && g.v.total.files > 0) { g.v.misc.data_completed = 0; getrelname(&g); if (g.l.nfo_incomplete) { if (findfileext(dir, ".nfo")) { d_log("postdel: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else if (matchpath(check_for_missing_nfo_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("postdel: Creating missing-nfo indicator %s.\n", g.l.nfo_incomplete); if (create_incomplete_nfo()) { d_log("postdel: Warning: create_incomplete_nfo() returned something.\n"); } } else { if (findfileextparent(parent, ".nfo")) { d_log("postdel: Removing missing-nfo indicator (if any)\n"); remove_nfo_indicator(&g); } else { d_log("postdel: Creating missing-nfo indicator (base) %s.\n", g.l.nfo_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_nfo()) { d_log("postdel: Warning: create_incomplete_nfo() returned something.\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #if (create_missing_sample_link) if (g.l.sample_incomplete) { if (findfileextsub(".", sample_types, sample_list) || matchpartialdirname(missing_sample_check_ignore_list, g.v.misc.release_name, missing_sample_check_ignore_dividers)) { d_log("postdel: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else if (matchpath(check_for_missing_sample_dirs, g.l.path) && (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs)) { if (!g.l.in_cd_dir) { d_log("postdel: Creating missing-sample indicator %s.\n", g.l.sample_incomplete); if (create_incomplete_sample()) { d_log("postdel: Warning: create_incomplete_sample() returned something.\n"); } } else { if (findfileextsub("..", sample_types, sample_list)) { d_log("postdel: Removing missing-sample indicator (if any)\n"); remove_sample_indicator(&g); } else { d_log("postdel: Creating missing-sample indicator (base) %s.\n", g.l.sample_incomplete); /* This is not pretty, but should be functional. */ if ((inc_point[0] = find_last_of(g.l.path, "/")) != g.l.path) *inc_point[0] = '\0'; if ((inc_point[1] = find_last_of(g.v.misc.release_name, "/")) != g.v.misc.release_name) *inc_point[1] = '\0'; if (create_incomplete_sample()) { d_log("postdel: Warning: create_incomplete_sample() returned something.\n"); } if (*inc_point[0] == '\0') *inc_point[0] = '/'; if (*inc_point[1] == '\0') *inc_point[1] = '/'; } } } } #endif if (!matchpath(group_dirs, g.l.path) || create_incomplete_links_in_group_dirs) { d_log("postdel: Creating incomplete indicator\n"); d_log("postdel: incomplete: '%s', path: '%s'\n", g.l.incomplete, g.l.path); if (create_incomplete()) { d_log("postdel: Warning: create_incomplete() returned something.\n"); } } d_log("postdel: Moving progress bar (%d)\n", g.v.misc.release_type); g.v.misc.release_type = ftype; move_progress_bar(0, &g.v, g.ui, g.gi); } d_log("postdel: Releasing memory and removing lock.\n"); closedir(dir); closedir(parent); updatestats_free(&g); ng_free(target); ng_free(g.l.race); ng_free(g.l.sfv); ng_free(g.l.sfvbackup); ng_free(g.l.leader); remove_lock(&g.v); if (empty_dir) { d_log("postdel: Removing missing-sfv indicator (if any)\n"); unlink(g.l.sfv_incomplete); if (fileexists(".debug") && remove_dot_debug_on_delete) unlink(".debug"); } d_log("postdel: Exit 0\n"); return 0; }
/* * Modified : 01.16.2002 Author : Dark0n3 * * Description : Goes through all untested files and compares crc of file * with one that is reported in sfv. * */ void testfiles(struct LOCATIONS *locations, struct VARS *raceI, int rstatus) { int fd, lret, count; char *ext, target[PATH_MAX], real_file[PATH_MAX]; FILE *racefile; unsigned int Tcrc; struct stat filestat; time_t timenow; RACEDATA rd; if ((fd = open(locations->race, O_CREAT | O_RDWR, 0666)) == -1) { if (errno != EEXIST) { d_log("testfiles: open(%s): %s\n", locations->race, strerror(errno)); remove_lock(raceI); exit(EXIT_FAILURE); } } close(fd); if (!(racefile = fopen(locations->race, "r+"))) { d_log("testfiles: fopen(%s) failed\n", locations->race); exit(EXIT_FAILURE); } strlcpy(real_file, raceI->file.name, sizeof(real_file)); if (rstatus) printf("\n"); count = 0; rd.status = F_NOTCHECKED; while ((fread(&rd, sizeof(RACEDATA), 1, racefile))) { if (!update_lock(raceI, 1, 0)) { d_log("testfiles: Lock is suggested removed. Will comply and exit\n"); remove_lock(raceI); fclose(racefile); exit(EXIT_FAILURE); } ext = find_last_of(raceI->file.name, "."); if (*ext == '.') ext++; strlcpy(raceI->file.name, rd.fname, NAME_MAX); Tcrc = readsfv(locations->sfv, raceI, 0); timenow = time(NULL); stat(rd.fname, &filestat); if (fileexists(rd.fname)) { d_log("testfiles: Processing %s\n", rd.fname); if (S_ISDIR(filestat.st_mode)) rd.status = F_IGNORED; else if (rd.crc32 != 0 && Tcrc == rd.crc32) rd.status = F_CHECKED; else if (rd.crc32 != 0 && strcomp(ignored_types, ext)) rd.status = F_IGNORED; else if (rd.crc32 != 0 && Tcrc == 0 && (strcomp(allowed_types, ext) && !matchpath(allowed_types_exemption_dirs, locations->path))) rd.status = F_IGNORED; else if ((rd.crc32 != 0) && (Tcrc != rd.crc32) && (strcomp(allowed_types, ext) && !matchpath(allowed_types_exemption_dirs, locations->path))) rd.status = F_IGNORED; else if ((rd.crc32 == 0) && strcomp(allowed_types, ext)) rd.status = F_IGNORED; else if ((timenow == filestat.st_ctime) && (filestat.st_mode & 0111)) { d_log("testfiles: Looks like this file (%s) is in the process of being uploaded. Ignoring.\n", rd.fname); rd.status = F_IGNORED; create_missing(rd.fname, raceI); } } else if (snprintf(target, sizeof(target), "%s.bad", rd.fname) > 4 && fileexists(target)) { d_log("testfiles: File doesnt exist (%s), bad version of it does, keeping it marked as bad.\n", rd.fname); rd.status = F_BAD; if (rstatus) printf("File: %s BAD!\n", rd.fname); } else { d_log("testfiles: File doesnt exist (%s), marking as missing.\n", rd.fname); rd.status = F_MISSING; if (rstatus) printf("File: %s MISSING!\n", rd.fname); remove_from_race(locations->race, rd.fname, raceI); --count; } if (rd.status == F_MISSING || rd.status == F_NOTCHECKED) { if (rd.status == F_NOTCHECKED) { d_log("testfiles: Marking file (%s) as bad and removing it.\n", rd.fname); mark_as_bad(rd.fname); if (rd.fname) unlink(rd.fname); rd.status = F_BAD; if (rstatus) printf("File: %s FAILED!\n", rd.fname); } #if ( create_missing_files ) if (Tcrc != 0) create_missing(rd.fname, raceI); #endif #if (enable_unduper_script == TRUE) if (!fileexists(unduper_script)) { d_log("Failed to undupe '%s' - '%s' does not exist.\n", rd.fname, unduper_script); } else { sprintf(target, unduper_script " \"%s\"", rd.fname); if (execute(target) == 0) d_log("testfiles: undupe of %s successful (%s).\n", rd.fname, target); else d_log("testfiles: undupe of %s failed (%s).\n", rd.fname, target); } #endif } if (rd.status != F_MISSING) { if ((lret = fseek(racefile, sizeof(RACEDATA) * count, SEEK_SET)) == -1) { d_log("testfiles: fseek: %s\n", strerror(errno)); fclose(racefile); remove_lock(raceI); exit(EXIT_FAILURE); } if (fwrite(&rd, sizeof(RACEDATA), 1, racefile) == 0) d_log("testfiles: write failed: %s\n", strerror(errno)); if (rd.status != F_BAD && !((timenow == filestat.st_ctime) && (filestat.st_mode & 0111))) unlink_missing(rd.fname); } ++count; } strlcpy(raceI->file.name, real_file, strlen(real_file)+1); raceI->total.files = raceI->total.files_missing = 0; fclose(racefile); d_log("testfiles: finished checking\n"); }