Установка / изменение атрибута ctime или "Изменить время" в файле

Я хочу изменить метаданные метки времени для файлов в Java, используя java.nio.Files учебный класс.

Я хотел бы изменить все 3 временные метки Linux/ext4 (последнее изменение, доступ и изменение).

Я могу изменить первые два поля отметок времени следующим образом:

Files.setLastModifiedTime(pathToMyFile, myCustomTime);
Files.setAttribute(pathToMyFile, "basic:lastAccessTime", myCustomTime);

Однако я не могу изменить последнее изменение: время в файле. Кроме того, это касается того, что нет отметки времени изменения, упомянутой в документации. Ближайший доступный атрибут creationTimeчто я пытался без какого-либо успеха.

Любые идеи о том, как изменить Change: метаданные для файла в соответствии с пользовательской меткой времени в Java?

Спасибо!

2 ответа

Решение

Я смог изменить ctime двумя разными способами:

  1. Меняем ядро ​​так, чтобы ctime соответствует mtime
  2. Написание простого (но хакерского) сценария оболочки.

1-й метод: смена ядра.

Я подправил всего несколько строк KERNEL_SRC/fs/attr.c Эта модификация обновляет ctime, чтобы соответствовать mtime всякий раз, когда mtime "явно определено".

Есть много способов "явно определить" mtime, например:

В Linux:

touch -m --date="Wed Jun 12 14:00:00 IDT 2013" filename

В Java (используя Java 6 или 7 и, предположительно, другие):

long newModificationTime = TIME_IN_MILLIS_SINCE_EPOCH;
File myFile = new File(myPath);
newmeta.setLastModified(newModificationTime);

Вот изменение KERNEL_SRC/fs/attr.c в notify_change функция:

    now = current_fs_time(inode->i_sb);

    //attr->ia_ctime = now;  (1) Comment this out
    if (!(ia_valid & ATTR_ATIME_SET))
        attr->ia_atime = now;
    if (!(ia_valid & ATTR_MTIME_SET)) {
        attr->ia_mtime = now;
    }
    else { //mtime is modified to a specific time. (2) Add these lines
        attr->ia_ctime = attr->ia_mtime; //Sets the ctime
        attr->ia_atime = attr->ia_mtime; //Sets the atime (optional)
    }

(1) Эта строка без комментариев обновит ctime до текущего времени после изменения файла. Мы этого не хотим, так как хотим сами установить время. Таким образом, мы комментируем эту строку. (Это не обязательно)

(2) Это действительно суть решения. notify_change Функция выполняется после изменения файла, где метаданные времени должны быть обновлены. Если mtime не было указано, то mtime устанавливается на текущее время. Иначе, если mtime было установлено на определенное значение, мы также устанавливаем ctime и atime на это значение.

2-й способ: простой (но хакерский) скрипт оболочки.

Краткое объяснение: 1) Измените системное время на ваше целевое время 2) Выполните chmod для файла, файл ctime теперь отражает целевое время 3) Верните системное время назад.

changectime.sh

#!/bin/sh
now=$(date)
echo $now
sudo date --set="Sat May 11 06:00:00 IDT 2013"
chmod 777 $1
sudo date --set="$now"

Запустите это следующим образом: ./changectime.sh MYFILE

Ctime файла теперь будет отражать время в файле.

Конечно, вам, вероятно, не нужен файл с разрешениями 777. Убедитесь, что вы изменили этот скрипт в соответствии со своими потребностями, прежде чем использовать его.

Адаптируем этот ответ к вашему делу:

// Warning: Disk must be unmounted before this operation
String disk = "/dev/sda1";
// Update ctime
Runtime.getRuntime().exec("debugfs -w -R 'set_inode_field "+pathToMyFile+" ctime "+myCustomTime+"' "+disk);
// Drop vm cache so ctime update is reflected
Runtime.getRuntime().exec("echo 2 > /proc/sys/vm/drop_caches");

Я сомневаюсь, что мы увидим удобный метод в Standard Java API для этого, так как ни Linux (man touch), ни Windows (функцияGetFileTime в MSDN) не предоставляют легкий доступ к этому полю. Собственные системные вызовы предоставляют только доступ к созданию / доступу / изменению временных меток, так же как и Java.

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