0

abcLinuxで、次のメソッドを使用したプログラムがあるとします。

char *currentPath(){
        char *path=NULL;
        path = getcwd(path, MAXPATHLEN);
        return path;
}

直接呼び出す場合abc、このパスはにあるパスを返しますabc

にシンボリックリンクを作成し、シンボリックリンクをabc呼び出すと、シンボリックリンクcurrentPath()のパスが返されます。

このメソッドにのパスを返すようにする方法はありabcますか?の場所に関連するファイルにアクセスすることに興味がありますabc

4

3 に答える 3

4

getcwd()実行可能ファイル名の取得を支援するために使用することはできません。実行可能ファイルのパス名を見つけるのは賢明な方法ではありません。

Linuxには、システムコール/proc/self/exeで実行可能ファイルを読み取った場合に、実行可能ファイルの名前を示すシンボリックリンクがあります。システムコールは、返す値をnullで終了しないことreadlink()に注意してください(理由はわかりません。私の本では非常に奇妙な動作であり、不注意なバグの瞬間的な原因です)。readlink()

あなたの計画には多くの問題があります。

  1. プログラムが$PATHを介して見つかった場合、現在のディレクトリが実行可能ファイルを含むディレクトリと同じであるという保証はありません。あなたがそれについて考えるならば、あなたはディレクトリ/bin/lsにいなくても走ります。/bin
  2. セキュリティが心配な場合は、の値がargv[0]ターゲットプログラムを起動するプログラムの制御下にあることに注意してください。シェルは適切に動作します。他のプログラムはもっと悪意があるかもしれません:

    #include <unistd.h>
    int main(void)
    {
        char *argv[] = { "/opt/you/bin/bogus", "300", 0 };
        execvp("sleep", argv);
        return(-1);
    }
    

    /opt/you/bin/bogusこれにより、プログラムが呼び出された場合でも、プログラム名が渡されますsleep

Webを検索すると、「実行可能ファイル名を取得する方法」の例がたくさん見つかりますargv[0]。そうではない。他のプラットフォームには、実行可能ファイル名を取得するための他の手法があります。使用/proc/self/exeは移植性がありません。他のテクニックもありません。

于 2012-08-12T06:44:48.190 に答える
2

使用するrealpath(const char *path, char *resolved_path)

realpath()は、すべてのシンボリックリンクを展開し、pathで指定されたnullで終了する文字列内の/./、/../および余分な「/」文字への参照を解決して、正規化された絶対パス名を生成します。

あなたの場合:

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

于 2012-08-12T06:45:56.690 に答える
0

このコードを試してください(必要に応じて変更してください)。

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

#define MAXPATHLEN      256

char buffer[1024];

char *currentPath(char *bin_path){
        char *path = NULL;
        ssize_t len;
        struct stat file_stat;

        if (lstat(bin_path, &file_stat) != 0) 
        {
                /* handle error */
                fprintf(stderr, "ERROR\n");
        }

        if (!S_ISREG(file_stat.st_mode)) 
        {
                /* file is a symlink */
                fprintf(stdout, "Is a symlink\n");
                if ((len = readlink(bin_path, buffer, sizeof(buffer)-1)) != -1)
                        buffer[len] = '\0';
                /* In this case we return the name of the link */
                return buffer;
        }
        else
        {
                fprintf(stdout, "Is a regular file\n");
                path = getcwd(bin_path, MAXPATHLEN);

                return path;
        }
}

int main(int argc, char **argv)
{
        fprintf(stdout, "My path is : %s\n", currentPath(argv[0]));

        return 0;
}
于 2012-08-12T07:13:16.420 に答える