7

В Linux, с учетом смещения на устройство с необработанным диском, возможно ли отобразить обратно на раздел + inode?

Например, предположим, я знаю, что строка "xyz" содержится со смещением байтов 1000000 в /dev /sda:(например, xxd -l 100 -s 1000000 /dev /sda показывает дамп, который начинается с "xyz")

1) Как определить, в каком разделе (если есть) смещение 1000000 находится?(Я думаю, что это легко, но я включил это для полноты)

2) Предполагая, что смещение находится в разделе, как мне узнать, к какому индексу он принадлежит (или определить, что оно является частью свободного пространства)? Предположительно, это зависит от конкретной файловой системы, и в этом случае кто-нибудь знает, как это сделать для ext4 и ext3?

2 ответа2

13

Я просто должен был сделать нечто подобное, поэтому я решил поделиться своим решением.

Вы можете увидеть, к какому разделу относится смещение байта диска, проверив элементы 'offset' и 'size' в выводе udisks --show-info; например

user@host:~$ sudo udisks --show-info /dev/sda1 | grep -i 'offset'
    offset:                    1048576
    alignment offset:          0

Вычтите это смещение из смещения диска, чтобы получить байтовое смещение в разделе. Таким образом, смещение диска (10000000) в /dev /sda равно смещению раздела (10000000 - 1048576) = 8951424 в /dev /sda1

Вы можете узнать, какие большие блоки находятся в разделе, используя следующую команду:

user@host:~$ sudo tune2fs -l /dev/sda1  | grep -i 'block size'
Block size:               4096

Разделите смещение байта разделения на размер блока, чтобы определить смещение блока, в этом случае 8951424/4096 = 2185

Выполните следующую команду, чтобы узнать, какой inode занимает этот блок:

user@host:~$ sudo debugfs -R "icheck 2185" /dev/sda1
debugfs 1.41.11 (14-Mar-2010)
Block   Inode number
2185    123456 

затем следующая команда, чтобы узнать, какое имя файла для этого inode:

user@host:~$ sudo debugfs -R "ncheck 123456" /dev/sda1
debugfs 1.41.11 (14-Mar-2010)
Inode   Pathname
123456  /tmp/some-filename.txt

Более подробное описание того, как это можно найти на http://www.randomnoun.com/wp/2013/09/12/determining-the-file-at-a-specific-vmdk-offset

0

Ответ Грега Нокса правильный, но может быть проще. Я написал скрипт оболочки, lba2file, который выполняет всю арифметику для вас, исходный код ниже.

Пример использования lba2file

Решение проблемы, поставленной в вопросе (с адресом, указанным в байтах):

kremvax$ sudo lba2file -b 1000000 /dev/sda
Disk Byte 1000000 is at filesystem block 124744 in /dev/sda1
Block is used by inode 21762939
Searching for filename(s)...
Inode           Pathname
21762939        /home/lilnjn/backups/adhumbla_pics_2.zip

Пример использования с SMART

Если на вашем жестком диске поврежден сектор, вы можете узнать, какой файл поврежден, прежде чем переназначить сектор, записав в него нули. Вы можете сделать это легко, используя smartctl и lba2file .

kremvax$ sudo smartctl -C -t short /dev/sdd    
kremvax$ sudo smartctl -a /dev/sdd | grep '^# 1'
# 1  Short captive   Completed: read failure   90%   20444   1218783739

Обратите внимание, что последний номер 1218783739 - это адрес диска в блоках, а не в байтах:

kremvax$ sudo lba2file 1218783739 /dev/sdd
Disk Sector 1218783739 is at filesystem block 152347711 in /dev/sdd1
Block is used by inode 31219834
Searching for filename(s)...
Inode           Pathname
31219834        /home/mryuk/2020-11-03-3045-us-la-msy.jpg
31219834        /home/mryuk/web/2020-11-03-3045-us-la-msy.jpg

обсуждение

Обратите внимание, что мой скрипт по умолчанию имеет адрес сектора (часто называемый "LBA"), а не байты. Это связано с тем, что LBA - это то, о чем сообщают такие инструменты, как smartctl , когда на диске обнаружен сбойный блок. Однако, если вы хотите указать байты вместо секторов, просто укажите флаг -b .

Исходный код

Вырезать и вставить в файл или нажмите здесь, чтобы загрузить с https://github.com/hackerb9/lba2file/

#!/bin/bash

# lba2file: Given an LBA number and a drive in /dev/, print which
# filename(s), if any, use that sector.

# This is the opposite of `hdparm --fibmap /foo/bar`

# B9 Feburary 2019

if [[ "$1" == "-b" ]]; then
    BYTESFLAG=Byte
    shift
fi

if [[ $# -lt 2 ]]; then
    echo "Usage: lba2file  [-b]  <sector number>  /dev/sdX"
    echo "      -b: Use byte address instead of sector"
    exit 1
fi

lba=$1
drive=$2


for partition in ${drive}?; do
    info=$(udisks --show-info $partition)
    if ! e2blocksize=$(tune2fs -l $partition 2>/dev/null |
                              grep '^Block size' | egrep -o '[0-9]+'); then
        continue                # Not an Ext2/3/4 partition
    fi
    offset=$(grep '^    offset:' <<< "$info" | egrep -o '[0-9]+')
    partitionsize=$(grep '^  size:' <<< "$info" | egrep -o '[0-9]+')
    diskblocksize=$(grep '^  block size:' <<< "$info" | egrep -o '[0-9]+')

    # Typically: e2blocksize==4096, diskblocksize==512
    # Example: offset=1048576, partitionsize=640133980160
    if [[ -z "$BYTESFLAG" ]]; then
        byteaddress=$((lba * diskblocksize))
    else
        byteaddress=$lba
    fi
    if [[ $byteaddress -lt $offset ||
          $byteaddress -ge $((offset+partitionsize)) ]]; then
        echo "Not in $partition"
        continue                # Not in this partition
    fi

    # Shift to byteaddress within partition
    partitionbyteaddress=$((byteaddress - offset))

    # Scale address by filesystem blocksize to find filesystem block number
    e2blockaddress=$((partitionbyteaddress / e2blocksize))

    Sector=${BYTESFLAG:-Sector}
    echo "$Sector $lba is at filesystem block $e2blockaddress in $partition"
    inode=$(debugfs -R "icheck $e2blockaddress" $partition 2>/dev/null |
                   tail -1 | cut -f2)
    if [[ "$inode" && "$inode" != "<block not found>" ]]; then
        echo "$Sector is used by inode $inode"
        echo "Searching for filename(s)..."
        debugfs -R "ncheck $inode" $partition 2>/dev/null
    else
        echo "$Sector is not in use."
    fi
done

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .