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