C プログラムで realpath 関数を使用する方法の例を探しています。Web や私の C プログラミングの本で見つけられないようです。
3 に答える
ノート
realpath()
関数は C 標準に記述されていませ ん- ただし、POSIX 1997およびPOSIX 2008で説明されています。
サンプルコード
#include <limits.h> /* PATH_MAX */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[PATH_MAX]; /* PATH_MAX incudes the \0 so +1 is not required */
char *res = realpath("this_source.c", buf);
if (res) { // or: if (res != NULL)
printf("This source is at %s.\n", buf);
} else {
char* errStr = strerror(errno);
printf("error string: %s\n", errStr);
perror("realpath");
exit(EXIT_FAILURE);
}
return 0;
}
- 参照
- POSIX 1997のPATH_MAXで定義されたPATH_MAX
- エラー番号
- ストエラー
ワンライン ビルド コマンド ライン
ミニマリストですが、それは仕事をします!
建てる
gcc -o realpath -x c - <<< $'#include<stdlib.h>\n#include<stdio.h>\nint main(int c,char**v){puts(realpath(v[1],0));}'
テスト
$> ./realpath ~/../../../usr/./bin/./awk
/bin/gawk
$> readlink -f ~/../../../usr/./bin/./awk
/bin/gawk
要件
クラッシュ
私の最小限の 1 行のコマンド ラインは、パスが存在しない場合にrealpath
生成される実行可能ファイルをビルドします。私の回答内でその問題を処理するために/ブロックをSegmentation fault
書く代わりに、いくつかのリンクを下に追加して、 Busybox のおよびの実装を確認できるようにしました。if
else
realpath
readlink
ビジーボックスの実装
より完全なソース コードについては、この単純な実装をご覧ください。
公式の Git リポジトリ
GitHub ミラー リポジトリ
関数が行うことは、realpath()
すべてのシンボリック リンクが解決されたときにファイルのパス名を通知することです。指定した値が相対名である場合、必ずしも絶対パス名であるとは限りませんが、リンク値の絶対名を持つシンボリックリンクをトラバースするかどうかに部分的に依存します-そうする場合、出力は結局のところ絶対名です. また、相対名がルート ディレクトリ (または、ディレクトリ階層の深さが 3 レベルのみの場合、「../../../../../..」のように「beyond」) までトラバースする場合。
マシンに「realpath」プログラムが既にある場合があります。これが私が書いた(非標準の)バージョンです。
/*
@(#)File: $RCSfile: realpath.c,v $
@(#)Version: $Revision: 1.3 $
@(#)Last changed: $Date: 2007/10/23 20:23:44 $
@(#)Purpose: Command to evaluate realpath(3) on given arguments.
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2007
@(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "stderr.h"
static const char optstr[] = "hlsV";
static const char usestr[] = "[-hslV] given-path [...]";
static const char hlpstr[] =
" -h Print this help message\n"
" -l Long format: print given-path and real-path\n"
" -s Short format: print just real-path\n"
" -V Print version and exit\n"
;
enum { FMT_LONG, FMT_SHORT };
static int format_type = FMT_LONG;
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_realpath_c[];
const char jlss_id_realpath_c[] = "@(#)$Id: realpath.c,v 1.3 2007/10/23 20:23:44 jleffler Exp $";
#endif /* lint */
static int eval_realpath(const char *given)
{
char realname[_POSIX_PATH_MAX];
int rc = 0;
if (realpath(given, realname) == 0)
{
rc = -1;
err_sysrem("failed to resolve real path name for %s\n", given);
}
else if (format_type == FMT_SHORT)
printf("%s\n", realname);
else
printf("%s %s\n", given, realname);
return(rc);
}
int main(int argc, char **argv)
{
int i;
int rc = EXIT_SUCCESS;
int opt;
err_setarg0(argv[0]);
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'V':
err_version("REALPATH", &"@(#)$Revision: 1.3 $ ($Date: 2007/10/23 20:23:44 $)"[4]);
break;
case 'h':
err_help(usestr, hlpstr);
break;
case 'l':
format_type = FMT_LONG;
break;
case 's':
format_type = FMT_SHORT;
break;
default:
err_usage(usestr);
break;
}
}
for (i = optind; i < argc; i++)
{
if (eval_realpath(argv[i]) != 0)
rc = EXIT_FAILURE;
}
return(rc);
}
パスのセキュリティを評価しているソフトウェアをテストするために必要であり、コードが同じ解決された場所への特定のパスを評価していることを確認する必要がありましたrealpath()
。「-a」オプションで拡張して、名前が絶対名にマップされるようにすることはおそらく賢明でしょう(の結果getcwd()
を相対パス名にプレフィックスすることにより)。
(stderr.c、stderr.h のソースはオンラインで見つけることができます。または、私に連絡してください - 私のプロフィールを参照してください。)