linux - realpath_ex

博客介绍了使用realpath将相对路径转绝对路径时,遇到不存在路径无法转换的问题。查看realpath实现后发现,在gnu coreutils工程中可编译生成realpath可执行文件,添加 -m 参数就能将不存在路径转成绝对路径,调用该文件用管道取结果即可。

前言

用到realpath来将相对路径转成绝对路径。
但是有个问题,如果这个路径是一个不存在的路径(e.g. mkdir psz_new_path), realpath是没法将不存在的路径或文件转成全路径的。

然后就想到要去看看realpath的实现。
realpath的实现在 gnu coreutils 工程中,具体的实现是 src\realpath.c.
gnu coreutils 编译完,可以生成 realpath这个磁盘命令可执行文件.
我就去看看realpath的帮助,一看,人家已经考虑到了将不存在的文件转成全路径的问题。
只需要在realpath后加参数 -m, 就可以将不存在的路径转成绝对路径。
这样,我只需要调用realpath可执行文件,用管道来取转换后的结果就行,不用去理解参考修改realpath的实现了.

demo下载点

test_realpath_2019_0508_1435.7z

运行效果

将一个复杂的,相对的,不存在路径,转成了绝对的全路径

root@localhost:/home/dev/test_realpath/src# ./test               
ok : [~dev/coreutils-8.24/../bash-4.4/doc/../../../../../../../var/log/new_dir/] convert to realpath[/var/log/new_dir]

实现

// @file main.cpp
//
// @note
//
//	on fedora22 view syslog use 'journalctl -f'
// 'tail -f /var/log/message' is invalid
//
// on fedora23, can use 'tail -f /var/log/message' to view syslog
// also use 'journalctl -f' to view syslog too

#include <stdlib.h>
#include <stdio.h>

#include <string.h>
#include <unistd.h>

#include <syslog.h>
#include <signal.h>

#ifndef MYLOG_D
	
