jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
test_fileutils01.cpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
26
27#include <jau/file_util.hpp>
28#include <jau/secmem.hpp>
29
30extern "C" {
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36}
37
39 public:
40
42 std::string cwd = jau::fs::get_cwd();
43 jau::fs::file_stats image_stats = getTestDataImageFile(executable_path); // optional
44 jau::fs::file_stats proot_stats_01 = getTestDataDirStats(executable_path);
45 std::string rel_project_root = getTestDataRelDir(executable_path);
46 jau::fs::file_stats proot_stats_02(rel_project_root);
47 jau::fprintf_td(stdout, "test00: cwd: %s\n", cwd.c_str());
48 jau::fprintf_td(stdout, "test00: 00: image.stat: %s\n", image_stats.to_string().c_str());
49 jau::fprintf_td(stdout, "test00: 02: proot01.stats: %s\n", proot_stats_01.to_string().c_str());
50 jau::fprintf_td(stdout, "test00: 02: proot02.rel: %s\n", rel_project_root.c_str());
51 jau::fprintf_td(stdout, "test00: 02: proot02.stats: %s\n", proot_stats_02.to_string().c_str());
52 REQUIRE( proot_stats_01.exists() );
53 REQUIRE( proot_stats_02.exists() );
54 }
55
56 /**
57 *
58 */
59 void test01_cwd() {
60 const std::string cwd = jau::fs::get_cwd();
61 INFO_STR("\n\ntest01_cwd: cwd "+cwd+"\n");
62 REQUIRE( 0 < cwd.size() );
63 const size_t idx = cwd.find("/jaulib");
64 REQUIRE( 0 < idx );
65 REQUIRE( idx < cwd.size() );
66 REQUIRE( idx != std::string::npos );
67 }
68
69 /**
70 *
71 */
73 {
74 const std::string pathname0 = "/";
75 const std::string pathname1 = jau::fs::dirname(pathname0);
76 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
77 REQUIRE( 0 < pathname1.size() );
78 REQUIRE( pathname1 == "/" );
79 }
80 {
81 {
82 const std::string pathname0 = "lala.txt";
83 const std::string pathname1 = jau::fs::dirname(pathname0);
84 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
85 REQUIRE( 0 < pathname1.size() );
86 REQUIRE( pathname1 == "." );
87 }
88 {
89 const std::string pathname0 = "lala";
90 const std::string pathname1 = jau::fs::dirname(pathname0);
91 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
92 REQUIRE( 0 < pathname1.size() );
93 REQUIRE( pathname1 == "." );
94 }
95 {
96 const std::string pathname0 = "lala/";
97 const std::string pathname1 = jau::fs::dirname(pathname0);
98 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
99 REQUIRE( 0 < pathname1.size() );
100 REQUIRE( pathname1 == "." );
101 }
102 }
103 {
104 const std::string pathname0 = "/lala.txt";
105 const std::string pathname1 = jau::fs::dirname(pathname0);
106 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
107 REQUIRE( 0 < pathname1.size() );
108 REQUIRE( pathname1 == "/" );
109 }
110 {
111 const std::string pathname0 = "blabla/jaulib/test/sub.txt";
112 const std::string pathname1 = jau::fs::dirname(pathname0);
113 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
114 REQUIRE( 0 < pathname1.size() );
115 REQUIRE( pathname1 == "blabla/jaulib/test" );
116 }
117 {
118 const std::string pathname0 = "blabla/jaulib/test/sub";
119 const std::string pathname1 = jau::fs::dirname(pathname0);
120 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
121 REQUIRE( 0 < pathname1.size() );
122 REQUIRE( pathname1 == "blabla/jaulib/test" );
123 }
124 {
125 const std::string pathname0 = "blabla/jaulib/test/";
126 const std::string pathname1 = jau::fs::dirname(pathname0);
127 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
128 REQUIRE( 0 < pathname1.size() );
129 REQUIRE( pathname1 == "blabla/jaulib" );
130 }
131 {
132 const std::string pathname0 = "blabla/jaulib/test";
133 const std::string pathname1 = jau::fs::dirname(pathname0);
134 INFO_STR("\n\ntest02_dirname: cwd "+pathname0+" -> "+pathname1+"\n");
135 REQUIRE( 0 < pathname1.size() );
136 REQUIRE( pathname1 == "blabla/jaulib" );
137 }
138 }
139
141 {
142 const std::string pathname0 = "/";
143 const std::string pathname1 = jau::fs::basename(pathname0);
144 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
145 REQUIRE( 0 < pathname1.size() );
146 REQUIRE( pathname1 == "/" );
147 REQUIRE( true == jau::fs::isAbsolute(pathname1));
148 }
149 {
150 {
151 const std::string pathname0 = "lala.txt";
152 const std::string pathname1 = jau::fs::basename(pathname0);
153 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
154 REQUIRE( 0 < pathname1.size() );
155 REQUIRE( pathname1 == "lala.txt" );
156 REQUIRE( false == jau::fs::isAbsolute(pathname1));
157 }
158 {
159 const std::string pathname0 = "lala";
160 const std::string pathname1 = jau::fs::basename(pathname0);
161 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
162 REQUIRE( 0 < pathname1.size() );
163 REQUIRE( pathname1 == "lala" );
164 REQUIRE( false == jau::fs::isAbsolute(pathname1));
165 }
166 {
167 const std::string pathname0 = "lala/";
168 const std::string pathname1 = jau::fs::basename(pathname0);
169 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
170 REQUIRE( 0 < pathname1.size() );
171 REQUIRE( pathname1 == "lala" );
172 }
173 }
174 {
175 const std::string pathname0 = "/lala.txt";
176 const std::string pathname1 = jau::fs::basename(pathname0);
177 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
178 REQUIRE( 0 < pathname1.size() );
179 REQUIRE( pathname1 == "lala.txt" );
180 }
181 {
182 const std::string pathname0 = "blabla/jaulib/test/sub.txt";
183 const std::string pathname1 = jau::fs::basename(pathname0);
184 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
185 REQUIRE( 0 < pathname1.size() );
186 REQUIRE( pathname1 == "sub.txt" );
187 }
188
189 {
190 const std::string pathname0 = "blabla/jaulib/test/";
191 const std::string pathname1 = jau::fs::basename(pathname0);
192 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
193 REQUIRE( 0 < pathname1.size() );
194 REQUIRE( pathname1 == "test" );
195 }
196
197 {
198 const std::string pathname0 = "blabla/jaulib/test";
199 const std::string pathname1 = jau::fs::basename(pathname0);
200 INFO_STR("\n\ntest03_basename: cwd "+pathname0+" -> "+pathname1+"\n");
201 REQUIRE( 0 < pathname1.size() );
202 REQUIRE( pathname1 == "test" );
203 }
204 }
205
207 {
208 std::string rel_project_root = getTestDataRelDir(executable_path);
209 jau::fs::file_stats proot_stats(rel_project_root);
210 jau::fprintf_td(stdout, "test03b_absolute: 01: cwd: %s\n", jau::fs::get_cwd().c_str());
211 jau::fprintf_td(stdout, "test03b_absolute: 01: rel_project_root %s\n", rel_project_root.c_str());
212 jau::fprintf_td(stdout, "test03b_absolute: 01: proot_stats %s\n", proot_stats.to_string().c_str());
213 jau::fprintf_td(stdout, "test03b_absolute: 01: fields %s\n", jau::fs::to_string( proot_stats.fields() ).c_str());
214 REQUIRE( true == proot_stats.exists() );
215 REQUIRE( true == proot_stats.is_dir() );
216
217 std::string abs_project_root;
218 {
219 abs_project_root = jau::fs::absolute(rel_project_root);
220 jau::fprintf_td(stdout, "test03b_absolute: 02: %s\n", abs_project_root.c_str());
221 REQUIRE( 0 < abs_project_root.size() );
222 REQUIRE( false == jau::fs::isAbsolute(rel_project_root) );
223 REQUIRE( true == jau::fs::isAbsolute(abs_project_root) );
224
225 jau::fs::file_stats stats(abs_project_root);
226 jau::fprintf_td(stdout, "test03b_absolute: 02: %s\n", stats.to_string().c_str());
227 jau::fprintf_td(stdout, "test03b_absolute: 02: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
228 REQUIRE( stats.exists() );
229 REQUIRE( stats.is_dir() );
230 }
231 {
232 std::string bname0 = jau::fs::basename(rel_project_root);
233 std::string bname1 = jau::fs::basename(abs_project_root);
234 jau::fprintf_td(stdout, "test03b_absolute: 03.0: %s\n", bname0.c_str());
235 jau::fprintf_td(stdout, "test03b_absolute: 03.1: %s\n", bname1.c_str());
236 REQUIRE( bname0 == bname1 );
237 }
238 }
239 }
240
242 {
243 const jau::fs::dir_item di;
244 INFO_STR("\n\ntest04_dir_item: 00 "+di.to_string()+" -> '"+di.path()+"'\n");
245 REQUIRE( "." == di.dirname() );
246 REQUIRE( "." == di.basename() );
247 REQUIRE( "." == di.path() );
248 REQUIRE( true == di.empty() );
249 }
250 {
251 const std::string dirname_;
252 const jau::fs::dir_item di(dirname_);
253 INFO_STR("\n\ntest04_dir_item: 01 '"+dirname_+"' -> "+di.to_string()+" -> '"+di.path()+"'\n");
254 REQUIRE( "." == di.dirname() );
255 REQUIRE( "." == di.basename() );
256 REQUIRE( "." == di.path() );
257 REQUIRE( true == di.empty() );
258 }
259 {
260 const std::string dirname_(".");
261 const jau::fs::dir_item di(dirname_);
262 INFO_STR("\n\ntest04_dir_item: 02 '"+dirname_+"' -> "+di.to_string()+" -> '"+di.path()+"'\n");
263 REQUIRE( "." == di.dirname() );
264 REQUIRE( "." == di.basename() );
265 REQUIRE( "." == di.path() );
266 REQUIRE( false == di.empty() );
267 }
268 {
269 const std::string dirname_("/");
270 const jau::fs::dir_item di(dirname_);
271 INFO_STR("\n\ntest04_dir_item: 03 '"+dirname_+"' -> "+di.to_string()+" -> '"+di.path()+"'\n");
272 REQUIRE( "/" == di.dirname() );
273 REQUIRE( "." == di.basename() );
274 REQUIRE( "/" == di.path() );
275 REQUIRE( false == di.empty() );
276 }
277
278 {
279 const std::string path1_ = "lala";
280 const jau::fs::dir_item di(path1_);
281 INFO_STR("\n\ntest04_dir_item: 10 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
282 REQUIRE( "." == di.dirname() );
283 REQUIRE( "lala" == di.basename() );
284 REQUIRE( "lala" == di.path() );
285 REQUIRE( false == di.empty() );
286 }
287 {
288 const std::string path1_ = "lala/";
289 const jau::fs::dir_item di(path1_);
290 INFO_STR("\n\ntest04_dir_item: 11 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
291 REQUIRE( "." == di.dirname() );
292 REQUIRE( "lala" == di.basename() );
293 REQUIRE( "lala" == di.path() );
294 REQUIRE( false == di.empty() );
295 }
296
297 {
298 const std::string path1_ = "/lala";
299 const jau::fs::dir_item di(path1_);
300 INFO_STR("\n\ntest04_dir_item: 12 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
301 REQUIRE( "/" == di.dirname() );
302 REQUIRE( "lala" == di.basename() );
303 REQUIRE( "/lala" == di.path() );
304 REQUIRE( false == di.empty() );
305 }
306
307 {
308 const std::string path1_ = "dir0/lala";
309 const jau::fs::dir_item di(path1_);
310 INFO_STR("\n\ntest04_dir_item: 20 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
311 REQUIRE( "dir0" == di.dirname() );
312 REQUIRE( "lala" == di.basename() );
313 REQUIRE( "dir0/lala" == di.path() );
314 }
315 {
316 const std::string path1_ = "dir0/lala/";
317 const jau::fs::dir_item di(path1_);
318 INFO_STR("\n\ntest04_dir_item: 21 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
319 REQUIRE( "dir0" == di.dirname() );
320 REQUIRE( "lala" == di.basename() );
321 REQUIRE( "dir0/lala" == di.path() );
322 }
323 {
324 const std::string path1_ = "/dir0/lala";
325 const jau::fs::dir_item di(path1_);
326 INFO_STR("\n\ntest04_dir_item: 22 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
327 REQUIRE( "/dir0" == di.dirname() );
328 REQUIRE( "lala" == di.basename() );
329 REQUIRE( "/dir0/lala" == di.path() );
330 }
331 {
332 const std::string path1_ = "/dir0/lala/";
333 const jau::fs::dir_item di(path1_);
334 INFO_STR("\n\ntest04_dir_item: 23 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
335 REQUIRE( "/dir0" == di.dirname() );
336 REQUIRE( "lala" == di.basename() );
337 REQUIRE( "/dir0/lala" == di.path() );
338 }
339
340
341 {
342 const std::string path1_ = "/dir0/../lala";
343 const jau::fs::dir_item di(path1_);
344 INFO_STR("\n\ntest04_dir_item: 30 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
345 REQUIRE( "/" == di.dirname() );
346 REQUIRE( "lala" == di.basename() );
347 REQUIRE( "/lala" == di.path() );
348 }
349 {
350 const std::string path1_ = "dir0/../lala";
351 const jau::fs::dir_item di(path1_);
352 INFO_STR("\n\ntest04_dir_item: 31 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
353 REQUIRE( "." == di.dirname() );
354 REQUIRE( "lala" == di.basename() );
355 REQUIRE( "lala" == di.path() );
356 }
357 {
358 const std::string path1_ = "../../lala";
359 const jau::fs::dir_item di(path1_);
360 INFO_STR("\n\ntest04_dir_item: 32 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
361 REQUIRE( "../.." == di.dirname() );
362 REQUIRE( "lala" == di.basename() );
363 REQUIRE( "../../lala" == di.path() );
364 }
365 {
366 const std::string path1_ = "./../lala";
367 const jau::fs::dir_item di(path1_);
368 INFO_STR("\n\ntest04_dir_item: 33 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
369 REQUIRE( ".." == di.dirname() );
370 REQUIRE( "lala" == di.basename() );
371 REQUIRE( "../lala" == di.path() );
372 }
373 {
374 const std::string path1_ = "dir0/../../lala";
375 const jau::fs::dir_item di(path1_);
376 INFO_STR("\n\ntest04_dir_item: 34 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
377 REQUIRE( ".." == di.dirname() );
378 REQUIRE( "lala" == di.basename() );
379 REQUIRE( "../lala" == di.path() );
380 }
381
382 {
383 const std::string path1_ = "dir0/dir1/../lala";
384 const jau::fs::dir_item di(path1_);
385 INFO_STR("\n\ntest04_dir_item: 40 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
386 REQUIRE( "dir0" == di.dirname() );
387 REQUIRE( "lala" == di.basename() );
388 REQUIRE( "dir0/lala" == di.path() );
389 }
390 {
391 const std::string path1_ = "/dir0/dir1/../lala/";
392 const jau::fs::dir_item di(path1_);
393 INFO_STR("\n\ntest04_dir_item: 41 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
394 REQUIRE( "/dir0" == di.dirname() );
395 REQUIRE( "lala" == di.basename() );
396 REQUIRE( "/dir0/lala" == di.path() );
397 }
398 {
399 const std::string path1_ = "dir0/dir1/../bbb/ccc/../lala";
400 const jau::fs::dir_item di(path1_);
401 INFO_STR("\n\ntest04_dir_item: 42 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
402 REQUIRE( "dir0/bbb" == di.dirname() );
403 REQUIRE( "lala" == di.basename() );
404 REQUIRE( "dir0/bbb/lala" == di.path() );
405 }
406 {
407 const std::string path1_ = "dir0/dir1/bbb/../../lala";
408 const jau::fs::dir_item di(path1_);
409 INFO_STR("\n\ntest04_dir_item: 43 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
410 REQUIRE( "dir0" == di.dirname() );
411 REQUIRE( "lala" == di.basename() );
412 REQUIRE( "dir0/lala" == di.path() );
413 }
414 {
415 const std::string path1_ = "dir0/dir1/bbb/../../../lala";
416 const jau::fs::dir_item di(path1_);
417 INFO_STR("\n\ntest04_dir_item: 44 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
418 REQUIRE( "." == di.dirname() );
419 REQUIRE( "lala" == di.basename() );
420 REQUIRE( "lala" == di.path() );
421 }
422 {
423 const std::string path1_ = "dir0/dir1/bbb/../../../../lala";
424 const jau::fs::dir_item di(path1_);
425 INFO_STR("\n\ntest04_dir_item: 45 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
426 REQUIRE( ".." == di.dirname() );
427 REQUIRE( "lala" == di.basename() );
428 REQUIRE( "../lala" == di.path() );
429 }
430 {
431 const std::string path1_ = "dir0/dir1/bbb/../../lala/..";
432 const jau::fs::dir_item di(path1_);
433 INFO_STR("\n\ntest04_dir_item: 46 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
434 REQUIRE( "." == di.dirname() );
435 REQUIRE( "dir0" == di.basename() );
436 REQUIRE( "dir0" == di.path() );
437 }
438 {
439 const std::string path1_ = "dir0/./dir1/./bbb/../.././lala";
440 const jau::fs::dir_item di(path1_);
441 INFO_STR("\n\ntest04_dir_item: 50 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
442 REQUIRE( "dir0" == di.dirname() );
443 REQUIRE( "lala" == di.basename() );
444 REQUIRE( "dir0/lala" == di.path() );
445 }
446 {
447 const std::string path1_ = "dir0/./dir1/./bbb/../.././lala/.";
448 const jau::fs::dir_item di(path1_);
449 INFO_STR("\n\ntest04_dir_item: 51 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
450 REQUIRE( "dir0" == di.dirname() );
451 REQUIRE( "lala" == di.basename() );
452 REQUIRE( "dir0/lala" == di.path() );
453 }
454 {
455 const std::string path1_ = "./dir0/./dir1/./bbb/../.././lala/.";
456 const jau::fs::dir_item di(path1_);
457 INFO_STR("\n\ntest04_dir_item: 51 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
458 REQUIRE( "dir0" == di.dirname() );
459 REQUIRE( "lala" == di.basename() );
460 REQUIRE( "dir0/lala" == di.path() );
461 }
462 {
463 const std::string path1_ = "/./dir0/./dir1/./bbb/../.././lala/.";
464 const jau::fs::dir_item di(path1_);
465 INFO_STR("\n\ntest04_dir_item: 52 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
466 REQUIRE( "/dir0" == di.dirname() );
467 REQUIRE( "lala" == di.basename() );
468 REQUIRE( "/dir0/lala" == di.path() );
469 }
470
471 {
472 const std::string path1_ = "../../test_data/file_01_slink09R1.txt";
473 const jau::fs::dir_item di(path1_);
474 INFO_STR("\n\ntest04_dir_item: 60 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
475 REQUIRE( "../../test_data" == di.dirname() );
476 REQUIRE( "file_01_slink09R1.txt" == di.basename() );
477 REQUIRE( path1_ == di.path() );
478 }
479
480 {
481 const std::string path1_ = "../../../jaulib/test_data";
482 const jau::fs::dir_item di(path1_);
483 INFO_STR("\n\ntest04_dir_item: 61 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
484 REQUIRE( "../../../jaulib" == di.dirname() );
485 REQUIRE( "test_data" == di.basename() );
486 REQUIRE( path1_ == di.path() );
487 }
488
489 {
490 const std::string path1_ = "../../../../jaulib/test_data";
491 const jau::fs::dir_item di(path1_);
492 INFO_STR("\n\ntest04_dir_item: 62 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
493 REQUIRE( "../../../../jaulib" == di.dirname() );
494 REQUIRE( "test_data" == di.basename() );
495 REQUIRE( path1_ == di.path() );
496 }
497
498 {
499 const std::string path1_ = "././././jaulib/test_data";
500 const jau::fs::dir_item di(path1_);
501 INFO_STR("\n\ntest04_dir_item: 63 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
502 REQUIRE( "jaulib" == di.dirname() );
503 REQUIRE( "test_data" == di.basename() );
504 REQUIRE( "jaulib/test_data" == di.path() );
505 }
506 {
507 const std::string path1_ = "a/././././jaulib/test_data";
508 const jau::fs::dir_item di(path1_);
509 INFO_STR("\n\ntest04_dir_item: 64 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
510 REQUIRE( "a/jaulib" == di.dirname() );
511 REQUIRE( "test_data" == di.basename() );
512 REQUIRE( "a/jaulib/test_data" == di.path() );
513 }
514
515 {
516 // Error
517 const std::string path1_ = "/../lala";
518 const jau::fs::dir_item di(path1_);
519 INFO_STR("\n\ntest04_dir_item: 99 '"+path1_+" -> "+di.to_string()+" -> '"+di.path()+"'\n");
520 REQUIRE( "/.." == di.dirname() );
521 REQUIRE( "lala" == di.basename() );
522 REQUIRE( "/../lala" == di.path() );
523 }
524 }
525
527 errno = 0;
528 INFO_STR("\n\ntest05_file_stat\n");
529
530 {
532 jau::fprintf_td(stdout, "test05_file_stat: 0a: %s\n", stats.to_string().c_str());
533 jau::fprintf_td(stdout, "test05_file_stat: 0a: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
534 REQUIRE( false == stats.exists() );
535 }
536 {
537 jau::fs::file_stats stats("");
538 jau::fprintf_td(stdout, "test05_file_stat: 0b: %s\n", stats.to_string().c_str());
539 jau::fprintf_td(stdout, "test05_file_stat: 0b: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
540 REQUIRE( false == stats.exists() );
541 }
542 {
543 jau::fs::file_stats stats(project_root_ext+"/file_01.txt");
544 jau::fprintf_td(stdout, "test05_file_stat: 01: %s\n", stats.to_string().c_str());
545 jau::fprintf_td(stdout, "test05_file_stat: 01: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
546 if( stats.exists() ) {
547 REQUIRE( stats.has_access() );
548 REQUIRE( !stats.is_dir() );
549 REQUIRE( stats.is_file() );
550 REQUIRE( !stats.is_link() );
551 REQUIRE( 15 == stats.size() );
552 }
553 }
554
555 jau::fs::file_stats proot_stats = getTestDataDirStats(executable_path);
556 jau::fprintf_td(stdout, "test05_file_stat: 11: %s\n", proot_stats.to_string().c_str());
557 jau::fprintf_td(stdout, "test05_file_stat: 11: fields %s\n", jau::fs::to_string( proot_stats.fields() ).c_str());
558 REQUIRE( true == proot_stats.exists() );
559 REQUIRE( true == proot_stats.is_dir() );
560 {
561 jau::fs::file_stats stats(proot_stats.path()+"/file_01.txt");
562 jau::fprintf_td(stdout, "test05_file_stat: 12: %s\n", stats.to_string().c_str());
563 jau::fprintf_td(stdout, "test05_file_stat: 12: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
564 REQUIRE( stats.exists() );
565 REQUIRE( stats.has_access() );
566 REQUIRE( !stats.is_dir() );
567 REQUIRE( stats.is_file() );
568 REQUIRE( !stats.is_link() );
569 REQUIRE( 15 == stats.size() );
570
571 size_t link_count;
572 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
573 jau::fprintf_td(stdout, "test05_file_stat: 12: final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
574 REQUIRE( 0 == link_count );
575 REQUIRE( final_target == &stats );
576
577 {
578 jau::fs::file_stats stats2(proot_stats.path()+"/file_01.txt");
579 REQUIRE( stats2.exists() );
580 REQUIRE( stats2.has_access() );
581 REQUIRE( !stats2.is_dir() );
582 REQUIRE( stats2.is_file() );
583 REQUIRE( !stats2.is_link() );
584 REQUIRE( 15 == stats2.size() );
585 REQUIRE( stats == stats2 );
586 }
587 {
588 jau::fs::file_stats stats2(proot_stats.path()+"/dir_01/file_02.txt");
589 REQUIRE( stats2.exists() );
590 REQUIRE( stats2.has_access() );
591 REQUIRE( !stats2.is_dir() );
592 REQUIRE( stats2.is_file() );
593 REQUIRE( !stats2.is_link() );
594 REQUIRE( stats != stats2 );
595 }
596 }
597 {
598 jau::fs::file_stats stats(proot_stats.path()+"/dir_01");
599 jau::fprintf_td(stdout, "test05_file_stat: 13: %s\n", stats.to_string().c_str());
600 jau::fprintf_td(stdout, "test05_file_stat: 13: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
601 REQUIRE( stats.exists() );
602 REQUIRE( stats.has_access() );
603 REQUIRE( stats.is_dir() );
604 REQUIRE( !stats.is_file() );
605 REQUIRE( !stats.is_link() );
606 REQUIRE( 0 == stats.size() );
607
608 size_t link_count;
609 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
610 jau::fprintf_td(stdout, "test05_file_stat: 13: final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
611 REQUIRE( 0 == link_count );
612 REQUIRE( final_target == &stats );
613 }
614 {
615 jau::fs::file_stats stats(proot_stats.path()+"/does_not_exist");
616 jau::fprintf_td(stdout, "test05_file_stat: 14: %s\n", stats.to_string().c_str());
617 jau::fprintf_td(stdout, "test05_file_stat: 14: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
618 REQUIRE( !stats.exists() );
619 REQUIRE( stats.has_access() );
620 REQUIRE( !stats.is_dir() );
621 REQUIRE( !stats.is_file() );
622 REQUIRE( !stats.is_link() );
623 REQUIRE( 0 == stats.size() );
624
625 size_t link_count;
626 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
627 jau::fprintf_td(stdout, "test05_file_stat: 14: final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
628 REQUIRE( 0 == link_count );
629 REQUIRE( final_target == &stats );
630 }
631 }
632
634 errno = 0;
635 INFO_STR("\n\ntest06_file_stat_symlinks\n");
636
637 jau::fs::file_stats proot_stats = getTestDataDirStats(executable_path);
638 REQUIRE( true == proot_stats.exists() );
639 REQUIRE( true == proot_stats.is_dir() );
640 {
641 jau::fs::file_stats stats(proot_stats.path()+"/file_01_slink01.txt");
642 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 13: %s\n", stats.to_string().c_str());
643 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 13: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
644 REQUIRE( stats.exists() );
645 REQUIRE( stats.has_access() );
646 REQUIRE( !stats.is_dir() );
647 REQUIRE( stats.is_file() );
648 REQUIRE( stats.is_link() );
649 REQUIRE( 15 == stats.size() );
650 REQUIRE( nullptr != stats.link_target_path() );
651 REQUIRE( "file_01.txt" == *stats.link_target_path() );
652
653 size_t link_count;
654 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
655 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
656 REQUIRE( 1 == link_count );
657 REQUIRE( final_target != &stats );
658 REQUIRE( proot_stats.path()+"/file_01.txt" == final_target->path() );
659
660 REQUIRE( nullptr != stats.link_target() );
661 const jau::fs::file_stats* link_target = stats.link_target().get();
662 REQUIRE( nullptr != link_target );
663 jau::fprintf_td(stdout, "- link_target %s\n", link_target->to_string().c_str());
664 REQUIRE( final_target == link_target );
665 REQUIRE( !link_target->is_dir() );
666 REQUIRE( link_target->is_file() );
667 REQUIRE( !link_target->is_link() );
668 REQUIRE( nullptr == link_target->link_target_path() );
669 REQUIRE( nullptr == link_target->link_target() );
670 }
671 {
672 jau::fs::file_stats stats(proot_stats.path()+"/fstab_slink07_absolute");
673 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 14: %s\n", stats.to_string().c_str());
674 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 14: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
675 REQUIRE( stats.exists() );
676 REQUIRE( stats.has_access() );
677 REQUIRE( !stats.is_dir() );
678 REQUIRE( stats.is_file() );
679 REQUIRE( stats.is_link() );
680 REQUIRE( 20 < stats.size() ); // greater than basename
681 REQUIRE( nullptr != stats.link_target_path() );
682 REQUIRE( "/etc/fstab" == *stats.link_target_path() );
683
684 size_t link_count;
685 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
686 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
687 REQUIRE( 1 == link_count );
688 REQUIRE( final_target != &stats );
689 REQUIRE( "/etc/fstab" == final_target->path() );
690
691 REQUIRE( nullptr != stats.link_target() );
692 const jau::fs::file_stats* link_target = stats.link_target().get();
693 REQUIRE( nullptr != link_target );
694 jau::fprintf_td(stdout, "- link_target %s\n", link_target->to_string().c_str());
695 REQUIRE( final_target == link_target );
696 REQUIRE( !link_target->is_dir() );
697 REQUIRE( link_target->is_file() );
698 REQUIRE( !link_target->is_link() );
699 REQUIRE( nullptr == link_target->link_target_path() );
700 REQUIRE( nullptr == link_target->link_target() );
701 }
702 {
703 jau::fs::file_stats stats(proot_stats.path()+"/file_01_slink10R2.txt"); // -> file_01_slink09R1.txt -> file_01_slink01.txt -> file_01.txt
704 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 20: %s\n", stats.to_string().c_str());
705 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 20: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
706 REQUIRE( stats.exists() );
707 REQUIRE( stats.has_access() );
708 REQUIRE( !stats.is_dir() );
709 REQUIRE( stats.is_file() );
710 REQUIRE( stats.is_link() );
711 REQUIRE( 15 == stats.size() );
712 REQUIRE( nullptr != stats.link_target_path() );
713 REQUIRE( "file_01_slink09R1.txt" == *stats.link_target_path() );
714
715 size_t link_count;
716 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
717 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
718 REQUIRE( 3 == link_count );
719 REQUIRE( final_target != &stats );
720 REQUIRE( proot_stats.path()+"/file_01.txt" == final_target->path() );
721
722 REQUIRE( nullptr != stats.link_target() );
723 const jau::fs::file_stats* link_target1 = stats.link_target().get();
724 jau::fprintf_td(stdout, "- link_target1 %s\n", link_target1->to_string().c_str());
725 REQUIRE( final_target != link_target1 );
726 REQUIRE( proot_stats.path()+"/file_01_slink09R1.txt" == link_target1->path() );
727 REQUIRE( 15 == link_target1->size() );
728 REQUIRE( !link_target1->is_dir() );
729 REQUIRE( link_target1->is_file() );
730 REQUIRE( link_target1->is_link() );
731 REQUIRE( nullptr != link_target1->link_target_path() );
732 REQUIRE( "file_01_slink01.txt" == *link_target1->link_target_path() );
733 {
734 const jau::fs::file_stats* link_target2 = link_target1->link_target().get();
735 REQUIRE( nullptr != link_target2 );
736 jau::fprintf_td(stdout, " - link_target2 %s\n", link_target2->to_string().c_str());
737 REQUIRE( final_target != link_target2 );
738 REQUIRE( link_target1 != link_target2 );
739 REQUIRE( proot_stats.path()+"/file_01_slink01.txt" == link_target2->path() );
740 REQUIRE( 15 == link_target2->size() );
741 REQUIRE( !link_target2->is_dir() );
742 REQUIRE( link_target2->is_file() );
743 REQUIRE( link_target2->is_link() );
744 REQUIRE( nullptr != link_target2->link_target_path() );
745 REQUIRE( "file_01.txt" == *link_target2->link_target_path() );
746
747 const jau::fs::file_stats* link_target3 = link_target2->link_target().get();
748 REQUIRE( nullptr != link_target3 );
749 jau::fprintf_td(stdout, " - link_target3 %s\n", link_target3->to_string().c_str());
750 REQUIRE( final_target == link_target3 );
751 REQUIRE( link_target1 != link_target3 );
752 REQUIRE( link_target2 != link_target3 );
753 REQUIRE( 15 == link_target3->size() );
754 REQUIRE( !link_target3->is_dir() );
755 REQUIRE( link_target3->is_file() );
756 REQUIRE( !link_target3->is_link() );
757 REQUIRE( nullptr == link_target3->link_target_path() );
758 REQUIRE( nullptr == link_target3->link_target() );
759 }
760 }
761 {
762 jau::fs::file_stats stats(proot_stats.path()+"/dead_link23"); // -> not_existing_file
763 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 30: %s\n", stats.to_string().c_str());
764 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 30: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
765 REQUIRE( !stats.exists() );
766 REQUIRE( stats.has_access() );
767 REQUIRE( !stats.is_dir() );
768 REQUIRE( !stats.is_file() );
769 REQUIRE( stats.is_link() );
770 REQUIRE( 0 == stats.size() );
771 REQUIRE( nullptr != stats.link_target_path() );
772 REQUIRE( "not_existing_file" == *stats.link_target_path() );
773 REQUIRE( nullptr == stats.link_target() );
774
775 size_t link_count;
776 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
777 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
778 REQUIRE( 0 == link_count );
779 REQUIRE( final_target == &stats );
780 }
781 {
782 jau::fs::file_stats stats(proot_stats.path()+"/dead_link22"); // LOOP: dead_link22 -> dead_link21 -> dead_link20 -> dead_link22 ...
783 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 31: %s\n", stats.to_string().c_str());
784 jau::fprintf_td(stdout, "test06_file_stat_symlinks: 31: fields %s\n", jau::fs::to_string( stats.fields() ).c_str());
785 REQUIRE( !stats.exists() );
786 REQUIRE( stats.has_access() );
787 REQUIRE( !stats.is_dir() );
788 REQUIRE( !stats.is_file() );
789 REQUIRE( stats.is_link() );
790 REQUIRE( 0 == stats.size() );
791 REQUIRE( nullptr != stats.link_target_path() );
792 REQUIRE( "dead_link21" == *stats.link_target_path() );
793 REQUIRE( nullptr == stats.link_target() );
794
795 size_t link_count;
796 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
797 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
798 REQUIRE( 0 == link_count );
799 REQUIRE( *final_target == stats );
800 REQUIRE( final_target == &stats );
801 }
802 }
803
804 static void test_file_stat_fd_item(const jau::fs::fmode_t exp_type, const int fd, const std::string& named_fd1, const std::string& named_fd_link) {
805 jau::fprintf_td(stdout, "test_file_stat_fd_item: expect '%s', fd %d, name_fd1 '%s', make_fd_link '%s'\n",
806 jau::fs::to_string(exp_type).c_str(), fd, named_fd1.c_str(), named_fd_link.c_str());
807 {
808 errno = 0;
809 jau::fprintf_td(stdout, "test_file_stat_fd_item.1: expect '%s', fd %d\n", jau::fs::to_string(exp_type).c_str(), fd);
810 jau::fs::file_stats stats(fd);
811 jau::fprintf_td(stdout, "fd: %s\n", stats.to_string().c_str());
812 REQUIRE( stats.exists() );
813 REQUIRE( stats.has_access() );
814 REQUIRE( !stats.is_socket() );
815 REQUIRE( !stats.is_block() );
816 REQUIRE( !stats.is_dir() );
817 if( jau::fs::fmode_t::none == ( stats.type_mode() & exp_type ) ) {
818 jau::fprintf_td(stdout, "INFO: Not matching expected type '%s': fd: %s\n", jau::fs::to_string(exp_type).c_str(), stats.to_string().c_str());
819 }
820 REQUIRE( stats.has_fd() );
821 REQUIRE( fd == stats.fd() );
822 if( !stats.is_file() ) {
823 REQUIRE( 0 == stats.size() );
824 }
825 jau::fprintf_td(stdout, "test_file_stat_fd_item.1: X\n\n");
826 }
827 if( !named_fd1.empty() ) {
828 errno = 0;
829 jau::fprintf_td(stdout, "test_file_stat_fd_item.2: expect '%s', fd %d, name_fd1 '%s'\n",
830 jau::fs::to_string(exp_type).c_str(), fd, named_fd1.c_str());
831 jau::fs::file_stats stats(named_fd1);
832 jau::fprintf_td(stdout, "fd_1: %s\n", stats.to_string().c_str());
833 REQUIRE( stats.exists() );
834 REQUIRE( stats.has_access() );
835 REQUIRE( !stats.is_socket() );
836 REQUIRE( !stats.is_block() );
837 REQUIRE( !stats.is_dir() );
838 if( jau::fs::fmode_t::none == ( stats.type_mode() & exp_type ) ) {
839 jau::fprintf_td(stdout, "INFO: Not matching expected type '%s': fd: %s\n", jau::fs::to_string(exp_type).c_str(), stats.to_string().c_str());
840 }
841 REQUIRE( stats.has_fd() );
842 REQUIRE( fd == stats.fd() );
843 if( !stats.is_file() ) {
844 REQUIRE( 0 == stats.size() );
845 }
846 jau::fprintf_td(stdout, "test_file_stat_fd_item.2: X\n\n");
847 }
848 if( !named_fd_link.empty() ) {
849 errno = 0;
850 jau::fprintf_td(stdout, "test_file_stat_fd_item.3: expect '%s', fd %d, make_fd_link '%s'\n",
851 jau::fs::to_string(exp_type).c_str(), fd, named_fd_link.c_str());
852 jau::fs::file_stats stats(named_fd_link);
853 jau::fprintf_td(stdout, "fd_link: %s\n", stats.to_string().c_str());
854 REQUIRE( stats.exists() );
855 REQUIRE( stats.has_access() );
856 REQUIRE( !stats.is_socket() );
857 REQUIRE( !stats.is_block() );
858 REQUIRE( !stats.is_dir() );
859 if( jau::fs::fmode_t::none == ( stats.type_mode() & exp_type ) ) {
860 jau::fprintf_td(stdout, "INFO: Not matching expected type '%s': fd: %s\n", jau::fs::to_string(exp_type).c_str(), stats.to_string().c_str());
861 }
862 REQUIRE( stats.has_fd() );
863 REQUIRE( fd == stats.fd() );
864 if( !stats.is_file() ) {
865 REQUIRE( 0 == stats.size() );
866 }
867
868 size_t link_count;
869 const jau::fs::file_stats* final_target = stats.final_target(&link_count);
870 REQUIRE( nullptr != final_target );
871 jau::fprintf_td(stdout, "- final_target (%zu link count): %s\n", link_count, final_target->to_string().c_str());
872 REQUIRE( 1 <= link_count );
873 REQUIRE( 2 >= link_count );
874 jau::fprintf_td(stdout, "test_file_stat_fd_item.3: X\n\n");
875 }
876 }
877
879 jau::fprintf_td(stdout, "test07_file_stat_fd\n");
880
881 const std::string fd_stdin_1 = "/dev/fd/0";
882 const std::string fd_stdout_1 = "/dev/fd/1";
883 const std::string fd_stderr_1 = "/dev/fd/2";
884
885 const std::string fd_stdin_l = "/dev/stdin";
886 const std::string fd_stdout_l = "/dev/stdout";
887 const std::string fd_stderr_l = "/dev/stderr";
888
889 test_file_stat_fd_item(jau::fs::fmode_t::chr, 0, fd_stdin_1, fd_stdin_l);
890 test_file_stat_fd_item(jau::fs::fmode_t::chr, 1, fd_stdout_1, fd_stdout_l);
891 test_file_stat_fd_item(jau::fs::fmode_t::chr, 2, fd_stderr_1, fd_stderr_l);
892 {
893 int fd = ::open("test07_file_stat_fd_tmp", O_CREAT|O_WRONLY|O_NOCTTY, S_IRUSR | S_IWUSR | S_IRGRP );
894 REQUIRE( 0 <= fd );
896 ::close(fd);
897 }
898 {
899 int pipe_fds[2];
900 REQUIRE( 0 == ::pipe(pipe_fds) );
903 ::close(pipe_fds[0]);
904 ::close(pipe_fds[1]);
905 }
906 }
907
908 // 128 bytes
909 static constexpr const char* pipe_msg = "Therefore I say unto you, Take no thought for your life, what ye shall eat, or what ye shall drink; nor yet for your body, what.";
910 static const size_t pipe_msg_len = 128;
911 static const size_t pipe_msg_count = 10;
912
914 errno = 0;
915 jau::fprintf_td(stdout, "test08_pipe_01\n");
916
917 int pipe_fds[2];
918 REQUIRE( 0 == ::pipe(pipe_fds) );
919 ::pid_t pid = ::fork();
920
921 if( 0 == pid ) {
922 // child process: WRITE
923 ::close(pipe_fds[0]); // close unused read end
924 const int new_stdout = pipe_fds[1];
925 const std::string fd_stdout = jau::fs::to_named_fd(new_stdout);
926
927 jau::fs::file_stats stats_stdout(fd_stdout);
928 jau::fprintf_td(stdout, "Child: stats_stdout %s\n", stats_stdout.to_string().c_str());
929 if( !stats_stdout.exists() || !stats_stdout.has_fd() || new_stdout != stats_stdout.fd() ) {
930 jau::fprintf_td(stdout, "Child: Error: stats_stdout %s\n", stats_stdout.to_string().c_str());
931 ::_exit(EXIT_FAILURE);
932 }
933 jau::io::ByteOutStream_File outfile(fd_stdout);
934 if( !outfile.good() || !outfile.is_open() ) {
935 jau::fprintf_td(stdout, "Child: Error: outfile bad: %s\n", outfile.to_string().c_str());
936 ::_exit(EXIT_FAILURE);
937 }
938
939 // throttled w/ 64 bytes per 8_ms, i.e. 1280 / 64 * 8_ms ~ 160_ms (~20 chunks)
940 const size_t max_chunck = 64;
941 for(size_t count=0; count < pipe_msg_count; ++count) {
942 size_t sent=0;
943 while( sent < pipe_msg_len && !outfile.fail() ) {
944 const size_t chunck_sz = std::min(max_chunck, pipe_msg_len-sent);
945 if( chunck_sz != outfile.write(pipe_msg+sent, chunck_sz) ) {
946 count = pipe_msg_count;
947 break;
948 }
949 sent += chunck_sz;
950 jau::sleep_for( 8_ms );
951 }
952 }
953
954 outfile.close();
955 ::close(pipe_fds[1]);
956
957 if( outfile.fail() ) {
958 jau::fprintf_td(stdout, "Child: Error: outfile failed after write/closure: %s\n", outfile.to_string().c_str());
959 ::_exit(EXIT_FAILURE);
960 }
961 jau::fprintf_td(stdout, "Child: Done\n");
962 ::_exit(EXIT_SUCCESS);
963
964 } else if( 0 < pid ) {
965 // parent process: READ
966 ::close(pipe_fds[1]); // close unused write end
967 const int new_stdin = pipe_fds[0]; // dup2(fd[0], 0);
968 const std::string fd_stdin = jau::fs::to_named_fd(new_stdin);
969
970 jau::fs::file_stats stats_stdin(fd_stdin);
971 jau::fprintf_td(stdout, "Parent: stats_stdin %s\n", stats_stdin.to_string().c_str());
972 REQUIRE( stats_stdin.exists() );
973 REQUIRE( stats_stdin.has_access() );
974 REQUIRE( !stats_stdin.is_socket() );
975 REQUIRE( !stats_stdin.is_block() );
976 REQUIRE( !stats_stdin.is_dir() );
977 REQUIRE( !stats_stdin.is_file() );
978 const bool fifo_or_char = stats_stdin.is_fifo() || stats_stdin.is_char();
979 REQUIRE( true == fifo_or_char );
980 REQUIRE( stats_stdin.has_fd() );
981 REQUIRE( new_stdin == stats_stdin.fd() );
982 REQUIRE( 0 == stats_stdin.size() );
983
984 // capture stdin
985 jau::io::ByteInStream_File infile(fd_stdin);
986 jau::fprintf_td(stdout, "Parent: infile %s\n", infile.to_string().c_str());
987 REQUIRE( !infile.fail() );
988
989 uint8_t buffer[pipe_msg_count * pipe_msg_len + 512];
990 jau::zero_bytes_sec(buffer, sizeof(buffer));
991 size_t total_read = 0;
992 {
993 while( infile.good() && total_read < sizeof(buffer) ) {
994 const size_t got = infile.read(buffer+total_read, sizeof(buffer)-total_read);
995 jau::fprintf_td(stdout, "Parent: infile.a_ %s\n", infile.to_string().c_str());
996 REQUIRE( !infile.fail() );
997 total_read += got;
998 jau::fprintf_td(stdout, "Parent: Got %zu -> %zu\n", got, total_read);
999 }
1000 jau::fprintf_td(stdout, "Parent: infile.a_1 %s\n", infile.to_string().c_str());
1001 infile.close();
1002 jau::fprintf_td(stdout, "Parent: infile.a_2 %s\n", infile.to_string().c_str());
1003 ::close(pipe_fds[0]);
1004 jau::fprintf_td(stdout, "Parent: infile.a_3 %s\n", infile.to_string().c_str());
1005 REQUIRE( !infile.fail() );
1006 }
1007 // check actual transmitted content
1008 REQUIRE( total_read == pipe_msg_len*pipe_msg_count);
1009 for(size_t count=0; count < pipe_msg_count; ++count) {
1010 REQUIRE( 0 == ::memcmp(pipe_msg, buffer+(count*pipe_msg_len), pipe_msg_len) );
1011 }
1012
1013 int pid_status = 0;
1014 ::pid_t child_pid = ::waitpid(pid, &pid_status, 0);
1015 if( 0 > child_pid ) {
1016 jau::fprintf_td(stdout, "Parent: Error: wait(%d) failed: child_pid %d\n", pid, child_pid);
1017 REQUIRE_MSG("wait for child failed", false);
1018 } else {
1019 if( child_pid != pid ) {
1020 jau::fprintf_td(stdout, "Parent: Error: wait(%d) terminated child_pid pid %d\n", pid, child_pid);
1021 REQUIRE(child_pid == pid);
1022 }
1023 if( !WIFEXITED(pid_status) ) {
1024 jau::fprintf_td(stdout, "Parent: Error: wait(%d) terminated abnormally child_pid %d, pid_status %d\n", pid, child_pid, pid_status);
1025 REQUIRE(true == WIFEXITED(pid_status));
1026 }
1027 if( EXIT_SUCCESS != WEXITSTATUS(pid_status) ) {
1028 jau::fprintf_td(stdout, "Parent: Error: wait(%d) exit with failure child_pid %d, exit_code %d\n", pid, child_pid, WEXITSTATUS(pid_status));
1029 REQUIRE(EXIT_SUCCESS == WEXITSTATUS(pid_status));
1030 }
1031 }
1032 } else {
1033 // fork failed
1034 jau::fprintf_td(stdout, "fork failed %d, %s\n", errno, ::strerror(errno));
1035 REQUIRE_MSG( "fork failed", false );
1036 }
1037 }
1038
1039 /**
1040 *
1041 */
1043 INFO_STR("\n\ntest10_mkdir\n");
1044
1046 {
1047 jau::fs::file_stats root_stats(temp_root);
1048 INFO_STR("root_stats.pre: "+root_stats.to_string()+"\n");
1049 REQUIRE( !root_stats.exists() );
1050 REQUIRE( root_stats.has_access() );
1051 REQUIRE( !root_stats.is_dir() );
1052 REQUIRE( !root_stats.is_file() );
1053 REQUIRE( !root_stats.is_link() );
1054 }
1056 {
1057 jau::fs::file_stats root_stats(temp_root);
1058 INFO_STR("root_stats.post: "+root_stats.to_string()+"\n");
1059 REQUIRE( root_stats.exists() );
1060 REQUIRE( root_stats.has_access() );
1061 REQUIRE( root_stats.is_dir() );
1062 REQUIRE( !root_stats.is_file() );
1063 REQUIRE( !root_stats.is_link() );
1064 }
1067 }
1068
1070 const jau::fraction_timespec td_1s(1, 0);
1071
1072 INFO_STR("\n\ntest11_touch\n");
1073 const std::string file_01 = temp_root+"/data01.txt";
1074 const std::string file_02 = temp_root+"/data02.txt";
1076 {
1077 jau::fs::file_stats root_stats(temp_root);
1078 jau::fprintf_td(stdout, "root_stats1.post: %s\n", root_stats.to_string().c_str());
1079 REQUIRE( root_stats.exists() );
1080 REQUIRE( root_stats.has_access() );
1081 REQUIRE( root_stats.is_dir() );
1082 REQUIRE( !root_stats.is_file() );
1083 REQUIRE( !root_stats.is_link() );
1084 }
1085
1086 REQUIRE( true == jau::fs::touch(file_01, jau::fs::fmode_t::def_file_prot) );
1087 {
1089 jau::fs::file_stats file_stats(file_01);
1090 jau::fprintf_td(stdout, "file_stats2.post: %s\n", file_stats.to_string().c_str());
1091 const jau::fraction_timespec btime = file_stats.btime();
1092 const jau::fraction_timespec atime = file_stats.atime();
1093 const jau::fraction_timespec atime_td = jau::abs(now - atime);
1094 const jau::fraction_timespec mtime = file_stats.mtime();
1095 const jau::fraction_timespec mtime_td = jau::abs(now - mtime);
1096 jau::fprintf_td(stdout, "now: %s, %s\n", now.to_iso8601_string().c_str(), now.to_string().c_str());
1097 jau::fprintf_td(stdout, "btime: %s, %s\n", btime.to_iso8601_string().c_str(), btime.to_string().c_str());
1098 jau::fprintf_td(stdout, "atime: %s, %s, td_now %s\n",
1099 atime.to_iso8601_string().c_str(), atime.to_string().c_str(), atime_td.to_string().c_str());
1100 jau::fprintf_td(stdout, "mtime: %s, %s, td_now %s\n",
1101 mtime.to_iso8601_string().c_str(), mtime.to_string().c_str(), mtime_td.to_string().c_str());
1102 REQUIRE( file_stats.exists() );
1103 REQUIRE( file_stats.has_access() );
1104 REQUIRE( !file_stats.is_dir() );
1105 REQUIRE( file_stats.is_file() );
1106 REQUIRE( !file_stats.is_link() );
1107 if( file_stats.has( jau::fs::file_stats::field_t::atime ) ) {
1108 REQUIRE( td_1s >= atime_td );
1109 }
1110 if( file_stats.has( jau::fs::file_stats::field_t::mtime ) ) {
1111 REQUIRE( td_1s >= mtime_td );
1112 }
1113 }
1114
1115 REQUIRE( true == jau::fs::touch(file_02, jau::fs::fmode_t::def_file_prot) );
1116 {
1118 jau::fs::file_stats file_stats_pre(file_02);
1119 const jau::fraction_timespec btime_pre = file_stats_pre.btime();
1120 const jau::fraction_timespec atime_pre = file_stats_pre.atime();
1121 const jau::fraction_timespec atime_td = jau::abs(now - atime_pre);
1122 const jau::fraction_timespec mtime_pre = file_stats_pre.mtime();
1123 const jau::fraction_timespec mtime_td = jau::abs(now - mtime_pre);
1124 jau::fprintf_td(stdout, "now : %s, %s\n", now.to_iso8601_string().c_str(), now.to_string().c_str());
1125 jau::fprintf_td(stdout, "btime.pre: %s, %s\n", btime_pre.to_iso8601_string().c_str(), btime_pre.to_string().c_str());
1126 jau::fprintf_td(stdout, "atime.pre: %s, %s, td_now %s\n",
1127 atime_pre.to_iso8601_string().c_str(), atime_pre.to_string().c_str(), atime_td.to_string().c_str());
1128 jau::fprintf_td(stdout, "mtime.pre: %s, %s, td_now %s\n",
1129 mtime_pre.to_iso8601_string().c_str(), mtime_pre.to_string().c_str(), mtime_td.to_string().c_str());
1130 if( file_stats_pre.has( jau::fs::file_stats::field_t::atime ) ) {
1131 REQUIRE( td_1s >= atime_td );
1132 }
1133 if( file_stats_pre.has( jau::fs::file_stats::field_t::mtime ) ) {
1134 REQUIRE( td_1s >= mtime_td );
1135 }
1136
1137 const jau::fraction_timespec ts_20200101( 1577836800_s + 0_h); // 2020-01-01 00:00:00
1138 const jau::fraction_timespec atime_set( ts_20200101 + 1_d + 10_h );
1139 const jau::fraction_timespec mtime_set( ts_20200101 + 31_d + 10_h );
1140 INFO_STR("atime.set: "+atime_set.to_iso8601_string()+", "+atime_set.to_string()+"\n");
1141 INFO_STR("mtime.set: "+mtime_set.to_iso8601_string()+", "+mtime_set.to_string()+"\n");
1142 REQUIRE( true == jau::fs::touch(file_02, atime_set, mtime_set, jau::fs::fmode_t::def_file_prot) );
1143
1144 jau::fs::file_stats file_stats_post(file_02);
1145 const jau::fraction_timespec atime_post = file_stats_post.atime();
1146 const jau::fraction_timespec mtime_post = file_stats_post.mtime();
1147 INFO_STR("atime.post: "+atime_post.to_iso8601_string()+", "+atime_post.to_string()+"\n");
1148 INFO_STR("mtime.post: "+mtime_post.to_iso8601_string()+", "+mtime_post.to_string()+"\n");
1149 jau::fprintf_td(stdout, "test11_touch: 03: %s\n", file_stats_post.to_string().c_str());
1150 {
1151 REQUIRE( file_stats_post.exists() );
1152 REQUIRE( file_stats_post.has_access() );
1153 REQUIRE( !file_stats_post.is_dir() );
1154 REQUIRE( file_stats_post.is_file() );
1155 REQUIRE( !file_stats_post.is_link() );
1156 if( file_stats_post.has( jau::fs::file_stats::field_t::atime ) ) {
1157 REQUIRE( atime_set == file_stats_post.atime() );
1158 }
1159 if( file_stats_post.has( jau::fs::file_stats::field_t::mtime ) ) {
1160 REQUIRE( mtime_set == file_stats_post.mtime() );
1161 }
1162 }
1163 }
1164
1166 }
1167
1168
1170 INFO_STR("\n\ntest21_visit_error\n");
1171 }
1172
1174 INFO_STR("\n\ntest20_visit\n");
1175
1176 std::string sub_dir1 = temp_root+"/sub1";
1177 std::string sub_dir2 = temp_root+"/sub2";
1178 std::string sub_dir3 = temp_root+"/sub1/sub3";
1179
1181 REQUIRE( true == jau::fs::touch(temp_root+"/data01.txt") );
1182 REQUIRE( true == jau::fs::touch(temp_root+"/data02.txt") );
1183 REQUIRE( true == jau::fs::mkdir(sub_dir1, jau::fs::fmode_t::def_dir_prot) );
1184 REQUIRE( true == jau::fs::mkdir(sub_dir2, jau::fs::fmode_t::def_dir_prot) );
1185 REQUIRE( true == jau::fs::mkdir(sub_dir3, jau::fs::fmode_t::def_dir_prot) );
1186 REQUIRE( true == jau::fs::touch(sub_dir1+"/data03.txt") );
1187 REQUIRE( true == jau::fs::touch(sub_dir1+"/data04.txt") );
1188 REQUIRE( true == jau::fs::touch(sub_dir2+"/data05.txt") );
1189 REQUIRE( true == jau::fs::touch(sub_dir2+"/data06.txt") );
1190 REQUIRE( true == jau::fs::touch(sub_dir3+"/data07.txt") );
1191 REQUIRE( true == jau::fs::touch(sub_dir3+"/data08.txt") );
1192
1196 visitor_stats stats_R_FSL_PDL(topts_R_FSL_PDL);
1197 {
1198 // Use an easy-code capturing lambda visitor
1199 const jau::fs::path_visitor pv = [&](jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1200 (void)tevt;
1201 (void)depth;
1202 stats_R_FSL_PDL.add(element_stats);
1203 return true;
1204 };
1205 REQUIRE( true == jau::fs::visit(temp_root, topts_R_FSL_PDL, pv) );
1206 jau::fprintf_td(stdout, "test20_visit[R, FSL, PDL]: %s\n%s\n", to_string(topts_R_FSL_PDL).c_str(), stats_R_FSL_PDL.to_string().c_str());
1207 REQUIRE( 12 == stats_R_FSL_PDL.total_real );
1208 REQUIRE( 0 == stats_R_FSL_PDL.total_sym_links_existing );
1209 REQUIRE( 0 == stats_R_FSL_PDL.total_sym_links_not_existing );
1210 REQUIRE( 0 == stats_R_FSL_PDL.total_no_access );
1211 REQUIRE( 0 == stats_R_FSL_PDL.total_not_existing );
1212 REQUIRE( 0 == stats_R_FSL_PDL.total_file_bytes );
1213 REQUIRE( 8 == stats_R_FSL_PDL.files_real );
1214 REQUIRE( 0 == stats_R_FSL_PDL.files_sym_link );
1215 REQUIRE( 4 == stats_R_FSL_PDL.dirs_real );
1216 REQUIRE( 0 == stats_R_FSL_PDL.dirs_sym_link );
1217 }
1221 visitor_stats stats_R_FSL(topts_R_FSL);
1222 {
1223 // Use a harder to code internal capturing-reference type visitor
1224 const jau::fs::path_visitor pv = jau::bind_capref(&stats_R_FSL,
1225 ( bool(*)(visitor_stats*, jau::fs::traverse_event, const jau::fs::file_stats&, size_t) ) /* help template type deduction of function-ptr */
1226 ( [](visitor_stats* stats_ptr, jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1227 (void)tevt;
1228 (void)depth;
1229 stats_ptr->add(element_stats);
1230 return true;
1231 } ) );
1232 REQUIRE( true == jau::fs::visit(temp_root, topts_R_FSL, pv) );
1233 jau::fprintf_td(stdout, "test20_visit[R, FSL]: %s\n%s\n", to_string(topts_R_FSL).c_str(), stats_R_FSL.to_string().c_str());
1234 REQUIRE( stats_R_FSL_PDL == stats_R_FSL );
1235 }
1236
1238 }
1239
1241 INFO_STR("\n\ntest22_visit_symlinks\n");
1242
1243 jau::fs::file_stats proot_stats = getTestDataDirStats(executable_path);
1244 REQUIRE( true == proot_stats.exists() );
1245 // recursive without symlinks
1246 {
1249 visitor_stats stats(topts);
1250
1251 // Use an easy-code capturing lambda visitor
1252 const jau::fs::path_visitor pv = [&](jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1253 (void)tevt;
1254 (void)depth;
1255 stats.add(element_stats);
1256 return true;
1257 };
1258 REQUIRE( true == jau::fs::visit(proot_stats, topts, pv) );
1259 jau::fprintf_td(stdout, "test22_visit[R]: %s\n%s\n", to_string(topts).c_str(), stats.to_string().c_str());
1260 REQUIRE( 7 == stats.total_real );
1261 REQUIRE( 10 == stats.total_sym_links_existing );
1262 REQUIRE( 4 == stats.total_sym_links_not_existing );
1263 REQUIRE( 0 == stats.total_no_access );
1264 REQUIRE( 4 == stats.total_not_existing );
1265 REQUIRE( 60 == stats.total_file_bytes );
1266 REQUIRE( 4 == stats.files_real );
1267 REQUIRE( 9 == stats.files_sym_link );
1268 REQUIRE( 3 == stats.dirs_real );
1269 REQUIRE( 1 == stats.dirs_sym_link );
1270 }
1271 // recursive with symlinks
1272 {
1276 visitor_stats stats(topts);
1277
1278 // Use an easy-code capturing lambda visitor
1279 const jau::fs::path_visitor pv = [&](jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1280 (void)tevt;
1281 (void)depth;
1282 stats.add(element_stats);
1283 return true;
1284 };
1285 REQUIRE( true == jau::fs::visit(proot_stats, topts, pv) );
1286 jau::fprintf_td(stdout, "test22_visit[R, FSL]: %s\n%s\n", to_string(topts).c_str(), stats.to_string().c_str());
1287 REQUIRE( 9 == stats.total_real );
1288 REQUIRE( 11 == stats.total_sym_links_existing );
1289 REQUIRE( 4 == stats.total_sym_links_not_existing );
1290 REQUIRE( 0 == stats.total_no_access );
1291 REQUIRE( 4 == stats.total_not_existing );
1292 REQUIRE( 60 < stats.total_file_bytes ); // some followed symlink files are of unknown size, e.g. /etc/fstab
1293 REQUIRE( 6 == stats.files_real );
1294 REQUIRE( 10 == stats.files_sym_link );
1295 REQUIRE( 3 == stats.dirs_real );
1296 REQUIRE( 1 == stats.dirs_sym_link );
1297 }
1298 // flat with symlinks
1299 {
1304 visitor_stats stats(topts);
1305
1306 // Use an easy-code capturing lambda visitor
1307 const jau::fs::path_visitor pv = [&](jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1308 (void)tevt;
1310 return false;
1311 }
1312 stats.add(element_stats);
1313 return true;
1314 };
1315 REQUIRE( true == jau::fs::visit(proot_stats, topts, pv) );
1316 jau::fprintf_td(stdout, "test22_visit[F, FSL]: %s\n%s\n", to_string(topts).c_str(), stats.to_string().c_str());
1317 REQUIRE( 3 == stats.total_real );
1318 REQUIRE( 5 == stats.total_sym_links_existing );
1319 REQUIRE( 4 == stats.total_sym_links_not_existing );
1320 REQUIRE( 0 == stats.total_no_access );
1321 REQUIRE( 4 == stats.total_not_existing );
1322 REQUIRE( 60 < stats.total_file_bytes ); // some followed symlink files are of unknown size, e.g. /etc/fstab
1323 REQUIRE( 1 == stats.files_real );
1324 REQUIRE( 5 == stats.files_sym_link );
1325 REQUIRE( 2 == stats.dirs_real );
1326 REQUIRE( 0 == stats.dirs_sym_link );
1327 }
1328 }
1329
1331 INFO_STR("\n\ntest30_copy_file2dir\n");
1332
1333 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1334 REQUIRE( true == root_orig_stats.exists() );
1335
1336 const std::string root_copy = temp_root+"_copy_test30";
1337 {
1338 // Fresh target folder
1340
1341 REQUIRE( true == jau::fs::mkdir(root_copy, jau::fs::fmode_t::def_dir_prot) );
1342 {
1343 jau::fs::file_stats stats(root_copy);
1344 REQUIRE( true == stats.exists() );
1345 REQUIRE( true == stats.ok() );
1346 REQUIRE( true == stats.is_dir() );
1347 }
1348 }
1349 jau::fs::file_stats source1_stats(root_orig_stats.path()+"/file_01.txt");
1350 jau::fprintf_td(stdout, "test30_copy_file2dir: source1: %s\n", source1_stats.to_string().c_str());
1351 {
1352 REQUIRE( true == source1_stats.exists() );
1353 REQUIRE( true == source1_stats.ok() );
1354 REQUIRE( true == source1_stats.is_file() );
1355 }
1356 {
1357 // Copy file to folder
1360 {
1361 jau::fs::file_stats dest_stats(root_copy+"/file_01.txt");
1362 jau::fprintf_td(stdout, "test30_copy_file2dir: 01: dest.pre: %s\n", dest_stats.to_string().c_str());
1363 REQUIRE( false == dest_stats.exists() );
1364 }
1365 REQUIRE( true == jau::fs::copy(source1_stats.path(), root_copy, copts) );
1366 {
1367 jau::fs::file_stats dest_stats(root_copy+"/file_01.txt");
1368 jau::fprintf_td(stdout, "test30_copy_file2dir: 01: dest.post: %s\n", dest_stats.to_string().c_str());
1369 REQUIRE( true == dest_stats.exists() );
1370 REQUIRE( true == dest_stats.ok() );
1371 REQUIRE( true == dest_stats.is_file() );
1372 REQUIRE( source1_stats.size() == dest_stats.size() );
1373 REQUIRE( source1_stats.mode() == dest_stats.mode() );
1374 }
1375 }
1376 {
1377 // Error: already exists of 'Copy file to folder'
1380 {
1381 jau::fs::file_stats dest_stats(root_copy+"/file_01.txt");
1382 jau::fprintf_td(stdout, "test30_copy_file2dir: 02: dest.pre: %s\n", dest_stats.to_string().c_str());
1383 REQUIRE( true == dest_stats.exists() );
1384 REQUIRE( true == dest_stats.ok() );
1385 REQUIRE( true == dest_stats.is_file() );
1386 }
1387 REQUIRE( false == jau::fs::copy(source1_stats.path(), root_copy, copts) );
1388 }
1389 {
1390 // Overwrite copy file to folder
1394
1395 jau::fprintf_td(stdout, "test30_copy_file2dir: 03: source: %s\n", source1_stats.to_string().c_str());
1396 {
1397 jau::fs::file_stats dest_stats(root_copy+"/file_01.txt");
1398 jau::fprintf_td(stdout, "test30_copy_file2dir: 03: dest.pre: %s\n", dest_stats.to_string().c_str());
1399 REQUIRE( true == dest_stats.exists() );
1400 REQUIRE( true == dest_stats.ok() );
1401 REQUIRE( true == dest_stats.is_file() );
1402 REQUIRE( source1_stats.size() == dest_stats.size() );
1403 REQUIRE( source1_stats.mode() == dest_stats.mode() );
1404 }
1405 REQUIRE( true == jau::fs::copy(source1_stats.path(), root_copy, copts) );
1406 {
1407 jau::fs::file_stats dest_stats(root_copy+"/file_01.txt");
1408 jau::fprintf_td(stdout, "test30_copy_file2dir: 03: dest.post: %s\n", dest_stats.to_string().c_str());
1409 REQUIRE( true == dest_stats.exists() );
1410 REQUIRE( true == dest_stats.ok() );
1411 REQUIRE( true == dest_stats.is_file() );
1412 REQUIRE( source1_stats.size() == dest_stats.size() );
1413 REQUIRE( source1_stats.mode() == dest_stats.mode() );
1414 }
1415 }
1416 if constexpr ( _remove_target_test_dir ) {
1417 REQUIRE( true == jau::fs::remove(root_copy, jau::fs::traverse_options::recursive) );
1418 }
1419 }
1420
1422 INFO_STR("\n\ntest31_copy_file2file\n");
1423
1424 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1425 REQUIRE( true == root_orig_stats.exists() );
1426
1427 const std::string root_copy = temp_root+"_copy_test31";
1428 {
1429 // Fresh target folder
1431
1432 REQUIRE( true == jau::fs::mkdir(root_copy, jau::fs::fmode_t::def_dir_prot) );
1433 {
1434 jau::fs::file_stats stats(root_copy);
1435 REQUIRE( true == stats.exists() );
1436 REQUIRE( true == stats.ok() );
1437 REQUIRE( true == stats.is_dir() );
1438 }
1439 }
1440 jau::fs::file_stats source1_stats(root_orig_stats.path()+"/file_01.txt");
1441 jau::fprintf_td(stdout, "test31_copy_file2file: source1: %s\n", source1_stats.to_string().c_str());
1442 {
1443 REQUIRE( true == source1_stats.exists() );
1444 REQUIRE( true == source1_stats.ok() );
1445 REQUIRE( true == source1_stats.is_file() );
1446 }
1447 jau::fs::file_stats source2_stats(root_orig_stats.path()+"/README_slink08_relext.txt");
1448 jau::fprintf_td(stdout, "test31_copy_file2file: source2: %s\n", source2_stats.to_string().c_str());
1449 {
1450 REQUIRE( true == source2_stats.exists() );
1451 REQUIRE( true == source2_stats.ok() );
1452 REQUIRE( true == source2_stats.is_file() );
1453 REQUIRE( true == source2_stats.is_link() );
1454 }
1455 {
1456 // Copy file to new file-name
1459 {
1460 jau::fs::file_stats dest_stats(root_copy+"/file_10.txt");
1461 jau::fprintf_td(stdout, "test31_copy_file2file: 10: dest.pre: %s\n", dest_stats.to_string().c_str());
1462 REQUIRE( false == dest_stats.exists() );
1463 }
1464 REQUIRE( true == jau::fs::copy(source1_stats.path(), root_copy+"/file_10.txt", copts) );
1465 jau::fs::sync(); // just check API
1466 {
1467 jau::fs::file_stats dest_stats(root_copy+"/file_10.txt");
1468 jau::fprintf_td(stdout, "test31_copy_file2file: 10: dest.post: %s\n", dest_stats.to_string().c_str());
1469 REQUIRE( true == dest_stats.exists() );
1470 REQUIRE( true == dest_stats.ok() );
1471 REQUIRE( true == dest_stats.is_file() );
1472 REQUIRE( source1_stats.size() == dest_stats.size() );
1473 REQUIRE( source1_stats.mode() == dest_stats.mode() );
1474 }
1475 }
1476 {
1477 // Error: already exists of 'Copy file to file'
1480 {
1481 jau::fs::file_stats dest_stats(root_copy+"/file_10.txt");
1482 jau::fprintf_td(stdout, "test31_copy_file2file: 11: dest.pre: %s\n", dest_stats.to_string().c_str());
1483 REQUIRE( true == dest_stats.exists() );
1484 REQUIRE( true == dest_stats.ok() );
1485 REQUIRE( true == dest_stats.is_file() );
1486 }
1487 REQUIRE( false == jau::fs::copy(source1_stats.path(), root_copy+"/file_10.txt", copts) );
1488 jau::fs::sync(); // just check API
1489 }
1490 {
1491 // Overwrite copy file to file
1496
1497 {
1498 jau::fs::file_stats dest_stats(root_copy+"/file_10.txt");
1499 jau::fprintf_td(stdout, "test31_copy_file2file: 12: dest.pre: %s\n", dest_stats.to_string().c_str());
1500 REQUIRE( true == dest_stats.exists() );
1501 REQUIRE( true == dest_stats.ok() );
1502 REQUIRE( true == dest_stats.is_file() );
1503 REQUIRE( source1_stats.size() == dest_stats.size() );
1504 REQUIRE( source1_stats.mode() == dest_stats.mode() );
1505 }
1506 REQUIRE( true == jau::fs::copy(source2_stats.path(), root_copy+"/file_10.txt", copts) );
1507 jau::fs::sync(); // just check API
1508 {
1509 jau::fs::file_stats dest_stats(root_copy+"/file_10.txt");
1510 jau::fprintf_td(stdout, "test31_copy_file2file: 12: dest.post: %s\n", dest_stats.to_string().c_str());
1511 REQUIRE( true == dest_stats.exists() );
1512 REQUIRE( true == dest_stats.ok() );
1513 REQUIRE( true == dest_stats.is_file() );
1514 REQUIRE( false == dest_stats.is_link() );
1515 REQUIRE( source2_stats.size() == dest_stats.size() );
1516 REQUIRE( source2_stats.link_target()->prot_mode() == dest_stats.prot_mode() );
1517 }
1518 }
1519 if constexpr ( _remove_target_test_dir ) {
1520 REQUIRE( true == jau::fs::remove(root_copy, jau::fs::traverse_options::recursive) );
1521 }
1522 }
1523
1525 INFO_STR("\n\ntest40_copy_ext_r_p\n");
1526
1527 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1528 REQUIRE( true == root_orig_stats.exists() );
1529
1534 const std::string root_copy = temp_root+"_copy_test40";
1536 testxx_copy_r_p("test40_copy_ext_r_p", root_orig_stats, 0 /* source_added_dead_links */, root_copy, copts, false /* dest_is_vfat */);
1537 REQUIRE( true == jau::fs::remove(root_copy, jau::fs::traverse_options::recursive) );
1538 }
1539
1541 INFO_STR("\n\ntest41_copy_ext_r_p_below\n");
1542
1543 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1544 REQUIRE( true == root_orig_stats.exists() );
1545
1550 const std::string root_copy_parent = temp_root+"_copy_test41_parent";
1552 REQUIRE( true == jau::fs::mkdir(root_copy_parent, jau::fs::fmode_t::def_dir_prot) );
1553 testxx_copy_r_p("test41_copy_ext_r_p_below", root_orig_stats, 0 /* source_added_dead_links */, root_copy_parent, copts, false /* dest_is_vfat */);
1554 REQUIRE( true == jau::fs::remove(root_copy_parent, jau::fs::traverse_options::recursive) );
1555 }
1556
1558 INFO_STR("\n\ntest41_copy_ext_r_p_into\n");
1559
1560 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1561 REQUIRE( true == root_orig_stats.exists() );
1562
1568 const std::string root_copy = temp_root+"_copy_test42_into";
1570 REQUIRE( true == jau::fs::mkdir(root_copy, jau::fs::fmode_t::def_dir_prot) );
1571 testxx_copy_r_p("test42_copy_ext_r_p_into", root_orig_stats, 0 /* source_added_dead_links */, root_copy, copts, false /* dest_is_vfat */);
1572 REQUIRE( true == jau::fs::remove(root_copy, jau::fs::traverse_options::recursive) );
1573 }
1574
1576 INFO_STR("\n\ntest43_copy_ext_r_p_over\n");
1577
1578 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1579 REQUIRE( true == root_orig_stats.exists() );
1580
1585 const std::string root_copy = temp_root+"_copy_test43_over";
1587 REQUIRE( true == jau::fs::mkdir(root_copy, jau::fs::fmode_t::def_dir_prot) );
1588 const std::string root_copy_sub = root_copy+"/"+root_orig_stats.item().basename();
1589 REQUIRE( true == jau::fs::mkdir(root_copy_sub, jau::fs::fmode_t::def_dir_prot) );
1590 testxx_copy_r_p("test43_copy_ext_r_p_over", root_orig_stats, 0 /* source_added_dead_links */, root_copy, copts, false /* dest_is_vfat */);
1591 REQUIRE( true == jau::fs::remove(root_copy, jau::fs::traverse_options::recursive) );
1592 }
1593
1595 INFO_STR("\n\ntest49_copy_ext_r_p_vfat\n");
1596
1597 // Query and prepare vfat data sink
1598 jau::fs::file_stats dest_fs_vfat_stats(dest_fs_vfat);
1599 if( !dest_fs_vfat_stats.is_dir() ) {
1600 jau::fprintf_td(stdout, "test49_copy_ext_r_p_vfat: Skipped, no vfat dest-dir %s\n", dest_fs_vfat_stats.to_string().c_str());
1601 return;
1602 }
1603 const std::string dest_vfat_parent = dest_fs_vfat+"/test49_data_sink";
1605 if( !jau::fs::mkdir(dest_vfat_parent, jau::fs::fmode_t::def_dir_prot) ) {
1606 jau::fprintf_td(stdout, "test49_copy_ext_r_p_vfat: Skipped, couldn't create vfat dest folder %s\n", dest_vfat_parent.c_str());
1607 return;
1608 }
1609
1610 // Source
1611 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1612 REQUIRE( true == root_orig_stats.exists() );
1613
1619 const std::string dest_vfat_dir = dest_vfat_parent+"/"+temp_root;
1620 testxx_copy_r_p("test49_copy_ext_r_p_vfat", root_orig_stats, 0 /* source_added_dead_links */, dest_vfat_dir, copts, true /* dest_is_vfat */);
1621
1622 REQUIRE( true == jau::fs::remove(dest_vfat_parent, jau::fs::traverse_options::recursive) );
1623 }
1624
1626 INFO_STR("\n\ntest50_copy_ext_r_p_fsl\n");
1627
1628 jau::fs::file_stats root_orig_stats = getTestDataDirStats(executable_path);
1629 REQUIRE( true == root_orig_stats.exists() );
1630
1631 const std::string root_copy = temp_root+"_copy_test50";
1637 {
1639
1640 REQUIRE( true == jau::fs::copy(root_orig_stats.path(), root_copy, copts) );
1641 }
1642 jau::fs::file_stats root_copy_stats(root_copy);
1643 REQUIRE( true == root_copy_stats.exists() );
1644 REQUIRE( true == root_copy_stats.ok() );
1645 REQUIRE( true == root_copy_stats.is_dir() );
1646
1647 bool(*pv_capture)(visitor_stats*, jau::fs::traverse_event, const jau::fs::file_stats&, size_t) =
1648 ( [](visitor_stats* stats_ptr, jau::fs::traverse_event tevt, const jau::fs::file_stats& element_stats, size_t depth) -> bool {
1649 (void)tevt;
1650 (void)depth;
1651 stats_ptr->add(element_stats);
1652 return true;
1653 } );
1654 {
1658
1661 visitor_stats stats(topts_orig);
1662 visitor_stats stats_copy(topts_copy);
1663 const jau::fs::path_visitor pv_orig = jau::bind_capref(&stats, pv_capture);
1664 const jau::fs::path_visitor pv_copy = jau::bind_capref(&stats_copy, pv_capture);
1665 REQUIRE( true == jau::fs::visit(root_orig_stats, topts_orig, pv_orig) );
1666 REQUIRE( true == jau::fs::visit(root_copy_stats, topts_copy, pv_copy) );
1667
1668 jau::fprintf_td(stdout, "test50_copy_ext_r_p_fsl: copy %s, traverse_orig %s, traverse_copy %s\n",
1669 to_string(copts).c_str(), to_string(topts_orig).c_str(), to_string(topts_copy).c_str());
1670
1671 jau::fprintf_td(stdout, "test50_copy_ext_r_p_fsl: source visitor stats\n%s\n", stats.to_string().c_str());
1672 jau::fprintf_td(stdout, "test50_copy_ext_r_p_fsl: destination visitor stats\n%s\n", stats_copy.to_string().c_str());
1673
1674 REQUIRE( 9 == stats.total_real );
1675 REQUIRE( 11 == stats.total_sym_links_existing );
1676 REQUIRE( 4 == stats.total_sym_links_not_existing );
1677 REQUIRE( 0 == stats.total_no_access );
1678 REQUIRE( 4 == stats.total_not_existing );
1679 REQUIRE( 60 < stats.total_file_bytes ); // some followed symlink files are of unknown size, e.g. /etc/fstab
1680 REQUIRE( 6 == stats.files_real );
1681 REQUIRE( 10 == stats.files_sym_link );
1682 REQUIRE( 3 == stats.dirs_real );
1683 REQUIRE( 1 == stats.dirs_sym_link );
1684
1685 REQUIRE( 20 == stats_copy.total_real );
1686 REQUIRE( 0 == stats_copy.total_sym_links_existing );
1687 REQUIRE( 0 == stats_copy.total_sym_links_not_existing );
1688 REQUIRE( 0 == stats_copy.total_no_access );
1689 REQUIRE( 0 == stats_copy.total_not_existing );
1690 REQUIRE( 60 < stats_copy.total_file_bytes ); // some followed symlink files are of unknown size, e.g. /etc/fstab
1691 REQUIRE( 16 == stats_copy.files_real );
1692 REQUIRE( 0 == stats_copy.files_sym_link );
1693 REQUIRE( 4 == stats_copy.dirs_real );
1694 REQUIRE( 0 == stats_copy.dirs_sym_link );
1695 }
1696
1697 const std::string root_copy_renamed = temp_root+"_copy_test50_renamed";
1698 {
1699 REQUIRE( true == jau::fs::rename(root_copy, root_copy_renamed) );
1700 }
1701 jau::fs::file_stats root_copy_stats2(root_copy);
1702 REQUIRE( false == root_copy_stats2.exists() );
1703
1704 jau::fs::file_stats root_copy_renamed_stats(root_copy_renamed);
1705 REQUIRE( true == root_copy_renamed_stats.exists() );
1706 REQUIRE( true == root_copy_renamed_stats.ok() );
1707 REQUIRE( true == root_copy_renamed_stats.is_dir() );
1708
1709 {
1712 visitor_stats stats_copy(topts_copy);
1713 const jau::fs::path_visitor pv_copy = jau::bind_capref(&stats_copy, pv_capture);
1714 REQUIRE( true == jau::fs::visit(root_copy_renamed_stats, topts_copy, pv_copy) );
1715
1716 jau::fprintf_td(stdout, "test50_copy_ext_r_p_fsl: renamed: traverse_copy %s\n", to_string(topts_copy).c_str());
1717
1718 jau::fprintf_td(stdout, "test50_copy_ext_r_p_fsl: renamed: visitor stats\n%s\n", stats_copy.to_string().c_str());
1719
1720 REQUIRE( 20 == stats_copy.total_real );
1721 REQUIRE( 0 == stats_copy.total_sym_links_existing );
1722 REQUIRE( 0 == stats_copy.total_sym_links_not_existing );
1723 REQUIRE( 0 == stats_copy.total_no_access );
1724 REQUIRE( 0 == stats_copy.total_not_existing );
1725 REQUIRE( 60 < stats_copy.total_file_bytes ); // some followed symlink files are of unknown size, e.g. /etc/fstab
1726 REQUIRE( 16 == stats_copy.files_real );
1727 REQUIRE( 0 == stats_copy.files_sym_link );
1728 REQUIRE( 4 == stats_copy.dirs_real );
1729 REQUIRE( 0 == stats_copy.dirs_sym_link );
1730 }
1731
1732 if constexpr ( _remove_target_test_dir ) {
1733 REQUIRE( true == jau::fs::remove(root_copy_renamed, jau::fs::traverse_options::recursive) );
1734 }
1735 }
1736};
1737
1738METHOD_AS_TEST_CASE( TestFileUtil01::test00_testfiles, "Test TestFileUtil01 - test00_testfiles");
1739METHOD_AS_TEST_CASE( TestFileUtil01::test01_cwd, "Test TestFileUtil01 - test01_cwd");
1740METHOD_AS_TEST_CASE( TestFileUtil01::test02_dirname, "Test TestFileUtil01 - test02_dirname");
1741METHOD_AS_TEST_CASE( TestFileUtil01::test03_basename, "Test TestFileUtil01 - test03_basename");
1742METHOD_AS_TEST_CASE( TestFileUtil01::test03b_absolute, "Test TestFileUtil01 - test03b_absolute");
1743METHOD_AS_TEST_CASE( TestFileUtil01::test04_dir_item, "Test TestFileUtil01 - test04_dir_item");
1744METHOD_AS_TEST_CASE( TestFileUtil01::test05_file_stat, "Test TestFileUtil01 - test05_file_stat");
1745METHOD_AS_TEST_CASE( TestFileUtil01::test06_file_stat_symlinks, "Test TestFileUtil01 - test06_file_stat_symlinks");
1746METHOD_AS_TEST_CASE( TestFileUtil01::test07_file_stat_fd, "Test TestFileUtil01 - test07_file_stat_fd");
1747METHOD_AS_TEST_CASE( TestFileUtil01::test08_pipe_01, "Test TestFileUtil01 - test08_pipe_01");
1748
1749METHOD_AS_TEST_CASE( TestFileUtil01::test10_mkdir, "Test TestFileUtil01 - test10_mkdir");
1750METHOD_AS_TEST_CASE( TestFileUtil01::test11_touch, "Test TestFileUtil01 - test11_touch");
1751
1752METHOD_AS_TEST_CASE( TestFileUtil01::test20_visit, "Test TestFileUtil01 - test20_visit");
1753METHOD_AS_TEST_CASE( TestFileUtil01::test22_visit_symlinks, "Test TestFileUtil01 - test22_visit_symlinks");
1754
1755METHOD_AS_TEST_CASE( TestFileUtil01::test30_copy_file2dir, "Test TestFileUtil01 - test30_copy_file2dir");
1756METHOD_AS_TEST_CASE( TestFileUtil01::test31_copy_file2file, "Test TestFileUtil01 - test31_copy_file2file");
1757
1758METHOD_AS_TEST_CASE( TestFileUtil01::test40_copy_ext_r_p, "Test TestFileUtil01 - test40_copy_ext_r_p");
1759METHOD_AS_TEST_CASE( TestFileUtil01::test41_copy_ext_r_p_below, "Test TestFileUtil01 - test41_copy_ext_r_p_below");
1760METHOD_AS_TEST_CASE( TestFileUtil01::test42_copy_ext_r_p_into, "Test TestFileUtil01 - test42_copy_ext_r_p_into");
1761METHOD_AS_TEST_CASE( TestFileUtil01::test43_copy_ext_r_p_over, "Test TestFileUtil01 - test43_copy_ext_r_p_over");
1762
1763METHOD_AS_TEST_CASE( TestFileUtil01::test49_copy_ext_r_p_vfat, "Test TestFileUtil01 - test49_copy_ext_r_p_vfat");
1764
1765METHOD_AS_TEST_CASE( TestFileUtil01::test50_copy_ext_r_p_fsl, "Test TestFileUtil01 - test50_copy_ext_r_p_fsl");
static void test_file_stat_fd_item(const jau::fs::fmode_t exp_type, const int fd, const std::string &named_fd1, const std::string &named_fd_link)
static const size_t pipe_msg_count
static const size_t pipe_msg_len
static constexpr const char * pipe_msg
jau::fs::file_stats getTestDataImageFile(const std::string &test_exe_path) noexcept
const std::string temp_root
const std::string dest_fs_vfat
std::string getTestDataRelDir(const std::string &test_exe_path) noexcept
jau::fs::file_stats getTestDataDirStats(const std::string &test_exe_path) noexcept
const std::string project_root_ext
Representing a directory item split into dirname() and basename().
std::string path() const noexcept
Returns a full unix path representation combining dirname() and basename().
const std::string & basename() const noexcept
Return the basename, shall not be empty nor contain a dirname.
bool empty() const noexcept
Returns true if bot, dirname() and basename() refer to .
std::string to_string() const noexcept
Returns a comprehensive string representation of this item.
const std::string & dirname() const noexcept
Returns the dirname, shall not be empty and denotes .
Platform agnostic representation of POSIX ::lstat() and ::stat() for a given pathname.
constexpr bool is_char() const noexcept
Returns true if entity is a character device, might be in combination with is_link().
int fd() const noexcept
Returns the file descriptor if has_fd(), otherwise -1 for no file descriptor.
constexpr bool exists() const noexcept
Returns true if entity does not exist, exclusive bit.
fmode_t type_mode() const noexcept
Returns the type bit portion of fmode_t, i.e.
constexpr bool has_fd() const noexcept
Returns true if entity has a file descriptor.
const fraction_timespec & mtime() const noexcept
Returns the last modification time of this element since Unix Epoch.
constexpr bool is_fifo() const noexcept
Returns true if entity is a fifo/pipe, might be in combination with is_link().
constexpr bool is_link() const noexcept
Returns true if entity is a symbolic link, might be in combination with is_file(),...
constexpr bool is_file() const noexcept
Returns true if entity is a file, might be in combination with is_link().
const file_stats * final_target(size_t *link_count=nullptr) const noexcept
Returns the final target element, either a pointer to this instance if not a symbolic-link or the fin...
constexpr bool is_dir() const noexcept
Returns true if entity is a directory, might be in combination with is_link().
const dir_item & item() const noexcept
Returns the dir_item.
bool has(const field_t fields) const noexcept
Returns true if the given field_t fields were retrieved, otherwise false.
uint64_t size() const noexcept
Returns the size in bytes of this element if is_file(), otherwise zero.
constexpr bool is_socket() const noexcept
Returns true if entity is a socket, might be in combination with is_link().
const fraction_timespec & btime() const noexcept
Returns the birth time of this element since Unix Epoch, i.e.
constexpr bool has_access() const noexcept
Returns true if entity gives no access to user, exclusive bit.
constexpr bool ok() const noexcept
Returns true if no error occurred.
const std::shared_ptr< std::string > & link_target_path() const noexcept
Returns the stored link-target path this symbolic-link points to if instance is a symbolic-link,...
fmode_t mode() const noexcept
Returns the fmode_t, file type and mode.
const std::shared_ptr< file_stats > & link_target() const noexcept
Returns the link-target this symbolic-link points to if instance is a symbolic-link,...
std::string to_string() const noexcept
Returns a comprehensive string representation of this element.
fmode_t prot_mode() const noexcept
Returns the POSIX protection bit portion of fmode_t, i.e.
const fraction_timespec & atime() const noexcept
Returns the last access time of this element since Unix Epoch.
constexpr field_t fields() const noexcept
Returns the retrieved field_t fields.
constexpr bool is_block() const noexcept
Returns true if entity is a block device, might be in combination with is_link().
std::string path() const noexcept
Returns the unix path representation.
File based byte input stream, including named file descriptor.
std::string to_string() const noexcept override
void close() noexcept override
Close the stream if supported by the underlying mechanism.
size_t read(void *, size_t) noexcept override
Read from the source.
File based byte output stream, including named file descriptor.
void close() noexcept override
Close the stream if supported by the underlying mechanism.
size_t write(const void *, size_t) noexcept override
Write to the data sink.
std::string to_string() const noexcept override
bool is_open() const noexcept override
Checks if the stream has an associated file.
bool fail() const noexcept
Checks if an error has occurred.
bool good() const noexcept
Checks if no error nor eof() has occurred i.e.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr bool is_set(const E mask, const E bits) noexcept
bool mkdir(const std::string &path, const fmode_t mode=jau::fs::fmode_t::def_dir_prot, const bool verbose=false) noexcept
Create directory.
std::string to_named_fd(const int fd) noexcept
Returns platform dependent named file descriptor of given file descriptor, if supported.
std::string to_string(const fmode_t mask, const bool show_rwx) noexcept
Return the string representation of fmode_t.
bool copy(const std::string &source_path, const std::string &dest_path, const copy_options copts=copy_options::none) noexcept
Copy the given source_path to dest_path using copy_options.
fmode_t
Generic file type and POSIX protection mode bits as used in file_stats, touch(), mkdir() etc.
std::string basename(const std::string_view &path) noexcept
Return stripped leading directory components from given path separated by /.
std::string get_cwd() noexcept
Return the current working directory or empty on failure.
Definition file_util.cpp:84
bool visit(const std::string &path, const traverse_options topts, const path_visitor &visitor, std::vector< int > *dirfds=nullptr) noexcept
Visit element(s) of a given path, see traverse_options for detailed settings.
std::string absolute(const std::string_view &relpath) noexcept
Returns the absolute path of given relpath if existing, otherwise an empty string.
std::string dirname(const std::string_view &path) noexcept
Return stripped last component from given path separated by /, excluding the trailing separator /.
copy_options
Filesystem copy options used to copy() path elements.
bool touch(const std::string &path, const jau::fraction_timespec &atime, const jau::fraction_timespec &mtime, const fmode_t mode=jau::fs::fmode_t::def_file_prot) noexcept
Touch the file with given atime and mtime and create file if not existing yet.
traverse_options
Filesystem traverse options used to visit() path elements.
bool rename(const std::string &oldpath, const std::string &newpath) noexcept
Rename oldpath to newpath using POSIX rename(), with the following combinations.
bool remove(const std::string &path, const traverse_options topts=traverse_options::none) noexcept
Remove the given path.
void sync() noexcept
Synchronizes filesystems, i.e.
bool isAbsolute(const std::string_view &path) noexcept
Returns true if first character is / or - in case of Windows - \\.
traverse_event
Filesystem traverse event used to call path_visitor for path elements from visit().
jau::function< bool(traverse_event, const file_stats &, size_t)> path_visitor
path_visitor jau::FunctionDef definition
@ def_file_prot
Default file protection bit: Safe default: POSIX S_IRUSR | S_IWUSR | S_IRGRP or read_usr | write_usr ...
@ none
No mode bit set.
@ chr
Type: Entity is a character device, might be in combination with link.
@ file
Type: Entity is a file, might be in combination with link.
@ fifo
Type: Entity is a fifo/pipe, might be in combination with link.
@ def_dir_prot
Default directory protection bit: Safe default: POSIX S_IRWXU | S_IRGRP | S_IXGRP or rwx_usr | read_g...
@ ignore_symlink_errors
Ignore errors from erroneous symlinks, e.g.
@ verbose
Enable verbosity mode, show error messages on stderr.
@ follow_symlinks
Copy referenced symbolic linked files or directories instead of just the symbolic link with property ...
@ sync
Ensure data and meta-data file synchronization is performed via ::fsync() after asynchronous copy ope...
@ overwrite
Overwrite existing destination files.
@ preserve_all
Preserve uid and gid if allowed and access- and modification-timestamps, i.e.
@ into_existing_dir
Copy source dir content into an already existing destination directory as if destination directory di...
@ recursive
Traverse through directories, i.e.
@ verbose
Enable verbosity mode, potentially used by a path_visitor implementation like remove().
@ follow_symlinks
Traverse through symbolic linked directories if traverse_options::recursive is set,...
@ dir_check_entry
Call path_visitor at directory entry, allowing path_visitor to skip traversal of this directory if re...
@ dir_entry
Call path_visitor at directory entry.
@ dir_exit
Call path_visitor at directory exit.
@ recursive
Traverse through directories, i.e.
@ dir_check_entry
Visiting a directory on entry, see traverse_options::dir_check_entry.
fraction_timespec getWallClockTime() noexcept
Returns current wall-clock real-time since Unix Epoch 00:00:00 UTC on 1970-01-01.
jau::function< R(A...)> bind_capref(I *data_ptr, R(*func)(I *, A...)) noexcept
Bind given data by passing the captured reference (pointer) to the value and non-void function to an ...
constexpr T abs(const T x) noexcept
Returns the absolute value of an arithmetic number (w/ branching) in O(1)
void zero_bytes_sec(void *s, size_t n) noexcept __attrdecl_no_optimize__
Wrapper to ::explicit_bzero(), ::bzero() or ::memset(), whichever is available in that order.
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
Definition debug.cpp:270
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
std::string to_string() const noexcept
Return simple string representation in seconds and nanoseconds.
std::string to_iso8601_string(bool space_separator=false, bool muteTime=false) const noexcept
Convenience string conversion interpreted since Unix Epoch in UTC to ISO 8601 YYYY-mm-ddTHH:MM:SS....
std::string to_string() const noexcept
int total_sym_links_not_existing
void add(const jau::fs::file_stats &element_stats)
METHOD_AS_TEST_CASE(TestFileUtil01::test00_testfiles, "Test TestFileUtil01 - test00_testfiles")
static constexpr const bool _remove_target_test_dir
void testxx_copy_r_p(const std::string &title, const jau::fs::file_stats &source, const int source_added_dead_links, const std::string &dest, const jau::fs::copy_options copts, const bool dest_is_vfat)