static void filedb_setlink(char *dir, char *fn, char *link) { filedb_entry *fdbe = NULL; FILE *fdb = NULL; fdb = filedb_open(dir, 0); if (!fdb) return; filedb_readtop(fdb, NULL); fdbe = filedb_matchfile(fdb, ftell(fdb), fn); if (fdbe) { /* Change existing one? */ if ((fdbe->stat & FILE_DIR) || !fdbe->sharelink) return; if (!link || !link[0]) filedb_delfile(fdb, fdbe->pos); else { my_free(fdbe->sharelink); malloc_strcpy(fdbe->sharelink, link); filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL); } free_fdbe(&fdbe); return; } fdbe = malloc_fdbe(); malloc_strcpy(fdbe->uploader, botnetnick); malloc_strcpy(fdbe->filename, fn); malloc_strcpy(fdbe->sharelink, link); fdbe->uploaded = now; filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); filedb_close(fdb); }
/* Reads file DB v2 entries from fdb_s and saves them to fdb_t in * v3 format. */ static void convert_version2(FILE *fdb_s, FILE *fdb_t) { filedb2 fdb2; fseek(fdb_s, 0L, SEEK_SET); while (!feof(fdb_s)) { fread(&fdb2, sizeof(filedb2), 1, fdb_s); if (!feof(fdb_s)) { if (!(fdb2.stat & FILE_UNUSED)) { filedb_entry *fdbe = malloc_fdbe(); fdbe->stat = fdb2.stat; if (fdb2.filename[0]) malloc_strcpy(fdbe->filename, fdb2.filename); if (fdb2.desc[0]) malloc_strcpy(fdbe->desc, fdb2.desc); if (fdb2.chname[0]) malloc_strcpy(fdbe->chan, fdb2.chname); if (fdb2.uploader[0]) malloc_strcpy(fdbe->uploader, fdb2.uploader); if (fdb2.flags_req[0]) malloc_strcpy(fdbe->flags_req, fdb2.flags_req); fdbe->uploaded = fdb2.uploaded; fdbe->size = fdb2.size; fdbe->gots = fdb2.gots; if (fdb2.sharelink[0]) malloc_strcpy(fdbe->sharelink, fdb2.sharelink); filedb_addfile(fdb_t, fdbe); free_fdbe(&fdbe); } } } }
/* 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 */ }
/* Convert '.files' db to newest db. Returns 1 if a valid file is * found and could be converted, 0 in all other cases. * * '.files' is a text file which contains file records built up in the * following way: * '<filename> <nick> <tm> <gots>\n' * '- <comment>\n' * '- <comment>\n' * ... */ static int convert_old_files(char *path, char *newfiledb) { FILE *f, *fdb; char *s, *fn, *nick, *tm, *s1; filedb_entry *fdbe = NULL; int in_file = 0, i; struct stat st; s = nmalloc(strlen(path) + 8); sprintf(s, "%s/.files", path); f = fopen(s, "r"); my_free(s); if (f == NULL) return 0; fdb = fopen(newfiledb, "w+b"); if (!fdb) { putlog(LOG_MISC, "(!) Can't create filedb in %s", newfiledb); fclose(f); return 0; } lockfile(fdb); lockfile(f); filedb_initdb(fdb); putlog(LOG_FILES, "*", FILES_CONVERT, path); /* Scan contents of .files and painstakingly create .filedb entries */ while (!feof(f)) { s = nmalloc(121); s1 = s; fgets(s, 120, f); if (s[strlen(s) - 1] == '\n') s[strlen(s) - 1] = 0; if (!feof(f)) { fn = newsplit(&s1); rmspace(fn); if ((fn[0]) && (fn[0] != ';') && (fn[0] != '#')) { /* Not comment */ if (fn[0] == '-') { /* Adjust comment for current file */ if (in_file && fdbe) { rmspace(s); if (fdbe->desc) { fdbe->desc = nrealloc(fdbe->desc, strlen(fdbe->desc) + strlen(s) + 2); strcat(fdbe->desc, "\n"); } else fdbe->desc = nmalloc(strlen(s) + 2); strcat(fdbe->desc, s); } } else { if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fdbe = malloc_fdbe(); in_file = 1; nick = newsplit(&s1); rmspace(nick); tm = newsplit(&s1); rmspace(tm); rmspace(s1); i = strlen(fn) - 1; if (fn[i] == '/') fn[i] = 0; malloc_strcpy(fdbe->filename, fn); malloc_strcpy(fdbe->uploader, nick); fdbe->gots = atoi(s1); fdbe->uploaded = atoi(tm); sprintf(s, "%s/%s", path, fn); if (stat(s, &st) == 0) { /* File is okay */ if (S_ISDIR(st.st_mode)) { fdbe->stat |= FILE_DIR; if (nick[0] == '+') { char x[100]; /* Only do global flags, it's an old one */ struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 }; break_down_flags(nick + 1, &fr, NULL); build_flags(x, &fr, NULL); /* We only want valid flags */ malloc_strcpy_nocheck(fdbe->flags_req, x); } } fdbe->size = st.st_size; } else in_file = 0; /* skip */ } } } my_free(s); } if (fdbe) { /* File pending. Write to DB */ filedb_addfile(fdb, fdbe); free_fdbe(&fdbe); } fseek(fdb, 0L, SEEK_END); unlockfile(f); unlockfile(fdb); fclose(fdb); fclose(f); return 1; }
static int tcl_mv_cp(Tcl_Interp *irp, int argc, char **argv, int copy) { char *p, *fn = NULL, *oldpath = NULL, *s = NULL, *s1 = NULL; char *newfn = NULL, *newpath = NULL; int ok = 0, only_first, skip_this; FILE *fdb_old, *fdb_new; filedb_entry *fdbe_old, *fdbe_new; long where; BADARGS(3, 3, " oldfilepath newfilepath"); malloc_strcpy(fn, argv[1]); p = strrchr(fn, '/'); if (p != NULL) { *p = 0; malloc_strcpy(s, fn); strcpy(fn, p + 1); if (!resolve_dir("/", s, &oldpath, -1)) { /* Tcl can do * anything */ Tcl_AppendResult(irp, "-1", NULL); /* Invalid source */ my_free(fn); my_free(oldpath); return TCL_OK; } my_free(s); } else malloc_strcpy(oldpath, "/"); malloc_strcpy(s, argv[2]); if (!resolve_dir("/", s, &newpath, -1)) { /* Destination is not just a directory */ p = strrchr(s, '/'); if (!p) { malloc_strcpy(newfn, s); s[0] = 0; } else { *p = 0; malloc_strcpy(newfn, p + 1); } my_free(newpath); if (!resolve_dir("/", s, &newpath, -1)) { Tcl_AppendResult(irp, "-2", NULL); /* Invalid desto */ my_free(newpath); my_free(s); my_free(newfn); return TCL_OK; } } else malloc_strcpy(newfn, ""); my_free(s); /* Stupidness checks */ if ((!strcmp(oldpath, newpath)) && (!newfn[0] || !strcmp(newfn, fn))) { my_free(newfn); my_free(fn); my_free(oldpath); my_free(newpath); Tcl_AppendResult(irp, "-3", NULL); /* Stupid copy to self */ return TCL_OK; } /* Be aware of 'cp * this.file' possibility: ONLY COPY FIRST ONE */ if ((strchr(fn, '?') || strchr(fn, '*')) && newfn[0]) only_first = 1; else only_first = 0; fdb_old = filedb_open(oldpath, 0); if (!strcmp(oldpath, newpath)) fdb_new = fdb_old; else fdb_new = filedb_open(newpath, 0); if (!fdb_old || !fdb_new) { my_free(newfn); my_free(fn); my_free(oldpath); my_free(newpath); if (fdb_old) filedb_close(fdb_old); else if (fdb_new) filedb_close(fdb_new); Tcl_AppendResult(irp, "-5", NULL); /* DB access failed */ return -1; } filedb_readtop(fdb_old, NULL); fdbe_old = filedb_matchfile(fdb_old, ftell(fdb_old), fn); if (!fdbe_old) { my_free(newfn); my_free(fn); my_free(oldpath); my_free(newpath); if (fdb_new != fdb_old) filedb_close(fdb_new); filedb_close(fdb_old); Tcl_AppendResult(irp, "-4", NULL); /* No match */ return -2; } while (fdbe_old) { where = ftell(fdb_old); skip_this = 0; if (!(fdbe_old->stat & (FILE_HIDDEN | FILE_DIR))) { s = nmalloc(strlen(dccdir) + strlen(oldpath) + strlen(fdbe_old->filename) + 2); s1 = nmalloc(strlen(dccdir) + strlen(newpath) + strlen(newfn[0] ? newfn : fdbe_old->filename) + 2); sprintf(s, "%s%s%s%s", dccdir, oldpath, oldpath[0] ? "/" : "", fdbe_old->filename); sprintf(s1, "%s%s%s%s", dccdir, newpath, newpath[0] ? "/" : "", newfn[0] ? newfn : fdbe_old->filename); if (!strcmp(s, s1)) { Tcl_AppendResult(irp, "-3", NULL); /* Stupid copy to self */ skip_this = 1; } /* Check for existence of file with same name in new dir */ filedb_readtop(fdb_new, NULL); fdbe_new = filedb_matchfile(fdb_new, ftell(fdb_new), newfn[0] ? newfn : fdbe_old->filename); if (fdbe_new) { /* It's ok if the entry in the new dir is a normal file (we'll * just scrap the old entry and overwrite the file) -- but if * it's a directory, this file has to be skipped. */ if (fdbe_new->stat & FILE_DIR) skip_this = 1; else filedb_delfile(fdb_new, fdbe_new->pos); free_fdbe(&fdbe_new); } if (!skip_this) { if ((fdbe_old->sharelink) || ((copy ? copyfile(s, s1) : movefile(s, s1)) == 0)) { /* Raw file moved okay: create new entry for it */ ok++; fdbe_new = malloc_fdbe(); fdbe_new->stat = fdbe_old->stat; /* We don't have to worry about any entries to be * NULL, because malloc_strcpy takes care of that. */ malloc_strcpy(fdbe_new->flags_req, fdbe_old->flags_req); malloc_strcpy(fdbe_new->chan, fdbe_old->chan); malloc_strcpy(fdbe_new->filename, fdbe_old->filename); malloc_strcpy(fdbe_new->desc, fdbe_old->desc); if (newfn[0]) malloc_strcpy(fdbe_new->filename, newfn); malloc_strcpy(fdbe_new->uploader, fdbe_old->uploader); fdbe_new->uploaded = fdbe_old->uploaded; fdbe_new->size = fdbe_old->size; fdbe_new->gots = fdbe_old->gots; malloc_strcpy(fdbe_new->sharelink, fdbe_old->sharelink); filedb_addfile(fdb_new, fdbe_new); if (!copy) filedb_delfile(fdb_old, fdbe_old->pos); free_fdbe(&fdbe_new); } } my_free(s); my_free(s1); } free_fdbe(&fdbe_old); fdbe_old = filedb_matchfile(fdb_old, where, fn); if (ok && only_first) { free_fdbe(&fdbe_old); } } if (fdb_old != fdb_new) filedb_close(fdb_new); filedb_close(fdb_old); if (!ok) Tcl_AppendResult(irp, "-4", NULL); /* No match */ else { char x[30]; sprintf(x, "%d", ok); Tcl_AppendResult(irp, x, NULL); } my_free(newfn); my_free(fn); my_free(oldpath); my_free(newpath); return TCL_OK; }