Beispiel #1
0
/* Throws out all entries marked as unused, by walking through the
 * filedb and moving all good ones towards the top.
 */
static void filedb_cleanup(FILE *fdb)
{
    long oldpos, newpos, temppos;
    filedb_entry *fdbe = NULL;

    filedb_readtop(fdb, NULL);    /* Skip DB header  */
    newpos = temppos = oldpos = ftell(fdb);
    fseek(fdb, oldpos, SEEK_SET); /* Go to beginning */
    while (!feof(fdb)) {          /* Loop until EOF  */
        fdbe = filedb_getfile(fdb, oldpos, GET_HEADER);     /* Read header     */
        if (fdbe) {
            if (fdbe->stat & FILE_UNUSED) {   /* Found dirt!     */
                free_fdbe(&fdbe);
                while (!feof(fdb)) {    /* Loop until EOF  */
                    newpos = ftell(fdb);
                    fdbe = filedb_getfile(fdb, newpos, GET_FULL); /* Read next entry */
                    if (!fdbe)
                        break;
                    if (!(fdbe->stat & FILE_UNUSED)) {    /* Not unused?     */
                        temppos = ftell(fdb);
                        filedb_movefile(fdb, oldpos, fdbe); /* Move to top     */
                        oldpos = ftell(fdb);
                        fseek(fdb, temppos, SEEK_SET);
                    }
                    free_fdbe(&fdbe);
                }
            } else {
                free_fdbe(&fdbe);
                oldpos = ftell(fdb);
            }
        }
    }
    ftruncate(fileno(fdb), oldpos);       /* Shorten file    */
}
Beispiel #2
0
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);
}
Beispiel #3
0
/* Converts old versions of the filedb to the newest. Returns 1 if all went
 * well and otherwise 0. The new db is first written to a temporary place
 * and then moved over to the original db's position.
 *
 * Note: Unfortunately there is a small time-frame where aren't locking the
 *       DB, but want to replace it with a new one, using movefile().
 *       TODO: Copy old db to tmp file and then build the new db directly
 *             in the original file. This solves the tiny locking problem.
 *
 * Also remember to check the returned *fdb_s on failure, as it could be
 * NULL.
 */
