Подтвердить что ты не робот

Java, как удалить файл с установленным набором IMMUTABLE

Работа над проектом Java 8, где я копирую файлы из внешних источников. В одном из этих источников файл устанавливается с неизменным битовым флагом.

В OSX это установлено так

sudo chflags schg /path/to/file

В Linux

chattr +i /path/to/file

Теперь мне нужно удалить файлы, которые я скопировал. Я использовал Apache Commons IO для удаления такого каталога,

FileUtils.deleteDirectory(new File("/path/here"));

Однако это вылетает с помощью java.io.IOException exception.

Есть ли способ Cross Platform удалить эти файлы? Выполнение процесса является владельцем файла.

4b9b3361

Ответ 1

Проблема: Поскольку мы знаем, что файл с неизменяемым атрибутом не может быть удален любым пользователем. Даже пользователь root не может удалить следующий файл.

Теперь, чтобы удалить файл, вы должны удалить неизменяемый атрибут, а затем удалить файл.

Теперь вам нужно применить команду оболочки через код и удалить неизменяемый атрибут в файле.

Как вы упомянули проблему с кросс-платформой

Таким образом, основное альго будет


Шаг 1: Определите, какую ОС вы используете, примерный код:
private static String OS = System.getProperty("os.name").toLowerCase();
if(OS.indexOf("win") >= 0)
    //your code for windows OS.
else if(OS.indexOf("mac") >= 0)
    //your code for MAC OS.
else if(OS.indexOf("sunos") >= 0)
    //your code for Solaris OS

Примечание. Я не добавил код для проверки всех ОС. Поэтому взгляните на них самостоятельно. Шаг 2: Этот шаг поможет вам решить проблему Cross platform. Выпустите соответствующую команду оболочки через java.lang.Runtime.exec, чтобы удалить неизменяемый атрибут файла.
Посмотрите java.lang.Runtime.exec.
java.lang.Runtime.exec. Благодаря этому вы предоставляете соответствующую команду оболочки для любой базовой среды, будь то MAC, Windows, Linux и т.д.

пример кода будет

//if the OS detected is Linux then
Process p = Runtime.getRuntime().exec("chattr -i /path/to/file");
//Play with the process as you would like to, using the documentation.
//else if the OS detected is OSX then : example to unlock in OSX
Process p = Runtime.getRuntime().exec("chflags nouchg /path/to/file");
//Play with the process as you would like to, using the documentation.
//else if the OS detected is say Windows then : example to unlock in    Windows
Process p = Runtime.getRuntime().exec("ATTRIB -s -h /path/to/file");
//-s -h are used to unlock and unhide (i dont the Antonym of hide :p ) the file in windows
//Play with the process as you would like to, using the documentation.

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

Process p = Runtime.getRuntime().exec(new String[]{"csh","-c","cat /home/narek/pk.txt"});


Шаг 3: Используйте тот же Runtime.exec(), чтобы проверить, был ли отключен неизменяемый атрибут, например:

Process p = Runtime.getRuntime().exec("lsattr /whateverPath");
//Play with the process to check whether the attribute is set or not, using the documentation.


Шаг 4: Если Step3 имеет значение true | false, независимо от используемой логики, затем снова удалите файл с помощью соответствующей команды, используя Runtime.exec().

Вещь должна посмотреть на связанную выше документацию java.lang.Runtime.exec и работать с ней.
пожалуйста, дайте мне знать, помогли ли это в определенной степени или нет.

Ответ 2

Есть ли способ Cross Platform для удаления этих файлов?

Не то, чтобы я смог найти. Мне пришлось принять очевидное решение, которое вы уже рассмотрели, длинный путь:

  • определить, на какой ОС я запущен,
  • выдать соответствующую команду оболочки для удаления неизменяемого бита
  • Убедитесь, что он удален.
  • и, наконец, удалить (в моем случае, изменить) файл.

На самом деле проще и легче, ярлык:

  • выполните команду разблокировки вслепую для всех известных двоичных файлов (/usr/bin/chattr и т.д.) с полным путем, чтобы избежать возможных проблем безопасности. Они все быстро потерпят неудачу, кроме одного; напр. Linux любой вызов ATTRIB.EXE или chflags завершится с ошибкой. Если все они не работают, система не поддерживается.
  • выполнить с соответствующими параметрами один бинарный файл, который не завершился, или соответствующий контрольный двоичный файл (например, lsattr для chattr), чтобы проверить удаление флага.
  • или вы можете просто попробовать удалить файл и поймать java.io.IOException.

Я начал изучать, что это такое, что было chattr, но сразу стало ясно, что было несколько специальных системных вызовов, специфичных для ОС, которые мне нужно было бы выдать: таким образом, не было реального преимущества перед вызовом внешнего двоичного кода, за исключением, возможно, производительности, но это не было проблемой в моем случае.

Как только вы перейдете на конкретную для ОС (родную) дорогу, через JNI или JNA, в системе Linux это "простой" вопрос о вызове соответствующей функции IOCTL.

Обратите внимание, что недостаточно идентифицировать ОС, вам также необходимо определить файловую систему, так как, например, FAT32 или FSFS NTFS-3G, IOCTL вернет ошибку (флаг либо недоступен на низком уровне, либо нет (пока поддерживается) промежуточным драйвером IOSS).

Та же проблема существует в Python 2.7, где на высоком уровне предоставляется независимый от ОС вызов... но он не работает везде.