在C中,当从符号链接调用时,如何使用getcwd获取可执行路径
假设我在Linux中有一个程序,在C中,当从符号链接调用时,如何使用getcwd获取可执行路径,c,linux,file-io,symlink,C,Linux,File Io,Symlink,假设我在Linux中有一个程序,abc,它有一个方法: char *currentPath(){ char *path=NULL; path = getcwd(path, MAXPATHLEN); return path; } 直接调用abc时,此路径返回abc所在的路径 如果我创建一个指向abc的符号链接并调用该符号链接,currentPath()将返回符号链接的路径 有没有办法让这个方法返回abc的路径?我对访问与abc位置相关的文件感兴趣。
abc
,它有一个方法:
char *currentPath(){
char *path=NULL;
path = getcwd(path, MAXPATHLEN);
return path;
}
直接调用abc
时,此路径返回abc
所在的路径
如果我创建一个指向abc的符号链接并调用该符号链接,currentPath()
将返回符号链接的路径
有没有办法让这个方法返回abc的路径?我对访问与abc
位置相关的文件感兴趣。您不能使用getcwd()
来帮助获取可执行文件名;查找可执行文件的路径名是不明智的
在Linux上,有一个符号链接/proc/self/exe
,如果您使用系统调用读取可执行文件,它将为您提供可执行文件的名称。请注意,readlink()
系统调用不会以null终止它返回的值(我也不知道为什么不为空;在我的书中,这是一种奇怪的行为,对于粗心的人来说,这是导致bug的即时原因)
你的计划有很多问题
/bin/ls
,而不必位于/bin
目录中argv[0]
的值受启动目标程序的程序控制。外壳表现良好;其他程序可能更恶意:
#include <unistd.h>
int main(void)
{
char *argv[] = { "/opt/you/bin/bogus", "300", 0 };
execvp("sleep", argv);
return(-1);
}
#包括
内部主(空)
{
char*argv[]={/opt/you/bin/bogus,“300”,0};
execvp(“睡眠”,argv);
返回(-1);
}
这会将程序名传递为/opt/you/bin/bogus
,即使它调用程序sleep
argv[0]
是一条可行之路;事实并非如此。其他平台有其他获取可执行文件名的技术。使用/proc/self/exe
是不可移植的;其他技术也一样。您不能使用getcwd()
来帮助获取可执行文件名;查找可执行文件的路径名是不明智的
在Linux上,有一个符号链接/proc/self/exe
,如果您使用系统调用读取可执行文件,它将为您提供可执行文件的名称。请注意,readlink()
系统调用不会以null终止它返回的值(我也不知道为什么不为空;在我的书中,这是一种奇怪的行为,对于粗心的人来说,这是导致bug的即时原因)
你的计划有很多问题
/bin/ls
,而不必位于/bin
目录中argv[0]
的值受启动目标程序的程序控制。外壳表现良好;其他程序可能更恶意:
#include <unistd.h>
int main(void)
{
char *argv[] = { "/opt/you/bin/bogus", "300", 0 };
execvp("sleep", argv);
return(-1);
}
#包括
内部主(空)
{
char*argv[]={/opt/you/bin/bogus,“300”,0};
execvp(“睡眠”,argv);
返回(-1);
}
这会将程序名传递为/opt/you/bin/bogus
,即使它调用程序sleep
argv[0]
是一条可行之路;事实并非如此。其他平台有其他获取可执行文件名的技术。使用/proc/self/exe
是不可移植的;其他技术也不适用。使用
realpath()展开所有符号链接,并解析对/、/../和的引用
以路径命名的以空结尾的字符串中的额外“/”字符,用于生成
规范化的绝对路径名
就你而言:
char *currentPath() {
char *path, *canon_path;
path = getcwd(NULL, MAXPATHLEN);
canon_path = realpath(path, NULL);
free(path);
return canon_path;
}
请注意,这不会获取可执行程序的路径(不清楚您正在尝试执行什么)。要做到这一点,便携是比较棘手的。您需要使用argv[0]
的值来获取它:
char *bindir(char *argv0) {
char *canon_path = realpath(argv0, NULL);
char *canon_dir = strdup(dirname(canon_path));
free(canon_path);
return canon_dir;
}
strdup
调用是必需的,因为dirname
可以修改其参数并将指针返回到该参数中,或返回指向静态分配的缓冲区的指针。使用
realpath()展开所有符号链接,并解析对/、/../和的引用
以路径命名的以空结尾的字符串中的额外“/”字符,用于生成
规范化的绝对路径名
就你而言:
char *currentPath() {
char *path, *canon_path;
path = getcwd(NULL, MAXPATHLEN);
canon_path = realpath(path, NULL);
free(path);
return canon_path;
}
请注意,这不会获取可执行程序的路径(不清楚您正在尝试执行什么)。要做到这一点,便携是比较棘手的。您需要使用argv[0]
的值来获取它:
char *bindir(char *argv0) {
char *canon_path = realpath(argv0, NULL);
char *canon_dir = strdup(dirname(canon_path));
free(canon_path);
return canon_dir;
}
strdup
调用是必需的,因为dirname
可能会修改其参数并将指针返回到该参数中,或返回指向静态分配的缓冲区的指针。请尝试此代码(修改它以满足您的需要):
#包括
#包括
#包括
#包括
#定义MAXPATHLEN 256
字符缓冲区[1024];
char*currentPath(char*bin\u路径){
char*path=NULL;
西泽特伦;
结构统计文件_stat;
if(lstat(bin\u路径和文件统计)!=0)
{
/*处理错误*/
fprintf(stderr,“ERROR\n”);
}
如果(!S_ISREG(文件统计模式))
{
/*文件是一个符号链接*/
fprintf(stdout,“是一个符号链接\n”);
if((len=readlink(bin_路径,缓冲区,sizeof(缓冲区)-1))!=-1)
缓冲区[len]='\0';
/*在本例中,我们返回链接的名称*/
返回缓冲区;
}
其他的
{
fprintf(stdout,“是一个常规文件\n”)