-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
6 GB metadata.db but no files? :-( #12
Comments
I have not touched this repo in quite a while. |
Linux 5.4 something... the current LTS in Arch... |
Happened to me too, but I don't remember which kernel version created that BTRFS partition... |
Ok, it doesn't work even when I create a new BTRFS partition. truncate -s 1G tmp.img
mkfs.btrfs -f tmp.img
mkdir tmp_mount
mount tmp.img tmp_mount
mkdir tmp_mount/folder
touch tmp_mount/folder/file
umount tmp_mount
btrfscue identify tmp.img
btrfscue recon --id UUID_FSID --metadata metadata.db tmp.img
btrfscue --metadata metadata.db mount tmp.img tmp_mount |
I'm having the same isssue. The filesystem was last acessed using Fedora Linux 37, kernel 6.2.14-200.fc37.x86_64. Now running btrfscue on Fedora Linux 38, kernel 6.2.14-300.fc38.x86_64. |
What external program did you use to access metadata.db contents? What type of file is metadata.db? |
I didn't recover much from it, only small files. The external program I was referring to is a script that I made. Let me recover it and I will share it here. |
Thanks. During installation of Fedora Linux 38 I inadvertently deleted the format of my second disk (NVMe). This disk contains one partition formatted with Btrfs using all the disk space without a partition table. I was able to recover my disk (all file data and metadata) using btrfs-select-super utility to overwrite the primary superblock with a backup copy. |
Hi. Same issue here: Linux raspberrypi 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux Using mount option with a 4.9GB metadata file I only can see a metadata file and a void "rescue" directory. |
so... |
I don't remember which one I used, but it's probably this: package main
import (
"encoding/gob"
"encoding/hex"
"errors"
"fmt"
"io"
"log"
"os"
"path"
"strings"
bolt "go.etcd.io/bbolt"
"github.com/giacomoferretti/bbolt-dump/internal/btrfs"
"github.com/giacomoferretti/bbolt-dump/internal/btrfscue"
)
type Inode struct {
Generation uint64
Inode uint64
ParentInode uint64
Name string
IsFile bool
FullPath string
Size uint64
}
var inodeData []Inode
func createDir(inode Inode) {
f := path.Join(os.Args[1], inode.FullPath)
if !inode.IsFile {
os.MkdirAll(f, os.ModePerm)
}
}
func createFile(inode Inode, data []byte) {
f := path.Join(os.Args[1], inode.FullPath)
log.Printf("[GEN:%v] Writing %v bytes to %v...", inode.Generation, inode.Size, f)
if inode.IsFile {
if err := os.WriteFile(f, data, 0644); err != nil {
log.Fatal(err)
}
}
}
func readFileFromDisk(offset, length uint64) []byte {
fmt.Fprintf(os.Stderr, "Reading offset %v and length %v\n", offset, length)
f, err := os.Open(os.Args[4])
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err = f.Seek(int64(offset), io.SeekStart)
if err != nil {
log.Fatal(err)
}
ret := make([]byte, length)
_, err = f.Read(ret)
if err != nil {
log.Fatal(err)
}
return ret
}
func findInode(inode uint64) (Inode, error) {
for _, v := range inodeData {
if v.Inode == inode {
return v, nil
}
}
return Inode{}, errors.New("inode not found")
}
func dbProcessEntry(key, value []byte) error {
btrfsKeyV2 := btrfscue.BtrfscueParseDbKey(key)
btrfsKey, data := btrfscue.BtrfscueParseDbValue(value)
// Print data
dataHex := hex.EncodeToString(data)
dataSanitized := string(data)
dataSanitized = strings.Replace(dataSanitized, "\n", "\\x0a", -1)
dataSanitized = strings.Replace(dataSanitized, "\b", "\\x0b", -1)
dataPrint := ""
if btrfsKey.Size > 0 {
dataPrint = fmt.Sprintf(" %s, %s", dataSanitized, dataHex)
}
if btrfsKeyV2.Type == 108 {
fmt.Printf("[G:%v O:%v ID:%v OF1:%v T:%v OF2:%v S:%v]%s\n", btrfsKeyV2.Generation, btrfsKeyV2.Owner, btrfsKeyV2.ObjectID, btrfsKeyV2.Offset, btrfsKeyV2.Type, btrfsKey.Offset, btrfsKey.Size, dataPrint)
// BTRFS_EXTENT_DATA_KEY
inode := btrfsKeyV2.ObjectID
offset := btrfsKeyV2.Offset
file_extent_item := btrfs.ParseFileExtentItem(data)
targetInode, err := findInode(inode)
if err != nil {
log.Fatal(err)
}
// Inline data
if file_extent_item.Type == 0 {
// Check length
if file_extent_item.RamBytes != uint64(len(data[21:])) {
log.Fatal("WRONG LENGTH ON EXTENT_DATA")
}
if btrfsKeyV2.Generation == targetInode.Generation {
createFile(targetInode, data[21:])
}
} else if file_extent_item.Type == 1 {
file_extent_item_disk := btrfs.ParseFileExtentItemDisk(data[21:])
fmt.Printf(" └─ FILE_EXTENT_ITEM = %v\n", file_extent_item_disk)
if btrfsKeyV2.Generation == targetInode.Generation {
createFile(targetInode, readFileFromDisk(file_extent_item_disk.DiskBytenr, targetInode.Size))
}
}
fmt.Printf(" └─ BTRFS_EXTENT_DATA_KEY - INODE:%v OFFSET:%v = %v\n", inode, offset, file_extent_item)
}
return nil
}
func main() {
// Check arguments
if len(os.Args) != 5 {
fmt.Fprintf(os.Stderr, "Usage: %v <output_folder> <output.bin> <metadata.db> <disk.img>\n", os.Args[0])
os.Exit(1)
}
// GOB DECODE
dataFile, err := os.Open(os.Args[2])
if err != nil {
log.Fatal(err)
}
dataDecoder := gob.NewDecoder(dataFile)
err = dataDecoder.Decode(&inodeData)
if err != nil {
log.Fatal(err)
}
dataFile.Close()
// Create folder
for _, v := range inodeData {
if !v.IsFile {
createDir(v)
}
}
// Open bbolt database
db, err := bolt.Open(os.Args[3], 0600, &bolt.Options{ReadOnly: true})
if err != nil {
log.Fatalln(err)
}
defer db.Close()
// Process all entries on "index"
err = db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte("index"))
b.ForEach(dbProcessEntry)
return nil
})
if err != nil {
log.Fatalln(err)
}
} |
Check https://github.com/giacomoferretti/btrfscue-metadata-extract for a full source. |
same issue here, had hoped to gain access to my data using this project but
UPDATE: I found a much simpler and nicer way to recover my data from my broken btrfs disk: |
Am I screwed? I'm trying to recover file names. Photorec has recovered 150 GB of data but it has no file names...
The text was updated successfully, but these errors were encountered: