libadc-cxx 1.0.0
Structured logging for scientific computing
Loading...
Searching...
No Matches
mergefiles.ipp
Go to the documentation of this file.
1#include <sys/sendfile.h>
2#include <sys/stat.h>
3#include <fcntl.h>
4#include <unistd.h>
5#include <glob.h>
6#include <cerrno>
7#include <vector>
8#include <string>
9
10/*! \brief use sendfile to join all files matching pattern in new dest file.
11 * \param dest file to write merge result.
12 * \param pattern glob pattern to match possible input files.
13 * \param merged list of files added
14 * \return 0 and updated merged list or errno and merged content undefined.
15 */
16int glob_sendfile_join(const char *dest, const char *pattern, int perm, std::vector<std::string>& merged)
17{
18 glob_t glob_results;
19 merged.clear();
20 int err = glob(pattern, GLOB_NOSORT|GLOB_TILDE, NULL, &glob_results);
21 switch(err) {
22 case 0:
23 break;
24 case GLOB_NOSPACE:
25 globfree(&glob_results);
26 return ENOMEM;
27 case GLOB_ABORTED:
28 globfree(&glob_results);
29 return EPERM;
30 case GLOB_NOMATCH:
31 globfree(&glob_results);
32 return 0;
33 }
34
35 int dest_fd = open(dest, O_WRONLY | O_CREAT |O_CLOEXEC | O_TRUNC , perm);
36 if (dest_fd == -1) {
37 globfree(&glob_results);
38 return errno;
39 }
40
41 for (size_t i = 0; i < glob_results.gl_pathc; i++) {
42 int src_fd = open(glob_results.gl_pathv[i], O_RDONLY);
43 if (src_fd == -1) continue;
44
45 struct stat stat_buf;
46 if (fstat(src_fd, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode)) {
47 off_t offset = 0;
48 size_t remaining = stat_buf.st_size;
49
50 // Loop until the entire file is transferred
51 while (remaining > 0) {
52 ssize_t sent = sendfile(dest_fd, src_fd, &offset, remaining);
53
54 if (sent <= 0) {
55 // Handle errors or unexpected EOF
56 if (sent == -1 && errno == EINTR) continue; // Interrupted by signal, retry
57 break;
58 }
59 remaining -= sent;
60 }
61 }
62 close(src_fd);
63 merged.push_back(glob_results.gl_pathv[i]);
64 }
65
66 close(dest_fd);
67 globfree(&glob_results);
68 return 0;
69}
70
int glob_sendfile_join(const char *dest, const char *pattern, int perm, std::vector< std::string > &merged)
use sendfile to join all files matching pattern in new dest file.