Coverage Report

Created: 2024-05-20 06:31

/src/clamav/libclamunrar/find.cpp
Line
Count
Source (jump to first uncovered line)
1
#include "rar.hpp"
2
3
FindFile::FindFile()
4
0
{
5
0
  *FindMask=0;
6
0
  FirstCall=true;
7
#ifdef _WIN_ALL
8
  hFind=INVALID_HANDLE_VALUE;
9
#else
10
0
  dirp=NULL;
11
0
#endif
12
0
}
13
14
15
FindFile::~FindFile()
16
0
{
17
#ifdef _WIN_ALL
18
  if (hFind!=INVALID_HANDLE_VALUE)
19
    FindClose(hFind);
20
#else
21
0
  if (dirp!=NULL)
22
0
    closedir(dirp);
23
0
#endif
24
0
}
25
26
27
void FindFile::SetMask(const wchar *Mask)
28
0
{
29
0
  wcsncpyz(FindMask,Mask,ASIZE(FindMask));
30
0
  FirstCall=true;
31
0
}
32
33
34
bool FindFile::Next(FindData *fd,bool GetSymLink)
35
0
{
36
0
  fd->Error=false;
37
0
  if (*FindMask==0)
38
0
    return false;
39
#ifdef _WIN_ALL
40
  if (FirstCall)
41
  {
42
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
43
      return false;
44
  }
45
  else
46
    if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
47
      return false;
48
#else
49
0
  if (FirstCall)
50
0
  {
51
0
    wchar DirName[NM];
52
0
    wcsncpyz(DirName,FindMask,ASIZE(DirName));
53
0
    RemoveNameFromPath(DirName);
54
0
    if (*DirName==0)
55
0
      wcsncpyz(DirName,L".",ASIZE(DirName));
56
0
    char DirNameA[NM];
57
0
    WideToChar(DirName,DirNameA,ASIZE(DirNameA));
58
0
    if ((dirp=opendir(DirNameA))==NULL)
59
0
    {
60
0
      fd->Error=(errno!=ENOENT);
61
0
      return false;
62
0
    }
63
0
  }
64
0
  while (1)
65
0
  {
66
0
    wchar Name[NM];
67
0
    struct dirent *ent=readdir(dirp);
68
0
    if (ent==NULL)
69
0
      return false;
70
0
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
71
0
      continue;
72
0
    if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
73
0
      uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
74
75
0
    if (CmpName(FindMask,Name,MATCH_NAMES))
76
0
    {
77
0
      wchar FullName[NM];
78
0
      wcsncpyz(FullName,FindMask,ASIZE(FullName));
79
0
      *PointToName(FullName)=0;
80
0
      if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
81
0
      {
82
0
        uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
83
0
        return false;
84
0
      }
85
0
      wcsncatz(FullName,Name,ASIZE(FullName));
86
0
      if (!FastFind(FullName,fd,GetSymLink))
87
0
      {
88
0
        ErrHandler.OpenErrorMsg(FullName);
89
0
        continue;
90
0
      }
91
0
      wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
92
0
      break;
93
0
    }
94
0
  }
95
0
#endif
96
0
  fd->Flags=0;
97
0
  fd->IsDir=IsDir(fd->FileAttr);
98
0
  fd->IsLink=IsLink(fd->FileAttr);
99
100
0
  FirstCall=false;
101
0
  wchar *NameOnly=PointToName(fd->Name);
102
0
  if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
103
0
    return Next(fd);
104
0
  return true;
105
0
}
106
107
108
bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
109
0
{
110
0
  fd->Error=false;
111
#ifndef _UNIX
112
  if (IsWildcard(FindMask))
113
    return false;
114
#endif    
115
#ifdef _WIN_ALL
116
  HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
117
  if (hFind==INVALID_HANDLE_VALUE)
118
    return false;
119
  FindClose(hFind);
120
#elif defined(_UNIX)
121
  char FindMaskA[NM];
122
0
  WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
123
124
0
  struct stat st;
125
0
  if (GetSymLink)
126
0
  {
127
0
#ifdef SAVE_LINKS
128
0
    if (lstat(FindMaskA,&st)!=0)
129
#else
130
    if (stat(FindMaskA,&st)!=0)
131
#endif
132
0
    {
133
0
      fd->Error=(errno!=ENOENT);
134
0
      return false;
135
0
    }
136
0
  }
137
0
  else
138
0
    if (stat(FindMaskA,&st)!=0)
139
0
    {
140
0
      fd->Error=(errno!=ENOENT);
141
0
      return false;
142
0
    }
143
0
  fd->FileAttr=st.st_mode;
144
0
  fd->Size=st.st_size;
145
146
0
  File::StatToRarTime(st,&fd->mtime,&fd->ctime,&fd->atime);
147
148
0
  wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
149
0
#endif
150
0
  fd->Flags=0;
151
0
  fd->IsDir=IsDir(fd->FileAttr);
152
0
  fd->IsLink=IsLink(fd->FileAttr);
153
154
0
  return true;
155
0
}
156
157
158
#ifdef _WIN_ALL
159
HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
160
{
161
  WIN32_FIND_DATA FindData;
162
  if (hFind==INVALID_HANDLE_VALUE)
163
  {
164
    hFind=FindFirstFile(Mask,&FindData);
165
    if (hFind==INVALID_HANDLE_VALUE)
166
    {
167
      wchar LongMask[NM];
168
      if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
169
        hFind=FindFirstFile(LongMask,&FindData);
170
    }
171
    if (hFind==INVALID_HANDLE_VALUE)
172
    {
173
      int SysErr=GetLastError();
174
      // We must not issue an error for "file not found" and "path not found",
175
      // because it is normal to not find anything for wildcard mask when
176
      // archiving. Also searching for non-existent file is normal in some
177
      // other modules, like WinRAR scanning for winrar_theme_description.txt
178
      // to check if any themes are available.
179
      fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && 
180
                SysErr!=ERROR_PATH_NOT_FOUND &&
181
                SysErr!=ERROR_NO_MORE_FILES;
182
    }
183
  }
184
  else
185
    if (!FindNextFile(hFind,&FindData))
186
    {
187
      hFind=INVALID_HANDLE_VALUE;
188
      fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
189
    }
190
191
  if (hFind!=INVALID_HANDLE_VALUE)
192
  {
193
    wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
194
    SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
195
    fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
196
    fd->FileAttr=FindData.dwFileAttributes;
197
    fd->ftCreationTime=FindData.ftCreationTime;
198
    fd->ftLastAccessTime=FindData.ftLastAccessTime;
199
    fd->ftLastWriteTime=FindData.ftLastWriteTime;
200
    fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
201
    fd->ctime.SetWinFT(&FindData.ftCreationTime);
202
    fd->atime.SetWinFT(&FindData.ftLastAccessTime);
203
204
205
  }
206
  fd->Flags=0;
207
  return hFind;
208
}
209
#endif
210