/*
 *	glob.c
 *
 *	パターンにマッチするパス名を見付ける(POSIX関数)
 *
 *	* Tue May 17 21:36:02 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	  参照資料:「Linux Programmer's Manual (3) - GLOB」(http://linuxjm.osdn.jp/html/LDP_man-pages/man3/glob.3.html)
 *	- まず、Win32用だけを実装しました。
 *	  glob()は、scandir()等と違って、途中のフォルダにもワイルドカードを使えるので、Windowsプログラミングでも便利に使えると思ったからです。
 *	- P/ECE用は、未実装です。
 *	  P/ECEにはフォルダが無いので、scandir()を使ってもほとんど同じだと思います。
 *	* Tue May 17 23:11:10 JST 2016 Naoyuki Sawa
 *	- P/ECE用も実装しました。
 *	  scandir()ではなく、readdir()とfnmatch()を使って実装しました。
 *	  その方が実装し易かったからそうしただけであり、結果はscandir()を使った場合とほとんど同じです。
 *	* Wed May 18 21:26:51 JST 2016 Naoyuki Sawa
 *	- Win32用のglob()のpattern引数に絶対パス(「C:\Foo\～」「\Foo\～」等)が指定された時に、誤ってカレントフォルダからの相対パスとして処理してしまっていたバグを修正ました。
 *	  _findfirst()がfileinfo.nameに格納するパス名のルールが直観的でないため、glob(),及び,glob_subr()の処理もかなり複雑で判り辛くなってしまいました。
 *	  詳細は、glob(),及び,glob_subr()内のコメントを参照して下さい。
 *	  一見、無駄な処理を行っているように見える部分が有るかもしれませんが、それぞれに意味が有ります。
 *	  不用意に変えると正しく動作しなくなる恐れが有るので、注意して下さい。
 *	- コメントの中で、パスセパレータを'\'と'/'の片方だけについて書いている箇所が有りますが、'\'も'/'も対応しています。
 *	  glob()のpattern引数の中で使用するパスセパレータとしては、'\'も'/'も使用可能です。
 *	  尚、当モジュールがgl_pathvに出力するパスセパレータとしては、'\'を使用しています。
 *	- glob.cの一番下に、「使用例 (Win32)」を書きました。
 *	* Tue Sep 06 21:06:46 JST 2016 Naoyuki Sawa
 *	- 64ビット対応のために、VS2015では_findfirst()が返した検索ハンドルを格納する変数の型を(long)⇒(intptr_t)に変更しました。
 *	  VC++6.0の頃は(long)だったのですが、VS2015までの間のどこかで(intptr_t)に仕様変更になっていたようです。
 *	  32ビットならばどちらでも同じですが、64ビットの場合は正しく(intptr_t)で扱わないと_findnext()が異常終了します。
 *	- 尚、VC++6.0は32ビット専用なので(intptr_t)に統一しても構わないのですが、VC++6.0の_findfirst()の仕様は(long)である事を強調するために、敢えて条件コンパイルする事にしました。
 */
#include "clip.h"
/*****************************************************************************
 *	glob (Win32用)
 *****************************************************************************/