static int convert_old_db(FILE ** fdb_s, char *filedb)
{
    filedb_top fdbt;
    FILE *fdb_t;
    int ret = 0;                  /* Default to 'failure' */

    filedb_readtop(*fdb_s, &fdbt);
    /* Old DB version? */
    if (fdbt.version > 0 && fdbt.version < FILEDB_VERSION3) {
        char *tempdb;

        putlog(LOG_MISC, "*", "Converting old filedb %s to newest format.",
               filedb);
        /* Create temp DB name */
        tempdb = nmalloc(strlen(filedb) + 5);
        simple_sprintf(tempdb, "%s-tmp", filedb);

        fdb_t = fopen(tempdb, "w+b");       /* Open temp DB         */
        if (fdb_t) {
            filedb_initdb(fdb_t);     /* Initialise new DB    */

            /* Convert old database to new one, saving
             * in temporary db file
             */
            if (fdbt.version == FILEDB_VERSION1)
                convert_version1(*fdb_s, fdb_t);        /* v1 -> v3             */
            else
                convert_version2(*fdb_s, fdb_t);        /* v2 -> v3             */

            unlockfile(*fdb_s);
            fclose(fdb_t);
            fclose(*fdb_s);

            /* Move over db to new location */
            if (movefile(tempdb, filedb))
                putlog(LOG_MISC, "*", "(!) Moving file db from %s to %s failed.",
                       tempdb, filedb);

            *fdb_s = fopen(filedb, "r+b");    /* Reopen new db        */
            if (*fdb_s) {
                lockfile(*fdb_s);
                /* Now we should have recreated the original situation,
                 * with the file pointer just pointing to the new version
                 * of the DB instead of the original one.
                 */
                ret = 1;
            } else
                putlog(LOG_MISC, "*", "(!) Reopening db %s failed.", filedb);
        }
        my_free(tempdb);
        /* Database already at the newest version? */
    } else if (fdbt.version == FILEDB_VERSION3)
        ret = 1;
    else
        putlog(LOG_MISC, "*", "(!) Unknown db version: %d", fdbt.version);
    if (!ret)
        putlog(LOG_MISC, "*", "Conversion of filedb %s failed.", filedb);
    return ret;
}
Beispiel #4
0
static void filedb_timestamp(FILE *fdb)
{
    filedb_top fdbt;

    filedb_readtop(fdb, &fdbt);
    fdbt.timestamp = time(NULL);
    filedb_writetop(fdb, &fdbt);
}
Beispiel #5
0
static int tcl_setflags(ClientData cd, Tcl_Interp *irp,
                        int argc, char *argv[])
{
  FILE *fdb;
  filedb_entry *fdbe;
  char *s = NULL, *p, *d;

  BADARGS(3, 4, " dir ?flags ?channel??");

  malloc_strcpy(s, argv[1]);
  if (s[strlen(s) - 1] == '/')
    s[strlen(s) - 1] = 0;
  p = strrchr(s, '/');
  if (p == NULL) {
    p = s;
    d = "";
  } else {
    *p = 0;
    p++;
    d = s;
  }

  fdb = filedb_open(d, 0);
  if (!fdb) {
    Tcl_AppendResult(irp, "-3", NULL);  /* filedb access failed */
    my_free(s);
    return TCL_OK;
  }
  filedb_readtop(fdb, NULL);
  fdbe = filedb_matchfile(fdb, ftell(fdb), p);
  my_free(s);

  if (!fdbe) {
    Tcl_AppendResult(irp, "-1", NULL);  /* No such dir */
    return TCL_OK;
  }
  if (!(fdbe->stat & FILE_DIR)) {
    Tcl_AppendResult(irp, "-2", NULL);  /* Not a dir */
    return TCL_OK;
  }
  if (argc >= 3) {
    struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
    char f[100];

    break_down_flags(argv[2], &fr, NULL);
    build_flags(f, &fr, NULL);
    malloc_strcpy(fdbe->flags_req, f);
  } else
    my_free(fdbe->flags_req);
  if (argc == 4)
    malloc_strcpy(fdbe->chan, argv[3]);

  filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL);
  free_fdbe(&fdbe);
  filedb_close(fdb);
  Tcl_AppendResult(irp, "0", NULL);
  return TCL_OK;
}
Beispiel #6
0
/* Returns the filedb entry matching the filename 'fn' in
 * directory 'dir'.
 */
static filedb_entry *filedb_getentry(char *dir, char *fn)
{
    FILE *fdb;
    filedb_entry *fdbe = NULL;

    fdb = filedb_open(dir, 0);
    if (fdb) {
        filedb_readtop(fdb, NULL);
        fdbe = filedb_matchfile(fdb, ftell(fdb), fn);
        filedb_close(fdb);
    }
    return fdbe;
}
Beispiel #7
0
/* Adds information for a newly added file. Actually the name
 * is misleading, as the file is added in filedb_open() and we
 * only add information in here.
 */
static void filedb_add(FILE *fdb, char *filename, char *nick)
{
    filedb_entry *fdbe = NULL;

    filedb_readtop(fdb, NULL);
    /* When the filedb was opened, a record was already created. */
    fdbe = filedb_matchfile(fdb, ftell(fdb), filename);
    if (!fdbe)
        return;
    my_free(fdbe->uploader);
    malloc_strcpy(fdbe->uploader, nick);
    fdbe->uploaded = now;
    filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL);
    free_fdbe(&fdbe);
}
Beispiel #8
0
/* Merges empty entries to one big entry, if they directly
 * follow each other. Does this for the complete DB.
 * This considerably speeds up several actions performed on
 * the db.
 */
