/* Closes the filedb. Also removes the lock and updates the * timestamp. */ static void filedb_close(FILE *fdb) { filedb_timestamp(fdb); fseek(fdb, 0L, SEEK_END); count--; unlockfile(fdb); fclose(fdb); }
/* Updates the specified filedb in several ways: * * 1. Adds all new files from the directory to the db. * 2. Removes all stale entries from the db. * 3. Optimises the db. */ static void filedb_update(char *path, FILE *fdb, int sort) { struct dirent *dd = NULL; struct stat st; filedb_entry *fdbe = NULL; DIR *dir = NULL; long where = 0; char *name = NULL, *s = NULL; /* * FIRST: make sure every real file is in the database */ dir = opendir(path); if (dir == NULL) { putlog(LOG_MISC, "*", FILES_NOUPDATE); return; } dd = readdir(dir); while (dd != NULL) { malloc_strcpy(name, dd->d_name); if (name[0] != '.') { s = nmalloc(strlen(path) + strlen(name) + 2); sprintf(s, "%s/%s", path, name); stat(s, &st); my_free(s); filedb_readtop(fdb, NULL); fdbe = filedb_matchfile(fdb, ftell(fdb), name); if (!fdbe) { /* new file! */ fdbe = malloc_fdbe(); malloc_strcpy(fdbe->filename, name); malloc_strcpy(fdbe->uploader, botnetnick); fdbe->uploaded = now; fdbe->size = st.st_size; if (S_ISDIR(st.st_mode)) fdbe->stat |= FILE_DIR; filedb_addfile(fdb, fdbe); } else if (fdbe->size != st.st_size) { /* update size if needed */ fdbe->size = st.st_size; filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_HEADER); } free_fdbe(&fdbe); } dd = readdir(dir); } if (name) my_free(name); closedir(dir); /* * SECOND: make sure every db file is real */ filedb_readtop(fdb, NULL); fdbe = filedb_getfile(fdb, ftell(fdb), GET_FILENAME); while (fdbe) { where = ftell(fdb); if (!(fdbe->stat & FILE_UNUSED) && !(fdbe->stat & FILE_ISLINK) && fdbe->filename) { s = nmalloc(strlen(path) + 1 + strlen(fdbe->filename) + 1); sprintf(s, "%s/%s", path, fdbe->filename); if (stat(s, &st) != 0) /* gone file */ filedb_delfile(fdb, fdbe->pos); my_free(s); } free_fdbe(&fdbe); fdbe = filedb_getfile(fdb, where, GET_FILENAME); } /* * THIRD: optimise database * * Instead of sorting, we only clean up the db, because sorting is now * done on-the-fly when we display the file list. */ if (sort) filedb_cleanup(fdb); /* Cleanup DB */ filedb_timestamp(fdb); /* Write new timestamp */ }
static void filedb_update(char *path, FILE * f, int sort) { struct dirent *dd; DIR *dir; filedb fdb[2]; char name[61]; long where, oldwhere; struct stat st; char s[512]; int ret; /* FIRST: make sure every real file is in the database */ dir = opendir(path); if (dir == NULL) { putlog(LOG_MISC, "*", FILES_NOUPDATE); return; } dd = readdir(dir); while (dd != NULL) { strncpy(name, dd->d_name, 60); name[60] = 0; if (NAMLEN(dd) <= 60) name[NAMLEN(dd)] = 0; else { /* truncate name on disk */ char s1[512], s2[256]; strcpy(s1, path); strcat(s1, "/"); strncat(s1, dd->d_name, NAMLEN(dd)); s1[strlen(path) + NAMLEN(dd) + 1] = 0; sprintf(s2, "%s/%s", path, name); movefile(s1, s2); } if (name[0] != '.') { sprintf(s, "%s/%s", path, name); stat(s, &st); where = 0; ret = findmatch(f, name, &where, &fdb[0]); if (!ret) { /* new file! */ where = findempty(f); fseek(f, where, SEEK_SET); fdb[0].version = FILEVERSION; fdb[0].stat = 0; /* by default, visible regular file */ strcpy(fdb[0].filename, name); fdb[0].desc[0] = 0; strcpy(fdb[0].uploader, botnetnick); fdb[0].gots = 0; fdb[0].flags_req[0] = 0; fdb[0].uploaded = now; fdb[0].size = st.st_size; fdb[0].sharelink[0] = 0; if (S_ISDIR(st.st_mode)) fdb[0].stat |= FILE_DIR; fwrite(&fdb[0], sizeof(filedb), 1, f); } else if (fdb[0].version < FILEVERSION) { /* old version filedb, do the dirty */ if (fdb[0].version == FILEVERSION_OLD) { filedb_old *fdbo = (filedb_old *) & fdb[0]; fdb[0].desc[185] = 0; /* truncate it */ fdb[0].chname[0] = 0; /* new entry */ strcpy(fdb[0].uploader, fdbo->uploader); /* moved forward * a few bytes */ strcpy(fdb[0].flags_req, fdbo->flags_req); /* and again */ fdb[0].version = FILEVERSION; fdb[0].size = st.st_size; fseek(f, where, SEEK_SET); fwrite(&fdb[0], sizeof(filedb), 1, f); } else { putlog(LOG_MISC, "*", "!!! Unknown filedb type !"); } } else { /* update size if needed */ fdb[0].size = st.st_size; fseek(f, where, SEEK_SET); fwrite(&fdb[0], sizeof(filedb), 1, f); } } dd = readdir(dir); } closedir(dir); /* SECOND: make sure every db file is real, and sort as we go, * if we're sorting */ rewind(f); while (!feof(f)) { where = ftell(f); fread(&fdb[0], sizeof(filedb), 1, f); if (!feof(f)) { if (!(fdb[0].stat & FILE_UNUSED) && !fdb[0].sharelink[0]) { sprintf(s, "%s/%s", path, fdb[0].filename); if (stat(s, &st) != 0) { /* gone file */ fseek(f, where, SEEK_SET); fdb[0].stat |= FILE_UNUSED; fwrite(&fdb[0], sizeof(filedb), 1, f); /* sunos and others will puke bloody chunks if you write the * last record in a file and then attempt to read to EOF: */ fseek(f, where, SEEK_SET); continue; /* cycle to next one */ } } if (sort && !(fdb[0].stat & FILE_UNUSED)) { rewind(f); oldwhere = ftell(f); ret = 0; while (!feof(f) && (oldwhere < where)) { fread(&fdb[1 - ret], sizeof(filedb), 1, f); if (!feof(f)) { if ((fdb[0].stat & FILE_UNUSED) || (strcasecmp(fdb[ret].filename, fdb[1 - ret].filename) < 0)) { /* our current is < the checked one, insert here */ fseek(f, oldwhere, SEEK_SET); fwrite(&fdb[ret], sizeof(filedb), 1, f); ret = 1 - ret; /* and fall out */ } /* otherwise read next entry */ oldwhere = ftell(f); } } /* here, either we've found a place to insert, or got to * the end of the list */ /* if we've got to the end of the current list oldwhere == where * so we fall through ret will point to the current valid one */ while (!feof(f) && (oldwhere < where)) { /* need to move this entry up 1 .. */ fread(&fdb[1 - ret], sizeof(filedb), 1, f); oldwhere = ftell(f); /* write lower record here */ fseek(f, oldwhere, SEEK_SET); fwrite(&fdb[ret], sizeof(filedb), 1, f); ret = 1 - ret; } /* when we get here fdb[ret] holds the last record, * which needs to be written where we first grabbed the * record from */ fseek(f, where, SEEK_SET); fwrite(&fdb[ret], sizeof(filedb), 1, f); } } } /* write new timestamp */ filedb_timestamp(f); }