1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Mayaqua Kernel
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // FileIO.c
103 // File Input / Output code
104 
105 #include <GlobalConst.h>
106 
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <wchar.h>
111 #include <stdarg.h>
112 #include <time.h>
113 #include <errno.h>
114 #include <Mayaqua/Mayaqua.h>
115 
116 static char exe_file_name[MAX_SIZE] = "/tmp/a.out";
117 static wchar_t exe_file_name_w[MAX_SIZE] = L"/tmp/a.out";
118 static LIST *hamcore = NULL;
119 static IO *hamcore_io = NULL;
120 
121 #define	NUM_CRC32_TABLE	256
122 static UINT crc32_table[NUM_CRC32_TABLE];
123 
124 // Confirm that the specified string exists as a line
IsInLines(BUF * buf,char * str,bool instr)125 bool IsInLines(BUF *buf, char *str, bool instr)
126 {
127 	bool ret = false;
128 	// Validate arguments
129 	if (buf == NULL || str == NULL)
130 	{
131 		return false;
132 	}
133 
134 	if (IsEmptyStr(str))
135 	{
136 		return false;
137 	}
138 
139 	SeekBufToBegin(buf);
140 
141 	while (ret == false)
142 	{
143 		char *line = CfgReadNextLine(buf);
144 
145 		if (line == NULL)
146 		{
147 			break;
148 		}
149 
150 		Trim(line);
151 
152 		if (IsEmptyStr(line) == false)
153 		{
154 			if (StrCmpi(line, str) == 0)
155 			{
156 				ret = true;
157 			}
158 
159 			if (instr)
160 			{
161 				if (InStr(str, line))
162 				{
163 					ret = true;
164 				}
165 
166 				if (InStr(line, str))
167 				{
168 					ret = true;
169 				}
170 			}
171 		}
172 
173 		Free(line);
174 	}
175 
176 	return ret;
177 }
IsInLinesFile(wchar_t * filename,char * str,bool instr)178 bool IsInLinesFile(wchar_t *filename, char *str, bool instr)
179 {
180 	bool ret = false;
181 	BUF *b;
182 	// Validate arguments
183 	if (filename == NULL || str == NULL)
184 	{
185 		return false;
186 	}
187 
188 	b = ReadDumpW(filename);
189 	if (b == NULL)
190 	{
191 		return false;
192 	}
193 
194 	ret = IsInLines(b, str, instr);
195 
196 	FreeBuf(b);
197 
198 	return ret;
199 }
200 
201 // Check whether the file is write-locked
IsFileWriteLockedW(wchar_t * name)202 bool IsFileWriteLockedW(wchar_t *name)
203 {
204 	IO *io;
205 	// Validate arguments
206 	if (name == NULL)
207 	{
208 		return false;
209 	}
210 
211 	if (IsFileExistsW(name) == false)
212 	{
213 		return false;
214 	}
215 
216 	io = FileOpenW(name, true);
217 	if (io == NULL)
218 	{
219 		return true;
220 	}
221 
222 	FileClose(io);
223 
224 	return false;
225 }
IsFileWriteLocked(char * name)226 bool IsFileWriteLocked(char *name)
227 {
228 	bool ret;
229 	wchar_t *tmp;
230 	// Validate arguments
231 	if (name == NULL)
232 	{
233 		return false;
234 	}
235 
236 	tmp = CopyStrToUni(name);
237 
238 	ret = IsFileWriteLockedW(tmp);
239 
240 	Free(tmp);
241 
242 	return ret;
243 }
244 
245 // Creating a ZIP packer
NewZipPacker()246 ZIP_PACKER *NewZipPacker()
247 {
248 	ZIP_PACKER *p = ZeroMalloc(sizeof(ZIP_PACKER));
249 
250 	p->Fifo = NewFifo();
251 	p->FileList = NewList(NULL);
252 	p->CurrentFile = NULL;
253 
254 	return p;
255 }
256 
257 // Release of ZIP packer
FreeZipPacker(ZIP_PACKER * p)258 void FreeZipPacker(ZIP_PACKER *p)
259 {
260 	UINT i;
261 	// Validate arguments
262 	if (p == NULL)
263 	{
264 		return;
265 	}
266 
267 	ReleaseFifo(p->Fifo);
268 
269 	for (i = 0;i < LIST_NUM(p->FileList);i++)
270 	{
271 		ZIP_FILE *f = LIST_DATA(p->FileList, i);
272 
273 		Free(f);
274 	}
275 
276 	ReleaseList(p->FileList);
277 
278 	Free(p);
279 }
280 
281 // Simply add the file
ZipAddFileSimple(ZIP_PACKER * p,char * name,UINT64 dt,UINT attribute,void * data,UINT size)282 void ZipAddFileSimple(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, void *data, UINT size)
283 {
284 	// Validate arguments
285 	if (p == NULL || IsEmptyStr(name) || (size != 0 && data == NULL))
286 	{
287 		return;
288 	}
289 
290 	ZipAddFileStart(p, name, size, dt, attribute);
291 	ZipAddFileData(p, data, 0, size);
292 }
ZipAddRealFileW(ZIP_PACKER * p,char * name,UINT64 dt,UINT attribute,wchar_t * srcname)293 bool ZipAddRealFileW(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, wchar_t *srcname)
294 {
295 	BUF *b;
296 	// Validate arguments
297 	if (p == NULL || IsEmptyStr(name) || srcname == NULL)
298 	{
299 		return false;
300 	}
301 
302 	b = ReadDumpW(srcname);
303 	if (b == NULL)
304 	{
305 		return false;
306 	}
307 
308 	ZipAddFileSimple(p, name, dt, attribute, b->Buf, b->Size);
309 
310 	FreeBuf(b);
311 
312 	return true;
313 }
ZipAddRealFile(ZIP_PACKER * p,char * name,UINT64 dt,UINT attribute,char * srcname)314 bool ZipAddRealFile(ZIP_PACKER *p, char *name, UINT64 dt, UINT attribute, char *srcname)
315 {
316 	bool ret = false;
317 	wchar_t *s;
318 
319 	s = CopyStrToUni(srcname);
320 
321 	ret = ZipAddRealFileW(p, name, dt, attribute, s);
322 
323 	Free(s);
324 
325 	return ret;
326 }
327 
328 // Start adding a file
ZipAddFileStart(ZIP_PACKER * p,char * name,UINT size,UINT64 dt,UINT attribute)329 void ZipAddFileStart(ZIP_PACKER *p, char *name, UINT size, UINT64 dt, UINT attribute)
330 {
331 	char tmp[MAX_PATH];
332 	ZIP_FILE *f;
333 	ZIP_DATA_HEADER h;
334 	// Validate arguments
335 	if (p == NULL || IsEmptyStr(name))
336 	{
337 		return;
338 	}
339 	if (dt == 0)
340 	{
341 		dt = LocalTime64();
342 	}
343 
344 	if (p->CurrentFile != NULL)
345 	{
346 		return;
347 	}
348 
349 	StrCpy(tmp, sizeof(tmp), name);
350 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "\\", true);
351 
352 	f = ZeroMalloc(sizeof(ZIP_FILE));
353 
354 	StrCpy(f->Name, sizeof(f->Name), tmp);
355 	f->Size = size;
356 	f->DateTime = dt;
357 	f->Attributes = attribute;
358 
359 	Add(p->FileList, f);
360 
361 	Zero(&h, sizeof(h));
362 	f->HeaderPos = (UINT)p->Fifo->total_write_size;
363 	WriteZipDataHeader(f, &h, false);
364 	WriteFifo(p->Fifo, &h, sizeof(h));
365 	WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
366 	f->Crc32 = 0xffffffff;
367 
368 	p->CurrentFile = f;
369 }
370 
371 // Add data to the file
ZipAddFileData(ZIP_PACKER * p,void * data,UINT pos,UINT len)372 UINT ZipAddFileData(ZIP_PACKER *p, void *data, UINT pos, UINT len)
373 {
374 	UINT ret;
375 	UINT total_size;
376 	// Validate arguments
377 	if (p == NULL)
378 	{
379 		return 0;
380 	}
381 
382 	total_size = p->CurrentFile->CurrentSize + len;
383 
384 	if (total_size > p->CurrentFile->Size)
385 	{
386 		return 0;
387 	}
388 
389 	WriteFifo(p->Fifo, ((UCHAR *)data) + pos, len);
390 
391 	p->CurrentFile->CurrentSize += len;
392 	p->CurrentFile->Crc32 = Crc32Next(data, pos, len, p->CurrentFile->Crc32);
393 
394 	ret = p->CurrentFile->Size - p->CurrentFile->CurrentSize;
395 
396 	if (ret == 0)
397 	{
398 		p->CurrentFile->Crc32 = ~p->CurrentFile->Crc32;
399 
400 		ZipAddFileFooter(p);
401 
402 		p->CurrentFile = NULL;
403 	}
404 
405 	return ret;
406 }
407 
408 // Append a file footer
ZipAddFileFooter(ZIP_PACKER * p)409 void ZipAddFileFooter(ZIP_PACKER *p)
410 {
411 	ZIP_DATA_FOOTER f;
412 	// Validate arguments
413 	if (p == NULL)
414 	{
415 		return;
416 	}
417 
418 	Zero(&f, sizeof(f));
419 	WriteZipDataFooter(p->CurrentFile, &f);
420 
421 	WriteFifo(p->Fifo, &f, sizeof(f));
422 }
423 
424 // Output the ZIP data to a file
ZipWriteW(ZIP_PACKER * p,wchar_t * name)425 bool ZipWriteW(ZIP_PACKER *p, wchar_t *name)
426 {
427 	FIFO *f;
428 	// Validate arguments
429 	if (p == NULL || name == NULL)
430 	{
431 		return false;
432 	}
433 
434 	f = ZipFinish(p);
435 	if (f == NULL)
436 	{
437 		return false;
438 	}
439 
440 	return FileWriteAllW(name, FifoPtr(f), FifoSize(f));
441 }
442 
443 // Complete the creation of the ZIP data
ZipFinish(ZIP_PACKER * p)444 FIFO *ZipFinish(ZIP_PACKER *p)
445 {
446 	UINT i;
447 	UINT pos_start;
448 	UINT pos_end;
449 	ZIP_END_HEADER e;
450 	// Validate arguments
451 	if (p == NULL)
452 	{
453 		return NULL;
454 	}
455 
456 	pos_start = (UINT)p->Fifo->total_write_size;
457 
458 	for (i = 0;i < LIST_NUM(p->FileList);i++)
459 	{
460 		ZIP_FILE *f = LIST_DATA(p->FileList, i);
461 		ZIP_DIR_HEADER d;
462 		ZIP_DATA_HEADER dh;
463 
464 		Zero(&d, sizeof(d));
465 		Zero(&dh, sizeof(dh));
466 
467 		d.Signature = Endian32(Swap32(0x02014B50));
468 		d.MadeVer = Endian16(Swap16(ZIP_VERSION));
469 
470 		WriteZipDataHeader(f, &dh, true);
471 
472 		d.NeedVer = dh.NeedVer;
473 		d.Option = dh.Option;
474 		d.CompType = dh.CompType;
475 		d.FileTime = dh.FileTime;
476 		d.FileDate = dh.FileDate;
477 		d.Crc32 = dh.Crc32;
478 		d.CompSize = dh.CompSize;
479 		d.UncompSize = dh.UncompSize;
480 		d.FileNameLen = dh.FileNameLen;
481 		d.ExtraLen = dh.ExtraLen;
482 		d.CommentLen = 0;
483 		d.DiskNum = 0;
484 		d.InAttr = 0;
485 		d.OutAttr = Endian32(Swap32((USHORT)f->Attributes));
486 		d.HeaderPos = Endian32(Swap32(f->HeaderPos));
487 
488 		WriteFifo(p->Fifo, &d, sizeof(d));
489 		WriteFifo(p->Fifo, f->Name, StrLen(f->Name));
490 	}
491 
492 	pos_end = (UINT)p->Fifo->total_write_size;
493 
494 	Zero(&e, sizeof(e));
495 	e.Signature = Endian32(Swap32(ZIP_SIGNATURE_END));
496 	e.DiskNum = e.StartDiskNum = 0;
497 	e.DiskDirEntry = e.DirEntry = Endian16(Swap16((USHORT)LIST_NUM(p->FileList)));
498 	e.DirSize = Endian32(Swap32((UINT)(pos_end - pos_start)));
499 	e.StartPos = Endian32(Swap32(pos_start));
500 	e.CommentLen = 0;
501 
502 	WriteFifo(p->Fifo, &e, sizeof(e));
503 
504 	return p->Fifo;
505 }
506 
507 // Creating a ZIP data header
WriteZipDataHeader(ZIP_FILE * f,ZIP_DATA_HEADER * h,bool write_sizes)508 void WriteZipDataHeader(ZIP_FILE *f, ZIP_DATA_HEADER *h, bool write_sizes)
509 {
510 	// Validate arguments
511 	if (f == NULL || h ==NULL)
512 	{
513 		return;
514 	}
515 
516 	h->Signature = Endian32(Swap32(ZIP_SIGNATURE));
517 	h->NeedVer = Endian16(Swap16(ZIP_VERSION));
518 	h->CompType = 0;
519 	h->FileDate = Endian16(Swap16(System64ToDosDate(f->DateTime)));
520 	h->FileTime = Endian16(Swap16(System64ToDosTime(f->DateTime)));
521 	h->Option = Endian16(Swap16(8)); // bit3: Set the file-size and the CRC in local header to 0
522 
523 	if (write_sizes == false)
524 	{
525 		h->CompSize = h->UncompSize = 0;
526 		h->Crc32 = 0;
527 	}
528 	else
529 	{
530 		h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
531 		h->Crc32 = Endian32(Swap32(f->Crc32));
532 	}
533 
534 	h->FileNameLen = Endian16(Swap16(StrLen(f->Name)));
535 	h->ExtraLen = 0;
536 }
537 
538 // Creating a ZIP data footer
WriteZipDataFooter(ZIP_FILE * f,ZIP_DATA_FOOTER * h)539 void WriteZipDataFooter(ZIP_FILE *f, ZIP_DATA_FOOTER *h)
540 {
541 	// Validate arguments
542 	if (f == NULL || h ==NULL)
543 	{
544 		return;
545 	}
546 
547 	h->Signature = Endian32(Swap32(0x08074B50));
548 	h->CompSize = h->UncompSize = Endian32(Swap32(f->Size));
549 	h->Crc32 = Endian32(Swap32(f->Crc32));
550 }
551 
552 // Initialize the common table of CRC32
InitCrc32()553 void InitCrc32()
554 {
555 	UINT poly = 0xEDB88320;
556 	UINT u, i, j;
557 
558 	for (i = 0;i < 256;i++)
559 	{
560 		u = i;
561 
562 		for (j = 0;j < 8;j++)
563 		{
564 			if ((u & 0x1) != 0)
565 			{
566 				u = (u >> 1) ^ poly;
567 			}
568 			else
569 			{
570 				u >>= 1;
571 			}
572 		}
573 
574 		crc32_table[i] = u;
575 	}
576 }
577 
578 // CRC32 arithmetic processing
Crc32(void * buf,UINT pos,UINT len)579 UINT Crc32(void *buf, UINT pos, UINT len)
580 {
581 	return Crc32Finish(Crc32First(buf, pos, len));
582 }
Crc32First(void * buf,UINT pos,UINT len)583 UINT Crc32First(void *buf, UINT pos, UINT len)
584 {
585 	return Crc32Next(buf, pos, len, 0xffffffff);
586 }
Crc32Next(void * buf,UINT pos,UINT len,UINT last_crc32)587 UINT Crc32Next(void *buf, UINT pos, UINT len, UINT last_crc32)
588 {
589 	UINT ret = last_crc32;
590 	UINT i;
591 
592 	for (i = 0;i < len;i++)
593 	{
594 		ret = (ret >> 8) ^ crc32_table[((UCHAR *)buf)[pos + i] ^ (ret & 0xff)];
595 	}
596 
597 	return ret;
598 }
Crc32Finish(UINT last_crc32)599 UINT Crc32Finish(UINT last_crc32)
600 {
601 	return ~last_crc32;
602 }
603 
604 // Save the file
SaveFileW(wchar_t * name,void * data,UINT size)605 bool SaveFileW(wchar_t *name, void *data, UINT size)
606 {
607 	IO *io;
608 	// Validate arguments
609 	if (name == NULL || (data == NULL && size != 0))
610 	{
611 		return false;
612 	}
613 
614 	io = FileCreateW(name);
615 	if (io == NULL)
616 	{
617 		return false;
618 	}
619 
620 	if (FileWrite(io, data, size) == false)
621 	{
622 		FileClose(io);
623 		return false;
624 	}
625 
626 	FileClose(io);
627 
628 	return true;
629 }
SaveFile(char * name,void * data,UINT size)630 bool SaveFile(char *name, void *data, UINT size)
631 {
632 	wchar_t *name_w = CopyStrToUni(name);
633 	bool ret = SaveFileW(name_w, data, size);
634 
635 	Free(name_w);
636 
637 	return ret;
638 }
639 
640 // Check whether the file exists
IsFile(char * name)641 bool IsFile(char *name)
642 {
643 	wchar_t *name_w = CopyStrToUni(name);
644 	bool ret = IsFileW(name_w);
645 
646 	Free(name_w);
647 
648 	return ret;
649 }
IsFileW(wchar_t * name)650 bool IsFileW(wchar_t *name)
651 {
652 	IO *io;
653 	// Validate arguments
654 	if (name == NULL)
655 	{
656 		return false;
657 	}
658 
659 	io = FileOpenExW(name, false, false);
660 	if (io == NULL)
661 	{
662 		return false;
663 	}
664 
665 	FileClose(io);
666 
667 	return true;
668 }
669 
670 // Rename to replace the file
FileReplaceRename(char * old_name,char * new_name)671 bool FileReplaceRename(char *old_name, char *new_name)
672 {
673 	wchar_t *old_name_w = CopyStrToUni(old_name);
674 	wchar_t *new_name_w = CopyStrToUni(new_name);
675 	bool ret = FileReplaceRenameW(old_name_w, new_name_w);
676 
677 	Free(old_name_w);
678 	Free(new_name_w);
679 
680 	return ret;
681 }
FileReplaceRenameW(wchar_t * old_name,wchar_t * new_name)682 bool FileReplaceRenameW(wchar_t *old_name, wchar_t *new_name)
683 {
684 	// Validate arguments
685 	if (old_name == NULL || new_name == NULL)
686 	{
687 		return false;
688 	}
689 
690 	if (FileCopyW(old_name, new_name) == false)
691 	{
692 		return false;
693 	}
694 
695 	FileDeleteW(old_name);
696 
697 	return true;
698 }
699 
700 // Make the file name safe
ConvertSafeFileName(char * dst,UINT size,char * src)701 void ConvertSafeFileName(char *dst, UINT size, char *src)
702 {
703 	UINT i;
704 	// Validate arguments
705 	if (dst == NULL || src == NULL)
706 	{
707 		return;
708 	}
709 
710 	StrCpy(dst, size, src);
711 	for (i = 0;i < StrLen(dst);i++)
712 	{
713 		if (IsSafeChar(dst[i]) == false)
714 		{
715 			dst[i] = '_';
716 		}
717 	}
718 }
ConvertSafeFileNameW(wchar_t * dst,UINT size,wchar_t * src)719 void ConvertSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
720 {
721 	UINT i;
722 	// Validate arguments
723 	if (dst == NULL || src == NULL)
724 	{
725 		return;
726 	}
727 
728 	UniStrCpy(dst, size, src);
729 	for (i = 0;i < UniStrLen(dst);i++)
730 	{
731 		if (UniIsSafeChar(dst[i]) == false)
732 		{
733 			dst[i] = L'_';
734 		}
735 	}
736 }
737 
738 // Get the free disk space
GetDiskFree(char * path,UINT64 * free_size,UINT64 * used_size,UINT64 * total_size)739 bool GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
740 {
741 	bool ret;
742 	// Validate arguments
743 	if (path == NULL)
744 	{
745 		path = "./";
746 	}
747 
748 #ifdef	OS_WIN32
749 	ret = Win32GetDiskFree(path, free_size, used_size, total_size);
750 #else	// OS_WIN32
751 	ret = UnixGetDiskFree(path, free_size, used_size, total_size);
752 #endif	// OS_WIN32
753 
754 	return ret;
755 }
GetDiskFreeW(wchar_t * path,UINT64 * free_size,UINT64 * used_size,UINT64 * total_size)756 bool GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
757 {
758 	bool ret;
759 	// Validate arguments
760 	if (path == NULL)
761 	{
762 		path = L"./";
763 	}
764 
765 #ifdef	OS_WIN32
766 	ret = Win32GetDiskFreeW(path, free_size, used_size, total_size);
767 #else	// OS_WIN32
768 	ret = UnixGetDiskFreeW(path, free_size, used_size, total_size);
769 #endif	// OS_WIN32
770 
771 	return ret;
772 }
773 
774 // Enumeration of direction with all sub directories
EnumDirWithSubDirs(char * dirname)775 TOKEN_LIST *EnumDirWithSubDirs(char *dirname)
776 {
777 	TOKEN_LIST *ret;
778 	UNI_TOKEN_LIST *ret2;
779 	wchar_t tmp[MAX_SIZE];
780 	// Validate arguments
781 	if (dirname == NULL)
782 	{
783 		dirname = "./";
784 	}
785 
786 	StrToUni(tmp, sizeof(tmp), dirname);
787 
788 	ret2 = EnumDirWithSubDirsW(tmp);
789 
790 	ret = UniTokenListToTokenList(ret2);
791 
792 	UniFreeToken(ret2);
793 
794 	return ret;
795 }
EnumDirWithSubDirsW(wchar_t * dirname)796 UNI_TOKEN_LIST *EnumDirWithSubDirsW(wchar_t *dirname)
797 {
798 	ENUM_DIR_WITH_SUB_DATA d;
799 	UNI_TOKEN_LIST *ret;
800 	UINT i;
801 	// Validate arguments
802 	if (dirname == NULL)
803 	{
804 		dirname = L"./";
805 	}
806 
807 	Zero(&d, sizeof(d));
808 
809 	d.FileList = NewListFast(NULL);
810 
811 	EnumDirWithSubDirsMain(&d, dirname);
812 
813 	ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
814 
815 	ret->NumTokens = LIST_NUM(d.FileList);
816 	ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
817 
818 	for (i = 0;i < ret->NumTokens;i++)
819 	{
820 		wchar_t *s = LIST_DATA(d.FileList, i);
821 
822 		ret->Token[i] = UniCopyStr(s);
823 	}
824 
825 	FreeStrList(d.FileList);
826 
827 	return ret;
828 }
EnumDirWithSubDirsMain(ENUM_DIR_WITH_SUB_DATA * d,wchar_t * dirname)829 void EnumDirWithSubDirsMain(ENUM_DIR_WITH_SUB_DATA *d, wchar_t *dirname)
830 {
831 	DIRLIST *dir;
832 	UINT i;
833 	// Validate arguments
834 	if (d == NULL || dirname == NULL)
835 	{
836 		return;
837 	}
838 
839 	dir = EnumDirExW(dirname, NULL);
840 	if (dir == NULL)
841 	{
842 		return;
843 	}
844 
845 	// Files
846 	for (i = 0;i < dir->NumFiles;i++)
847 	{
848 		DIRENT *e = dir->File[i];
849 
850 		if (e->Folder == false)
851 		{
852 			wchar_t tmp[MAX_SIZE];
853 
854 			ConbinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
855 
856 			Add(d->FileList, CopyUniStr(tmp));
857 		}
858 	}
859 
860 	// Sub directories
861 	for (i = 0;i < dir->NumFiles;i++)
862 	{
863 		DIRENT *e = dir->File[i];
864 
865 		if (e->Folder)
866 		{
867 			wchar_t tmp[MAX_SIZE];
868 
869 			ConbinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
870 
871 			EnumDirWithSubDirsMain(d, tmp);
872 		}
873 	}
874 
875 	FreeDir(dir);
876 }
877 
878 // Enumeration of directory
EnumDirEx(char * dirname,COMPARE * compare)879 DIRLIST *EnumDirEx(char *dirname, COMPARE *compare)
880 {
881 	wchar_t *dirname_w = CopyStrToUni(dirname);
882 	DIRLIST *ret = EnumDirExW(dirname_w, compare);
883 
884 	Free(dirname_w);
885 
886 	return ret;
887 }
EnumDirExW(wchar_t * dirname,COMPARE * compare)888 DIRLIST *EnumDirExW(wchar_t *dirname, COMPARE *compare)
889 {
890 	DIRLIST *d = NULL;
891 	// Validate arguments
892 	if (dirname == NULL)
893 	{
894 		dirname = L"./";
895 	}
896 
897 	if (compare == NULL)
898 	{
899 		compare = CompareDirListByName;
900 	}
901 
902 #ifdef	OS_WIN32
903 	d = Win32EnumDirExW(dirname, compare);
904 #else	// OS_WIN32
905 	d = UnixEnumDirExW(dirname, compare);
906 #endif	// OS_WIN32
907 
908 	return d;
909 }
EnumDir(char * dirname)910 DIRLIST *EnumDir(char *dirname)
911 {
912 	return EnumDirEx(dirname, NULL);
913 }
EnumDirW(wchar_t * dirname)914 DIRLIST *EnumDirW(wchar_t *dirname)
915 {
916 	return EnumDirExW(dirname, NULL);
917 }
918 
919 // Comparison of DIRLIST list entry
CompareDirListByName(void * p1,void * p2)920 int CompareDirListByName(void *p1, void *p2)
921 {
922 	DIRENT *d1, *d2;
923 	if (p1 == NULL || p2 == NULL)
924 	{
925 		return 0;
926 	}
927 	d1 = *(DIRENT **)p1;
928 	d2 = *(DIRENT **)p2;
929 	if (d1 == NULL || d2 == NULL)
930 	{
931 		return 0;
932 	}
933 	return UniStrCmpi(d1->FileNameW, d2->FileNameW);
934 }
935 
936 // Release the enumeration of the directory
FreeDir(DIRLIST * d)937 void FreeDir(DIRLIST *d)
938 {
939 	UINT i;
940 	// Validate arguments
941 	if (d == NULL)
942 	{
943 		return;
944 	}
945 
946 	for (i = 0;i < d->NumFiles;i++)
947 	{
948 		DIRENT *f = d->File[i];
949 		Free(f->FileName);
950 		Free(f->FileNameW);
951 		Free(f);
952 	}
953 	Free(d->File);
954 	Free(d);
955 }
956 
957 
958 // Make the file name safe
UniSafeFileName(wchar_t * name)959 void UniSafeFileName(wchar_t *name)
960 {
961 	UINT i, len, dlen;
962 	static wchar_t *danger_str = L"\\/:*?\"<>|";
963 	// Validate arguments
964 	if (name == NULL)
965 	{
966 		return;
967 	}
968 
969 	dlen = UniStrLen(danger_str);
970 	len = UniStrLen(name);
971 
972 	for (i = 0;i < len;i++)
973 	{
974 		wchar_t c = name[i];
975 		UINT j;
976 		for (j = 0;j < dlen;j++)
977 		{
978 			if (c == danger_str[j])
979 			{
980 				c = L'_';
981 			}
982 		}
983 		name[i] = c;
984 	}
985 }
SafeFileNameW(wchar_t * name)986 void SafeFileNameW(wchar_t *name)
987 {
988 	UniSafeFileName(name);
989 }
990 
991 // Read HamCore file
ReadHamcoreW(wchar_t * filename)992 BUF *ReadHamcoreW(wchar_t *filename)
993 {
994 	char *filename_a = CopyUniToStr(filename);
995 	BUF *ret;
996 
997 	ret = ReadHamcore(filename_a);
998 
999 	Free(filename_a);
1000 
1001 	return ret;
1002 }
ReadHamcore(char * name)1003 BUF *ReadHamcore(char *name)
1004 {
1005 	wchar_t tmp[MAX_SIZE];
1006 	wchar_t exe_dir[MAX_SIZE];
1007 	BUF *b;
1008 	char filename[MAX_PATH];
1009 	// Validate arguments
1010 	if (name == NULL)
1011 	{
1012 		return NULL;
1013 	}
1014 
1015 	if (name[0] == '|')
1016 	{
1017 		name++;
1018 	}
1019 
1020 	if (name[0] == '/' || name[0] == '\\')
1021 	{
1022 		name++;
1023 	}
1024 
1025 	StrCpy(filename, sizeof(filename), name);
1026 
1027 	ReplaceStrEx(filename, sizeof(filename), filename, "/", "\\", true);
1028 
1029 	if (MayaquaIsMinimalMode())
1030 	{
1031 		return NULL;
1032 	}
1033 
1034 	// If the file exist in hamcore/ directory on the local disk, read it
1035 	GetExeDirW(exe_dir, sizeof(exe_dir));
1036 
1037 	UniFormat(tmp, sizeof(tmp), L"%s/%S/%S", exe_dir, HAMCORE_DIR_NAME, filename);
1038 
1039 	b = ReadDumpW(tmp);
1040 	if (b != NULL)
1041 	{
1042 		return b;
1043 	}
1044 
1045 	// Search from HamCore file system if it isn't found
1046 	LockList(hamcore);
1047 	{
1048 		HC t, *c;
1049 		UINT i;
1050 
1051 		Zero(&t, sizeof(t));
1052 		t.FileName = filename;
1053 		c = Search(hamcore, &t);
1054 
1055 		if (c == NULL)
1056 		{
1057 			// File does not exist
1058 			b = NULL;
1059 		}
1060 		else
1061 		{
1062 			// File exists
1063 			if (c->Buffer != NULL)
1064 			{
1065 				// It is already loaded
1066 				b = NewBuf();
1067 				WriteBuf(b, c->Buffer, c->Size);
1068 				SeekBuf(b, 0, 0);
1069 				c->LastAccess = Tick64();
1070 			}
1071 			else
1072 			{
1073 				// Read from a file is if it is not read
1074 				if (FileSeek(hamcore_io, 0, c->Offset) == false)
1075 				{
1076 					// Failed to seek
1077 					b = NULL;
1078 				}
1079 				else
1080 				{
1081 					// Read the compressed data
1082 					void *data = Malloc(c->SizeCompressed);
1083 					if (FileRead(hamcore_io, data, c->SizeCompressed) == false)
1084 					{
1085 						// Failed to read
1086 						Free(data);
1087 						b = NULL;
1088 					}
1089 					else
1090 					{
1091 						// Expand
1092 						c->Buffer = ZeroMalloc(c->Size);
1093 						if (Uncompress(c->Buffer, c->Size, data, c->SizeCompressed) != c->Size)
1094 						{
1095 							// Failed to expand
1096 							Free(data);
1097 							Free(c->Buffer);
1098 							b = NULL;
1099 						}
1100 						else
1101 						{
1102 							// Successful
1103 							Free(data);
1104 							b = NewBuf();
1105 							WriteBuf(b, c->Buffer, c->Size);
1106 							SeekBuf(b, 0, 0);
1107 							c->LastAccess = Tick64();
1108 						}
1109 					}
1110 				}
1111 			}
1112 		}
1113 
1114 		// Delete the expired cache
1115 		for (i = 0;i < LIST_NUM(hamcore);i++)
1116 		{
1117 			HC *c = LIST_DATA(hamcore, i);
1118 
1119 			if (c->Buffer != NULL)
1120 			{
1121 				if (((c->LastAccess + HAMCORE_CACHE_EXPIRES) <= Tick64()) ||
1122 					(StartWith(c->FileName, "Li")))
1123 				{
1124 					Free(c->Buffer);
1125 					c->Buffer = NULL;
1126 				}
1127 			}
1128 		}
1129 	}
1130 	UnlockList(hamcore);
1131 
1132 	return b;
1133 }
1134 
1135 // Initialization of HamCore file system
InitHamcore()1136 void InitHamcore()
1137 {
1138 	wchar_t tmp[MAX_PATH];
1139 	wchar_t tmp2[MAX_PATH];
1140 	wchar_t exe_dir[MAX_PATH];
1141 	UINT i, num;
1142 	char header[HAMCORE_HEADER_SIZE];
1143 
1144 	hamcore = NewList(CompareHamcore);
1145 
1146 	if (MayaquaIsMinimalMode())
1147 	{
1148 		return;
1149 	}
1150 
1151 	GetExeDirW(exe_dir, sizeof(exe_dir));
1152 	UniFormat(tmp, sizeof(tmp), L"%s/%S", exe_dir, HAMCORE_FILE_NAME);
1153 
1154 	UniFormat(tmp2, sizeof(tmp2), L"%s/%S", exe_dir, HAMCORE_FILE_NAME_2);
1155 
1156 	// If there is _hamcore.se2, overwrite it yo the hamcore.se2
1157 	FileReplaceRenameW(tmp2, tmp);
1158 
1159 	// Read if there is a file hamcore.se2
1160 	hamcore_io = FileOpenW(tmp, false);
1161 	if (hamcore_io == NULL)
1162 	{
1163 		// Look in other locations if it isn't found
1164 #ifdef	OS_WIN32
1165 		UniFormat(tmp, sizeof(tmp), L"%S/%S", MsGetSystem32Dir(), HAMCORE_FILE_NAME);
1166 #else	// OS_WIN32
1167 		UniFormat(tmp, sizeof(tmp), L"/bin/%S", HAMCORE_FILE_NAME);
1168 #endif	// OS_WIN32
1169 
1170 		hamcore_io = FileOpenW(tmp, false);
1171 		if (hamcore_io == NULL)
1172 		{
1173 			return;
1174 		}
1175 	}
1176 
1177 	// Read the file header
1178 	Zero(header, sizeof(header));
1179 	FileRead(hamcore_io, header, HAMCORE_HEADER_SIZE);
1180 
1181 	if (Cmp(header, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE) != 0)
1182 	{
1183 		// Invalid header
1184 		FileClose(hamcore_io);
1185 		hamcore_io = NULL;
1186 		return;
1187 	}
1188 
1189 	// The number of the File
1190 	num = 0;
1191 	FileRead(hamcore_io, &num, sizeof(num));
1192 	num = Endian32(num);
1193 	for (i = 0;i < num;i++)
1194 	{
1195 		// File name
1196 		char tmp[MAX_SIZE];
1197 		UINT str_size = 0;
1198 		HC *c;
1199 
1200 		FileRead(hamcore_io, &str_size, sizeof(str_size));
1201 		str_size = Endian32(str_size);
1202 		if (str_size >= 1)
1203 		{
1204 			str_size--;
1205 		}
1206 
1207 		Zero(tmp, sizeof(tmp));
1208 		FileRead(hamcore_io, tmp, str_size);
1209 
1210 		c = ZeroMalloc(sizeof(HC));
1211 		c->FileName = CopyStr(tmp);
1212 
1213 		FileRead(hamcore_io, &c->Size, sizeof(UINT));
1214 		c->Size = Endian32(c->Size);
1215 
1216 		FileRead(hamcore_io, &c->SizeCompressed, sizeof(UINT));
1217 		c->SizeCompressed = Endian32(c->SizeCompressed);
1218 
1219 		FileRead(hamcore_io, &c->Offset, sizeof(UINT));
1220 		c->Offset = Endian32(c->Offset);
1221 
1222 		Insert(hamcore, c);
1223 	}
1224 }
1225 
1226 // Release of HamCore file system
FreeHamcore()1227 void FreeHamcore()
1228 {
1229 	UINT i;
1230 	for (i = 0;i < LIST_NUM(hamcore);i++)
1231 	{
1232 		HC *c = LIST_DATA(hamcore, i);
1233 		Free(c->FileName);
1234 		if (c->Buffer != NULL)
1235 		{
1236 			Free(c->Buffer);
1237 		}
1238 		Free(c);
1239 	}
1240 	ReleaseList(hamcore);
1241 
1242 	FileClose(hamcore_io);
1243 	hamcore_io = NULL;
1244 	hamcore = NULL;
1245 }
1246 
1247 // Build a Hamcore file
BuildHamcore(char * dst_filename,char * src_dir,bool unix_only)1248 void BuildHamcore(char *dst_filename, char *src_dir, bool unix_only)
1249 {
1250 	char exe_dir[MAX_SIZE];
1251 	bool ok = true;
1252 	LIST *o;
1253 	UINT i;
1254 	TOKEN_LIST *src_file_list;
1255 
1256 	GetExeDir(exe_dir, sizeof(exe_dir));
1257 
1258 	src_file_list = EnumDirWithSubDirs(src_dir);
1259 
1260 	o = NewListFast(CompareHamcore);
1261 
1262 	for (i = 0;i < src_file_list->NumTokens;i++)
1263 	{
1264 		char rpath[MAX_SIZE];
1265 		BUF *b;
1266 		char s[MAX_SIZE];
1267 
1268 		StrCpy(s, sizeof(s), src_file_list->Token[i]);
1269 		Trim(s);
1270 
1271 		if (GetRelativePath(rpath, sizeof(rpath), s, src_dir) == false)
1272 		{
1273 			// Unknown error !
1274 		}
1275 		else
1276 		{
1277 			bool ok = true;
1278 
1279 			ReplaceStr(rpath, sizeof(rpath), rpath, "/", "\\");
1280 
1281 			if (unix_only)
1282 			{
1283 				// Exclude non-UNIX files
1284 				if (EndWith(s, ".exe") ||
1285 					EndWith(s, ".dll") ||
1286 					EndWith(s, ".sys") ||
1287 					EndWith(s, ".inf") ||
1288 					EndWith(s, ".cat") ||
1289 					EndWith(s, ".wav"))
1290 				{
1291 					ok = false;
1292 				}
1293 			}
1294 
1295 			if (InStr(rpath, "\\node_modules\\"))
1296 			{
1297 				// Exclude node_modules in the hamcore\webroot
1298 				ok = false;
1299 			}
1300 
1301 			if (ok)
1302 			{
1303 				b = ReadDump(s);
1304 				if (b == NULL)
1305 				{
1306 					Print("Failed to open '%s'.\n", s);
1307 					ok = false;
1308 				}
1309 				else
1310 				{
1311 					HC *c = ZeroMalloc(sizeof(HC));
1312 					UINT tmp_size;
1313 					void *tmp;
1314 					c->FileName = CopyStr(rpath);
1315 					c->Size = b->Size;
1316 					tmp_size = CalcCompress(c->Size);
1317 					tmp = Malloc(tmp_size);
1318 					c->SizeCompressed = Compress(tmp, tmp_size, b->Buf, b->Size);
1319 					c->Buffer = tmp;
1320 					Insert(o, c);
1321 					Print("%s: %u -> %u\n", s, c->Size, c->SizeCompressed);
1322 					FreeBuf(b);
1323 				}
1324 			}
1325 		}
1326 	}
1327 
1328 	if (ok)
1329 	{
1330 		// Calculate the offset of the buffer for each file
1331 		UINT i, z;
1332 		char tmp[MAX_SIZE];
1333 		BUF *b;
1334 		z = 0;
1335 		z += HAMCORE_HEADER_SIZE;
1336 		// The number of files
1337 		z += sizeof(UINT);
1338 		// For file table first
1339 		for (i = 0;i < LIST_NUM(o);i++)
1340 		{
1341 			HC *c = LIST_DATA(o, i);
1342 			// File name
1343 			z += StrLen(c->FileName) + sizeof(UINT);
1344 			// File size
1345 			z += sizeof(UINT);
1346 			z += sizeof(UINT);
1347 			// Offset data
1348 			z += sizeof(UINT);
1349 		}
1350 		// File body
1351 		for (i = 0;i < LIST_NUM(o);i++)
1352 		{
1353 			HC *c = LIST_DATA(o, i);
1354 			// Buffer body
1355 			c->Offset = z;
1356 			printf("%s: offset: %u\n", c->FileName, c->Offset);
1357 			z += c->SizeCompressed;
1358 		}
1359 		// Writing
1360 		b = NewBuf();
1361 		// Header
1362 		WriteBuf(b, HAMCORE_HEADER_DATA, HAMCORE_HEADER_SIZE);
1363 		WriteBufInt(b, LIST_NUM(o));
1364 		for (i = 0;i < LIST_NUM(o);i++)
1365 		{
1366 			HC *c = LIST_DATA(o, i);
1367 			// File name
1368 			WriteBufStr(b, c->FileName);
1369 			// File size
1370 			WriteBufInt(b, c->Size);
1371 			WriteBufInt(b, c->SizeCompressed);
1372 			// Offset
1373 			WriteBufInt(b, c->Offset);
1374 		}
1375 		// Body
1376 		for (i = 0;i < LIST_NUM(o);i++)
1377 		{
1378 			HC *c = LIST_DATA(o, i);
1379 			WriteBuf(b, c->Buffer, c->SizeCompressed);
1380 		}
1381 		// Writing
1382 		StrCpy(tmp, sizeof(tmp), dst_filename);
1383 		Print("Writing %s...\n", tmp);
1384 		FileDelete(tmp);
1385 		DumpBuf(b, tmp);
1386 		FreeBuf(b);
1387 	}
1388 
1389 	for (i = 0;i < LIST_NUM(o);i++)
1390 	{
1391 		HC *c = LIST_DATA(o, i);
1392 		Free(c->Buffer);
1393 		Free(c->FileName);
1394 		Free(c);
1395 	}
1396 
1397 	ReleaseList(o);
1398 
1399 	FreeToken(src_file_list);
1400 }
1401 
1402 // Comparison of the HCs
CompareHamcore(void * p1,void * p2)1403 int CompareHamcore(void *p1, void *p2)
1404 {
1405 	HC *c1, *c2;
1406 	if (p1 == NULL || p2 == NULL)
1407 	{
1408 		return 0;
1409 	}
1410 	c1 = *(HC **)p1;
1411 	c2 = *(HC **)p2;
1412 	if (c1 == NULL || c2 == NULL)
1413 	{
1414 		return 0;
1415 	}
1416 	return StrCmpi(c1->FileName, c2->FileName);
1417 }
1418 
1419 // Getting the name of the directory where the EXE file is in
GetExeDir(char * name,UINT size)1420 void GetExeDir(char *name, UINT size)
1421 {
1422 	// Validate arguments
1423 	if (name == NULL)
1424 	{
1425 		return;
1426 	}
1427 
1428 	GetDirNameFromFilePath(name, size, exe_file_name);
1429 }
GetExeDirW(wchar_t * name,UINT size)1430 void GetExeDirW(wchar_t *name, UINT size)
1431 {
1432 	// Validate arguments
1433 	if (name == NULL)
1434 	{
1435 		return;
1436 	}
1437 
1438 	GetDirNameFromFilePathW(name, size, exe_file_name_w);
1439 }
1440 
1441 // Get the EXE file name
GetExeName(char * name,UINT size)1442 void GetExeName(char *name, UINT size)
1443 {
1444 	// Validate arguments
1445 	if (name == NULL)
1446 	{
1447 		return;
1448 	}
1449 
1450 	StrCpy(name, size, exe_file_name);
1451 }
GetExeNameW(wchar_t * name,UINT size)1452 void GetExeNameW(wchar_t *name, UINT size)
1453 {
1454 	// Validate arguments
1455 	if (name == NULL)
1456 	{
1457 		return;
1458 	}
1459 
1460 	UniStrCpy(name, size, exe_file_name_w);
1461 }
1462 
GetLogDir(char * name,UINT size)1463 void GetLogDir(char *name, UINT size)
1464 {
1465 	Format(name, size, "/var/log/softether");
1466 }
1467 
GetLogDirW(wchar_t * name,UINT size)1468 void GetLogDirW(wchar_t *name, UINT size)
1469 {
1470 	UniFormat(name, size, L"/var/log/softether");
1471 }
1472 
GetDbDir(char * name,UINT size)1473 void GetDbDir(char *name, UINT size)
1474 {
1475 	Format(name, size, "/var/db/softether");
1476 }
1477 
GetDbDirW(wchar_t * name,UINT size)1478 void GetDbDirW(wchar_t *name, UINT size)
1479 {
1480 	UniFormat(name, size, L"/var/db/softether");
1481 }
1482 
GetPidDir(char * name,UINT size)1483 void GetPidDir(char *name, UINT size)
1484 {
1485 	Format(name, size, "/var/run/softether");
1486 }
1487 
GetPidDirW(wchar_t * name,UINT size)1488 void GetPidDirW(wchar_t *name, UINT size)
1489 {
1490 	UniFormat(name, size, L"/var/run/softether");
1491 }
1492 
1493 // Initialization of the aquisition of the EXE file name
InitGetExeName(char * arg)1494 void InitGetExeName(char *arg)
1495 {
1496 	wchar_t *arg_w = NULL;
1497 	// Validate arguments
1498 	if (arg == NULL)
1499 	{
1500 		arg = "./a.out";
1501 	}
1502 
1503 	arg_w = CopyUtfToUni(arg);
1504 
1505 #ifdef	OS_WIN32
1506 	Win32GetExeNameW(exe_file_name_w, sizeof(exe_file_name_w));
1507 #else	// OS_WIN32
1508 	UnixGetExeNameW(exe_file_name_w, sizeof(exe_file_name_w), arg_w);
1509 #endif	// OS_WIN32
1510 
1511 	UniToStr(exe_file_name, sizeof(exe_file_name), exe_file_name_w);
1512 
1513 	Free(arg_w);
1514 }
1515 
1516 // Get the full path of the executable binary file in Unix
UnixGetExeNameW(wchar_t * name,UINT size,wchar_t * arg)1517 void UnixGetExeNameW(wchar_t *name, UINT size, wchar_t *arg)
1518 {
1519 	UNI_TOKEN_LIST *t;
1520 	char *path_str;
1521 	wchar_t *path_str_w;
1522 	bool ok = false;
1523 	// Validate arguments
1524 	if (name == NULL || arg == NULL)
1525 	{
1526 		return;
1527 	}
1528 
1529 	path_str = GetCurrentPathEnvStr();
1530 	path_str_w = CopyUtfToUni(path_str);
1531 
1532 	t = ParseSplitedPathW(path_str_w);
1533 
1534 	if (t != NULL)
1535 	{
1536 		UINT i;
1537 		for (i = 0;i < t->NumTokens;i++)
1538 		{
1539 			wchar_t *s = t->Token[i];
1540 			wchar_t tmp[MAX_SIZE];
1541 
1542 			ConbinePathW(tmp, sizeof(tmp), s, arg);
1543 
1544 			if (IsFileExistsInnerW(tmp))
1545 			{
1546 #ifdef	OS_UNIX
1547 				if (UnixCheckExecAccessW(tmp) == false)
1548 				{
1549 					continue;
1550 				}
1551 #endif	// OS_UNIX
1552 				ok = true;
1553 				UniStrCpy(name, size, tmp);
1554 				break;
1555 			}
1556 		}
1557 
1558 		UniFreeToken(t);
1559 	}
1560 
1561 	Free(path_str);
1562 	Free(path_str_w);
1563 
1564 	if (ok == false)
1565 	{
1566 		// In the case of failing to find the path
1567 #ifdef	OS_UNIX
1568 		UnixGetCurrentDirW(name, size);
1569 #else	// OS_UNIX
1570 		Win32GetCurrentDirW(name, size);
1571 #endif	// OS_UNIX
1572 		ConbinePathW(name, size, name, arg);
1573 	}
1574 }
1575 
1576 // Generate a secure file name
MakeSafeFileName(char * dst,UINT size,char * src)1577 void MakeSafeFileName(char *dst, UINT size, char *src)
1578 {
1579 	char tmp[MAX_PATH];
1580 	// Validate arguments
1581 	if (dst == NULL || src == NULL)
1582 	{
1583 		return;
1584 	}
1585 
1586 	StrCpy(tmp, sizeof(tmp), src);
1587 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "..", "__", false);
1588 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "/", "_", false);
1589 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "\\", "_", false);
1590 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "@", "_", false);
1591 	ReplaceStrEx(tmp, sizeof(tmp), tmp, "|", "_", false);
1592 
1593 	StrCpy(dst, size, tmp);
1594 }
MakeSafeFileNameW(wchar_t * dst,UINT size,wchar_t * src)1595 void MakeSafeFileNameW(wchar_t *dst, UINT size, wchar_t *src)
1596 {
1597 	wchar_t tmp[MAX_PATH];
1598 	// Validate arguments
1599 	if (dst == NULL || src == NULL)
1600 	{
1601 		return;
1602 	}
1603 
1604 	UniStrCpy(tmp, sizeof(tmp), src);
1605 	UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"..", L"__", false);
1606 	UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"/", L"_", false);
1607 	UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"\\", L"_", false);
1608 	UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"@", L"_", false);
1609 	UniReplaceStrEx(tmp, sizeof(tmp), tmp, L"|", L"_", false);
1610 
1611 	UniStrCpy(dst, size, tmp);
1612 }
1613 
1614 // Get the file name from the file path
GetFileNameFromFilePathW(wchar_t * dst,UINT size,wchar_t * filepath)1615 void GetFileNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
1616 {
1617 	wchar_t tmp[MAX_SIZE];
1618 	UINT i, len, wp;
1619 	// Validate arguments
1620 	if (dst == NULL || filepath == NULL)
1621 	{
1622 		return;
1623 	}
1624 
1625 	len = MIN(UniStrLen(filepath), (MAX_SIZE - 2));
1626 	wp = 0;
1627 
1628 	for (i = 0;i < (len + 1);i++)
1629 	{
1630 		wchar_t c = filepath[i];
1631 
1632 		switch (c)
1633 		{
1634 		case L'\\':
1635 		case L'/':
1636 		case 0:
1637 			tmp[wp] = 0;
1638 			wp = 0;
1639 			break;
1640 
1641 		default:
1642 			tmp[wp] = c;
1643 			wp++;
1644 			break;
1645 		}
1646 	}
1647 
1648 	UniStrCpy(dst, size, tmp);
1649 }
GetFileNameFromFilePath(char * dst,UINT size,char * filepath)1650 void GetFileNameFromFilePath(char *dst, UINT size, char *filepath)
1651 {
1652 	char tmp[MAX_SIZE];
1653 	UINT i, len, wp;
1654 	// Validate arguments
1655 	if (dst == NULL || filepath == NULL)
1656 	{
1657 		return;
1658 	}
1659 
1660 	len = MIN(StrLen(filepath), (MAX_SIZE - 2));
1661 	wp = 0;
1662 
1663 	for (i = 0;i < (len + 1);i++)
1664 	{
1665 		char c = filepath[i];
1666 
1667 		switch (c)
1668 		{
1669 		case '\\':
1670 		case '/':
1671 		case 0:
1672 			tmp[wp] = 0;
1673 			wp = 0;
1674 			break;
1675 
1676 		default:
1677 			tmp[wp] = c;
1678 			wp++;
1679 			break;
1680 		}
1681 	}
1682 
1683 	StrCpy(dst, size, tmp);
1684 }
GetDirNameFromFilePathW(wchar_t * dst,UINT size,wchar_t * filepath)1685 void GetDirNameFromFilePathW(wchar_t *dst, UINT size, wchar_t *filepath)
1686 {
1687 	wchar_t tmp[MAX_SIZE];
1688 	UINT wp;
1689 	UINT i;
1690 	UINT len;
1691 	// Validate arguments
1692 	if (dst == NULL || filepath == NULL)
1693 	{
1694 		return;
1695 	}
1696 
1697 	UniStrCpy(tmp, sizeof(tmp), filepath);
1698 	if (UniEndWith(tmp, L"\\") || UniEndWith(tmp, L"/"))
1699 	{
1700 		tmp[UniStrLen(tmp) - 1] = 0;
1701 	}
1702 
1703 	len = UniStrLen(tmp);
1704 
1705 	UniStrCpy(dst, size, L"");
1706 
1707 	wp = 0;
1708 
1709 	for (i = 0;i < len;i++)
1710 	{
1711 		wchar_t c = tmp[i];
1712 		if (c == L'/' || c == L'\\')
1713 		{
1714 			tmp[wp++] = 0;
1715 			wp = 0;
1716 			UniStrCat(dst, size, tmp);
1717 			tmp[wp++] = c;
1718 		}
1719 		else
1720 		{
1721 			tmp[wp++] = c;
1722 		}
1723 	}
1724 
1725 	if (UniStrLen(dst) == 0)
1726 	{
1727 		UniStrCpy(dst, size, L"/");
1728 	}
1729 
1730 	NormalizePathW(dst, size, dst);
1731 }
1732 
1733 // Get the directory name from the file path
GetDirNameFromFilePath(char * dst,UINT size,char * filepath)1734 void GetDirNameFromFilePath(char *dst, UINT size, char *filepath)
1735 {
1736 	char tmp[MAX_SIZE];
1737 	UINT wp;
1738 	UINT i;
1739 	UINT len;
1740 	// Validate arguments
1741 	if (dst == NULL || filepath == NULL)
1742 	{
1743 		return;
1744 	}
1745 
1746 	StrCpy(tmp, sizeof(tmp), filepath);
1747 	if (EndWith(tmp, "\\") || EndWith(tmp, "/"))
1748 	{
1749 		tmp[StrLen(tmp) - 1] = 0;
1750 	}
1751 
1752 	len = StrLen(tmp);
1753 
1754 	StrCpy(dst, size, "");
1755 
1756 	wp = 0;
1757 
1758 	for (i = 0;i < len;i++)
1759 	{
1760 		char c = tmp[i];
1761 		if (c == '/' || c == '\\')
1762 		{
1763 			tmp[wp++] = 0;
1764 			wp = 0;
1765 			StrCat(dst, size, tmp);
1766 			tmp[wp++] = c;
1767 		}
1768 		else
1769 		{
1770 			tmp[wp++] = c;
1771 		}
1772 	}
1773 
1774 	if (StrLen(dst) == 0)
1775 	{
1776 		StrCpy(dst, size, "/");
1777 	}
1778 
1779 	NormalizePath(dst, size, dst);
1780 }
1781 
1782 // Combine the two paths
ConbinePath(char * dst,UINT size,char * dirname,char * filename)1783 void ConbinePath(char *dst, UINT size, char *dirname, char *filename)
1784 {
1785 	wchar_t dst_w[MAX_PATH];
1786 	wchar_t *dirname_w = CopyStrToUni(dirname);
1787 	wchar_t *filename_w = CopyStrToUni(filename);
1788 
1789 	ConbinePathW(dst_w, sizeof(dst_w), dirname_w, filename_w);
1790 
1791 	Free(dirname_w);
1792 	Free(filename_w);
1793 
1794 	UniToStr(dst, size, dst_w);
1795 }
ConbinePathW(wchar_t * dst,UINT size,wchar_t * dirname,wchar_t * filename)1796 void ConbinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
1797 {
1798 	bool is_full_path;
1799 	wchar_t tmp[MAX_SIZE];
1800 	wchar_t filename_ident[MAX_SIZE];
1801 	// Validate arguments
1802 	if (dst == NULL || dirname == NULL || filename == NULL)
1803 	{
1804 		return;
1805 	}
1806 
1807 	NormalizePathW(filename_ident, sizeof(filename_ident), filename);
1808 
1809 	is_full_path = false;
1810 
1811 	if (UniStartWith(filename_ident, L"\\") || UniStartWith(filename_ident, L"/"))
1812 	{
1813 		is_full_path = true;
1814 	}
1815 
1816 	filename = &filename_ident[0];
1817 
1818 #ifdef	OS_WIN32
1819 	if (UniStrLen(filename) >= 2)
1820 	{
1821 		if ((L'a' <= filename[0] && filename[0] <= L'z') || (L'A' <= filename[0] && filename[0] <= L'Z'))
1822 		{
1823 			if (filename[1] == L':')
1824 			{
1825 				is_full_path = true;
1826 			}
1827 		}
1828 	}
1829 #endif	// OS_WIN32
1830 
1831 	if (is_full_path == false)
1832 	{
1833 		UniStrCpy(tmp, sizeof(tmp), dirname);
1834 		if (UniEndWith(tmp, L"/") == false && UniEndWith(tmp, L"\\") == false)
1835 		{
1836 			UniStrCat(tmp, sizeof(tmp), L"/");
1837 		}
1838 		UniStrCat(tmp, sizeof(tmp), filename);
1839 	}
1840 	else
1841 	{
1842 		UniStrCpy(tmp, sizeof(tmp), filename);
1843 	}
1844 
1845 	NormalizePathW(dst, size, tmp);
1846 }
CombinePath(char * dst,UINT size,char * dirname,char * filename)1847 void CombinePath(char *dst, UINT size, char *dirname, char *filename)
1848 {
1849 	ConbinePath(dst, size, dirname, filename);
1850 }
CombinePathW(wchar_t * dst,UINT size,wchar_t * dirname,wchar_t * filename)1851 void CombinePathW(wchar_t *dst, UINT size, wchar_t *dirname, wchar_t *filename)
1852 {
1853 	ConbinePathW(dst, size, dirname, filename);
1854 }
1855 
1856 // Check whether the file exists
IsFileExists(char * name)1857 bool IsFileExists(char *name)
1858 {
1859 	wchar_t *name_w = CopyStrToUni(name);
1860 	bool ret = IsFileExistsW(name_w);
1861 
1862 	Free(name_w);
1863 
1864 	return ret;
1865 }
IsFileExistsW(wchar_t * name)1866 bool IsFileExistsW(wchar_t *name)
1867 {
1868 	wchar_t tmp[MAX_SIZE];
1869 	// Validate arguments
1870 	if (name == NULL)
1871 	{
1872 		return false;
1873 	}
1874 
1875 	InnerFilePathW(tmp, sizeof(tmp), name);
1876 
1877 	return IsFileExistsInnerW(tmp);
1878 }
IsFileExistsInner(char * name)1879 bool IsFileExistsInner(char *name)
1880 {
1881 	wchar_t *name_w = CopyStrToUni(name);
1882 	bool ret = IsFileExistsInnerW(name_w);
1883 
1884 	Free(name_w);
1885 
1886 	return ret;
1887 }
IsFileExistsInnerW(wchar_t * name)1888 bool IsFileExistsInnerW(wchar_t *name)
1889 {
1890 	IO *o;
1891 	// Validate arguments
1892 	if (name == NULL)
1893 	{
1894 		return false;
1895 	}
1896 
1897 	o = FileOpenInnerW(name, false, false);
1898 	if (o == NULL)
1899 	{
1900 		return false;
1901 	}
1902 
1903 	FileClose(o);
1904 
1905 	return true;
1906 }
1907 
1908 // Get the current contents of the PATH environment variable
GetCurrentPathEnvStr()1909 char *GetCurrentPathEnvStr()
1910 {
1911 	char tmp[1024];
1912 	char *tag_name;
1913 
1914 #ifdef	OS_WIN32
1915 	tag_name = "Path";
1916 #else	// OS_WIN32
1917 	tag_name = "PATH";
1918 #endif	// OS_WIN32
1919 
1920 	if (GetEnv(tag_name, tmp, sizeof(tmp)) == false)
1921 	{
1922 #ifdef	OS_WIN32
1923 		Win32GetCurrentDir(tmp, sizeof(tmp));
1924 #else	// OS_WIN32
1925 		UnixGetCurrentDir(tmp, sizeof(tmp));
1926 #endif	// OS_WIN32
1927 	}
1928 
1929 	return CopyStr(tmp);
1930 }
1931 
1932 // Get multiple paths separated by colons
ParseSplitedPathW(wchar_t * path)1933 UNI_TOKEN_LIST *ParseSplitedPathW(wchar_t *path)
1934 {
1935 	UNI_TOKEN_LIST *ret;
1936 	wchar_t *tmp = UniCopyStr(path);
1937 	wchar_t *split_str;
1938 	UINT i;
1939 
1940 	UniTrim(tmp);
1941 	UniTrimCrlf(tmp);
1942 	UniTrim(tmp);
1943 	UniTrimCrlf(tmp);
1944 
1945 #ifdef	OS_WIN32
1946 	split_str = L";";
1947 #else	// OS_WIN32
1948 	split_str = L":";
1949 #endif	// OS_WIN32
1950 
1951 	ret = UniParseToken(tmp, split_str);
1952 
1953 	if (ret != NULL)
1954 	{
1955 		for (i = 0;i < ret->NumTokens;i++)
1956 		{
1957 			UniTrim(ret->Token[i]);
1958 			UniTrimCrlf(ret->Token[i]);
1959 			UniTrim(ret->Token[i]);
1960 			UniTrimCrlf(ret->Token[i]);
1961 		}
1962 	}
1963 
1964 	Free(tmp);
1965 
1966 	return ret;
1967 }
ParseSplitedPath(char * path)1968 TOKEN_LIST *ParseSplitedPath(char *path)
1969 {
1970 	TOKEN_LIST *ret;
1971 	char *tmp = CopyStr(path);
1972 	char *split_str;
1973 	UINT i;
1974 
1975 	Trim(tmp);
1976 	TrimCrlf(tmp);
1977 	Trim(tmp);
1978 	TrimCrlf(tmp);
1979 
1980 #ifdef	OS_WIN32
1981 	split_str = ";";
1982 #else	// OS_WIN32
1983 	split_str = ":";
1984 #endif	// OS_WIN32
1985 
1986 	ret = ParseToken(tmp, split_str);
1987 
1988 	if (ret != NULL)
1989 	{
1990 		for (i = 0;i < ret->NumTokens;i++)
1991 		{
1992 			Trim(ret->Token[i]);
1993 			TrimCrlf(ret->Token[i]);
1994 			Trim(ret->Token[i]);
1995 			TrimCrlf(ret->Token[i]);
1996 		}
1997 	}
1998 
1999 	Free(tmp);
2000 
2001 	return ret;
2002 }
2003 
2004 // Get the current directory
GetCurrentDirW(wchar_t * name,UINT size)2005 void GetCurrentDirW(wchar_t *name, UINT size)
2006 {
2007 	// Validate arguments
2008 	if (name == NULL)
2009 	{
2010 		return;
2011 	}
2012 
2013 #ifdef	OS_WIN32
2014 	Win32GetCurrentDirW(name, size);
2015 #else	// OS_WIN32
2016 	UnixGetCurrentDirW(name, size);
2017 #endif	// OS_WIN32
2018 }
GetCurrentDir(char * name,UINT size)2019 void GetCurrentDir(char *name, UINT size)
2020 {
2021 	wchar_t name_w[MAX_PATH];
2022 
2023 	GetCurrentDirW(name_w, sizeof(name_w));
2024 
2025 	UniToStr(name, size, name_w);
2026 }
2027 
2028 // Get the relative path
GetRelativePathW(wchar_t * dst,UINT size,wchar_t * fullpath,wchar_t * basepath)2029 bool GetRelativePathW(wchar_t *dst, UINT size, wchar_t *fullpath, wchar_t *basepath)
2030 {
2031 	wchar_t fullpath2[MAX_SIZE];
2032 	wchar_t basepath2[MAX_SIZE];
2033 	// Validate arguments
2034 	if (dst == NULL || fullpath == NULL || basepath == NULL)
2035 	{
2036 		return false;
2037 	}
2038 	ClearUniStr(dst, size);
2039 
2040 	NormalizePathW(fullpath2, sizeof(fullpath2), fullpath);
2041 	NormalizePathW(basepath2, sizeof(basepath2), basepath);
2042 
2043 #ifdef	OS_WIN32
2044 	UniStrCat(basepath2, sizeof(basepath2), L"\\");
2045 #else	// OS_WIN32
2046 	UniStrCat(basepath2, sizeof(basepath2), L"/");
2047 #endif	// OS_WIN32
2048 
2049 	if (UniStrLen(fullpath2) <= UniStrLen(basepath2))
2050 	{
2051 		return false;
2052 	}
2053 
2054 	if (UniStartWith(fullpath2, basepath2) == false)
2055 	{
2056 		return false;
2057 	}
2058 
2059 	UniStrCpy(dst, size, fullpath2 + UniStrLen(basepath2));
2060 
2061 	return true;
2062 }
GetRelativePath(char * dst,UINT size,char * fullpath,char * basepath)2063 bool GetRelativePath(char *dst, UINT size, char *fullpath, char *basepath)
2064 {
2065 	wchar_t dst_w[MAX_SIZE];
2066 	wchar_t fullpath_w[MAX_SIZE];
2067 	wchar_t basepath_w[MAX_SIZE];
2068 	bool ret;
2069 	// Validate arguments
2070 	if (dst == NULL || fullpath == NULL || basepath == NULL)
2071 	{
2072 		return false;
2073 	}
2074 
2075 	StrToUni(fullpath_w, sizeof(fullpath_w), fullpath);
2076 	StrToUni(basepath_w, sizeof(basepath_w), basepath);
2077 
2078 	ret = GetRelativePathW(dst_w, sizeof(dst_w), fullpath_w, basepath_w);
2079 	if (ret == false)
2080 	{
2081 		return false;
2082 	}
2083 
2084 	UniToStr(dst, size, dst_w);
2085 
2086 	return true;
2087 }
2088 
2089 // Normalize the file path
NormalizePathW(wchar_t * dst,UINT size,wchar_t * src)2090 void NormalizePathW(wchar_t *dst, UINT size, wchar_t *src)
2091 {
2092 	wchar_t tmp[MAX_SIZE];
2093 	UNI_TOKEN_LIST *t;
2094 	bool first_double_slash = false;
2095 	bool first_single_slash = false;
2096 	wchar_t win32_drive_char = 0;
2097 	bool is_full_path = false;
2098 	UINT i;
2099 	SK *sk;
2100 	// Validate arguments
2101 	if (dst == NULL || src == 0)
2102 	{
2103 		return;
2104 	}
2105 
2106 	// Convert the path (Win32, UNIX conversion)
2107 	UniStrCpy(tmp, sizeof(tmp), src);
2108 	ConvertPathW(tmp);
2109 	UniTrim(tmp);
2110 
2111 	// If the path begins with "./ " or " ../", replace it to the current directory
2112 	if (UniStartWith(tmp, L"./") || UniStartWith(tmp, L".\\") ||
2113 		UniStartWith(tmp, L"../") || UniStartWith(tmp, L"..\\") ||
2114 		UniStrCmpi(tmp, L".") == 0 || UniStrCmpi(tmp, L"..") == 0)
2115 	{
2116 		wchar_t cd[MAX_SIZE];
2117 		Zero(cd, sizeof(cd));
2118 
2119 #ifdef	OS_WIN32
2120 		Win32GetCurrentDirW(cd, sizeof(cd));
2121 #else	// OS_WIN32
2122 		UnixGetCurrentDirW(cd, sizeof(cd));
2123 #endif	// OS_WIN32
2124 
2125 		if (UniStartWith(tmp, L".."))
2126 		{
2127 			UniStrCat(cd, sizeof(cd), L"/../");
2128 			UniStrCat(cd, sizeof(cd), tmp + 2);
2129 		}
2130 		else
2131 		{
2132 			UniStrCat(cd, sizeof(cd), L"/");
2133 			UniStrCat(cd, sizeof(cd), tmp);
2134 		}
2135 
2136 		UniStrCpy(tmp, sizeof(tmp), cd);
2137 	}
2138 
2139 	// If the path starts with "~/", replace it with the home directory
2140 	if (UniStartWith(tmp, L"~/") || UniStartWith(tmp, L"~\\"))
2141 	{
2142 		wchar_t tmp2[MAX_SIZE];
2143 		GetHomeDirW(tmp2, sizeof(tmp2));
2144 		UniStrCat(tmp2, sizeof(tmp2), L"/");
2145 		UniStrCat(tmp2, sizeof(tmp2), tmp + 2);
2146 		UniStrCpy(tmp, sizeof(tmp), tmp2);
2147 	}
2148 
2149 	if (UniStartWith(tmp, L"//") || UniStartWith(tmp, L"\\\\"))
2150 	{
2151         // Begin with "//" or "\\"
2152 		first_double_slash = true;
2153 		is_full_path = true;
2154 	}
2155 	else if (UniStartWith(tmp, L"/") || UniStartWith(tmp, L"\\"))
2156 	{
2157 		// Begin with "\"
2158 		first_single_slash = true;
2159 		is_full_path = true;
2160 	}
2161 
2162 #ifdef	OS_WIN32
2163 	if (UniStrLen(tmp) >= 2)
2164 	{
2165 		if (tmp[1] == L':')
2166 		{
2167 			// The drive string representation of the Win32
2168 			wchar_t tmp2[MAX_SIZE];
2169 			is_full_path = true;
2170 			win32_drive_char = tmp[0];
2171 			UniStrCpy(tmp2, sizeof(tmp2), tmp + 2);
2172 			UniStrCpy(tmp, sizeof(tmp), tmp2);
2173 		}
2174 	}
2175 #endif	// OS_WIN32
2176 
2177 	if (UniStrLen(tmp) == 1 && (tmp[0] == L'/' || tmp[0] == L'\\'))
2178 	{
2179 		tmp[0] = 0;
2180 	}
2181 
2182 	// Tokenize
2183 	t = UniParseToken(tmp, L"/\\");
2184 
2185 	sk = NewSk();
2186 
2187 	for (i = 0;i < t->NumTokens;i++)
2188 	{
2189 		wchar_t *s = t->Token[i];
2190 
2191 		if (UniStrCmpi(s, L".") == 0)
2192 		{
2193 			continue;
2194 		}
2195 		else if (UniStrCmpi(s, L"..") == 0)
2196 		{
2197 			if (sk->num_item >= 1 && (first_double_slash == false || sk->num_item >= 2))
2198 			{
2199 				Pop(sk);
2200 			}
2201 		}
2202 		else
2203 		{
2204 			Push(sk, s);
2205 		}
2206 	}
2207 
2208 	// Token concatenation
2209 	UniStrCpy(tmp, sizeof(tmp), L"");
2210 
2211 	if (first_double_slash)
2212 	{
2213 		UniStrCat(tmp, sizeof(tmp), L"//");
2214 	}
2215 	else if (first_single_slash)
2216 	{
2217 		UniStrCat(tmp, sizeof(tmp), L"/");
2218 	}
2219 
2220 	if (win32_drive_char != 0)
2221 	{
2222 		wchar_t d[2];
2223 		d[0] = win32_drive_char;
2224 		d[1] = 0;
2225 		UniStrCat(tmp, sizeof(tmp), d);
2226 		UniStrCat(tmp, sizeof(tmp), L":/");
2227 	}
2228 
2229 	for (i = 0;i < sk->num_item;i++)
2230 	{
2231 		UniStrCat(tmp, sizeof(tmp), (wchar_t *)sk->p[i]);
2232 		if (i != (sk->num_item - 1))
2233 		{
2234 			UniStrCat(tmp, sizeof(tmp), L"/");
2235 		}
2236 	}
2237 
2238 	ReleaseSk(sk);
2239 
2240 	UniFreeToken(t);
2241 
2242 	ConvertPathW(tmp);
2243 
2244 	UniStrCpy(dst, size, tmp);
2245 }
NormalizePath(char * dst,UINT size,char * src)2246 void NormalizePath(char *dst, UINT size, char *src)
2247 {
2248 	wchar_t dst_w[MAX_SIZE];
2249 	wchar_t *src_w = CopyStrToUni(src);
2250 
2251 	NormalizePathW(dst_w, sizeof(dst_w), src_w);
2252 
2253 	Free(src_w);
2254 
2255 	UniToStr(dst, size, dst_w);
2256 }
2257 
2258 // Close and delete the file
FileCloseAndDelete(IO * o)2259 void FileCloseAndDelete(IO *o)
2260 {
2261 	wchar_t *name;
2262 	// Validate arguments
2263 	if (o == NULL)
2264 	{
2265 		return;
2266 	}
2267 
2268 	name = CopyUniStr(o->NameW);
2269 	FileClose(o);
2270 
2271 	FileDeleteW(name);
2272 
2273 	Free(name);
2274 }
2275 
2276 // Rename the file
FileRename(char * old_name,char * new_name)2277 bool FileRename(char *old_name, char *new_name)
2278 {
2279 	wchar_t *old_name_w = CopyStrToUni(old_name);
2280 	wchar_t *new_name_w = CopyStrToUni(new_name);
2281 	bool ret = FileRenameW(old_name_w, new_name_w);
2282 
2283 	Free(old_name_w);
2284 	Free(new_name_w);
2285 
2286 	return ret;
2287 }
FileRenameW(wchar_t * old_name,wchar_t * new_name)2288 bool FileRenameW(wchar_t *old_name, wchar_t *new_name)
2289 {
2290 	wchar_t tmp1[MAX_SIZE];
2291 	wchar_t tmp2[MAX_SIZE];
2292 	// Validate arguments
2293 	if (old_name == NULL || new_name == NULL)
2294 	{
2295 		return false;
2296 	}
2297 
2298 	InnerFilePathW(tmp1, sizeof(tmp1), old_name);
2299 	InnerFilePathW(tmp2, sizeof(tmp2), new_name);
2300 
2301 	return FileRenameInnerW(tmp1, tmp2);
2302 }
FileRenameInner(char * old_name,char * new_name)2303 bool FileRenameInner(char *old_name, char *new_name)
2304 {
2305 	wchar_t *old_name_w = CopyStrToUni(old_name);
2306 	wchar_t *new_name_w = CopyStrToUni(new_name);
2307 	bool ret = FileRenameInnerW(old_name_w, new_name_w);
2308 
2309 	Free(old_name_w);
2310 	Free(new_name_w);
2311 
2312 	return ret;
2313 }
FileRenameInnerW(wchar_t * old_name,wchar_t * new_name)2314 bool FileRenameInnerW(wchar_t *old_name, wchar_t *new_name)
2315 {
2316 	// Validate arguments
2317 	if (old_name == NULL || new_name == NULL)
2318 	{
2319 		return false;
2320 	}
2321 
2322 	return OSFileRenameW(old_name, new_name);
2323 }
2324 
2325 // Convert the path
ConvertPath(char * path)2326 void ConvertPath(char *path)
2327 {
2328 	UINT i, len;
2329 #ifdef	PATH_BACKSLASH
2330 	char new_char = '\\';
2331 #else
2332 	char new_char = '/';
2333 #endif
2334 
2335 	len = StrLen(path);
2336 	for (i = 0;i < len;i++)
2337 	{
2338 		if (path[i] == '\\' || path[i] == '/')
2339 		{
2340 			path[i] = new_char;
2341 		}
2342 	}
2343 }
ConvertPathW(wchar_t * path)2344 void ConvertPathW(wchar_t *path)
2345 {
2346 	UINT i, len;
2347 #ifdef	PATH_BACKSLASH
2348 	wchar_t new_char = L'\\';
2349 #else
2350 	wchar_t new_char = L'/';
2351 #endif
2352 
2353 	len = UniStrLen(path);
2354 	for (i = 0;i < len;i++)
2355 	{
2356 		if (path[i] == L'\\' || path[i] == L'/')
2357 		{
2358 			path[i] = new_char;
2359 		}
2360 	}
2361 }
2362 
2363 // Delete the directory
DeleteDir(char * name)2364 bool DeleteDir(char *name)
2365 {
2366 	wchar_t *name_w = CopyStrToUni(name);
2367 	bool ret = DeleteDirW(name_w);
2368 
2369 	Free(name_w);
2370 
2371 	return ret;
2372 }
DeleteDirW(wchar_t * name)2373 bool DeleteDirW(wchar_t *name)
2374 {
2375 	wchar_t tmp[MAX_SIZE];
2376 	// Validate arguments
2377 	if (name == NULL)
2378 	{
2379 		return false;
2380 	}
2381 
2382 	InnerFilePathW(tmp, sizeof(tmp), name);
2383 
2384 	return DeleteDirInnerW(tmp);
2385 }
DeleteDirInner(char * name)2386 bool DeleteDirInner(char *name)
2387 {
2388 	wchar_t *name_w = CopyStrToUni(name);
2389 	bool ret = DeleteDirInnerW(name_w);
2390 
2391 	Free(name_w);
2392 
2393 	return ret;
2394 }
DeleteDirInnerW(wchar_t * name)2395 bool DeleteDirInnerW(wchar_t *name)
2396 {
2397 	// Validate arguments
2398 	if (name == NULL)
2399 	{
2400 		return false;
2401 	}
2402 
2403 	return OSDeleteDirW(name);
2404 }
2405 
2406 // Generation of internal file path
InnerFilePathW(wchar_t * dst,UINT size,wchar_t * src)2407 void InnerFilePathW(wchar_t *dst, UINT size, wchar_t *src)
2408 {
2409 	// Validate arguments
2410 	if (dst == NULL || src == NULL)
2411 	{
2412 		return;
2413 	}
2414 
2415 	if (src[0] != L'@' && src[0] != L'$')
2416 	{
2417 		NormalizePathW(dst, size, src);
2418 	}
2419 	else if (src[0] == L'$')
2420 	{
2421 		wchar_t dir[MAX_SIZE];
2422 		GetDbDirW(dir, sizeof(dir));
2423 		ConbinePathW(dst, size, dir, &src[1]);
2424 	}
2425 	else
2426 	{
2427 		wchar_t dir[MAX_SIZE];
2428 		GetLogDirW(dir, sizeof(dir));
2429 		ConbinePathW(dst, size, dir, &src[1]);
2430 	}
2431 }
InnerFilePath(char * dst,UINT size,char * src)2432 void InnerFilePath(char *dst, UINT size, char *src)
2433 {
2434 	wchar_t dst_w[MAX_PATH];
2435 	wchar_t *src_w = CopyStrToUni(src);
2436 
2437 	InnerFilePathW(dst_w, sizeof(dst_w), src_w);
2438 
2439 	Free(src_w);
2440 
2441 	UniToStr(dst, size, dst_w);
2442 }
2443 
2444 // Recursive directory creation
MakeDirEx(char * name)2445 bool MakeDirEx(char *name)
2446 {
2447 	bool ret;
2448 	wchar_t *name_w = CopyStrToUni(name);
2449 
2450 	ret = MakeDirExW(name_w);
2451 
2452 	Free(name_w);
2453 
2454 	return ret;
2455 }
MakeDirExW(wchar_t * name)2456 bool MakeDirExW(wchar_t *name)
2457 {
2458 	LIST *o;
2459 	wchar_t tmp[MAX_PATH];
2460 	wchar_t tmp2[MAX_PATH];
2461 	UINT i;
2462 	bool ret;
2463 	// Validate arguments
2464 	if (name == NULL)
2465 	{
2466 		return false;
2467 	}
2468 
2469 	o = NewListFast(NULL);
2470 
2471 	UniStrCpy(tmp, sizeof(tmp), name);
2472 	while (true)
2473 	{
2474 		wchar_t *s = CopyUniStr(tmp);
2475 
2476 		Add(o, s);
2477 
2478 		GetDirNameFromFilePathW(tmp2, sizeof(tmp2), tmp);
2479 
2480 		if (UniStrCmpi(tmp2, tmp) == 0)
2481 		{
2482 			break;
2483 		}
2484 
2485 		UniStrCpy(tmp, sizeof(tmp), tmp2);
2486 	}
2487 
2488 	for (i = 0;i < LIST_NUM(o);i++)
2489 	{
2490 		UINT j = LIST_NUM(o) - i - 1;
2491 		wchar_t *s = LIST_DATA(o, j);
2492 
2493 		if (UniStrCmpi(s, L"\\") != 0 && UniStrCmpi(s, L"/") != 0)
2494 		{
2495 			ret = MakeDirW(s);
2496 		}
2497 	}
2498 
2499 	UniFreeStrList(o);
2500 
2501 	return ret;
2502 }
2503 
2504 // Create a directory
MakeDir(char * name)2505 bool MakeDir(char *name)
2506 {
2507 	wchar_t *name_w = CopyStrToUni(name);
2508 	bool ret = MakeDirW(name_w);
2509 
2510 	Free(name_w);
2511 
2512 	return ret;
2513 }
MakeDirW(wchar_t * name)2514 bool MakeDirW(wchar_t *name)
2515 {
2516 	wchar_t tmp[MAX_SIZE];
2517 	// Validate arguments
2518 	if (name == NULL)
2519 	{
2520 		return false;
2521 	}
2522 
2523 	InnerFilePathW(tmp, sizeof(tmp), name);
2524 
2525 	return MakeDirInnerW(tmp);
2526 }
MakeDirInner(char * name)2527 bool MakeDirInner(char *name)
2528 {
2529 	wchar_t *name_w = CopyStrToUni(name);
2530 	bool ret = MakeDirInnerW(name_w);
2531 
2532 	Free(name_w);
2533 
2534 	return ret;
2535 }
MakeDirInnerW(wchar_t * name)2536 bool MakeDirInnerW(wchar_t *name)
2537 {
2538 	// Validate arguments
2539 	if (name == NULL)
2540 	{
2541 		return false;
2542 	}
2543 
2544 	return OSMakeDirW(name);
2545 }
2546 
2547 // Delete the file
FileDelete(char * name)2548 bool FileDelete(char *name)
2549 {
2550 	wchar_t *name_w = CopyStrToUni(name);
2551 	bool ret = FileDeleteW(name_w);
2552 
2553 	Free(name_w);
2554 
2555 	return ret;
2556 }
FileDeleteW(wchar_t * name)2557 bool FileDeleteW(wchar_t *name)
2558 {
2559 	wchar_t tmp[MAX_SIZE];
2560 	// Validate arguments
2561 	if (name == NULL)
2562 	{
2563 		return false;
2564 	}
2565 
2566 	InnerFilePathW(tmp, sizeof(tmp), name);
2567 
2568 	return FileDeleteInnerW(tmp);
2569 }
FileDeleteInner(char * name)2570 bool FileDeleteInner(char *name)
2571 {
2572 	wchar_t *name_w = CopyStrToUni(name);
2573 	bool ret = FileDeleteInnerW(name_w);
2574 
2575 	Free(name_w);
2576 
2577 	return ret;
2578 }
FileDeleteInnerW(wchar_t * name)2579 bool FileDeleteInnerW(wchar_t *name)
2580 {
2581 	wchar_t name2[MAX_SIZE];
2582 	// Validate arguments
2583 	if (name == NULL)
2584 	{
2585 		return false;
2586 	}
2587 
2588 	UniStrCpy(name2, sizeof(name2), name);
2589 	ConvertPathW(name2);
2590 
2591 	return OSFileDeleteW(name2);
2592 }
2593 
2594 // Seek the file
FileSeek(IO * o,UINT mode,int offset)2595 bool FileSeek(IO *o, UINT mode, int offset)
2596 {
2597 	// Validate arguments
2598 	if (o == NULL)
2599 	{
2600 		return false;
2601 	}
2602 
2603 	if (o->HamMode == false)
2604 	{
2605 		return OSFileSeek(o->pData, mode, offset);
2606 	}
2607 	else
2608 	{
2609 		return false;
2610 	}
2611 }
2612 
2613 // Get the file size by specifying the file name
FileSizeEx(char * name)2614 UINT FileSizeEx(char *name)
2615 {
2616 	wchar_t *name_w = CopyStrToUni(name);
2617 	UINT ret = FileSizeExW(name_w);
2618 
2619 	Free(name_w);
2620 
2621 	return ret;
2622 }
FileSizeExW(wchar_t * name)2623 UINT FileSizeExW(wchar_t *name)
2624 {
2625 	IO *io;
2626 	UINT size;
2627 	// Validate arguments
2628 	if (name == NULL)
2629 	{
2630 		return 0;
2631 	}
2632 
2633 	io = FileOpenW(name, false);
2634 	if (io == NULL)
2635 	{
2636 		return 0;
2637 	}
2638 
2639 	size = FileSize(io);
2640 
2641 	FileClose(io);
2642 
2643 	return size;
2644 }
2645 
2646 // Get the file size
FileSize64(IO * o)2647 UINT64 FileSize64(IO *o)
2648 {
2649 	// Validate arguments
2650 	if (o == NULL)
2651 	{
2652 		return 0;
2653 	}
2654 
2655 	if (o->HamMode == false)
2656 	{
2657 		return OSFileSize(o->pData);
2658 	}
2659 	else
2660 	{
2661 		return (UINT64)o->HamBuf->Size;
2662 	}
2663 }
FileSize(IO * o)2664 UINT FileSize(IO *o)
2665 {
2666 	UINT64 size = (UINT)(FileSize64(o));
2667 
2668 	if (size >= 4294967296ULL)
2669 	{
2670 		size = 4294967295ULL;
2671 	}
2672 
2673 	return (UINT)size;
2674 }
2675 
2676 // Read from a file
FileRead(IO * o,void * buf,UINT size)2677 bool FileRead(IO *o, void *buf, UINT size)
2678 {
2679 	// Validate arguments
2680 	if (o == NULL || buf == NULL)
2681 	{
2682 		return false;
2683 	}
2684 
2685 	// KS
2686 	KS_INC(KS_IO_READ_COUNT);
2687 	KS_ADD(KS_IO_TOTAL_READ_SIZE, size);
2688 
2689 	if (size == 0)
2690 	{
2691 		return true;
2692 	}
2693 
2694 	if (o->HamMode == false)
2695 	{
2696 		return OSFileRead(o->pData, buf, size);
2697 	}
2698 	else
2699 	{
2700 		return ReadBuf(o->HamBuf, buf, size) == size ? true : false;
2701 	}
2702 }
2703 
2704 // Write to a file
FileWrite(IO * o,void * buf,UINT size)2705 bool FileWrite(IO *o, void *buf, UINT size)
2706 {
2707 	// Validate arguments
2708 	if (o == NULL || buf == NULL)
2709 	{
2710 		return false;
2711 	}
2712 	if (o->WriteMode == false)
2713 	{
2714 		return false;
2715 	}
2716 
2717 	// KS
2718 	KS_INC(KS_IO_WRITE_COUNT);
2719 	KS_ADD(KS_IO_TOTAL_WRITE_SIZE, size);
2720 
2721 	if (size == 0)
2722 	{
2723 		return true;
2724 	}
2725 
2726 	return OSFileWrite(o->pData, buf, size);
2727 }
2728 
2729 // Flush the file
FileFlush(IO * o)2730 void FileFlush(IO *o)
2731 {
2732 	// Validate arguments
2733 	if (o == NULL)
2734 	{
2735 		return;
2736 	}
2737 
2738 	if (o->HamMode)
2739 	{
2740 		return;
2741 	}
2742 
2743 	OSFileFlush(o->pData);
2744 }
2745 
2746 // Close the file
FileClose(IO * o)2747 void FileClose(IO *o)
2748 {
2749 	FileCloseEx(o, false);
2750 }
FileCloseEx(IO * o,bool no_flush)2751 void FileCloseEx(IO *o, bool no_flush)
2752 {
2753 	// Validate arguments
2754 	if (o == NULL)
2755 	{
2756 		return;
2757 	}
2758 
2759 	if (o->HamMode == false)
2760 	{
2761 		if (o->WriteMode)
2762 		{
2763 #ifdef	OS_WIN32
2764 			Win32FileSetDate(o->pData, o->SetCreateTime, o->SetUpdateTime);
2765 #endif	// OS_WIN32
2766 		}
2767 
2768 		OSFileClose(o->pData, no_flush);
2769 	}
2770 	else
2771 	{
2772 		FreeBuf(o->HamBuf);
2773 	}
2774 	Free(o);
2775 
2776 	// KS
2777 	KS_INC(KS_IO_CLOSE_COUNT);
2778 }
2779 
2780 // Create a file
FileCreateInner(char * name)2781 IO *FileCreateInner(char *name)
2782 {
2783 	wchar_t *name_w = CopyStrToUni(name);
2784 	IO *ret = FileCreateInnerW(name_w);
2785 
2786 	Free(name_w);
2787 
2788 	return ret;
2789 }
FileCreateInnerW(wchar_t * name)2790 IO *FileCreateInnerW(wchar_t *name)
2791 {
2792 	IO *o;
2793 	void *p;
2794 	wchar_t name2[MAX_SIZE];
2795 	// Validate arguments
2796 	if (name == NULL)
2797 	{
2798 		return NULL;
2799 	}
2800 
2801 	UniStrCpy(name2, sizeof(name2), name);
2802 	ConvertPathW(name2);
2803 
2804 	p = OSFileCreateW(name2);
2805 	if (p == NULL)
2806 	{
2807 		return NULL;
2808 	}
2809 
2810 	o = ZeroMalloc(sizeof(IO));
2811 	o->pData = p;
2812 	UniStrCpy(o->NameW, sizeof(o->NameW), name2);
2813 	UniToStr(o->Name, sizeof(o->Name), o->NameW);
2814 	o->WriteMode = true;
2815 
2816 	// KS
2817 	KS_INC(KS_IO_CREATE_COUNT);
2818 
2819 	return o;
2820 }
FileCreate(char * name)2821 IO *FileCreate(char *name)
2822 {
2823 	wchar_t *name_w = CopyStrToUni(name);
2824 	IO *ret = FileCreateW(name_w);
2825 
2826 	Free(name_w);
2827 
2828 	return ret;
2829 }
FileCreateW(wchar_t * name)2830 IO *FileCreateW(wchar_t *name)
2831 {
2832 	wchar_t tmp[MAX_SIZE];
2833 	// Validate arguments
2834 	if (name == NULL)
2835 	{
2836 		return NULL;
2837 	}
2838 
2839 	InnerFilePathW(tmp, sizeof(tmp), name);
2840 
2841 	return FileCreateInnerW(tmp);
2842 }
2843 
2844 // Write all the data to the file
FileWriteAll(char * name,void * data,UINT size)2845 bool FileWriteAll(char *name, void *data, UINT size)
2846 {
2847 	IO *io;
2848 	// Validate arguments
2849 	if (name == NULL || (data == NULL && size != 0))
2850 	{
2851 		return false;
2852 	}
2853 
2854 	io = FileCreate(name);
2855 
2856 	if (io == NULL)
2857 	{
2858 		return false;
2859 	}
2860 
2861 	FileWrite(io, data, size);
2862 
2863 	FileClose(io);
2864 
2865 	return true;
2866 }
FileWriteAllW(wchar_t * name,void * data,UINT size)2867 bool FileWriteAllW(wchar_t *name, void *data, UINT size)
2868 {
2869 	IO *io;
2870 	// Validate arguments
2871 	if (name == NULL || (data == NULL && size != 0))
2872 	{
2873 		return false;
2874 	}
2875 
2876 	io = FileCreateW(name);
2877 
2878 	if (io == NULL)
2879 	{
2880 		return false;
2881 	}
2882 
2883 	FileWrite(io, data, size);
2884 
2885 	FileClose(io);
2886 
2887 	return true;
2888 }
2889 
2890 // Open the file
FileOpenInner(char * name,bool write_mode,bool read_lock)2891 IO *FileOpenInner(char *name, bool write_mode, bool read_lock)
2892 {
2893 	wchar_t *name_w = CopyStrToUni(name);
2894 	IO *ret = FileOpenInnerW(name_w, write_mode, read_lock);
2895 
2896 	Free(name_w);
2897 
2898 	return ret;
2899 }
FileOpenInnerW(wchar_t * name,bool write_mode,bool read_lock)2900 IO *FileOpenInnerW(wchar_t *name, bool write_mode, bool read_lock)
2901 {
2902 	IO *o;
2903 	void *p;
2904 	wchar_t name2[MAX_SIZE];
2905 	// Validate arguments
2906 	if (name == NULL)
2907 	{
2908 		return NULL;
2909 	}
2910 
2911 	UniStrCpy(name2, sizeof(name2), name);
2912 	ConvertPathW(name2);
2913 
2914 	p = OSFileOpenW(name2, write_mode, read_lock);
2915 	if (p == NULL)
2916 	{
2917 		return NULL;
2918 	}
2919 
2920 	o = ZeroMalloc(sizeof(IO));
2921 	o->pData = p;
2922 	UniStrCpy(o->NameW, sizeof(o->NameW), name2);
2923 	UniToStr(o->Name, sizeof(o->Name), o->NameW);
2924 	o->WriteMode = write_mode;
2925 
2926 #ifdef	OS_WIN32
2927 	Win32FileGetDate(p, &o->GetCreateTime, &o->GetUpdateTime, &o->GetAccessTime);
2928 #endif	// OS_WIN32
2929 
2930 	// KS
2931 	KS_INC(KS_IO_OPEN_COUNT);
2932 
2933 	return o;
2934 }
FileOpen(char * name,bool write_mode)2935 IO *FileOpen(char *name, bool write_mode)
2936 {
2937 	return FileOpenEx(name, write_mode, true);
2938 }
FileOpenW(wchar_t * name,bool write_mode)2939 IO *FileOpenW(wchar_t *name, bool write_mode)
2940 {
2941 	return FileOpenExW(name, write_mode, true);
2942 }
FileOpenEx(char * name,bool write_mode,bool read_lock)2943 IO *FileOpenEx(char *name, bool write_mode, bool read_lock)
2944 {
2945 	wchar_t *name_w = CopyStrToUni(name);
2946 	IO *ret = FileOpenExW(name_w, write_mode, read_lock);
2947 
2948 	Free(name_w);
2949 
2950 	return ret;
2951 }
FileOpenExW(wchar_t * name,bool write_mode,bool read_lock)2952 IO *FileOpenExW(wchar_t *name, bool write_mode, bool read_lock)
2953 {
2954 	wchar_t tmp[MAX_SIZE];
2955 	// Validate arguments
2956 	if (name == NULL)
2957 	{
2958 		return NULL;
2959 	}
2960 
2961 	InnerFilePathW(tmp, sizeof(tmp), name);
2962 
2963 	if (name[0] == L'|')
2964 	{
2965 		IO *o = ZeroMalloc(sizeof(IO));
2966 		name++;
2967 		UniStrCpy(o->NameW, sizeof(o->NameW), name);
2968 		UniToStr(o->Name, sizeof(o->Name), o->NameW);
2969 		o->HamMode = true;
2970 		o->HamBuf = ReadHamcoreW(name);
2971 		if (o->HamBuf == NULL)
2972 		{
2973 			Free(o);
2974 			return NULL;
2975 		}
2976 		return o;
2977 	}
2978 	else
2979 	{
2980 		return FileOpenInnerW(tmp, write_mode, read_lock);
2981 	}
2982 }
2983 
2984 
2985