|
15 | 15 | package com.google.devtools.build.lib.windows;
|
16 | 16 |
|
17 | 17 | import com.google.devtools.build.lib.jni.JniLoader;
|
| 18 | +import java.io.FileNotFoundException; |
18 | 19 | import java.io.IOException;
|
| 20 | +import java.nio.file.AccessDeniedException; |
19 | 21 |
|
20 | 22 | /** File operations on Windows. */
|
21 | 23 | public class WindowsFileOperations {
|
@@ -82,6 +84,12 @@ public Status getStatus() {
|
82 | 84 | // IS_SYMLINK_OR_JUNCTION_ERROR = 1;
|
83 | 85 | private static final int IS_SYMLINK_OR_JUNCTION_DOES_NOT_EXIST = 2;
|
84 | 86 |
|
| 87 | + // Keep GET_CHANGE_TIME_* values in sync with src/main/native/windows/file.cc. |
| 88 | + private static final int GET_CHANGE_TIME_SUCCESS = 0; |
| 89 | + // private static final int GET_CHANGE_TIME_ERROR = 1; |
| 90 | + private static final int GET_CHANGE_TIME_DOES_NOT_EXIST = 2; |
| 91 | + private static final int GET_CHANGE_TIME_ACCESS_DENIED = 3; |
| 92 | + |
85 | 93 | // Keep CREATE_JUNCTION_* values in sync with src/main/native/windows/file.h.
|
86 | 94 | private static final int CREATE_JUNCTION_SUCCESS = 0;
|
87 | 95 | // CREATE_JUNCTION_ERROR = 1;
|
@@ -114,6 +122,9 @@ public Status getStatus() {
|
114 | 122 | private static native int nativeIsSymlinkOrJunction(
|
115 | 123 | String path, boolean[] result, String[] error);
|
116 | 124 |
|
| 125 | + private static native int nativeGetChangeTime( |
| 126 | + String path, boolean followReparsePoints, long[] result, String[] error); |
| 127 | + |
117 | 128 | private static native boolean nativeGetLongPath(String path, String[] result, String[] error);
|
118 | 129 |
|
119 | 130 | private static native int nativeCreateJunction(String name, String target, String[] error);
|
@@ -143,6 +154,25 @@ public static boolean isSymlinkOrJunction(String path) throws IOException {
|
143 | 154 | throw new IOException(String.format("Cannot tell if '%s' is link: %s", path, error[0]));
|
144 | 155 | }
|
145 | 156 |
|
| 157 | + /** Returns the time at which the file was last changed, including metadata changes. */ |
| 158 | + public static long getLastChangeTime(String path, boolean followReparsePoints) |
| 159 | + throws IOException { |
| 160 | + long[] result = new long[] {0}; |
| 161 | + String[] error = new String[] {null}; |
| 162 | + switch (nativeGetChangeTime(asLongPath(path), followReparsePoints, result, error)) { |
| 163 | + case GET_CHANGE_TIME_SUCCESS: |
| 164 | + return result[0]; |
| 165 | + case GET_CHANGE_TIME_DOES_NOT_EXIST: |
| 166 | + throw new FileNotFoundException(path); |
| 167 | + case GET_CHANGE_TIME_ACCESS_DENIED: |
| 168 | + throw new AccessDeniedException(path); |
| 169 | + default: |
| 170 | + // This is GET_CHANGE_TIME_ERROR (1). The JNI code puts a custom message in 'error[0]'. |
| 171 | + break; |
| 172 | + } |
| 173 | + throw new IOException(String.format("Cannot get last change time of '%s': %s", path, error[0])); |
| 174 | + } |
| 175 | + |
146 | 176 | /**
|
147 | 177 | * Returns the long path associated with the input `path`.
|
148 | 178 | *
|
|
0 commit comments