source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/FileIO.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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