#ifdef  _MSC_VER
//driveとdirを一緒にしてはいけない。理由は以下の通り:
//│_findfirst("C:Foo",～)に対してマッチすると、fileinfo.nameは"C:Foo"ではなく"Foo"になるようだ。
//│もしdriveとdirを一緒にして、glob()からの最初の呼び出しでargv[0]="C:Foo"になっていると、fileinfo.nameは"Foo"なので、glob_subr()内でmakepath()を行った時点で"C:"が失われてしまう。
//│普通はカレントドライブがC:で検索対象もC:だろうから、普通は問題ないのだが、
//│カレントドライブがD:で、「C:Foo/Bar/Baz」等を検索しようとした時に、二段目からのglob_subr()がD:に対して行われてしまい、問題が生じる。
//│上記の問題を避けるために、driveは分けて保持しておく必要が有る。
//│尚、glob()のpattern引数にドライブが含まれていなかった場合は、glob()の処理でdrive=""となるのでdrive=NULLになる事は無く、同じ処理で問題無い。
static void glob_subr(const char* drive, const char* dir/*NULL可*/, char** argv, glob_t* pglob) {
	char path[MAX_PATH], *fname;
	struct _finddata_t fileinfo;
//{{2016/09/06変更:64ビット対応のために、VS2015では_findfirst()が返した検索ハンドルを格納する変数の型を(long)⇒(intptr_t)に変更しました。
//	long hfind;
//↓2016/09/06変更:64ビット対応のために、VS2015では_findfirst()が返した検索ハンドルを格納する変数の型を(long)⇒(intptr_t)に変更しました。
    #if     (_MSC_VER <= 1200)
	long hfind;		//VC++6.0では、_findfirst()が返した検索ハンドルを格納する変数の型は(long)です。
    #else //(_MSC_VER <= 1200)
	intptr_t hfind;		//VS2015では、_findfirst()が返した検索ハンドルを格納する変数の型は(intptr_t)です。VS.NET～VS2013は不明ですが、仮にVS2015と同じ(intptr_t)としました。
    #endif//(_MSC_VER <= 1200)
//}}2016/09/06変更:64ビット対応のために、VS2015では_findfirst()が返した検索ハンドルを格納する変数の型を(long)⇒(intptr_t)に変更しました。
	//パス要素(ワイルドカード未展開)を取得し、パス要素へのポインタを次へ進める。
	fname = *argv++;
	//パス要素(ワイルドカード未展開)が有れば…
	if(fname) {
		//既存のパス(ワイルドカード展開済み)に、パス要素(ワイルドカード未展開)を追加して、パターン(ワイルドカード未展開)を組み立てる。
		makepath(path, drive, dir/*NULL可*/, fname/*NULL可*/, NULL);
		//このパターン(ワイルドカード未展開)にマッチする、最初のファイル,又は,フォルダを取得する。
		hfind = _findfirst(path, &fileinfo);
		//このパターン(ワイルドカード未展開)にマッチする、ファイル,又は,フォルダが有れば…
		if(hfind != -1) {
			do {
				//デフォルトでは、メタキャラクターは先頭のピリオドにはマッチできない。(GLOB_PERIODのコメント参照)
				if((fileinfo.name[0] == '.') && (fname[0] != '.')) { continue; }	//マッチしたファイル名の一文字目が'.'で、パス要素(ワイルドカード未展開)の一文字目が'.'でなければ、除外する。こうしないと、glob("*/*",～)で呼び出した時に、"../foo","../bar",…等にもマッチしてしまう。
//{{■■■要注意!!■■■_findfirst(".",～)に対してfileinfo.nameが"."ではなく本当のフォルダ名("test.win"等)を返すようで、そのまま使うとカレントフォルダ内で再帰できない問題が生じる。同様に、_findfirst("..",～)に対してfileinfo.nameが".."ではなく本当のフォルダ名("clip"等)を返すようで、そのまま使うと親フォルダへ再帰して行けなくなる問題が生じる。仕方が無いので、パターンが".",又は,".."ならば、_findfirst()が返したfileinfo.nameを、パターンそのもの(".",又は,"..")で上書きして回避する事にした。綺麗な方法ではないが、意図通りの結果にはなる。
				if(!strcmp(fname, ".") || !strcmp(fname, "..")) {		//この時多分、fileinfo.nameには、実際のフォルダ名が格納されてしまっている。
					if(sizeof fileinfo.name <= strlen(fname)) { DIE(); }	//念のためfileinfo.nameの容量を確認する。実際には_finddata_t.name[260]だから大丈夫なはず。
					strcpy(fileinfo.name, fname);				//_findfirst()が返したfileinfo.nameを、パターンそのもの(".",又は,"..")で上書きする。
				}
//}}■■■要注意!!■■■_findfirst(".",～)に対してfileinfo.nameが"."ではなく本当のフォルダ名("test.win"等)を返すようで、そのまま使うとカレントフォルダ内で再帰できない問題が生じる。同様に、_findfirst("..",～)に対してfileinfo.nameが".."ではなく本当のフォルダ名("clip"等)を返すようで、そのまま使うと親フォルダへ再帰して行けなくなる問題が生じる。仕方が無いので、パターンが".",又は,".."ならば、_findfirst()が返したfileinfo.nameを、パターンそのもの(".",又は,"..")で上書きして回避する事にした。綺麗な方法ではないが、意図通りの結果にはなる。
				//既存のパス(ワイルドカード展開済み)に、マッチしたファイル名,又は,フォルダ名を追加して、新しいパス(ワイルドカード展開済み)を組み立てる。
				makepath(path, NULL, dir/*NULL可*/, fileinfo.name, NULL);
				//             ~~~~driveは個別でglob_subr()に渡すのでパスに組み込まないように注意しろ。
				//次の再帰を呼び出す。                 │
				glob_subr(drive, path, argv, pglob); //│
				//        ~~~~~←───────────┘
			} while(!_findnext(hfind, &fileinfo));	//次にマッチするファイル(又はフォルダ)が有る間、繰り返す。
			//検索ハンドルを閉じる。
			if(_findclose(hfind)) { DIE(); }
		}
	//パス要素(ワイルドカード未展開)が無ければ…	つまり、直前の再帰がargvの末尾だったならば…
	} else {
		//直前の再帰で組み立てた新しいパス(ワイルドカード展開済み)が有れば…	要するに、相対パス指定のglob()からの最初の再帰呼び出しでなければ…
		if(dir) {
			//既存のパス(ワイルドカード展開済み)に、drive(指定されていれば)を組み込んだ文字列を組み立てる。
			makepath(path, drive, NULL, dir, NULL);	//dirをfnameと見なして組み立てる。「makepath(path,drive,dir,NULL,NULL)」では不可。そうしないと末尾に余計な'\'が付いてしまう。
			//直前の再帰で組み立てた新しいパス(ワイルドカード展開済み)に、drive(指定されていれば)を組み込んだ文字列を、マッチしたパス名のリストに追加する。
			strv_extend(&pglob->gl_pathv, path);			//    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~これ忘れないように!!「strv_extend(&pglob->gl_pathv,dir)」では不可。そうしないとglob("C:\Foo",～)の結果が"\Foo"になってしまう。ドライブを指定した場合は結果にもドライブを含めて"C:\Foo"になるのが正しい。
		}
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int glob(const char* pattern, int flags, int (*errfunc)(const char* epath, int eerrno), glob_t* pglob) {
	if(flags || errfunc) { DIE(); }	//当実装は、flags,及び,errfuncに未対応です。flags,又は,errfuncに0(NULL)以外を指定してglob()を呼び出すと、エラー停止します。
	//空のリストを作成する。
	pglob->gl_pathv = strv_new(NULL);
	{
		char path[MAX_PATH], drive[MAX_DRIVE], dir[MAX_DIR], fname[MAX_FNAME], ext[MAX_EXT];
		//パターン(ワイルドカード未展開)を、構成要素に分割する。
		splitpath(pattern, drive, dir, fname, ext);
		//ドライブを除いた構成要素を、ドライブを除いたパターン(ワイルドカード未展開)に合成し直す。
		makepath(path, NULL, dir, fname, ext);
		//ドライブを除いたパターン(ワイルドカード未展開)が空文字だった場合は、何もしない。
		// - 以下の処理を判り易くするために、path=""のケースは最初に除外しておく事にした。
		if(*path) {
			//ドライブを除いたパターン(ワイルドカード未展開)を、パス要素(ワイルドカード未展開)に分割する。
			char** argv = strsplit_set(path, "/\\", 0);
			//ドライブを除いたパターン(ワイルドカード未展開)が、相対パス指定ならば…
			// - ちなみに、'if(!PathIsRelative(pattern)){'では上手く動かなかった。
			//   PathIsRelative()は、「C:Foo」も絶対パスと見なしてFALSEを返してしまうようだ(バグでは?)。
			//   PathIsRelativeの問題については下記のフォーラムでも指摘されている:
			//   「Stack Overflow - Is it a WinAPI Bug with PathIsRelative function?」(http://stackoverflow.com/questions/26099361/is-it-a-winapi-bug-with-pathisrelative-function)
			// - 仕方が無いので、自分で判断する事にした。
			//   argv[0]が空文字になるのは、分割元のpathの一文字目が'\',又は,'/'だった場合のみである。
			//   従って、argv[0]が空文字ならば絶対パス,argv[0]が空文字でなければ相対パスだと判定出来る。
			if(*argv[0]) {	//argv[0]が空文字でなければ…
				//最初の再帰を呼び出す。
				glob_subr(drive, NULL, &argv[0], pglob);
			//ドライブを除いたパターン(ワイルドカード未展開)が、絶対パス指定ならば…
			} else {	//argv[0]が空文字ならば…
				//最初の再帰を呼び出す。
				// - 絶対パスを示す'\'は、argv[1]の先頭に付与してはいけない。
				//   もしargv[1]の先頭に付与すると、_findfirst("\\usr")に対してマッチした場合、fileinfo.name="usr"になり、絶対パスを示す'\'が失われてしまう。
				//   下記のようにglob_subr()へのdir引数して渡せば、_findfirst()の結果で置き換えられる事は無いので、この'\'が失われる事は無い。
				glob_subr(drive, "\\", &argv[1], pglob);	//argv[0]が空文字なので、argv[1]から開始する。
			}
			//分割したパス要素(ワイルドカード未展開)を開放する。
			strv_free(argv);
		}
	}
	//デフォルトでは、返されるパス名はソートされる。(GLOB_NOSORTのコメント参照)
	strv_sort(pglob->gl_pathv);
	//マッチしたパスの数を格納する。
	pglob->gl_pathc = strv_length(pglob->gl_pathv);
	//一つもマッチしなければ、空のリストを開放して、GLOB_NOMATCHを返す。
	if(!pglob->gl_pathc) {
		globfree(pglob);
		return GLOB_NOMATCH;	//この後、アプリケーションがglobfree()を呼び出す必要は無い。
	}
	//一つでもマッチしたら0を返す。
	return 0;			//この後、アプリケーションがglobfree()を呼び出す必要が有る。
}
#endif//_MSC_VER
/*****************************************************************************
 *	glob (P/ECE用)
 *****************************************************************************/
#ifdef  PIECE
int glob(const char* pattern, int flags, int (*errfunc)(const char* epath, int eerrno), glob_t* pglob) {
	if(flags || errfunc) { DIE(); }	//当実装は、flags,及び,errfuncに未対応です。flags,又は,errfuncに0(NULL)以外を指定してglob()を呼び出すと、エラー停止します。
	//空のリストを作成する。
	pglob->gl_pathv = strv_new(NULL);
	{
		struct dirent* e;
		//フォルダを開く。
		DIR* d = opendir(".");	//当ライブラリのopendir()の実装は必ず成功する。clipdire.cを参照せよ。
		//各ファイルについて…
		while((e = readdir(d))) {
			//パターンにマッチするファイル名ならば…
			if(!fnmatch(pattern, e->d_name, 0)) {	//fnmatch()はマッチした時に0を返す事に注意せよ。
				//マッチしたパス名のリストに追加する。
				strv_extend(&pglob->gl_pathv, e->d_name);
			}
		}
		//フォルダを閉じる。
		closedir(d);
	}
	//デフォルトでは、返されるパス名はソートされる。(GLOB_NOSORTのコメント参照)
	strv_sort(pglob->gl_pathv);
	//マッチしたパスの数を格納する。
	pglob->gl_pathc = strv_length(pglob->gl_pathv);
	//一つもマッチしなければ、空のリストを開放して、GLOB_NOMATCHを返す。
	if(!pglob->gl_pathc) {
		globfree(pglob);
		return GLOB_NOMATCH;	//この後、アプリケーションがglobfree()を呼び出す必要は無い。
	}
	//一つでもマッチしたら0を返す。
	return 0;			//この後、アプリケーションがglobfree()を呼び出す必要が有る。
}
#endif//PIECE
/*****************************************************************************
 *	globfree (共通)
 *****************************************************************************/
void globfree(glob_t* pglob) {
	//マッチしたパス名のリストを開放する。
	strv_free(pglob->gl_pathv/*NULL可*/);
	//安全のため、構造体をクリアしておく。
	// - こうしておけば、万一、同じpglobに対して再度globfree()が呼ばれても、ダミー処理となる。(strv_free(NULL)は安全だから)
	memset(pglob, 0, sizeof(glob_t));
}
/*****************************************************************************
 *	使用例 (Win32)
 *****************************************************************************/
#if 0
//以下の使用例ではワイルドカードに'*'だけを使っていますが、'?'も使用可能です。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定した絶対パスの例
void testA1() {
	glob_t g;
	if(!glob("C:\\usr\\PIECE\\app\\adpcm\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│C:\usr\PIECE\app\adpcm\hello.c
//│C:\usr\PIECE\app\adpcm\ose16.c
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定した絶対パスで、途中にワイルドカードを使った例
void testA2() {
	glob_t g;
	if(!glob("C:\\usr\\PIECE\\app\\*\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│C:\usr\PIECE\app\BlackWings\after.c
//│C:\usr\PIECE\app\BlackWings\decode.c
//│～
//│C:\usr\PIECE\app\adpcm\hello.c
//│C:\usr\PIECE\app\adpcm\ose16.c
//│C:\usr\PIECE\app\gamepad\gamepad.c
//│C:\usr\PIECE\app\hello\hello.c
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しない絶対パスの例
void testA3() {
	glob_t g;
	if(!glob("\\usr\\PIECE\\app\\adpcm\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│\usr\PIECE\app\adpcm\hello.c
//│\usr\PIECE\app\adpcm\ose16.c
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しない絶対パスで、途中にワイルドカードを使った例
void testA4() {
	glob_t g;
	if(!glob("\\usr\\PIECE\\app\\*\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│\usr\PIECE\app\BlackWings\after.c
//│\usr\PIECE\app\BlackWings\decode.c
//│～
//│\usr\PIECE\app\adpcm\hello.c
//│\usr\PIECE\app\adpcm\ose16.c
//│\usr\PIECE\app\gamepad\gamepad.c
//│\usr\PIECE\app\hello\hello.c
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定した相対パスの例
void testR1() {
	glob_t g;
	_chdir("C:\\usr\\PIECE\\app");
	_chdrive(4);	//1=A,2=B,3=C,4=D,...	カレントドライブをD:にする。
	if(!glob("C:adpcm\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│C:adpcm\hello.c
//│C:adpcm\ose16.c
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定した相対パスで、途中にワイルドカードを使った例
void testR2() {
	glob_t g;
	_chdir("C:\\usr\\PIECE\\app");
	_chdrive(4);	//1=A,2=B,3=C,4=D,...	カレントドライブをD:にする。
	if(!glob("C:*\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│C:BlackWings\after.c
//│C:BlackWings\decode.c
//│～
//│C:adpcm\hello.c
//│C:adpcm\ose16.c
//│C:gamepad\gamepad.c
//│C:hello\hello.c
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しない相対パスの例
void testR3() {
	glob_t g;
	_chdir("\\usr\\PIECE\\app");
	if(!glob("adpcm\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│adpcm\hello.c
//│adpcm\ose16.c
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しない相対パスで、途中にワイルドカードを使った例
void testR4() {
	glob_t g;
	_chdir("\\usr\\PIECE\\app");
	if(!glob("*\\*.c", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│BlackWings\after.c
//│BlackWings\decode.c
//│～
//│adpcm\hello.c
//│adpcm\ose16.c
//│gamepad\gamepad.c
//│hello\hello.c
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■カレントフォルダ相対の例①
void testF1() {
	glob_t g;
	_chdir("\\usr\\PIECE\\app");
	if(!glob(".\\*", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│.\BlackWings
//│.\adpcm
//│.\block
//│.\date
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■カレントフォルダ相対の例②
void testF2() {
	glob_t g;
	_chdir("\\usr\\PIECE\\app");
	if(!glob("*", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│BlackWings
//│adpcm
//│block
//│date
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■親フォルダ相対の例
void testF3() {
	glob_t g;
	_chdir("\\usr\\PIECE\\app");
	if(!glob("..\\*", 0, NULL, &g)) {
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│..\DirectX8a
//│..\HTML
//│..\INDEX.HTM
//│..\Piece.inf
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定するルートフォルダの例①
void testG1() {
	glob_t g;
	if(!glob("C:\\", 0, NULL, &g)) {	//誤り。これではマッチしない。
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│(無し)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定するルートフォルダの例④
void testG2() {
	glob_t g;
	if(!glob("C:\\*", 0, NULL, &g)) {	//正しい。これならマッチする。
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│C:\$RECYCLE.BIN
//│C:\$SysReset
//│C:\Documents and Settings
//│C:\Home
//│～
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しないルートフォルダの例①
void testG3() {
	glob_t g;
	if(!glob("\\", 0, NULL, &g)) {	//誤り。これではマッチしない。
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│(無し)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//■ドライブを指定しないルートフォルダの例④
void testG4() {
	glob_t g;
	if(!glob("\\*", 0, NULL, &g)) {	//正しい。これならマッチする。
		int i;
		for(i = 0; i < (int)g.gl_pathc; i++) {
			puts(g.gl_pathv[i]);
		}
		globfree(&g);
	}
}
//□結果
//│\$RECYCLE.BIN
//│\$SysReset
//│\Documents and Settings
//│\Home
//│～
#endif
