関数pathcheck マニュアル

(The documentation of function pathcheck)

Last Update: 2021/12/1


◆機能・用途(Purpose)

ファイルのパス部分のディレクトリが存在するかをチェックする。
Check if the directory of a file path exists.


◆形式(Format)

#include <file.h>
inline void pathcheck(const char ∗filename,const char ∗mode)


◆引数(Arguments)

filename ファイル名。絶対パスでも相対パスでもファイル名のみでも良い。
A file name, which can be either an absolute path, a relative path, or a file name without a path.
mode パス部分のディレクトリが存在しなかった場合の対処方法。 以下の選択肢からいずれか1つを指定すること。
Processings when the path directory does not exist. Choose one of the followings.
  • mkdir : ディレクトリが存在しなければ作成する。
    Create the path directory if it is absent.
  • mkdir- : 同上。但しディレクトリを作成した旨のメッセージを表示しない。
    Same as above, but without notifying that the directory was created.
  • exit : ディレクトリが存在しなければプログラムを終了する。
    Exit the program if the path directory is absent.
  • ask : ディレクトリを作成するか否か尋ねる。
    Ask if the path directory should be created or not.


◆使用例(Example)

char inputfile[]="/dat/asama/2004/04062717.win";
pathcheck(inputfile,"exit");


◆補足(Additional remarks)

この関数は主にファイルを書き込みモードでオープンする際の利便性のために 作成したものである。 ファイルを書き込みモードでオープンする場合、 ファイルへのパス部分のディレクトリが存在しなければ関数fopenからNULLが返される。 しかし、NULLが返る理由はほかにも多数あり (例: パーミッションが無い, 排他ロックが掛かっている)、 NULLが返ったからと言ってパスのディレクトリが存在しないとは限らない。 また、パスのディレクトリが存在しない場合の処理として、 その旨のエラーメッセージを出力して終了したい場合や、 ディレクトリを自動作成するアルゴリズムにしたい場合等、 さまざまな場合が考えられる。
This function was created mainly for convenience of opening a file by the writing mode. When a file is tried to be opened by the writing mode and a path directory does not exist, NULL is returned from function fopen. However, NULL may be returned by various other causes (e.g., there is no permission, an exclusive file lock is in effect), meaning that NULL does not indicate an absence of the path directory. In addition, optimal operations in case of the absence of the path directory may differ by situations; for example, it may be best to finish the program run with an error message in some cases, and the absent directory should be automatically created in some other cases.

そこで、このようなパスディレクトリの存在チェックと パスが存在しない場合のディレクトリ作成等を 一括して簡単に行うために用意したのがこの関数である。 この関数ではファイルのパス部分のディレクトリの存在の有無を先頭から順に調べていく。 存在しない場合の処理(エラー終了、ディレクトリを自動作成等)を 第2引数で指定できる。
This function checks whether a directory path exists, and automatically correspond to absent paths. This function checks if directory paths of a specified file exist from the beginning. Processings for absent paths (e.g., error exit, automatically creating the path directories) can be specified by the 2nd argument.

ディレクトリの存在有無については ディレクトリを読み込みモードで開いてみてNULLが返るかどうかで判定される。 したがって例えば読み込みパーミッションが無い場合も存在しないと判定される (書き込みパーミッションが無いだけならそうはならない)。
The path directory is regarded to be absent when NULL is returned by opening the directory by the reading mode. Therefore, the path directory is regarded to be absent if the directory does not have a reading permission, while regarded to be present if only a writing permission is missing.


◆関数内部でのコーディングに関する説明 (A description for the function coding)

一般にディレクトリパスは1つのファイルに対して複数存在する。 例えばAAA/BBBB/CCCCC/DDDDDD/EEEEEEEというファイル名の場合、
という4つのディレクトリパスが存在する。 この関数ではこれらを上位のパス(AAA)から順にチェックしていく。
Generally, multiple directory paths exist for a single file. For example, for a file AAA/BBBB/CCCCC/DDDDDD/EEEEEEE, there are the following 4 directory paths:
This function checks these directories from the upper side (i.e., AAA).

