ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
ftree.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
10#include "alib/files/ftools.hpp"
11#include "alib/alox.hpp"
12
13#if ALIB_DEBUG
14# if !defined(HPP_ALIB_LANG_FORMAT_FORMATTER)
16# endif
17#endif
18
19#if !defined ( _WIN32 )
20# include <pwd.h>
21# include <grp.h>
22#endif
23namespace alib::files {
24
25
26//==================================================================================================
27//=== FTree
28//==================================================================================================
31{
32 // todo: add some log statements
33 ALIB_DBG( if( alib::FILES.IsBootstrapped())
34 {
35 Log_SetDomain( "ALIB/FILES", Scope::Path)
36 Log_SetDomain( "FTREE" , Scope::Filename)
37 } )
38
40}
41
43{
45 "CAMP/FILES", "Given node is not a directory.")
46
47 FInfo::DirectorySums& sums= node.Value().Sums();
49 node.GoToFirstChild();
50 while( node.IsValid())
51 {
52 FInfo& v= node.Value();
53 sums.TypeCounters[int(v.Type())]++;
54 if( v.IsDirectory() )
55 sums+= v.Sums();
56
57 node.GoToNextSibling();
58 }
59}
60
61void FTree::AllocateExtendedInfo(Cursor& node, String& symLinkDest, String& symLinkRealPath)
62{
64 || node.Value().Type() == FInfo::Types::SYMBOLIC_LINK
65 || node.Value().Type() == FInfo::Types::SYMBOLIC_LINK_DIR,
66 "CAMP/FILES", "Given node is not a directory or symbolic link.")
67
69 == symLinkDest.IsEmpty(),
70 "CAMP/FILES", "Error in symbolic link parameter" )
71
72
73 auto& v = node.Value();
74 auto* ma= GetAllocator();
75 ALIB_ASSERT_ERROR( v.GetExtendedInfo() == nullptr, "CAMP/FILES", "Already set")
76
78 switch (v.Type())
79 {
81 {
82 if( recyclerEIDir != nullptr )
83 {
84 auto* recycled= recyclerEIDir;
85 recyclerEIDir= recycled->next;
86 recycled->data= FInfo::EIDirectory();
87 v.SetExtendedInfo(&recycled->data);
88 return;
89 }
90
91 v.SetExtendedInfo( &ma->Emplace<LinkedEIDir>()->data );
92 }
93 return;
94
96 {
97 if( recyclerEISL != nullptr )
98 {
99 auto* recycled= recyclerEISL;
100 recyclerEISL= recycled->next;
101 recycled->data= FInfo::EISymLinkFile();
102 v.SetExtendedInfo(&recycled->data);
103 }
104 else
105 v.SetExtendedInfo( &ma->Emplace<LinkedEISL>()->data );
106 v.SetLinkTarget(symLinkDest, symLinkRealPath);
107 }
108 return;
109
111 {
112 if( recyclerEISlDir != nullptr )
113 {
114 auto* recycled= recyclerEISlDir;
115 recyclerEISlDir= recycled->next;
116 recycled->data= FInfo::EISymLinkDir();
117 v.SetExtendedInfo(&recycled->data);
118 }
119 else
120 v.SetExtendedInfo( &ma->Emplace<LinkedEISLDir>()->data );
121 v.SetLinkTarget(symLinkDest, symLinkRealPath);
122 }
123 return;
124 default:
125 return;
126 }
128}
129
131{
132 int result= 0;
133 if( type == FInfo::Types::DIRECTORY )
134 {
135 auto* act= recyclerEIDir;
136 while( act )
137 {
138 ++result;
139 act= act->next;
140 }
141 return result;
142 }
143
144 if( type == FInfo::Types::SYMBOLIC_LINK )
145 {
146 auto* act= recyclerEISL;
147 while( act )
148 {
149 ++result;
150 act= act->next;
151 }
152 return result;
153 }
154
156 {
157 auto* act= recyclerEISlDir;
158 while( act )
159 {
160 ++result;
161 act= act->next;
162 }
163 return result;
164 }
165
166 ALIB_ERROR( "CAMP/FILES", "No extended information for type {!Q}", type )
167 return 0;
168}
169
170
171//==================================================================================================
172//=== Debug Dump
173//==================================================================================================
174
175#if ALIB_DEBUG && !defined(ALIB_DOX)
176namespace {
177void dbgDumpEntry( AString& buf ,
178 OwnerAndGroupResolver& ogResolver,
179 SPFormatter fmt ,
180 const int* nameWidth,
181 const FTree::Cursor& node )
182{
183 String32 bufPerms;
184
185 auto& entry= node.Value();
186 std::pair<String,String> ownerAndGroup= ogResolver.Get( entry );
187
188 auto type= entry.Type();
189
190 String128 bufSize;
191 uinteger size= entry.Size();
192 if( size <1000 )
193 fmt->Format( bufSize, "{:5}" , size );
194 else
195 {
196 uinteger ks= 1024;
197 for( const char* entity : {"K", "M", "G", "T" , "P", "E" } )
198 {
199 if( size < ks*1000 )
200 {
201 fmt->Format( bufSize, "{:5.1}{}", double(size) / double(ks), entity );
202 break;
203 }
204 ks*= 1024;
205 }
206 }
207
208
209 auto quality= entry.Quality();
210
211 String128 bufSizes;
212 if( ( type == FInfo::Types::DIRECTORY
214 && quality == FInfo::Qualities::RECURSIVE )
215 {
216 FInfo::DirectorySums& dirInfo= entry.Sums();
217 fmt->Format( bufSizes, "({}d, {}f, {}ea, {}bl)",
218 dirInfo.CountDirectories(),
219 dirInfo.CountNonDirectories(),
220 dirInfo.QtyErrsAccess,
221 dirInfo.QtyErrsBrokenLink );
222 }
223 String scanResultText;
224 switch (quality)
225 {
226 case FInfo::Qualities::NONE: scanResultText= A_CHAR("---"); break;
227 case FInfo::Qualities::STATS: entry.IsDirectory() ? scanResultText= A_CHAR("sta")
228 : scanResultText= A_CHAR("OK "); break;
229 case FInfo::Qualities::RESOLVED: scanResultText= A_CHAR("res"); break;
230 case FInfo::Qualities::RECURSIVE: scanResultText= A_CHAR("OK "); break;
231
232 case FInfo::Qualities::MAX_DEPTH_REACHED: scanResultText= A_CHAR("MXD"); break;
233 case FInfo::Qualities::NOT_FOLLOWED: scanResultText= A_CHAR("NOF"); break;
234 case FInfo::Qualities::NOT_CROSSING_FS: scanResultText= A_CHAR("NOX"); break;
235 case FInfo::Qualities::NO_AFS: scanResultText= A_CHAR("AFS"); break;
236
237 case FInfo::Qualities::NO_ACCESS: scanResultText= A_CHAR("NA "); break;
238 case FInfo::Qualities::NO_ACCESS_SL: scanResultText= A_CHAR("NAL"); break;
239 case FInfo::Qualities::NO_ACCESS_SL_TARGET: scanResultText= A_CHAR("NAT"); break;
240 case FInfo::Qualities::NO_ACCESS_DIR: scanResultText= A_CHAR("NAD"); break;
241 case FInfo::Qualities::BROKEN_LINK: scanResultText= A_CHAR("BRL"); break;
242 case FInfo::Qualities::CIRCULAR_LINK: scanResultText= A_CHAR("CIL"); break;
243 case FInfo::Qualities::DUPLICATE: scanResultText= A_CHAR("DBL"); break;
244 case FInfo::Qualities::NOT_EXISTENT: scanResultText= A_CHAR("NEX"); break;
245 case FInfo::Qualities::UNKNOWN_ERROR: scanResultText= A_CHAR("UKN"); break;
246 }
247
248 String4K symlinkInfo;
249 if( ( type == FInfo::Types::SYMBOLIC_LINK
251 && entry.Quality() >= FInfo::Qualities::RESOLVED )
252 {
253 symlinkInfo << " -> " << entry.GetLinkTarget();
254 if( entry.GetRealLinkTarget().IsNotEmpty()
255 && !entry.GetLinkTarget().Equals( entry.GetRealLinkTarget()) )
256 symlinkInfo << " (" << entry.GetRealLinkTarget() << ")";
257 if( quality == FInfo::Qualities::BROKEN_LINK )
258 symlinkInfo <<" (Broken)";
259 }
260
261 // print first part
262 fmt->Format( buf, "{} {:>4} {:>4} {:>6} {:yyyy-MM-dd HH:mm} {} {}{}",
263 entry.WriteTypeAndAccess( bufPerms.Reset() ),
264 ownerAndGroup.first, ownerAndGroup.second,
265 bufSize,
266 entry.MTime(),
267 scanResultText,
268 entry.IsCrossingFS() ? 'M' : '-',
269 entry.IsArtificialFS() ? 'A' : '-' );
270
271 buf << ' ';
272
273 // print path as table
274 {
275 // build stack of parent nodes
276 auto actNode= node;
277 FTree::Cursor nodeStack[256];
278 int sp= 1;
279 nodeStack[0]= actNode;
280 while( actNode.GoToParent().IsValid() )
281 nodeStack[sp++]= actNode;
282
283 // process stack reversely
285 for (int i = sp-1; i >= 0; --i)
286 {
287 const String& name= nodeStack[i].Name();
288 fmt->Format( buf, "{}{}{!FillC }",
289 i > sp-3 ? "" : DirSep,
290 name.IsEmpty() ? DirSep : name,
291 i>0 ? nameWidth[sp-i-1] - name.Length() : 0);
292 }
293
294 }
295
296 buf << ' ';
297
298 // print last part
299 fmt->Format( buf, "{} {}\n", symlinkInfo, bufSizes );
300
301
302} //dbgDumpEntry()
303}// anonymous namespace
304
305AString& DbgDump( AString& target,
306 FTree& tree,
307 EnumBitSet<FInfo::Types> includedTypes,
308 FTree::Cursor startNode ,
309 unsigned int depth )
310
311{
312 if( startNode.IsInvalid() )
313 startNode= tree.Root();
314
317 rit.SetPathGeneration(lang::Switch::Off);
318
319 // determine the maximum width of child names for each depth level
320 int nameWidth[256];
321 {
322 for (int i = 0; i < 256; ++i) nameWidth[i]=0;
323 rit.Initialize( startNode );
324 while( rit.IsValid())
325 {
326 if( includedTypes.Test(rit.Node().Value().Type()))
327 nameWidth[rit.CurrentDepth()+1]= (std::max)( nameWidth[rit.CurrentDepth()+1],
328 int(rit.Node().Name().Length()) );
329 rit.Next();
330 }
331 }
332
333 // loop over all nodes and dump
334 OwnerAndGroupResolver ogResolver;
335 dbgDumpEntry( target, ogResolver, fmt, nameWidth, startNode );
336 rit.Initialize( startNode, depth );
337 while( rit.IsValid())
338 {
339 if( includedTypes.Test(rit.Node().Value().Type()))
340 dbgDumpEntry( target, ogResolver, fmt, nameWidth, rit.Node() );
341 rit.Next();
342 }
343
344 fmt->Release();
345
346 return target;
347}
348
349#endif // ALIB_DEBUG && !defined(ALIB_DOX) (dump methods)
350
351} // namespace alib::files
@ DIRECTORY
Directory/folder.
constexpr DirectorySums & Sums() const
Definition finfo.hpp:448
constexpr bool IsDirectory() const noexcept
Definition finfo.hpp:409
@ NONE
no permission bits are set
constexpr Types Type() const noexcept
Definition finfo.hpp:407
@ RECURSIVE
Follow symlink target strings.
@ STATS
Only stats (size, time, owner, etc.) read.
@ NO_ACCESS_DIR
Scanner failure due to limited access rights.
@ MAX_DEPTH_REACHED
Scanner stopped, because maximum depth was reached.
@ NOT_CROSSING_FS
A directory that represented a mounted filesystem was not followed due to field.
@ RESOLVED
Read symlink target strings.
@ NO_ACCESS_SL
Scanner failure due to limited access rights.
@ UNKNOWN_ERROR
Unknown scanner failure.
@ BROKEN_LINK
A symbolic link targets a non-existent file or directory.
@ NO_ACCESS_SL_TARGET
Scanner failure due to limited access rights.
@ NOT_FOLLOWED
A symbolic link that targets a directory, but scan parameters specify not to follow.
@ NO_ACCESS
Scanner failure due to limited access rights.
@ NOT_EXISTENT
Set if a given start path does not exist.
ALIB_API void AllocateExtendedInfo(Cursor &node, String &symLinkDest, String &symLinkRealPath)
Definition ftree.cpp:61
static ALIB_API void FixSums(Cursor directoryNode)
Definition ftree.cpp:42
LinkedEISLDir * recyclerEISlDir
Linked list hook for recycling information elements of disposed nodes.
Definition ftree.hpp:180
LinkedEIDir * recyclerEIDir
Linked list hook for recycling information elements of disposed nodes.
Definition ftree.hpp:178
ALIB_API integer CountRecyclables(FInfo::Types type)
Definition ftree.cpp:130
LinkedEISL * recyclerEISL
Linked list hook for recycling information elements of disposed nodes.
Definition ftree.hpp:179
ALIB_API FTree(monomem::MonoAllocator *allocator)
Definition ftree.cpp:29
ALIB_API std::pair< String, String > Get(const FInfo &finfo)
Definition ftools.cpp:23
static SPFormatter AcquireDefault(const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
MonoAllocator * GetAllocator()
void ConstructRootValue(TArgs &&... args)
TRecursiveIterator< false > RecursiveIterator
constexpr bool IsEmpty() const
Definition string.hpp:414
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_ERROR(...)
Definition alib.hpp:980
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
Definition alib.hpp:669
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define Log_SetDomain(...)
Definition macros.inl:60
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_CALLER_PRUNED
Definition alib.hpp:845
ALIB_API AString & DbgDump(AString &target, FTree &tree, EnumBitSet< FInfo::Types > includedTypes=EnumBitSet< FInfo::Types >(true), FTree::Cursor startNode=FTree::Cursor(), unsigned int depth=(std::numeric_limits< unsigned int >::max)())
@ Off
Switch it off, switched off, etc.
files::Files FILES
Definition filescamp.cpp:30
files::OwnerAndGroupResolver OwnerAndGroupResolver
Type alias in namespace alib.
Definition ftools.hpp:52
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:289
constexpr nchar DirectorySeparator
LocalString< 8 > String8
Type alias name for TLocalString<character,8> .
LocalString< 4096 > String4K
Type alias name for TLocalString<character,4096> .
std::shared_ptr< lang::format::Formatter > SPFormatter
strings::TAString< character > AString
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
files::FTree FTree
Type alias in namespace alib.
Definition ftree.hpp:284
LocalString< 128 > String128
Type alias name for TLocalString<character,128> .
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
uint32_t TypeCounters[int(Types::MARKER_TYPES_END)]
Per-type counters.
Definition finfo.hpp:137
FInfo::EIDirectory data
The usable data receivable with the FInfo instance.
Definition ftree.hpp:157
LinkedEIDir * next
A recursive link to implement a recyling list.
Definition ftree.hpp:158
LinkedEISLDir * next
A recursive link to implement a recyling list.
Definition ftree.hpp:174
FInfo::EISymLinkDir data
The usable data receivable with the FInfo instance.
Definition ftree.hpp:173
FInfo::EISymLinkFile data
The usable data receivable with the FInfo instance.
Definition ftree.hpp:165
LinkedEISL * next
A recursive link to implement a recyling list.
Definition ftree.hpp:166