static void handle_mkd(struct vsf_session* p_sess) { int retval; vsf_log_start_entry(p_sess, kVSFLogEntryMkdir); str_copy(&p_sess->log_str, &p_sess->ftp_arg_str); prepend_path_to_filename(&p_sess->log_str); /* NOTE! Actual permissions will be governed by the tunable umask */ retval = str_mkdir(&p_sess->ftp_arg_str, 0777); if (retval != 0) { vsf_log_do_log(p_sess, 0); vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Create directory operation failed."); return; } vsf_log_do_log(p_sess, 1); { static struct mystr s_mkd_res; static struct mystr s_tmp_str; str_copy(&s_tmp_str, &p_sess->ftp_arg_str); prepend_path_to_filename(&s_tmp_str); /* Double up double quotes */ str_replace_text(&s_tmp_str, "\"", "\"\""); /* Build result string */ str_alloc_text(&s_mkd_res, "\""); str_append_str(&s_mkd_res, &s_tmp_str); str_append_text(&s_mkd_res, "\" created"); vsf_cmdio_write_str(p_sess, FTP_MKDIROK, &s_mkd_res); } }
enum EVSFPrivopLoginResult vsf_privop_do_login(struct vsf_session* p_sess, const struct mystr* p_pass_str) { enum EVSFPrivopLoginResult result = handle_login(p_sess, &p_sess->user_str, p_pass_str); vsf_log_start_entry(p_sess, kVSFLogEntryLogin); if (result == kVSFLoginFail) { vsf_log_do_log(p_sess, 0); if (tunable_delay_failed_login) { vsf_sysutil_sleep((double) tunable_delay_failed_login); } } else { vsf_log_do_log(p_sess, 1); if (tunable_delay_successful_login) { vsf_sysutil_sleep((double) tunable_delay_successful_login); } } return result; }
enum EVSFPrivopLoginResult vsf_privop_do_login(struct vsf_session* p_sess, const struct mystr* p_pass_str) { enum EVSFPrivopLoginResult result = handle_login(p_sess, &p_sess->user_str, p_pass_str); vsf_log_start_entry(p_sess, kVSFLogEntryLogin); if (result == kVSFLoginFail) { vsf_log_do_log(p_sess, 0); } else { vsf_log_do_log(p_sess, 1); } return result; }
static void handle_upload_common(struct vsf_session* p_sess, int is_append) { struct vsf_transfer_ret trans_ret; int new_file_fd; int remote_fd; int retval; filesize_t offset = p_sess->restart_pos; p_sess->restart_pos = 0; if (!pasv_active(p_sess) && !port_active(p_sess)) { vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first."); return; } /* NOTE - actual file permissions will be governed by the tunable umask */ /* XXX - do we care about race between create and chown() of anonymous * upload? */ if (p_sess->is_anonymous && !tunable_anon_other_write_enable) { new_file_fd = str_create(&p_sess->ftp_arg_str); } else { /* For non-anonymous, allow open() to overwrite or append existing files */ if (!is_append && offset == 0) { new_file_fd = str_create_overwrite(&p_sess->ftp_arg_str); } else { new_file_fd = str_create_append(&p_sess->ftp_arg_str); } } if (vsf_sysutil_retval_is_error(new_file_fd)) { vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create file."); return; } /* Are we required to chown() this file for security? */ if (p_sess->is_anonymous && tunable_chown_uploads) { if (tunable_one_process_model) { vsf_one_process_chown_upload(p_sess, new_file_fd); } else { vsf_two_process_chown_upload(p_sess, new_file_fd); } } if (!is_append && offset != 0) { /* XXX - warning, allows seek past end of file! Check for seek > size? */ vsf_sysutil_lseek_to(new_file_fd, offset); } remote_fd = get_remote_transfer_fd(p_sess); if (vsf_sysutil_retval_is_error(remote_fd)) { goto port_pasv_cleanup_out; } vsf_cmdio_write(p_sess, FTP_DATACONN, "Ok to send data."); vsf_log_start_entry(p_sess, kVSFLogEntryUpload); str_copy(&p_sess->log_str, &p_sess->ftp_arg_str); prepend_path_to_filename(&p_sess->log_str); if (tunable_ascii_upload_enable && p_sess->is_ascii) { trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd, new_file_fd, 1, 1); } else { trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd, new_file_fd, 1, 0); } p_sess->transfer_size = trans_ret.transferred; /* XXX - handle failure, delete file? */ retval = dispose_remote_transfer_fd(p_sess); /* Log _after_ the blocking dispose call, so we get transfer times right */ if (trans_ret.retval == 0 && retval == 0) { vsf_log_do_log(p_sess, 1); } else { vsf_log_do_log(p_sess, 0); } port_pasv_cleanup_out: port_cleanup(p_sess); pasv_cleanup(p_sess); vsf_sysutil_close(new_file_fd); }
static void handle_retr(struct vsf_session* p_sess) { static struct mystr s_mark_str; static struct vsf_sysutil_statbuf* s_p_statbuf; struct vsf_transfer_ret trans_ret; int retval; int remote_fd; int opened_file; int is_ascii = 0; filesize_t offset = p_sess->restart_pos; p_sess->restart_pos = 0; if (!pasv_active(p_sess) && !port_active(p_sess)) { vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first."); return; } if (p_sess->is_ascii && offset != 0) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "No support for resume of ASCII transfer."); return; } opened_file = str_open(&p_sess->ftp_arg_str, kVSFSysStrOpenReadOnly); if (vsf_sysutil_retval_is_error(opened_file)) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file."); return; } vsf_sysutil_fstat(opened_file, &s_p_statbuf); /* No games please */ if (!vsf_sysutil_statbuf_is_regfile(s_p_statbuf)) { /* Note - pretend open failed */ vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file."); goto file_close_out; } /* Optionally, we'll be paranoid and only serve publicly readable stuff */ if (p_sess->is_anonymous && tunable_anon_world_readable_only && !vsf_sysutil_statbuf_is_readable_other(s_p_statbuf)) { vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file."); goto file_close_out; } /* Set the download offset (from REST) if any */ if (offset != 0) { vsf_sysutil_lseek_to(opened_file, offset); } remote_fd = get_remote_transfer_fd(p_sess); if (vsf_sysutil_retval_is_error(remote_fd)) { goto port_pasv_cleanup_out; } vsf_log_start_entry(p_sess, kVSFLogEntryDownload); str_copy(&p_sess->log_str, &p_sess->ftp_arg_str); prepend_path_to_filename(&p_sess->log_str); str_alloc_text(&s_mark_str, "Opening "); if (tunable_ascii_download_enable && p_sess->is_ascii) { str_append_text(&s_mark_str, "ASCII"); is_ascii = 1; } else { str_append_text(&s_mark_str, "BINARY"); } str_append_text(&s_mark_str, " mode data connection for "); str_append_str(&s_mark_str, &p_sess->ftp_arg_str); str_append_text(&s_mark_str, " ("); str_append_filesize_t(&s_mark_str, vsf_sysutil_statbuf_get_size(s_p_statbuf)); str_append_text(&s_mark_str, " bytes)."); vsf_cmdio_write_str(p_sess, FTP_DATACONN, &s_mark_str); trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd, opened_file, 0, is_ascii); p_sess->transfer_size = trans_ret.transferred; retval = dispose_remote_transfer_fd(p_sess); /* Log _after_ the blocking dispose call, so we get transfer times right */ if (trans_ret.retval == 0 && retval == 0) { vsf_log_do_log(p_sess, 1); } else { vsf_log_do_log(p_sess, 0); } port_pasv_cleanup_out: port_cleanup(p_sess); pasv_cleanup(p_sess); file_close_out: vsf_sysutil_close(opened_file); }