/*
* tclfiles.c -- part of filesys.mod
* Tcl stubs for file system commands moved here to support modules
*
* $Id: tclfiles.c,v 1.26 2006-03-28 02:35:51 wcc Exp $
*/
/*
* Copyright (C) 1997 Robey Pointer
* Copyright (C) 1999 - 2006 Eggheads Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
static int tcl_getdesc STDVAR
{
char *s = NULL;
BADARGS(3, 3, " dir file");
filedb_getdesc(argv[1], argv[2], &s);
if (s) {
Tcl_AppendResult(irp, s, NULL);
my_free(s);
return TCL_OK;
} else {
Tcl_AppendResult(irp, "filedb access failed", NULL);
return TCL_ERROR;
}
}
static int tcl_setdesc STDVAR
{
BADARGS(4, 4, " dir file desc");
filedb_setdesc(argv[1], argv[2], argv[3]);
return TCL_OK;
}
static int tcl_getowner STDVAR
{
char *s = NULL;
BADARGS(3, 3, " dir file");
filedb_getowner(argv[1], argv[2], &s);
if (s) {
Tcl_AppendResult(irp, s, NULL);
my_free(s);
return TCL_OK;
} else {
Tcl_AppendResult(irp, "filedb access failed", NULL);
return TCL_ERROR;
}
}
static int tcl_setowner STDVAR
{
BADARGS(4, 4, " dir file owner");
filedb_setowner(argv[1], argv[2], argv[3]);
return TCL_OK;
}
static int tcl_getgots STDVAR
{
int i;
char s[10];
BADARGS(3, 3, " dir file");
i = filedb_getgots(argv[1], argv[2]);
sprintf(s, "%d", i);
Tcl_AppendResult(irp, s, NULL);
return TCL_OK;
}
static int tcl_setlink STDVAR
{
BADARGS(4, 4, " dir file link");
filedb_setlink(argv[1], argv[2], argv[3]);
return TCL_OK;
}
static int tcl_getlink STDVAR
{
char *s = NULL;
BADARGS(3, 3, " dir file");
filedb_getlink(argv[1], argv[2], &s);
if (s) {
Tcl_AppendResult(irp, s, NULL);
return TCL_OK;
} else {
Tcl_AppendResult(irp, "filedb access failed", NULL);
return TCL_ERROR;
}
}
static int tcl_setpwd STDVAR
{
int i, idx;
BADARGS(3, 3, " idx dir");
i = atoi(argv[1]);
idx = findanyidx(i);
if ((idx < 0) || (dcc[idx].type != &DCC_FILES)) {
Tcl_AppendResult(irp, "invalid idx", NULL);
return TCL_ERROR;
}
files_setpwd(idx, argv[2]);
return TCL_OK;
}
static int tcl_getpwd STDVAR
{
int i, idx;
BADARGS(2, 2, " idx");
i = atoi(argv[1]);
idx = findanyidx(i);
if ((idx < 0) || (dcc[idx].type != &DCC_FILES)) {
Tcl_AppendResult(irp, "invalid idx", NULL);
return TCL_ERROR;
}
Tcl_AppendResult(irp, dcc[idx].u.file->dir, NULL);
return TCL_OK;
}
static int tcl_getfiles STDVAR
{
BADARGS(2, 2, " dir");
filedb_getfiles(irp, argv[1]);
return TCL_OK;
}
static int tcl_getdirs STDVAR
{
BADARGS(2, 2, " dir");
filedb_getdirs(irp, argv[1]);
return TCL_OK;
}
static int tcl_hide STDVAR
{
BADARGS(3, 3, " dir file");
filedb_change(argv[1], argv[2], FILEDB_HIDE);
return TCL_OK;
}
static int tcl_unhide STDVAR
{
BADARGS(3, 3, " dir file");
filedb_change(argv[1], argv[2], FILEDB_UNHIDE);
return TCL_OK;
}
static int tcl_share STDVAR
{
BADARGS(3, 3, " dir file");
filedb_change(argv[1], argv[2], FILEDB_SHARE);
return TCL_OK;
}
static int tcl_unshare STDVAR
{
BADARGS(3, 3, " dir file");
filedb_change(argv[1], argv[2], FILEDB_UNSHARE);
return TCL_OK;
}
static int tcl_setflags STDVAR
{
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;
}
static int tcl_getflags STDVAR
{
filedb_entry *fdbe;
char *s = NULL, *p, *d;
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;
}
fdbe = filedb_getentry(d, p);
/* Directory doesn't exist? */
if (!fdbe || !(fdbe->stat & FILE_DIR)) {
Tcl_AppendResult(irp, "", NULL);
my_free(s);
free_fdbe(&fdbe);
return TCL_OK;
}
if (fdbe->flags_req) {
malloc_strcpy(s, fdbe->flags_req);
if (s[0] == '-')
s[0] = 0;
} else
s[0] = 0;
Tcl_AppendElement(irp, s);
Tcl_AppendElement(irp, fdbe->chan);
my_free(s);
free_fdbe(&fdbe);
return TCL_OK;
}
static int tcl_mkdir STDVAR
{
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;
}
static int tcl_rmdir STDVAR
{
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;
}
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;
}
static int tcl_mv STDVAR
{
return tcl_mv_cp(irp, argc, argv, 0);
}
static int tcl_cp STDVAR
{
return tcl_mv_cp(irp, argc, argv, 1);
}
static int tcl_fileresend_send(ClientData cd, Tcl_Interp *irp, int argc,
char *argv[], int resend)
{
int i, idx;
char s[21];
BADARGS(3, 4, " idx filename ?nick?");
i = atoi(argv[1]);
idx = findanyidx(i);
if (idx < 0 || dcc[idx].type != &DCC_FILES) {
Tcl_AppendResult(irp, "invalid idx", NULL);
return TCL_ERROR;
}
if (argc == 4)
i = files_reget(idx, argv[2], argv[3], resend);
else
i = files_reget(idx, argv[2], "", resend);
sprintf(s, "%d", i);
Tcl_AppendResult(irp, s, NULL);
return TCL_OK;
}
static int tcl_fileresend STDVAR
{
return tcl_fileresend_send(cd, irp, argc, argv, 1);
}
static int tcl_filesend STDVAR
{
return tcl_fileresend_send(cd, irp, argc, argv, 0);
}
static tcl_cmds mytcls[] = {
{"getdesc", tcl_getdesc},
{"getowner", tcl_getowner},
{"setdesc", tcl_setdesc},
{"setowner", tcl_setowner},
{"getgots", tcl_getgots},
{"getpwd", tcl_getpwd},
{"setpwd", tcl_setpwd},
{"getlink", tcl_getlink},
{"setlink", tcl_setlink},
{"getfiles", tcl_getfiles},
{"getdirs", tcl_getdirs},
{"hide", tcl_hide},
{"unhide", tcl_unhide},
{"share", tcl_share},
{"unshare", tcl_unshare},
{"filesend", tcl_filesend},
{"fileresend", tcl_fileresend},
{"mkdir", tcl_mkdir},
{"rmdir", tcl_rmdir},
{"cp", tcl_cp},
{"mv", tcl_mv},
{"getflags", tcl_getflags},
{"setflags", tcl_setflags},
{NULL, NULL}
};
syntax highlighted by Code2HTML, v. 0.9.1