Пример #1
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);
}
Пример #2
0
static void remote_filereq(int idx, char *from, char *file)
{
  char *p, what[256], dir[256], s[256], s1[256], *reject;
  FILE *f;
  filedb fdb;
  long i = 0;

  strcpy(what, file);
  p = strrchr(what, '/');
  if (p == NULL)
    dir[0] = 0;
  else {
    *p = 0;
    strcpy(dir, what);
    strcpy(what, p + 1);
  }
  f = filedb_open(dir, 0);
  reject = NULL;
  if (f == NULL) {
    reject = FILES_DIRDNE;
  } else {
    if (!findmatch(f, what, &i, &fdb)) {
      reject = FILES_FILEDNE;
      filedb_close(f);
    } else {
      if ((!(fdb.stat & FILE_SHARE)) ||
	  (fdb.stat & (FILE_HIDDEN | FILE_DIR))) {
	reject = FILES_NOSHARE;
	filedb_close(f);
      } else {
	filedb_close(f);
	/* copy to /tmp if needed */
	sprintf(s1, "%s%s%s%s", dccdir, dir, dir[0] ? "/" : "", what);
	if (copy_to_tmp) {
	  sprintf(s, "%s%s", tempdir, what);
	  copyfile(s1, s);
	} else
	  strcpy(s, s1);
	i = raw_dcc_send(s, "*remote", FILES_REMOTE, s);
	if (i > 0) {
	  wipe_tmp_filename(s, -1);
	  reject = FILES_SENDERR;
	}
      }
    }
  }
  simple_sprintf(s1, "%s:%s/%s", botnetnick, dir, what);
  if (reject) {
    botnet_send_filereject(idx, s1, from, reject);
    return;
  }
  /* grab info from dcc struct and bounce real request across net */
  i = dcc_total - 1;
  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);
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
static int filedb_getgots(char *dir, char *fn)
{
  FILE *f;
  filedb fdb;
  long i = 0;

  f = filedb_open(dir, 0);
  if (!f)
    return 0;
  if (!findmatch(f, fn, &i, &fdb))
    fdb.gots = 0;
  filedb_close(f);
  return fdb.gots;
}
Пример #6
0
static void filedb_getlink(char *dir, char *fn, char *link)
{
  FILE *f;
  filedb fdb;
  long i = 0;

  f = filedb_open(dir, 0);
  link[0] = 0;
  if (!f)
    return;
  if (findmatch(f, fn, &i, &fdb) && !(fdb.stat & FILE_DIR))
    strcpy(link, fdb.sharelink);
  filedb_close(f);
  return;
}
Пример #7
0
static void filedb_getdesc(char *dir, char *fn, char *desc)
{
  FILE *f;
  filedb fdb;
  long i = 0;

  f = filedb_open(dir, 0);
  if (!f) {
    desc[0] = 0;
    return;
  }
  if (!findmatch(f, fn, &i, &fdb))
    desc[0] = 0;
  else
    strcpy(desc, fdb.desc);
  filedb_close(f);
  return;
}
Пример #8
0
static void filedb_setowner(char *dir, char *fn, char *owner)
{
  FILE *f;
  filedb fdb;
  long where = 0;

  f = filedb_open(dir, 0);
  if (!f)
    return;
  if (findmatch(f, fn, &where, &fdb)) {
    strncpy(fdb.uploader, owner, HANDLEN);
    fdb.uploader[HANDLEN] = 0;
    fseek(f, where, SEEK_SET);
    fwrite(&fdb, sizeof(filedb), 1, f);
  }
  filedb_close(f);
  return;
}
Пример #9
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);
}
Пример #10
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);
}
Пример #11
0
static void filedb_setdesc(char *dir, char *fn, char *desc)
{
  FILE *f;
  filedb fdb;
  long where = 0;

  f = filedb_open(dir, 0);
  if (!f)
    return;
  if (findmatch(f, fn, &where, &fdb)) {
    strncpy(fdb.desc, desc, 185);
    fdb.desc[185] = 0;
    fseek(f, where, SEEK_SET);
    fwrite(&fdb, sizeof(filedb), 1, f);
  }
  filedb_close(f);
  return;
}
Пример #12
0
static void filedb_getdirs(Tcl_Interp * irp, char *dir)
{
  FILE *f;
  filedb fdb;

  f = filedb_open(dir, 0);
  if (!f)
    return;
  rewind(f);
  while (!feof(f)) {
    fread(&fdb, sizeof(filedb), 1, f);
    if (!feof(f)) {
      if ((!(fdb.stat & FILE_UNUSED)) && (fdb.stat & FILE_DIR))
	Tcl_AppendElement(irp, fdb.filename);
    }
  }
  filedb_close(f);
}
Пример #13
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);
}
Пример #14
0
static void filedb_setlink(char *dir, char *fn, char *link)
{
  FILE *f;
  filedb fdb;
  long where = 0;

  f = filedb_open(dir, 0);
  if (!f)
    return;
  if (findmatch(f, fn, &where, &fdb)) {
    /* change existing one? */
    if ((fdb.stat & FILE_DIR) || !(fdb.sharelink[0]))
      return;
    if (!link[0]) {
      /* erasing file */
      fdb.stat |= FILE_UNUSED;
    } else {
      strncpy(fdb.sharelink, link, 60);
      fdb.sharelink[60] = 0;
    }
    fseek(f, where, SEEK_SET);
    fwrite(&fdb, sizeof(filedb), 1, f);
    filedb_close(f);
    return;
  }
  fdb.version = FILEVERSION;
  fdb.stat = 0;
  fdb.desc[0] = 0;
  strcpy(fdb.uploader, botnetnick);
  strncpy(fdb.filename, fn, 30);
  fdb.filename[30] = 0;
  fdb.flags_req[0] = 0;
  fdb.uploaded = now;
  fdb.size = 0;
  fdb.gots = 0;
  fdb.chname[0] = 0;
  strncpy(fdb.sharelink, link, 60);
  fdb.sharelink[60] = 0;
  where = findempty(f);
  fseek(f, where, SEEK_SET);
  fwrite(&fdb, sizeof(filedb), 1, f);
  filedb_close(f);
}
Пример #15
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);
}
Пример #16
0
static void filedb_getowner(char *dir, char *fn, char *owner)
{
  FILE *f;
  filedb fdb;
  long i = 0;

  f = filedb_open(dir, 0);
  if (!f) {
    owner[0] = 0;
    return;
  }
  if (!findmatch(f, fn, &i, &fdb))
    owner[0] = 0;
  else {
    strncpy(owner, fdb.uploader, HANDLEN);
    owner[HANDLEN] = 0;
  }
  filedb_close(f);
  return;
}
Пример #17
0
static void filedb_change(char *dir, char *fn, int what)
{
  FILE *f;
  filedb fdb;
  int changed = 0;
  long where = 0;

  f = filedb_open(dir, 0);
  if (f) {
    if (findmatch(f, fn, &where, &fdb)) {
      if (!(fdb.stat & FILE_DIR)) {
	switch (what) {
	case FILEDB_SHARE:
	  fdb.stat |= FILE_SHARE;
	  break;
	case FILEDB_UNSHARE:
	  fdb.stat &= ~FILE_SHARE;
	  break;
	}
	changed = 1;
      }
      switch(what) {
      case FILEDB_HIDE:
	fdb.stat |= FILE_HIDDEN;
	changed = 1;
	break;
      case FILEDB_UNHIDE:
	fdb.stat &= ~FILE_HIDDEN;
	changed = 1;
	break;
      }
      if (changed) {
	fseek(f, where, SEEK_SET);
	fwrite(&fdb, sizeof(filedb), 1, f);
      }
    }
    filedb_close(f);
  }
  return;
}
Пример #18
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);
}
Пример #19
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;
}
Пример #20
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);
}
Пример #21
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;
}
Пример #22
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;
}