C 不解析符号链接的realpath()?

C 不解析符号链接的realpath()?,c,normalization,symlink,realpath,C,Normalization,Symlink,Realpath,我已经读过关于realpath(),但是有没有一个函数可以让我传递一个基本目录和一个文件名,从而在不解析符号链接或不检查文件是否实际存在的情况下得到以下结果?或者我必须使用修改过的realpath() function normalize_path($path,$pwd='/')){ 如果(!isset($path[0])| |$path[0]!=='/')){ $result=explode('/',getcwd()); }否则{ $result=数组(“”); } $parts=分解(“/”

我已经读过关于
realpath()
,但是有没有一个函数可以让我传递一个基本目录和一个文件名,从而在不解析符号链接或不检查文件是否实际存在的情况下得到以下结果?或者我必须使用修改过的
realpath()

function normalize_path($path,$pwd='/')){
如果(!isset($path[0])| |$path[0]!=='/')){
$result=explode('/',getcwd());
}否则{
$result=数组(“”);
}
$parts=分解(“/”,$path);
foreach($parts作为$part){
如果($part==''| |$part=''。){
继续;
}如果($part==“…”){
数组_pop($result);
}否则{
$result[]=$part;
}
}
返回内爆('/',$result);
}
(在我写这篇文章时,这个问题被标记为PHP。)

无论如何,这里有一个正则表达式版本:

function normalize_path($path,$pwd='/')){
如果(!isset($path[0])| |$path[0]!=='/')){
$path=“$pwd/$path”;
}
返回预更换('~
^(?P>sdot)?(?:(?P>sdot)*/\.\)*
|(?(?:(?P>sdot)*/(?!\.\)(?:[^/])+(?P>sdotdot)?(?P>sdot)*/\.\)+)
|(?/\.?(?=/|$))+
~sx','',$path);
}
下面是一个normalize_path()函数:

如果给定的路径是相对的,则函数首先将当前工作目录添加到该路径

然后处理特殊路径组件,如
或空组件,并返回结果

对于
,如果存在一个组件,则最后一个组件将被删除(
/..
将返回
/
)。
对于
或空组件(双
/
),这只是跳过

