/*****************************************************************************\ * 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; }