Установка времени последнего изменения каталога, открытого для 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 при доступе к каталогу.

Другие вопросы по тегам