该函数确保不会返回空路径(而是返回
/

#定义_GNU_SOURCE/*memrchr()*/
#包括
#包括
#包括
#包括
字符*规格化路径(常量字符*src,大小\u t src\u len){
字符*res;
尺寸大小;
常量字符*ptr=src;
const char*end=&src[src_len];
常量字符*下一个;
如果(src_len==0 | | src[0]!='/')){
//相对路径
字符pwd[PATH_MAX];
尺寸尺寸;
if(getcwd(pwd,sizeof(pwd))==NULL){
返回NULL;
}
pwd_len=strlen(pwd);
res=malloc(pwd_len+1+src_len+1);
memcpy(res、pwd、pwd_len);
res_len=pwd_len;
}否则{
res=malloc((src_len>0?src_len:1)+1);
res_len=0;
}
对于(ptr=src;ptr
我使用的是:


注意:

  • 第一个参数是目录路径(绝对路径),其他路径将被规范化。它通常是当前目录的绝对路径
  • 第二个参数是要在不解析符号链接的情况下进行规范化的字符串
  • 第三个参数是
    char*
    ,它必须具有包含规范化路径所需的内存/容量

  • 是的,它被标记为没有语言,有人在上面加了“php”,我把它改为“c”-很抱歉忘记了这个标记。@user576875@thejh My bad(我把它标记为php)。应该先检查一下你最近的问题。向所有人道歉。“/dir/a\u random\u synlink/。/hello”的结果应该是什么?请记住,如果\u random\u synlink不指向同一目录中的目录,则它可能与“/dir/hello”不同directory@BatchyX:似乎是标准行为:
    readlink-v-m'/home/user/linktoslashtmp/./'
    返回
    /home/user
    可能readlink会这样做,但底层操作系统不会。ls/home/user/linktoslashtmp/。/列出了/@BatchyX的内容是否正确,执行此“规范化”将意味着前后路径不一定再打开同一个文件。@BatchyX您显然有错误的工具
    ls
    对我的作用与
    readlink
    的作用相同。您必须检查
    readlink
    +1的源代码:对于相对于当前目录计算路径的情况,这似乎很有效。严格地说,我认为问题的解释是“相对于
    /var/
    ”评估路径
    。/etc///././passwd
    ”,这是主题的一个简单变体(您不需要使用
    getcwd()
    建立当前目录;您使用用户传递的值)。谢谢,看起来不错-我稍微修改了函数以接受pwd参数permission@user576875你能给我讲讲吗
    "/var/", "../etc///././/passwd" => "/etc/passwd"
    
    #define _GNU_SOURCE /* memrchr() */
    
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <limits.h>
    
    char * normalize_path(const char * src, size_t src_len) {
    
            char * res;
            size_t res_len;
    
            const char * ptr = src;
            const char * end = &src[src_len];
            const char * next;
    
            if (src_len == 0 || src[0] != '/') {
    
                    // relative path
    
                    char pwd[PATH_MAX];
                    size_t pwd_len;
    
                    if (getcwd(pwd, sizeof(pwd)) == NULL) {
                            return NULL;
                    }
    
                    pwd_len = strlen(pwd);
                    res = malloc(pwd_len + 1 + src_len + 1);
                    memcpy(res, pwd, pwd_len);
                    res_len = pwd_len;
            } else {
                    res = malloc((src_len > 0 ? src_len : 1) + 1);
                    res_len = 0;
            }
    
            for (ptr = src; ptr < end; ptr=next+1) {
                    size_t len;
                    next = memchr(ptr, '/', end-ptr);
                    if (next == NULL) {
                            next = end;
                    }
                    len = next-ptr;
                    switch(len) {
                    case 2:
                            if (ptr[0] == '.' && ptr[1] == '.') {
                                    const char * slash = memrchr(res, '/', res_len);
                                    if (slash != NULL) {
                                            res_len = slash - res;
                                    }
                                    continue;
                            }
                            break;
                    case 1:
                            if (ptr[0] == '.') {
                                    continue;
    
                            }
                            break;
                    case 0:
                            continue;
                    }
                    res[res_len++] = '/';
                    memcpy(&res[res_len], ptr, len);
                    res_len += len;
            }
    
            if (res_len == 0) {
                    res[res_len++] = '/';
            }
            res[res_len] = '\0';
            return res;
    }
    
    #include <string.h>
    
    char * normalizePath(char* pwd, const char * src, char* res) {
        size_t res_len;
        size_t src_len = strlen(src);
    
        const char * ptr = src;
        const char * end = &src[src_len];
        const char * next;
    
        if (src_len == 0 || src[0] != '/') {
            // relative path
            size_t pwd_len;
    
            pwd_len = strlen(pwd);
            memcpy(res, pwd, pwd_len);
            res_len = pwd_len;
        } else {
            res_len = 0;
        }
    
        for (ptr = src; ptr < end; ptr=next+1) {
            size_t len;
            next = (char*)memchr(ptr, '/', end-ptr);
            if (next == NULL) {
                next = end;
            }
            len = next-ptr;
            switch(len) {
            case 2:
                if (ptr[0] == '.' && ptr[1] == '.') {
                    const char * slash = (char*)memrchr(res, '/', res_len);
                    if (slash != NULL) {
                        res_len = slash - res;
                    }
                    continue;
                }
                break;
            case 1:
                if (ptr[0] == '.') {
                    continue;
                }
                break;
            case 0:
                continue;
            }
    
            if (res_len != 1)
                res[res_len++] = '/';
    
            memcpy(&res[res_len], ptr, len);
            res_len += len;
        }
    
        if (res_len == 0) {
            res[res_len++] = '/';
        }
        res[res_len] = '\0';
        return res;
    }
    
    #include <stdio.h>
    
    int main(){
        char path[FILENAME_MAX+1];
        printf("\n%s\n",normalizePath((char*)"/usr/share/local/apps",(char*)"./../../../",path));
        return 0;
    }
    
    /usr