100 { |
104 { |
101 metadata.modified().map(Self::from) |
105 metadata.modified().map(Self::from) |
102 } |
106 } |
103 } |
107 } |
104 |
108 |
105 /// Returns whether this timestamp is reliable as the "mtime" of a file. |
109 /// Like `for_mtime_of`, but may return `None` or a value with |
|
110 /// `second_ambiguous` set if the mtime is not "reliable". |
106 /// |
111 /// |
107 /// A modification time is reliable if it is older than `boundary` (or |
112 /// A modification time is reliable if it is older than `boundary` (or |
108 /// sufficiently in the future). |
113 /// sufficiently in the future). |
109 /// |
114 /// |
110 /// Otherwise a concurrent modification might happens with the same mtime. |
115 /// Otherwise a concurrent modification might happens with the same mtime. |
111 pub fn is_reliable_mtime(&self, boundary: &Self) -> bool { |
116 pub fn for_reliable_mtime_of( |
|
117 metadata: &fs::Metadata, |
|
118 boundary: &Self, |
|
119 ) -> io::Result<Option<Self>> { |
|
120 let mut mtime = Self::for_mtime_of(metadata)?; |
112 // If the mtime of the ambiguous file is younger (or equal) to the |
121 // If the mtime of the ambiguous file is younger (or equal) to the |
113 // starting point of the `status` walk, we cannot garantee that |
122 // starting point of the `status` walk, we cannot garantee that |
114 // another, racy, write will not happen right after with the same mtime |
123 // another, racy, write will not happen right after with the same mtime |
115 // and we cannot cache the information. |
124 // and we cannot cache the information. |
116 // |
125 // |
117 // However if the mtime is far away in the future, this is likely some |
126 // However if the mtime is far away in the future, this is likely some |
118 // mismatch between the current clock and previous file system |
127 // mismatch between the current clock and previous file system |
119 // operation. So mtime more than one days in the future are considered |
128 // operation. So mtime more than one days in the future are considered |
120 // fine. |
129 // fine. |
121 if self.truncated_seconds == boundary.truncated_seconds { |
130 let reliable = if mtime.truncated_seconds == boundary.truncated_seconds |
122 self.nanoseconds != 0 |
131 { |
|
132 mtime.second_ambiguous = true; |
|
133 mtime.nanoseconds != 0 |
123 && boundary.nanoseconds != 0 |
134 && boundary.nanoseconds != 0 |
124 && self.nanoseconds < boundary.nanoseconds |
135 && mtime.nanoseconds < boundary.nanoseconds |
125 } else { |
136 } else { |
126 // `truncated_seconds` is less than 2**31, |
137 // `truncated_seconds` is less than 2**31, |
127 // so this does not overflow `u32`: |
138 // so this does not overflow `u32`: |
128 let one_day_later = boundary.truncated_seconds + 24 * 3600; |
139 let one_day_later = boundary.truncated_seconds + 24 * 3600; |
129 self.truncated_seconds < boundary.truncated_seconds |
140 mtime.truncated_seconds < boundary.truncated_seconds |
130 || self.truncated_seconds > one_day_later |
141 || mtime.truncated_seconds > one_day_later |
|
142 }; |
|
143 if reliable { |
|
144 Ok(Some(mtime)) |
|
145 } else { |
|
146 Ok(None) |
131 } |
147 } |
132 } |
148 } |
133 |
149 |
134 /// The lower 31 bits of the number of seconds since the epoch. |
150 /// The lower 31 bits of the number of seconds since the epoch. |
135 pub fn truncated_seconds(&self) -> u32 { |
151 pub fn truncated_seconds(&self) -> u32 { |