Pages

Friday, December 25, 2009

vsftpd 日誌(log)不支援中文檔名的解決方式

vsftpd (2.0.4-1.2) 的日誌(vsftpd.log)不支援中文日文等字元(如檔名),會顯示為一串的問號。

網路上找了一下,解決的方式有二:
方法一. 將 log 寫入系統 log
方法二.修改原始碼


方法一比較好處理,缺點是會寫入 message 裡,跟其他 log 混在一起,只要在 vsftpd.conf 裡加入
syslog_enable=YES 即可


方法二要先看一下原始檔,以下節錄網路資料:

日誌記錄檔, file logging.c, line 152 - 171:
static void
vsf_log_do_log_to_file(int fd, struct mystr* p_str)
{
if (!tunable_no_log_lock)
{
int retval = vsf_sysutil_lock_file_write(fd);
if (vsf_sysutil_retval_is_error(retval))
{
return;
}
}
str_replace_unprintable(p_str, '?');
str_append_char(p_str, '\n');
/* Ignore write failure; maybe the disk filled etc. */
(void) str_write_loop(p_str, fd);
if (!tunable_no_log_lock)
{
vsf_sysutil_unlock_file(fd);
}
}



函數用 str_replace_unprintable(p_str, '?') 把所有「無法輸出的字元」替換為問號.

str_replace_unprintable 函數, file str.c, line 656 - 668:
void
str_replace_unprintable(struct mystr* p_str, char new_char)
{
unsigned int i;
for (i=0; i <>len; i++)
{
if (!vsf_sysutil_isprint(p_str->p_buf[i]))
{
p_str->p_buf[i] = new_char;
}
}
}



函數 vsf_sysutil_isprint, file sysutil.c, line 883 - 903:
int
vsf_sysutil_isprint(int the_char)
{
/* From Solar - we know better than some libc's! Don't let any potential
* control chars through
*/
unsigned char uc = (unsigned char) the_char;
if (uc <= 31)
{
return 0;
}
if (uc == 177)
{
return 0;
}
if (uc >= 128 && uc <= 159)
{
return 0;
}
return isprint(the_char);
}



作者注釋 "Don't let any potential control chars through" 表明對「無法輸出的字元」所做的定義

解決的方法就是注釋掉 logging.c 檔中的 static void vsf_log_do_log_to_file(int fd, struct mystr* p_str) 函數中的 str_replace_unprintable(p_str, '?');這一行
個人覺得比較麻煩,且有降低系統的安全的可能性(potential),所以我選「方法一」~