You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

119 lines
2.7 KiB

  1. #pragma once
  2. #include <sstream>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <linux/limits.h>
  7. #include <cppcore/conversion/string.h>
  8. #include <cppfs/config.h>
  9. #include "path.h"
  10. namespace cppfs
  11. {
  12. path path::current()
  13. {
  14. char buf[PATH_MAX + 1];
  15. if (!getcwd(&buf[0], sizeof(buf)-1))
  16. throw cppcore::error_exception(errno);
  17. return path(&buf[0]);
  18. }
  19. path::path(const std::string& p_path)
  20. : _status (path_status::none)
  21. , _path (p_path)
  22. , _parts ()
  23. {
  24. if (!_path.empty())
  25. {
  26. if (_path[0] == '.')
  27. {
  28. _status = path_status::relative;
  29. }
  30. else if (_path[0] == '/' || _path[0] == '\\')
  31. {
  32. _status = path_status::absoulte;
  33. }
  34. }
  35. bool ok = cppcore::string_split(
  36. _path,
  37. [](char c) {
  38. return c == '\\'
  39. || c == '/';
  40. },
  41. [this](auto&& s){
  42. if (_parts.empty() && s.empty())
  43. return true;
  44. if (s != ".")
  45. _parts.emplace_back(std::move(s));
  46. return true;
  47. });
  48. if (!ok)
  49. throw cppcore::exception("Error while splitting path into parts");
  50. }
  51. file_type path::type() const
  52. {
  53. struct stat st;
  54. auto& s = str();
  55. if (stat(s.c_str(), &st))
  56. return file_type::unknown;
  57. switch (st.st_mode & S_IFMT)
  58. {
  59. case S_IFSOCK: return file_type::socket;
  60. case S_IFLNK: return file_type::symbolic_link;
  61. case S_IFREG: return file_type::file;
  62. case S_IFBLK: return file_type::block_device;
  63. case S_IFDIR: return file_type::directory;
  64. case S_IFCHR: return file_type::char_device;
  65. case S_IFIFO: return file_type::named_pipe;
  66. default: return file_type::unknown;
  67. }
  68. }
  69. std::string path::make_path() const
  70. {
  71. std::ostringstream ss;
  72. switch (_status)
  73. {
  74. case path_status::none:
  75. break;
  76. case path_status::absoulte:
  77. ss << constants::path_delimiter;
  78. break;
  79. case path_status::relative:
  80. ss << '.' << constants::path_delimiter;
  81. break;
  82. }
  83. bool first = true;
  84. for (auto& part : _parts)
  85. {
  86. if (first)
  87. first = false;
  88. else
  89. ss << constants::path_delimiter;
  90. ss << part;
  91. }
  92. return ss.str();
  93. }
  94. }