/*
** Copyright 2000-2004 University of Illinois Board of Trustees
** Copyright 2000-2004 Mark D. Roth
** All rights reserved.
**
** ftpops.c - miscellaneous FTP operations
**
** Mark D. Roth <roth@feep.net>
*/
#include <internal.h>
#include <errno.h>
#ifdef STDC_HEADERS
# include <string.h>
#endif
/* set TYPE for data connection */
int
ftp_type(FTP *ftp, char *type)
{
char buf[FTPBUFSIZE];
int code;
/*
** if we've already asked for the right type,
** nothing needs to be done
*/
if (strcmp(ftp->ftp_type, type) == 0)
return 0;
/* send TYPE command */
if (_ftp_send_command(ftp, "TYPE %s", type) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
/* check response code */
if (code != 200)
{
if (code == 421)
errno = ECONNRESET;
else
errno = EINVAL;
return -1;
}
/* save new type setting */
strlcpy(ftp->ftp_type, type, sizeof(ftp->ftp_type));
return 0;
}
/* rename a file */
int
ftp_rename(FTP *ftp, char *oldname, char *newname)
{
int code;
char buf[FTPBUFSIZE];
if (_ftp_send_command(ftp, "RNFR %s", oldname) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 350)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 450)
errno = ETXTBSY;
else if (code == 550)
errno = ENOENT;
else if (code == 530)
errno = EACCES;
else
errno = EINVAL;
return -1;
}
if (_ftp_send_command(ftp, "RNTO %s", newname) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 250)
{
if (code == 421)
errno = ECONNRESET;
else
errno = EINVAL;
return -1;
}
return 0;
}
/* remove a file or directory */
int
ftp_remove(FTP *ftp, char *path)
{
struct ftpstat fs;
if (ftp_lstat(ftp, path, &fs) == -1)
return -1;
return (S_ISDIR(fs.fs_mode)
? ftp_rmdir(ftp, path)
: ftp_unlink(ftp, path));
}
/* remove a file */
int
ftp_unlink(FTP *ftp, char *file)
{
int code;
char buf[FTPBUFSIZE];
if (_ftp_send_command(ftp, "DELE %s", file) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 250)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 550)
errno = ENOENT;
else if (code == 530)
errno = EACCES;
else if (code == 450)
errno = ETXTBSY;
else
errno = EINVAL;
return -1;
}
return 0;
}
/* determine the remote system type */
char *
ftp_systype(FTP *ftp)
{
int code;
char buf[FTPBUFSIZE];
char *cp;
if (ftp->ftp_systype[0] != 0)
return ftp->ftp_systype;
if (_ftp_send_command(ftp, "SYST") == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return NULL;
if (code == 215)
{
if ((cp = strchr(buf, ' ')) != NULL)
*cp = '\0';
strlcpy(ftp->ftp_systype, buf, sizeof(ftp->ftp_systype));
}
else if (code == 500)
strlcpy(ftp->ftp_systype, "Unknown", sizeof(ftp->ftp_systype));
else
{
if (code == 421)
errno = ECONNRESET;
else
errno = EINVAL;
return NULL;
}
return ftp->ftp_systype;
}
/* get server status */
int
ftp_status(FTP *ftp, char *buf, size_t bufsize)
{
int code;
if (_ftp_send_command(ftp, "STAT") == -1
|| _ftp_get_response(ftp, &code, buf, bufsize) == -1)
return -1;
if (code != 211)
{
if (code == 421)
errno = ECONNRESET;
else
errno = EINVAL;
return -1;
}
return 0;
}
/* get current directory */
static char *
_ftp_pwd(FTP *ftp)
{
int code;
char buf[FTPBUFSIZE];
char *cp1, *cp2;
if (_ftp_send_command(ftp, "PWD") == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return NULL;
if (code != 257)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 550)
errno = ENOENT;
else
errno = EINVAL;
return NULL;
}
if ((cp1 = strchr(buf, '"')) != NULL
&& (cp2 = strchr(++cp1, '"')) != NULL)
{
*cp2 = '\0';
strlcpy(ftp->ftp_dir, cp1, sizeof(ftp->ftp_dir));
return ftp->ftp_dir;
}
errno = EINVAL;
return NULL;
}
/* return current directory */
char *
ftp_getcwd(FTP *ftp)
{
if (ftp->ftp_dir[0] != '\0')
return ftp->ftp_dir;
return _ftp_pwd(ftp);
}
/* change directory */
int
ftp_chdir(FTP *ftp, char *dir)
{
int code;
char buf[FTPBUFSIZE];
if (_ftp_send_command(ftp, "CWD %s", dir) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 250)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 530)
errno = EACCES;
else if (code == 550)
{
/*
** the server returns the same response code
** for ENOENT and ENOTDIR, so let's try to
** guess which one it really means
*/
if (strstr(buf, "Not a directory") != NULL)
errno = ENOTDIR;
else
errno = ENOENT;
}
else
errno = EINVAL;
return -1;
}
/* make sure we update our cached copy */
if (_ftp_pwd(ftp) == NULL)
return -1;
return 0;
}
/* make a directory */
int
ftp_mkdir(FTP *ftp, char *dir)
{
int code;
char buf[FTPBUFSIZE];
if (_ftp_send_command(ftp, "MKD %s", dir) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 257)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 530)
errno = EACCES;
else if (code == 550)
errno = ENOENT;
else
errno = EINVAL;
return -1;
}
return 0;
}
/* remove a directory */
int
ftp_rmdir(FTP *ftp, char *dir)
{
int code;
char buf[FTPBUFSIZE];
if (_ftp_send_command(ftp, "RMD %s", dir) == -1
|| _ftp_get_response(ftp, &code, buf, sizeof(buf)) == -1)
return -1;
if (code != 250)
{
if (code == 421)
errno = ECONNRESET;
else if (code == 530)
errno = EACCES;
else if (code == 550)
errno = ENOENT;
else
errno = EINVAL;
return -1;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1