irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

filesystem.cpp
Go to the documentation of this file.
2 
3 #include "filesystem/path.hpp"
5 
6 // clang-format off
7 #ifdef IRODS_FILESYSTEM_ENABLE_SERVER_SIDE_API
8  #define RODS_SERVER
9 
10  #include "rods.h"
11  #include "apiHeaderAll.h"
12  #include "rsSpecificQuery.hpp"
13  #include "rsObjStat.hpp"
14  #include "rsDataObjCopy.hpp"
15  #include "rsDataObjRename.hpp"
16  #include "rsDataObjUnlink.hpp"
17  #include "rsDataObjChksum.hpp"
18  #include "rsOpenCollection.hpp"
19  #include "rsCloseCollection.hpp"
20  #include "rsReadCollection.hpp"
21  #include "rsModAccessControl.hpp"
22  #include "rsCollCreate.hpp"
23  #include "rsModColl.hpp"
24  #include "rsRmColl.hpp"
25  #include "rsModAVUMetadata.hpp"
26  #include "rsModDataObjMeta.hpp"
27 #else
28  #include "rodsClient.h"
29  #include "specificQuery.h"
30  #include "objStat.h"
31  #include "dataObjCopy.h"
32  #include "dataObjRename.h"
33  #include "dataObjUnlink.h"
34  #include "dataObjChksum.h"
35  #include "openCollection.h"
36  #include "closeCollection.h"
37  #include "readCollection.h"
38  #include "modAccessControl.h"
39  #include "collCreate.h"
40  #include "modColl.h"
41  #include "rmColl.h"
42  #include "modAVUMetadata.h"
43  #include "data_object_modify_info.h"
44 #endif // IRODS_FILESYSTEM_ENABLE_SERVER_SIDE_API
45 // clang-format on
46 
47 #include "rcMisc.h"
48 #include "rodsErrorTable.h"
49 #include "irods_log.hpp"
50 #include "irods_error.hpp"
51 #include "irods_exception.hpp"
52 #include "irods_query.hpp"
53 #include "irods_at_scope_exit.hpp"
54 #include "query_builder.hpp"
55 
56 #include <boost/optional.hpp>
57 
58 #include "fmt/format.h"
59 
60 #include <cctype>
61 #include <cstring>
62 #include <string>
63 #include <iterator>
64 #include <exception>
65 #include <sstream>
66 #include <iomanip>
67 #include <algorithm>
68 
70 {
71  namespace
72  {
74 
75 #ifdef IRODS_FILESYSTEM_ENABLE_SERVER_SIDE_API
76  int rsDataObjCopy(rsComm_t* _comm, dataObjCopyInp_t* _dataObjCopyInp)
77  {
78  //_dataObjCopyInp->srcDataObjInp.oprType = COPY_SRC;
79  //_dataObjCopyInp->destDataObjInp.oprType = COPY_DEST;
80 
81  transferStat_t* ts_ptr{};
82 
83  const auto ec = rsDataObjCopy(_comm, _dataObjCopyInp, &ts_ptr);
84 
85  if (ts_ptr) {
86  std::free(ts_ptr);
87  }
88 
89  return ec;
90  }
91 
92  const auto rsRmColl = [](rsComm_t* _comm, collInp_t* _rmCollInp, int) -> int
93  {
94  collOprStat_t* stat{};
95  return ::rsRmColl(_comm, _rmCollInp, &stat);
96  };
97 #endif // IRODS_FILESYSTEM_ENABLE_SERVER_SIDE_API
98 
99  struct stat
100  {
101  int error;
102  long long size;
103  int type;
104  int mode;
105  long long id;
106  std::string owner_name;
107  std::string owner_zone;
108  long long ctime;
109  long long mtime;
110  std::vector<entity_permission> prms;
111  };
112 
113  auto to_permission_enum(const std::string& _perm) -> perms
114  {
115  // clang-format off
116  if (_perm == "read object") { return perms::read; }
117  else if (_perm == "modify object") { return perms::write; }
118  else if (_perm == "own") { return perms::own; }
119  else if (_perm == "inherit") { return perms::inherit; }
120  else if (_perm == "noinherit") { return perms::noinherit; }
121  // clang-format on
122 
123  return perms::null;
124  }
125 
126  auto get_zone_name(const path& _p) -> boost::optional<std::string>
127  {
128  using difference_type = path::iterator::difference_type;
129 
130  constexpr difference_type hops = 2;
131  auto iter = std::begin(_p);
132 
133  if (std::distance(iter, std::end(_p)) >= hops) {
134  return (++iter)->string();
135  }
136 
137  return boost::none;
138  }
139 
140  auto set_permissions(rxComm& _comm, const path& _p, stat& _s) -> void
141  {
142  if (DATA_OBJ_T == _s.type) {
143  std::string sql = "select DATA_USER_NAME, DATA_ZONE_NAME, DATA_ACCESS_NAME, USER_TYPE "
144  "where COLL_NAME = '";
145  sql += _p.parent_path();
146  sql += "' and DATA_NAME = '";
147  sql += _p.object_name();
148  sql += "' and DATA_TOKEN_NAMESPACE = 'access_type'";
149 
151 
152  const auto zone = get_zone_name(_p);
153 
154  if (zone) {
155  qb.zone_hint(*zone);
156  }
157 
158  for (const auto& row : qb.build(_comm, sql)) {
159  _s.prms.push_back({row[0], row[1], to_permission_enum(row[2]), row[3]});
160  }
161  }
162  else if (COLL_OBJ_T == _s.type) {
164 
165  const auto zone = get_zone_name(_p);
166 
167  if (zone) {
168  qb.zone_hint(*zone);
169  }
170 
171  try {
172  std::vector<std::string> args{_p.string()};
173 
175  .bind_arguments(args);
176 
177  for (const auto& row : qb.build(_comm, "ShowCollAcls")) {
178  _s.prms.push_back({row[0], row[1], to_permission_enum(row[2]), row[3]});
179  }
180  }
181  catch (...) {
182  // Fallback to GenQuery if the specific query fails (does not exist).
183  //
184  // In the case where the specific query, "ShowCollAcls", does not exist,
185  // this implementation is required to fallback to GenQuery. The following
186  // code does not require any information from the exception object, therefore
187  // it is ignored.
188 
189  qb.type(irods::experimental::query_type::general);
190 
191  std::string sql = "select COLL_USER_NAME, COLL_ZONE_NAME, COLL_ACCESS_NAME, USER_TYPE "
192  "where COLL_TOKEN_NAMESPACE = 'access_type' and COLL_NAME = '";
193  sql += _p.c_str();
194  sql += "'";
195 
196  for (const auto& row : qb.build(_comm, sql)) {
197  _s.prms.push_back({row[0], row[1], to_permission_enum(row[2]), row[3]});
198  }
199  }
200  }
201  }
202 
203  auto stat(rxComm& _comm, const path& _p) -> stat
204  {
205  dataObjInp_t input{};
206  std::strncpy(input.objPath, _p.c_str(), std::strlen(_p.c_str()));
207 
209  struct stat s{};
210 
211  s.error = rxObjStat(&_comm, &input, &output);
212 
213  if (s.error >= 0) {
214  irods::at_scope_exit<std::function<void()>> at_scope_exit{[output] {
216  }};
217 
218  try {
219  s.id = std::stoll(output->dataId);
220  s.ctime = std::stoll(output->createTime);
221  s.mtime = std::stoll(output->modifyTime);
222  }
223  catch (...) {
224  throw filesystem_error{"stat error: cannot convert string to integer", _p, make_error_code(SYS_INTERNAL_ERR)};
225  }
226 
227  s.size = output->objSize;
228  s.type = output->objType;
229  s.mode = static_cast<int>(output->dataMode);
230  s.owner_name = output->ownerName;
231  s.owner_zone = output->ownerZone;
232 
233  set_permissions(_comm, _p, s);
234  }
235  else if (USER_FILE_DOES_NOT_EXIST == s.error) {
236  s.error = 0;
237  s.type = UNKNOWN_OBJ_T;
238  }
239 
240  return s;
241  }
242 
243  auto is_collection_empty(rxComm& _comm, const path& _p) -> bool
244  {
245  return collection_iterator{} == collection_iterator{_comm, _p};
246  }
247 
248  struct remove_impl_options
249  {
250  bool no_trash = false;
251  bool recursive = false;
252  };
253 
254  auto remove_impl(rxComm& _comm, const path& _p, remove_impl_options _opts) -> bool
255  {
257 
258  const auto s = status(_comm, _p);
259 
260  if (!exists(s)) {
261  return false;
262  }
263 
264  if (is_data_object(s)) {
265  dataObjInp_t input{};
266 
267  std::strncpy(input.objPath, _p.c_str(), std::strlen(_p.c_str()));
268 
269  if (_opts.no_trash) {
270  addKeyVal(&input.condInput, FORCE_FLAG_KW, "");
271  }
272 
273  return rxDataObjUnlink(&_comm, &input) == 0;
274  }
275 
276  if (is_collection(s)) {
277  if (!_opts.recursive && !is_collection_empty(_comm, _p)) {
278  throw filesystem_error{"cannot remove non-empty collection", _p, make_error_code(SYS_COLLECTION_NOT_EMPTY)};
279  }
280 
281  collInp_t input{};
282 
283  std::strncpy(input.collName, _p.c_str(), std::strlen(_p.c_str()));
284 
285  if (_opts.no_trash) {
286  addKeyVal(&input.condInput, FORCE_FLAG_KW, "");
287  }
288 
289  if (_opts.recursive) {
290  addKeyVal(&input.condInput, RECURSIVE_OPR__KW, "");
291  }
292 
293  constexpr int verbose = 0;
294  return rxRmColl(&_comm, &input, verbose) >= 0;
295  }
296 
297  throw filesystem_error{"cannot remove: unknown object type", _p, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
298  }
299 
300  auto has_prefix(const path& _p, const path& _prefix) -> bool
301  {
302  if (_p == _prefix) {
303  return false;
304  }
305 
306  auto p_iter = std::begin(_prefix);
307  auto p_last = std::end(_prefix);
308  auto c_iter = std::begin(_p);
309  auto c_last = std::end(_p);
310 
311  for (; p_iter != p_last && c_iter != c_last && *p_iter == *c_iter; ++p_iter, ++c_iter);
312 
313  return (p_iter == p_last);
314  }
315 
316  auto do_metadata_op(rxComm& _comm, const path& _p, const metadata& _metadata, std::string_view op) -> void
317  {
318  if (_p.empty()) {
319  throw filesystem_error{"empty path", make_error_code(SYS_INVALID_INPUT_PARAM)};
320  }
321 
323 
324  modAVUMetadataInp_t input{};
325 
326  char* command = const_cast<char*>(op.data());
327  input.arg0 = command;
328 
329  char type[3]{};
330 
331  if (const auto s = status(_comm, _p); is_data_object(s)) {
332  std::strncpy(type, "-d", std::strlen("-d"));
333  }
334  else if (is_collection(s)) {
335  std::strncpy(type, "-C", std::strlen("-C"));
336  }
337  else {
338  std::string_view op_full_name = (op == "rm") ? "remove" : op;
339  throw filesystem_error{fmt::format("cannot {} metadata: unknown object type", op_full_name), _p,
341  }
342 
343  input.arg1 = type;
344 
345  char path_buf[MAX_NAME_LEN]{};
346  std::strncpy(path_buf, _p.c_str(), std::strlen(_p.c_str()));
347  input.arg2 = path_buf;
348 
349  char attr_buf[MAX_NAME_LEN]{};
350  std::strncpy(attr_buf, _metadata.attribute.c_str(), _metadata.attribute.size());
351  input.arg3 = attr_buf;
352 
353  char value_buf[MAX_NAME_LEN]{};
354  std::strncpy(value_buf, _metadata.value.c_str(), _metadata.value.size());
355  input.arg4 = value_buf;
356 
357  char units_buf[MAX_NAME_LEN]{};
358  std::strncpy(units_buf, _metadata.units.c_str(), _metadata.units.size());
359  input.arg5 = units_buf;
360 
361  if (const auto ec = rxModAVUMetadata(&_comm, &input); ec != 0) {
362  std::string_view op_full_name = (op == "rm") ? "remove" : op;
363  throw filesystem_error{fmt::format("cannot {} metadata", op_full_name), _p, make_error_code(ec)};
364  }
365  }
366  } // anonymous namespace
367 
368  // Operational functions
369 
370  auto copy(rxComm& _comm, const path& _from, const path& _to, copy_options _options) -> void
371  {
372  const auto from_status = status(_comm, _from);
373 
374  if (!exists(from_status)) {
375  throw filesystem_error{"path does not exist", _from, make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
376  }
377 
378  const auto to_status = status(_comm, _to);
379 
380  if (exists(to_status) && equivalent(_comm, _from, _to)) {
381  throw filesystem_error{"paths cannot point to the same object", _from, _to, make_error_code(SAME_SRC_DEST_PATHS_ERR)};
382  }
383 
384  if (is_other(from_status)) {
385  throw filesystem_error{"cannot copy: unknown object type", _from, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
386  }
387 
388  if (is_other(to_status)) {
389  throw filesystem_error{"cannot copy: unknown object type", _to, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
390  }
391 
392  if (is_collection(from_status) && is_data_object(to_status)) {
393  throw filesystem_error{"cannot copy a collection into a data object", _from, _to, make_error_code(SYS_INVALID_INPUT_PARAM)};
394  }
395 
396  if (is_data_object(from_status)) {
397  if (copy_options::collections_only == (copy_options::collections_only & _options)) {
398  return;
399  }
400 
401  if (is_collection(to_status)) {
402  copy_data_object(_comm, _from, _to / _from.object_name(), _options);
403  return;
404  }
405 
406  copy_data_object(_comm, _from, _to, _options);
407  }
408  else if (is_collection(from_status)) {
409  if (copy_options::recursive == (copy_options::recursive & _options) ||
410  copy_options::none == _options)
411  {
412  if (!exists(to_status)) {
413  if (!create_collection(_comm, _to, _from)) {
414  throw filesystem_error{"cannot create collection", _to, make_error_code(FILE_CREATE_ERROR)};
415  }
416  }
417 
418  for (const auto& e : collection_iterator{_comm, _from}) {
419  copy(_comm, e.path(), _to / e.path().object_name(), _options | copy_options::in_recursive_copy);
420  }
421  }
422  }
423  }
424 
425  auto copy_data_object(rxComm& _comm, const path& _from, const path& _to, copy_options _options) -> bool
426  {
429 
430  if (!is_data_object(_comm, _from)) {
431  throw filesystem_error{"path does not point to a data object", _from, make_error_code(INVALID_OBJECT_TYPE)};
432  }
433 
434  dataObjCopyInp_t input{};
435 
436  const auto s = status(_comm, _to);
437 
438  if (exists(s)) {
439  if (equivalent(_comm, _from, _to)) {
440  throw filesystem_error{"paths cannot point to the same object", _from, _to, make_error_code(SAME_SRC_DEST_PATHS_ERR)};
441  }
442 
443  if (!is_data_object(s)) {
444  throw filesystem_error{"path does not point to a data object", _to, make_error_code(INVALID_OBJECT_TYPE)};
445  }
446 
447  if (copy_options::none == _options) {
448  throw filesystem_error{"copy options not set", make_error_code(SYS_INVALID_INPUT_PARAM)};
449  }
450 
451  if (copy_options::skip_existing == _options) {
452  return false;
453  }
454 
455  if (copy_options::overwrite_existing == _options) {
456  addKeyVal(&input.destDataObjInp.condInput, FORCE_FLAG_KW, "");
457  }
458 
459  if (copy_options::update_existing == _options) {
460  if (last_write_time(_comm, _from) <= last_write_time(_comm, _to)) {
461  return false;
462  }
463  }
464  }
465 
466  std::strncpy(input.srcDataObjInp.objPath, _from.c_str(), std::strlen(_from.c_str()));
467  std::strncpy(input.destDataObjInp.objPath, _to.c_str(), std::strlen(_to.c_str()));
468  addKeyVal(&input.destDataObjInp.condInput, DEST_RESC_NAME_KW, "");
469 
470  const auto ec = rxDataObjCopy(&_comm, &input);
471 
472  if (ec < 0) {
473  throw filesystem_error{"cannot copy data object", _from, _to, make_error_code(ec)};
474  }
475 
476  return true;
477  }
478 
479  auto create_collection(rxComm& _comm, const path& _p) -> bool // Implies perms::all
480  {
482 
483  if (!exists(_comm, _p.parent_path())) {
484  throw filesystem_error{"path does not exist", _p.parent_path(), make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
485  }
486 
487  if (exists(_comm, _p)) {
488  return false;
489  }
490 
491  collInp_t input{};
492  std::strncpy(input.collName, _p.c_str(), std::strlen(_p.c_str()));
493 
494  const auto ec = rxCollCreate(&_comm, &input);
495 
496  if (ec != 0) {
497  throw filesystem_error{"cannot create collection", _p, make_error_code(ec)};
498  }
499 
500  return true;
501  }
502 
503  auto create_collection(rxComm& _comm, const path& _p, const path& _existing_p) -> bool
504  {
505  if (_p.empty() || _existing_p.empty()) {
507  }
508 
511 
512  const auto s = status(_comm, _existing_p);
513 
514  if (!is_collection(s)) {
515  throw filesystem_error{"existing path is not a collection", _existing_p, make_error_code(INVALID_OBJECT_TYPE)};
516  }
517 
518  create_collection(_comm, _p);
519 
520  for (auto&& p : s.permissions()) {
521  permissions(_comm, _p, p.name, p.prms);
522  }
523 
524  return true;
525  }
526 
527  auto create_collections(rxComm& _comm, const path& _p) -> bool
528  {
530 
531  if (exists(_comm, _p)) {
532  return false;
533  }
534 
535  collInp_t input{};
536  std::strncpy(input.collName, _p.c_str(), std::strlen(_p.c_str()));
537  addKeyVal(&input.condInput, RECURSIVE_OPR__KW, "");
538 
539  return rxCollCreate(&_comm, &input) == 0;
540  }
541 
542  auto exists(object_status _s) noexcept -> bool
543  {
544  return status_known(_s) && _s.type() != object_type::not_found;
545  }
546 
547  auto exists(rxComm& _comm, const path& _p) -> bool
548  {
549  return exists(status(_comm, _p));
550  }
551 
552  auto equivalent(rxComm& _comm, const path& _p1, const path& _p2) -> bool
553  {
554  if (_p1.empty() || _p2.empty()) {
556  }
557 
558  const auto p1_info = stat(_comm, _p1);
559 
560  if (p1_info.error < 0) {
561  throw filesystem_error{"cannot stat path", _p1, make_error_code(p1_info.error)};
562  }
563 
564  if (p1_info.type == UNKNOWN_OBJ_T) {
565  throw filesystem_error{"path does not exist", _p1, make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
566  }
567 
568  const auto p2_info = stat(_comm, _p2);
569 
570  if (p2_info.error < 0) {
571  throw filesystem_error{"cannot stat path", _p2, make_error_code(p2_info.error)};
572  }
573 
574  if (p2_info.type == UNKNOWN_OBJ_T) {
575  throw filesystem_error{"path does not exist", _p2, make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
576  }
577 
578  return p1_info.id == p2_info.id;
579  }
580 
581  auto data_object_size(rxComm& _comm, const path& _p) -> std::uintmax_t
582  {
583  const auto s = stat(_comm, _p);
584 
585  if (s.error < 0) {
586  throw filesystem_error{"cannot get size", _p, make_error_code(s.error)};
587  }
588 
589  if (s.type == UNKNOWN_OBJ_T) {
590  throw filesystem_error{"path does not exist", _p, make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
591  }
592 
593  if (s.type == DATA_OBJ_T) {
594  return static_cast<std::uintmax_t>(s.size);
595  }
596 
597  return 0;
598  }
599 
600  auto is_collection(object_status _s) noexcept -> bool
601  {
602  return _s.type() == object_type::collection;
603  }
604 
605  auto is_collection(rxComm& _comm, const path& _p) -> bool
606  {
607  return is_collection(status(_comm, _p));
608  }
609 
610  auto is_empty(rxComm& _comm, const path& _p) -> bool
611  {
612  const auto s = status(_comm, _p);
613 
614  if (is_data_object(s)) {
615  return data_object_size(_comm, _p) == 0;
616  }
617 
618  if (is_collection(s)) {
619  return is_collection_empty(_comm, _p);
620  }
621 
622  throw filesystem_error{"cannot check emptiness: unknown object type", _p, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
623  }
624 
625  auto is_other(object_status _s) noexcept -> bool
626  {
627  return _s.type() == object_type::unknown;
628  }
629 
630  auto is_other(rxComm& _comm, const path& _p) -> bool
631  {
632  return is_other(status(_comm, _p));
633  }
634 
635  auto is_data_object(object_status _s) noexcept -> bool
636  {
637  return _s.type() == object_type::data_object;
638  }
639 
640  auto is_data_object(rxComm& _comm, const path& _p) -> bool
641  {
642  return is_data_object(status(_comm, _p));
643  }
644 
645  auto last_write_time(rxComm& _comm, const path& _p) -> object_time_type
646  {
647  const auto s = stat(_comm, _p);
648 
649  if (s.error < 0 || s.type == UNKNOWN_OBJ_T) {
650  throw filesystem_error{"cannot get mtime", _p, make_error_code(s.error)};
651  }
652 
653  return object_time_type{std::chrono::seconds{s.mtime}};
654  }
655 
656  auto last_write_time(rxComm& _comm, const path& _p, object_time_type _new_time) -> void
657  {
659 
660  const auto seconds = _new_time.time_since_epoch();
661  std::stringstream new_time;
662  new_time << std::setfill('0') << std::setw(11) << std::to_string(seconds.count());
663 
664  const auto object_status = status(_comm, _p);
665 
667  collInp_t input{};
668  std::strncpy(input.collName, _p.c_str(), std::strlen(_p.c_str()));
669  addKeyVal(&input.condInput, COLLECTION_MTIME_KW, new_time.str().c_str());
670 
671  const auto ec = rxModColl(&_comm, &input);
672 
673  if (ec != 0) {
674  throw filesystem_error{"cannot set mtime", _p, make_error_code(ec)};
675  }
676  }
677  else if (is_data_object(object_status)) {
678  dataObjInfo_t info{};
679  std::strncpy(info.objPath, _p.c_str(), std::strlen(_p.c_str()));
680 
681  keyValPair_t reg_params{};
682  addKeyVal(&reg_params, DATA_MODIFY_KW, new_time.str().c_str());
683 
684  modDataObjMeta_t input{};
685  input.dataObjInfo = &info;
686  input.regParam = &reg_params;
687 
688  const auto ec = rxModDataObjMeta(&_comm, &input);
689 
690  if (ec != 0) {
691  throw filesystem_error{"cannot set mtime", _p, make_error_code(ec)};
692  }
693  }
694  else {
695  throw filesystem_error{"cannot set mtime of unknown object type", _p, make_error_code(SYS_INTERNAL_ERR)};
696  }
697  }
698 
699  auto remove(rxComm& _comm, const path& _p, remove_options _opts) -> bool
700  {
701  const auto no_trash = (remove_options::no_trash == _opts);
702  constexpr auto recursive = false;
703  return remove_impl(_comm, _p, {no_trash, recursive});
704  }
705 
706  auto remove_all(rxComm& _comm, const path& _p, remove_options _opts) -> std::uintmax_t
707  {
708  std::string data_obj_sql = "select count(DATA_ID) where COLL_NAME like '";
709  data_obj_sql += _p;
710  data_obj_sql += "%'";
711 
712  std::string colls_sql = "select count(COLL_ID) where COLL_NAME like '";
713  colls_sql += _p;
714  colls_sql += "%'";
715 
717 
718  const auto zone = get_zone_name(_p);
719 
720  if (zone) {
721  qb.zone_hint(*zone);
722  }
723 
724  std::uintmax_t count = 0;
725 
726  for (const auto& sql : {data_obj_sql, colls_sql}) {
727  for (const auto& row : qb.build(_comm, sql)) {
728  count += std::stoull(row[0]);
729  }
730  }
731 
732  if (0 == count) {
733  return 0;
734  }
735 
736  const auto no_trash = (remove_options::no_trash == _opts);
737  constexpr auto recursive = true;
738 
739  if (remove_impl(_comm, _p, {no_trash, recursive})) {
740  return count;
741  }
742 
743  return 0;
744  }
745 
746  auto permissions(rxComm& _comm, const path& _p, const std::string& _user_or_group, perms _prms) -> void
747  {
749 
750  char username[NAME_LEN]{};
751  char zone[NAME_LEN]{};
752 
753  auto ec = parseUserName(_user_or_group.c_str(), username, zone);
754 
755  if (ec != 0) {
756  throw filesystem_error{"cannot parse user/group name", _p, make_error_code(ec)};
757  }
758 
759  modAccessControlInp_t input{};
760 
761  input.userName = username;
762  input.zone = zone;
763 
764  char path[MAX_NAME_LEN]{};
765  std::strncpy(path, _p.c_str(), std::strlen(_p.c_str()));
766  input.path = path;
767 
768  char access[10]{};
769 
770  switch (_prms) {
771  case perms::null:
772  std::strncpy(access, "null", 4);
773  break;
774 
775  case perms::read:
776  std::strncpy(access, "read", 4);
777  break;
778 
779  case perms::write:
780  std::strncpy(access, "write", 5);
781  break;
782 
783  case perms::own:
784  std::strncpy(access, "own", 3);
785  break;
786 
787  case perms::inherit:
788  std::strncpy(access, "inherit", 7);
789  break;
790 
791  case perms::noinherit:
792  std::strncpy(access, "noinherit", 9);
793  break;
794  }
795 
796  input.accessLevel = access;
797 
798  ec = rxModAccessControl(&_comm, &input);
799 
800  if (ec != 0) {
801  throw filesystem_error{"cannot set permissions", _p, make_error_code(ec)};
802  }
803  }
804 
805  auto rename(rxComm& _comm, const path& _old_p, const path& _new_p) -> void
806  {
807  if (_old_p.empty() || _new_p.empty()) {
809  }
810 
813 
814  const auto old_p_stat = status(_comm, _old_p.lexically_normal());
815  const auto new_p_stat = status(_comm, _new_p.lexically_normal());
816 
817  // Case 1: "_new_p" is the same object as "_old_p".
818  if (exists(old_p_stat) && exists(new_p_stat) && equivalent(_comm, _old_p, _new_p)) {
819  return;
820  }
821 
822  if (has_prefix(_new_p, _old_p)) {
823  throw filesystem_error{"old path cannot be an ancestor of the new path", _old_p, _new_p, make_error_code(SYS_INVALID_INPUT_PARAM)};
824  }
825 
826  {
827  const char* dot = ".";
828  const char* dot_dot = "..";
829 
830  if (_new_p.object_name() == dot || _new_p.object_name() == dot_dot) {
831  throw filesystem_error{R"_(path cannot end with "." or "..")_", _new_p, make_error_code(SYS_INVALID_INPUT_PARAM)};
832  }
833  }
834 
835  if (is_data_object(old_p_stat)) {
836  // Case 2: "_new_p" is an existing non-collection object.
837  if (exists(new_p_stat)) {
838  if (!is_data_object(new_p_stat)) {
839  throw filesystem_error{"path is not a data object", _new_p, make_error_code(INVALID_OBJECT_TYPE)};
840  }
841  }
842  // Case 3: "_new_p" is a non-existing data object in an existing collection.
843  else if (!exists(_comm, _new_p.parent_path())) {
844  throw filesystem_error{"path does not exist", _new_p.parent_path(), make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
845  }
846  }
847  else if (is_collection(old_p_stat)) {
848  // Case 2: "_new_p" is an existing collection.
849  if (exists(new_p_stat)) {
850  if (!is_collection(new_p_stat)) {
851  throw filesystem_error{"path is not a collection", _new_p, make_error_code(INVALID_OBJECT_TYPE)};
852  }
853  }
854  // Case 3: "_new_p" is a non-existing collection w/ the following requirements:
855  // 1. Does not end with a collection separator.
856  // 2. The parent collection must exist.
857  else if (detail::is_separator(_new_p.string().back()))
858  {
859  throw filesystem_error{"path cannot end with a separator", _new_p, make_error_code(SYS_INVALID_INPUT_PARAM)};
860  }
861  else if (!is_collection(_comm, _new_p.parent_path()))
862  {
863  throw filesystem_error{"path does not exist", _new_p.parent_path(), make_error_code(OBJ_PATH_DOES_NOT_EXIST)};
864  }
865  }
866  else {
867  throw filesystem_error{"cannot rename: unknown object type", _new_p, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
868  }
869 
870  dataObjCopyInp_t input{};
871  std::strncpy(input.srcDataObjInp.objPath, _old_p.c_str(), std::strlen(_old_p.c_str()));
872  std::strncpy(input.destDataObjInp.objPath, _new_p.c_str(), std::strlen(_new_p.c_str()));
873 
874  const auto ec = rxDataObjRename(&_comm, &input);
875 
876  if (ec < 0) {
877  throw filesystem_error{"cannot rename object", _old_p, _new_p, make_error_code(ec)};
878  }
879  }
880 
881  auto move(rxComm& _comm, const path& _old_p, const path& _new_p) -> void
882  {
883  rename(_comm, _old_p, _new_p);
884  }
885 
887  const path& _p,
888  const boost::variant<int, replica_number>& _replica_number,
889  verification_calculation _calculation)
890  -> std::vector<checksum>
891  {
892  if (_p.empty()) {
894  }
895 
897 
898  if (!is_data_object(_comm, _p)) {
899  throw filesystem_error{"path does not point to a data object", _p, make_error_code(SYS_INVALID_INPUT_PARAM)};
900  }
901 
902  if (verification_calculation::if_empty == _calculation ||
903  verification_calculation::always == _calculation)
904  {
905  dataObjInp_t input{};
906  std::string replica_number_string;
907 
908  const auto* v = boost::get<replica_number>(&_replica_number);
909 
910  if (v) {
911  addKeyVal(&input.condInput, CHKSUM_ALL_KW, "");
912  }
913  else {
914  const auto *i = boost::get<int>(&_replica_number);
915 
916  if (i && *i >= 0) {
917  replica_number_string = std::to_string(*i);
918  addKeyVal(&input.condInput, REPL_NUM_KW, replica_number_string.c_str());
919  }
920  else {
921  throw filesystem_error{"cannot get checksum: invalid replica number", make_error_code(SYS_INVALID_INPUT_PARAM)};
922  }
923  }
924 
925  std::strncpy(input.objPath, _p.c_str(), std::strlen(_p.c_str()));
926 
927  if (verification_calculation::always == _calculation) {
928  addKeyVal(&input.condInput, FORCE_CHKSUM_KW, "");
929  }
930 
931  char* checksum{};
932 
933  const auto ec = rxDataObjChksum(&_comm, &input, &checksum);
934 
935  if (ec < 0) {
936  throw filesystem_error{"cannot get checksum", _p, make_error_code(ec)};
937  }
938  }
939 
940  std::string sql = "select DATA_REPL_NUM, DATA_CHECKSUM, DATA_SIZE, DATA_REPL_STATUS where DATA_NAME = '";
941  sql += _p.object_name();
942  sql += "' and COLL_NAME = '";
943  sql += _p.parent_path();
944  sql += "'";
945 
947 
948  const auto zone = get_zone_name(_p);
949 
950  if (zone) {
951  qb.zone_hint(*zone);
952  }
953 
954  std::vector<checksum> checksums;
955 
956  for (const auto& row : qb.build(_comm, sql)) {
957  checksums.push_back({std::stoi(row[0]), row[1], std::stoull(row[2]), row[3] == "1"});
958  }
959 
960  return checksums;
961  }
962 
963  auto status(rxComm& _comm, const path& _p) -> object_status
964  {
965  const auto s = stat(_comm, _p);
966 
967  if (s.error < 0) {
968  throw filesystem_error{"cannot get status", _p, make_error_code(s.error)};
969  }
970 
972 
973  status.permissions(s.prms);
974 
975  // XXX This does not handle the case of object_type::unknown.
976  // This type means a file exists, but the type is unknown.
977  // Maybe this case is not possible in iRODS.
978  switch (s.type) {
979  case DATA_OBJ_T:
981  break;
982 
983  case COLL_OBJ_T:
985  break;
986 
987  // This case indicates that iRODS does not contain a data object or
988  // collection at path "_p".
989  case UNKNOWN_OBJ_T:
990  status.type(object_type::not_found);
991  break;
992 
993  /*
994  case ?:
995  status.type(object_type::unknown);
996  break;
997  */
998 
999  default:
1000  status.type(object_type::none);
1001  break;
1002  }
1003 
1004  return status;
1005  }
1006 
1007  auto status_known(object_status _s) noexcept -> bool
1008  {
1009  return _s.type() != object_type::none;
1010  }
1011 
1012  auto get_metadata(rxComm& _comm, const path& _p) -> std::vector<metadata>
1013  {
1014  if (_p.empty()) {
1016  }
1017 
1019 
1020  std::string sql;
1021 
1022  const auto s = status(_comm, _p);
1023 
1024  if (is_data_object(s)) {
1025  sql = "select META_DATA_ATTR_NAME, META_DATA_ATTR_VALUE, META_DATA_ATTR_UNITS where DATA_NAME = '";
1026  sql += _p.object_name();
1027  sql += "' and COLL_NAME = '";
1028  sql += _p.parent_path();
1029  sql += "'";
1030  }
1031  else if (is_collection(s)) {
1032  sql = "select META_COLL_ATTR_NAME, META_COLL_ATTR_VALUE, META_COLL_ATTR_UNITS where COLL_NAME = '";
1033  sql += _p;
1034  sql += "'";
1035  }
1036  else {
1037  throw filesystem_error{"cannot get metadata: unknown object type", _p, make_error_code(CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION)};
1038  }
1039 
1041 
1042  const auto zone = get_zone_name(_p);
1043 
1044  if (zone) {
1045  qb.zone_hint(*zone);
1046  }
1047 
1048  std::vector<metadata> results;
1049 
1050  for (const auto& row : qb.build(_comm, sql)) {
1051  results.push_back({row[0], row[1], row[2]});
1052  }
1053 
1054  return results;
1055  }
1056 
1057  auto set_metadata(rxComm& _comm, const path& _p, const metadata& _metadata) -> void
1058  {
1059  do_metadata_op(_comm, _p, _metadata, "set");
1060  }
1061 
1062  auto add_metadata(rxComm& _comm, const path& _p, const metadata& _metadata) -> void
1063  {
1064  do_metadata_op(_comm, _p, _metadata, "add");
1065  }
1066 
1067  auto remove_metadata(rxComm& _comm, const path& _p, const metadata& _metadata) -> void
1068  {
1069  do_metadata_op(_comm, _p, _metadata, "rm");
1070  }
1071 } // namespace irods::experimental::filesystem::NAMESPACE_IMPL
1072 
irods::experimental::filesystem::client::get_metadata
auto get_metadata(rcComm_t &_comm, const path &_path) -> std::vector< metadata >
Definition: filesystem.cpp:1012
irods::at_scope_exit
Definition: irods_at_scope_exit.hpp:10
irods::experimental::filesystem::perms::null
@ null
rsComm_t
Definition: rcConnect.h:145
irods::experimental::filesystem::client::is_collection
auto is_collection(object_status _s) noexcept -> bool
Definition: filesystem.cpp:600
transferStat_t
Definition: objInfo.h:291
addKeyVal
int addKeyVal(keyValPair_t *condInput, const char *keyWord, const char *value)
Definition: rcMisc.cpp:789
modAVUMetadataInp_t::arg0
char * arg0
Definition: modAVUMetadata.h:7
DataObjCopyInp
Definition: dataObjCopy.h:25
DATA_MODIFY_KW
#define DATA_MODIFY_KW
Definition: rodsKeyWdDef.h:42
modColl.h
CollInp
Definition: dataObjInpOut.h:157
irods::experimental::filesystem::client::is_data_object
auto is_data_object(object_status _s) noexcept -> bool
Definition: filesystem.cpp:635
irods::experimental::filesystem::path
Definition: path.hpp:15
UNKNOWN_OBJ_T
@ UNKNOWN_OBJ_T
Definition: rodsType.h:37
objStat.h
irods::experimental::filesystem::checksum
Definition: filesystem.hpp:43
modAccessControlInp_t::userName
char * userName
Definition: modAccessControl.h:12
irods::experimental::filesystem::perms::write
@ write
rxModAccessControl
#define rxModAccessControl
Definition: config.hpp:60
data_object_modify_info.h
irods_exception.hpp
irods::experimental::query_type::general
@ general
generate_iadmin_commands_for_41_to_42_upgrade.output
output
Definition: generate_iadmin_commands_for_41_to_42_upgrade.py:21
modAccessControl.h
irods::experimental::administration::client::v1::exists
auto exists(rcComm_t &conn, const user &user) -> bool
Definition: user_administration.cpp:359
rcMisc.h
pid_age.p
p
Definition: pid_age.py:13
NAMESPACE_IMPL
#define NAMESPACE_IMPL
Definition: default_transport.hpp:36
rsOpenCollection.hpp
irods::experimental::filesystem::client::last_write_time
auto last_write_time(rcComm_t &_comm, const path &_p) -> object_time_type
Definition: filesystem.cpp:645
USER_FILE_DOES_NOT_EXIST
@ USER_FILE_DOES_NOT_EXIST
Definition: rodsErrorTable.h:241
ctime
long long ctime
Definition: filesystem.cpp:108
dataObjRename.h
rxComm
#define rxComm
Definition: default_transport.hpp:38
REPL_NUM_KW
#define REPL_NUM_KW
Definition: rodsKeyWdDef.h:30
irods::experimental::query_builder
Definition: query_builder.hpp:19
rmColl.h
modAccessControlInp_t
Definition: modAccessControl.h:9
RECURSIVE_OPR__KW
#define RECURSIVE_OPR__KW
Definition: rodsKeyWdDef.h:66
irods::experimental::filesystem::client::data_object_size
auto data_object_size(rcComm_t &_comm, const path &_p) -> std::uintmax_t
Definition: filesystem.cpp:581
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
collCreate.h
rsReadCollection.hpp
readCollection.h
irods::experimental::filesystem::client::permissions
auto permissions(rcComm_t &_comm, const path &_p, const std::string &_user_or_group, perms _prms) -> void
Definition: filesystem.cpp:746
id
long long id
Definition: filesystem.cpp:105
rsModAVUMetadata.hpp
prms
std::vector< entity_permission > prms
Definition: filesystem.cpp:110
irods_query.hpp
SYS_INTERNAL_ERR
@ SYS_INTERNAL_ERR
Definition: rodsErrorTable.h:211
irods::experimental::filesystem::client::end
auto end(const collection_iterator &) noexcept -> const collection_iterator
Definition: collection_iterator.hpp:88
freeRodsObjStat
int freeRodsObjStat(rodsObjStat_t *rodsObjStat)
Definition: rcMisc.cpp:3537
COLL_OBJ_T
@ COLL_OBJ_T
Definition: rodsType.h:39
closeCollection.h
DEST_RESC_NAME_KW
#define DEST_RESC_NAME_KW
Definition: rodsKeyWdDef.h:20
irods::experimental::query_builder::type
auto type(query_type _v) noexcept -> query_builder &
Definition: query_builder.hpp:21
owner_zone
std::string owner_zone
Definition: filesystem.cpp:107
irods::experimental::filesystem::client::begin
auto begin(collection_iterator _iter) noexcept -> collection_iterator
Definition: collection_iterator.hpp:83
irods::experimental::filesystem::verification_calculation::none
@ none
rsSpecificQuery.hpp
irods::experimental::filesystem::client::copy_data_object
auto copy_data_object(rcComm_t &_comm, const path &_from, const path &_to, copy_options _options=copy_options::none) -> bool
Definition: filesystem.cpp:425
rxModColl
#define rxModColl
Definition: config.hpp:53
irods::experimental::filesystem::object_type::none
@ none
recursive
bool recursive
Definition: filesystem.cpp:251
rsModColl.hpp
collOprStat_t
Definition: objInfo.h:298
irods::experimental::filesystem::client::copy
auto copy(rcComm_t &_comm, const path &_from, const path &_to, copy_options _options=copy_options::none) -> void
Definition: filesystem.cpp:370
rxDataObjRename
#define rxDataObjRename
Definition: config.hpp:57
CHKSUM_ALL_KW
#define CHKSUM_ALL_KW
Definition: rodsKeyWdDef.h:59
rsDataObjCopy.hpp
rxObjStat
#define rxObjStat
Definition: config.hpp:52
rsDataObjRename.hpp
rxDataObjUnlink
#define rxDataObjUnlink
Definition: config.hpp:58
CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION
@ CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION
Definition: rodsErrorTable.h:451
DataObjInp
Definition: dataObjInpOut.h:65
OBJ_PATH_DOES_NOT_EXIST
@ OBJ_PATH_DOES_NOT_EXIST
Definition: rodsErrorTable.h:279
no_trash
bool no_trash
Definition: filesystem.cpp:250
irods::experimental::filesystem::verification_calculation
verification_calculation
Definition: filesystem.hpp:56
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
terminate_irods_processes.e
e
Definition: terminate_irods_processes.py:19
irods::experimental::filesystem::detail::throw_if_path_length_exceeds_limit
auto throw_if_path_length_exceeds_limit(const irods::experimental::filesystem::path &_p) -> void
Definition: detail.hpp:20
rsDataObjChksum.hpp
rxCollCreate
#define rxCollCreate
Definition: config.hpp:54
irods::experimental::filesystem::object_time_type
std::chrono::time_point< std::chrono::system_clock, std::chrono::seconds > object_time_type
Definition: filesystem.hpp:34
irods::experimental::filesystem::client::is_empty
auto is_empty(rcComm_t &_comm, const path &_p) -> bool
Definition: filesystem.cpp:610
irods::experimental::filesystem::client::create_collections
auto create_collections(rcComm_t &_comm, const path &_p) -> bool
Definition: filesystem.cpp:527
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
irods::experimental::filesystem::remove_options::no_trash
@ no_trash
rxDataObjChksum
#define rxDataObjChksum
Definition: config.hpp:59
irods::experimental::filesystem::client::collection_iterator
Definition: collection_iterator.hpp:23
irods::experimental::filesystem::client::move
auto move(rcComm_t &_comm, const path &_old_p, const path &_new_p) -> void
Definition: filesystem.cpp:881
irods::experimental::filesystem::path::iterator::difference_type
std::ptrdiff_t difference_type
Definition: path.hpp:253
irods::experimental::query_builder::build
auto build(ConnectionType &_conn, const std::string &_query) -> irods::query< ConnectionType >
Definition: query_builder.hpp:63
INVALID_OBJECT_TYPE
@ INVALID_OBJECT_TYPE
Definition: rodsErrorTable.h:679
modAVUMetadataInp_t
Definition: modAVUMetadata.h:6
rsDataObjCopy
int rsDataObjCopy(rsComm_t *rsComm, dataObjCopyInp_t *dataObjCopyInp, transferStat_t **transferStat)
Definition: rsDataObjCopy.cpp:148
run_tests.results
def results
Definition: run_tests.py:154
DATA_OBJ_T
@ DATA_OBJ_T
Definition: rodsType.h:38
irods::experimental::filesystem::copy_options::recursive
@ recursive
int
typedef int((*funcPtr)())
modDataObjMeta_t::dataObjInfo
dataObjInfo_t * dataObjInfo
Definition: modDataObjMeta.h:8
irods::experimental::filesystem::client::status_known
auto status_known(object_status _s) noexcept -> bool
Definition: filesystem.cpp:1007
irods::experimental::filesystem::client::data_object_checksum
auto data_object_checksum(rcComm_t &_comm, const path &_path, const boost::variant< int, replica_number > &_replica_number, verification_calculation _calculation=verification_calculation::none) -> std::vector< checksum >
Definition: filesystem.cpp:886
specificQuery.h
irods::experimental::filesystem::client::is_other
auto is_other(object_status _s) noexcept -> bool
Definition: filesystem.cpp:625
irods::experimental::filesystem::perms
perms
Definition: permissions.hpp:9
FORCE_FLAG_KW
#define FORCE_FLAG_KW
Definition: rodsKeyWdDef.h:13
irods::experimental::filesystem::client::remove
auto remove(rcComm_t &_comm, const path &_p, remove_options _opts=remove_options::none) -> bool
Definition: filesystem.cpp:699
rsObjStat.hpp
owner_name
std::string owner_name
Definition: filesystem.cpp:106
irods::experimental::filesystem::object_type::collection
@ collection
irods::experimental::filesystem::object_type::data_object
@ data_object
rodsClient.h
irods::experimental::filesystem::client::set_metadata
auto set_metadata(rcComm_t &_comm, const path &_path, const metadata &_metadata) -> void
Definition: filesystem.cpp:1057
apiHeaderAll.h
FORCE_CHKSUM_KW
#define FORCE_CHKSUM_KW
Definition: rodsKeyWdDef.h:60
op
Definition: parser.hpp:25
filesystem.hpp
irods::experimental::filesystem::detail::is_separator
auto is_separator(path::value_type _c) noexcept -> bool
Definition: detail.hpp:28
irods::experimental::query_builder::zone_hint
auto zone_hint(const std::string &_v) -> query_builder &
Definition: query_builder.hpp:27
error
int error
Definition: filesystem.cpp:101
openCollection.h
query_builder.hpp
modAVUMetadata.h
collection_iterator.hpp
rsModDataObjMeta.hpp
has_prefix
int has_prefix(const char *path, const char *prefix)
Definition: rodsPath.cpp:561
irods::experimental::filesystem::filesystem_error
Definition: filesystem_error.hpp:16
irods::experimental::filesystem::client::add_metadata
auto add_metadata(rcComm_t &_comm, const path &_path, const metadata &_metadata) -> void
Definition: filesystem.cpp:1062
irods_at_scope_exit.hpp
irods::experimental::filesystem::client::remove_metadata
auto remove_metadata(rcComm_t &_comm, const path &_path, const metadata &_metadata) -> void
Definition: filesystem.cpp:1067
irods::experimental::filesystem::object_status
Definition: object_status.hpp:22
COLLECTION_MTIME_KW
#define COLLECTION_MTIME_KW
Definition: rodsKeyWdDef.h:70
irods::experimental::filesystem::path::c_str
auto c_str() const noexcept -> const value_type *
Definition: path.hpp:200
irods::experimental::filesystem::detail::make_error_code
auto make_error_code(int _ec) noexcept -> std::error_code
Definition: detail.hpp:15
irods::experimental::filesystem::copy_options::none
@ none
rxDataObjCopy
#define rxDataObjCopy
Definition: config.hpp:56
rodsObjStat
Definition: objStat.h:8
mtime
long long mtime
Definition: filesystem.cpp:109
irods::experimental::filesystem::client::rename
auto rename(rcComm_t &_comm, const path &_from, const path &_to) -> void
Definition: filesystem.cpp:805
rsRmColl.hpp
rodsErrorTable.h
dataObjCopy.h
irods_error.hpp
size
long long size
Definition: filesystem.cpp:102
irods::experimental::filesystem::client::create_collection
auto create_collection(rcComm_t &_comm, const path &_p) -> bool
Definition: filesystem.cpp:479
mode
int mode
Definition: filesystem.cpp:104
path.hpp
rsRmColl
int rsRmColl(rsComm_t *rsComm, collInp_t *rmCollInp, collOprStat_t **collOprStat)
Definition: rsRmColl.cpp:35
modDataObjMeta_t
Definition: modDataObjMeta.h:7
NAME_LEN
#define NAME_LEN
Definition: rodsDef.h:55
KeyValPair
Definition: objInfo.h:120
dataObjChksum.h
rsCollCreate.hpp
parseUserName
int parseUserName(const char *fullUserNameIn, char *userName, char *userZone)
Definition: rcMisc.cpp:204
rsModAccessControl.hpp
type
int type
Definition: filesystem.cpp:103
DataObjInfo
Definition: objInfo.h:129
SAME_SRC_DEST_PATHS_ERR
@ SAME_SRC_DEST_PATHS_ERR
Definition: rodsErrorTable.h:260
irods::experimental::filesystem::remove_options
remove_options
Definition: filesystem.hpp:37
irods::experimental::filesystem::copy_options
copy_options
Definition: copy_options.hpp:10
rsCloseCollection.hpp
rods.h
irods_log.hpp
irods::experimental::filesystem::client::equivalent
auto equivalent(rcComm_t &_comm, const path &_p1, const path &_p2) -> bool
Definition: filesystem.cpp:552
irods::experimental::filesystem::client::remove_all
auto remove_all(rcComm_t &_comm, const path &_p, remove_options _opts=remove_options::none) -> std::uintmax_t
Definition: filesystem.cpp:706
rxRmColl
#define rxRmColl
Definition: config.hpp:55
rxModAVUMetadata
#define rxModAVUMetadata
Definition: config.hpp:61
irods::experimental::filesystem::metadata
Definition: filesystem.hpp:63
rxModDataObjMeta
#define rxModDataObjMeta
Definition: config.hpp:62
SYS_COLLECTION_NOT_EMPTY
@ SYS_COLLECTION_NOT_EMPTY
Definition: rodsErrorTable.h:146
FILE_CREATE_ERROR
@ FILE_CREATE_ERROR
Definition: rodsErrorTable.h:672