Почему Files.deleteDirectoryContents () не рекомендуется в Guava? - PullRequest
9 голосов
/ 30 ноября 2011

В Guava 10+ Google устарел Files.deleteDirectoryContents () .JavaDoc говорит:

устарело.Этот метод страдает от плохого обнаружения символических ссылок и условий гонки.Эта функциональность может поддерживаться подходящим образом только путем предоставления команды операционной системе, такой как rm -rf или del / s.Этот метод планируется удалить из Гуавы в версии 11.0

. Я не понимаю, почему возникло состояние гонки.Я думаю, что использование этого метода на самом деле полезно, и я считаю, что обстрел операционной системы - плохое решение.Может авторы поделятся, почему приняли это решение?

Ответы [ 4 ]

5 голосов
/ 02 декабря 2011

Состояние гонки потенциально хуже, чем «каталог может быть не пустым», и это частично из-за плохого обнаружения символической ссылки. Рассмотрим этот фрагмент кода:

// Symbolic links will have different canonical and absolute paths
if (!directory.getCanonicalPath().equals(directory.getAbsolutePath())) {
  return;
}
... delete its contents ...

Если directory является простым каталогом во время проверки, но символическая ссылка на / впоследствии, deleteDirectoryContents с радостью попытается стереть всю файловую систему.

Может быть, есть обходной путь, но мы его не нашли. И делать специальные исправления для потенциальной ошибки безопасности страшно.

5 голосов
/ 30 ноября 2011

Я не понимаю, почему возникло состояние гонки.

Например, предположим, что один поток вызывает Files.deleteDirectoryContents(), а второй поток (или внешний процесс) одновременно создает новый файл в каталоге.

Когда вы возвращаетесь из звонка, можете ли вы полагаться на то, что каталог пуст? Неа!

В любом случае, если вы считаете, что функциональность этого метода полезна ... несмотря на его недостатки ... вы можете взять копию кода, настроить его и встроить в свое приложение. (Просто проверьте лицензию на исходный код Guava и убедитесь, что вы соответствуете ей.)

Могут ли авторы поделиться, почему приняли это решение?

Я думаю, что они уже есть; см. уведомление об устаревании. Если вы хотите больше, попробуйте поискать трекер проблем и дискуссионную группу Guava. Вы могли бы даже попытаться вежливо спросить в дискуссионной группе, хотя, если ваша повестка дня состоит в том, чтобы изменить их мнение, я сомневаюсь, что у вас все получится.

1 голос
/ 20 февраля 2013

Ты серьезно?Вы пытаетесь решить многопоточность:

Например, предположим, что один поток вызывает Files.deleteDirectoryContents (), а второй поток (или внешний процесс) одновременно создает новый файл в каталоге.Когда вы вернетесь после звонка, можете ли вы полагаться на то, что каталог пуст?Нет!

А как насчет другого процесса, работающего в каталоге ???Это не может быть решено, и вы не должны обрабатывать транзакции, поскольку это просто невозможно.И аргумент, что кто-то делает символическую ссылку на root, поэтому я удаляю всю файловую систему - не должны ли права доступа к файловой системе обрабатывать это?И если вы выполняете такую ​​операцию как root, вы должны знать, что вы делаете.А как же отключить удаление файлов вообще в файловой системе, это опасно !!!Тогда я буду использовать другую библиотеку, если авторы Guava решат такие идиотские проблемы.

1 голос
/ 02 декабря 2011

Дополнительные примеры обнаружения неработающей символической ссылки см. В этих ошибках, зарегистрированных пользователями .

Короче говоря, невозможно стереть каталог, если вы не указали канонический путь к этому каталогу.Если /tmp является ссылкой на /some/other/directory, deleteDirectoryContents не может стереть /tmp/mytempdirectory.Может быть, и здесь есть возможный обходной путь, но мы подняли руки.

...