IFSパスを解決する
Question
IFS パスをどのように解決すればよいでしょうか。「blah」などのパスがある場合、OS では基本ディレクトリーは自分のカレント・ディレクトリーである /example と想定されるため、/example/blah という結果になります。あるいは、パスが「/usr/local/httpd/../otherfiles」の場合、「/usr/local/otherfiles」と解決されます。この解決パスを返す API はありませんか。
Answer
PASE 環境にはパス名を解決する realpath() というルーチンがあります。しかし、IBM i 環境ではこの API はありません。したがって、私の意見では、最も簡単な解決方法は、現在の作業ディレクトリー (CWD) を解決したいディレクトリーに変更することです。chdir() API を使用してこれを行うことができます。次に getcwd() API を呼び出して、新しい CWD を取得します。これが解決されたパス名になります。ILE RPG でその方法を示します。
わからないと困りますので説明しますが、この技法はすでに存在する IFS パスにのみ機能します。存在しないディレクトリー名で使用しても、「No such path or directory (パスまたはディレクトリーが見つかりません)」というエラーが表示されます。
以下のような擬似プログラムになります。
- 後で返却できるようにオリジナルの CWD を取得します。
- CWD を解決するパス名に変更します。IBM i により強制的にパス名が解決されます。
- 新しい CWD を取得します。パス名の解決先が示されます。
- ジョブが開始時の CWD に戻るよう、CWD の設定をオリジナルの設定に戻します。
以下の RPG サブプロシージャーは、その擬似プログラムを実装しています。
P IFS_ResolveDir B export D IFS_ResolveDir PI 5000a varying D dir 5000a varying const D origDir s 5000a static D newDir s 5000a static /free if getcwd(%addr(origDir): %size(origDir)) = *null; ReportError(); return; endif; if chdir(%trimr(dir)) = -1; ReportError(); return; endif; if getcwd(%addr(newDir): %size(newDir)) = *null; chdir(%addr(origDir)); ReportError(); return; endif; chdir(%addr(origDir)); return %str(%addr(newDir)); /end-free P E
以下の例は、このルーチンを RPG プログラムから呼び出しています。
mydir = '/usr/local/httpd/../otherfiles';
realdir = IFS_resolveDir(mydir);
この結果、「realdir」が「/usr/local/otherfiles」に設定されます。
前記のコードはサンプルに過ぎません。作業用の完全な例をダウンロードできます。