/* ** 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 */ #include #include #ifdef STDC_HEADERS # include #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; }