static void filedb_mergeempty(FILE *fdb)
{
  filedb_entry *fdbe_t, *fdbe_i;
  int modified;

  filedb_readtop(fdb, NULL);
  while (!feof(fdb))
  {
    fdbe_t = filedb_getfile(fdb, ftell(fdb), GET_HEADER);
    if (fdbe_t) {
      if (fdbe_t->stat & FILE_UNUSED) {
	modified = 0;
	fdbe_i = filedb_getfile(fdb, ftell(fdb), GET_HEADER);
	while (fdbe_i) {
	  /* Is this entry in use? */
	  if (!(fdbe_i->stat & FILE_UNUSED))
	    break;	/* It is, exit loop. */

	  /* Woohoo, found an empty entry. Append it's space to
	   * our target entry's buffer space.
	   */
	  fdbe_t->buf_len += sizeof(filedb_header) + fdbe_i->buf_len;
	  modified++;
	  free_fdbe(&fdbe_i);
	  /* Get next file entry */
	  fdbe_i = filedb_getfile(fdb, ftell(fdb), GET_HEADER);
	}

	/* Did we exit the loop because of a used entry? */
	if (fdbe_i) {
	  free_fdbe(&fdbe_i);
	  /* Did we find any empty entries before? */
	  if (modified)
	    filedb_updatefile(fdb, fdbe_t->pos, fdbe_t, UPDATE_SIZE);
	/* ... or because we hit EOF? */
	} else {
	  /* Truncate trailing empty entries and exit. */
	  ftruncate(fileno(fdb), fdbe_t->pos);
	  free_fdbe(&fdbe_t);
	  return;
	}
      }
      free_fdbe(&fdbe_t);
    }
  }
}
Beispiel #9
0
static void filedb_setowner(char *dir, char *fn, char *owner)
{
    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) {
        my_free(fdbe->uploader);
        malloc_strcpy(fdbe->uploader, owner);
        filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL);
        free_fdbe(&fdbe);
    }
    filedb_close(fdb);
}
Beispiel #10
0
static void filedb_setdesc(char *dir, char *fn, char *desc)
{
  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) {
    free_null(fdbe->desc);
    realloc_strcpy(fdbe->desc, desc);
    filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL);
    free_fdbe(&fdbe);
  }
  filedb_close(fdb);
}
Beispiel #11
0
static void filedb_getdirs(Tcl_Interp *irp, char *dir)
{
    FILE *fdb;
    filedb_entry *fdbe;

    fdb = filedb_open(dir, 0);
    if (!fdb)
        return;
    filedb_readtop(fdb, NULL);
    while (!feof(fdb)) {
        fdbe = filedb_getfile(fdb, ftell(fdb), GET_FILENAME);
        if (fdbe) {
            if ((!(fdbe->stat & FILE_UNUSED)) && (fdbe->stat & FILE_DIR))
                Tcl_AppendElement(irp, fdbe->filename);
            free_fdbe(&fdbe);
        }
    }
    filedb_close(fdb);
}
Beispiel #12
0
static void filedb_change(char *dir, char *fn)
{
  FILE *fdb;
  filedb_entry *fdbe;
  int changed = 0;

  fdb = filedb_open(dir, 0);
  if (!fdb)
    return;
  filedb_readtop(fdb, NULL);
  fdbe = filedb_matchfile(fdb, ftell(fdb), fn);
  if (fdbe) {
    if (!(fdbe->stat & FILE_DIR))
      changed = 1;
    if (changed)
      filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_HEADER);
    free_fdbe(&fdbe);
  }
  filedb_close(fdb);
}
Beispiel #13
0
/* Searches for a suitable place to write an entry which uses tot
 * bytes for dynamic data.
 *
 *  * If there is no such existing entry, it just points to the
 *    end of the DB.
 *  * If it finds an empty entry and it has enough space to fit
 *    in another entry, we split it up and only use the space we
 *    really need.
 *
 * Note: We can assume that empty entries' dyn_lengths are zero.
 *       Therefore we only need to check buf_len.
 */
