Установка времени последнего изменения каталога, открытого для ReadDirectoryChangesW
У меня есть Java-программа, которая должна отслеживать дерево каталогов на предмет изменений. У меня есть код JNI, который использует ReadDirectoryChangesW()
, Каталог открывается как:
HANDLE dirHandle = CreateFile(
path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);
а потом я прохожу dirHandle
в ReadDirectoryChangesW()
, Все это работает просто отлично.
Проблема в том, что другие части кода (на стороне Java) используют File.setLastModified()
"трогать" файлы или каталоги (обновлять их метки времени, чтобы быть "сейчас"). Это обычно работает; однако, это терпит неудачу, когда он пытался "коснуться" каталога, который был открыт с помощью CreateFile()
,
Чтобы увидеть, что на самом деле происходит ошибка Windows, я посмотрел на источник JDK для File.setLastModified()
и переопределил его в моем собственном коде с добавлением печати ошибки из GetLastError()
; ошибка:
ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."
WTF? Это тот же процесс. Я даже сдал FILE_SHARE_READ
а также FILE_SHARE_WRITE
в CreateFile()
,
Есть ли способ сделать эту работу?
Больше информации
Реализация нативного кода File.setLastModified()
в JDK делает:
h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
Если я изменю первый 0
в FILE_SHARE_READ | FILE_SHARE_WRITE
, все работает. Таким образом, кажется, что реализация JDK немного сломана.:(
Таким образом, мой вопрос теперь звучит так: есть ли способ сделать эту работу без использования моей (пере) реализации File.setLastModified()
?
1 ответ
Хотя в данном случае сообщение об ошибке немного вводит в заблуждение, вы видите нормальное поведение.
Открыв каталог с dwShareMode
равный нулю, JDK фактически запрашивает монопольный доступ, что приведет к сбою любой другой попытки доступа с ошибкой нарушения совместного доступа. Это в равной степени относится и к доступам из других процессов и из вашего собственного процесса.
CreateFile
документация описывает dwShareMode
параметр:
Если этот параметр равен нулю и CreateFile завершается успешно, файл или устройство не могут быть общими и не могут быть открыты снова, пока не будет закрыт дескриптор файла или устройства.
Вы не можете запросить режим совместного использования, который конфликтует с режимом доступа, который указан в существующем запросе с открытым дескриптором.
CreateFile
потерпит неудачу иGetLastError
функция вернетсяERROR_SHARING_VIOLATION
,
Итак, кажется, вы ответили на свой вопрос: вам нужен кастом setLastModified
функция, которая определяет FILE_SHARE_READ | FILE_SHARE_WRITE
при доступе к каталогу.