1 // Windows/FileName.cpp
2
3 #include "StdAfx.h"
4
5 #include "FileName.h"
6
7 #ifndef _UNICODE
8 extern bool g_IsNT;
9 #endif
10
11 namespace NWindows {
12 namespace NFile {
13 namespace NName {
14
15 #define IS_SEPAR(c) IS_PATH_SEPAR(c)
16
FindSepar(const wchar_t * s)17 int FindSepar(const wchar_t *s) throw()
18 {
19 for (const wchar_t *p = s;; p++)
20 {
21 const wchar_t c = *p;
22 if (c == 0)
23 return -1;
24 if (IS_SEPAR(c))
25 return (int)(p - s);
26 }
27 }
28
29 #ifndef USE_UNICODE_FSTRING
FindSepar(const FChar * s)30 int FindSepar(const FChar *s) throw()
31 {
32 for (const FChar *p = s;; p++)
33 {
34 const FChar c = *p;
35 if (c == 0)
36 return -1;
37 if (IS_SEPAR(c))
38 return (int)(p - s);
39 }
40 }
41 #endif
42
43 #ifndef USE_UNICODE_FSTRING
NormalizeDirPathPrefix(FString & dirPath)44 void NormalizeDirPathPrefix(FString &dirPath)
45 {
46 if (dirPath.IsEmpty())
47 return;
48 if (!IsPathSepar(dirPath.Back()))
49 dirPath.Add_PathSepar();
50 }
51 #endif
52
NormalizeDirPathPrefix(UString & dirPath)53 void NormalizeDirPathPrefix(UString &dirPath)
54 {
55 if (dirPath.IsEmpty())
56 return;
57 if (!IsPathSepar(dirPath.Back()))
58 dirPath.Add_PathSepar();
59 }
60
61 #define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
62
IsDrivePath(const wchar_t * s)63 bool IsDrivePath(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
64
IsAltPathPrefix(CFSTR s)65 bool IsAltPathPrefix(CFSTR s) throw()
66 {
67 unsigned len = MyStringLen(s);
68 if (len == 0)
69 return false;
70 if (s[len - 1] != ':')
71 return false;
72
73 #if defined(_WIN32) && !defined(UNDER_CE)
74 if (IsDevicePath(s))
75 return false;
76 if (IsSuperPath(s))
77 {
78 s += kSuperPathPrefixSize;
79 len -= kSuperPathPrefixSize;
80 }
81 if (len == 2 && IsDrivePath2(s))
82 return false;
83 #endif
84
85 return true;
86 }
87
88 #if defined(_WIN32) && !defined(UNDER_CE)
89
90 const wchar_t *kSuperPathPrefix = L"\\\\?\\";
91 static const wchar_t *kSuperUncPrefix = L"\\\\?\\UNC\\";
92
93 #define IS_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))
94 #define IS_SUPER_PREFIX(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))
95 #define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))
96
97 #define IS_UNC_WITH_SLASH(s) ( \
98 ((s)[0] == 'U' || (s)[0] == 'u') \
99 && ((s)[1] == 'N' || (s)[1] == 'n') \
100 && ((s)[2] == 'C' || (s)[2] == 'c') \
101 && IS_SEPAR((s)[3]))
102
IsDevicePath(CFSTR s)103 bool IsDevicePath(CFSTR s) throw()
104 {
105 #ifdef UNDER_CE
106
107 s = s;
108 return false;
109 /*
110 // actually we don't know the way to open device file in WinCE.
111 unsigned len = MyStringLen(s);
112 if (len < 5 || len > 5 || memcmp(s, FTEXT("DSK"), 3 * sizeof(FChar)) != 0)
113 return false;
114 if (s[4] != ':')
115 return false;
116 // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));
117 */
118
119 #else
120
121 if (!IS_DEVICE_PATH(s))
122 return false;
123 unsigned len = MyStringLen(s);
124 if (len == 6 && s[5] == ':')
125 return true;
126 if (len < 18 || len > 22 || memcmp(s + kDevicePathPrefixSize, FTEXT("PhysicalDrive"), 13 * sizeof(FChar)) != 0)
127 return false;
128 for (unsigned i = 17; i < len; i++)
129 if (s[i] < '0' || s[i] > '9')
130 return false;
131 return true;
132
133 #endif
134 }
135
IsSuperUncPath(CFSTR s)136 bool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
IsNetworkPath(CFSTR s)137 bool IsNetworkPath(CFSTR s) throw()
138 {
139 if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
140 return false;
141 if (IsSuperUncPath(s))
142 return true;
143 FChar c = s[2];
144 return (c != '.' && c != '?');
145 }
146
GetNetworkServerPrefixSize(CFSTR s)147 unsigned GetNetworkServerPrefixSize(CFSTR s) throw()
148 {
149 if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))
150 return 0;
151 unsigned prefixSize = 2;
152 if (IsSuperUncPath(s))
153 prefixSize = kSuperUncPathPrefixSize;
154 else
155 {
156 FChar c = s[2];
157 if (c == '.' || c == '?')
158 return 0;
159 }
160 int pos = FindSepar(s + prefixSize);
161 if (pos < 0)
162 return 0;
163 return prefixSize + pos + 1;
164 }
165
IsNetworkShareRootPath(CFSTR s)166 bool IsNetworkShareRootPath(CFSTR s) throw()
167 {
168 unsigned prefixSize = GetNetworkServerPrefixSize(s);
169 if (prefixSize == 0)
170 return false;
171 s += prefixSize;
172 int pos = FindSepar(s);
173 if (pos < 0)
174 return true;
175 return s[(unsigned)pos + 1] == 0;
176 }
177
178 static const unsigned kDrivePrefixSize = 3; /* c:\ */
179
IsDrivePath2(const wchar_t * s)180 bool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
181 // bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
IsSuperPath(const wchar_t * s)182 bool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }
IsSuperOrDevicePath(const wchar_t * s)183 bool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
184 // bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }
185
186 #ifndef USE_UNICODE_FSTRING
IsDrivePath2(CFSTR s)187 bool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }
188 // bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }
IsDrivePath(CFSTR s)189 bool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }
IsSuperPath(CFSTR s)190 bool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }
IsSuperOrDevicePath(CFSTR s)191 bool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }
192 #endif // USE_UNICODE_FSTRING
193
194 /*
195 bool IsDrivePath_SuperAllowed(CFSTR s)
196 {
197 if (IsSuperPath(s))
198 s += kSuperPathPrefixSize;
199 return IsDrivePath(s);
200 }
201 */
202
IsDriveRootPath_SuperAllowed(CFSTR s)203 bool IsDriveRootPath_SuperAllowed(CFSTR s) throw()
204 {
205 if (IsSuperPath(s))
206 s += kSuperPathPrefixSize;
207 return IsDrivePath(s) && s[kDrivePrefixSize] == 0;
208 }
209
IsAbsolutePath(const wchar_t * s)210 bool IsAbsolutePath(const wchar_t *s) throw()
211 {
212 return IS_SEPAR(s[0]) || IsDrivePath2(s);
213 }
214
FindAltStreamColon(CFSTR path)215 int FindAltStreamColon(CFSTR path)
216 {
217 unsigned i = 0;
218 if (IsDrivePath2(path))
219 i = 2;
220 int colonPos = -1;
221 for (;; i++)
222 {
223 FChar c = path[i];
224 if (c == 0)
225 return colonPos;
226 if (c == ':')
227 {
228 if (colonPos < 0)
229 colonPos = i;
230 continue;
231 }
232 if (IS_SEPAR(c))
233 colonPos = -1;
234 }
235 }
236
237 #ifndef USE_UNICODE_FSTRING
238
GetRootPrefixSize_Of_NetworkPath(CFSTR s)239 static unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)
240 {
241 // Network path: we look "server\path\" as root prefix
242 int pos = FindSepar(s);
243 if (pos < 0)
244 return 0;
245 int pos2 = FindSepar(s + (unsigned)pos + 1);
246 if (pos2 < 0)
247 return 0;
248 return pos + pos2 + 2;
249 }
250
GetRootPrefixSize_Of_SimplePath(CFSTR s)251 static unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)
252 {
253 if (IsDrivePath(s))
254 return kDrivePrefixSize;
255 if (!IS_SEPAR(s[0]))
256 return 0;
257 if (s[1] == 0 || !IS_SEPAR(s[1]))
258 return 1;
259 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
260 return (size == 0) ? 0 : 2 + size;
261 }
262
GetRootPrefixSize_Of_SuperPath(CFSTR s)263 static unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)
264 {
265 if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
266 {
267 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
268 return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
269 }
270 // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
271 int pos = FindSepar(s + kSuperPathPrefixSize);
272 if (pos < 0)
273 return 0;
274 return kSuperPathPrefixSize + pos + 1;
275 }
276
GetRootPrefixSize(CFSTR s)277 unsigned GetRootPrefixSize(CFSTR s)
278 {
279 if (IS_DEVICE_PATH(s))
280 return kDevicePathPrefixSize;
281 if (IsSuperPath(s))
282 return GetRootPrefixSize_Of_SuperPath(s);
283 return GetRootPrefixSize_Of_SimplePath(s);
284 }
285
286 #endif // USE_UNICODE_FSTRING
287
GetRootPrefixSize_Of_NetworkPath(const wchar_t * s)288 static unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s)
289 {
290 // Network path: we look "server\path\" as root prefix
291 int pos = FindSepar(s);
292 if (pos < 0)
293 return 0;
294 int pos2 = FindSepar(s + (unsigned)pos + 1);
295 if (pos2 < 0)
296 return 0;
297 return pos + pos2 + 2;
298 }
299
GetRootPrefixSize_Of_SimplePath(const wchar_t * s)300 static unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s)
301 {
302 if (IsDrivePath(s))
303 return kDrivePrefixSize;
304 if (!IS_SEPAR(s[0]))
305 return 0;
306 if (s[1] == 0 || !IS_SEPAR(s[1]))
307 return 1;
308 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);
309 return (size == 0) ? 0 : 2 + size;
310 }
311
GetRootPrefixSize_Of_SuperPath(const wchar_t * s)312 static unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s)
313 {
314 if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))
315 {
316 unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);
317 return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;
318 }
319 // we support \\?\c:\ paths and volume GUID paths \\?\Volume{GUID}\"
320 int pos = FindSepar(s + kSuperPathPrefixSize);
321 if (pos < 0)
322 return 0;
323 return kSuperPathPrefixSize + pos + 1;
324 }
325
GetRootPrefixSize(const wchar_t * s)326 unsigned GetRootPrefixSize(const wchar_t *s) throw()
327 {
328 if (IS_DEVICE_PATH(s))
329 return kDevicePathPrefixSize;
330 if (IsSuperPath(s))
331 return GetRootPrefixSize_Of_SuperPath(s);
332 return GetRootPrefixSize_Of_SimplePath(s);
333 }
334
335 #else // _WIN32
336
IsAbsolutePath(const wchar_t * s)337 bool IsAbsolutePath(const wchar_t *s) { return IS_SEPAR(s[0]); }
338
339 #ifndef USE_UNICODE_FSTRING
GetRootPrefixSize(CFSTR s)340 unsigned GetRootPrefixSize(CFSTR s) { return IS_SEPAR(s[0]) ? 1 : 0; }
341 #endif
GetRootPrefixSize(const wchar_t * s)342 unsigned GetRootPrefixSize(const wchar_t *s) { return IS_SEPAR(s[0]) ? 1 : 0; }
343
344 #endif // _WIN32
345
346
347 #ifndef UNDER_CE
348
GetCurDir(UString & path)349 static bool GetCurDir(UString &path)
350 {
351 path.Empty();
352 DWORD needLength;
353 #ifndef _UNICODE
354 if (!g_IsNT)
355 {
356 TCHAR s[MAX_PATH + 2];
357 s[0] = 0;
358 needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);
359 path = fs2us(fas2fs(s));
360 }
361 else
362 #endif
363 {
364 WCHAR s[MAX_PATH + 2];
365 s[0] = 0;
366 needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
367 path = s;
368 }
369 return (needLength > 0 && needLength <= MAX_PATH);
370 }
371
ResolveDotsFolders(UString & s)372 static bool ResolveDotsFolders(UString &s)
373 {
374 #ifdef _WIN32
375 // s.Replace(L'/', WCHAR_PATH_SEPARATOR);
376 #endif
377
378 for (unsigned i = 0;;)
379 {
380 const wchar_t c = s[i];
381 if (c == 0)
382 return true;
383 if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
384 {
385 const wchar_t c1 = s[i + 1];
386 if (c1 == '.')
387 {
388 const wchar_t c2 = s[i + 2];
389 if (IS_SEPAR(c2) || c2 == 0)
390 {
391 if (i == 0)
392 return false;
393 int k = i - 2;
394 i += 2;
395
396 for (;; k--)
397 {
398 if (k < 0)
399 return false;
400 if (!IS_SEPAR(s[(unsigned)k]))
401 break;
402 }
403
404 do
405 k--;
406 while (k >= 0 && !IS_SEPAR(s[(unsigned)k]));
407
408 unsigned num;
409
410 if (k >= 0)
411 {
412 num = i - k;
413 i = k;
414 }
415 else
416 {
417 num = (c2 == 0 ? i : (i + 1));
418 i = 0;
419 }
420
421 s.Delete(i, num);
422 continue;
423 }
424 }
425 else if (IS_SEPAR(c1) || c1 == 0)
426 {
427 unsigned num = 2;
428 if (i != 0)
429 i--;
430 else if (c1 == 0)
431 num = 1;
432 s.Delete(i, num);
433 continue;
434 }
435 }
436
437 i++;
438 }
439 }
440
441 #endif // UNDER_CE
442
443 #define LONG_PATH_DOTS_FOLDERS_PARSING
444
445
446 /*
447 Windows (at least 64-bit XP) can't resolve "." or ".." in paths that start with SuperPrefix \\?\
448 To solve that problem we check such path:
449 - super path contains "." or ".." - we use kSuperPathType_UseOnlySuper
450 - super path doesn't contain "." or ".." - we use kSuperPathType_UseOnlyMain
451 */
452 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
453 #ifndef UNDER_CE
AreThereDotsFolders(CFSTR s)454 static bool AreThereDotsFolders(CFSTR s)
455 {
456 for (unsigned i = 0;; i++)
457 {
458 FChar c = s[i];
459 if (c == 0)
460 return false;
461 if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))
462 {
463 FChar c1 = s[i + 1];
464 if (c1 == 0 || IS_SEPAR(c1) ||
465 (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))
466 return true;
467 }
468 }
469 }
470 #endif
471 #endif // LONG_PATH_DOTS_FOLDERS_PARSING
472
473 #ifdef WIN_LONG_PATH
474
475 /*
476 Most of Windows versions have problems, if some file or dir name
477 contains '.' or ' ' at the end of name (Bad Path).
478 To solve that problem, we always use Super Path ("\\?\" prefix and full path)
479 in such cases. Note that "." and ".." are not bad names.
480
481 There are 3 cases:
482 1) If the path is already Super Path, we use that path
483 2) If the path is not Super Path :
484 2.1) Bad Path; we use only Super Path.
485 2.2) Good Path; we use Main Path. If it fails, we use Super Path.
486
487 NeedToUseOriginalPath returns:
488 kSuperPathType_UseOnlyMain : Super already
489 kSuperPathType_UseOnlySuper : not Super, Bad Path
490 kSuperPathType_UseMainAndSuper : not Super, Good Path
491 */
492
GetUseSuperPathType(CFSTR s)493 int GetUseSuperPathType(CFSTR s) throw()
494 {
495 if (IsSuperOrDevicePath(s))
496 {
497 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
498 if ((s)[2] != '.')
499 if (AreThereDotsFolders(s + kSuperPathPrefixSize))
500 return kSuperPathType_UseOnlySuper;
501 #endif
502 return kSuperPathType_UseOnlyMain;
503 }
504
505 for (unsigned i = 0;; i++)
506 {
507 FChar c = s[i];
508 if (c == 0)
509 return kSuperPathType_UseMainAndSuper;
510 if (c == '.' || c == ' ')
511 {
512 FChar c2 = s[i + 1];
513 if (c2 == 0 || IS_SEPAR(c2))
514 {
515 // if it's "." or "..", it's not bad name.
516 if (c == '.')
517 {
518 if (i == 0 || IS_SEPAR(s[i - 1]))
519 continue;
520 if (s[i - 1] == '.')
521 {
522 if (i - 1 == 0 || IS_SEPAR(s[i - 2]))
523 continue;
524 }
525 }
526 return kSuperPathType_UseOnlySuper;
527 }
528 }
529 }
530 }
531
532
533 /*
534 returns false in two cases:
535 - if GetCurDir was used, and GetCurDir returned error.
536 - if we can't resolve ".." name.
537 if path is ".", "..", res is empty.
538 if it's Super Path already, res is empty.
539 for \**** , and if GetCurDir is not drive (c:\), res is empty
540 for absolute paths, returns true, res is Super path.
541 */
542
543
GetSuperPathBase(CFSTR s,UString & res)544 static bool GetSuperPathBase(CFSTR s, UString &res)
545 {
546 res.Empty();
547
548 FChar c = s[0];
549 if (c == 0)
550 return true;
551 if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
552 return true;
553
554 if (IsSuperOrDevicePath(s))
555 {
556 #ifdef LONG_PATH_DOTS_FOLDERS_PARSING
557
558 if ((s)[2] == '.')
559 return true;
560
561 // we will return true here, so we will try to use these problem paths.
562
563 if (!AreThereDotsFolders(s + kSuperPathPrefixSize))
564 return true;
565
566 UString temp = fs2us(s);
567 unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp);
568 if (fixedSize == 0)
569 return true;
570
571 UString rem = &temp[fixedSize];
572 if (!ResolveDotsFolders(rem))
573 return true;
574
575 temp.DeleteFrom(fixedSize);
576 res += temp;
577 res += rem;
578
579 #endif
580
581 return true;
582 }
583
584 if (IS_SEPAR(c))
585 {
586 if (IS_SEPAR(s[1]))
587 {
588 UString temp = fs2us(s + 2);
589 unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);
590 // we ignore that error to allow short network paths server\share?
591 /*
592 if (fixedSize == 0)
593 return false;
594 */
595 UString rem = &temp[fixedSize];
596 if (!ResolveDotsFolders(rem))
597 return false;
598 res += kSuperUncPrefix;
599 temp.DeleteFrom(fixedSize);
600 res += temp;
601 res += rem;
602 return true;
603 }
604 }
605 else
606 {
607 if (IsDrivePath2(s))
608 {
609 UString temp = fs2us(s);
610 unsigned prefixSize = 2;
611 if (IsDrivePath(s))
612 prefixSize = kDrivePrefixSize;
613 UString rem = temp.Ptr(prefixSize);
614 if (!ResolveDotsFolders(rem))
615 return true;
616 res += kSuperPathPrefix;
617 temp.DeleteFrom(prefixSize);
618 res += temp;
619 res += rem;
620 return true;
621 }
622 }
623
624 UString curDir;
625 if (!GetCurDir(curDir))
626 return false;
627 NormalizeDirPathPrefix(curDir);
628
629 unsigned fixedSizeStart = 0;
630 unsigned fixedSize = 0;
631 const wchar_t *superMarker = NULL;
632 if (IsSuperPath(curDir))
633 {
634 fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
635 if (fixedSize == 0)
636 return false;
637 }
638 else
639 {
640 if (IsDrivePath(curDir))
641 {
642 superMarker = kSuperPathPrefix;
643 fixedSize = kDrivePrefixSize;
644 }
645 else
646 {
647 if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
648 return false;
649 fixedSizeStart = 2;
650 fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
651 if (fixedSize == 0)
652 return false;
653 superMarker = kSuperUncPrefix;
654 }
655 }
656
657 UString temp;
658 if (IS_SEPAR(c))
659 {
660 temp = fs2us(s + 1);
661 }
662 else
663 {
664 temp += &curDir[fixedSizeStart + fixedSize];
665 temp += fs2us(s);
666 }
667 if (!ResolveDotsFolders(temp))
668 return false;
669 if (superMarker)
670 res += superMarker;
671 res += curDir.Mid(fixedSizeStart, fixedSize);
672 res += temp;
673 return true;
674 }
675
676
677 /*
678 In that case if GetSuperPathBase doesn't return new path, we don't need
679 to use same path that was used as main path
680
681 GetSuperPathBase superPath.IsEmpty() onlyIfNew
682 false * * GetCurDir Error
683 true false * use Super path
684 true true true don't use any path, we already used mainPath
685 true true false use main path as Super Path, we don't try mainMath
686 That case is possible now if GetCurDir returns unknow
687 type of path (not drive and not network)
688
689 We can change that code if we want to try mainPath, if GetSuperPathBase returns error,
690 and we didn't try mainPath still.
691 If we want to work that way, we don't need to use GetSuperPathBase return code.
692 */
693
GetSuperPath(CFSTR path,UString & superPath,bool onlyIfNew)694 bool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)
695 {
696 if (GetSuperPathBase(path, superPath))
697 {
698 if (superPath.IsEmpty())
699 {
700 // actually the only possible when onlyIfNew == true and superPath is empty
701 // is case when
702
703 if (onlyIfNew)
704 return false;
705 superPath = fs2us(path);
706 }
707 return true;
708 }
709 return false;
710 }
711
GetSuperPaths(CFSTR s1,CFSTR s2,UString & d1,UString & d2,bool onlyIfNew)712 bool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)
713 {
714 if (!GetSuperPathBase(s1, d1) ||
715 !GetSuperPathBase(s2, d2))
716 return false;
717 if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)
718 return false;
719 if (d1.IsEmpty()) d1 = fs2us(s1);
720 if (d2.IsEmpty()) d2 = fs2us(s2);
721 return true;
722 }
723
724
725 /*
726 // returns true, if we need additional use with New Super path.
727 bool GetSuperPath(CFSTR path, UString &superPath)
728 {
729 if (GetSuperPathBase(path, superPath))
730 return !superPath.IsEmpty();
731 return false;
732 }
733 */
734 #endif // WIN_LONG_PATH
735
GetFullPath(CFSTR dirPrefix,CFSTR s,FString & res)736 bool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)
737 {
738 res = s;
739
740 #ifdef UNDER_CE
741
742 if (!IS_SEPAR(s[0]))
743 {
744 if (!dirPrefix)
745 return false;
746 res = dirPrefix;
747 res += s;
748 }
749
750 #else
751
752 unsigned prefixSize = GetRootPrefixSize(s);
753 if (prefixSize != 0)
754 {
755 if (!AreThereDotsFolders(s + prefixSize))
756 return true;
757
758 UString rem = fs2us(s + prefixSize);
759 if (!ResolveDotsFolders(rem))
760 return true; // maybe false;
761 res.DeleteFrom(prefixSize);
762 res += us2fs(rem);
763 return true;
764 }
765
766 /*
767 FChar c = s[0];
768 if (c == 0)
769 return true;
770 if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
771 return true;
772 if (IS_SEPAR(c) && IS_SEPAR(s[1]))
773 return true;
774 if (IsDrivePath(s))
775 return true;
776 */
777
778 UString curDir;
779 if (dirPrefix)
780 curDir = fs2us(dirPrefix);
781 else
782 {
783 if (!GetCurDir(curDir))
784 return false;
785 }
786 NormalizeDirPathPrefix(curDir);
787
788 unsigned fixedSize = 0;
789
790 #ifdef _WIN32
791
792 if (IsSuperPath(curDir))
793 {
794 fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);
795 if (fixedSize == 0)
796 return false;
797 }
798 else
799 {
800 if (IsDrivePath(curDir))
801 fixedSize = kDrivePrefixSize;
802 else
803 {
804 if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))
805 return false;
806 fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));
807 if (fixedSize == 0)
808 return false;
809 fixedSize += 2;
810 }
811 }
812
813 #endif // _WIN32
814
815 UString temp;
816 if (IS_SEPAR(s[0]))
817 {
818 temp = fs2us(s + 1);
819 }
820 else
821 {
822 temp += curDir.Ptr(fixedSize);
823 temp += fs2us(s);
824 }
825 if (!ResolveDotsFolders(temp))
826 return false;
827 curDir.DeleteFrom(fixedSize);
828 res = us2fs(curDir);
829 res += us2fs(temp);
830
831 #endif // UNDER_CE
832
833 return true;
834 }
835
GetFullPath(CFSTR path,FString & fullPath)836 bool GetFullPath(CFSTR path, FString &fullPath)
837 {
838 return GetFullPath(NULL, path, fullPath);
839 }
840
841 }}}
842