Skip to content

Instantly share code, notes, and snippets.

@mischief
Created June 4, 2025 21:57
Show Gist options
  • Select an option

  • Save mischief/52f948063fb848125dc5119079a6d33d to your computer and use it in GitHub Desktop.

Select an option

Save mischief/52f948063fb848125dc5119079a6d33d to your computer and use it in GitHub Desktop.
scan for ffs2 slices
local ffi = require("ffi")
local io = require("io")
local bit = require("bit")
ffi.cdef[[
typedef unsigned char u_char;
typedef unsigned char u_int8_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
enum { SBSIZE = 8192 };
enum { SBLOCK_UFS2 = 65536, };
enum { MAXMNTLEN = 468, };
enum { MAXVOLLEN = 32, };
enum { NOCSPTRS = ((128 / sizeof(void *)) - 4), };
enum { FSMAXSNAP = 20, };
struct csum {
int32_t cs_ndir;
int32_t cs_nbfree;
int32_t cs_nifree;
int32_t cs_nffree;
};
struct csum_total {
int64_t cs_ndir;
int64_t cs_nbfree;
int64_t cs_nifree;
int64_t cs_nffree;
int64_t cs_spare[4];
};
struct fs {
int32_t fs_firstfield;
int32_t fs_unused_1;
int32_t fs_sblkno;
int32_t fs_cblkno;
int32_t fs_iblkno;
int32_t fs_dblkno;
int32_t fs_cgoffset;
int32_t fs_cgmask;
int32_t fs_ffs1_time;
int32_t fs_ffs1_size;
int32_t fs_ffs1_dsize;
u_int32_t fs_ncg;
int32_t fs_bsize;
int32_t fs_fsize;
int32_t fs_frag;
int32_t fs_minfree;
int32_t fs_rotdelay;
int32_t fs_rps;
int32_t fs_bmask;
int32_t fs_fmask;
int32_t fs_bshift;
int32_t fs_fshift;
int32_t fs_maxcontig;
int32_t fs_maxbpg;
int32_t fs_fragshift;
int32_t fs_fsbtodb;
int32_t fs_sbsize;
int32_t fs_csmask;
int32_t fs_csshift;
int32_t fs_nindir;
u_int32_t fs_inopb;
int32_t fs_nspf;
int32_t fs_optim;
int32_t fs_npsect;
int32_t fs_interleave;
int32_t fs_trackskew;
int32_t fs_id[2];
int32_t fs_ffs1_csaddr;
int32_t fs_cssize;
int32_t fs_cgsize;
int32_t fs_ntrak;
int32_t fs_nsect;
int32_t fs_spc;
int32_t fs_ncyl;
int32_t fs_cpg;
u_int32_t fs_ipg;
int32_t fs_fpg;
struct csum fs_ffs1_cstotal;
int8_t fs_fmod;
int8_t fs_clean;
int8_t fs_ronly;
int8_t fs_ffs1_flags;
u_char fs_fsmnt[MAXMNTLEN];
u_char fs_volname[MAXVOLLEN];
u_int64_t fs_swuid;
int32_t fs_pad;
int32_t fs_cgrotor;
void *fs_ocsp[NOCSPTRS];
u_int8_t *fs_contigdirs;
struct csum *fs_csp;
int32_t *fs_maxcluster;
u_char *fs_active;
int32_t fs_cpc;
int32_t fs_maxbsize;
int64_t fs_spareconf64[17];
int64_t fs_sblockloc;
struct csum_total fs_cstotal;
int64_t fs_time;
int64_t fs_size;
int64_t fs_dsize;
int64_t fs_csaddr;
int64_t fs_pendingblocks;
u_int32_t fs_pendinginodes;
u_int32_t fs_snapinum[FSMAXSNAP];
u_int32_t fs_avgfilesize;
u_int32_t fs_avgfpdir;
int32_t fs_sparecon[26];
u_int32_t fs_flags;
int32_t fs_fscktime;
int32_t fs_contigsumsize;
int32_t fs_maxsymlinklen;
int32_t fs_inodefmt;
u_int64_t fs_maxfilesize;
int64_t fs_qbmask;
int64_t fs_qfmask;
int32_t fs_state;
int32_t fs_postblformat;
int32_t fs_nrpos;
int32_t fs_postbloff;
int32_t fs_rotbloff;
int32_t fs_magic;
u_int8_t fs_space[1];
};
enum { FS_UFS2_MAGIC = 0x19540119, };
]]
local sbtype = ffi.typeof("struct fs")
local sbsize = ffi.sizeof(sbtype)
local d = assert(io.open(arg[1] or "/dev/rsd0c", "r"))
local idx = 0
while true do
local buf = d:read(ffi.C.SBSIZE)
if not buf then break end
local sb = ffi.new(sbtype)
ffi.copy(sb, buf, sbsize)
if sb.fs_magic == ffi.C.FS_UFS2_MAGIC and sb.fs_sbsize <= ffi.C.SBSIZE and bit.band(sb.fs_bsize, sb.fs_bsize-1) == 0 then
local mnt = ffi.string(sb.fs_fsmnt)
if string.sub(mnt, 1, 1) == "/" then
print((idx*ffi.C.SBSIZE) / 512, "UFS2", ffi.string(sb.fs_fsmnt))
end
end
idx = idx + 1
end
@mischief
Copy link
Author

mischief commented Jun 4, 2025

2112    UFS2    /
18966080        UFS2    /tmp
27354688        UFS2    /var
55071808        UFS2    /usr
67654720        UFS2    /usr/X11R6
69751872        UFS2    /usr/local
103641280       UFS2    /usr/src
109932736       UFS2    /usr/obj
122515648       UFS2    /home

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment