xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Common/ArchiveName.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // ArchiveName.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../../C/Sort.h"
6 
7 #include "../../../Common/Wildcard.h"
8 #include "../../../Common/StringToInt.h"
9 
10 #include "../../../Windows/FileDir.h"
11 #include "../../../Windows/FileName.h"
12 
13 #include "ArchiveName.h"
14 #include "ExtractingFilePath.h"
15 
16 using namespace NWindows;
17 using namespace NFile;
18 
19 
20 static const char *g_ArcExts =
21         "7z"
22   "\0"  "zip"
23   "\0"  "tar"
24   "\0"  "wim"
25   "\0";
26 
27 static const char *g_HashExts =
28   "sha256"
29   "\0";
30 
31 
CreateArchiveName(const UStringVector & paths,bool isHash,const NFind::CFileInfo * fi,UString & baseName)32 UString CreateArchiveName(
33     const UStringVector &paths,
34     bool isHash,
35     const NFind::CFileInfo *fi,
36     UString &baseName)
37 {
38   bool keepName = isHash;
39   /*
40   if (paths.Size() == 1)
41   {
42     const UString &name = paths[0];
43     if (name.Len() > 4)
44       if (CompareFileNames(name.RightPtr(4), L".tar") == 0)
45         keepName = true;
46   }
47   */
48 
49   UString name ("Archive");
50   NFind::CFileInfo fi3;
51   if (paths.Size() > 1)
52     fi = NULL;
53   if (!fi && paths.Size() != 0)
54   {
55     const UString &path = paths.Front();
56     if (paths.Size() == 1)
57     {
58       if (fi3.Find(us2fs(path)))
59         fi = &fi3;
60     }
61     else
62     {
63       // we try to use name of parent folder
64       FString dirPrefix;
65       if (NDir::GetOnlyDirPrefix(us2fs(path), dirPrefix))
66       {
67         if (!dirPrefix.IsEmpty() && IsPathSepar(dirPrefix.Back()))
68         {
69          #if defined(_WIN32) && !defined(UNDER_CE)
70           if (NName::IsDriveRootPath_SuperAllowed(dirPrefix))
71           {
72             if (path != fs2us(dirPrefix))
73               name = dirPrefix[dirPrefix.Len() - 3]; // only letter
74           }
75           else
76          #endif
77           {
78             dirPrefix.DeleteBack();
79             if (!dirPrefix.IsEmpty())
80             {
81               const int slash = dirPrefix.ReverseFind_PathSepar();
82               if (slash >= 0 && slash != (int)dirPrefix.Len() - 1)
83                 name = dirPrefix.Ptr(slash + 1);
84               else if (fi3.Find(dirPrefix))
85                 name = fs2us(fi3.Name);
86             }
87           }
88         }
89       }
90     }
91   }
92 
93   if (fi)
94   {
95     name = fs2us(fi->Name);
96     if (!fi->IsDir() && !keepName)
97     {
98       const int dotPos = name.Find(L'.');
99       if (dotPos > 0 && name.Find(L'.', (unsigned)dotPos + 1) < 0)
100         name.DeleteFrom((unsigned)dotPos);
101     }
102   }
103   name = Get_Correct_FsFile_Name(name);
104 
105   CRecordVector<UInt32> ids;
106   bool simple_IsAllowed = true;
107   // for (int y = 0; y < 10000; y++) // for debug
108   {
109     // ids.Clear();
110     UString n;
111 
112     FOR_VECTOR (i, paths)
113     {
114       const UString &a = paths[i];
115       const int slash = a.ReverseFind_PathSepar();
116       // if (name.Len() >= a.Len() - slash + 1) continue;
117       const wchar_t *s = a.Ptr(slash + 1);
118       if (!IsPath1PrefixedByPath2(s, name))
119         continue;
120       s += name.Len();
121       const char *exts = isHash ? g_HashExts : g_ArcExts;
122 
123       for (;;)
124       {
125         const char *ext = exts;
126         const unsigned len = MyStringLen(ext);
127         if (len == 0)
128           break;
129         exts += len + 1;
130         n = s;
131         if (n.Len() <= len)
132           continue;
133         if (!StringsAreEqualNoCase_Ascii(n.RightPtr(len), ext))
134           continue;
135         n.DeleteFrom(n.Len() - len);
136         if (n.Back() != '.')
137           continue;
138         n.DeleteBack();
139         if (n.IsEmpty())
140         {
141           simple_IsAllowed = false;
142           break;
143         }
144         if (n.Len() < 2)
145           continue;
146         if (n[0] != '_')
147           continue;
148         const wchar_t *end;
149         const UInt32 v = ConvertStringToUInt32(n.Ptr(1), &end);
150         if (*end != 0)
151           continue;
152         ids.Add(v);
153         break;
154       }
155     }
156   }
157 
158   baseName = name;
159   if (!simple_IsAllowed)
160   {
161     HeapSort(ids.NonConstData(), ids.Size());
162     UInt32 v = 2;
163     const unsigned num = ids.Size();
164     for (unsigned i = 0; i < num; i++)
165     {
166       const UInt32 id = ids[i];
167       if (id > v)
168         break;
169       if (id == v)
170         v = id + 1;
171     }
172     name.Add_Char('_');
173     name.Add_UInt32(v);
174   }
175   return name;
176 }
177