Skip to content

Commit

Permalink
Update fakefsify for the modern age
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed May 12, 2019
1 parent fdedd2a commit b696f9f
Showing 1 changed file with 17 additions and 21 deletions.
38 changes: 17 additions & 21 deletions tools/fakefsify.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
import os
import sys
from pathlib import Path
import struct
@@ -12,15 +13,11 @@
create table stats (inode integer primary key, stat blob);
create table paths (path blob primary key, inode integer references stats(inode));
create index inode_to_path on paths (inode, path);
create trigger delete_path after delete on paths
when not exists (select 1 from paths where inode = old.inode)
begin
delete from stats where not exists (select 1 from paths where inode = old.inode) and inode = old.inode;
end;
pragma user_version=2;
pragma user_version=3;
"""
# no index is needed on stats, because the rows are ordered by the primary key


def extract_member(archive, db, member):
path = data/(member.name)
major = member.devmajor
@@ -44,20 +41,31 @@ def extract_member(archive, db, member):
else:
raise ValueError('unrecognized tar entry type')

if path != data and not path.parent.exists():
parent_member = tarfile.TarInfo(os.path.dirname(member.name))
parent_member.type = tarfile.DIRTYPE
parent_member.mode = 0o755
extract_member(archive, db, parent_member)

if member.isdir():
path.mkdir(parents=True, exist_ok=True)
path.mkdir()
elif member.issym():
path.write_text(member.linkname)
elif member.isfile():
archive.extract(member, data)
else:
path.touch()

def meta_path(path):
path = path.relative_to(data)
return b'/' + bytes(path) if path.parts else b''

cursor = db.cursor()
if member.islnk():
# a hard link shares its target's inode
target_path = data/(member.linkname)
inode = target_path.stat().st_ino
cursor.execute('select inode from paths where path = ?', (meta_path(target_path),))
inode, = cursor.fetchone()
else:
statblob = memoryview(struct.pack(
'=iiii',
@@ -68,24 +76,12 @@ def extract_member(archive, db, member):
))
cursor.execute('insert into stats (stat) values (?)', (statblob,))
inode = cursor.lastrowid
meta_path = path.relative_to(data)
meta_path = b'/' + bytes(meta_path) if meta_path.parts else b''
cursor.execute('insert into paths values (?, ?)', (meta_path, inode))
cursor.execute('insert into paths values (?, ?)', (meta_path(path), inode))

def extract_archive(archive, db):
for member in archive.getmembers():
# hack
if member.name == './etc/securetty':
continue
extract_member(archive, db, member)

devtty = tarfile.TarInfo('./dev/tty')
devtty.mode = 0o666
devtty.type = b'3'
devtty.devmajor = 5
devtty.devminor = 0
extract_member(archive, db, devtty)

try:
_, archive_path, fs = sys.argv
except ValueError:

0 comments on commit b696f9f

Please sign in to comment.