これを実現するため、この関数では引数filenameで示された文字列を 一旦別の変数(filename_cpy)にコピーした上で、 チェックしたいディレクトリパスの末尾の「/」を「\0」に置き換えて ディレクトリの存在をチェックした後に「\0」を「/」に戻す、という処理を 先頭から順に実行している。 上の例であれば次の手順になる。
To realize this, a string given by the argument filename is copied to another variable (filename_cpy), and then the following procedures are repeated from the beginning: replacing “/” at the end of the directory path to check by “\0”, checking whether the directory exists, and replacing back “\0” with “/”. These procedures for the example above are as follows.

  1. filenameが表す文字列をfilename_cpyにコピーする。
    Copy a string represented by filename to filename_cpy.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD/EEEEEEE"
  2. filename_cpyの最初の「/」を探して「\0」で置き換える。
    Search the first “/” of filename_cpy, and replace it with “\0”.
    結果(Result):
    filename_cpy= "AAA\0BBBB/CCCCC/DDDDDD/EEEEEEE"
  3. filename_cpyが表すディレクトリ(AAA)の存在チェックを行う。 Check if the directory represented by filename_cpy (AAA) exists.
  4. 「\0」を「/」に戻す。
    Replace back the “\0” to “/”. 結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD/EEEEEEE"
  5. filename_cpyの先頭から2番目の「/」を探して「\0」で置き換える。
    Search the second “/” of filename_cpy, and replace it with “\0”.
    結果(Result):
    filename_cpy= "AAA/BBBB\0CCCCC/DDDDDD/EEEEEEE"
  6. filename_cpyが表すディレクトリ(AAA/BBBB)の存在チェックを行う。
    Check if the directory represented by filename_cpy (AAA/BBBB) exists.
  7. 「\0」を「/」に戻す。
    Replace back the “\0” to “/”.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD/EEEEEEE"
  8. filename_cpyの先頭から3番目の「/」を探して「\0」で置き換える。
    Search the third “/” of filename_cpy, and replace it with “\0”.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC\0DDDDDD/EEEEEEE"
  9. filename_cpyが表すディレクトリ(AAA/BBBB/CCCCC)の存在チェックを行う。
    Check if the directory represented by filename_cpy (AAA/BBBB/CCCCC) exists.
  10. 「\0」を「/」に戻す。
    Replace back the “\0” to “/”.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD/EEEEEEE"
  11. filename_cpyの先頭から4番目の「/」を探して「\0」で置き換える。
    Search the 4th “/” of filename_cpy, and replace it with “\0”.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD\0EEEEEEE"
  12. filename_cpyが表すディレクトリ(AAA/BBBB/CCCCC/DDDDDD) の存在チェックを行う。
    Check if the directory represented by filename_cpy (AAA/BBBB/CCCCC/DDDDDD) exists.
  13. 「\0」を「/」に戻す。
    Replace back the “\0” to “/”.
    結果(Result):
    filename_cpy= "AAA/BBBB/CCCCC/DDDDDD/EEEEEEE"

上記の手順を実現するため、この関数では path_endpos, path_remainedという2つのポインタ変数を使用する。 path_endposは次にチェックしたいディレクトリパスの末尾の「/」を表すポインタで、 このポインタが示す値を一時的に「\0」に置き換えてディレクトリの存在チェックを行う。 path_remainedはまだチェックが終わっていない部分の先頭アドレスであり、 次の「/」を関数strchrを使って探すために用いる。
To realize the procedures above, this function uses two pointer variables, which are path_endpos and path_remained. The pointer path_endpos points to the end “/” of the directory path to check next, the value of which is temporarily replaced with “\0” to check if the directory exists. The pointer path_remained points to the head address of the part of the path for which the check is not finished. This pointer is used to search the next “/” by function strchr.

最後は「/」が見つからない場合にpath_endpos=NULLとなるのでそこでループを抜ける。
Finally, the value of path_endpos becomes NULL when “/” is not found. At this stage, the function escapes from the loop.