* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / FileIO.c
1 // SoftEther UT-VPN SourceCode\r
2 // \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
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \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
13 // \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
18 // \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
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \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
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // FileIO.c\r
79 // ファイル入出力コード\r
80 \r
81 #include <stdio.h>\r
82 #include <stdlib.h>\r
83 #include <string.h>\r
84 #include <wchar.h>\r
85 #include <stdarg.h>\r
86 #include <time.h>\r
87 #include <errno.h>\r
88 #include <Mayaqua/Mayaqua.h>\r
89 \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
94 \r
95 \r
96 // ファイルを保存する\r
97 bool SaveFileW(wchar_t *name, void *data, UINT size)\r
98 {\r
99         IO *io;\r
100         // 引数チェック\r
101         if (name == NULL || (data == NULL && size != 0))\r
102         {\r
103                 return false;\r
104         }\r
105 \r
106         io = FileCreateW(name);\r
107         if (io == NULL)\r
108         {\r
109                 return false;\r
110         }\r
111 \r
112         if (FileWrite(io, data, size) == false)\r
113         {\r
114                 FileClose(io);\r
115                 return false;\r
116         }\r
117 \r
118         FileClose(io);\r
119 \r
120         return true;\r
121 }\r
122 bool SaveFile(char *name, void *data, UINT size)\r
123 {\r
124         wchar_t *name_w = CopyStrToUni(name);\r
125         bool ret = SaveFileW(name_w, data, size);\r
126 \r
127         Free(name_w);\r
128 \r
129         return ret;\r
130 }\r
131 \r
132 // ファイルが存在するかどうか確認する\r
133 bool IsFile(char *name)\r
134 {\r
135         wchar_t *name_w = CopyStrToUni(name);\r
136         bool ret = IsFileW(name_w);\r
137 \r
138         Free(name_w);\r
139 \r
140         return ret;\r
141 }\r
142 bool IsFileW(wchar_t *name)\r
143 {\r
144         IO *io;\r
145         // 引数チェック\r
146         if (name == NULL)\r
147         {\r
148                 return false;\r
149         }\r
150 \r
151         io = FileOpenExW(name, false, false);\r
152         if (io == NULL)\r
153         {\r
154                 return false;\r
155         }\r
156 \r
157         FileClose(io);\r
158 \r
159         return true;\r
160 }\r
161 \r
162 // ファイルを置換してリネームする\r
163 bool FileReplaceRename(char *old_name, char *new_name)\r
164 {\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
168 \r
169         Free(old_name_w);\r
170         Free(new_name_w);\r
171 \r
172         return ret;\r
173 }\r
174 bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name)\r
175 {\r
176         // 引数チェック\r
177         if (old_name == NULL || new_name == NULL)\r
178         {\r
179                 return false;\r
180         }\r
181 \r
182         if (FileCopyW(old_name, new_name) == false)\r
183         {\r
184                 return false;\r
185         }\r
186 \r
187         FileDeleteW(old_name);\r
188 \r
189         return true;\r
190 }\r
191 \r
192 // ファイル名を安全な名前にする\r
193 void ConvertSafeFileName(char *dst, UINT size, char *src)\r
194 {\r
195         UINT i;\r
196         // 引数チェック\r
197         if (dst == NULL || src == NULL)\r
198         {\r
199                 return;\r
200         }\r
201 \r
202         StrCpy(dst, size, src);\r
203         for (i = 0;i < StrLen(dst);i++)\r
204         {\r
205                 if (IsSafeChar(dst[i]) == false)\r
206                 {\r
207                         dst[i] = '_';\r
208                 }\r
209         }\r
210 }\r
211 void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)\r
212 {\r
213         UINT i;\r
214         // 引数チェック\r
215         if (dst == NULL || src == NULL)\r
216         {\r
217                 return;\r
218         }\r
219 \r
220         UniStrCpy(dst, size, src);\r
221         for (i = 0;i < UniStrLen(dst);i++)\r
222         {\r
223                 if (UniIsSafeChar(dst[i]) == false)\r
224                 {\r
225                         dst[i] = L'_';\r
226                 }\r
227         }\r
228 }\r
229 \r
230 // ディスクの空き容量を取得する\r
231 bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)\r
232 {\r
233         bool ret;\r
234         // 引数チェック\r
235         if (path == NULL)\r
236         {\r
237                 path = "./";\r
238         }\r
239 \r
240 #ifdef  OS_WIN32\r
241         ret = Win32GetDiskFree(path, free_size, used_size, total_size);\r
242 #else   // OS_WIN32\r
243         ret = UnixGetDiskFree(path, free_size, used_size, total_size);\r
244 #endif  // OS_WIN32\r
245 \r
246         return ret;\r
247 }\r
248 bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)\r
249 {\r
250         bool ret;\r
251         // 引数チェック\r
252         if (path == NULL)\r
253         {\r
254                 path = L"./";\r
255         }\r
256 \r
257 #ifdef  OS_WIN32\r
258         ret = Win32GetDiskFreeW(path, free_size, used_size, total_size);\r
259 #else   // OS_WIN32\r
260         ret = UnixGetDiskFreeW(path, free_size, used_size, total_size);\r
261 #endif  // OS_WIN32\r
262 \r
263         return ret;\r
264 }\r
265 \r
266 // ディレクトリの列挙\r
267 DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)\r
268 {\r
269         wchar_t *dirname_w = CopyStrToUni(dirname);\r
270         DIRLIST *ret = EnumDirExW(dirname_w, compare);\r
271 \r
272         Free(dirname_w);\r
273 \r
274         return ret;\r
275 }\r
276 DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare)\r
277 {\r
278         DIRLIST *d = NULL;\r
279         // 引数チェック\r
280         if (dirname == NULL)\r
281         {\r
282                 dirname = L"./";\r
283         }\r
284 \r
285         if (compare == NULL)\r
286         {\r
287                 compare = CompareDirListByName;\r
288         }\r
289 \r
290 #ifdef  OS_WIN32\r
291         d = Win32EnumDirExW(dirname, compare);\r
292 #else   // OS_WIN32\r
293         d = UnixEnumDirExW(dirname, compare);\r
294 #endif  // OS_WIN32\r
295 \r
296         return d;\r
297 }\r
298 DIRLIST *EnumDir(char *dirname)\r
299 {\r
300         return EnumDirEx(dirname, NULL);\r
301 }\r
302 DIRLIST *EnumDirW(wchar_t *dirname)\r
303 {\r
304         return EnumDirExW(dirname, NULL);\r
305 }\r
306 \r
307 // DIRLIST リストの比較\r
308 int CompareDirListByName(void *p1, void *p2)\r
309 {\r
310         DIRENT *d1, *d2;\r
311         if (p1 == NULL || p2 == NULL)\r
312         {\r
313                 return 0;\r
314         }\r
315         d1 = *(DIRENT **)p1;\r
316         d2 = *(DIRENT **)p2;\r
317         if (d1 == NULL || d2 == NULL)\r
318         {\r
319                 return 0;\r
320         }\r
321         return UniStrCmpi(d1->FileNameW, d2->FileNameW);\r
322 }\r
323 \r
324 // ディレクトリ列挙の解放\r
325 void FreeDir(DIRLIST *d)\r
326 {\r
327         UINT i;\r
328         // 引数チェック\r
329         if (d == NULL)\r
330         {\r
331                 return;\r
332         }\r
333 \r
334         for (i = 0;i < d->NumFiles;i++)\r
335         {\r
336                 DIRENT *f = d->File[i];\r
337                 Free(f->FileName);\r
338                 Free(f->FileNameW);\r
339                 Free(f);\r
340         }\r
341         Free(d->File);\r
342         Free(d);\r
343 }\r
344 \r
345 \r
346 // ファイル名を安全にする\r
347 void UniSafeFileName(wchar_t *name)\r
348 {\r
349         UINT i, len, dlen;\r
350         static wchar_t *danger_str = L"\\/:*?\"<>|";\r
351         // 引数チェック\r
352         if (name == NULL)\r
353         {\r
354                 return;\r
355         }\r
356 \r
357         dlen = UniStrLen(danger_str);\r
358         len = UniStrLen(name);\r
359 \r
360         for (i = 0;i < len;i++)\r
361         {\r
362                 wchar_t c = name[i];\r
363                 UINT j;\r
364                 for (j = 0;j < dlen;j++)\r
365                 {\r
366                         if (c == danger_str[j])\r
367                         {\r
368                                 c = L'_';\r
369                         }\r
370                 }\r
371                 name[i] = c;\r
372         }\r
373 }\r
374 void SafeFileNameW(wchar_t *name)\r
375 {\r
376         UniSafeFileName(name);\r
377 }\r
378 \r
379 // HamCore の読み込み\r
380 BUF *ReadHamcoreW(wchar_t *filename)\r
381 {\r
382         char *filename_a = CopyUniToStr(filename);\r
383         BUF *ret;\r
384 \r
385         ret = ReadHamcore(filename_a);\r
386 \r
387         Free(filename_a);\r
388 \r
389         return ret;\r
390 }\r
391 BUF *ReadHamcore(char *name)\r
392 {\r
393         wchar_t tmp[MAX_SIZE];\r
394         wchar_t exe_dir[MAX_SIZE];\r
395         BUF *b;\r
396         char filename[MAX_PATH];\r
397         // 引数チェック\r
398         if (name == NULL)\r
399         {\r
400                 return NULL;\r
401         }\r
402 \r
403         if (name[0] == '|')\r
404         {\r
405                 name++;\r
406         }\r
407 \r
408         if (name[0] == '/' || name[0] == '\\')\r
409         {\r
410                 name++;\r
411         }\r
412 \r
413         StrCpy(filename, sizeof(filename), name);\r
414 \r
415         ReplaceStrEx(filename, sizeof(filename), filename, "/", "\\", true);\r
416 \r
417         if (MayaquaIsMinimalMode())\r
418         {\r
419                 return NULL;\r
420         }\r
421 \r
422         // ローカルディスクの hamcore/ ディレクトリにファイルがあればそれを読み込む\r
423         GetExeDirW(exe_dir, sizeof(exe_dir));\r
424 \r
425         UniFormat(tmp, sizeof(tmp), L"%s/%S/%S", exe_dir, HAMCORE_DIR_NAME, filename);\r
426 \r
427         b = ReadDumpW(tmp);\r
428         if (b != NULL)\r
429         {\r
430                 return b;\r
431         }\r
432 \r
433         // 無い場合は HamCore ファイルシステムから探す\r
434         LockList(hamcore);\r
435         {\r
436                 HC t, *c;\r
437                 UINT i;\r
438 \r
439                 Zero(&t, sizeof(t));\r
440                 t.FileName = filename;\r
441                 c = Search(hamcore, &t);\r
442 \r
443                 if (c == NULL)\r
444                 {\r
445                         // ファイルが存在しない\r
446                         b = NULL;\r
447                 }\r
448                 else\r
449                 {\r
450                         // ファイルが存在する\r
451                         if (c->Buffer != NULL)\r
452                         {\r
453                                 // 既に読み込まれている\r
454                                 b = NewBuf();\r
455                                 WriteBuf(b, c->Buffer, c->Size);\r
456                                 SeekBuf(b, 0, 0);\r
457                                 c->LastAccess = Tick64();\r
458                         }\r
459                         else\r
460                         {\r
461                                 // 読み込まれていないのでファイルから読み込む\r
462                                 if (FileSeek(hamcore_io, 0, c->Offset) == false)\r
463                                 {\r
464                                         // シークに失敗した\r
465                                         b = NULL;\r
466                                 }\r
467                                 else\r
468                                 {\r
469                                         // 圧縮データを読み込む\r
470                                         void *data = Malloc(c->SizeCompressed);\r
471                                         if (FileRead(hamcore_io, data, c->SizeCompressed) == false)\r
472                                         {\r
473                                                 // 読み込みに失敗した\r
474                                                 Free(data);\r
475                                                 b = NULL;\r
476                                         }\r
477                                         else\r
478                                         {\r
479                                                 // 展開する\r
480                                                 c->Buffer = ZeroMalloc(c->Size);\r
481                                                 if (Uncompress(c->Buffer, c->Size, data, c->SizeCompressed) != c->Size)\r
482                                                 {\r
483                                                         // 展開に失敗した\r
484                                                         Free(data);\r
485                                                         Free(c->Buffer);\r
486                                                         b = NULL;\r
487                                                 }\r
488                                                 else\r
489                                                 {\r
490                                                         // 成功した\r
491                                                         Free(data);\r
492                                                         b = NewBuf();\r
493                                                         WriteBuf(b, c->Buffer, c->Size);\r
494                                                         SeekBuf(b, 0, 0);\r
495                                                         c->LastAccess = Tick64();\r
496                                                 }\r
497                                         }\r
498                                 }\r
499                         }\r
500                 }\r
501 \r
502                 // 有効期限の切れたキャッシュを削除する\r
503                 for (i = 0;i < LIST_NUM(hamcore);i++)\r
504                 {\r
505                         HC *c = LIST_DATA(hamcore, i);\r
506 \r
507                         if (c->Buffer != NULL)\r
508                         {\r
509                                 if (((c->LastAccess + HAMCORE_CACHE_EXPIRES) <= Tick64()) ||\r
510                                         (StartWith(c->FileName, "Li")))\r
511                                 {\r
512                                         Free(c->Buffer);\r
513                                         c->Buffer = NULL;\r
514                                 }\r
515                         }\r
516                 }\r
517         }\r
518         UnlockList(hamcore);\r
519 \r
520         return b;\r
521 }\r
522 \r
523 // HamCore ファイルシステムの初期化\r
524 void InitHamcore()\r
525 {\r
526         wchar_t tmp[MAX_PATH];\r
527         wchar_t tmp2[MAX_PATH];\r
528         wchar_t exe_dir[MAX_PATH];\r
529         UINT i, num;\r
530         char header[HAMCORE_HEADER_SIZE];\r
531 \r
532         hamcore = NewList(CompareHamcore);\r
533 \r
534         if (MayaquaIsMinimalMode())\r
535         {\r
536                 return;\r
537         }\r
538 \r
539         GetExeDirW(exe_dir, sizeof(exe_dir));\r
540         UniFormat(tmp, sizeof(tmp), L"%s/%S", exe_dir, HAMCORE_FILE_NAME);\r
541 \r
542         UniFormat(tmp2, sizeof(tmp2), L"%s/%S", exe_dir, HAMCORE_FILE_NAME_2);\r
543 \r
544         // _hamcore.utvpn がある場合は hamcore.utvpn に上書きする\r
545         FileReplaceRenameW(tmp2, tmp);\r
546 \r
547         // hamcore.utvpn ファイルがあれば読み込む\r
548         hamcore_io = FileOpenW(tmp, false);\r
549         if (hamcore_io == NULL)\r
550         {\r
551                 // 無い場合は別の場所を探す\r
552 #ifdef  OS_WIN32\r
553                 UniFormat(tmp, sizeof(tmp), L"%S/%S", MsGetSystem32Dir(), HAMCORE_FILE_NAME);\r
554 #else   // OS_WIN32\r
555                 UniFormat(tmp, sizeof(tmp), L"/bin/%S", HAMCORE_FILE_NAME);\r
556 #endif  // OS_WIN32\r
557 \r
558                 hamcore_io = FileOpenW(tmp, false);\r
559                 if (hamcore_io == NULL)\r
560                 {\r
561                         return;\r
562                 }\r
563         }\r
564 \r
565         // ファイルヘッダを読み込む\r
566         Zero(header, sizeof(header));\r
567         FileRead(hamcore_io, header, HAMCORE_HEADER_SIZE);\r
568 \r
569         if (Cmp(header, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE) != 0)\r
570         {\r
571                 // ヘッダ不正\r
572                 FileClose(hamcore_io);\r
573                 hamcore_io = NULL;\r
574                 return;\r
575         }\r
576 \r
577         // ファイル個数\r
578         num = 0;\r
579         FileRead(hamcore_io, &num, sizeof(num));\r
580         num = Endian32(num);\r
581         for (i = 0;i < num;i++)\r
582         {\r
583                 // ファイル名\r
584                 char tmp[MAX_SIZE];\r
585                 UINT str_size = 0;\r
586                 HC *c;\r
587 \r
588                 FileRead(hamcore_io, &str_size, sizeof(str_size));\r
589                 str_size = Endian32(str_size);\r
590                 if (str_size >= 1)\r
591                 {\r
592                         str_size--;\r
593                 }\r
594 \r
595                 Zero(tmp, sizeof(tmp));\r
596                 FileRead(hamcore_io, tmp, str_size);\r
597 \r
598                 c = ZeroMalloc(sizeof(HC));\r
599                 c->FileName = CopyStr(tmp);\r
600 \r
601                 FileRead(hamcore_io, &c->Size, sizeof(UINT));\r
602                 c->Size = Endian32(c->Size);\r
603 \r
604                 FileRead(hamcore_io, &c->SizeCompressed, sizeof(UINT));\r
605                 c->SizeCompressed = Endian32(c->SizeCompressed);\r
606 \r
607                 FileRead(hamcore_io, &c->Offset, sizeof(UINT));\r
608                 c->Offset = Endian32(c->Offset);\r
609 \r
610                 Insert(hamcore, c);\r
611         }\r
612 }\r
613 \r
614 // HamCore ファイルシステムの解放\r
615 void FreeHamcore()\r
616 {\r
617         UINT i;\r
618         for (i = 0;i < LIST_NUM(hamcore);i++)\r
619         {\r
620                 HC *c = LIST_DATA(hamcore, i);\r
621                 Free(c->FileName);\r
622                 if (c->Buffer != NULL)\r
623                 {\r
624                         Free(c->Buffer);\r
625                 }\r
626                 Free(c);\r
627         }\r
628         ReleaseList(hamcore);\r
629 \r
630         FileClose(hamcore_io);\r
631         hamcore_io = NULL;\r
632         hamcore = NULL;\r
633 }\r
634 \r
635 // Hamcore のビルド\r
636 void BuildHamcore()\r
637 {\r
638         BUF *b;\r
639         char tmp[MAX_SIZE];\r
640         char exe_dir[MAX_SIZE];\r
641         char *s;\r
642         bool ok = true;\r
643         LIST *o;\r
644         UINT i;\r
645 \r
646         GetExeDir(exe_dir, sizeof(exe_dir));\r
647         Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_TEXT_NAME);\r
648 \r
649         b = ReadDump(tmp);\r
650         if (b == NULL)\r
651         {\r
652                 Print("Failed to open %s.\n", tmp);\r
653                 return;\r
654         }\r
655 \r
656         o = NewListFast(CompareHamcore);\r
657 \r
658         while ((s = CfgReadNextLine(b)) != NULL)\r
659         {\r
660                 char tmp[MAX_SIZE];\r
661                 BUF *b;\r
662                 Trim(s);\r
663 \r
664                 Format(tmp, sizeof(tmp), "%s/%s/%s", exe_dir, HAMCORE_DIR_NAME, s);\r
665 \r
666                 b = ReadDump(tmp);\r
667                 if (b == NULL)\r
668                 {\r
669                         Print("Failed to open %s.\n", s);\r
670                         ok = false;\r
671                 }\r
672                 else\r
673                 {\r
674                         HC *c = ZeroMalloc(sizeof(HC));\r
675                         UINT tmp_size;\r
676                         void *tmp;\r
677                         c->FileName = CopyStr(s);\r
678                         c->Size = b->Size;\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
682                         c->Buffer = tmp;\r
683                         Insert(o, c);\r
684                         Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);\r
685                         FreeBuf(b);\r
686                 }\r
687 \r
688                 Free(s);\r
689         }\r
690 \r
691         if (ok)\r
692         {\r
693                 // 各ファイルのバッファのオフセットを計算する\r
694                 UINT i, z;\r
695                 char tmp[MAX_SIZE];\r
696                 BUF *b;\r
697                 z = 0;\r
698                 z += HAMCORE_HEADER_SIZE;\r
699                 // ファイルの個数\r
700                 z += sizeof(UINT);\r
701                 // まずファイルテーブル\r
702                 for (i = 0;i < LIST_NUM(o);i++)\r
703                 {\r
704                         HC *c = LIST_DATA(o, i);\r
705                         // ファイル名\r
706                         z += StrLen(c->FileName) + sizeof(UINT);\r
707                         // ファイルサイズ\r
708                         z += sizeof(UINT);\r
709                         z += sizeof(UINT);\r
710                         // オフセットデータ\r
711                         z += sizeof(UINT);\r
712                 }\r
713                 // ファイル本体\r
714                 for (i = 0;i < LIST_NUM(o);i++)\r
715                 {\r
716                         HC *c = LIST_DATA(o, i);\r
717                         // バッファ本体\r
718                         c->Offset = z;\r
719                         printf("%s: offset: %u\n", c->FileName, c->Offset);\r
720                         z += c->SizeCompressed;\r
721                 }\r
722                 // 書き込み\r
723                 b = NewBuf();\r
724                 // ヘッダ\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
728                 {\r
729                         HC *c = LIST_DATA(o, i);\r
730                         // ファイル名\r
731                         WriteBufStr(b, c->FileName);\r
732                         // ファイルサイズ\r
733                         WriteBufInt(b, c->Size);\r
734                         WriteBufInt(b, c->SizeCompressed);\r
735                         // オフセット\r
736                         WriteBufInt(b, c->Offset);\r
737                 }\r
738                 // 本体\r
739                 for (i = 0;i < LIST_NUM(o);i++)\r
740                 {\r
741                         HC *c = LIST_DATA(o, i);\r
742                         WriteBuf(b, c->Buffer, c->SizeCompressed);\r
743                 }\r
744                 // 書き込み\r
745                 Format(tmp, sizeof(tmp), "%s/%s", exe_dir, HAMCORE_FILE_NAME "__");\r
746                 Print("Writing %s...\n", tmp);\r
747                 FileDelete(tmp);\r
748                 DumpBuf(b, tmp);\r
749                 FreeBuf(b);\r
750         }\r
751 \r
752         for (i = 0;i < LIST_NUM(o);i++)\r
753         {\r
754                 HC *c = LIST_DATA(o, i);\r
755                 Free(c->Buffer);\r
756                 Free(c->FileName);\r
757                 Free(c);\r
758         }\r
759 \r
760         ReleaseList(o);\r
761 \r
762         FreeBuf(b);\r
763 }\r
764 \r
765 // HC の比較\r
766 int CompareHamcore(void *p1, void *p2)\r
767 {\r
768         HC *c1, *c2;\r
769         if (p1 == NULL || p2 == NULL)\r
770         {\r
771                 return 0;\r
772         }\r
773         c1 = *(HC **)p1;\r
774         c2 = *(HC **)p2;\r
775         if (c1 == NULL || c2 == NULL)\r
776         {\r
777                 return 0;\r
778         }\r
779         return StrCmpi(c1->FileName, c2->FileName);\r
780 }\r
781 \r
782 // EXE ファイルがあるディレクトリ名の取得\r
783 void GetExeDir(char *name, UINT size)\r
784 {\r
785         // 引数チェック\r
786         if (name == NULL)\r
787         {\r
788                 return;\r
789         }\r
790 \r
791         GetDirNameFromFilePath(name, size, exe_file_name);\r
792 }\r
793 void GetExeDirW(wchar_t *name, UINT size)\r
794 {\r
795         // 引数チェック\r
796         if (name == NULL)\r
797         {\r
798                 return;\r
799         }\r
800 \r
801         GetDirNameFromFilePathW(name, size, exe_file_name_w);\r
802 }\r
803 \r
804 // EXE ファイル名の取得\r
805 void GetExeName(char *name, UINT size)\r
806 {\r
807         // 引数チェック\r
808         if (name == NULL)\r
809         {\r
810                 return;\r
811         }\r
812 \r
813         StrCpy(name, size, exe_file_name);\r
814 }\r
815 void GetExeNameW(wchar_t *name, UINT size)\r
816 {\r
817         // 引数チェック\r
818         if (name == NULL)\r
819         {\r
820                 return;\r
821         }\r
822 \r
823         UniStrCpy(name, size, exe_file_name_w);\r
824 }\r
825 \r
826 // EXE ファイル名の取得初期化\r
827 void InitGetExeName(char *arg)\r
828 {\r
829         wchar_t *arg_w = NULL;\r
830         // 引数チェック\r
831         if (arg == NULL)\r
832         {\r
833                 arg = "./a.out";\r
834         }\r
835 \r
836         arg_w = CopyUtfToUni(arg);\r
837 \r
838 #ifdef  OS_WIN32\r
839         Win32GetExeNameW(exe_file_name_w, sizeof(exe_file_name_w));\r
840 #else   // OS_WIN32\r
841         UnixGetExeNameW(exe_file_name_w, sizeof(exe_file_name_w), arg_w);\r
842 #endif  // OS_WIN32\r
843 \r
844         UniToStr(exe_file_name, sizeof(exe_file_name), exe_file_name_w);\r
845 \r
846         Free(arg_w);\r
847 }\r
848 \r
849 // Unix における実行可能バイナリファイルのフルパスの取得\r
850 void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg)\r
851 {\r
852         UNI_TOKEN_LIST *t;\r
853         char *path_str;\r
854         wchar_t *path_str_w;\r
855         bool ok = false;\r
856         // 引数チェック\r
857         if (name == NULL || arg == NULL)\r
858         {\r
859                 return;\r
860         }\r
861 \r
862         path_str = GetCurrentPathEnvStr();\r
863         path_str_w = CopyUtfToUni(path_str);\r
864 \r
865         t = ParseSplitedPathW(path_str_w);\r
866 \r
867         if (t != NULL)\r
868         {\r
869                 UINT i;\r
870                 for (i = 0;i < t->NumTokens;i++)\r
871                 {\r
872                         wchar_t *s = t->Token[i];\r
873                         wchar_t tmp[MAX_SIZE];\r
874 \r
875                         ConbinePathW(tmp, sizeof(tmp), s, arg);\r
876 \r
877                         if (IsFileExistsInnerW(tmp))\r
878                         {\r
879 #ifdef  OS_UNIX\r
880                                 if (UnixCheckExecAccessW(tmp) == false)\r
881                                 {\r
882                                         continue;\r
883                                 }\r
884 #endif  // OS_UNIX\r
885                                 ok = true;\r
886                                 UniStrCpy(name, size, tmp);\r
887                                 break;\r
888                         }\r
889                 }\r
890 \r
891                 UniFreeToken(t);\r
892         }\r
893 \r
894         Free(path_str);\r
895         Free(path_str_w);\r
896 \r
897         if (ok == false)\r
898         {\r
899                 // パスの検索に失敗した場合\r
900 #ifdef  OS_UNIX\r
901                 UnixGetCurrentDirW(name, size);\r
902 #else   // OS_UNIX\r
903                 Win32GetCurrentDirW(name, size);\r
904 #endif  // OS_UNIX\r
905                 ConbinePathW(name, size, name, arg);\r
906         }\r
907 }\r
908 \r
909 // 安全なファイル名を生成する\r
910 void MakeSafeFileName(char *dst, UINT size, char *src)\r
911 {\r
912         char tmp[MAX_PATH];\r
913         // 引数チェック\r
914         if (dst == NULL || src == NULL)\r
915         {\r
916                 return;\r
917         }\r
918 \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
925 \r
926         StrCpy(dst, size, tmp);\r
927 }\r
928 void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)\r
929 {\r
930         wchar_t tmp[MAX_PATH];\r
931         // 引数チェック\r
932         if (dst == NULL || src == NULL)\r
933         {\r
934                 return;\r
935         }\r
936 \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
943 \r
944         UniStrCpy(dst, size, tmp);\r
945 }\r
946 \r
947 // ファイルパスからファイル名を取得する\r
948 void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)\r
949 {\r
950         wchar_t tmp[MAX_SIZE];\r
951         UINT i, len, wp;\r
952         // 引数チェック\r
953         if (dst == NULL || filepath == NULL)\r
954         {\r
955                 return;\r
956         }\r
957 \r
958         len = MIN(UniStrLen(filepath), (MAX_SIZE - 2));\r
959         wp = 0;\r
960 \r
961         for (i = 0;i < (len + 1);i++)\r
962         {\r
963                 wchar_t c = filepath[i];\r
964 \r
965                 switch (c)\r
966                 {\r
967                 case L'\\':\r
968                 case L'/':\r
969                 case 0:\r
970                         tmp[wp] = 0;\r
971                         wp = 0;\r
972                         break;\r
973 \r
974                 default:\r
975                         tmp[wp] = c;\r
976                         wp++;\r
977                         break;\r
978                 }\r
979         }\r
980 \r
981         UniStrCpy(dst, size, tmp);\r
982 }\r
983 void GetFileNameFromFilePath(char *dst, UINT size, char *filepath)\r
984 {\r
985         char tmp[MAX_SIZE];\r
986         UINT i, len, wp;\r
987         // 引数チェック\r
988         if (dst == NULL || filepath == NULL)\r
989         {\r
990                 return;\r
991         }\r
992 \r
993         len = MIN(StrLen(filepath), (MAX_SIZE - 2));\r
994         wp = 0;\r
995 \r
996         for (i = 0;i < (len + 1);i++)\r
997         {\r
998                 char c = filepath[i];\r
999 \r
1000                 switch (c)\r
1001                 {\r
1002                 case '\\':\r
1003                 case '/':\r
1004                 case 0:\r
1005                         tmp[wp] = 0;\r
1006                         wp = 0;\r
1007                         break;\r
1008 \r
1009                 default:\r
1010                         tmp[wp] = c;\r
1011                         wp++;\r
1012                         break;\r
1013                 }\r
1014         }\r
1015 \r
1016         StrCpy(dst, size, tmp);\r
1017 }\r
1018 void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)\r
1019 {\r
1020         wchar_t tmp[MAX_SIZE];\r
1021         UINT wp;\r
1022         UINT i;\r
1023         UINT len;\r
1024         // 引数チェック\r
1025         if (dst == NULL || filepath == NULL)\r
1026         {\r
1027                 return;\r
1028         }\r
1029 \r
1030         UniStrCpy(tmp, sizeof(tmp), filepath);\r
1031         if (UniEndWith(tmp, L"\\") || UniEndWith(tmp, L"/"))\r
1032         {\r
1033                 tmp[UniStrLen(tmp) - 1] = 0;\r
1034         }\r
1035 \r
1036         len = UniStrLen(tmp);\r
1037 \r
1038         UniStrCpy(dst, size, L"");\r
1039 \r
1040         wp = 0;\r
1041 \r
1042         for (i = 0;i < len;i++)\r
1043         {\r
1044                 wchar_t c = tmp[i];\r
1045                 if (c == L'/' || c == L'\\')\r
1046                 {\r
1047                         tmp[wp++] = 0;\r
1048                         wp = 0;\r
1049                         UniStrCat(dst, size, tmp);\r
1050                         tmp[wp++] = c;\r
1051                 }\r
1052                 else\r
1053                 {\r
1054                         tmp[wp++] = c;\r
1055                 }\r
1056         }\r
1057 \r
1058         if (UniStrLen(dst) == 0)\r
1059         {\r
1060                 UniStrCpy(dst, size, L"/");\r
1061         }\r
1062 \r
1063         NormalizePathW(dst, size, dst);\r
1064 }\r
1065 \r
1066 // ファイルパスからディレクトリ名を取得する\r
1067 void GetDirNameFromFilePath(char *dst, UINT size, char *filepath)\r
1068 {\r
1069         char tmp[MAX_SIZE];\r
1070         UINT wp;\r
1071         UINT i;\r
1072         UINT len;\r
1073         // 引数チェック\r
1074         if (dst == NULL || filepath == NULL)\r
1075         {\r
1076                 return;\r
1077         }\r
1078 \r
1079         StrCpy(tmp, sizeof(tmp), filepath);\r
1080         if (EndWith(tmp, "\\") || EndWith(tmp, "/"))\r
1081         {\r
1082                 tmp[StrLen(tmp) - 1] = 0;\r
1083         }\r
1084 \r
1085         len = StrLen(tmp);\r
1086 \r
1087         StrCpy(dst, size, "");\r
1088 \r
1089         wp = 0;\r
1090 \r
1091         for (i = 0;i < len;i++)\r
1092         {\r
1093                 char c = tmp[i];\r
1094                 if (c == '/' || c == '\\')\r
1095                 {\r
1096                         tmp[wp++] = 0;\r
1097                         wp = 0;\r
1098                         StrCat(dst, size, tmp);\r
1099                         tmp[wp++] = c;\r
1100                 }\r
1101                 else\r
1102                 {\r
1103                         tmp[wp++] = c;\r
1104                 }\r
1105         }\r
1106 \r
1107         if (StrLen(dst) == 0)\r
1108         {\r
1109                 StrCpy(dst, size, "/");\r
1110         }\r
1111 \r
1112         NormalizePath(dst, size, dst);\r
1113 }\r
1114 \r
1115 // 2 つのパスを結合する\r
1116 void ConbinePath(char *dst, UINT size, char *dirname, char *filename)\r
1117 {\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
1121 \r
1122         ConbinePathW(dst_w, sizeof(dst_w), dirname_w, filename_w);\r
1123 \r
1124         Free(dirname_w);\r
1125         Free(filename_w);\r
1126 \r
1127         UniToStr(dst, size, dst_w);\r
1128 }\r
1129 void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)\r
1130 {\r
1131         bool is_full_path;\r
1132         wchar_t tmp[MAX_SIZE];\r
1133         wchar_t filename_ident[MAX_SIZE];\r
1134         // 引数チェック\r
1135         if (dst == NULL || dirname == NULL || filename == NULL)\r
1136         {\r
1137                 return;\r
1138         }\r
1139 \r
1140         NormalizePathW(filename_ident, sizeof(filename_ident), filename);\r
1141 \r
1142         is_full_path = false;\r
1143 \r
1144         if (UniStartWith(filename_ident, L"\\") || UniStartWith(filename_ident, L"/"))\r
1145         {\r
1146                 is_full_path = true;\r
1147         }\r
1148 \r
1149         filename = &filename_ident[0];\r
1150 \r
1151 #ifdef  OS_WIN32\r
1152         if (UniStrLen(filename) >= 2)\r
1153         {\r
1154                 if ((L'a' <= filename[0] && filename[0] <= L'z') || (L'A' <= filename[0] && filename[0] <= L'Z'))\r
1155                 {\r
1156                         if (filename[1] == L':')\r
1157                         {\r
1158                                 is_full_path = true;\r
1159                         }\r
1160                 }\r
1161         }\r
1162 #endif  // OS_WIN32\r
1163 \r
1164         if (is_full_path == false)\r
1165         {\r
1166                 UniStrCpy(tmp, sizeof(tmp), dirname);\r
1167                 if (UniEndWith(tmp, L"/") == false && UniEndWith(tmp, L"\\") == false)\r
1168                 {\r
1169                         UniStrCat(tmp, sizeof(tmp), L"/");\r
1170                 }\r
1171                 UniStrCat(tmp, sizeof(tmp), filename);\r
1172         }\r
1173         else\r
1174         {\r
1175                 UniStrCpy(tmp, sizeof(tmp), filename);\r
1176         }\r
1177 \r
1178         NormalizePathW(dst, size, tmp);\r
1179 }\r
1180 void CombinePath(char *dst, UINT size, char *dirname, char *filename)\r
1181 {\r
1182         ConbinePath(dst, size, dirname, filename);\r
1183 }\r
1184 void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)\r
1185 {\r
1186         ConbinePathW(dst, size, dirname, filename);\r
1187 }\r
1188 \r
1189 // ファイルが存在するかどうか確認する\r
1190 bool IsFileExists(char *name)\r
1191 {\r
1192         wchar_t *name_w = CopyStrToUni(name);\r
1193         bool ret = IsFileExistsW(name_w);\r
1194 \r
1195         Free(name_w);\r
1196 \r
1197         return ret;\r
1198 }\r
1199 bool IsFileExistsW(wchar_t *name)\r
1200 {\r
1201         wchar_t tmp[MAX_SIZE];\r
1202         // 引数チェック\r
1203         if (name == NULL)\r
1204         {\r
1205                 return false;\r
1206         }\r
1207 \r
1208         InnerFilePathW(tmp, sizeof(tmp), name);\r
1209 \r
1210         return IsFileExistsInnerW(tmp);\r
1211 }\r
1212 bool IsFileExistsInner(char *name)\r
1213 {\r
1214         wchar_t *name_w = CopyStrToUni(name);\r
1215         bool ret = IsFileExistsInnerW(name_w);\r
1216 \r
1217         Free(name_w);\r
1218 \r
1219         return ret;\r
1220 }\r
1221 bool IsFileExistsInnerW(wchar_t *name)\r
1222 {\r
1223         IO *o;\r
1224         // 引数チェック\r
1225         if (name == NULL)\r
1226         {\r
1227                 return false;\r
1228         }\r
1229 \r
1230         o = FileOpenInnerW(name, false, false);\r
1231         if (o == NULL)\r
1232         {\r
1233                 return false;\r
1234         }\r
1235 \r
1236         FileClose(o);\r
1237 \r
1238         return true;\r
1239 }\r
1240 \r
1241 // 現在の環境変数 PATH の内容を取得\r
1242 char *GetCurrentPathEnvStr()\r
1243 {\r
1244         char tmp[1024];\r
1245         char *tag_name;\r
1246 \r
1247 #ifdef  OS_WIN32\r
1248         tag_name = "Path";\r
1249 #else   // OS_WIN32\r
1250         tag_name = "PATH";\r
1251 #endif  // OS_WIN32\r
1252 \r
1253         if (GetEnv(tag_name, tmp, sizeof(tmp)) == false)\r
1254         {\r
1255 #ifdef  OS_WIN32\r
1256                 Win32GetCurrentDir(tmp, sizeof(tmp));\r
1257 #else   // OS_WIN32\r
1258                 UnixGetCurrentDir(tmp, sizeof(tmp));\r
1259 #endif  // OS_WIN32\r
1260         }\r
1261 \r
1262         return CopyStr(tmp);\r
1263 }\r
1264 \r
1265 // コロン文字列で区切られた複数のパスを取得する\r
1266 UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)\r
1267 {\r
1268         UNI_TOKEN_LIST *ret;\r
1269         wchar_t *tmp = UniCopyStr(path);\r
1270         wchar_t *split_str;\r
1271         UINT i;\r
1272 \r
1273         UniTrim(tmp);\r
1274         UniTrimCrlf(tmp);\r
1275         UniTrim(tmp);\r
1276         UniTrimCrlf(tmp);\r
1277 \r
1278 #ifdef  OS_WIN32\r
1279         split_str = L";";\r
1280 #else   // OS_WIN32\r
1281         split_str = L":";\r
1282 #endif  // OS_WIN32\r
1283 \r
1284         ret = UniParseToken(tmp, split_str);\r
1285 \r
1286         if (ret != NULL)\r
1287         {\r
1288                 for (i = 0;i < ret->NumTokens;i++)\r
1289                 {\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
1294                 }\r
1295         }\r
1296 \r
1297         Free(tmp);\r
1298 \r
1299         return ret;\r
1300 }\r
1301 TOKEN_LIST *ParseSplitedPath(char *path)\r
1302 {\r
1303         TOKEN_LIST *ret;\r
1304         char *tmp = CopyStr(path);\r
1305         char *split_str;\r
1306         UINT i;\r
1307 \r
1308         Trim(tmp);\r
1309         TrimCrlf(tmp);\r
1310         Trim(tmp);\r
1311         TrimCrlf(tmp);\r
1312 \r
1313 #ifdef  OS_WIN32\r
1314         split_str = ";";\r
1315 #else   // OS_WIN32\r
1316         split_str = ":";\r
1317 #endif  // OS_WIN32\r
1318 \r
1319         ret = ParseToken(tmp, split_str);\r
1320 \r
1321         if (ret != NULL)\r
1322         {\r
1323                 for (i = 0;i < ret->NumTokens;i++)\r
1324                 {\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
1329                 }\r
1330         }\r
1331 \r
1332         Free(tmp);\r
1333 \r
1334         return ret;\r
1335 }\r
1336 \r
1337 // 現在のディレクトリを取得する\r
1338 void GetCurrentDirW(wchar_t *name, UINT size)\r
1339 {\r
1340         // 引数チェック\r
1341         if (name == NULL)\r
1342         {\r
1343                 return;\r
1344         }\r
1345 \r
1346 #ifdef  OS_WIN32\r
1347         Win32GetCurrentDirW(name, size);\r
1348 #else   // OS_WIN32\r
1349         UnixGetCurrentDirW(name, size);\r
1350 #endif  // OS_WIN32\r
1351 }\r
1352 void GetCurrentDir(char *name, UINT size)\r
1353 {\r
1354         wchar_t name_w[MAX_PATH];\r
1355 \r
1356         GetCurrentDirW(name_w, sizeof(name_w));\r
1357 \r
1358         UniToStr(name, size, name_w);\r
1359 }\r
1360 \r
1361 // ファイルパスを正規化する\r
1362 void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)\r
1363 {\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
1370         UINT i;\r
1371         SK *sk;\r
1372         // 引数チェック\r
1373         if (dst == NULL || src == 0)\r
1374         {\r
1375                 return;\r
1376         }\r
1377 \r
1378         // パスを変換する (Win32, UNIX 変換)\r
1379         UniStrCpy(tmp, sizeof(tmp), src);\r
1380         ConvertPathW(tmp);\r
1381         UniTrim(tmp);\r
1382 \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
1387         {\r
1388                 wchar_t cd[MAX_SIZE];\r
1389                 Zero(cd, sizeof(cd));\r
1390 \r
1391 #ifdef  OS_WIN32\r
1392                 Win32GetCurrentDirW(cd, sizeof(cd));\r
1393 #else   // OS_WIN32\r
1394                 UnixGetCurrentDirW(cd, sizeof(cd));\r
1395 #endif  // OS_WIN32\r
1396 \r
1397                 if (UniStartWith(tmp, L".."))\r
1398                 {\r
1399                         UniStrCat(cd, sizeof(cd), L"/../");\r
1400                         UniStrCat(cd, sizeof(cd), tmp + 2);\r
1401                 }\r
1402                 else\r
1403                 {\r
1404                         UniStrCat(cd, sizeof(cd), L"/");\r
1405                         UniStrCat(cd, sizeof(cd), tmp);\r
1406                 }\r
1407 \r
1408                 UniStrCpy(tmp, sizeof(tmp), cd);\r
1409         }\r
1410 \r
1411         // 先頭が "~/" で始まっている場合はホームディレクトリに置換する\r
1412         if (UniStartWith(tmp, L"~/") || UniStartWith(tmp, L"~\\"))\r
1413         {\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
1419         }\r
1420 \r
1421         if (UniStartWith(tmp, L"//") || UniStartWith(tmp, L"\\\\"))\r
1422         {\r
1423                 // 最初が "//" または "\\" で始まる\r
1424                 first_double_slash = true;\r
1425                 is_full_path = true;\r
1426         }\r
1427         else if (UniStartWith(tmp, L"/") || UniStartWith(tmp, L"\\"))\r
1428         {\r
1429                 // 最初が "\" で始まる\r
1430                 first_single_slash = true;\r
1431                 is_full_path = true;\r
1432         }\r
1433 \r
1434         if (UniStrLen(tmp) >= 2)\r
1435         {\r
1436                 if (tmp[1] == L':')\r
1437                 {\r
1438                         if (OS_IS_WINDOWS(GetOsInfo()->OsType))\r
1439                         {\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
1446                         }\r
1447                 }\r
1448         }\r
1449 \r
1450         if (UniStrLen(tmp) == 1 && (tmp[0] == L'/' || tmp[0] == L'\\'))\r
1451         {\r
1452                 tmp[0] = 0;\r
1453         }\r
1454 \r
1455         // トークン分割\r
1456         t = UniParseToken(tmp, L"/\\");\r
1457 \r
1458         sk = NewSk();\r
1459 \r
1460         for (i = 0;i < t->NumTokens;i++)\r
1461         {\r
1462                 wchar_t *s = t->Token[i];\r
1463 \r
1464                 if (UniStrCmpi(s, L".") == 0)\r
1465                 {\r
1466                         continue;\r
1467                 }\r
1468                 else if (UniStrCmpi(s, L"..") == 0)\r
1469                 {\r
1470                         if (sk->num_item >= 1 && (first_double_slash == false || sk->num_item >= 2))\r
1471                         {\r
1472                                 Pop(sk);\r
1473                         }\r
1474                 }\r
1475                 else\r
1476                 {\r
1477                         Push(sk, s);\r
1478                 }\r
1479         }\r
1480 \r
1481         // トークン結合\r
1482         UniStrCpy(tmp, sizeof(tmp), L"");\r
1483 \r
1484         if (first_double_slash)\r
1485         {\r
1486                 UniStrCat(tmp, sizeof(tmp), L"//");\r
1487         }\r
1488         else if (first_single_slash)\r
1489         {\r
1490                 UniStrCat(tmp, sizeof(tmp), L"/");\r
1491         }\r
1492 \r
1493         if (win32_drive_char != 0)\r
1494         {\r
1495                 wchar_t d[2];\r
1496                 d[0] = win32_drive_char;\r
1497                 d[1] = 0;\r
1498                 UniStrCat(tmp, sizeof(tmp), d);\r
1499                 UniStrCat(tmp, sizeof(tmp), L":/");\r
1500         }\r
1501 \r
1502         for (i = 0;i < sk->num_item;i++)\r
1503         {\r
1504                 UniStrCat(tmp, sizeof(tmp), (wchar_t *)sk->p[i]);\r
1505                 if (i != (sk->num_item - 1))\r
1506                 {\r
1507                         UniStrCat(tmp, sizeof(tmp), L"/");\r
1508                 }\r
1509         }\r
1510 \r
1511         ReleaseSk(sk);\r
1512 \r
1513         UniFreeToken(t);\r
1514 \r
1515         ConvertPathW(tmp);\r
1516 \r
1517         UniStrCpy(dst, size, tmp);\r
1518 }\r
1519 void NormalizePath(char *dst, UINT size, char *src)\r
1520 {\r
1521         wchar_t dst_w[MAX_SIZE];\r
1522         wchar_t *src_w = CopyStrToUni(src);\r
1523 \r
1524         NormalizePathW(dst_w, sizeof(dst_w), src_w);\r
1525 \r
1526         Free(src_w);\r
1527 \r
1528         UniToStr(dst, size, dst_w);\r
1529 }\r
1530 \r
1531 // ファイルを閉じて削除する\r
1532 void FileCloseAndDelete(IO *o)\r
1533 {\r
1534         wchar_t *name;\r
1535         // 引数チェック\r
1536         if (o == NULL)\r
1537         {\r
1538                 return;\r
1539         }\r
1540 \r
1541         name = CopyUniStr(o->NameW);\r
1542         FileClose(o);\r
1543 \r
1544         FileDeleteW(name);\r
1545 \r
1546         Free(name);\r
1547 }\r
1548 \r
1549 // ファイル名の変更\r
1550 bool FileRename(char *old_name, char *new_name)\r
1551 {\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
1555 \r
1556         Free(old_name_w);\r
1557         Free(new_name_w);\r
1558 \r
1559         return ret;\r
1560 }\r
1561 bool FileRenameW(wchar_t *old_name, wchar_t *new_name)\r
1562 {\r
1563         wchar_t tmp1[MAX_SIZE];\r
1564         wchar_t tmp2[MAX_SIZE];\r
1565         // 引数チェック\r
1566         if (old_name == NULL || new_name == NULL)\r
1567         {\r
1568                 return false;\r
1569         }\r
1570 \r
1571         InnerFilePathW(tmp1, sizeof(tmp1), old_name);\r
1572         InnerFilePathW(tmp2, sizeof(tmp2), new_name);\r
1573 \r
1574         return FileRenameInnerW(tmp1, tmp2);\r
1575 }\r
1576 bool FileRenameInner(char *old_name, char *new_name)\r
1577 {\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
1581 \r
1582         Free(old_name_w);\r
1583         Free(new_name_w);\r
1584 \r
1585         return ret;\r
1586 }\r
1587 bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name)\r
1588 {\r
1589         // 引数チェック\r
1590         if (old_name == NULL || new_name == NULL)\r
1591         {\r
1592                 return false;\r
1593         }\r
1594 \r
1595         return OSFileRenameW(old_name, new_name);\r
1596 }\r
1597 \r
1598 // パスの変換\r
1599 void ConvertPath(char *path)\r
1600 {\r
1601         UINT i, len;\r
1602 #ifdef  PATH_BACKSLASH\r
1603         char new_char = '\\';\r
1604 #else\r
1605         char new_char = '/';\r
1606 #endif\r
1607 \r
1608         len = StrLen(path);\r
1609         for (i = 0;i < len;i++)\r
1610         {\r
1611                 if (path[i] == '\\' || path[i] == '/')\r
1612                 {\r
1613                         path[i] = new_char;\r
1614                 }\r
1615         }\r
1616 }\r
1617 void ConvertPathW(wchar_t *path)\r
1618 {\r
1619         UINT i, len;\r
1620 #ifdef  PATH_BACKSLASH\r
1621         wchar_t new_char = L'\\';\r
1622 #else\r
1623         wchar_t new_char = L'/';\r
1624 #endif\r
1625 \r
1626         len = UniStrLen(path);\r
1627         for (i = 0;i < len;i++)\r
1628         {\r
1629                 if (path[i] == L'\\' || path[i] == L'/')\r
1630                 {\r
1631                         path[i] = new_char;\r
1632                 }\r
1633         }\r
1634 }\r
1635 \r
1636 // ディレクトリの削除\r
1637 bool DeleteDir(char *name)\r
1638 {\r
1639         wchar_t *name_w = CopyStrToUni(name);\r
1640         bool ret = DeleteDirW(name_w);\r
1641 \r
1642         Free(name_w);\r
1643 \r
1644         return ret;\r
1645 }\r
1646 bool DeleteDirW(wchar_t *name)\r
1647 {\r
1648         wchar_t tmp[MAX_SIZE];\r
1649         // 引数チェック\r
1650         if (name == NULL)\r
1651         {\r
1652                 return false;\r
1653         }\r
1654 \r
1655         InnerFilePathW(tmp, sizeof(tmp), name);\r
1656 \r
1657         return DeleteDirInnerW(tmp);\r
1658 }\r
1659 bool DeleteDirInner(char *name)\r
1660 {\r
1661         wchar_t *name_w = CopyStrToUni(name);\r
1662         bool ret = DeleteDirInnerW(name_w);\r
1663 \r
1664         Free(name_w);\r
1665 \r
1666         return ret;\r
1667 }\r
1668 bool DeleteDirInnerW(wchar_t *name)\r
1669 {\r
1670         // 引数チェック\r
1671         if (name == NULL)\r
1672         {\r
1673                 return false;\r
1674         }\r
1675 \r
1676         return OSDeleteDirW(name);\r
1677 }\r
1678 \r
1679 // 内部ファイルパスの生成\r
1680 void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src)\r
1681 {\r
1682         // 引数チェック\r
1683         if (dst == NULL || src == NULL)\r
1684         {\r
1685                 return;\r
1686         }\r
1687 \r
1688         if (src[0] != L'@')\r
1689         {\r
1690                 NormalizePathW(dst, size, src);\r
1691         }\r
1692         else\r
1693         {\r
1694                 wchar_t dir[MAX_SIZE];\r
1695                 GetExeDirW(dir, sizeof(dir));\r
1696                 ConbinePathW(dst, size, dir, &src[1]);\r
1697         }\r
1698 }\r
1699 void InnerFilePath(char *dst, UINT size, char *src)\r
1700 {\r
1701         wchar_t dst_w[MAX_PATH];\r
1702         wchar_t *src_w = CopyStrToUni(src);\r
1703 \r
1704         InnerFilePathW(dst_w, sizeof(dst_w), src_w);\r
1705 \r
1706         Free(src_w);\r
1707 \r
1708         UniToStr(dst, size, dst_w);\r
1709 }\r
1710 \r
1711 // ディレクトリの再帰作成\r
1712 void MakeDirEx(char *name)\r
1713 {\r
1714         wchar_t *name_w = CopyStrToUni(name);\r
1715 \r
1716         MakeDirExW(name_w);\r
1717 \r
1718         Free(name_w);\r
1719 }\r
1720 void MakeDirExW(wchar_t *name)\r
1721 {\r
1722         LIST *o;\r
1723         wchar_t tmp[MAX_PATH];\r
1724         wchar_t tmp2[MAX_PATH];\r
1725         UINT i;\r
1726         // 引数チェック\r
1727         if (name == NULL)\r
1728         {\r
1729                 return;\r
1730         }\r
1731 \r
1732         o = NewListFast(NULL);\r
1733 \r
1734         UniStrCpy(tmp, sizeof(tmp), name);\r
1735         while (true)\r
1736         {\r
1737                 wchar_t *s = CopyUniStr(tmp);\r
1738 \r
1739                 Add(o, s);\r
1740 \r
1741                 GetDirNameFromFilePathW(tmp2, sizeof(tmp2), tmp);\r
1742 \r
1743                 if (UniStrCmpi(tmp2, tmp) == 0)\r
1744                 {\r
1745                         break;\r
1746                 }\r
1747 \r
1748                 UniStrCpy(tmp, sizeof(tmp), tmp2);\r
1749         }\r
1750 \r
1751         for (i = 0;i < LIST_NUM(o);i++)\r
1752         {\r
1753                 UINT j = LIST_NUM(o) - i - 1;\r
1754                 wchar_t *s = LIST_DATA(o, j);\r
1755 \r
1756                 if (UniStrCmpi(s, L"\\") != 0 && UniStrCmpi(s, L"/") != 0)\r
1757                 {\r
1758                         MakeDirW(s);\r
1759                 }\r
1760         }\r
1761 \r
1762         UniFreeStrList(o);\r
1763 }\r
1764 \r
1765 // ディレクトリの作成\r
1766 bool MakeDir(char *name)\r
1767 {\r
1768         wchar_t *name_w = CopyStrToUni(name);\r
1769         bool ret = MakeDirW(name_w);\r
1770 \r
1771         Free(name_w);\r
1772 \r
1773         return ret;\r
1774 }\r
1775 bool MakeDirW(wchar_t *name)\r
1776 {\r
1777         wchar_t tmp[MAX_SIZE];\r
1778         // 引数チェック\r
1779         if (name == NULL)\r
1780         {\r
1781                 return false;\r
1782         }\r
1783 \r
1784         InnerFilePathW(tmp, sizeof(tmp), name);\r
1785 \r
1786         return MakeDirInnerW(tmp);\r
1787 }\r
1788 bool MakeDirInner(char *name)\r
1789 {\r
1790         wchar_t *name_w = CopyStrToUni(name);\r
1791         bool ret = MakeDirInnerW(name_w);\r
1792 \r
1793         Free(name_w);\r
1794 \r
1795         return ret;\r
1796 }\r
1797 bool MakeDirInnerW(wchar_t *name)\r
1798 {\r
1799         // 引数チェック\r
1800         if (name == NULL)\r
1801         {\r
1802                 return false;\r
1803         }\r
1804 \r
1805         return OSMakeDirW(name);\r
1806 }\r
1807 \r
1808 // ファイルの削除\r
1809 bool FileDelete(char *name)\r
1810 {\r
1811         wchar_t *name_w = CopyStrToUni(name);\r
1812         bool ret = FileDeleteW(name_w);\r
1813 \r
1814         Free(name_w);\r
1815 \r
1816         return ret;\r
1817 }\r
1818 bool FileDeleteW(wchar_t *name)\r
1819 {\r
1820         wchar_t tmp[MAX_SIZE];\r
1821         // 引数チェック\r
1822         if (name == NULL)\r
1823         {\r
1824                 return false;\r
1825         }\r
1826 \r
1827         InnerFilePathW(tmp, sizeof(tmp), name);\r
1828 \r
1829         return FileDeleteInnerW(tmp);\r
1830 }\r
1831 bool FileDeleteInner(char *name)\r
1832 {\r
1833         wchar_t *name_w = CopyStrToUni(name);\r
1834         bool ret = FileDeleteInnerW(name_w);\r
1835 \r
1836         Free(name_w);\r
1837 \r
1838         return ret;\r
1839 }\r
1840 bool FileDeleteInnerW(wchar_t *name)\r
1841 {\r
1842         wchar_t name2[MAX_SIZE];\r
1843         // 引数チェック\r
1844         if (name == NULL)\r
1845         {\r
1846                 return false;\r
1847         }\r
1848 \r
1849         UniStrCpy(name2, sizeof(name2), name);\r
1850         ConvertPathW(name2);\r
1851 \r
1852         return OSFileDeleteW(name2);\r
1853 }\r
1854 \r
1855 // ファイルをシークする\r
1856 bool FileSeek(IO *o, UINT mode, int offset)\r
1857 {\r
1858         // 引数チェック\r
1859         if (o == NULL)\r
1860         {\r
1861                 return false;\r
1862         }\r
1863 \r
1864         if (o->HamMode == false)\r
1865         {\r
1866                 return OSFileSeek(o->pData, mode, offset);\r
1867         }\r
1868         else\r
1869         {\r
1870                 return false;\r
1871         }\r
1872 }\r
1873 \r
1874 // ファイル名を指定してファイルサイズを取得する\r
1875 UINT FileSizeEx(char *name)\r
1876 {\r
1877         wchar_t *name_w = CopyStrToUni(name);\r
1878         UINT ret = FileSizeExW(name_w);\r
1879 \r
1880         Free(name_w);\r
1881 \r
1882         return ret;\r
1883 }\r
1884 UINT FileSizeExW(wchar_t *name)\r
1885 {\r
1886         IO *io;\r
1887         UINT size;\r
1888         // 引数チェック\r
1889         if (name == NULL)\r
1890         {\r
1891                 return 0;\r
1892         }\r
1893 \r
1894         io = FileOpenW(name, false);\r
1895         if (io == NULL)\r
1896         {\r
1897                 return 0;\r
1898         }\r
1899 \r
1900         size = FileSize(io);\r
1901 \r
1902         FileClose(io);\r
1903 \r
1904         return size;\r
1905 }\r
1906 \r
1907 // ファイルサイズを取得する\r
1908 UINT64 FileSize64(IO *o)\r
1909 {\r
1910         // 引数チェック\r
1911         if (o == NULL)\r
1912         {\r
1913                 return 0;\r
1914         }\r
1915 \r
1916         if (o->HamMode == false)\r
1917         {\r
1918                 return OSFileSize(o->pData);\r
1919         }\r
1920         else\r
1921         {\r
1922                 return (UINT64)o->HamBuf->Size;\r
1923         }\r
1924 }\r
1925 UINT FileSize(IO *o)\r
1926 {\r
1927         UINT64 size = (UINT)(FileSize64(o));\r
1928 \r
1929         if (size >= 4294967296ULL)\r
1930         {\r
1931                 size = 4294967295ULL;\r
1932         }\r
1933 \r
1934         return (UINT)size;\r
1935 }\r
1936 \r
1937 // ファイルから読み込む\r
1938 bool FileRead(IO *o, void *buf, UINT size)\r
1939 {\r
1940         // 引数チェック\r
1941         if (o == NULL || buf == NULL)\r
1942         {\r
1943                 return false;\r
1944         }\r
1945 \r
1946         // KS\r
1947         KS_INC(KS_IO_READ_COUNT);\r
1948         KS_ADD(KS_IO_TOTAL_READ_SIZE, size);\r
1949 \r
1950         if (size == 0)\r
1951         {\r
1952                 return true;\r
1953         }\r
1954 \r
1955         if (o->HamMode == false)\r
1956         {\r
1957                 return OSFileRead(o->pData, buf, size);\r
1958         }\r
1959         else\r
1960         {\r
1961                 return ReadBuf(o->HamBuf, buf, size) == size ? true : false;\r
1962         }\r
1963 }\r
1964 \r
1965 // ファイルに書き込む\r
1966 bool FileWrite(IO *o, void *buf, UINT size)\r
1967 {\r
1968         // 引数チェック\r
1969         if (o == NULL || buf == NULL)\r
1970         {\r
1971                 return false;\r
1972         }\r
1973         if (o->WriteMode == false)\r
1974         {\r
1975                 return false;\r
1976         }\r
1977 \r
1978         // KS\r
1979         KS_INC(KS_IO_WRITE_COUNT);\r
1980         KS_ADD(KS_IO_TOTAL_WRITE_SIZE, size);\r
1981 \r
1982         if (size == 0)\r
1983         {\r
1984                 return true;\r
1985         }\r
1986 \r
1987         return OSFileWrite(o->pData, buf, size);\r
1988 }\r
1989 \r
1990 // ファイルをフラッシュする\r
1991 void FileFlush(IO *o)\r
1992 {\r
1993         // 引数チェック\r
1994         if (o == NULL)\r
1995         {\r
1996                 return;\r
1997         }\r
1998 \r
1999         if (o->HamMode)\r
2000         {\r
2001                 return;\r
2002         }\r
2003 \r
2004         OSFileFlush(o->pData);\r
2005 }\r
2006 \r
2007 // ファイルを閉じる\r
2008 void FileClose(IO *o)\r
2009 {\r
2010         FileCloseEx(o, false);\r
2011 }\r
2012 void FileCloseEx(IO *o, bool no_flush)\r
2013 {\r
2014         // 引数チェック\r
2015         if (o == NULL)\r
2016         {\r
2017                 return;\r
2018         }\r
2019 \r
2020         if (o->HamMode == false)\r
2021         {\r
2022                 OSFileClose(o->pData, no_flush);\r
2023         }\r
2024         else\r
2025         {\r
2026                 FreeBuf(o->HamBuf);\r
2027         }\r
2028         Free(o);\r
2029 \r
2030         // KS\r
2031         KS_INC(KS_IO_CLOSE_COUNT);\r
2032 }\r
2033 \r
2034 // ファイルを作成する\r
2035 IO *FileCreateInner(char *name)\r
2036 {\r
2037         wchar_t *name_w = CopyStrToUni(name);\r
2038         IO *ret = FileCreateInnerW(name_w);\r
2039 \r
2040         Free(name_w);\r
2041 \r
2042         return ret;\r
2043 }\r
2044 IO *FileCreateInnerW(wchar_t *name)\r
2045 {\r
2046         IO *o;\r
2047         void *p;\r
2048         wchar_t name2[MAX_SIZE];\r
2049         // 引数チェック\r
2050         if (name == NULL)\r
2051         {\r
2052                 return NULL;\r
2053         }\r
2054 \r
2055         UniStrCpy(name2, sizeof(name2), name);\r
2056         ConvertPathW(name2);\r
2057 \r
2058         p = OSFileCreateW(name2);\r
2059         if (p == NULL)\r
2060         {\r
2061                 return NULL;\r
2062         }\r
2063 \r
2064         o = ZeroMalloc(sizeof(IO));\r
2065         o->pData = p;\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
2069 \r
2070         // KS\r
2071         KS_INC(KS_IO_CREATE_COUNT);\r
2072 \r
2073         return o;\r
2074 }\r
2075 IO *FileCreate(char *name)\r
2076 {\r
2077         wchar_t *name_w = CopyStrToUni(name);\r
2078         IO *ret = FileCreateW(name_w);\r
2079 \r
2080         Free(name_w);\r
2081 \r
2082         return ret;\r
2083 }\r
2084 IO *FileCreateW(wchar_t *name)\r
2085 {\r
2086         wchar_t tmp[MAX_SIZE];\r
2087         // 引数チェック\r
2088         if (name == NULL)\r
2089         {\r
2090                 return NULL;\r
2091         }\r
2092 \r
2093         InnerFilePathW(tmp, sizeof(tmp), name);\r
2094 \r
2095         return FileCreateInnerW(tmp);\r
2096 }\r
2097 \r
2098 // ファイルにすべてのデータを書き込む\r
2099 bool FileWriteAll(char *name, void *data, UINT size)\r
2100 {\r
2101         IO *io;\r
2102         // 引数チェック\r
2103         if (name == NULL || (data == NULL && size != 0))\r
2104         {\r
2105                 return false;\r
2106         }\r
2107 \r
2108         io = FileCreate(name);\r
2109 \r
2110         if (io == NULL)\r
2111         {\r
2112                 return false;\r
2113         }\r
2114 \r
2115         FileWrite(io, data, size);\r
2116 \r
2117         FileClose(io);\r
2118 \r
2119         return true;\r
2120 }\r
2121 bool FileWriteAllW(wchar_t *name, void *data, UINT size)\r
2122 {\r
2123         IO *io;\r
2124         // 引数チェック\r
2125         if (name == NULL || (data == NULL && size != 0))\r
2126         {\r
2127                 return false;\r
2128         }\r
2129 \r
2130         io = FileCreateW(name);\r
2131 \r
2132         if (io == NULL)\r
2133         {\r
2134                 return false;\r
2135         }\r
2136 \r
2137         FileWrite(io, data, size);\r
2138 \r
2139         FileClose(io);\r
2140 \r
2141         return true;\r
2142 }\r
2143 \r
2144 // ファイルを開く\r
2145 IO *FileOpenInner(char *name, bool write_mode, bool read_lock)\r
2146 {\r
2147         wchar_t *name_w = CopyStrToUni(name);\r
2148         IO *ret = FileOpenInnerW(name_w, write_mode, read_lock);\r
2149 \r
2150         Free(name_w);\r
2151 \r
2152         return ret;\r
2153 }\r
2154 IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock)\r
2155 {\r
2156         IO *o;\r
2157         void *p;\r
2158         wchar_t name2[MAX_SIZE];\r
2159         // 引数チェック\r
2160         if (name == NULL)\r
2161         {\r
2162                 return NULL;\r
2163         }\r
2164 \r
2165         UniStrCpy(name2, sizeof(name2), name);\r
2166         ConvertPathW(name2);\r
2167 \r
2168         p = OSFileOpenW(name2, write_mode, read_lock);\r
2169         if (p == NULL)\r
2170         {\r
2171                 return NULL;\r
2172         }\r
2173 \r
2174         o = ZeroMalloc(sizeof(IO));\r
2175         o->pData = p;\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
2179 \r
2180         // KS\r
2181         KS_INC(KS_IO_OPEN_COUNT);\r
2182 \r
2183         return o;\r
2184 }\r
2185 IO *FileOpen(char *name, bool write_mode)\r
2186 {\r
2187         return FileOpenEx(name, write_mode, true);\r
2188 }\r
2189 IO *FileOpenW(wchar_t *name, bool write_mode)\r
2190 {\r
2191         return FileOpenExW(name, write_mode, true);\r
2192 }\r
2193 IO *FileOpenEx(char *name, bool write_mode, bool read_lock)\r
2194 {\r
2195         wchar_t *name_w = CopyStrToUni(name);\r
2196         IO *ret = FileOpenExW(name_w, write_mode, read_lock);\r
2197 \r
2198         Free(name_w);\r
2199 \r
2200         return ret;\r
2201 }\r
2202 IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock)\r
2203 {\r
2204         wchar_t tmp[MAX_SIZE];\r
2205         // 引数チェック\r
2206         if (name == NULL)\r
2207         {\r
2208                 return NULL;\r
2209         }\r
2210 \r
2211         InnerFilePathW(tmp, sizeof(tmp), name);\r
2212 \r
2213         if (name[0] == L'|')\r
2214         {\r
2215                 IO *o = ZeroMalloc(sizeof(IO));\r
2216                 name++;\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
2222                 {\r
2223                         Free(o);\r
2224                         return NULL;\r
2225                 }\r
2226                 return o;\r
2227         }\r
2228         else\r
2229         {\r
2230                 return FileOpenInnerW(tmp, write_mode, read_lock);\r
2231         }\r
2232 }\r
2233 \r
2234 \r