AFLOW
 
Loading...
Searching...
No Matches
aurostd_xfile.cpp
Go to the documentation of this file.
1// ***************************************************************************
2// * *
3// * Aflow STEFANO CURTAROLO - Duke University 2003-2024 *
4// * *
5// ***************************************************************************
6// This file hold function dealing with files
7// hagen.eckert@duke.edu
8
9#ifndef _AUROSTD_XFILE_CPP_
10#define _AUROSTD_XFILE_CPP_
11
12#include "aurostd_xfile.h"
13
14#include <algorithm>
15#include <cmath>
16#include <cstddef>
17#include <cstdlib>
18#include <ctime>
19#include <deque>
20#include <filesystem>
21#include <fstream>
22#include <ios>
23#include <iostream>
24#include <regex>
25#include <sstream>
26
27#include <archive.h>
28#include <archive_entry.h>
29
30#include <sys/stat.h>
31
32#include "aurostd.h"
33#include "aurostd_defs.h"
34#include "aurostd_time.h"
35#include "aurostd_xerror.h"
36#include "aurostd_xrandom.h"
37#include "aurostd_xscalar.h"
38
39#include "aflow_xhost.h" // todo required for XPID use and XHOST.DEBUG use
40
41using std::cerr;
42using std::endl;
43
44namespace aurostd {
51 bool DirectoryMake(const string& directory_raw) {
52 const string directory = CleanFileName(directory_raw);
53 if (!std::filesystem::is_directory(directory)) {
54 return std::filesystem::create_directories(directory);
55 }
56 return true;
57 }
58
63 [[deprecated("Should be rewritten without using system calls")]]
64 bool SSH_DirectoryMake(const string& user, const string& machine, const string& directory_raw) { // "" compliant SC20190401
65 const bool LDEBUG = (false || XHOST.DEBUG);
66 const string Directory(aurostd::CleanFileName(directory_raw));
67 std::deque<string> tokens;
68 string dir_tmp;
69 string command;
70 aurostd::string2tokens(Directory, tokens, "/");
71 if (Directory.at(0) == '/') {
72 tokens[0] = "/" + tokens[0]; // fix the root thing
73 }
74 for (const auto& token : tokens) {
75 dir_tmp += token + "/";
76 command = "ssh " + user + "@" + machine + " mkdir \"" + dir_tmp + "\"";
77 if (LDEBUG) {
78 cerr << "SSH_DirectoryMake creating directory=" << command << endl;
79 }
80 aurostd::execute(command);
81 }
82 return true;
83 }
84
92 bool SubDirectoryLS(const string& directory_raw, vector<string>& vsubd) {
93 const string directory = CleanFileName(directory_raw);
94 if (directory.empty()) {
95 return false;
96 }
97 vsubd.clear();
98 vsubd.push_back(directory);
99 for (const std::filesystem::directory_entry& dir_entry : std::filesystem::directory_iterator(directory)) {
100 if (dir_entry.is_directory()) {
101 vsubd.push_back(dir_entry.path().filename().string());
102 }
103 }
104 return true;
105 }
106
114 bool DirectoryLS(const string& directory_raw, vector<string>& vfiles) {
115 const string directory = CleanFileName(directory_raw);
116 if (directory.empty()) {
117 return false;
118 }
119 vfiles.clear();
120 for (const std::filesystem::directory_entry& dir_entry : std::filesystem::directory_iterator(directory)) {
121 vfiles.push_back(dir_entry.path().filename().string());
122 }
123 return true;
124 }
125
126 bool DirectoryLS(const string& directory_raw, deque<string>& vfiles) {
127 vector<string> _vfiles;
128 if (DirectoryLS(directory_raw, _vfiles)) {
129 vfiles = aurostd::vector2deque(_vfiles);
130 return true;
131 }
132 return false;
133 }
134
141 string dirname(const string& file) {
142 return std::filesystem::path(aurostd::CleanFileName(file)).parent_path();
143 }
144
151 string basename(const string& file) {
152 return std::filesystem::path(aurostd::CleanFileName(file)).stem();
153 }
154
159 string GetFileExtension(const string& FileName) {
160 return std::filesystem::path(FileName).extension().string();
161 }
162
170 string CleanFileName(const string& fileIN) {
171 const bool LDEBUG = (false || XHOST.DEBUG);
172 if (fileIN.empty()) {
173 return fileIN;
174 }
175 // ME20211001
176 // Remove any control characters (below ASCII 32) while copying. This is useful
177 // when fileIN is read from a file, which can have all sorts of junk and causes
178 // FileExist to break. We cannot use RemoveControlCodeCharactersFromString()
179 // because it keeps tabs and linebreaks and cannot use CleanStringASCII because
180 // it keeps control characters.
181 string fileOUT;
182 for (const char c : fileIN) {
183 if (c > 31) {
184 fileOUT += c;
185 }
186 }
187 if (fileOUT.find('~') != string::npos) {
188 aurostd::StringSubstInPlace(fileOUT, "~", getenv("HOME"));
189 }
190 // ME20200922 - Cleaning // must be in a while loop, or it won't clean e.g. ///
191 while (fileOUT.find("//") != string::npos) {
192 aurostd::StringSubstInPlace(fileOUT, "//", "/");
193 }
194 aurostd::StringSubstInPlace(fileOUT, "/./", "/");
195
196 if (LDEBUG) {
197 cerr << __AFLOW_FUNC__ << " " << fileOUT << endl;
198 }
199 return fileOUT;
200 }
201
205 string CleanFileName(const fs::path& fileIN) {
206 return CleanFileName(fileIN.string());
207 }
208
210 bool DirectoryLocked(const string& directory, const string& LOCK) {
211 if (FileExist(directory + "/" + LOCK)) {
212 return true;
213 }
214 if (FileExist(directory + "/" + LOCK + _LOCK_LINK_SUFFIX_)) {
215 return true;
216 }
217 if (FileExist(directory + "/" + LOCK + ".xz")) {
218 return true;
219 }
220 if (FileExist(directory + "/" + LOCK + ".gz")) {
221 return true;
222 }
223 if (FileExist(directory + "/" + LOCK + ".bz2")) {
224 return true;
225 }
226 return false;
227 }
228
229 bool DirectoryLocked(const string& directory) {
230 return DirectoryLocked(directory, "LOCK");
231 }
232
234 bool DirectorySkipped(const string& directory) {
235 if (FileExist(directory + "/SKIP")) {
236 return true;
237 }
238 if (FileExist(directory + "/SKIP.xz")) {
239 return true;
240 }
241 if (FileExist(directory + "/SKIP.gz")) {
242 return true;
243 }
244 if (FileExist(directory + "/SKIP.bz2")) {
245 return true;
246 }
247 return false;
248 }
249
251 bool DirectoryWritable(const string& directory_raw) { // "" compliant SC20190401
252 const string Directory(aurostd::CleanFileName(directory_raw));
253 const string filename = aurostd::TmpFileCreate("DirectoryWritable", Directory, true); // SD20220223 - uses TmpFileCreate
254 const bool writable = aurostd::string2file("DirectoryWritable", filename);
255 if (!writable || !FileExist(filename)) {
256 return false;
257 }
258 aurostd::RemoveFile(filename);
259 return true;
260 }
261
268 bool IsDirectory(const string& path) {
269 return std::filesystem::is_directory(aurostd::CleanFileName(path));
270 }
271
277 //***************************************************************************//
278 // aurostd::IsCompressed
279 //***************************************************************************//
280 bool IsCompressed(const string& FileNameIn) {
281 const std::filesystem::path path(FileNameIn);
282 archive* a;
283 archive_entry* entry;
284 bool check = aurostd::FileNotEmpty(FileNameIn);
285 int r;
286
287 // initialized the new archive
288 a = archive_read_new();
289 if (path.extension() == ".zip") {
290 archive_read_support_format_zip(a);
291 } else {
292 archive_read_support_format_raw(a);
293 archive_read_support_format_empty(a);
294 archive_read_support_filter_all(a);
295 }
296
297 // open the archive
298 r = archive_read_open_filename(a, FileNameIn.c_str(), 16384);
299 if (r != ARCHIVE_OK) {
300 check = false;
301 }
302
303 if (check) {
304 // check if the content is valid (only quick check - file could be corrupt later)
305 archive_read_next_header(a, &entry);
306 if ((static_cast<std::string>(archive_filter_name(a, r)) == "none") && (static_cast<std::string>(archive_format_name(a)) == "raw")) {
307 check = false;
308 }
309 }
310 archive_read_free(a);
311 return check;
312 }
313
320 bool IsCompressed(const string& FileNameIn, string& FileNameOut) {
321 const std::filesystem::path path(FileNameIn);
322 FileNameOut = path.parent_path().string() + "/" + path.stem().string();
323 return IsCompressed(FileNameIn);
324 }
325
332 bool FileExist(const string& FileName) {
333 try {
334 return std::filesystem::exists(aurostd::CleanFileName(FileName));
335 } catch (std::filesystem::filesystem_error& e) {
336 return false;
337 }
338 }
339
345 bool FileExist(const string& FileName, string& FileNameOut) {
346 if (FileExist(FileName)) {
347 FileNameOut = FileName;
348 return true;
349 }
350 return false;
351 }
352
354 bool CompressFileExist(const string& FileName) {
355 string FileNameOut;
356 return CompressFileExist(FileName, FileNameOut);
357 }
358
365 bool CompressFileExist(const string& FileNameRaw, string& FileNameOut) {
366 const string FileName = aurostd::CleanFileName(FileNameRaw);
367 if (FileExist(FileName)) {
368 FileNameOut = FileName;
369 return true;
370 }
371 if (FileExist(FileName + ".xz")) {
372 FileNameOut = FileName + ".xz";
373 return true;
374 }
375 if (FileExist(FileName + ".bz2")) {
376 FileNameOut = FileName + ".bz2";
377 return true;
378 }
379 if (FileExist(FileName + ".gz")) {
380 FileNameOut = FileName + ".gz";
381 return true;
382 }
383 if (FileExist(FileName + ".zip")) {
384 FileNameOut = FileName + ".zip";
385 return true;
386 }
387 return false;
388 }
389
396 bool CompressFileWithinList(const vector<string>& list, const string& input) {
397 string output;
398 return CompressFileWithinList(list, input, output);
399 }
400
409 bool CompressFileWithinList(const vector<string>& list, const string& input, string& output) {
410 output = "";
411 for (const string& entry : list) {
412 for (const string& suffix : compression_suffix) {
413 if (entry == input + suffix) {
414 output = input + suffix;
415 return true;
416 }
417 }
418 }
419 return false;
420 }
421
427 bool FileEmpty(const string& FileNameRaw) {
428 const string FileName(aurostd::CleanFileName(FileNameRaw));
429 if (!FileExist(FileName)) {
430 return true; // does not exist hence empty
431 }
432 ifstream FileStream(FileName);
433 return (FileStream.peek() == ifstream::traits_type::eof());
434 }
435
437 bool FileNotEmpty(const string& FileName) {
438 return !FileEmpty(FileName);
439 }
440
446 long int GetTimestampModified(const string& FileNameRaw) {
447 const string FileName(aurostd::CleanFileName(FileNameRaw));
448 if (!FileExist(FileName)) {
449 return 0;
450 }
451 time_t tm = 0;
452 struct stat file_stat{};
453 if (stat(FileName.c_str(), &file_stat) == 0) {
454 tm = file_stat.st_mtime;
455 }
456 return static_cast<long int>(tm);
457 }
458
465 // gets modification time and returns SECONDS since now (as long int)
466 long int SecondsSinceFileModified(const string& FileNameRaw) {
467 const string FileName(aurostd::CleanFileName(FileNameRaw));
468 if (!FileExist(FileName)) {
469 return 0;
470 }
471 const long int tmod_file = GetTimestampModified(FileName);
472 // instead, write a new file and take the difference in the time stamps
473 // solution inspired by ME - create a temporary file IN THE CURRENT DIRECTORY (within NFS) and check time deltas
474 const string dir = aurostd::dirname(FileName);
475 const string tmpfile = aurostd::TmpFileCreate("timestamp", dir, true); // put in current directory, make it hidden
476 if (!aurostd::string2file("timestamp", tmpfile)) {
477 return 0;
478 } // write the file out, need a better fix here, perhaps write to /tmp?
479 const long int tmod_tmp = aurostd::GetTimestampModified(tmpfile);
480 aurostd::RemoveFile(tmpfile);
481 return max(static_cast<long int>(0), tmod_tmp - tmod_file); // max ensures that if something goes wrong, we return 0
482 }
483
492 unsigned long long int FileSize(const string& FileName) {
493 return std::filesystem::file_size(aurostd::CleanFileName(FileName));
494 }
495
500 void InFileExistCheck(const string& routine, const string& FileNameRaw, const ifstream& file_to_check) {
501 const string FileName(aurostd::CleanFileName(FileNameRaw));
502 if (!file_to_check) {
503 const string message = "In routine " + routine + ". Cannot open file " + FileName + ".";
505 }
506 }
507
515 string TmpStrCreate(const string& identifier_raw, const string& tmpdir_raw, const bool hidden, const bool directory) {
516 string identifier = identifier_raw;
517 if (identifier.empty()) {
518 identifier = "tmp";
519 } // CO20210624
520 string tmpdir = tmpdir_raw;
521 if (tmpdir.empty()) {
522 tmpdir = XHOST.tmpfs;
523 } // CO20210315
524 string str = tmpdir + "/" + (hidden ? "." : "") + "_aflow_" + identifier + "." + XHOST.user + ".pid" + XHOST.ostrPID.str() + ".tid" + XHOST.ostrTID.str() + ".a" + AFLOW_VERSION +
525 ".rnd" + aurostd::utype2string(uint(std::floor((double) 100000 * aurostd::ran0()))) + ".u" + aurostd::utype2string(uint((double) aurostd::get_useconds())) + (directory ? "_" : ".") + "tmp"; // CO20200502 - threadID
526 str = aurostd::CleanFileName(str);
527 return str;
528 }
529
533 string TmpFileCreate(const string& identifier, const string& tmpdir, const bool hidden) { // CO20210315
534 return TmpStrCreate(identifier, tmpdir, hidden, false); // directory=false -> creating a file
535 }
536
541 string TmpDirectoryCreate(const string& identifier, const string& tmpdir, const bool hidden) { // CO20210315
542 string dir = TmpStrCreate(identifier, tmpdir, hidden, true); // directory=true -> creating a directory
543 DirectoryMake(dir);
544 return dir;
545 }
546
555 bool CopyFile(const string& file_from, const string& file_to) {
556 const std::filesystem::path from_path = CleanFileName(file_from);
557 const std::filesystem::path to_path = CleanFileName(file_to);
558
559 if (!std::filesystem::is_regular_file(from_path)) {
560 return false;
561 }
562 if (std::filesystem::is_regular_file(to_path)) { // equivalence check can only be performed if both paths point to a file
563 if (std::filesystem::equivalent(from_path, to_path)) {
564 return false;
565 }
566 }
567 return std::filesystem::copy_file(from_path, to_path, std::filesystem::copy_options::overwrite_existing);
568 }
569
578 bool LinkFile(const string& file_from, const string& file_to, const bool soft) {
579 const string from_clean = CleanFileName(file_from);
580 const string to_clean = CleanFileName(file_to);
581 const std::filesystem::path from_path = from_clean;
582 const std::filesystem::path to_path = to_clean;
583 if (from_path.empty() || to_path.empty() || !std::filesystem::exists(from_path) || std::filesystem::exists(to_path) || !std::filesystem::exists(to_path.parent_path())) {
584 return false;
585 }
586 if (soft) {
587 std::filesystem::create_symlink(from_clean, to_clean);
588 return std::filesystem::is_symlink(to_clean);
589 }
590 std::filesystem::create_hard_link(from_clean, to_clean);
591 return std::filesystem::is_regular_file(to_clean);
592 }
593
601 bool file2directory(const string& file, const string& destination) {
602 const std::filesystem::path old_path = CleanFileName(file);
603 const std::filesystem::path dir_path = CleanFileName(destination);
604 if (!std::filesystem::is_regular_file(old_path)) {
605 return false;
606 }
607 if (!std::filesystem::is_directory(dir_path)) {
608 return false;
609 }
610 try {
611 std::filesystem::rename(old_path, dir_path / old_path.filename());
612 } catch (std::filesystem::filesystem_error& e) {
613 std::filesystem::copy(old_path, dir_path / old_path.filename(), std::filesystem::copy_options::overwrite_existing);
614 std::filesystem::remove(old_path);
615 }
616 return true;
617 }
618
622 bool file2directory(const vector<string>& files, const string& destination) {
623 for (const auto& file : files) {
624 if (!file2directory(file, destination)) {
625 return false;
626 }
627 }
628
629 return true;
630 }
631
639 bool file2file(const string& file, const string& destination) {
640 const std::filesystem::path old_path = CleanFileName(file);
641 const std::filesystem::path new_path = CleanFileName(destination);
642 if (!std::filesystem::is_regular_file(old_path)) {
643 return false;
644 }
645 try {
646 std::filesystem::rename(old_path, new_path);
647 } catch (std::filesystem::filesystem_error& e) {
648 std::filesystem::copy(old_path, new_path, std::filesystem::copy_options::overwrite_existing);
649 std::filesystem::remove(old_path);
650 }
651 return true;
652 }
653
660 bool RemoveFile(const string& file) {
661 const std::filesystem::path path(aurostd::CleanFileName(file));
662 if (std::filesystem::is_regular_file(path)) {
663 return std::filesystem::remove(path);
664 }
665 return false;
666 }
667
674 bool RemoveFile(const string& directory, const std::regex& regex_pattern) {
675 const std::filesystem::path path(aurostd::CleanFileName(directory));
676 for (const std::filesystem::directory_entry& dir_entry : std::filesystem::directory_iterator(std::filesystem::path(aurostd::CleanFileName(directory)))) {
677 if (dir_entry.is_regular_file() && std::regex_match(dir_entry.path().filename().string(), regex_pattern)) {
678 std::filesystem::remove(dir_entry.path());
679 }
680 }
681 return true;
682 }
683
688 bool RemoveFiles(const string& directory) {
689 for (const auto& dir_entry : std::filesystem::directory_iterator(aurostd::CleanFileName(directory))) {
690 if (dir_entry.is_regular_file()) {
691 std::filesystem::remove(dir_entry.path());
692 }
693 }
694 return true;
695 }
696
700 bool RemoveFile(const vector<string>& files) {
701 for (const auto& file : files) {
702 if (!RemoveFile(file)) {
703 return false;
704 }
705 }
706 return true;
707 }
708
715 bool RemoveDirectory(const string& directory) {
716 const std::filesystem::path path(aurostd::CleanFileName(directory));
717 if (std::filesystem::is_directory(path)) {
718 std::filesystem::remove_all(path);
719 }
720 return false;
721 }
722
723 compression_type GetCompressionType(const fs::path& path) {
724 const string extension = aurostd::GetFileExtension(path);
725 const auto it = std::find(compression_suffix.begin(), compression_suffix.end(), extension);
726 if (it == compression_suffix.end()) {
728 }
729 const compression_type ct = static_cast<compression_type>(it - compression_suffix.begin());
730 return ct;
731 }
732
738 size_t file2string(const string& FileNameIN, string& StringIN) {
739 const string FileNameINClean = aurostd::CleanFileName(FileNameIN);
740 if (GetCompressionType(FileNameINClean)) {
741 return compressfile2string(FileNameINClean, StringIN);
742 }
743 const std::ifstream open_file(FileNameINClean);
744 std::stringstream buffer;
745 buffer << open_file.rdbuf();
746 StringIN = buffer.str();
747 return StringIN.length();
748 }
749
751 string file2string(const string& FileNameIN) {
752 string StringIN;
753 file2string(FileNameIN, StringIN);
754 return StringIN;
755 }
756
763 size_t compressfile2string(const string& FileNameIN, string& content) {
764 const string file(aurostd::CleanFileName(FileNameIN));
765 std::stringstream ss;
767 content = ss.str();
768 return content.length();
769 }
770
772 string compressfile2string(const string& FileNameIN) {
773 string StringIN;
774 compressfile2string(FileNameIN, StringIN);
775 return StringIN;
776 }
777
779 size_t file2vectorstring(const string& FileNameIN, vector<string>& vline, bool consecutive, bool trim_edges) {
780 return aurostd::string2vectorstring(file2string(aurostd::CleanFileName(FileNameIN)), vline, consecutive, trim_edges);
781 }
782
784 size_t file2vectorstring(const string& FileNameIN, deque<string>& vline) {
786 }
787
790 size_t compressfile2vectorstring(const string& FileNameIN, vector<string>& vline, bool consecutive, bool trim_edges) {
791 return aurostd::string2vectorstring(compressfile2string(aurostd::CleanFileName(FileNameIN)), vline, consecutive, trim_edges);
792 }
793
796 size_t compressfile2vectorstring(const string& FileNameIN, deque<string>& vline) {
798 }
799
802 void file2stringstream(const string& FileNameIN, stringstream& StringstreamIN) {
803 const string FileNameINClean = aurostd::CleanFileName(FileNameIN);
804 if (GetCompressionType(FileNameINClean)) {
805 compressfile2stringstream(FileNameINClean, StringstreamIN);
806 } else {
807 const std::ifstream open_file(FileNameINClean);
808 StringstreamIN << open_file.rdbuf();
809 }
810 }
811
818 void compressfile2stringstream(const string& file_raw, stringstream& content) {
819 const string file(aurostd::CleanFileName(file_raw));
820 static constexpr size_t buff_len = 16384;
821 thread_local char buff[buff_len + 1];
822 archive* a = archive_read_new();
823 archive_entry* entry;
824
825 // initialized the archive to be read
826
827 if (aurostd::GetFileExtension(file) == ".zip") {
828 archive_read_support_format_zip(a);
829 } else {
830 archive_read_support_format_raw(a);
831 archive_read_support_format_empty(a);
832 archive_read_support_filter_all(a);
833 }
834
835 // open the archive
836 if (const int r = archive_read_open_filename(a, file.c_str(), buff_len); r != ARCHIVE_OK) {
837 const std::string message = "Problem loading output: ";
838 throw aurostd::xerror(__AFLOW_FILE__, __AFLOW_FUNC__, message + archive_error_string(a), _FILE_NOT_FOUND_);
839 }
840 archive_read_next_header(a, &entry);
841
842 // prepare the stringstream and write the data
844 size_t len = archive_read_data(a, buff, buff_len);
845 while (len > 0) { // read until archive is empty
846 buff[len] = '\0'; // ensure proper termination of the c style string
847 content << buff;
848 len = archive_read_data(a, buff, buff_len);
849 }
850
851 // free objects created in this function
852 archive_read_free(a);
853 }
854
865 bool string2file(const string& StringOUTPUT, const std::string& FileNameRawOUTPUT, const compression_type ct, const string& mode) {
866 const fs::path FileNameOUTPUT = CleanFileName(FileNameRawOUTPUT);
867 try {
868 fs::create_directories(fs::absolute(FileNameOUTPUT).parent_path());
869 } catch (fs::filesystem_error& e) {
870 return false;
871 }
872 bool writable = true; // CO20190808 - captures whether we can open/write file
873
874 if (mode == "POST" || mode == "APPEND" || mode == "PRE") {
875 string FileINPUT;
876 if (fs::exists(FileNameOUTPUT)) {
877 aurostd::file2string(FileNameOUTPUT, FileINPUT);
878 }
879 if (ct) {
880 if (mode == "POST" || mode == "APPEND") {
881 return string2compressfile(StringOUTPUT + FileINPUT, FileNameOUTPUT, ct);
882 }
883 return string2compressfile(FileINPUT + StringOUTPUT, FileNameOUTPUT, ct);
884 }
885 ofstream FileOUTPUT;
886 FileOUTPUT.open(FileNameOUTPUT.c_str(), std::ios::out);
887 writable = FileOUTPUT.is_open(); // CO20190808 - captures whether we can open/write file
888 if (mode == "POST" || mode == "APPEND") {
889 FileOUTPUT << FileINPUT;
890 }
891 FileOUTPUT << StringOUTPUT;
892 if (mode == "PRE") {
893 FileOUTPUT << FileINPUT;
894 }
895 FileOUTPUT.flush();
896 FileOUTPUT.clear();
897 FileOUTPUT.close();
898 return writable; // return false if something got messed up //CO20190808 - captures whether we can open/write file
899 }
900
901 if (mode == "WRITE" || mode.empty()) {
902 if (ct) {
903 return string2compressfile(StringOUTPUT, FileNameOUTPUT, ct);
904 }
905 ofstream FileOUTPUT;
906 FileOUTPUT.open(FileNameOUTPUT.c_str(), std::ios::out);
907 writable = FileOUTPUT.is_open(); // CO20190808 - captures whether we can open/write file
908 FileOUTPUT << StringOUTPUT;
909 FileOUTPUT.flush();
910 FileOUTPUT.clear();
911 FileOUTPUT.close();
912 return writable; // return false if something got messed up //CO20190808 - captures whether we can open/write file
913 }
914 return false;
915 }
916
925 bool string2compressfile(const string& content, const string& file_raw, const compression_type ct) {
926 fs::path file(aurostd::CleanFileName(file_raw));
927 try {
928 fs::create_directories(fs::absolute(file).parent_path());
929 } catch (fs::filesystem_error& e) {
930 return false;
931 }
932
933 archive* a;
934 archive_entry* entry;
935 int r;
936
937 // initialized the new archive
938 a = archive_write_new();
939 entry = archive_entry_new();
940
941 // select compression and archive format
942 aurostd::CompressInit(a, ct, true);
943
944 // open the new archive
945 if (const std::string ext = file.extension(); ext != compression_suffix[ct]) {
946 file = file.replace_extension(ext + compression_suffix[ct]);
947 }
948
949 r = archive_write_open_filename(a, file.c_str());
950 if (r != ARCHIVE_OK) {
951 const std::string message = "Problem preparing output: ";
952 throw aurostd::xerror(__AFLOW_FILE__, __AFLOW_FUNC__, message + archive_error_string(a), _FILE_NOT_FOUND_);
953 }
954
955 // configure new entry
956 archive_entry_set_pathname(entry, file.c_str());
957 archive_entry_set_size(entry, content.size());
958 archive_entry_set_filetype(entry, AE_IFREG);
959
960 // save file information to archive
961 archive_write_header(a, entry);
962
963 // write string to archive
964 archive_write_data(a, content.c_str(), content.size());
965
966 // free objects created in this function
967 archive_entry_free(entry);
968 archive_write_close(a);
969 archive_write_free(a);
970 return true;
971 }
972
974 bool stringstream2file(const stringstream& StringstreamOUTPUT, const string& FileNameOUTPUT, const compression_type ct, const string& mode) {
975 return string2file(StringstreamOUTPUT.str(), FileNameOUTPUT, ct, mode);
976 }
977
985 bool stringstream2compressfile(const stringstream& content, const string& file, const compression_type ct) {
986 return string2compressfile(content.str(), file, ct);
987 }
988
998 template <template <class...> class vtype> bool vectorstring2file(const vtype<string>& vline, const string& FileNameOUT, const compression_type ct) {
999 const fs::path file = aurostd::CleanFileName(FileNameOUT);
1000
1001 try {
1002 fs::create_directories(fs::absolute(file).parent_path());
1003 } catch (fs::filesystem_error& e) {
1004 return false;
1005 }
1006
1007 if (ct) {
1008 std::stringstream full_string;
1009 for (const auto& iline : vline) {
1010 full_string << iline << endl;
1011 }
1012 return stringstream2compressfile(full_string, file, ct);
1013 }
1014 ofstream FileOUT;
1015 FileOUT.open(file.c_str(), std::ios::out);
1016 const bool writable = FileOUT.is_open(); // CO20190808 - captures whether we can open/write file
1017 for (const auto& iline : vline) {
1018 FileOUT << iline << endl;
1019 }
1020 FileOUT.flush();
1021 FileOUT.clear();
1022 FileOUT.close();
1023 return writable;
1024 }
1025 template bool vectorstring2file(const vector<string>& vline, const string& FileNameOUT, compression_type ct);
1026 template bool vectorstring2file(const deque<string>& vline, const string& FileNameOUT, compression_type ct);
1027
1029 void CompressionErrorHandling(archive* a, const int r, const std::string& message) {
1030 if (r != ARCHIVE_OK) {
1031 if (r == ARCHIVE_WARN) {
1032 const string full_message = "LibArchive Warning during " + message + ": ";
1033 if (XHOST.DEBUG) {
1034 cerr << full_message << archive_error_string(a) << " (not a fatal error)" << endl;
1035 }
1036 } else {
1037 const string full_message = "LibArchive Error during " + message + ": ";
1038 throw aurostd::xerror(__AFLOW_FILE__, __AFLOW_FUNC__, full_message + archive_error_string(a), _RUNTIME_INIT_);
1039 }
1040 }
1041 }
1042
1050 void CompressInit(archive* a, const compression_type ct, const bool single) {
1051 int r = ARCHIVE_OK;
1052 const std::string error_message = "initialization";
1053 switch (ct) {
1054 case BZ2:
1055 if (single) {
1056 r = archive_write_set_format_raw(a);
1057 } else {
1058 r = archive_write_set_format_pax_restricted(a);
1059 }
1060 CompressionErrorHandling(a, r, error_message);
1061 r = archive_write_add_filter_bzip2(a);
1062 CompressionErrorHandling(a, r, error_message);
1063 r = archive_write_set_options(a, "compression-level=9");
1064 CompressionErrorHandling(a, r, error_message);
1065 break;
1066 case GZ:
1067 if (single) {
1068 r = archive_write_set_format_raw(a);
1069 } else {
1070 r = archive_write_set_format_pax_restricted(a);
1071 }
1072 CompressionErrorHandling(a, r, error_message);
1073 r = archive_write_add_filter_gzip(a);
1074 CompressionErrorHandling(a, r, error_message);
1075 r = archive_write_set_options(a, "compression-level=9");
1076 CompressionErrorHandling(a, r, error_message);
1077 break;
1078 case XZ:
1079 if (single) {
1080 r = archive_write_set_format_raw(a);
1081 } else {
1082 r = archive_write_set_format_pax_restricted(a);
1083 }
1084 CompressionErrorHandling(a, r, error_message);
1085 r = archive_write_add_filter_xz(a);
1086 CompressionErrorHandling(a, r, error_message);
1087 r = archive_write_set_options(a, "compression-level=9,threads=1");
1088 CompressionErrorHandling(a, r, error_message);
1089 break;
1090 case ZIP:
1091 r = archive_write_set_format_zip(a);
1092 CompressionErrorHandling(a, r, error_message);
1093 if (single) {
1094 r = archive_write_set_options(a, "compression=deflate,zip64");
1095 } else {
1096 r = archive_write_set_options(a, "compression=store,zip64");
1097 }
1098 CompressionErrorHandling(a, r, error_message);
1099 break;
1100 case ZSTD:
1101 if (single) {
1102 r = archive_write_set_format_raw(a);
1103 } else {
1104 r = archive_write_set_format_pax_restricted(a);
1105 }
1106 CompressionErrorHandling(a, r, error_message);
1107 r = archive_write_add_filter_zstd(a);
1108 CompressionErrorHandling(a, r, error_message);
1109 r = archive_write_set_options(a, "compression-level=20");
1110 CompressionErrorHandling(a, r, error_message);
1111 break;
1112 default: throw aurostd::xerror(__AFLOW_FILE__, __AFLOW_FUNC__, "Unknown archive format", _INPUT_UNKNOWN_);
1113 }
1114 }
1115
1123 void DecompressFile(const string& file_raw, const string& outfile_raw, const bool keep) {
1124 const string file(aurostd::CleanFileName(file_raw));
1125 string outfile(aurostd::CleanFileName(outfile_raw));
1126 const std::filesystem::path path(file);
1127 thread_local char buff[16384];
1128 archive* a;
1129 archive_entry* entry;
1130 size_t len;
1131 int r = ARCHIVE_OK;
1132 const std::string error_message = "decompression of a single file";
1133
1134 // initialized the new archive and the file entries
1135 a = archive_read_new();
1136 if (path.extension() == ".zip") {
1137 r = archive_read_support_format_zip(a);
1138 CompressionErrorHandling(a, r, error_message);
1139 } else {
1140 r = archive_read_support_format_raw(a);
1141 CompressionErrorHandling(a, r, error_message);
1142 r = archive_read_support_format_empty(a);
1143 CompressionErrorHandling(a, r, error_message);
1144 r = archive_read_support_filter_all(a);
1145 CompressionErrorHandling(a, r, error_message);
1146 }
1147
1148 // open the archive
1149 r = archive_read_open_filename(a, file.c_str(), sizeof(buff));
1150 CompressionErrorHandling(a, r, error_message);
1151 if (outfile.empty()) {
1152 outfile = path.parent_path().string() + "/" + path.stem().string();
1153 }
1154 r = archive_read_next_header(a, &entry);
1155 if (r == ARCHIVE_EOF) { // create empty file if archive has no data
1156 std::fstream fs(outfile, std::ios::out);
1157 fs.close();
1158 } else {
1159 CompressionErrorHandling(a, r, error_message);
1160 // open the new file and write it in chunks
1161 std::fstream fs(outfile, std::ios::out);
1162 len = archive_read_data(a, buff, sizeof(buff));
1163 while (len > 0) { // read until archive is empty
1164 fs.write(buff, len);
1165 len = archive_read_data(a, buff, sizeof(buff));
1166 }
1167 fs.close();
1168 }
1169
1170 // free objects created in this function
1171 if (!keep) {
1172 aurostd::RemoveFile(file);
1173 }
1174 r = archive_read_free(a);
1175 CompressionErrorHandling(a, r, error_message);
1176 }
1177
1178 void DecompressFile(const string& file_raw, const bool keep) {
1179 DecompressFile(file_raw, "", keep);
1180 }
1181
1188 void DecompressFiles(const string& archive_file, const string& directory, const bool keep) {
1189 const string archive_file_clean(aurostd::CleanFileName(archive_file));
1190 string directory_clean(aurostd::CleanFileName(directory));
1191 std::filesystem::path path(archive_file_clean);
1192 thread_local char buff[16384];
1193 archive* a;
1194 archive_entry* entry;
1195 size_t len;
1196 int r = ARCHIVE_OK;
1197 const std::string error_message = "decompression of multiple files";
1198
1199 // initialized the new archive and the file entries
1200 a = archive_read_new();
1201 if (path.extension() == ".zip") {
1202 r = archive_read_support_format_zip(a);
1203 CompressionErrorHandling(a, r, error_message);
1204 } else {
1205 r = archive_read_support_format_tar(a);
1206 CompressionErrorHandling(a, r, error_message);
1207 r = archive_read_support_filter_all(a);
1208 CompressionErrorHandling(a, r, error_message);
1209 }
1210
1211 // open the archive
1212 r = archive_read_open_filename(a, archive_file_clean.c_str(), sizeof(buff));
1213 CompressionErrorHandling(a, r, error_message);
1214
1215 // open the new files and write it in chunks
1216 if (directory_clean.empty()) {
1217 directory_clean = aurostd::getPWD();
1218 }
1219 while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
1220 if ((static_cast<std::string>(archive_filter_name(a, r)) == "none") && (static_cast<std::string>(archive_format_name(a)) == "raw")) {
1221 continue;
1222 }
1223 path = std::filesystem::path(directory_clean + "/" + archive_entry_pathname(entry));
1224 if (!std::filesystem::is_directory(path.parent_path())) {
1225 std::filesystem::create_directories(path.parent_path());
1226 }
1227 std::fstream fs(path.string(), std::ios::out);
1228 len = archive_read_data(a, buff, sizeof(buff));
1229 while (len > 0) { // read until archive is empty
1230 fs.write(buff, len);
1231 len = archive_read_data(a, buff, sizeof(buff));
1232 }
1233 fs.close();
1234 }
1235
1236 // free objects created in this function
1237 if (!keep) {
1238 aurostd::RemoveFile(archive_file_clean);
1239 }
1240 r = archive_read_free(a);
1241 CompressionErrorHandling(a, r, error_message);
1242 }
1243
1244 void DecompressFiles(const string& archive, const bool keep) {
1245 DecompressFiles(archive, "", keep);
1246 }
1247
1255 void CompressFile(const string& file_raw, const compression_type ct, const bool keep) {
1256 const fs::path file(aurostd::CleanFileName(file_raw));
1257
1258 thread_local char buff[16384];
1259 archive* a;
1260 archive* disk;
1261 archive_entry* entry;
1262 int r = ARCHIVE_OK;
1263 const std::string error_message = "compression of a single file";
1264
1265 // initialized the new archive, the disk reader and the file entries
1266 a = archive_write_new();
1267 entry = archive_entry_new();
1268 disk = archive_read_disk_new();
1269 r = archive_read_disk_set_standard_lookup(disk);
1270 CompressionErrorHandling(a, r, error_message);
1271
1272 // select compression and archive format
1273 aurostd::CompressInit(a, ct, true);
1274
1275 // open the disk reader
1276 r = archive_read_disk_open(disk, file.c_str());
1277 CompressionErrorHandling(a, r, error_message);
1278
1279 // open the new archive
1280 fs::path outfile = file;
1281 outfile.replace_extension(static_cast<string>(file.extension()) + compression_suffix[ct]);
1282
1283 r = archive_write_open_filename(a, outfile.c_str());
1284 CompressionErrorHandling(a, r, error_message);
1285
1286 // load information of file from disk
1287 r = archive_read_next_header2(disk, entry);
1288 CompressionErrorHandling(a, r, error_message);
1289 r = archive_read_disk_descend(disk);
1290 CompressionErrorHandling(a, r, error_message);
1291
1292 // save file information to archive
1293 r = archive_write_header(a, entry);
1294 CompressionErrorHandling(a, r, error_message);
1295
1296 // open the input file and write it in chunks to new archive
1297 std::ifstream is(archive_entry_sourcepath(entry), std::ifstream::binary);
1298 while (is) {
1299 is.read(buff, sizeof(buff));
1300 archive_write_data(a, buff, is.gcount());
1301 }
1302 is.close();
1303
1304 // free objects created in this function
1305 if (!keep) {
1306 aurostd::RemoveFile(file);
1307 }
1308 archive_entry_free(entry);
1309 r = archive_read_free(disk);
1310 CompressionErrorHandling(a, r, error_message);
1311 r = archive_write_free(a);
1312 CompressionErrorHandling(a, r, error_message);
1313 }
1314
1324 fs::path CompressFiles(const vector<string>& files_raw, const fs::path& relative_to_path, const string& archive_name, const compression_type ct, const bool keep) {
1325 thread_local char buff[16384];
1326 archive* a;
1327 archive* disk;
1328 archive_entry* entry;
1329 int r = ARCHIVE_OK;
1330 const std::string error_message = "compression of multiple files";
1331 vector<string> files;
1332 files.reserve(files_raw.size());
1333 for (const auto& f : files_raw) {
1334 files.push_back(aurostd::CleanFileName(f));
1335 }
1336
1337 // initialized the new archive and the disk reader
1338 a = archive_write_new();
1339
1340 // select compression and archive format
1341 aurostd::CompressInit(a, ct, false);
1342
1343 // open the new archive
1344 string tar_suffix = ".tar";
1345 if (ct == compression_type::ZIP) {
1346 tar_suffix = "";
1347 }
1348 fs::path outfile = archive_name + tar_suffix + compression_suffix[ct];
1349 try {
1350 fs::create_directories(fs::absolute(outfile).parent_path());
1351 } catch (fs::filesystem_error& e) {
1352 const string error = e.what();
1353 const string message = "Parent folder could not be created: " + static_cast<string>(outfile.parent_path()) + "\n" + error;
1355 }
1356
1357 r = archive_write_open_filename(a, outfile.c_str());
1358 CompressionErrorHandling(a, r, error_message);
1359
1360 for (const auto& file : files) {
1361 // initialized the file entries
1362 entry = archive_entry_new();
1363
1364 // initialized the disk reader
1365 disk = archive_read_disk_new();
1366 r = archive_read_disk_set_standard_lookup(disk);
1367 CompressionErrorHandling(a, r, error_message);
1368
1369 // open the disk reader
1370 r = archive_read_disk_open(disk, file.c_str());
1371 CompressionErrorHandling(a, r, error_message);
1372
1373 // load information of file from disk
1374 r = archive_read_next_header2(disk, entry);
1375 CompressionErrorHandling(a, r, error_message);
1376 r = archive_read_disk_descend(disk);
1377 CompressionErrorHandling(a, r, error_message);
1378
1379 // HE20240907 change path information to be relative
1380 const std::string original_path_raw = archive_entry_pathname(entry);
1381 const fs::path original_path(original_path_raw);
1382 // using proximate to avoid empty paths in case `relative_to_path` and `original_path` are not compatible
1383 const fs::path new_path = fs::proximate(original_path, relative_to_path);
1384 const std::string new_path_raw = new_path.string();
1385 archive_entry_set_pathname(entry, new_path_raw.c_str());
1386
1387 // save file information to archive
1388 r = archive_write_header(a, entry);
1389 CompressionErrorHandling(a, r, error_message);
1390
1391 // open the input file and write it in chunks to new archive
1392 std::ifstream is(archive_entry_sourcepath(entry), std::ifstream::binary);
1393 while (is) {
1394 is.read(buff, sizeof(buff));
1395 archive_write_data(a, buff, is.gcount());
1396 }
1397 is.close();
1398
1399 // free read objects
1400 if (!keep) {
1401 aurostd::RemoveFile(file);
1402 }
1403 archive_entry_free(entry);
1404 r = archive_read_free(disk);
1405 CompressionErrorHandling(a, r, error_message);
1406 }
1407
1408 // free write objects
1409 r = archive_write_close(a);
1410 CompressionErrorHandling(a, r, error_message);
1411 r = archive_write_free(a);
1412 CompressionErrorHandling(a, r, error_message);
1413
1414 return outfile;
1415 }
1416
1423 bool MatchCompressed(const string& CompressedFileName, const string& FileNameOUT) {
1424 if (!aurostd::IsCompressed(CompressedFileName) && !aurostd::IsCompressed(FileNameOUT)) {
1425 return true;
1426 }
1427 if (aurostd::IsCompressed(FileNameOUT)) {
1428 if (aurostd::GetFileExtension(CompressedFileName) == aurostd::GetFileExtension(FileNameOUT)) {
1429 return true;
1430 }
1431 return false;
1432 }
1433 const compression_type ct = aurostd::GetCompressionType(CompressedFileName);
1434 if (ct == compression_type::None) {
1435 return false;
1436 }
1437 aurostd::CompressFile(FileNameOUT, ct);
1438 return true;
1439 }
1440
1447 bool compressfile2tempfile(const string& FileNameIN, string& FileNameOUT) {
1448 bool tempfile_created = false;
1449 return compressfile2tempfile(FileNameIN, FileNameOUT, tempfile_created);
1450 }
1451
1453 bool compressfile2tempfile(const string& FileNameRawIN, string& FileNameOUT, bool& tempfile_created) {
1454 string FileNameIN;
1455 tempfile_created = false;
1456 if (!(aurostd::FileExist(FileNameRawIN, FileNameIN) || aurostd::CompressFileExist(FileNameRawIN, FileNameIN))) {
1457 return false;
1458 }
1459 if (!aurostd::IsCompressed(FileNameIN)) {
1460 FileNameOUT = FileNameIN;
1461 return true;
1462 }
1463 tempfile_created = true;
1464 FileNameOUT = aurostd::TmpStrCreate();
1465 aurostd::DecompressFile(FileNameIN, FileNameOUT, true);
1466 return true;
1467 }
1468
1475 void compressfile2compressfile(const string& file, const compression_type ct, const bool keep) {
1476 const std::filesystem::path path(file);
1477 thread_local char buff[16384];
1478 archive* a;
1479 archive* a_new;
1480 archive_entry* entry;
1481 size_t len;
1482 int r = ARCHIVE_OK;
1483 const std::string error_message = "re-compressing of a single file";
1484
1485 // initialized the new archive, the disk and the file entries
1486 a = archive_read_new();
1487 if (path.extension() == ".zip") {
1488 r = archive_read_support_format_zip(a);
1489 CompressionErrorHandling(a, r, error_message);
1490 } else {
1491 r = archive_read_support_format_raw(a);
1492 CompressionErrorHandling(a, r, error_message);
1493 r = archive_read_support_format_empty(a);
1494 CompressionErrorHandling(a, r, error_message);
1495 r = archive_read_support_filter_all(a);
1496 CompressionErrorHandling(a, r, error_message);
1497 }
1498 a_new = archive_write_new();
1499
1500 // select compression and archive format
1501 aurostd::CompressInit(a_new, ct, true);
1502
1503 // open the archive
1504 r = archive_read_open_filename(a, file.c_str(), sizeof(buff));
1505 CompressionErrorHandling(a, r, error_message);
1506 r = archive_read_next_header(a, &entry);
1507 CompressionErrorHandling(a, r, error_message);
1508
1509 // open the new archive
1510 const string outfile = path.parent_path().string() + "/" + path.stem().string() + compression_suffix[ct];
1511 r = archive_write_open_filename(a_new, outfile.c_str());
1512 CompressionErrorHandling(a, r, error_message);
1513
1514 // save file information to archive
1515 r = archive_write_header(a_new, entry);
1516 CompressionErrorHandling(a, r, error_message);
1517
1518 // open the input archive and write it in chunks to new archive
1519 len = archive_read_data(a, buff, sizeof(buff));
1520 while (len > 0) { // read until archive is empty
1521 archive_write_data(a_new, buff, len);
1522 len = archive_read_data(a, buff, sizeof(buff));
1523 }
1524
1525 // free objects created in this function
1526 if (!keep) {
1527 aurostd::RemoveFile(file);
1528 }
1529 r = archive_write_free(a_new);
1530 CompressionErrorHandling(a, r, error_message);
1531 r = archive_write_free(a);
1532 CompressionErrorHandling(a, r, error_message);
1533 }
1534
1541 void compressfiles2compressfiles(const string& directory, const compression_type ct, const bool keep) {
1542 const string directory_clean = aurostd::CleanFileName(directory);
1543 if (directory_clean.empty()) {
1544 return;
1545 }
1546 const string& ext_new = compression_suffix[ct];
1547 string ext = ext_new;
1548 for (const std::filesystem::directory_entry& dir_entry : std::filesystem::directory_iterator(directory_clean)) {
1549 ext = dir_entry.path().extension().string();
1550 if ((ext == ".bz2" || ext == ".gz" || ext == ".xz" || ext == ".zip" || ext == ".zstd") && (ext != ext_new)) {
1551 aurostd::compressfile2compressfile(dir_entry.path().string(), ct, keep);
1552 }
1553 }
1554 }
1555
1556} // namespace aurostd
1557
1558#endif //_AUROSTD_XFILE_CPP_
_XHOST XHOST
static char buff[16384]
Definition apack.c:19
unsigned uint
Definition aurostd.h:39
#define __AFLOW_FILE__
Definition aurostd.h:44
#define __AFLOW_FUNC__
Definition aurostd.h:43
#define _LOCK_LINK_SUFFIX_
#define _RUNTIME_INIT_
#define _FILE_NOT_FOUND_
#define _INPUT_UNKNOWN_
#define _FILE_ERROR_
string basename(const string &file)
returns the basename of file
bool string2file(const string &StringOUTPUT, const std::string &FileNameRawOUTPUT, const compression_type ct, const string &mode)
write string into a file
void CompressFile(const string &file_raw, const compression_type ct, const bool keep)
compress file
bool vectorstring2file(const vtype< string > &vline, const string &FileNameOUT, const compression_type ct)
write a list of strings to file
bool DirectoryLS(const string &directory_raw, vector< string > &vfiles)
returns the content of a directory
bool RemoveDirectory(const string &directory)
remove a file
unsigned long long int FileSize(const string &FileName)
returns in bytes the size of a file
bool RemoveFiles(const string &directory)
removes all regular files inside a directory, not recursive
bool file2directory(const string &file, const string &destination)
move file to directory
void StringSubstInPlace(string &work_string, const string &old_string, const string &new_string)
substitute parts of a strings in place
string TmpFileCreate(const string &identifier, const string &tmpdir, const bool hidden)
create a string pointing to the location of a unique temp file
long int SecondsSinceFileModified(const string &FileNameRaw)
gets duration since file modification
long int GetTimestampModified(const string &FileNameRaw)
gets modification time
bool stringstream2compressfile(const stringstream &content, const string &file, const compression_type ct)
stringstream to compressed file
const std::vector< std::string > compression_suffix
void compressfiles2compressfiles(const string &directory, const compression_type ct, const bool keep)
convert compressed files in a directory to another compression
long double get_useconds()
string TmpStrCreate(const string &identifier_raw, const string &tmpdir_raw, const bool hidden, const bool directory)
create a string pointing to the location of a unique temp file or directory
deque< utype > vector2deque(const vector< utype > &vin)
void compressfile2compressfile(const string &file, const compression_type ct, const bool keep)
convert a compressed file to another compression
bool CompressFileExist(const string &FileName)
check if a file or its compressed variant exits
double ran0()
string CleanFileName(const string &fileIN)
cleans file names from obvious things
uint string2tokens(const string &str, vector< string > &tokens, const string &delimiters=" ", bool consecutive=false) __xprototype
size_t file2string(const string &FileNameIN, string &StringIN)
read the content of a file into a string
void InFileExistCheck(const string &routine, const string &FileNameRaw, const ifstream &file_to_check)
checks if a filestream is empty
uint string2dequestring(const string &stringIN, deque< string > &vstringout)
utype mode(const xvector< utype > &a)
bool string2compressfile(const string &content, const string &file_raw, const compression_type ct)
string to compressed file
utype max(const vector< utype > vec)
bool DirectoryMake(const string &directory_raw)
create a directory
void CompressionErrorHandling(archive *a, const int r, const std::string &message)
check compression calls
string utype2string(const utype &from, int precision=AUROSTD_DEFAULT_PRECISION, char FORMAT=DEFAULT_STREAM) __xprototype
size_t string2vectorstring(const string &stringIN, vector< string > &vstringout, bool consecutive=false, bool trim_edges=false)
size_t compressfile2vectorstring(const string &FileNameIN, vector< string > &vline, bool consecutive, bool trim_edges)
write the content of a compressed file into a vector of strings
bool FileExist(const string &FileName)
check if file exists
void compressfile2stringstream(const string &file_raw, stringstream &content)
write the content of a compressed file into a stringstream
bool FileEmpty(const string &FileNameRaw)
check if file is empty
string TmpDirectoryCreate(const string &identifier, const string &tmpdir, const bool hidden)
create a string pointing to the location of a unique temp directory
bool FileNotEmpty(const string &FileName)
check if file is not empty
string dirname(const string &file)
returns the dirname of file
size_t compressfile2string(const string &FileNameIN, string &content)
compressed file to string
bool SSH_DirectoryMake(const string &user, const string &machine, const string &directory_raw)
create a directory on a remote computer
bool CopyFile(const string &file_from, const string &file_to)
copy a file
string GetFileExtension(const string &FileName)
returns the file extension
bool CompressFileWithinList(const vector< string > &list, const string &input)
Determines whether a compressed file is within the list.
bool MatchCompressed(const string &CompressedFileName, const string &FileNameOUT)
compress a file based on the compression of another filed
bool IsCompressed(const string &FileNameIn)
check if a file is compressed
void DecompressFiles(const string &archive_file, const string &directory, const bool keep)
decompress files
bool IsDirectory(const string &path)
check if path is a directory
bool SubDirectoryLS(const string &directory_raw, vector< string > &vsubd)
returns all the subdirectories of a directory, including itself
bool LinkFile(const string &file_from, const string &file_to, const bool soft)
link a file
bool DirectoryWritable(const string &directory_raw)
create a temporary file to check if a directory is writable
bool file2file(const string &file, const string &destination)
move file to another file
string getPWD()
returns the current directory
void DecompressFile(const string &file_raw, const string &outfile_raw, const bool keep)
decompress file
bool stringstream2file(const stringstream &StringstreamOUTPUT, const string &FileNameOUTPUT, const compression_type ct, const string &mode)
write stringstream into a file
fs::path CompressFiles(const vector< string > &files_raw, const fs::path &relative_to_path, const string &archive_name, const compression_type ct, const bool keep)
compress files
bool DirectorySkipped(const string &directory)
check the existence of a SKIP file
bool DirectoryLocked(const string &directory, const string &LOCK)
check the existence of a LOCK file
void StringstreamClean(ostringstream &stream)
bool RemoveFile(const string &file)
remove a file
size_t file2vectorstring(const string &FileNameIN, vector< string > &vline, bool consecutive, bool trim_edges)
write the content of a file into a vector of strings
compression_type GetCompressionType(const fs::path &path)
bool compressfile2tempfile(const string &FileNameIN, string &FileNameOUT)
decompress a file to a temp file
void file2stringstream(const string &FileNameIN, stringstream &StringstreamIN)
write the content of a file into a stringstream 20241216 | Hagen Eckert - add transparent compression...
bool execute(ostringstream &command)
void CompressInit(archive *a, const compression_type ct, const bool single)
initialize compression