int proxy_netio_postopen(pr_netio_stream_t *nstrm) { int res = 0, xerrno; pr_netio_t *curr_netio = NULL; if (nstrm == NULL) { errno = EINVAL; return -1; } curr_netio = proxy_netio_unset(nstrm->strm_type, "netio_postpopen"); res = pr_netio_postopen(nstrm); xerrno = errno; proxy_netio_set(nstrm->strm_type, curr_netio); errno = xerrno; return res; }
int pr_data_open(char *filename, char *reason, int direction, off_t size) { int res = 0; /* Make sure that any abort flags have been cleared. */ session.sf_flags &= ~SF_ABORT; if (session.xfer.p == NULL) { data_new_xfer(filename, direction); } else { session.xfer.direction = direction; } if (!reason) reason = filename; /* Passive data transfers... */ if (session.sf_flags & SF_PASSIVE || session.sf_flags & SF_EPSV_ALL) { if (session.d == NULL) { pr_log_pri(PR_LOG_ERR, "Internal error: PASV mode set, but no data " "connection listening"); pr_session_disconnect(NULL, PR_SESS_DISCONNECT_BY_APPLICATION, NULL); } res = data_pasv_open(reason, size); /* Active data transfers... */ } else { if (session.d != NULL) { pr_log_pri(PR_LOG_ERR, "Internal error: non-PASV mode, yet data " "connection already exists?!?"); pr_session_disconnect(NULL, PR_SESS_DISCONNECT_BY_APPLICATION, NULL); } res = data_active_open(reason, size); } if (res >= 0) { struct sigaction act; if (pr_netio_postopen(session.d->instrm) < 0) { pr_response_add_err(R_425, _("Unable to build data connection: %s"), strerror(session.d->xerrno)); destroy_pool(session.d->pool); session.d = NULL; return -1; } if (pr_netio_postopen(session.d->outstrm) < 0) { pr_response_add_err(R_425, _("Unable to build data connection: %s"), strerror(session.d->xerrno)); destroy_pool(session.d->pool); session.d = NULL; return -1; } memset(&session.xfer.start_time, '\0', sizeof(session.xfer.start_time)); gettimeofday(&session.xfer.start_time, NULL); if (session.xfer.direction == PR_NETIO_IO_RD) nstrm = session.d->instrm; else nstrm = session.d->outstrm; session.sf_flags |= SF_XFER; if (timeout_noxfer) pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE); /* Allow aborts -- set the current NetIO stream to allow interrupted * syscalls, so our SIGURG handler can interrupt it */ pr_netio_set_poll_interval(nstrm, 1); /* PORTABILITY: sigaction is used here to allow us to indicate * (w/ POSIX at least) that we want SIGURG to interrupt syscalls. Put * in whatever is necessary for your arch here; probably not necessary * as the only _important_ interrupted syscall is select(), which on * any sensible system is interrupted. */ act.sa_handler = data_urgent; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif if (sigaction(SIGURG, &act, NULL) < 0) pr_log_pri(PR_LOG_WARNING, "warning: unable to set SIGURG signal handler: %s", strerror(errno)); #ifdef HAVE_SIGINTERRUPT /* This is the BSD way of ensuring interruption. * Linux uses it too (??) */ if (siginterrupt(SIGURG, 1) < 0) pr_log_pri(PR_LOG_WARNING, "warning: unable to make SIGURG interrupt system calls: %s", strerror(errno)); #endif } return res; }