static filedb_entry *filedb_findempty(FILE *fdb, int tot)
{
    filedb_entry *fdbe;

    filedb_readtop(fdb, NULL);
    fdbe = filedb_getfile(fdb, ftell(fdb), GET_HEADER);
    while (fdbe) {
        /* Found an existing, empty entry? */
        if ((fdbe->stat & FILE_UNUSED) && (fdbe->buf_len >= tot)) {
            /* Do we have enough space to split up the entry to form
             * another empty entry? That way we would use the space
             * more efficiently.
             */
            if (fdbe->buf_len > (tot + sizeof(filedb_header) + FILEDB_ESTDYN)) {
                filedb_entry *fdbe_oe;

                /* Create new entry containing the additional space */
                fdbe_oe = malloc_fdbe();
                fdbe_oe->stat = FILE_UNUSED;
                fdbe_oe->pos = fdbe->pos + sizeof(filedb_header) + tot;
                fdbe_oe->buf_len = fdbe->buf_len - tot - sizeof(filedb_header);
                filedb_movefile(fdb, fdbe_oe->pos, fdbe_oe);
                free_fdbe(&fdbe_oe);

                /* Cut down buf_len of entry as the rest is now used in the new
                 * entry.
                 */
                fdbe->buf_len = tot;
            }
            return fdbe;
        }
        free_fdbe(&fdbe);
        fdbe = filedb_getfile(fdb, ftell(fdb), GET_HEADER);
    }

    /* No existing entries, so create new entry at end of DB instead. */
    fdbe = malloc_fdbe();
    fseek(fdb, 0L, SEEK_END);
    fdbe->pos = ftell(fdb);
    return fdbe;
}
Beispiel #14
0
static void filedb_change(char *dir, char *fn, int what)
{
    FILE *fdb;
    filedb_entry *fdbe;
    int changed = 0;

    fdb = filedb_open(dir, 0);
    if (!fdb)
        return;
    filedb_readtop(fdb, NULL);
    fdbe = filedb_matchfile(fdb, ftell(fdb), fn);
    if (fdbe) {
        if (!(fdbe->stat & FILE_DIR)) {
            switch (what) {
            case FILEDB_SHARE:
                fdbe->stat |= FILE_SHARE;
                break;
            case FILEDB_UNSHARE:
                fdbe->stat &= ~FILE_SHARE;
                break;
            }
            changed = 1;
        }
        switch (what) {
        case FILEDB_HIDE:
            fdbe->stat |= FILE_HIDDEN;
            changed = 1;
            break;
        case FILEDB_UNHIDE:
            fdbe->stat &= ~FILE_HIDDEN;
            changed = 1;
            break;
        }
        if (changed)
            filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_HEADER);
        free_fdbe(&fdbe);
    }
    filedb_close(fdb);
}
Beispiel #15
0
/* Outputs a sorted list of files/directories matching the mask,
 * to idx.
 */
