📄 sysdeputil.c
字号:
{ /* Grr - why is off_t signed? */ if (*p_offset < 0 || num_send < 0) { die("invalid offset or send count in vsf_sysutil_sendfile"); } if (max_chunk == 0) { max_chunk = INT_MAX; } while (num_send > 0) { int retval; unsigned int send_this_time; if (num_send > max_chunk) { send_this_time = max_chunk; } else { send_this_time = (unsigned int) num_send; } /* Keep input file position in line with sendfile() calls */ vsf_sysutil_lseek_to(in_fd, *p_offset); retval = do_sendfile(out_fd, in_fd, send_this_time, *p_offset); if (vsf_sysutil_retval_is_error(retval) || retval == 0) { return retval; } num_send -= retval; *p_offset += retval; } return 0;}static int do_sendfile(const int out_fd, const int in_fd, unsigned int num_send, filesize_t start_pos){ /* Probably should one day be shared with instance in ftpdataio.c */ static char* p_recvbuf; unsigned int total_written = 0; int retval; enum EVSFSysUtilError error; (void) start_pos; (void) error;#if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \ defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || \ defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || \ defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) || \ defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE) if (tunable_use_sendfile) { static int s_sendfile_checked; static int s_runtime_sendfile_works; if (!s_sendfile_checked || s_runtime_sendfile_works) { do { #ifdef VSF_SYSDEP_HAVE_LINUX_SENDFILE retval = sendfile(out_fd, in_fd, NULL, num_send); #elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) { /* XXX - start_pos will truncate on 32-bit machines - can we * say "start from current pos"? */ off_t written = 0; retval = sendfile(in_fd, out_fd, start_pos, num_send, NULL, &written, 0); /* Translate to Linux-like retval */ if (written > 0) { retval = (int) written; } } #elif defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE) { size_t written = 0; struct sendfilevec the_vec; vsf_sysutil_memclr(&the_vec, sizeof(the_vec)); the_vec.sfv_fd = in_fd; the_vec.sfv_off = start_pos; the_vec.sfv_len = num_send; retval = sendfilev(out_fd, &the_vec, 1, &written); /* Translate to Linux-like retval */ if (written > 0) { retval = (int) written; } } #elif defined(VSF_SYSDEP_HAVE_AIX_SENDFILE) { struct sf_parms sf_iobuf; vsf_sysutil_memclr(&sf_iobuf, sizeof(sf_iobuf)); sf_iobuf.header_data = NULL; sf_iobuf.header_length = 0; sf_iobuf.trailer_data = NULL; sf_iobuf.trailer_length = 0; sf_iobuf.file_descriptor = in_fd; sf_iobuf.file_offset = start_pos; sf_iobuf.file_bytes = num_send; retval = send_file((int*)&out_fd, &sf_iobuf, 0); if (retval >= 0) { retval = sf_iobuf.bytes_sent; } } #else /* must be VSF_SYSDEP_HAVE_HPUX_SENDFILE */ { retval = sendfile(out_fd, in_fd, start_pos, num_send, NULL, 0); } #endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */ error = vsf_sysutil_get_error(); vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, out_fd); } while (vsf_sysutil_retval_is_error(retval) && error == kVSFSysUtilErrINTR); if (!s_sendfile_checked) { s_sendfile_checked = 1; if (!vsf_sysutil_retval_is_error(retval) || error != kVSFSysUtilErrNOSYS) { s_runtime_sendfile_works = 1; } } if (!vsf_sysutil_retval_is_error(retval)) { return retval; } if (s_runtime_sendfile_works && error != kVSFSysUtilErrINVAL && error != kVSFSysUtilErrOPNOTSUPP) { return retval; } /* Fall thru to normal implementation. We won't check again. NOTE - * also falls through if sendfile() is OK but it returns EINVAL. For * Linux this means the file was not page cache backed. Original * complaint was trying to serve files from an NTFS filesystem! */ } }#endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE || VSF_SYSDEP_HAVE_FREEBSD_SENDFILE */ if (p_recvbuf == 0) { vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE); } while (1) { unsigned int num_read; unsigned int num_written; unsigned int num_read_this_time = VSFTP_DATA_BUFSIZE; if (num_read_this_time > num_send) { num_read_this_time = num_send; } retval = vsf_sysutil_read(in_fd, p_recvbuf, num_read_this_time); if (retval < 0) { return retval; } else if (retval == 0) { return -1; } num_read = (unsigned int) retval; retval = vsf_sysutil_write_loop(out_fd, p_recvbuf, num_read); if (retval < 0) { return retval; } num_written = (unsigned int) retval; total_written += num_written; if (num_written != num_read) { return num_written; } if (num_written > num_send) { bug("num_written bigger than num_send in do_sendfile"); } num_send -= num_written; if (num_send == 0) { /* Bingo! */ return total_written; } }}voidvsf_sysutil_set_proctitle_prefix(const struct mystr* p_str){ str_copy(&s_proctitle_prefix_str, p_str);}/* This delegation is common to all setproctitle() implementations */voidvsf_sysutil_setproctitle_str(const struct mystr* p_str){ vsf_sysutil_setproctitle(str_getbuf(p_str));}voidvsf_sysutil_setproctitle(const char* p_text){ struct mystr proctitle_str = INIT_MYSTR; str_copy(&proctitle_str, &s_proctitle_prefix_str); if (!str_isempty(&proctitle_str)) { str_append_text(&proctitle_str, ": "); } str_append_text(&proctitle_str, p_text); vsf_sysutil_setproctitle_internal(str_getbuf(&proctitle_str)); str_free(&proctitle_str);}#ifdef VSF_SYSDEP_HAVE_SETPROCTITLEvoidvsf_sysutil_setproctitle_init(int argc, const char* argv[]){ (void) argc; (void) argv;}voidvsf_sysutil_setproctitle_internal(const char* p_buf){ setproctitle("%s", p_buf);}#elif defined(VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE)voidvsf_sysutil_setproctitle_init(int argc, const char* argv[]){ (void) argc; (void) argv;}voidvsf_sysutil_setproctitle_internal(const char* p_buf){ struct mystr proctitle_str = INIT_MYSTR; union pstun p; str_alloc_text(&proctitle_str, "vsftpd: "); str_append_text(&proctitle_str, p_buf); p.pst_command = str_getbuf(&proctitle_str); pstat(PSTAT_SETCMD, p, 0, 0, 0); str_free(&proctitle_str);}#elif defined(VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK)voidvsf_sysutil_setproctitle_init(int argc, const char* argv[]){ int i; char** p_env = environ; if (s_proctitle_inited) { bug("vsf_sysutil_setproctitle_init called twice"); } s_proctitle_inited = 1; if (argv[0] == 0) { die("no argv[0] in vsf_sysutil_setproctitle_init"); } for (i=0; i<argc; i++) { s_proctitle_space += vsf_sysutil_strlen(argv[i]) + 1; if (i > 0) { argv[i] = 0; } } while (*p_env != 0) { s_proctitle_space += vsf_sysutil_strlen(*p_env) + 1; p_env++; } /* Oops :-) */ environ = 0; s_p_proctitle = (char*) argv[0]; vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space);}voidvsf_sysutil_setproctitle_internal(const char* p_buf){ struct mystr proctitle_str = INIT_MYSTR; unsigned int to_copy; if (!s_proctitle_inited) { bug("vsf_sysutil_setproctitle: not initialized"); } vsf_sysutil_memclr(s_p_proctitle, s_proctitle_space); if (s_proctitle_space < 32) { return; } str_alloc_text(&proctitle_str, "vsftpd: "); str_append_text(&proctitle_str, p_buf); to_copy = str_getlen(&proctitle_str); if (to_copy > s_proctitle_space - 1) { to_copy = s_proctitle_space - 1; } vsf_sysutil_memcpy(s_p_proctitle, str_getbuf(&proctitle_str), to_copy); str_free(&proctitle_str); s_p_proctitle[to_copy] = '\0';}#else /* VSF_SYSDEP_HAVE_SETPROCTITLE */voidvsf_sysutil_setproctitle_init(int argc, const char* argv[]){ (void) argc; (void) argv;}voidvsf_sysutil_setproctitle_internal(const char* p_buf){ (void) p_buf;}#endif /* VSF_SYSDEP_HAVE_SETPROCTITLE */#ifdef VSF_SYSDEP_HAVE_MAP_ANONvoidvsf_sysutil_map_anon_pages_init(void){}void*vsf_sysutil_map_anon_pages(unsigned int length){ char* retval = mmap(0, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (retval == MAP_FAILED) { die("mmap"); } return retval;}#else /* VSF_SYSDEP_HAVE_MAP_ANON */voidvsf_sysutil_map_anon_pages_init(void){ if (s_zero_fd != -1) { bug("vsf_sysutil_map_anon_pages_init called twice"); } s_zero_fd = open("/dev/zero", O_RDWR); if (s_zero_fd < 0) { die("could not open /dev/zero"); }}void*vsf_sysutil_map_anon_pages(unsigned int length){ char* retval = mmap(0, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, s_zero_fd, 0); if (retval == MAP_FAILED) { die("mmap"); } return retval;}#endif /* VSF_SYSDEP_HAVE_MAP_ANON */#ifndef VSF_SYSDEP_NEED_OLD_FD_PASSINGvoidvsf_sysutil_send_fd(int sock_fd, int send_fd){ int retval; struct msghdr msg; struct cmsghdr* p_cmsg; struct iovec vec; char cmsgbuf[CMSG_SPACE(sizeof(send_fd))]; int* p_fds; char sendchar = 0; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); p_cmsg = CMSG_FIRSTHDR(&msg); p_cmsg->cmsg_level = SOL_SOCKET; p_cmsg->cmsg_type = SCM_RIGHTS; p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd)); p_fds = (int*)CMSG_DATA(p_cmsg); *p_fds = send_fd; msg.msg_controllen = p_cmsg->cmsg_len; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_flags = 0; /* "To pass file descriptors or credentials you need to send/read at * least on byte" (man 7 unix) */ vec.iov_base = &sendchar; vec.iov_len = sizeof(sendchar); retval = sendmsg(sock_fd, &msg, 0); if (retval != 1) { die("sendmsg"); }}intvsf_sysutil_recv_fd(const int sock_fd){ int retval; struct msghdr msg; char recvchar; struct iovec vec; int recv_fd; char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))]; struct cmsghdr* p_cmsg; int* p_fd; vec.iov_base = &recvchar; vec.iov_len = sizeof(recvchar); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); msg.msg_flags = 0; /* In case something goes wrong, set the fd to -1 before the syscall */ p_fd = (int*)CMSG_DATA(CMSG_FIRSTHDR(&msg)); *p_fd = -1; retval = recvmsg(sock_fd, &msg, 0); if (retval != 1) { die("recvmsg"); } p_cmsg = CMSG_FIRSTHDR(&msg); if (p_cmsg == NULL) { die("no passed fd"); } /* We used to verify the returned cmsg_level, cmsg_type and cmsg_len here, * but Linux 2.0 totally uselessly fails to fill these in. */ p_fd = (int*)CMSG_DATA(p_cmsg); recv_fd = *p_fd; if (recv_fd == -1) { die("no passed fd"); } return recv_fd;}#else /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */voidvsf_sysutil_send_fd(int sock_fd, int send_fd){ int retval; char send_char = 0; struct msghdr msg; struct iovec vec; vec.iov_base = &send_char; vec.iov_len = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_accrights = (caddr_t) &send_fd; msg.msg_accrightslen = sizeof(send_fd); retval = sendmsg(sock_fd, &msg, 0); if (retval != 1) { die("sendmsg"); }}intvsf_sysutil_recv_fd(int sock_fd){ int retval; struct msghdr msg; struct iovec vec; char recv_char; int recv_fd = -1; vec.iov_base = &recv_char; vec.iov_len = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_accrights = (caddr_t) &recv_fd; msg.msg_accrightslen = sizeof(recv_fd); retval = recvmsg(sock_fd, &msg, 0); if (retval != 1) { die("recvmsg"); } if (recv_fd == -1) { die("no passed fd"); } return recv_fd;}#endif /* !VSF_SYSDEP_NEED_OLD_FD_PASSING */#ifndef VSF_SYSDEP_HAVE_UTMPXvoidvsf_insert_uwtmp(const struct mystr* p_user_str, const struct mystr* p_host_str){ (void) p_user_str; (void) p_host_str;}voidvsf_remove_uwtmp(void){}#else /* !VSF_SYSDEP_HAVE_UTMPX *//* IMHO, the pam_unix module REALLY should be doing this in its SM component *//* Statics */static int s_uwtmp_inserted;static struct utmpx s_utent;voidvsf_insert_uwtmp(const struct mystr* p_user_str, const struct mystr* p_host_str){ if (sizeof(s_utent.ut_line) < 16) { return; } if (s_uwtmp_inserted) { bug("vsf_insert_uwtmp"); } { struct mystr line_str = INIT_MYSTR; str_alloc_text(&line_str, "vsftpd:"); str_append_ulong(&line_str, vsf_sysutil_getpid()); if (str_getlen(&line_str) >= sizeof(s_utent.ut_line)) { str_free(&line_str); return; } vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str), sizeof(s_utent.ut_line)); str_free(&line_str); } s_uwtmp_inserted = 1; s_utent.ut_type = USER_PROCESS; s_utent.ut_pid = vsf_sysutil_getpid(); vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str), sizeof(s_utent.ut_user)); vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str), sizeof(s_utent.ut_host)); vsf_sysutil_update_cached_time(); s_utent.ut_tv.tv_sec = vsf_sysutil_get_cached_time_sec(); setutxent(); (void) pututxline(&s_utent); endutxent(); updwtmpx(WTMPX_FILE, &s_utent);}voidvsf_remove_uwtmp(void){ if (!s_uwtmp_inserted) { return; } s_uwtmp_inserted = 0; s_utent.ut_type = DEAD_PROCESS; vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user)); vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host)); s_utent.ut_tv.tv_sec = 0; setutxent(); (void) pututxline(&s_utent); endutxent(); vsf_sysutil_update_cached_time(); s_utent.ut_tv.tv_sec = vsf_sysutil_get_cached_time_sec(); updwtmpx(WTMPX_FILE, &s_utent);}#endif /* !VSF_SYSDEP_HAVE_UTMPX */voidvsf_set_die_if_parent_dies(){#ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) != 0) { die("prctl"); }#endif}voidvsf_set_term_if_parent_dies(){#ifdef VSF_SYSDEP_HAVE_SETPDEATHSIG if (prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) != 0) { die("prctl"); }#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -