如何使用 ANSI C 检查文件是不是可执行?
Posted
技术标签:
【中文标题】如何使用 ANSI C 检查文件是不是可执行?【英文标题】:How do I check if a file is executable using ANSI C?如何使用 ANSI C 检查文件是否可执行? 【发布时间】:2013-04-08 22:38:06 【问题描述】:我正在尝试编写一个程序来检查目录中的文件。创建新文件时,我必须检查它是否可执行,如果是,我必须执行它。
我正在使用 inotify 接口,它运行良好,但是当我尝试使用 stat(2) 检查文件是否可执行时遇到了一些问题。我发现我没有执行它的权限。
是否将我要检查的目录的绝对路径传递给程序会造成权限问题?
int main(int argc,char * argv [])
int fd,wd,len,i=0;
char buffer [EVENT_SIZE_BUF];
if(argc != 2)
usage();
if((fd = inotify_init()) == -1)
perror("inotify_init()");
if((wd = inotify_add_watch(fd,argv[1],IN_CREATE) -1))
perror("inotify_add_watch()");
while(1)
if((len = read(fd,buffer,EVENT_SIZE_BUF)) < 0)
perror("read()");
struct inotify_event * ev = (struct inotify_event *)&buffer;
if(ev->len > 0)
if(ev->mask & IN_CREATE && ((ev-> mask & IN_ISDIR) == 0x00))
printf("SPY; new file is created %s\n",ev->name);
char * path = strcat(argv[1],ev->name);
printf("%s\n",path);
struct stat sb;
if(!stat(path,&sb))
printf( (S_ISDIR(sb.st_mode)) ? "d" : "-");
printf( (sb.st_mode & S_IRUSR) ? "r" : "-");
printf( (sb.st_mode & S_IWUSR) ? "w" : "-");
printf( (sb.st_mode & S_IXUSR) ? "x" : "-");
printf( (sb.st_mode & S_IRGRP) ? "r" : "-");
printf( (sb.st_mode & S_IWGRP) ? "w" : "-");
printf( (sb.st_mode & S_IXGRP) ? "x" : "-");
printf( (sb.st_mode & S_IROTH) ? "r" : "-");
printf( (sb.st_mode & S_IWOTH) ? "w" : "-");
printf( (sb.st_mode & S_IXOTH) ? "x" : "-");
fflush(stdout);
printf("\n");
else printf("dir\n");
inotify_rm_watch(fd,wd);
close(fd);
return 0;
【问题讨论】:
我已经编辑了这个问题,试图让它更清楚一点。如果我进行了不正确的更改/忘记了某些内容,请随时回滚/编辑它。 【参考方案1】:你使用的是linux,所以你可以使用access()函数
if (access("/my/file", X_OK) != -1)
printf("execution permission enabled\n");
else
printf("execution permission disabled\n");
【讨论】:
感谢您的回答。我也尝试过访问,但你确定如果它返回 -1 意味着该文件不可执行?因为 linux 手册页告诉它在出错的情况下返回 -1 嗯,是的,但它总是告诉我没有权限。但我对这两个文件都有执行权限 检查你的文件应该没有执行权限 完成。我对使用 shell 中的 stat 检查的两个文件都有权限 请注意,在普通(不是 setuid,不是 setgid)程序的情况下,access()
提供了您想要的答案,但它执行的检查是真实的 UID 还是真实的 GID(或补充组 ID 之一)具有相关访问权限,而不是有效 UID 或有效 GID,但实际控制访问的是有效 UID 和有效 GID(加上补充组 ID)。因此,如果程序运行 SUID 或 SGID,您最终可能会得到错误的答案。诚然,这是对细节的吹毛求疵,但它们确实很重要……有时。【参考方案2】:
你在解决 Renzo Davoli 的练习吗? :)
但是,我和你一样被卡住了,我发现用 Nautilus 复制可执行文件会创建一个“可执行文件(复制)”,返回 X-Permission 错误,stat()
或 access()
。
用 cp cp exe1 exe2
复制就可以了!!
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#define _GNU_SOURCE
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
void main(int argc, char **argv)
int fd, wd, length, i=0;
char buffer[EVENT_BUF_LEN];
char* dir = argv[1];
/*creating the INOTIFY instance*/
if((fd = inotify_init()) < 0)
perror( "inotify_init" );
/*adding the directory into watch list.
Here, the suggestion is to validate the existence of the directory before adding into monitoring list.*/
wd = inotify_add_watch( fd, dir, IN_CREATE | IN_DELETE );
while(1)
i=0;
pid_t p;
struct stat st;
/*read to determine the event change happens on “/tmp” directory. Actually this read blocks until the change event occurs*/
if((length = read(fd, buffer, EVENT_BUF_LEN )) < 0)
perror( "read" );
/*actually read return the list of change events happens. Here, read the change event one by one and process it accordingly.*/
while ( i < length )
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len )
if ( event->mask & IN_CREATE )
if ( event->mask & IN_ISDIR )
printf("New directory %s created.\n", event->name );
else
printf("New file %s created.\n", event->name );
char* file_name;
asprintf(&file_name, "%s/%s", dir, event->name);
printf("Check if %s is executable\n", file_name);
if (access(file_name, X_OK) == 0) //If file is executable
printf("Executable file! Call fork()\n");
if ((p = fork()) == 0) // Child process: do your work here
if (execlp(file_name, file_name, (char*) 0)<0)
fprintf(stderr, "execlp error\n");
exit(0);
else
while(waitpid(p, NULL, WNOHANG) != p);
remove (event->name);
printf("%s done & gone\n", event->name);
else
fprintf(stderr, "Not executable file\n");
else if ( event->mask & IN_DELETE )
if ( event->mask & IN_ISDIR )
printf( "Directory %s deleted.\n", event->name );
else
printf( "File %s deleted.\n", event->name );
i += EVENT_SIZE + event->len;
/*removing the “/tmp” directory from the watch list.*/
inotify_rm_watch( fd, wd );
/*closing the INOTIFY instance*/
close( fd );
【讨论】:
【参考方案3】:这在 ANSI C 中是不可能的,你需要 POSIX。
【讨论】:
以上是关于如何使用 ANSI C 检查文件是不是可执行?的主要内容,如果未能解决你的问题,请参考以下文章