static void filedb_ls(FILE *fdb, int idx, char *mask, int showall)
{
    int ok = 0, cnt = 0, is = 0;
    char s1[81], *p = NULL;
    struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
    filedb_entry *fdbe = NULL;
    filelist_t *flist = NULL;

    flist = filelist_new();
    filedb_readtop(fdb, NULL);
    fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL);
    while (fdbe) {
        ok = 1;
        if (fdbe->stat & FILE_UNUSED)
            ok = 0;
        if (ok && (fdbe->stat & FILE_DIR) && fdbe->flags_req) {
            /* Check permissions */
            struct flag_record req = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };

            break_down_flags(fdbe->flags_req, &req, NULL);
            get_user_flagrec(dcc[idx].user, &user, dcc[idx].u.file->chat->con_chan);
            if (!flagrec_ok(&req, &user)) {
                ok = 0;
            }
        }
        if (ok)
            is = 1;
        if (ok && !wild_match_file(mask, fdbe->filename))
            ok = 0;
        if (ok && (fdbe->stat & FILE_HIDDEN) && !(showall))
            ok = 0;
        if (ok) {
            /* Display it! */
            if (cnt == 0) {
                dprintf(idx, FILES_LSHEAD1);
                dprintf(idx, FILES_LSHEAD2);
            }
            filelist_add(flist, fdbe->filename);
            if (fdbe->stat & FILE_DIR) {
                char *s2 = NULL, *s3 = NULL;

                /* Too long? */
                if (strlen(fdbe->filename) > 45) {
                    /* Display the filename on its own line. */
                    s2 = nmalloc(strlen(fdbe->filename) + 3);
                    sprintf(s2, "%s/\n", fdbe->filename);
                    filelist_addout(flist, s2);
                    my_free(s2);
                } else {
                    s2 = nmalloc(strlen(fdbe->filename) + 2);
                    sprintf(s2, "%s/", fdbe->filename);
                }
                /* Note: You have to keep the sprintf and the nmalloc statements
                 *       in sync, i.e. always check that you allocate enough
                 *       memory.
                 */
                if ((fdbe->flags_req) && (user.global &(USER_MASTER | USER_JANITOR))) {
                    s3 = nmalloc(42 + strlen(s2 ? s2 : "") + 6 +
                                 strlen(FILES_REQUIRES) + strlen(fdbe->flags_req) + 1 +
                                 strlen(fdbe->chan ? fdbe->chan : "") + 1);
                    sprintf(s3, "%-30s <DIR%s>  (%s %s%s%s)\n", s2,
                            fdbe->stat & FILE_SHARE ?
                            " SHARE" : "", FILES_REQUIRES, fdbe->flags_req,
                            fdbe->chan ? " " : "", fdbe->chan ? fdbe->chan : "");
                } else {
                    s3 = nmalloc(38 + strlen(s2 ? s2 : ""));
                    sprintf(s3, "%-30s <DIR>\n", s2 ? s2 : "");
                }
                if (s2)
                    my_free(s2);
                filelist_addout(flist, s3);
                my_free(s3);
            } else {
                char s2[41], t[50], *s3 = NULL, *s4;

                s2[0] = 0;
                if (showall) {
                    if (fdbe->stat & FILE_SHARE)
                        strcat(s2, " (shr)");
                    if (fdbe->stat & FILE_HIDDEN)
                        strcat(s2, " (hid)");
                }
                egg_strftime(t, 10, "%d%b%Y", localtime(&fdbe->uploaded));
                if (fdbe->size < 1024)
                    sprintf(s1, "%5d", fdbe->size);
                else
                    sprintf(s1, "%4dk", (int) (fdbe->size / 1024));
                if (fdbe->sharelink)
                    strcpy(s1, "     ");
                /* Too long? */
                if (strlen(fdbe->filename) > 30) {
                    s3 = nmalloc(strlen(fdbe->filename) + 2);
                    sprintf(s3, "%s\n", fdbe->filename);
                    filelist_addout(flist, s3);
                    my_free(s3);
                    /* Causes filename to be displayed on its own line */
                } else
                    malloc_strcpy(s3, fdbe->filename);
                s4 = nmalloc(69 + strlen(s3 ? s3 : "") + strlen(s1) +
                             strlen(fdbe->uploader) + strlen(t) + strlen(s2));
                sprintf(s4, "%-30s %s  %-9s (%s)  %6d%s\n", s3 ? s3 : "", s1,
                        fdbe->uploader, t, fdbe->gots, s2);
                if (s3)
                    my_free(s3);
                filelist_addout(flist, s4);
                my_free(s4);
                if (fdbe->sharelink) {
                    s4 = nmalloc(9 + strlen(fdbe->sharelink));
                    sprintf(s4, "   --> %s\n", fdbe->sharelink);
                    filelist_addout(flist, s4);
                    my_free(s4);
                }
            }
            if (fdbe->desc) {
                p = strchr(fdbe->desc, '\n');
                while (p != NULL) {
                    *p = 0;
                    if ((fdbe->desc)[0]) {
                        char *sd;

                        sd = nmalloc(strlen(fdbe->desc) + 5);
                        sprintf(sd, "   %s\n", fdbe->desc);
                        filelist_addout(flist, sd);
                        my_free(sd);
                    }
                    strcpy(fdbe->desc, p + 1);
                    p = strchr(fdbe->desc, '\n');
                }
                if ((fdbe->desc)[0]) {
                    char *sd;

                    sd = nmalloc(strlen(fdbe->desc) + 5);
                    sprintf(sd, "   %s\n", fdbe->desc);
                    filelist_addout(flist, sd);
                    my_free(sd);
                }
            }
            cnt++;
        }
        free_fdbe(&fdbe);
        fdbe = filedb_getfile(fdb, ftell(fdb), GET_FULL);
    }
    if (is == 0)
        dprintf(idx, FILES_NOFILES);
    else if (cnt == 0)
        dprintf(idx, FILES_NOMATCH);
    else {
        filelist_sort(flist);
        filelist_idxshow(flist, idx);
        dprintf(idx, "--- %d file%s.\n", cnt, cnt != 1 ? "s" : "");
    }
    filelist_free(flist);
}
Beispiel #16
0
/* Opens the filedb responsible to the specified directory.
 */
