fields.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // SPDX-FileCopyrightText: 2024 Christina SĆørensen
  2. // SPDX-License-Identifier: EUPL-1.2
  3. //
  4. // SPDX-FileCopyrightText: 2023-2024 Christina SĆørensen, eza contributors
  5. // SPDX-FileCopyrightText: 2014 Benjamin Sago
  6. // SPDX-License-Identifier: MIT
  7. //! Wrapper types for the values returned from `File`s.
  8. //!
  9. //! The methods of `File` that return information about the entry on the
  10. //! filesystem -- size, modification date, block count, or Git status -- used
  11. //! to just return these as formatted strings, but this became inflexible once
  12. //! customisable output styles landed.
  13. //!
  14. //! Instead, they will return a wrapper type from this module, which tags the
  15. //! type with what field it is while containing the actual raw value.
  16. //!
  17. //! The `output::details` module, among others, uses these types to render and
  18. //! display the information as formatted strings.
  19. #![allow(non_camel_case_types)]
  20. #![allow(clippy::struct_excessive_bools)]
  21. /// The type of a file’s group ID.
  22. #[cfg(unix)]
  23. pub type gid_t = u32;
  24. /// The type of a file’s inode.
  25. #[cfg(unix)]
  26. pub type ino_t = u64;
  27. /// The type of a file’s number of links.
  28. #[cfg(unix)]
  29. pub type nlink_t = u64;
  30. /// The type of a file’s user ID.
  31. #[cfg(unix)]
  32. pub type uid_t = u32;
  33. /// The type of user file flags
  34. pub type flag_t = u32;
  35. /// The file’s base type, which gets displayed in the very first column of the
  36. /// details output.
  37. ///
  38. /// This type is set entirely by the filesystem, rather than relying on a
  39. /// file’s contents. So ā€œlinkā€ is a type, but ā€œimageā€ is just a type of
  40. /// regular file. (See the `filetype` module for those checks.)
  41. ///
  42. /// Its ordering is used when sorting by type.
  43. #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
  44. pub enum Type {
  45. Directory,
  46. File,
  47. Link,
  48. Pipe,
  49. Socket,
  50. CharDevice,
  51. BlockDevice,
  52. Special,
  53. }
  54. impl Type {
  55. #[must_use]
  56. pub fn is_regular_file(self) -> bool {
  57. matches!(self, Self::File)
  58. }
  59. }
  60. /// The file’s Unix permission bitfield, with one entry per bit.
  61. #[derive(Copy, Clone)]
  62. #[rustfmt::skip]
  63. #[cfg(unix)]
  64. pub struct Permissions {
  65. pub user_read: bool,
  66. pub user_write: bool,
  67. pub user_execute: bool,
  68. pub group_read: bool,
  69. pub group_write: bool,
  70. pub group_execute: bool,
  71. pub other_read: bool,
  72. pub other_write: bool,
  73. pub other_execute: bool,
  74. pub sticky: bool,
  75. pub setgid: bool,
  76. pub setuid: bool,
  77. }
  78. /// The file's `FileAttributes` field, available only on Windows.
  79. #[derive(Copy, Clone)]
  80. #[rustfmt::skip]
  81. #[cfg(windows)]
  82. pub struct Attributes {
  83. pub archive: bool,
  84. pub directory: bool,
  85. pub readonly: bool,
  86. pub hidden: bool,
  87. pub system: bool,
  88. pub reparse_point: bool,
  89. }
  90. /// The three pieces of information that are displayed as a single column in
  91. /// the details view. These values are fused together to make the output a
  92. /// little more compressed.
  93. #[derive(Copy, Clone)]
  94. pub struct PermissionsPlus {
  95. #[allow(unused)]
  96. pub file_type: Type,
  97. #[cfg(unix)]
  98. pub permissions: Permissions,
  99. #[cfg(windows)]
  100. pub attributes: Attributes,
  101. #[allow(unused)]
  102. pub xattrs: bool,
  103. }
  104. /// The permissions encoded as octal values
  105. #[derive(Copy, Clone)]
  106. #[cfg(unix)]
  107. pub struct OctalPermissions {
  108. pub permissions: Permissions,
  109. }
  110. /// A file’s number of hard links on the filesystem.
  111. ///
  112. /// Under Unix, a file can exist on the filesystem only once but appear in
  113. /// multiple directories. However, it’s rare (but occasionally useful!) for a
  114. /// regular file to have a link count greater than 1, so we highlight the
  115. /// block count specifically for this case.
  116. #[cfg(unix)]
  117. #[derive(Copy, Clone)]
  118. pub struct Links {
  119. /// The actual link count.
  120. pub count: nlink_t,
  121. /// Whether this file is a regular file with more than one hard link.
  122. pub multiple: bool,
  123. }
  124. /// A file’s inode. Every directory entry on a Unix filesystem has an inode,
  125. /// including directories and links, so this is applicable to everything exa
  126. /// can deal with.
  127. #[cfg(unix)]
  128. #[derive(Copy, Clone)]
  129. pub struct Inode(pub ino_t);
  130. /// A file's size of allocated file system blocks.
  131. #[derive(Copy, Clone)]
  132. #[cfg(unix)]
  133. pub enum Blocksize {
  134. /// This file has the given number of blocks.
  135. Some(u64),
  136. /// This file isn’t of a type that can take up blocks.
  137. None,
  138. }
  139. /// The ID of the user that owns a file. This will only ever be a number;
  140. /// looking up the username is done in the `display` module.
  141. #[cfg(unix)]
  142. #[derive(Copy, Clone)]
  143. pub struct User(pub uid_t);
  144. /// The ID of the group that a file belongs to.
  145. #[cfg(unix)]
  146. #[derive(Copy, Clone)]
  147. pub struct Group(pub gid_t);
  148. /// A file’s size, in bytes. This is usually formatted by the `unit_prefix`
  149. /// crate into something human-readable.
  150. #[derive(Copy, Clone)]
  151. pub enum Size {
  152. /// This file has a defined size.
  153. Some(u64),
  154. /// This file has no size, or has a size but we aren’t interested in it.
  155. ///
  156. /// Under Unix, directory entries that aren’t regular files will still
  157. /// have a file size. For example, a directory will just contain a list of
  158. /// its files as its ā€œcontentsā€ and will be specially flagged as being a
  159. /// directory, rather than a file. However, seeing the ā€œfile sizeā€ of this
  160. /// data is rarely useful — I can’t think of a time when I’ve seen it and
  161. /// learnt something. So we discard it and just output ā€œ-ā€ instead.
  162. ///
  163. /// See this answer for more: <https://unix.stackexchange.com/a/68266>
  164. None,
  165. /// This file is a block or character device, so instead of a size, print
  166. /// out the file’s major and minor device IDs.
  167. ///
  168. /// This is what ls does as well. Without it, the devices will just have
  169. /// file sizes of zero.
  170. DeviceIDs(DeviceIDs),
  171. }
  172. /// The major and minor device IDs that gets displayed for device files.
  173. ///
  174. /// You can see what these device numbers mean:
  175. /// - <http://www.lanana.org/docs/device-list/>
  176. /// - <http://www.lanana.org/docs/device-list/devices-2.6+.txt>
  177. #[derive(Copy, Clone)]
  178. pub struct DeviceIDs {
  179. pub major: u32,
  180. pub minor: u32,
  181. }
  182. /// A file’s status in a Git repository. Whether a file is in a repository or
  183. /// not is handled by the Git module, rather than having a ā€œnullā€ variant in
  184. /// this enum.
  185. #[derive(PartialEq, Eq, Copy, Clone)]
  186. pub enum GitStatus {
  187. /// This file hasn’t changed since the last commit.
  188. NotModified,
  189. /// This file didn’t exist for the last commit, and is not specified in
  190. /// the ignored files list.
  191. New,
  192. /// A file that’s been modified since the last commit.
  193. Modified,
  194. /// A deleted file. This can’t ever be shown, but it’s here anyway!
  195. Deleted,
  196. /// A file that Git has tracked a rename for.
  197. Renamed,
  198. /// A file that’s had its type (such as the file permissions) changed.
  199. TypeChange,
  200. /// A file that’s ignored (that matches a line in .gitignore)
  201. Ignored,
  202. /// A file that’s updated but unmerged.
  203. Conflicted,
  204. }
  205. /// A file’s complete Git status. It’s possible to make changes to a file, add
  206. /// it to the staging area, then make *more* changes, so we need to list each
  207. /// file’s status for both of these.
  208. #[derive(Copy, Clone)]
  209. pub struct Git {
  210. pub staged: GitStatus,
  211. pub unstaged: GitStatus,
  212. }
  213. impl Default for Git {
  214. /// Create a Git status for a file with nothing done to it.
  215. fn default() -> Self {
  216. Self {
  217. staged: GitStatus::NotModified,
  218. unstaged: GitStatus::NotModified,
  219. }
  220. }
  221. }
  222. pub enum SecurityContextType<'a> {
  223. SELinux(&'a str),
  224. None,
  225. }
  226. pub struct SecurityContext<'a> {
  227. pub context: SecurityContextType<'a>,
  228. }
  229. #[allow(dead_code)]
  230. #[derive(PartialEq, Copy, Clone)]
  231. pub enum SubdirGitRepoStatus {
  232. NoRepo,
  233. GitClean,
  234. GitDirty,
  235. }
  236. #[derive(Clone)]
  237. pub struct SubdirGitRepo {
  238. pub status: Option<SubdirGitRepoStatus>,
  239. pub branch: Option<String>,
  240. }
  241. impl Default for SubdirGitRepo {
  242. fn default() -> Self {
  243. Self {
  244. status: Some(SubdirGitRepoStatus::NoRepo),
  245. branch: None,
  246. }
  247. }
  248. }
  249. /// The user file flags on the file. This will only ever be a number;
  250. /// looking up the flags is done in the `display` module.
  251. pub struct Flags(pub flag_t);