1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
88 #include <Mayaqua/Mayaqua.h>
\r
90 static char exe_file_name[MAX_SIZE] = "/tmp/a.out";
\r
91 static wchar_t exe_file_name_w[MAX_SIZE] = L"/tmp/a.out";
\r
92 static LIST *hamcore = NULL;
\r
93 static IO *hamcore_io = NULL;
\r
97 bool SaveFileW(wchar_t *name, void *data, UINT size)
\r
101 if (name == NULL || (data == NULL && size != 0))
\r
106 io = FileCreateW(name);
\r
112 if (FileWrite(io, data, size) == false)
\r
122 bool SaveFile(char *name, void *data, UINT size)
\r
124 wchar_t *name_w = CopyStrToUni(name);
\r
125 bool ret = SaveFileW(name_w, data, size);
\r
132 // ファイルが存在するかどうか確認する
\r
133 bool IsFile(char *name)
\r
135 wchar_t *name_w = CopyStrToUni(name);
\r
136 bool ret = IsFileW(name_w);
\r
142 bool IsFileW(wchar_t *name)
\r
151 io = FileOpenExW(name, false, false);
\r
163 bool FileReplaceRename(char *old_name, char *new_name)
\r
165 wchar_t *old_name_w = CopyStrToUni(old_name);
\r
166 wchar_t *new_name_w = CopyStrToUni(new_name);
\r
167 bool ret = FileReplaceRenameW(old_name_w, new_name_w);
\r
174 bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name)
\r
177 if (old_name == NULL || new_name == NULL)
\r
182 if (FileCopyW(old_name, new_name) == false)
\r
187 FileDeleteW(old_name);
\r
193 void ConvertSafeFileName(char *dst, UINT size, char *src)
\r
197 if (dst == NULL || src == NULL)
\r
202 StrCpy(dst, size, src);
\r
203 for (i = 0;i < StrLen(dst);i++)
\r
205 if (IsSafeChar(dst[i]) == false)
\r
211 void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
\r
215 if (dst == NULL || src == NULL)
\r
220 UniStrCpy(dst, size, src);
\r
221 for (i = 0;i < UniStrLen(dst);i++)
\r
223 if (UniIsSafeChar(dst[i]) == false)
\r
231 bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
\r
241 ret = Win32GetDiskFree(path, free_size, used_size, total_size);
\r
243 ret = UnixGetDiskFree(path, free_size, used_size, total_size);
\r
248 bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
\r
258 ret = Win32GetDiskFreeW(path, free_size, used_size, total_size);
\r
260 ret = UnixGetDiskFreeW(path, free_size, used_size, total_size);
\r
267 DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
\r
269 wchar_t *dirname_w = CopyStrToUni(dirname);
\r
270 DIRLIST *ret = EnumDirExW(dirname_w, compare);
\r
276 DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare)
\r
280 if (dirname == NULL)
\r
285 if (compare == NULL)
\r
287 compare = CompareDirListByName;
\r
291 d = Win32EnumDirExW(dirname, compare);
\r
293 d = UnixEnumDirExW(dirname, compare);
\r
298 DIRLIST *EnumDir(char *dirname)
\r
300 return EnumDirEx(dirname, NULL);
\r
302 DIRLIST *EnumDirW(wchar_t *dirname)
\r
304 return EnumDirExW(dirname, NULL);
\r
308 int CompareDirListByName(void *p1, void *p2)
\r
311 if (p1 == NULL || p2 == NULL)
\r
315 d1 = *(DIRENT **)p1;
\r
316 d2 = *(DIRENT **)p2;
\r
317 if (d1 == NULL || d2 == NULL)
\r
321 return UniStrCmpi(d1->FileNameW, d2->FileNameW);
\r
325 void FreeDir(DIRLIST *d)
\r
334 for (i = 0;i < d->NumFiles;i++)
\r
336 DIRENT *f = d->File[i];
\r
338 Free(f->FileNameW);
\r
347 void UniSafeFileName(wchar_t *name)
\r
350 static wchar_t *danger_str = L"\\/:*?\"<>|";
\r
357 dlen = UniStrLen(danger_str);
\r
358 len = UniStrLen(name);
\r
360 for (i = 0;i < len;i++)
\r
362 wchar_t c = name[i];
\r
364 for (j = 0;j < dlen;j++)
\r
366 if (c == danger_str[j])
\r
374 void SafeFileNameW(wchar_t *name)
\r
376 UniSafeFileName(name);
\r
380 BUF *ReadHamcoreW(wchar_t *filename)
\r
382 char *filename_a = CopyUniToStr(filename);
\r
385 ret = ReadHamcore(filename_a);
\r
391 BUF *ReadHamcore(char *name)
\r
393 wchar_t tmp[MAX_SIZE];
\r
394 wchar_t exe_dir[MAX_SIZE];
\r
396 char filename[MAX_PATH];
\r
403 if (name[0] == '|')
\r
408 if (name[0] == '/' || name[0] == '\\')
\r
413 StrCpy(filename, sizeof(filename), name);
\r
415 ReplaceStrEx(filename, sizeof(filename), filename, "/", "\\", true);
\r
417 if (MayaquaIsMinimalMode())
\r
422 // ローカルディスクの hamcore/ ディレクトリにファイルがあればそれを読み込む
\r
423 GetExeDirW(exe_dir, sizeof(exe_dir));
\r
425 UniFormat(tmp, sizeof(tmp), L"%s/%S/%S", exe_dir, HAMCORE_DIR_NAME, filename);
\r
427 b = ReadDumpW(tmp);
\r
433 // 無い場合は HamCore ファイルシステムから探す
\r
439 Zero(&t, sizeof(t));
\r
440 t.FileName = filename;
\r
441 c = Search(hamcore, &t);
\r
451 if (c->Buffer != NULL)
\r
455 WriteBuf(b, c->Buffer, c->Size);
\r
457 c->LastAccess = Tick64();
\r
461 // 読み込まれていないのでファイルから読み込む
\r
462 if (FileSeek(hamcore_io, 0, c->Offset) == false)
\r
470 void *data = Malloc(c->SizeCompressed);
\r
471 if (FileRead(hamcore_io, data, c->SizeCompressed) == false)
\r
480 c->Buffer = ZeroMalloc(c->Size);
\r
481 if (Uncompress(c->Buffer, c->Size, data, c->SizeCompressed) != c->Size)
\r
493 WriteBuf(b, c->Buffer, c->Size);
\r
495 c->LastAccess = Tick64();
\r
502 // 有効期限の切れたキャッシュを削除する
\r
503 for (i = 0;i < LIST_NUM(hamcore);i++)
\r
505 HC *c = LIST_DATA(hamcore, i);
\r
507 if (c->Buffer != NULL)
\r
509 if (((c->LastAccess + HAMCORE_CACHE_EXPIRES) <= Tick64()) ||
\r
510 (StartWith(c->FileName, "Li")))
\r
518 UnlockList(hamcore);
\r
523 // HamCore ファイルシステムの初期化
\r
526 wchar_t tmp[MAX_PATH];
\r
527 wchar_t tmp2[MAX_PATH];
\r
528 wchar_t exe_dir[MAX_PATH];
\r
530 char header[HAMCORE_HEADER_SIZE];
\r
532 hamcore = NewList(CompareHamcore);
\r
534 if (MayaquaIsMinimalMode())
\r
539 GetExeDirW(exe_dir, sizeof(exe_dir));
\r
540 UniFormat(tmp, sizeof(tmp), L"%s/%S", exe_dir, HAMCORE_FILE_NAME);
\r
542 UniFormat(tmp2, sizeof(tmp2), L"%s/%S", exe_dir, HAMCORE_FILE_NAME_2);
\r
544 // _hamcore.utvpn がある場合は hamcore.utvpn に上書きする
\r
545 FileReplaceRenameW(tmp2, tmp);
\r
547 // hamcore.utvpn ファイルがあれば読み込む
\r
548 hamcore_io = FileOpenW(tmp, false);
\r
549 if (hamcore_io == NULL)
\r
553 UniFormat(tmp, sizeof(tmp), L"%S/%S", MsGetSystem32Dir(), HAMCORE_FILE_NAME);
\r
555 UniFormat(tmp, sizeof(tmp), L"/bin/%S", HAMCORE_FILE_NAME);
\r
558 hamcore_io = FileOpenW(tmp, false);
\r
559 if (hamcore_io == NULL)
\r
566 Zero(header, sizeof(header));
\r
567 FileRead(hamcore_io, header, HAMCORE_HEADER_SIZE);
\r
569 if (Cmp(header, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE) != 0)
\r
572 FileClose(hamcore_io);
\r
579 FileRead(hamcore_io, &num, sizeof(num));
\r
580 num = Endian32(num);
\r
581 for (i = 0;i < num;i++)
\r
584 char tmp[MAX_SIZE];
\r
588 FileRead(hamcore_io, &str_size, sizeof(str_size));
\r
589 str_size = Endian32(str_size);
\r
595 Zero(tmp, sizeof(tmp));
\r
596 FileRead(hamcore_io, tmp, str_size);
\r
598 c = ZeroMalloc(sizeof(HC));
\r
599 c->FileName = CopyStr(tmp);
\r
601 FileRead(hamcore_io, &c->Size, sizeof(UINT));
\r
602 c->Size = Endian32(c->Size);
\r
604 FileRead(hamcore_io, &c->SizeCompressed, sizeof(UINT));
\r
605 c->SizeCompressed = Endian32(c->SizeCompressed);
\r
607 FileRead(hamcore_io, &c->Offset, sizeof(UINT));
\r
608 c->Offset = Endian32(c->Offset);
\r
610 Insert(hamcore, c);
\r
614 // HamCore ファイルシステムの解放
\r
618 for (i = 0;i < LIST_NUM(hamcore);i++)
\r
620 HC *c = LIST_DATA(hamcore, i);
\r
622 if (c->Buffer != NULL)
\r
628 ReleaseList(hamcore);
\r
630 FileClose(hamcore_io);
\r
636 void BuildHamcore()
\r
639 char tmp[MAX_SIZE];
\r
640 char exe_dir[MAX_SIZE];
\r
646 GetExeDir(exe_dir, sizeof(exe_dir));
\r
647 Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_TEXT_NAME);
\r
652 Print("Failed to open %s.\n", tmp);
\r
656 o = NewListFast(CompareHamcore);
\r
658 while ((s = CfgReadNextLine(b)) != NULL)
\r
660 char tmp[MAX_SIZE];
\r
664 Format(tmp, sizeof(tmp), "%s/%s/%s", exe_dir, HAMCORE_DIR_NAME, s);
\r
669 Print("Failed to open %s.\n", s);
\r
674 HC *c = ZeroMalloc(sizeof(HC));
\r
677 c->FileName = CopyStr(s);
\r
679 tmp_size = CalcCompress(c->Size);
\r
680 tmp = Malloc(tmp_size);
\r
681 c->SizeCompressed = Compress(tmp, tmp_size, b->Buf, b->Size);
\r
684 Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);
\r
693 // 各ファイルのバッファのオフセットを計算する
\r
695 char tmp[MAX_SIZE];
\r
698 z += HAMCORE_HEADER_SIZE;
\r
702 for (i = 0;i < LIST_NUM(o);i++)
\r
704 HC *c = LIST_DATA(o, i);
\r
706 z += StrLen(c->FileName) + sizeof(UINT);
\r
714 for (i = 0;i < LIST_NUM(o);i++)
\r
716 HC *c = LIST_DATA(o, i);
\r
719 printf("%s: offset: %u\n", c->FileName, c->Offset);
\r
720 z += c->SizeCompressed;
\r
725 WriteBuf(b, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
\r
726 WriteBufInt(b, LIST_NUM(o));
\r
727 for (i = 0;i < LIST_NUM(o);i++)
\r
729 HC *c = LIST_DATA(o, i);
\r
731 WriteBufStr(b, c->FileName);
\r
733 WriteBufInt(b, c->Size);
\r
734 WriteBufInt(b, c->SizeCompressed);
\r
736 WriteBufInt(b, c->Offset);
\r
739 for (i = 0;i < LIST_NUM(o);i++)
\r
741 HC *c = LIST_DATA(o, i);
\r
742 WriteBuf(b, c->Buffer, c->SizeCompressed);
\r
745 Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_FILE_NAME "__");
\r
746 Print("Writing %s...\n", tmp);
\r
752 for (i = 0;i < LIST_NUM(o);i++)
\r
754 HC *c = LIST_DATA(o, i);
\r
766 int CompareHamcore(void *p1, void *p2)
\r
769 if (p1 == NULL || p2 == NULL)
\r
775 if (c1 == NULL || c2 == NULL)
\r
779 return StrCmpi(c1->FileName, c2->FileName);
\r
782 // EXE ファイルがあるディレクトリ名の取得
\r
783 void GetExeDir(char *name, UINT size)
\r
791 GetDirNameFromFilePath(name, size, exe_file_name);
\r
793 void GetExeDirW(wchar_t *name, UINT size)
\r
801 GetDirNameFromFilePathW(name, size, exe_file_name_w);
\r
805 void GetExeName(char *name, UINT size)
\r
813 StrCpy(name, size, exe_file_name);
\r
815 void GetExeNameW(wchar_t *name, UINT size)
\r
823 UniStrCpy(name, size, exe_file_name_w);
\r
827 void InitGetExeName(char *arg)
\r
829 wchar_t *arg_w = NULL;
\r
836 arg_w = CopyUtfToUni(arg);
\r
839 Win32GetExeNameW(exe_file_name_w, sizeof(exe_file_name_w));
\r
841 UnixGetExeNameW(exe_file_name_w, sizeof(exe_file_name_w), arg_w);
\r
844 UniToStr(exe_file_name, sizeof(exe_file_name), exe_file_name_w);
\r
849 // Unix における実行可能バイナリファイルのフルパスの取得
\r
850 void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg)
\r
854 wchar_t *path_str_w;
\r
857 if (name == NULL || arg == NULL)
\r
862 path_str = GetCurrentPathEnvStr();
\r
863 path_str_w = CopyUtfToUni(path_str);
\r
865 t = ParseSplitedPathW(path_str_w);
\r
870 for (i = 0;i < t->NumTokens;i++)
\r
872 wchar_t *s = t->Token[i];
\r
873 wchar_t tmp[MAX_SIZE];
\r
875 ConbinePathW(tmp, sizeof(tmp), s, arg);
\r
877 if (IsFileExistsInnerW(tmp))
\r
880 if (UnixCheckExecAccessW(tmp) == false)
\r
886 UniStrCpy(name, size, tmp);
\r
901 UnixGetCurrentDirW(name, size);
\r
903 Win32GetCurrentDirW(name, size);
\r
905 ConbinePathW(name, size, name, arg);
\r
910 void MakeSafeFileName(char *dst, UINT size, char *src)
\r
912 char tmp[MAX_PATH];
\r
914 if (dst == NULL || src == NULL)
\r
919 StrCpy(tmp, sizeof(tmp), src);
\r
920 ReplaceStrEx(tmp, sizeof(tmp), tmp, "..", "__", false);
\r
921 ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "_", false);
\r
922 ReplaceStrEx(tmp, sizeof(tmp), tmp, "\\", "_", false);
\r
923 ReplaceStrEx(tmp, sizeof(tmp), tmp, "@", "_", false);
\r
924 ReplaceStrEx(tmp, sizeof(tmp), tmp, "|", "_", false);
\r
926 StrCpy(dst, size, tmp);
\r
928 void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
\r
930 wchar_t tmp[MAX_PATH];
\r
932 if (dst == NULL || src == NULL)
\r
937 UniStrCpy(tmp, sizeof(tmp), src);
\r
938 UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"..", L"__", false);
\r
939 UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"/", L"_", false);
\r
940 UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"\\", L"_", false);
\r
941 UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"@", L"_", false);
\r
942 UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"|", L"_", false);
\r
944 UniStrCpy(dst, size, tmp);
\r
947 // ファイルパスからファイル名を取得する
\r
948 void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
\r
950 wchar_t tmp[MAX_SIZE];
\r
953 if (dst == NULL || filepath == NULL)
\r
958 len = MIN(UniStrLen(filepath), (MAX_SIZE - 2));
\r
961 for (i = 0;i < (len + 1);i++)
\r
963 wchar_t c = filepath[i];
\r
981 UniStrCpy(dst, size, tmp);
\r
983 void GetFileNameFromFilePath(char *dst, UINT size, char *filepath)
\r
985 char tmp[MAX_SIZE];
\r
988 if (dst == NULL || filepath == NULL)
\r
993 len = MIN(StrLen(filepath), (MAX_SIZE - 2));
\r
996 for (i = 0;i < (len + 1);i++)
\r
998 char c = filepath[i];
\r
1016 StrCpy(dst, size, tmp);
\r
1018 void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
\r
1020 wchar_t tmp[MAX_SIZE];
\r
1025 if (dst == NULL || filepath == NULL)
\r
1030 UniStrCpy(tmp, sizeof(tmp), filepath);
\r
1031 if (UniEndWith(tmp, L"\\") || UniEndWith(tmp, L"/"))
\r
1033 tmp[UniStrLen(tmp) - 1] = 0;
\r
1036 len = UniStrLen(tmp);
\r
1038 UniStrCpy(dst, size, L"");
\r
1042 for (i = 0;i < len;i++)
\r
1044 wchar_t c = tmp[i];
\r
1045 if (c == L'/' || c == L'\\')
\r
1049 UniStrCat(dst, size, tmp);
\r
1058 if (UniStrLen(dst) == 0)
\r
1060 UniStrCpy(dst, size, L"/");
\r
1063 NormalizePathW(dst, size, dst);
\r
1066 // ファイルパスからディレクトリ名を取得する
\r
1067 void GetDirNameFromFilePath(char *dst, UINT size, char *filepath)
\r
1069 char tmp[MAX_SIZE];
\r
1074 if (dst == NULL || filepath == NULL)
\r
1079 StrCpy(tmp, sizeof(tmp), filepath);
\r
1080 if (EndWith(tmp, "\\") || EndWith(tmp, "/"))
\r
1082 tmp[StrLen(tmp) - 1] = 0;
\r
1085 len = StrLen(tmp);
\r
1087 StrCpy(dst, size, "");
\r
1091 for (i = 0;i < len;i++)
\r
1094 if (c == '/' || c == '\\')
\r
1098 StrCat(dst, size, tmp);
\r
1107 if (StrLen(dst) == 0)
\r
1109 StrCpy(dst, size, "/");
\r
1112 NormalizePath(dst, size, dst);
\r
1116 void ConbinePath(char *dst, UINT size, char *dirname, char *filename)
\r
1118 wchar_t dst_w[MAX_PATH];
\r
1119 wchar_t *dirname_w = CopyStrToUni(dirname);
\r
1120 wchar_t *filename_w = CopyStrToUni(filename);
\r
1122 ConbinePathW(dst_w, sizeof(dst_w), dirname_w, filename_w);
\r
1127 UniToStr(dst, size, dst_w);
\r
1129 void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
\r
1131 bool is_full_path;
\r
1132 wchar_t tmp[MAX_SIZE];
\r
1133 wchar_t filename_ident[MAX_SIZE];
\r
1135 if (dst == NULL || dirname == NULL || filename == NULL)
\r
1140 NormalizePathW(filename_ident, sizeof(filename_ident), filename);
\r
1142 is_full_path = false;
\r
1144 if (UniStartWith(filename_ident, L"\\") || UniStartWith(filename_ident, L"/"))
\r
1146 is_full_path = true;
\r
1149 filename = &filename_ident[0];
\r
1152 if (UniStrLen(filename) >= 2)
\r
1154 if ((L'a' <= filename[0] && filename[0] <= L'z') || (L'A' <= filename[0] && filename[0] <= L'Z'))
\r
1156 if (filename[1] == L':')
\r
1158 is_full_path = true;
\r
1162 #endif // OS_WIN32
\r
1164 if (is_full_path == false)
\r
1166 UniStrCpy(tmp, sizeof(tmp), dirname);
\r
1167 if (UniEndWith(tmp, L"/") == false && UniEndWith(tmp, L"\\") == false)
\r
1169 UniStrCat(tmp, sizeof(tmp), L"/");
\r
1171 UniStrCat(tmp, sizeof(tmp), filename);
\r
1175 UniStrCpy(tmp, sizeof(tmp), filename);
\r
1178 NormalizePathW(dst, size, tmp);
\r
1180 void CombinePath(char *dst, UINT size, char *dirname, char *filename)
\r
1182 ConbinePath(dst, size, dirname, filename);
\r
1184 void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
\r
1186 ConbinePathW(dst, size, dirname, filename);
\r
1189 // ファイルが存在するかどうか確認する
\r
1190 bool IsFileExists(char *name)
\r
1192 wchar_t *name_w = CopyStrToUni(name);
\r
1193 bool ret = IsFileExistsW(name_w);
\r
1199 bool IsFileExistsW(wchar_t *name)
\r
1201 wchar_t tmp[MAX_SIZE];
\r
1208 InnerFilePathW(tmp, sizeof(tmp), name);
\r
1210 return IsFileExistsInnerW(tmp);
\r
1212 bool IsFileExistsInner(char *name)
\r
1214 wchar_t *name_w = CopyStrToUni(name);
\r
1215 bool ret = IsFileExistsInnerW(name_w);
\r
1221 bool IsFileExistsInnerW(wchar_t *name)
\r
1230 o = FileOpenInnerW(name, false, false);
\r
1241 // 現在の環境変数 PATH の内容を取得
\r
1242 char *GetCurrentPathEnvStr()
\r
1248 tag_name = "Path";
\r
1250 tag_name = "PATH";
\r
1251 #endif // OS_WIN32
\r
1253 if (GetEnv(tag_name, tmp, sizeof(tmp)) == false)
\r
1256 Win32GetCurrentDir(tmp, sizeof(tmp));
\r
1258 UnixGetCurrentDir(tmp, sizeof(tmp));
\r
1259 #endif // OS_WIN32
\r
1262 return CopyStr(tmp);
\r
1265 // コロン文字列で区切られた複数のパスを取得する
\r
1266 UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)
\r
1268 UNI_TOKEN_LIST *ret;
\r
1269 wchar_t *tmp = UniCopyStr(path);
\r
1270 wchar_t *split_str;
\r
1282 #endif // OS_WIN32
\r
1284 ret = UniParseToken(tmp, split_str);
\r
1288 for (i = 0;i < ret->NumTokens;i++)
\r
1290 UniTrim(ret->Token[i]);
\r
1291 UniTrimCrlf(ret->Token[i]);
\r
1292 UniTrim(ret->Token[i]);
\r
1293 UniTrimCrlf(ret->Token[i]);
\r
1301 TOKEN_LIST *ParseSplitedPath(char *path)
\r
1304 char *tmp = CopyStr(path);
\r
1317 #endif // OS_WIN32
\r
1319 ret = ParseToken(tmp, split_str);
\r
1323 for (i = 0;i < ret->NumTokens;i++)
\r
1325 Trim(ret->Token[i]);
\r
1326 TrimCrlf(ret->Token[i]);
\r
1327 Trim(ret->Token[i]);
\r
1328 TrimCrlf(ret->Token[i]);
\r
1338 void GetCurrentDirW(wchar_t *name, UINT size)
\r
1347 Win32GetCurrentDirW(name, size);
\r
1349 UnixGetCurrentDirW(name, size);
\r
1350 #endif // OS_WIN32
\r
1352 void GetCurrentDir(char *name, UINT size)
\r
1354 wchar_t name_w[MAX_PATH];
\r
1356 GetCurrentDirW(name_w, sizeof(name_w));
\r
1358 UniToStr(name, size, name_w);
\r
1362 void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
\r
1364 wchar_t tmp[MAX_SIZE];
\r
1365 UNI_TOKEN_LIST *t;
\r
1366 bool first_double_slash = false;
\r
1367 bool first_single_slash = false;
\r
1368 wchar_t win32_drive_char = 0;
\r
1369 bool is_full_path = false;
\r
1373 if (dst == NULL || src == 0)
\r
1378 // パスを変換する (Win32, UNIX 変換)
\r
1379 UniStrCpy(tmp, sizeof(tmp), src);
\r
1380 ConvertPathW(tmp);
\r
1383 // 先頭が "./" や "../" で始まっている場合はカレントディレクトリに置換する
\r
1384 if (UniStartWith(tmp, L"./") || UniStartWith(tmp, L".\\") ||
\r
1385 UniStartWith(tmp, L"../") || UniStartWith(tmp, L"..\\") ||
\r
1386 UniStrCmpi(tmp, L".") == 0 || UniStrCmpi(tmp, L"..") == 0)
\r
1388 wchar_t cd[MAX_SIZE];
\r
1389 Zero(cd, sizeof(cd));
\r
1392 Win32GetCurrentDirW(cd, sizeof(cd));
\r
1394 UnixGetCurrentDirW(cd, sizeof(cd));
\r
1395 #endif // OS_WIN32
\r
1397 if (UniStartWith(tmp, L".."))
\r
1399 UniStrCat(cd, sizeof(cd), L"/../");
\r
1400 UniStrCat(cd, sizeof(cd), tmp + 2);
\r
1404 UniStrCat(cd, sizeof(cd), L"/");
\r
1405 UniStrCat(cd, sizeof(cd), tmp);
\r
1408 UniStrCpy(tmp, sizeof(tmp), cd);
\r
1411 // 先頭が "~/" で始まっている場合はホームディレクトリに置換する
\r
1412 if (UniStartWith(tmp, L"~/") || UniStartWith(tmp, L"~\\"))
\r
1414 wchar_t tmp2[MAX_SIZE];
\r
1415 GetHomeDirW(tmp2, sizeof(tmp2));
\r
1416 UniStrCat(tmp2, sizeof(tmp2), L"/");
\r
1417 UniStrCat(tmp2, sizeof(tmp2), tmp + 2);
\r
1418 UniStrCpy(tmp, sizeof(tmp), tmp2);
\r
1421 if (UniStartWith(tmp, L"//") || UniStartWith(tmp, L"\\\\"))
\r
1423 // 最初が "//" または "\\" で始まる
\r
1424 first_double_slash = true;
\r
1425 is_full_path = true;
\r
1427 else if (UniStartWith(tmp, L"/") || UniStartWith(tmp, L"\\"))
\r
1430 first_single_slash = true;
\r
1431 is_full_path = true;
\r
1434 if (UniStrLen(tmp) >= 2)
\r
1436 if (tmp[1] == L':')
\r
1438 if (OS_IS_WINDOWS(GetOsInfo()->OsType))
\r
1440 // Win32 のドライブ文字列表記
\r
1441 wchar_t tmp2[MAX_SIZE];
\r
1442 is_full_path = true;
\r
1443 win32_drive_char = tmp[0];
\r
1444 UniStrCpy(tmp2, sizeof(tmp2), tmp + 2);
\r
1445 UniStrCpy(tmp, sizeof(tmp), tmp2);
\r
1450 if (UniStrLen(tmp) == 1 && (tmp[0] == L'/' || tmp[0] == L'\\'))
\r
1456 t = UniParseToken(tmp, L"/\\");
\r
1460 for (i = 0;i < t->NumTokens;i++)
\r
1462 wchar_t *s = t->Token[i];
\r
1464 if (UniStrCmpi(s, L".") == 0)
\r
1468 else if (UniStrCmpi(s, L"..") == 0)
\r
1470 if (sk->num_item >= 1 && (first_double_slash == false || sk->num_item >= 2))
\r
1482 UniStrCpy(tmp, sizeof(tmp), L"");
\r
1484 if (first_double_slash)
\r
1486 UniStrCat(tmp, sizeof(tmp), L"//");
\r
1488 else if (first_single_slash)
\r
1490 UniStrCat(tmp, sizeof(tmp), L"/");
\r
1493 if (win32_drive_char != 0)
\r
1496 d[0] = win32_drive_char;
\r
1498 UniStrCat(tmp, sizeof(tmp), d);
\r
1499 UniStrCat(tmp, sizeof(tmp), L":/");
\r
1502 for (i = 0;i < sk->num_item;i++)
\r
1504 UniStrCat(tmp, sizeof(tmp), (wchar_t *)sk->p[i]);
\r
1505 if (i != (sk->num_item - 1))
\r
1507 UniStrCat(tmp, sizeof(tmp), L"/");
\r
1515 ConvertPathW(tmp);
\r
1517 UniStrCpy(dst, size, tmp);
\r
1519 void NormalizePath(char *dst, UINT size, char *src)
\r
1521 wchar_t dst_w[MAX_SIZE];
\r
1522 wchar_t *src_w = CopyStrToUni(src);
\r
1524 NormalizePathW(dst_w, sizeof(dst_w), src_w);
\r
1528 UniToStr(dst, size, dst_w);
\r
1532 void FileCloseAndDelete(IO *o)
\r
1541 name = CopyUniStr(o->NameW);
\r
1544 FileDeleteW(name);
\r
1550 bool FileRename(char *old_name, char *new_name)
\r
1552 wchar_t *old_name_w = CopyStrToUni(old_name);
\r
1553 wchar_t *new_name_w = CopyStrToUni(new_name);
\r
1554 bool ret = FileRenameW(old_name_w, new_name_w);
\r
1561 bool FileRenameW(wchar_t *old_name, wchar_t *new_name)
\r
1563 wchar_t tmp1[MAX_SIZE];
\r
1564 wchar_t tmp2[MAX_SIZE];
\r
1566 if (old_name == NULL || new_name == NULL)
\r
1571 InnerFilePathW(tmp1, sizeof(tmp1), old_name);
\r
1572 InnerFilePathW(tmp2, sizeof(tmp2), new_name);
\r
1574 return FileRenameInnerW(tmp1, tmp2);
\r
1576 bool FileRenameInner(char *old_name, char *new_name)
\r
1578 wchar_t *old_name_w = CopyStrToUni(old_name);
\r
1579 wchar_t *new_name_w = CopyStrToUni(new_name);
\r
1580 bool ret = FileRenameInnerW(old_name_w, new_name_w);
\r
1587 bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name)
\r
1590 if (old_name == NULL || new_name == NULL)
\r
1595 return OSFileRenameW(old_name, new_name);
\r
1599 void ConvertPath(char *path)
\r
1602 #ifdef PATH_BACKSLASH
\r
1603 char new_char = '\\';
\r
1605 char new_char = '/';
\r
1608 len = StrLen(path);
\r
1609 for (i = 0;i < len;i++)
\r
1611 if (path[i] == '\\' || path[i] == '/')
\r
1613 path[i] = new_char;
\r
1617 void ConvertPathW(wchar_t *path)
\r
1620 #ifdef PATH_BACKSLASH
\r
1621 wchar_t new_char = L'\\';
\r
1623 wchar_t new_char = L'/';
\r
1626 len = UniStrLen(path);
\r
1627 for (i = 0;i < len;i++)
\r
1629 if (path[i] == L'\\' || path[i] == L'/')
\r
1631 path[i] = new_char;
\r
1637 bool DeleteDir(char *name)
\r
1639 wchar_t *name_w = CopyStrToUni(name);
\r
1640 bool ret = DeleteDirW(name_w);
\r
1646 bool DeleteDirW(wchar_t *name)
\r
1648 wchar_t tmp[MAX_SIZE];
\r
1655 InnerFilePathW(tmp, sizeof(tmp), name);
\r
1657 return DeleteDirInnerW(tmp);
\r
1659 bool DeleteDirInner(char *name)
\r
1661 wchar_t *name_w = CopyStrToUni(name);
\r
1662 bool ret = DeleteDirInnerW(name_w);
\r
1668 bool DeleteDirInnerW(wchar_t *name)
\r
1676 return OSDeleteDirW(name);
\r
1680 void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src)
\r
1683 if (dst == NULL || src == NULL)
\r
1688 if (src[0] != L'@')
\r
1690 NormalizePathW(dst, size, src);
\r
1694 wchar_t dir[MAX_SIZE];
\r
1695 GetExeDirW(dir, sizeof(dir));
\r
1696 ConbinePathW(dst, size, dir, &src[1]);
\r
1699 void InnerFilePath(char *dst, UINT size, char *src)
\r
1701 wchar_t dst_w[MAX_PATH];
\r
1702 wchar_t *src_w = CopyStrToUni(src);
\r
1704 InnerFilePathW(dst_w, sizeof(dst_w), src_w);
\r
1708 UniToStr(dst, size, dst_w);
\r
1712 void MakeDirEx(char *name)
\r
1714 wchar_t *name_w = CopyStrToUni(name);
\r
1716 MakeDirExW(name_w);
\r
1720 void MakeDirExW(wchar_t *name)
\r
1723 wchar_t tmp[MAX_PATH];
\r
1724 wchar_t tmp2[MAX_PATH];
\r
1732 o = NewListFast(NULL);
\r
1734 UniStrCpy(tmp, sizeof(tmp), name);
\r
1737 wchar_t *s = CopyUniStr(tmp);
\r
1741 GetDirNameFromFilePathW(tmp2, sizeof(tmp2), tmp);
\r
1743 if (UniStrCmpi(tmp2, tmp) == 0)
\r
1748 UniStrCpy(tmp, sizeof(tmp), tmp2);
\r
1751 for (i = 0;i < LIST_NUM(o);i++)
\r
1753 UINT j = LIST_NUM(o) - i - 1;
\r
1754 wchar_t *s = LIST_DATA(o, j);
\r
1756 if (UniStrCmpi(s, L"\\") != 0 && UniStrCmpi(s, L"/") != 0)
\r
1762 UniFreeStrList(o);
\r
1766 bool MakeDir(char *name)
\r
1768 wchar_t *name_w = CopyStrToUni(name);
\r
1769 bool ret = MakeDirW(name_w);
\r
1775 bool MakeDirW(wchar_t *name)
\r
1777 wchar_t tmp[MAX_SIZE];
\r
1784 InnerFilePathW(tmp, sizeof(tmp), name);
\r
1786 return MakeDirInnerW(tmp);
\r
1788 bool MakeDirInner(char *name)
\r
1790 wchar_t *name_w = CopyStrToUni(name);
\r
1791 bool ret = MakeDirInnerW(name_w);
\r
1797 bool MakeDirInnerW(wchar_t *name)
\r
1805 return OSMakeDirW(name);
\r
1809 bool FileDelete(char *name)
\r
1811 wchar_t *name_w = CopyStrToUni(name);
\r
1812 bool ret = FileDeleteW(name_w);
\r
1818 bool FileDeleteW(wchar_t *name)
\r
1820 wchar_t tmp[MAX_SIZE];
\r
1827 InnerFilePathW(tmp, sizeof(tmp), name);
\r
1829 return FileDeleteInnerW(tmp);
\r
1831 bool FileDeleteInner(char *name)
\r
1833 wchar_t *name_w = CopyStrToUni(name);
\r
1834 bool ret = FileDeleteInnerW(name_w);
\r
1840 bool FileDeleteInnerW(wchar_t *name)
\r
1842 wchar_t name2[MAX_SIZE];
\r
1849 UniStrCpy(name2, sizeof(name2), name);
\r
1850 ConvertPathW(name2);
\r
1852 return OSFileDeleteW(name2);
\r
1856 bool FileSeek(IO *o, UINT mode, int offset)
\r
1864 if (o->HamMode == false)
\r
1866 return OSFileSeek(o->pData, mode, offset);
\r
1874 // ファイル名を指定してファイルサイズを取得する
\r
1875 UINT FileSizeEx(char *name)
\r
1877 wchar_t *name_w = CopyStrToUni(name);
\r
1878 UINT ret = FileSizeExW(name_w);
\r
1884 UINT FileSizeExW(wchar_t *name)
\r
1894 io = FileOpenW(name, false);
\r
1900 size = FileSize(io);
\r
1908 UINT64 FileSize64(IO *o)
\r
1916 if (o->HamMode == false)
\r
1918 return OSFileSize(o->pData);
\r
1922 return (UINT64)o->HamBuf->Size;
\r
1925 UINT FileSize(IO *o)
\r
1927 UINT64 size = (UINT)(FileSize64(o));
\r
1929 if (size >= 4294967296ULL)
\r
1931 size = 4294967295ULL;
\r
1934 return (UINT)size;
\r
1938 bool FileRead(IO *o, void *buf, UINT size)
\r
1941 if (o == NULL || buf == NULL)
\r
1947 KS_INC(KS_IO_READ_COUNT);
\r
1948 KS_ADD(KS_IO_TOTAL_READ_SIZE, size);
\r
1955 if (o->HamMode == false)
\r
1957 return OSFileRead(o->pData, buf, size);
\r
1961 return ReadBuf(o->HamBuf, buf, size) == size ? true : false;
\r
1966 bool FileWrite(IO *o, void *buf, UINT size)
\r
1969 if (o == NULL || buf == NULL)
\r
1973 if (o->WriteMode == false)
\r
1979 KS_INC(KS_IO_WRITE_COUNT);
\r
1980 KS_ADD(KS_IO_TOTAL_WRITE_SIZE, size);
\r
1987 return OSFileWrite(o->pData, buf, size);
\r
1991 void FileFlush(IO *o)
\r
2004 OSFileFlush(o->pData);
\r
2008 void FileClose(IO *o)
\r
2010 FileCloseEx(o, false);
\r
2012 void FileCloseEx(IO *o, bool no_flush)
\r
2020 if (o->HamMode == false)
\r
2022 OSFileClose(o->pData, no_flush);
\r
2026 FreeBuf(o->HamBuf);
\r
2031 KS_INC(KS_IO_CLOSE_COUNT);
\r
2035 IO *FileCreateInner(char *name)
\r
2037 wchar_t *name_w = CopyStrToUni(name);
\r
2038 IO *ret = FileCreateInnerW(name_w);
\r
2044 IO *FileCreateInnerW(wchar_t *name)
\r
2048 wchar_t name2[MAX_SIZE];
\r
2055 UniStrCpy(name2, sizeof(name2), name);
\r
2056 ConvertPathW(name2);
\r
2058 p = OSFileCreateW(name2);
\r
2064 o = ZeroMalloc(sizeof(IO));
\r
2066 UniStrCpy(o->NameW, sizeof(o->NameW), name2);
\r
2067 UniToStr(o->Name, sizeof(o->Name), o->NameW);
\r
2068 o->WriteMode = true;
\r
2071 KS_INC(KS_IO_CREATE_COUNT);
\r
2075 IO *FileCreate(char *name)
\r
2077 wchar_t *name_w = CopyStrToUni(name);
\r
2078 IO *ret = FileCreateW(name_w);
\r
2084 IO *FileCreateW(wchar_t *name)
\r
2086 wchar_t tmp[MAX_SIZE];
\r
2093 InnerFilePathW(tmp, sizeof(tmp), name);
\r
2095 return FileCreateInnerW(tmp);
\r
2098 // ファイルにすべてのデータを書き込む
\r
2099 bool FileWriteAll(char *name, void *data, UINT size)
\r
2103 if (name == NULL || (data == NULL && size != 0))
\r
2108 io = FileCreate(name);
\r
2115 FileWrite(io, data, size);
\r
2121 bool FileWriteAllW(wchar_t *name, void *data, UINT size)
\r
2125 if (name == NULL || (data == NULL && size != 0))
\r
2130 io = FileCreateW(name);
\r
2137 FileWrite(io, data, size);
\r
2145 IO *FileOpenInner(char *name, bool write_mode, bool read_lock)
\r
2147 wchar_t *name_w = CopyStrToUni(name);
\r
2148 IO *ret = FileOpenInnerW(name_w, write_mode, read_lock);
\r
2154 IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock)
\r
2158 wchar_t name2[MAX_SIZE];
\r
2165 UniStrCpy(name2, sizeof(name2), name);
\r
2166 ConvertPathW(name2);
\r
2168 p = OSFileOpenW(name2, write_mode, read_lock);
\r
2174 o = ZeroMalloc(sizeof(IO));
\r
2176 UniStrCpy(o->NameW, sizeof(o->NameW), name2);
\r
2177 UniToStr(o->Name, sizeof(o->Name), o->NameW);
\r
2178 o->WriteMode = write_mode;
\r
2181 KS_INC(KS_IO_OPEN_COUNT);
\r
2185 IO *FileOpen(char *name, bool write_mode)
\r
2187 return FileOpenEx(name, write_mode, true);
\r
2189 IO *FileOpenW(wchar_t *name, bool write_mode)
\r
2191 return FileOpenExW(name, write_mode, true);
\r
2193 IO *FileOpenEx(char *name, bool write_mode, bool read_lock)
\r
2195 wchar_t *name_w = CopyStrToUni(name);
\r
2196 IO *ret = FileOpenExW(name_w, write_mode, read_lock);
\r
2202 IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock)
\r
2204 wchar_t tmp[MAX_SIZE];
\r
2211 InnerFilePathW(tmp, sizeof(tmp), name);
\r
2213 if (name[0] == L'|')
\r
2215 IO *o = ZeroMalloc(sizeof(IO));
\r
2217 UniStrCpy(o->NameW, sizeof(o->NameW), name);
\r
2218 UniToStr(o->Name, sizeof(o->Name), o->NameW);
\r
2219 o->HamMode = true;
\r
2220 o->HamBuf = ReadHamcoreW(name);
\r
2221 if (o->HamBuf == NULL)
\r
2230 return FileOpenInnerW(tmp, write_mode, read_lock);
\r