-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Avi Deitcher <[email protected]>
- Loading branch information
Showing
41 changed files
with
6,829 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package ext4 | ||
|
||
import "fmt" | ||
|
||
// bitmap is a structure holding a bitmap | ||
type bitmap struct { | ||
bits []byte | ||
} | ||
|
||
// bitmapFromBytes create a bitmap struct from bytes | ||
func bitmapFromBytes(b []byte) *bitmap { | ||
// just copy them over | ||
bits := make([]byte, len(b)) | ||
copy(bits, b) | ||
bm := bitmap{ | ||
bits: bits, | ||
} | ||
|
||
return &bm | ||
} | ||
|
||
// toBytes returns raw bytes ready to be written to disk | ||
func (bm *bitmap) toBytes() []byte { | ||
b := make([]byte, len(bm.bits)) | ||
copy(b, bm.bits) | ||
|
||
return b | ||
} | ||
|
||
func (bm *bitmap) checkFree(location int) (bool, error) { | ||
byteNumber, bitNumber := findBitForIndex(location) | ||
if byteNumber > len(bm.bits) { | ||
return false, fmt.Errorf("location %d is not in %d size bitmap", location, len(bm.bits)*8) | ||
} | ||
mask := byte(0x1) << bitNumber | ||
return bm.bits[byteNumber]&mask == mask, nil | ||
} | ||
|
||
func (bm *bitmap) free(location int) error { | ||
byteNumber, bitNumber := findBitForIndex(location) | ||
if byteNumber > len(bm.bits) { | ||
return fmt.Errorf("location %d is not in %d size bitmap", location, len(bm.bits)*8) | ||
} | ||
mask := byte(0x1) << bitNumber | ||
mask = ^mask | ||
bm.bits[byteNumber] &= mask | ||
return nil | ||
} | ||
|
||
func (bm *bitmap) use(location int) error { | ||
byteNumber, bitNumber := findBitForIndex(location) | ||
if byteNumber > len(bm.bits) { | ||
return fmt.Errorf("location %d is not in %d size bitmap", location, len(bm.bits)*8) | ||
} | ||
mask := byte(0x1) << bitNumber | ||
bm.bits[byteNumber] |= mask | ||
return nil | ||
} | ||
|
||
func (bm *bitmap) findFirstFree() int { | ||
var location = -1 | ||
for i, b := range bm.bits { | ||
// if all used, continue to next | ||
if b&0xff == 0xff { | ||
continue | ||
} | ||
// not all used, so find first bit set to 0 | ||
for j := uint8(0); j < 8; j++ { | ||
mask := byte(0x1) << j | ||
if b&mask != mask { | ||
location = 8*i + (8 - int(j)) | ||
break | ||
} | ||
} | ||
break | ||
} | ||
return location | ||
} | ||
|
||
//nolint:revive // params are unused as of yet, but will be used in the future | ||
func (bm *bitmap) findFirstUsed() int { | ||
var location int = -1 | ||
for i, b := range bm.bits { | ||
// if all free, continue to next | ||
if b == 0x00 { | ||
continue | ||
} | ||
// not all free, so find first bit set to 1 | ||
for j := uint8(0); j < 8; j++ { | ||
mask := byte(0x1) << j | ||
mask = ^mask | ||
if b|mask != mask { | ||
location = 8*i + (8 - int(j)) | ||
break | ||
} | ||
} | ||
break | ||
} | ||
return location | ||
} | ||
|
||
func findBitForIndex(index int) (byteNumber int, bitNumber uint8) { | ||
return index / 8, uint8(index % 8) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package ext4 | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// blockGroup is a structure holding the data about a single block group | ||
// | ||
//nolint:unused // will be used in the future, not yet | ||
type blockGroup struct { | ||
inodeBitmap *bitmap | ||
blockBitmap *bitmap | ||
blockSize int | ||
number int | ||
inodeTableSize int | ||
firstDataBlock int | ||
} | ||
|
||
// blockGroupFromBytes create a blockGroup struct from bytes | ||
// it does not load the inode table or data blocks into memory, rather holding pointers to where they are | ||
// | ||
//nolint:unused // will be used in the future, not yet | ||
func blockGroupFromBytes(b []byte, blockSize, groupNumber int) (*blockGroup, error) { | ||
expectedSize := 2 * blockSize | ||
actualSize := len(b) | ||
if actualSize != expectedSize { | ||
return nil, fmt.Errorf("expected to be passed %d bytes for 2 blocks of size %d, instead received %d", expectedSize, blockSize, actualSize) | ||
} | ||
inodeBitmap := bitmapFromBytes(b[0:blockSize]) | ||
blockBitmap := bitmapFromBytes(b[blockSize : 2*blockSize]) | ||
|
||
bg := blockGroup{ | ||
inodeBitmap: inodeBitmap, | ||
blockBitmap: blockBitmap, | ||
number: groupNumber, | ||
blockSize: blockSize, | ||
} | ||
return &bg, nil | ||
} | ||
|
||
// toBytes returns bitmaps ready to be written to disk | ||
// | ||
//nolint:unused // will be used in the future, not yet | ||
func (bg *blockGroup) toBytes() ([]byte, error) { | ||
b := make([]byte, 2*bg.blockSize) | ||
inodeBitmapBytes := bg.inodeBitmap.toBytes() | ||
blockBitmapBytes := bg.blockBitmap.toBytes() | ||
|
||
b = append(b, inodeBitmapBytes...) | ||
b = append(b, blockBitmapBytes...) | ||
|
||
return b, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package ext4 | ||
|
||
import ( | ||
"encoding/binary" | ||
|
||
"github.com/diskfs/go-diskfs/filesystem/ext4/crc" | ||
) | ||
|
||
// checksumAppender is a function that takes a byte slice and returns a byte slice with a checksum appended | ||
type checksumAppender func([]byte) []byte | ||
type checksummer func([]byte) uint32 | ||
|
||
// directoryChecksummer returns a function that implements checksumAppender for a directory entries block | ||
// original calculations can be seen for e2fsprogs https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/lib/ext2fs/csum.c#n301 | ||
// and in the linux tree https://github.com/torvalds/linux/blob/master/fs/ext4/namei.c#L376-L384 | ||
func directoryChecksummer(seed, inodeNumber, inodeGeneration uint32) checksummer { | ||
numBytes := make([]byte, 4) | ||
binary.LittleEndian.PutUint32(numBytes, inodeNumber) | ||
crcResult := crc.CRC32c(seed, numBytes) | ||
genBytes := make([]byte, 4) | ||
binary.LittleEndian.PutUint32(genBytes, inodeGeneration) | ||
crcResult = crc.CRC32c(crcResult, genBytes) | ||
return func(b []byte) uint32 { | ||
checksum := crc.CRC32c(crcResult, b) | ||
return checksum | ||
} | ||
} | ||
|
||
// directoryChecksumAppender returns a function that implements checksumAppender for a directory entries block | ||
// original calculations can be seen for e2fsprogs https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/lib/ext2fs/csum.c#n301 | ||
// and in the linux tree https://github.com/torvalds/linux/blob/master/fs/ext4/namei.c#L376-L384 | ||
func directoryChecksumAppender(seed, inodeNumber, inodeGeneration uint32) checksumAppender { | ||
fn := directoryChecksummer(seed, inodeNumber, inodeGeneration) | ||
return func(b []byte) []byte { | ||
checksum := fn(b) | ||
checksumBytes := make([]byte, 12) | ||
checksumBytes[4] = 12 | ||
checksumBytes[7] = 0xde | ||
binary.LittleEndian.PutUint32(checksumBytes[8:12], checksum) | ||
b = append(b, checksumBytes...) | ||
return b | ||
} | ||
} | ||
|
||
// nullDirectoryChecksummer does not change anything | ||
func nullDirectoryChecksummer(b []byte) []byte { | ||
return b | ||
} |
Oops, something went wrong.