/*****************************************************************************\
* Copyright (c) 2002 Pelle Johansson. *
* All rights reserved. *
* *
* This file is part of the moftpd package. Use and distribution of *
* this software is governed by the terms in the file LICENCE, which *
* should have come with this package. *
\*****************************************************************************/
/* $moftpd: com_file.c 1251 2005-03-06 22:24:29Z morth $ */
#include "system.h"
#include "commands.h"
#include "connection.h"
#include "utf8fs/memory.h"
int command_rnfr(connection_t *conn, const char *arg, int expected)
{
struct stat st;
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if(check_access(arg, acRename) || lstat(arg, &st))
{
switch(errno)
{
case ENOENT:
reply(conn, "550 File does not exist.");
return 0;
default:
reply(conn, "553 %s.", strerror(errno));
return 0;
}
}
if(conn->rnfr)
pfree(conn->rnfr, conn);
conn->rnfr = pstring(arg, conn);
if(!conn->rnfr)
{
reply(conn, "553 %s.", strerror(errno));
return 0;
}
reply(conn, "350 RNTO expected.");
conn->expect = "RNTO";
return 0;
}
int command_rnto(connection_t *conn, const char *arg, int expected)
{
struct stat st;
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
if(!expected)
{
reply(conn, "503 RNTO not expected here.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if(check_access(arg, acRename))
{
reply(conn, "553 %s.", strerror(errno));
return 0;
}
if(!lstat(arg, &st))
{
reply(conn, "553 File exists.");
return 0;
}
if(rename_file(conn->rnfr, arg))
{
pfree(conn->rnfr, conn);
conn->rnfr = NULL;
reply(conn, "553 %s.", strerror(errno));
return 0;
}
pfree(conn->rnfr, conn);
conn->rnfr = NULL;
reply(conn, "250 Rename ok.");
return 0;
}
int command_dele(connection_t *conn, const char *arg, int expected)
{
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if(delete_file(arg))
{
switch(errno)
{
case ENOENT:
reply(conn, "550 File does not exist.");
return 0;
default:
reply(conn, "553 %s.", strerror(errno));
return 0;
}
}
reply(conn, "250 File deleted.");
return 0;
}
int command_rmd(connection_t *conn, const char *arg, int expected)
{
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if(delete_dir(arg))
{
switch(errno)
{
case ENOENT:
reply(conn, "550 File does not exist.");
return 0;
default:
reply(conn, "553 %s.", strerror(errno));
return 0;
}
}
reply(conn, "250 Directory deleted.");
return 0;
}
int command_mkd(connection_t *conn, const char *arg, int expected)
{
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if(create_dir(arg))
{
reply(conn, "553 %s.", strerror(errno));
return 0;
}
reply(conn, "250 Directory created.");
return 0;
}
int command_size(connection_t *conn, const char *arg, int expected)
{
struct stat st;
long long res;
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if (!check_access (arg, acReadFile) && !stat (arg, &st))
{
if(S_ISDIR(st.st_mode))
{
reply(conn, "553 Is a directory.");
return 0;
}
}
else
{
reply(conn, "550 %s.", strerror(errno));
return 0;
}
res = st.st_size;
if (conn->type == ttText)
{
int fd = open_file_reading (arg, 0);
int l;
char buf[1024], *bp;
if (fd < 0)
{
reply (conn, "550 %s.", strerror (errno));
return 0;
}
while ((l = read (fd, buf, 1024)) > 0)
{
bp = buf;
while (l > 0 && (bp = memchr (bp, '\n', l)))
{
res++;
l -= ++bp - buf;
}
}
close (fd);
}
reply(conn, "213 %lld", res);
return 0;
}
int command_mdtm(connection_t *conn, const char *arg, int expected)
{
struct stat st;
if (!strlen (arg))
{
reply (conn, "501 Path missing.");
return 0;
}
arg = chroot_path (arg, conn->cwd, conn->user->home);
if (!check_access (arg, acReadFile) && !stat (arg, &st))
{
struct tm *tm = gmtime (&st.st_mtime);
reply (conn, "213 %04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
}
else
reply (conn, "550 %s.", strerror (errno));
return 0;
}
int sitecommand_chmod (connection_t *conn, const char *arg, int expected)
{
const char *path = strchr (arg, ' ');
char *ap;
unsigned int mode;
if (!strlen (arg))
{
reply (conn, "501 mode missing.");
return 0;
}
mode = strtoul (arg, &ap, 8);
if (ap != path)
{
reply (conn, "500 Invalid mode.");
return 0;
}
if (!path || !strlen (++path))
{
reply (conn, "501 Path missing.");
return 0;
}
path = chroot_path (path, conn->cwd, conn->user->home);
if (!check_access (path, acCreateFile))
{
if (chmod (path, mode))
reply (conn, "550 %s.", strerror (errno));
else
reply (conn, "250 Mode changed successfully.");
}
else
reply (conn, "550 Access denied.");
return 0;
}
int command_mfmt (connection_t *conn, const char *arg, int expected)
{
const char *path = strchr (arg, ' ');
char *timestr;
struct timeval t[2];
if (!arg[0])
{
reply (conn, "501 time missing.");
return 0;
}
if (!path || strlen (path) < 2)
{
reply (conn, "501 Path missing.");
return 0;
}
timestr = talloc (path - arg + 1);
if (!timestr)
{
reply (conn, "500 %s.", strerror (errno));
return 0;
}
strncpy (timestr, arg, path - arg);
timestr[path++ - arg] = 0;
t[1].tv_sec = t[0].tv_sec = get_timeval (timestr);
if (t[0].tv_sec == -1)
{
reply (conn, "500 Invalid time-val.");
return 0;
}
t[1].tv_usec = t[0].tv_usec = 0;
path = chroot_path (path, conn->cwd, conn->user->home);
if (!check_access (path, acCreateFile))
{
if (utimes (path, t))
reply (conn, "550 %s.", strerror (errno));
else
{
time_t ti = t[0].tv_sec;
struct tm *tm = gmtime (&ti);
reply (conn, "213 Modify=%04d%02d%02d%02d%02d%02d; %s", tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, print_path (path));
}
}
else
reply (conn, "550 Access denied.");
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1