1 //===- FileInfo.h -----------------------------------------------*- C++ -*-===//
2 //
3 // This source file is part of the Swift.org open source project
4 //
5 // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6 // Licensed under Apache License v2.0 with Runtime Library Exception
7 //
8 // See http://swift.org/LICENSE.txt for license information
9 // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10 //
11 //===----------------------------------------------------------------------===//
12 //
13 // This file contains the FileInfo wrapper which is shared by the Ninja and
14 // BuildSystem libraries.
15 //
16 // FIXME: I am ambivalent about this living in Basic, I want all non-functional
17 // pieces to generally be pretty isolated (and ideally always mediated by a
18 // delegate access). We may eventually want a specific FileSystem component for
19 // dealing with efficient and abstracted access to the file system and
20 // containing other pieces (like stat caching, or dealing with distribution or
21 // virtualization).
22 //
23 //===----------------------------------------------------------------------===//
24 
25 #ifndef LLBUILD_BASIC_FILEINFO_H
26 #define LLBUILD_BASIC_FILEINFO_H
27 
28 #include "BinaryCoding.h"
29 
30 #include <cstdint>
31 #include <string>
32 
33 namespace llbuild {
34 namespace basic {
35 
36 /// File timestamp wrapper.
37 struct FileTimestamp {
38   uint64_t seconds;
39   uint64_t nanoseconds;
40 
41   bool operator==(const FileTimestamp& rhs) const {
42     return seconds == rhs.seconds && nanoseconds == rhs.nanoseconds;
43   }
44   bool operator!=(const FileTimestamp& rhs) const {
45     return !(*this == rhs);
46   }
47   bool operator<(const FileTimestamp& rhs) const {
48     return (seconds < rhs.seconds ||
49             (seconds == rhs.seconds && nanoseconds < rhs.nanoseconds));
50   }
51   bool operator<=(const FileTimestamp& rhs) const {
52     return (seconds < rhs.seconds ||
53             (seconds == rhs.seconds && nanoseconds <= rhs.nanoseconds));
54   }
55   bool operator>(const FileTimestamp& rhs) const {
56     return rhs < *this;
57   }
58   bool operator>=(const FileTimestamp& rhs) const {
59     return rhs <= *this;
60   }
61 };
62 
63 /// File information which is intended to be used as a proxy for when a file has
64 /// changed.
65 ///
66 /// This structure is intentionally sized to have no packing holes.
67 struct FileInfo {
68   /// The device number.
69   uint64_t device;
70   /// The inode number.
71   uint64_t inode;
72   /// The mode flags of the file.
73   uint64_t mode;
74   /// The size of the file.
75   uint64_t size;
76   /// The modification time of the file.
77   FileTimestamp modTime;
78 
79   /// Check if this is a FileInfo representing a missing file.
isMissingFileInfo80   bool isMissing() const {
81     // We use an all-zero FileInfo as a sentinel, under the assumption this can
82     // never exist in normal circumstances.
83     return (device == 0 && inode == 0 && mode == 0 && size == 0 &&
84             modTime.seconds == 0 && modTime.nanoseconds == 0);
85   }
86 
87   /// Check if the FileInfo corresponds to a directory.
88   bool isDirectory() const;
89 
90   bool operator==(const FileInfo& rhs) const {
91     return (device == rhs.device &&
92             inode == rhs.inode &&
93             size == rhs.size &&
94             modTime == rhs.modTime);
95   }
96   bool operator!=(const FileInfo& rhs) const {
97     return !(*this == rhs);
98   }
99 
100   /// Get the information to represent the state of the given node in the file
101   /// system.
102   ///
103   /// \param asLink If yes, checks the information for the file path without
104   /// looking through symbolic links.
105   ///
106   /// \returns The FileInfo for the given path, which will be missing if the
107   /// path does not exist (or any error was encountered).
108   static FileInfo getInfoForPath(const std::string& path, bool asLink = false);
109 };
110 
111 template<>
112 struct BinaryCodingTraits<FileTimestamp> {
113   static inline void encode(const FileTimestamp& value, BinaryEncoder& coder) {
114     coder.write(value.seconds);
115     coder.write(value.nanoseconds);
116   }
117   static inline void decode(FileTimestamp& value, BinaryDecoder& coder) {
118     coder.read(value.seconds);
119     coder.read(value.nanoseconds);
120   }
121 };
122 
123 template<>
124 struct BinaryCodingTraits<FileInfo> {
125   static inline void encode(const FileInfo& value, BinaryEncoder& coder) {
126     coder.write(value.device);
127     coder.write(value.inode);
128     coder.write(value.mode);
129     coder.write(value.size);
130     coder.write(value.modTime);
131   }
132   static inline void decode(FileInfo& value, BinaryDecoder& coder) {
133     coder.read(value.device);
134     coder.read(value.inode);
135     coder.read(value.mode);
136     coder.read(value.size);
137     coder.read(value.modTime);
138   }
139 };
140 
141 }
142 }
143 
144 #endif
145