static FILE *filedb_open(char *path, int sort)
{
    char *s, *npath;
    FILE *fdb;
    filedb_top fdbt;
    struct stat st;

    if (count >= 2)
        putlog(LOG_MISC, "*", "(@) warning: %d open filedb's", count);
    npath = nmalloc(strlen(dccdir) + strlen(path) + 1);
    simple_sprintf(npath, "%s%s", dccdir, path);
    /* Use alternate filename if requested */
    if (filedb_path[0]) {
        char *s2;

        s2 = make_point_path(path);
        s = nmalloc(strlen(filedb_path) + strlen(s2) + 8);
        simple_sprintf(s, "%sfiledb.%s", filedb_path, s2);
        my_free(s2);
    } else {
        s = nmalloc(strlen(npath) + 10);
        simple_sprintf(s, "%s/.filedb", npath);
    }
    fdb = fopen(s, "r+b");
    if (!fdb) {
        if (convert_old_files(npath, s)) {
            fdb = fopen(s, "r+b");
            if (fdb == NULL) {
                putlog(LOG_MISC, "*", FILES_NOCONVERT, npath);
                my_free(s);
                my_free(npath);
                return NULL;
            }
            lockfile(fdb);
            filedb_update(npath, fdb, sort);
            count++;
            my_free(s);
            my_free(npath);
            return fdb;
        } else {
            filedb_top fdbt;

            /* Create new database and fix it up */
            fdb = fopen(s, "w+b");
            if (!fdb) {
                my_free(s);
                my_free(npath);
                return NULL;
            }
            lockfile(fdb);
            fdbt.version = FILEDB_NEWEST_VER;
            fdbt.timestamp = now;
            filedb_writetop(fdb, &fdbt);
            filedb_update(npath, fdb, sort);
            count++;
            my_free(s);
            my_free(npath);
            return fdb;
        }
    }

    lockfile(fdb);                /* Lock it from other bots */
    filedb_readtop(fdb, &fdbt);
    if (fdbt.version < FILEDB_NEWEST_VER) {
        if (!convert_old_db(&fdb, s)) {
            /* Conversion failed. Unlock file again and error out.
             * (convert_old_db() could have modified fdb, so check
             * for fdb != NULL.)
             */
            if (fdb)
                unlockfile(fdb);
            my_free(npath);
            my_free(s);
            return NULL;
        }
        filedb_update(npath, fdb, sort);
    }
    stat(npath, &st);
    /* Update filedb if:
     * + it's been 6 hours since it was last updated
     * + the directory has been visibly modified since then
     * (6 hours may be a bit often)
     */
    if (sort || ((now - fdbt.timestamp) > (6 * 3600)) ||
            (fdbt.timestamp < st.st_mtime) || (fdbt.timestamp < st.st_ctime))
        /* File database isn't up-to-date! */
        filedb_update(npath, fdb, sort & 1);
    else if ((now - fdbt.timestamp) > 300)
        filedb_mergeempty(fdb);

    count++;
    my_free(npath);
    my_free(s);
    return fdb;
}
Beispiel #17
0
/* 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  */
}
Beispiel #18
0
static int tcl_rmdir(ClientData cd, Tcl_Interp *irp,
                     int argc, char *argv[])
{
  FILE *fdb;
  filedb_entry *fdbe;
  char *s = NULL, *t, *d, *p;

  BADARGS(2, 2, " dir");

  malloc_strcpy(s, argv[1]);
  if (s[strlen(s) - 1] == '/')
    s[strlen(s) - 1] = 0;
  p = strrchr(s, '/');
  if (p == NULL) {
    p = s;
    d = "";
  } else {
    *p = 0;
    p++;
    d = s;
  }

  fdb = filedb_open(d, 0);
  if (!fdb) {
    Tcl_AppendResult(irp, "1", NULL);
    my_free(s);
    return TCL_OK;
  }
  filedb_readtop(fdb, NULL);
  fdbe = filedb_matchfile(fdb, ftell(fdb), p);

  if (!fdbe) {
    Tcl_AppendResult(irp, "1", NULL);
    filedb_close(fdb);
    my_free(s);
    return TCL_OK;
  }
  if (!(fdbe->stat & FILE_DIR)) {
    Tcl_AppendResult(irp, "1", NULL);
    filedb_close(fdb);
    free_fdbe(&fdbe);
    my_free(s);
    return TCL_OK;
  }
  /* Erase '.filedb' and '.files' if they exist */
  t = nmalloc(strlen(dccdir) + strlen(d) + strlen(p) + 11);
  sprintf(t, "%s%s/%s/.filedb", dccdir, d, p);
  unlink(t);
  sprintf(t, "%s%s/%s/.files", dccdir, d, p);
  unlink(t);
  sprintf(t, "%s%s/%s", dccdir, d, p);
  my_free(s);
  if (rmdir(t) == 0) {
    filedb_delfile(fdb, fdbe->pos);
    filedb_close(fdb);
    free_fdbe(&fdbe);
    my_free(t);
    Tcl_AppendResult(irp, "0", NULL);
    return TCL_OK;
  }
  my_free(t);
  free_fdbe(&fdbe);
  filedb_close(fdb);
  Tcl_AppendResult(irp, "1", NULL);
  return TCL_OK;
}
Beispiel #19
0
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;
}
Beispiel #20
0
static int tcl_mkdir(ClientData cd, Tcl_Interp *irp,
                     int argc, char *argv[])
{
  FILE *fdb;
  filedb_entry *fdbe;
  char *s = NULL, *t, *d, *p;
  struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };

  BADARGS(2, 4, " dir ?required-flags ?channel??");

  malloc_strcpy(s, argv[1]);

  if (s[strlen(s) - 1] == '/')
    s[strlen(s) - 1] = 0;

  p = strrchr(s, '/');
  if (p == NULL) {
    p = s;
    d = "";
  } else {
    *p = 0;
    p++;
    d = s;
  }

  fdb = filedb_open(d, 0);
  if (!fdb) {
    Tcl_AppendResult(irp, "-3", NULL);  /* filedb access failed */
    my_free(s);
    return TCL_OK;
  }
  filedb_readtop(fdb, NULL);
  fdbe = filedb_matchfile(fdb, ftell(fdb), p);

  if (!fdbe) {
    t = nmalloc(strlen(dccdir) + strlen(d) + strlen(p) + 2);
    sprintf(t, "%s%s/%s", dccdir, d, p);
    if (mkdir(t, 0755) != 0) {
      Tcl_AppendResult(irp, "1", NULL);
      my_free(t);
      my_free(s);
      filedb_close(fdb);
      return TCL_OK;
    }
    fdbe = malloc_fdbe();
    fdbe->stat = FILE_DIR;
    malloc_strcpy(fdbe->filename, argv[1]);
    fdbe->uploaded = now;
  } else if (!(fdbe->stat & FILE_DIR)) {
    Tcl_AppendResult(irp, "2", NULL);
    free_fdbe(&fdbe);
    my_free(s);
    filedb_close(fdb);
    return TCL_OK;
  }
  if (argc >= 3) {
    char f[100];

    break_down_flags(argv[2], &fr, NULL);
    build_flags(f, &fr, NULL);
    malloc_strcpy(fdbe->flags_req, f);
  } else if (fdbe->flags_req) {
    my_free(fdbe->flags_req);
  }
  if (argc == 4) {
    malloc_strcpy(fdbe->chan, argv[3]);
  } else if (fdbe->chan)
    my_free(fdbe->chan);

  if (!fdbe->pos)
    fdbe->pos = POS_NEW;
  filedb_updatefile(fdb, fdbe->pos, fdbe, UPDATE_ALL);
  filedb_close(fdb);
  free_fdbe(&fdbe);

  Tcl_AppendResult(irp, "0", NULL);
  return TCL_OK;
}
Beispiel #21
0
static void remote_filereq(int idx, char *from, char *file)
{
    char *p = NULL, *what = NULL, *dir = NULL,
          *s1 = NULL, *reject = NULL, *s = NULL;
    FILE *fdb = NULL;
    int i = 0;
    filedb_entry *fdbe = NULL;

    malloc_strcpy(what, file);
    p = strrchr(what, '/');
    if (p) {
        *p = 0;
        malloc_strcpy(dir, what);
        strcpy(what, p + 1);
    } else {
        malloc_strcpy(dir, "");
    }
    fdb = filedb_open(dir, 0);
    if (!fdb) {
        reject = FILES_DIRDNE;
    } else {
        filedb_readtop(fdb, NULL);
        fdbe = filedb_matchfile(fdb, ftell(fdb), what);
        filedb_close(fdb);
        if (!fdbe) {
            reject = FILES_FILEDNE;
        } else {
            if ((!(fdbe->stat & FILE_SHARE)) ||
                    (fdbe->stat & (FILE_HIDDEN | FILE_DIR)))
                reject = FILES_NOSHARE;
            else {
                s1 = nmalloc(strlen(dccdir) + strlen(dir) + strlen(what) + 2);
                /* Copy to /tmp if needed */
                sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", what);
                if (copy_to_tmp) {
                    s = nmalloc(strlen(tempdir) + strlen(what) + 1);
                    sprintf(s, "%s%s", tempdir, what);
                    copyfile(s1, s);
                } else
                    s = s1;
                i = raw_dcc_send(s, "*remote", FILES_REMOTE, s);
                if (i > 0) {
                    wipe_tmp_filename(s, -1);
                    reject = FILES_SENDERR;
                }
                if (s1 != s)
                    my_free(s);
                my_free(s1);
            }
            free_fdbe(&fdbe);
        }
    }
    s1 = nmalloc(strlen(botnetnick) + strlen(dir) + strlen(what) + 3);
    simple_sprintf(s1, "%s:%s/%s", botnetnick, dir, what);
    if (reject) {
        botnet_send_filereject(idx, s1, from, reject);
        my_free(s1);
        my_free(what);
        my_free(dir);
        return;
    }
    /* Grab info from dcc struct and bounce real request across net */
    i = dcc_total - 1;
    s = nmalloc(40);              /* Enough? */
    simple_sprintf(s, "%d %u %d", iptolong(getmyip()), dcc[i].port,
                   dcc[i].u.xfer->length);
    botnet_send_filesend(idx, s1, from, s);
    putlog(LOG_FILES, "*", FILES_REMOTEREQ, dir, dir[0] ? "/" : "", what);
    my_free(s1);
    my_free(s);
    my_free(what);
    my_free(dir);
}