编辑:我重写了这个问题,因为我没有得到答案,而我正在努力缩小这个问题。
我正在尝试创建mysql UDF function检查服务器端是否存在文件。该函数称为“打开/关闭”。即使文件是可重新编辑的,它也不起作用。
我把这个函数的代码放在下面:
#include <mysql.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
/* The initialization function */
my_bool fileExists_init(
UDF_INIT *initid,
UDF_ARGS *args,
char *message
)
{
/* check the args */
if (!(args->arg_count == 1 &&
args->arg_type[0] == STRING_RESULT
))
{
strncpy(message,"Bad parameter expected a string",MYSQL_ERRMSG_SIZE);
return 1;
}
initid->maybe_null=1;
initid->ptr= NULL;
return 0;
}
/* The deinitialization function */
void fileExists_deinit(UDF_INIT *initid)
{
}
#define MAX_RESULT_LENGTH 250
char *fileExists(
UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *is_null, char *error)
{
//bad filename
if(args->args[0]==NULL || args->lengths[0]==0 || args->lengths[0] >= FILENAME_MAX )
{
strncpy(result,"#BAD_INPUT",MAX_RESULT_LENGTH);
}
else
{
char filename[FILENAME_MAX+1];
int err;
int in;
//create a NULL terminated string
memcpy(filename,args->args[0],args->lengths[0]);
filename[args->lengths[0]]=0;
errno=0;
in=open(filename,O_RDONLY|O_NDELAY);
err=errno;
if(in<0)
{
snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename);
}
else
{
close(in);
snprintf(result,MAX_RESULT_LENGTH,"OK:\"%s\".",filename);
}
}
*length=strlen(result);
return result;
}
请:
gcc -Wall -DMYSQL_VERSION -fPIC -shared `mysql_config --cflags` -o `mysql_config --plugindir`/libfileexists.so udffileexists.c `mysql_config --libs `
测试:
好吧,mysql可以打开一些文件:mysql> create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/etc/mysql/my.cnf"); drop function fileExists;
Query OK, 0 rows affected (0.00 sec)
+---------------------------------+
| fileExists("/etc/mysql/my.cnf") |
+---------------------------------+
| OK:"/etc/mysql/my.cnf". |
+---------------------------------+
1 row in set (0.00 sec)
mysql> create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/tmp/file.txt"); drop function fileExists;
Query OK, 0 rows affected (0.00 sec)
+-------------------------------+
| fileExists("/tmp/file.txt") |
+-------------------------------+
| OK:"/tmp/file.txt". |
+-------------------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
好的,没问题,有效,我可以在 / tmp /
中打开()file.txtls -la /tmp
drwxrwxrwt 16 root root 4096 2010-05-28 15:45 .
-rw-r--r-- 1 lindenb lindenb 0 2010-05-28 15:25 file.txt
但是当我想在 / data 中测试文件时:
ls -la /data
drwxrwxrwx 4 root root 4096 2010-05-28 16:11 .
-rw-r--r-- 1 lindenb lindenb 0 2010-05-28 15:25 file.txt
我得到了:
mysql> create function fileExists RETURNS STRING SONAME 'libfileexists.so'; select fileExists("/data/file.txt"); drop function fileExists;
Query OK, 0 rows affected (0.00 sec)
+--------------------------------------------+
| fileExists("/data/file.txt") |
+--------------------------------------------+
| #ERR:"Permission denied":"/data/file.txt". |
+--------------------------------------------+
1 row in set (0.00 sec)
有什么想法吗?
谢谢!
答案 0 :(得分:3)
mysqld受apparmor保护。
AppArmor代表其中之一 可能解决问题的方法 限制安装的操作 软件可以采取。
我添加了
/data/** r,
结束时的
/etc/apparmor.d/usr.sbin.mysqld
apparmor重新启动:
/etc/init.d/apparmor restart
现在我的UDF工作正常! : - )
答案 1 :(得分:0)
为什么要在其上打开文件?也许以这种方式做得更好:
char *fileExists( UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error) { //bad filename if(args->args[0]==NULL || args->lengths[0]==0 || args->lengths[0] >= FILENAME_MAX ) { strncpy(result,"#BAD_INPUT",MAX_RESULT_LENGTH); } else { char filename[FILENAME_MAX+1]; int err; int in; struct stat statbuffer; //create a NULL terminated string memcpy(filename,args->args[0],args->lengths[0]); filename[args->lengths[0]]=0; errno=0; if (!stat(filename, &statbuffer)){ if (S_ISREG(statbuffer.st_mode)){ snprintf(result,MAX_RESULT_LENGTH,"OK:\"%s\".",filename); }else{ snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename); } }else{ snprintf(result,MAX_RESULT_LENGTH,"#ERR:\"%s\":\"%s\".",strerror(err),filename); } } *length=strlen(result); return result; }
而不是打开文件,使用stat,这似乎是检查文件是否存在的可靠方式,而且,它将更容易归结为什么 stat 功能失败。