#define MYLOG_D(fmt, ...) \
	do { \
		syslog(LOG_INFO, "[%s : %s.%d : %s()] : " fmt, "LS_LOG", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \
	} while (0);
	
#endif // #ifndef MYLOG_D

void init(const char* psz_log_owner_name);
void uninit();
void proc_sig_term(int num);
int fn_test();

char* realpath_ex(const char* psz_path_in);

int main(int argc, char** argv)
{
    char sz_buf[1024] = {'\0'};

#ifdef MAKE_FILE_MACRO__BIN_NAME
    sprintf(sz_buf, "%s", MAKE_FILE_MACRO__BIN_NAME);
    init(sz_buf);
    MYLOG_D("MAKE_FILE_MACRO__BIN_NAME = [%s]", MAKE_FILE_MACRO__BIN_NAME);
#else
    init(NULL);
#endif // #ifdef MAKE_FILE_MACRO__BIN_NAME

    fn_test();
    uninit();

    MYLOG_D("THE END");
    return EXIT_SUCCESS;
}

void init(const char* psz_log_owner_name)
{
    int i = 0;

    // daemon(0, 0);
    openlog(((NULL != psz_log_owner_name) ? psz_log_owner_name : "my_syslog"), LOG_NOWAIT | LOG_PID, LOG_LOCAL1);

    // clear screen (print 25 empty line)
    for (i = 0; i < 25; i++) {
        MYLOG_D("");
    }

    signal(SIGTERM, proc_sig_term);
}

void uninit()
{
	closelog();
}

void proc_sig_term(int num)
{
    MYLOG_D("SIGTERM = %d, num = %d", SIGTERM, num);
    MYLOG_D("maybe can do some clean task before quit");
    exit(1);    
}

int fn_test()
{
    MYLOG_D(">> fn_test()");

	// 构造一个复杂的, 不存在的相对路径作为测试用例
	const char* psz_path_in = "~dev/coreutils-8.24/../bash-4.4/doc/../../../../../../../var/log/new_dir/";
	char* psz_realpath = NULL;

	psz_realpath = realpath_ex(psz_path_in);
	if (NULL == psz_realpath) {
		printf("error : can't convert [%s] to realpath\r\n", psz_path_in);
	} else {
		printf("ok : [%s] convert to realpath[%s]\r\n", psz_path_in, psz_realpath);
		free(psz_realpath);
		psz_realpath = NULL;
	}

    return 0;
}

char* realpath_ex(const char* psz_path_in)
{
	char* psz_realpath = NULL;
	char sz_buf[0x1000] = {'\0'};
	const char* psz_cmd_realpath = "realpath -m";
	FILE* fp = NULL;
	int i_len = 0;
	
	do {
		if ((NULL == psz_path_in)
			|| ((int)strlen(psz_path_in) >= (int)(sizeof(sz_buf) - strlen(psz_cmd_realpath) - 2) )
			) {
			break;
		}

		// realpath是磁盘命令, debian8.8和fedora23都有这个磁盘命令
		// 如果真没有realpath磁盘命令, 可以用gnu coreutils工程自己先编译一个出来, 放到/bin或/usr/bin中

		// /usr/bin/realpath
		// -m, --canonicalize-missing   no components of the path need exist
		// realpath带上 -m 参数就可以将任意一个路径(包括相对路径,不存在的路径)转成绝对路径
		// 将不存在的相对路径转成绝对路径有实际意义. e.g. 用mkdir 在任意位置 建立一个绝对路径的文件夹, 而不需要依赖当前路径

		sprintf(sz_buf, "%s %s%c", psz_cmd_realpath, psz_path_in, '\0');
		fp = popen(sz_buf, "r");
		if (NULL == fp) {
			break;
		}

		memset(sz_buf, 0, sizeof(sz_buf));
		if (NULL != fgets(sz_buf, sizeof(sz_buf), fp)) {
			i_len = strlen(sz_buf);
			if (i_len <= 0) {
				break;
			}
		
			if (('\r' == sz_buf[i_len - 1])
				|| ('\n' == sz_buf[i_len - 1])
				) {
				sz_buf[i_len - 1] = '\0';
			}

			psz_realpath = strdup(sz_buf);	
		}
	} while (0);

	if (NULL != fp) {
		pclose(fp);
		fp = NULL;
	}

	return psz_realpath;
}


# ==============================================================================
# @file makefile
# ==============================================================================
# @note 
# howto build project
# 		make BIN_NAME="bin_name_by_you_want" rebuild

MY_MAKE_FILE_PATH_NAME = $(MAKEFILE_LIST)

# macro from Makefile command line
# BIN_NAME

# macro to C project
MAKE_FILE_MACRO__BIN_NAME="make_file_macro__bin_name"

# var define on Makefile
BIN = output_not_give_bin_name
IS_BUILD_TYPE_VALID = 0

ifdef BIN_NAME
   	IS_BUILD_TYPE_VALID = 1
	BIN = $(BIN_NAME)
	MAKE_FILE_MACRO__BIN_NAME=$(BIN_NAME)
else
    IS_BUILD_TYPE_VALID = 0
endif

LINE80 = --------------------------------------------------------------------------------
CC = g++ -std=c++98

# -Werror is "warning as error"
CFLAGS = -Wall -Werror -g

INC = -I.
LIBPATH = -L/usr/lib/ -L/usr/local/lib/

ifeq (1, $(IS_BUILD_TYPE_VALID))
	LIBS = 
else
	LIBS = 
endif

DEPEND_CODE_DIR = ./empty_dir \

DEPEND_CODE_SRC = $(shell find $(DEPEND_CODE_DIR) -name '*.cpp')
DEPEND_CODE_OBJ = $(DEPEND_CODE_SRC:.cpp=.o)

ROOT_CODE_SRC = $(shell find ./ -name '*.cpp')
ROOT_CODE_OBJ = $(ROOT_CODE_SRC:.cpp=.o)

SUB_CODE_DIR = ./socket_easy
SUB_CODE_SRC = $(shell find $(SUB_CODE_DIR) -name '*.cpp')
SUB_CODE_OBJ = $(SUB_CODE_SRC:.cpp=.o)

.PHONY: help
help:
	clear
	@echo "usage:"
	@echo
	@echo "build project by given bin name"
	@echo "make BIN_NAME=\"bin_name_by_you_want\" rebuild"
	@echo

.PHONY: clean
clean:
	clear

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo
	@echo

	@echo
	@echo
	@echo
	@echo
	@echo
	
	@echo "make clean begin"
	@echo $(LINE80)

	@echo "@file $(MY_MAKE_FILE_PATH_NAME)"
	@echo "IS_BUILD_TYPE_VALID = $(IS_BUILD_TYPE_VALID)"
	@echo "BIN = $(BIN)"

	@echo $(LINE80)

	rm -f $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)
	
ifeq (1, $(IS_BUILD_TYPE_VALID))
	rm -f ./$(BIN)
endif

	@echo "make clean over"

.PHONY: all
all:$(BIN)
	@echo $(LINE80)
	@echo make all
	chmod 777 ./$(BIN)
	find . -name "$(BIN)"

$(BIN) : $(ROOT_CODE_OBJ) $(DEPEND_CODE_OBJ) $(SUB_CODE_OBJ)
	$(CC) $(CFLAGS) -o $@ $^ $(SHLIBS) $(INC) $(LIBPATH) $(LIBS)

.cpp.o:
	$(CC) -c $(CFLAGS) -DMAKE_FILE_MACRO__BIN_NAME="\"$(MAKE_FILE_MACRO__BIN_NAME)\"" $^ -o $@ $(INC) $(LIBPATH) $(LIBS)

.PHONY: rebuild
rebuild:
	make -f $(MY_MAKE_FILE_PATH_NAME) clean

ifeq (1, $(IS_BUILD_TYPE_VALID))
	@echo $(LINE80)
	make -f $(MY_MAKE_FILE_PATH_NAME) all
	chmod 775 ./$(BIN)
	ldd ./$(BIN)
else
	@echo $(LINE80)
	@echo "error : Makefile command line input error, please see help"	
	@echo "please run => make help"	
	@echo $(LINE80)
endif
	


#!/bin/bash
# ==============================================================================
# @file build_all_project.sh
# ==============================================================================

make BIN_NAME="test" rebuild


TARGET := mpp FW_SRC := mpp_proc.c FW_SRC += vb_proc.c log_proc.c sys_proc.c mpp_proc_common.c \ vi_proc.c vpss_proc.c venc_proc.c vdec_proc.c \ ai_proc.c ao_proc.c aenc_proc.c adec_proc.c \ vgs_proc.c cpm_proc.c region_proc.c media_mm_proc.c ifeq ($(ENABLE_MPP_TRACE),1) FW_SRC += trace_proc.c endif ifneq ($(findstring $(TARGET_CHIPSERIES), TX5335AX TX5368AX TX5339AX),) # $(info ----- proc TARGET_CHIPSERIES 52) # ccflags-y += -DCVE_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD FW_SRC += cve_proc.c FW_SRC += dma_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5336EX TX5256EX),) # $(info ------ proc TARGET_CHIPSERIES 53) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DCVE_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD # ccflags-y += -DBIS_PROC_BUILD ccflags-y += -DDX5336 -DVO_PROC_BUILD -DGDC_PROC_BUILD FW_SRC += cve_proc.c FW_SRC += bis_proc.c FW_SRC += gdc_proc.c FW_SRC += dma_proc.c FW_SRC += vo_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5215BX ),) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DCVE_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD ccflags-y += -DDX5215 -DVO_PROC_BUILD FW_SRC += cve_proc.c FW_SRC += dma_proc.c FW_SRC += vo_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5239BX TX5239CX),) # $(info ------ proc TARGET_CHIPSERIES 56) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DCVE_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD ccflags-y += -DTX5239 FW_SRC += cve_proc.c FW_SRC += dma_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5112DX),) # $(info ------ proc TARGET_CHIPSERIES 57) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD ccflags-y += -DDX5112 FW_SRC += cve_proc.c FW_SRC += dma_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5239DX),) # $(info ------ proc TARGET_CHIPSERIES 57) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD ccflags-y += -DTX5239 FW_SRC += cve_proc.c FW_SRC += dma_proc.c else ifneq ($(findstring $(TARGET_CHIPSERIES), TX5110FPGA TX5110FX),) # $(info ------ proc TARGET_CHIPSERIES 57B) # ccflags-y += -DAMR_PROC_BUILD # ccflags-y += -DDMA_PROC_BUILD ccflags-y += -DDX5110 FW_SRC += cve_proc.c FW_SRC += dma_proc.c endif FW_SRC_OBJ := $(FW_SRC:.c=.o) obj-m := $(TARGET).o $(TARGET)-y += $(FW_SRC_OBJ) ccflags-y += -fdebug-prefix-map=$(CURDIR)=. PWD := $(shell pwd) ccflags-y += -I$(PWD)/../libs/mpp/common/mpp_sys/inc \ -I$(PWD)/../libs/mpp/common/include/ \ -I$(PWD)/../libs/mpp/include/ \ -I$(PWD)/../libs/drv/audio/codec/ts_codec/ ccflags-y += -DUSE_MPP_HEADER -Wno-error=unused-variable ifeq ($(ENABLE_MPP_TRACE),1) ccflags-y += -DENABLE_MPP_TRACE endif modules: @echo "TARGET_CHIPSERIES:$(TARGET_CHIPSERIES)" @echo "ENABLE_MPP_TRACE:$(ENABLE_MPP_TRACE)" $(MAKE) -C $(TARGET_KERNEL_DIR) M=$(PWD) modules clear: @rm -f *.o *.cmd *.mod.c @rm -rf *~ core .depend .tmp_versions Module.symvers modules.order -f @rm -f .*ko.cmd .*.o.cmd .*.o.d @rm -f *.unsigned clean: @rm -f $(TARGET).ko @make -C $(TARGET_KERNEL_DIR) M=$(PWD) clean 同一套代码,该模块编译的ko在不同路径下为啥会不一样,以上是makefile脚本,
最新发布
08-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值