ewmscp  ..
truncate_file.cpp
Go to the documentation of this file.
1 #include <chrono>
2 
3 #include <Options.h>
4 #include <scoped.h>
5 #include <throwcall.h>
6 
7 #include <fcntl.h>
8 #include <linux/fs.h>
9 #include <sys/ioctl.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #ifdef WithXattr
13 #include <xattr.h>
14 #endif
15 #ifdef WithXattrUgly
16 #include WithXattrUgly
17 #endif
18 #ifndef ENOATTR
19 #define ENOATTR ENODATA
20 #endif
21 #include <unistd.h>
22 #include <utime.h>
23 #ifdef withGpfs
24 #include <sys/vfs.h>
25 #include "gpfsCommon.h"
26 #endif
27 #include "escapism.h"
28 
33 int main(int argc, const char *argv[]) {
34  options::parser parser("truncate_file", "", {});
36  "files to be truncated");
37  #if defined(WithXattr) || defined(WithXattrUgly)
38  options::single<std::string> name('n', "name",
39  "name of xattr to set", "user.truncated");
40  options::single<std::string> sizeName('s', "size attr name",
41  "name of xattr for old size", "user.origsize");
42  options::single<std::string> ctimeName('c', "ctime attr name",
43  "name of xattr for old ctime", "user.origctime");
44  #endif
45  options::single<bool> setImmutable('i', "immutable",
46  "set files to immutable", false);
47  options::single<bool> readPolicyOutput('p',"policyList",
48  "read files from policy list");
49  options::single<bool> verbose('v',"verbose",
50  "print paths of traeded files");
51  auto escaperOption = escapism::newEscaperOption("policyRunEscapeSchema",
52  "schema used for escaping file names in policy run file","C");
53  parser.fParse(argc, argv);
54 
55  if (readPolicyOutput) {
56  if (files.size() != 1) {
57  std::cerr << "with --policyList exactly 1 arg is required\n";
58  return 1;
59  }
60  auto escaper = escapism::newEscaper(*escaperOption);
61  auto listName=files.front();
62  files.clear();
63  std::ifstream list(listName);
64  std::string line;
65  while (std::getline(list, line)) {
66  auto separatorStart = line.find(" -- ");
67  if (separatorStart == std::string::npos) {
68  continue;
69  }
70  auto pathStart = separatorStart + 4; // length of " -- "
71  std::string file;
72  escaper->deEscape(line.substr(pathStart), file);
73  files.push_back(file);
74  }
75  }
76 
77  for (auto file : files) {
78  struct stat initialStat;
79  throwcall::good0(stat(file.c_str(), &initialStat), "can't stat ", file);
80  if (! S_ISREG(initialStat.st_mode)) {
81  if (verbose) {
82  std::cout << "ignoring non-file " << file << "\n";
83  }
84  continue;
85  }
86  if (verbose) {
87  std::cout << "truncating " << file << "\n";
88  }
89  #if defined(WithXattr) || defined(WithXattrUgly)
90  if (!name.empty()) {
91  auto value = std::to_string(std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::system_clock::now().time_since_epoch()).count());
92  throwcall::good0(setxattr(file.c_str(), name.c_str(), value.data(), value.size(), 0),
93  "can't set xattrs on ", file);
94  }
95  if (!sizeName.empty()) {
96  auto value = std::to_string(initialStat.st_size);
97  throwcall::good0(setxattr(file.c_str(), sizeName.c_str(), value.data(), value.size(), 0),
98  "can't set xattrs on ", file);
99  }
100  if (!ctimeName.empty()) {
101  auto value = std::to_string(std::chrono::duration_cast<std::chrono::duration<double>>(
102  std::chrono::seconds(initialStat.st_ctim.tv_sec) +
103  std::chrono::nanoseconds(initialStat.st_ctim.tv_nsec)
104  ).count());
105  throwcall::good0(setxattr(file.c_str(), ctimeName.c_str(), value.data(), value.size(), 0),
106  "can't set xattrs on ", file);
107  }
108  #endif
109 
110  throwcall::good0(truncate(file.c_str(), 0), "can't truncate ", file);
111  struct timespec times[2];
112  times[0].tv_sec = initialStat.st_atim.tv_sec;
113  times[0].tv_nsec = initialStat.st_atim.tv_nsec;
114  times[1].tv_sec = initialStat.st_mtim.tv_sec;
115  times[1].tv_nsec = initialStat.st_mtim.tv_nsec;
116 
117  throwcall::good0(utimensat(AT_FDCWD, file.c_str(), times, 0), "can't reset time stamps of ", file);
118 
119  if (setImmutable) { // does not work on gpfs. GRRR
120  scoped::Fd fd(file, throwcall::badval(open(file.c_str(), O_RDONLY),
121  -1, "can't open ", file));
122  #ifdef withGpfs
123  struct statfs statbuf;
124  throwcall::good0(fstatfs(fd, &statbuf), "can't statfs for file", file);
125  if (statbuf.f_type == GPFS_SUPER_MAGIC) {
126  gpfs_fcntl_handler fcntl;
127  auto& hint = fcntl.buffer.add<gpfsSetImmutable_t>(GPFS_FCNTL_SET_IMMUTABLE);
128  hint.setImmutable = 1;
129  hint.setIndefiniteRetention = 1;
130  fcntl.call(fd, file);
131  } else
132  #endif
133  {
134  int flags;
135  throwcall::good0(ioctl(fd, FS_IOC_GETFLAGS, &flags), "can't read flags on ", file);
136  flags |= FS_IMMUTABLE_FL;
137  throwcall::good0(ioctl(fd, FS_IOC_SETFLAGS, &flags), "can't set flags on ", file);
138  }
139  }
140  }
141 
142  return 0;
143 }
options::parser
class that contains the parser, i.e. does that option handling
Definition: Options.h:363
verbose
options::single< bool > verbose
options::single< std::string >
options::single< bool >
class specialisation for options of type bool
Definition: Options.h:595
throwcall::badval
T badval(T call, t badvalue, const Args &... args)
template function to wrap system calls that return a special bad value on failure
Definition: throwcall.h:54
main
int main(int argc, const char *argv[])
Definition: truncate_file.cpp:33
scoped.h
Options.h
gpfs_fcntl_handler
class for handling gpfs_fcnt calls with their very special parameter handling
Definition: gpfsFcntlHandler.h:6
escapism.h
throwcall.h
escapism::newEscaperOption
static options::single< std::string > * newEscaperOption(const std::string &name, const std::string &description, const std::string &defaultValue="Url")
Definition: escapism.cpp:36
gpfsCommon.h
gpfs_fcntl_handler::buffer
union gpfs_fcntl_handler::@2 buffer
escapism::newEscaper
static const escapism * newEscaper(const std::string &name)
Definition: escapism.cpp:25
options::positional
Definition: Options.h:876
gpfs_fcntl_handler::call
void call(int fd, const std::string &path)
Definition: gpfsFcntlHandler.cpp:15
throwcall::good0
void good0(T call, const Args &... args)
template function to wrap system calls that return 0 on success
Definition: throwcall.h:40
scoped::Fd
Definition: scoped.h:48