realpath()没有解析符号链接?

the*_*ejh 11 c symlink normalization realpath

我已经读过了realpath(),但是有一个函数,我可以传递一个基本目录和一个文件名,它会给我以下结果而不解析符号链接或检查文件是否确实存在?或者我必须使用修改realpath()

"/var/", "../etc///././/passwd" => "/etc/passwd"
Run Code Online (Sandbox Code Playgroud)

Arn*_*anc 9

这是一个normalize_path()函数:

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

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

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

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • 当然,我给你许可 (2认同)
  • 谢谢!我已将其修改为独立于系统调用并修复为正确处理cwd =='/'的情况:https://gist.github.com/Eugeny/5127791 (2认同)