uploaded what I have found

This commit is contained in:
Patrick Neumann 2018-06-16 14:11:16 +02:00
parent 81b6ba30d1
commit 0d355902ab
12 changed files with 863 additions and 0 deletions

1
AUTHORS Executable file
View File

@ -0,0 +1 @@
fatlister is written and maintained by Patrick Neumann <patrick@neumannsland.de>.

21
CHANGES Executable file
View File

@ -0,0 +1,21 @@
Release 1.0 (in development)
============================
(Incompatible) changes
----------------------
* none
Features added
--------------
* none
Bugs fixed
----------
* none

BIN
cf64mbwin.dd Executable file

Binary file not shown.

114
cf64mbwin.info Executable file
View File

@ -0,0 +1,114 @@
GUYMAGER ACQUISITION INFO FILE
==============================
Guymager
========
Version : 0.8.4-1
Compilation timestamp: 2017-02-02-16.19.12
Compiled with : gcc 4.9.2
libewf version : 20140608
libguytools version : 2.1.0beta5
Host name : host10
Domain name : (none)
System : Linux host10 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64
Device information
==================
Command executed: bash -c "search="`basename /dev/sdc`: H..t P.......d A..a de.....d" && dmesg | grep -A3 "$search" || echo "No kernel HPA messages for /dev/sdc""
Information returned:
----------------------------------------------------------------------------------------------------
No kernel HPA messages for /dev/sdc
Command executed: bash -c "smartctl -s on /dev/sdc ; smartctl -a /dev/sdc"
Information returned:
----------------------------------------------------------------------------------------------------
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org
/dev/sdc: Unknown USB bridge [0x0bda:0x0184 (0x8413)]
Please specify device type with the -d option.
Use smartctl -h to get a usage summary
smartctl 6.4 2014-10-07 r4002 [x86_64-linux-3.16.0-4-amd64] (local build)
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org
/dev/sdc: Unknown USB bridge [0x0bda:0x0184 (0x8413)]
Please specify device type with the -d option.
Use smartctl -h to get a usage summary
Command executed: bash -c "hdparm -I /dev/sdc"
Information returned:
----------------------------------------------------------------------------------------------------
SG_IO: bad/missing sense data, sb[]: 70 00 05 00 00 00 00 0a 00 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
/dev/sdc:
ATA device, with non-removable media
Standards:
Likely used: 1
Configuration:
Logical max current
cylinders 0 0
heads 0 0
sectors/track 0 0
--
Logical/Physical Sector size: 512 bytes
device size with M = 1024*1024: 0 MBytes
device size with M = 1000*1000: 0 MBytes
cache/buffer size = unknown
Capabilities:
IORDY not likely
Cannot perform double-word IO
R/W multiple sector transfer: not supported
DMA: not supported
PIO: pio0
Hidden areas: unknown
Acquisition
===========
Linux device : /dev/sdc
Device size : 65536000 (65,5MB)
Format : Linux split dd raw image - file extension is .xxx
Image path and file name: /home/user10/Dokumente/cf64mbwin.xxx
Info path and file name: /home/user10/Dokumente/cf64mbwin.info
Hash calculation : MD5 and SHA-1
Source verification : on
Image verification : on
No bad sectors encountered during acquisition.
No bad sectors encountered during verification.
State: Finished successfully
MD5 hash : 9073705f04e50e70790cddf48a1d0413
MD5 hash verified source : 9073705f04e50e70790cddf48a1d0413
MD5 hash verified image : 9073705f04e50e70790cddf48a1d0413
SHA1 hash : 08165d91b9f2d84581ecc087abf36855fb721da3
SHA1 hash verified source : 08165d91b9f2d84581ecc087abf36855fb721da3
SHA1 hash verified image : 08165d91b9f2d84581ecc087abf36855fb721da3
SHA256 hash : --
SHA256 hash verified source: --
SHA256 hash verified image : --
Source verification OK. The device delivered the same data during acquisition and verification.
Image verification OK. The image contains exactly the data that was written.
Acquisition started : 2017-05-08 15:10:06 (ISO format YYYY-MM-DD HH:MM:SS)
Verification started: 2017-05-08 15:10:24
Ended : 2017-05-08 15:10:43 (0 hours, 0 minutes and 37 seconds)
Acquisition speed : 3.47 MByte/s (0 hours, 0 minutes and 18 seconds)
Verification speed : 3.47 MByte/s (0 hours, 0 minutes and 18 seconds)
Generated image files and their MD5 hashes
==========================================
No MD5 hashes available (configuration parameter CalcImageFileMD5 is off)
MD5 Image file
n/a cf64mbwin.000

BIN
doc/fatlister.pdf Executable file

Binary file not shown.

522
fatlister.py Executable file
View File

@ -0,0 +1,522 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""List file and directory names in a FAT16 file system (disk image)."""
#===============================================================================
#
# FILE:
# ./fatlister.py
#
# BASIC USAGE:
# $ ./fatlister.py [-h|--help] [-o|--offset OFFSET] [-f|--file FILENAME] IMAGE
# OR
# $ python3 fatlister.py [-h|--help] [-o|--offset OFFSET] [-f|--file FILENAME] IMAGE
#
# OPTIONS:
# -h,
# --help show help message and exit
# -o OFFSET,
# --offset OFFSET offset in sectors (default=0)
# -f FILENAME, write output to file (default=unset)
# --file FILENAME if unset output goes to stdout
# IMAGE raw image file (esp. dd)
#
# EXIT STATES:
# 0 = success
# 1 = Python version not tested/supported
# 2 = states thrown by argparse:
# - IMAGE not passed to fatlister
# - unknown argument passed to fatlister
# - OFFSET is not an integer
# 3 = image file does not exist
# 4 = file is not readable
# 5 = offset is not a positive integer
# 6 = output file already exist
# 7 = output directory is not writable
# 8 = empty image file
# 9 = image file smaller than offset
# 10 = invalid vbr signatures
#
# REQUIREMENTS:
# python3.4+
#
# NOTES:
# Tested on:
# - ArchLinux (64-Bit) + python 3.6.1
# - Raspbian GNU/Linux 8.0 (32-Bit) + python 3.4.2
# - macOS (10.12.4) + python 3.6.1 (from Homebrew)
# - Bash on Ubuntu on Windows 10 "1703" (64-Bit) + python 3.5.2
# with:
# - raw images
# - filesystem(s) in partition(s) <--- TODO!
# - filesystem without a partition
# - no partition/no filesystem (empty file)
# - invalid filesystem
# - FAT16
#
# WARRANTY:
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See the LICENSE file for more details.
#
# HISTORY:
# See the CHANGES file for more details.
#
#===============================================================================
#=== MODULES ===================================================================
import argparse
import os
import os.path
import re
import struct
import sys
import time
#=== INFO ======================================================================
"""@author: Patrick Neumann
@contact: patrick@neumannsland.de
@copyright: Copyright (C) 2017, Patrick Neumann
@license: GNU General Public License 3.0
@date: 2017-03-26
@version: 1.0.1
@status: Development
"""
#=== CHECKS ====================================================================
"""Only tested with Python versions 3.4.x - 3.6.x!"""
if sys.version.startswith("2"):
sys.stderr.write("Python version 2.x is not supportet!\n")
sys.exit(1)
if sys.version_info < (3, 4, 0):
sys.stderr.write("Sorry, your Python version was not tested but may work?\n")
sys.exit(1)
#=== CLASS =====================================================================
class Fatlister:
def __init__(self, image, offset):
self._checkimage(image)
self.image = image
self._checkoffset(offset)
self.offset = offset
self._checkvbr()
self.output = ['# This RFC4180 compliant file was created with fatlister.py at ' + time.strftime("%Y-%m-%dT%H:%M:%S") + '.',
'"id", "path", "name", "LFN", "Allocated", "Size", "Accessed", "Modified", "Created", "Starting Cluster"']
self._processvbr()
self._readfiles()
#-------------------------------------------------------------------------------
# This is a private method for usage in this class only.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _checkimage(self, _file):
"""Check image file.
Check if the image is a existing and readable file.
Parameters
----------
_file : str
path to the image file.
Raises
------
Exits if the image does not exist or is not readable.
"""
if not os.path.isfile(_file):
sys.stderr.write("Error: image file does not exist!\n")
sys.exit(3)
size = os.stat(_file)[6]
if size == 0:
sys.stderr.write("Error: the image file is an empty file!\n")
sys.exit(8)
# Check if image is readable the first time if we need to read it!
#-------------------------------------------------------------------------------
# This is a private method for usage in this class only.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _checkoffset(self, offset):
"""Check offset.
Check if the offset is an integer and is equal or greater than zero.
Parameters
----------
offset : int
offset in bytes in the image file.
Raises
------
Exits if the offset is not equal or greater than zero.
"""
if not offset >= 0:
sys.stderr.write("Error: offset is not equal or greater zero!\n")
sys.exit(5)
size = os.stat(self.image)[6]
if size < offset + 512:
sys.stderr.write("Error: size of the image file is smaller than offset (+ 512 byte)!\n")
sys.exit(9)
#-------------------------------------------------------------------------------
# This is a private method for usage in this class only.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _checkvbr(self):
"""Check for FAT VBR.
Check for the existence of a valid FAT12/16 VBR.
Parameters
----------
self.image : str
path to the image file.
self.offset : int
offset in bytes in the image file.
Raises
------
Exits if the VBR can not be verified as a FAT12/16 VBR.
"""
try:
with open(self.image, "rb") as isreadable:
isreadable.seek(self.offset + 38)
extended_signature = isreadable.read(1)
isreadable.seek(15, 1)
file_system_type = isreadable.read(8)
isreadable.seek(448, 1)
vbr_signature = isreadable.read(2)
except IOError:
sys.stderr.write("Error: image file is not readable!\n")
sys.exit(4)
condition1 = extended_signature == b"\x29"
condition2 = re.search(r'FAT1(2|6) ', file_system_type.decode("ascii"))
condition3 = vbr_signature == b"\x55\xaa"
if not (condition1 and condition2 and condition3):
sys.stderr.write("Error: no valid FAT12/FAT16 VBR found!\n")
sys.exit(10)
#-------------------------------------------------------------------------------
def printoutput(self):
"""Print to stdout.
Prints every item of self.output to stdout.
Parameters
----------
self.output : list
List with every line of output as a item.
"""
for line in self.output:
print(line)
#-------------------------------------------------------------------------------
def writeoutput(self):
"""Write to file.
Writes every item of self.output to a file.
Parameters
----------
self.output : list
List with every line of output as a item.
Raises
------
Exits if output directory is not writable.
"""
try:
with open(self.file, "w") as iswritable:
for line in self.output:
iswritable.write(line + "\n")
except IOError:
sys.stderr.write("Error: output directory is not writable!\n")
sys.exit(7)
#-------------------------------------------------------------------------------
# This is a private method for usage in this class only.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _processvbr(self):
"""Process FAT12/FAT16 VBR.
Read, translate and calculate needed information out of the vbr and
write it into single attributes.
"""
# We have already checked if we are able to read the image.
with open(self.image, "rb") as image:
image.seek(self.offset + 11)
raw = image.read(2 + 1 + 2 + 1 + 2)
parts = struct.unpack_from("<HBHBH", raw)
bytesPerSector = parts[0]
sectorsPerCluster = parts[1]
reservedSectors = parts[2]
fatCopies = parts[3]
rootDirectoryEntries = parts[4]
image.seek(3, 1)
sectorsPerFat = struct.unpack_from("<H", image.read(2))[0]
self.StartOfFAT0 = reservedSectors * bytesPerSector
self.StartOfFAT1 = self.StartOfFAT0 + sectorsPerFat * bytesPerSector
# In theory there could be more than two FATs
# but I know nobody who has seen more of them in real!
self.firstRootDirectoryEntryLocation = ((reservedSectors + fatCopies * sectorsPerFat) * bytesPerSector) + 32
self.startOfClusterArea = ((reservedSectors + fatCopies * sectorsPerFat) * bytesPerSector) + (rootDirectoryEntries * 32)
self.bytesPerCluster = bytesPerSector * sectorsPerCluster
#-------------------------------------------------------------------------------
def _calculatedate(unsignedShort):
# TODO:
# candidate for external use?
# add test for unignedShort
# add comment
year = 1980 + ((0b1111111000000000 & unsignedShort) >> 9)
month = "{:02}".format((0b0000000111100000 & unsignedShort) >> 5)
day = "{:02}".format(0b0000000000011111 & unsignedShort)
return (year, month, day)
#-------------------------------------------------------------------------------
def _calculatetime(unsignedShort):
# TODO:
# candidate for external use?
# add test for unignedShort
# add comment
hours = "{:02}".format((0b1111100000000000 & unsignedShort) >> 11)
minutes = "{:02}".format((0b0000011111100000 & unsignedShort) >> 5)
seconds = "{:02}".format((0b0000000000011111 & unsignedShort) * 2)
return (hours, minutes, seconds)
#-------------------------------------------------------------------------------
# This is a private method for usage in this class only.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _readfiles(self):
"""Loop over directories and files.
Loop over all directories and add each file with SFN and optionally
LFN to the list (self.outout).
TODO
----
1. Move subloops to separate methods!?
"""
directoryOffsets = [self.offset + self.firstRootDirectoryEntryLocation]
directories = {self.offset + self.firstRootDirectoryEntryLocation: "/"}
_id = 0
longFileName = ""
# We have already checked if we are able to read the image.
with open(self.image, "rb") as image:
for directoryOffset in directoryOffsets:
fileOffset = directoryOffset
for entry in range(int(self.bytesPerCluster / 32)):
image.seek(fileOffset)
filename = image.read(8)
# skip . or ..:
if re.search(b"^\x2e\x20{7}|\x2e{2}\x20{6}", filename):
fileOffset = fileOffset + 32
continue
# if unused:
elif re.search(b"^\x00", filename):
break
# if deleted:
elif re.search(b"^\xe5", filename):
filename = b"\x3f" + filename[1:] # deleted (sigma) to ?
allocated = "deleted"
else:
# if the filename starts with "sigma":
if re.search(b"^\x05", filename):
filename = b"\xe5" + filename[1:]
allocated = "allocated"
filenameExtension = image.read(3)
fileAttributes = struct.unpack_from("<B", image.read(1))[0]
# if we have a LFN:
if fileAttributes == 15:
cache = b""
image.seek(fileOffset + 1)
for step in range(5):
cache = cache + struct.pack(">H", struct.unpack_from("<H", image.read(2))[0])
image.seek(3, 1)
for step in range(6):
cache = cache + struct.pack(">H", struct.unpack_from("<H", image.read(2))[0])
image.seek(2, 1)
for step in range(2):
cache = cache + struct.pack(">H", struct.unpack_from("<H", image.read(2))[0])
cache = re.sub(b"\x00\x00|\xff\xff", b"", cache) # end and unused
cache = re.sub(b"^\x03\xc3", b"\x00\x3f", cache) # deleted to ?
cache = re.sub(b"\x00", b"", cache) # delete unneeded zerobytes (ugly hack?)
longFileName = cache.decode("utf-8", "ignore") + longFileName # ignore undecodable codes
fileOffset = fileOffset + 32
continue
filename = re.sub(" *$", "", filename.decode("cp437")) # remove spaces at the end
filenameExtension = filenameExtension.decode("cp437")
if not re.search(r'^ *$', filenameExtension):
filename = filename + '.' + filenameExtension # add . and ext only if ext not empty
image.seek(2, 1)
raw = image.read(2 + 2 + 2)
parts = struct.unpack_from("<HHH", raw)
(createdHours, createdMinutes, createdSeconds) = Fatlister._calculatetime(parts[0])
(createdYear, createdMonth, createdDay) = Fatlister._calculatedate(parts[1])
(accessedYear, accessedMonth, accessedDay) = Fatlister._calculatedate(parts[2])
image.seek(2, 1)
raw = image.read(2 + 2 + 2 + 4)
parts = struct.unpack_from("<HHHI", raw)
(modifiedHours, modifiedMinutes, modifiedSeconds) = Fatlister._calculatetime(parts[0])
(modifiedYear, modifiedMonth, modifiedDay) = Fatlister._calculatedate(parts[1])
startingCluster = parts[2]
# if we have a directory:
if fileAttributes == 16:
longFileName = ""
clusterOffset = startingCluster
while True:
# just a ugly hack to avoid multiple rounds with the same directoryOffset! :-/
if not self.startOfClusterArea + ((clusterOffset - 2) * self.bytesPerCluster) in directoryOffsets:
directoryOffsets.append(self.startOfClusterArea + ((clusterOffset - 2) * self.bytesPerCluster))
directories[self.startOfClusterArea + ((clusterOffset - 2) * self.bytesPerCluster)] = directories[directoryOffset] + filename + "/"
nextCluster = self.offset + self.StartOfFAT0 + 4 + (clusterOffset * 2)
image.seek(nextCluster)
raw = image.read(2)
clusterOffset = struct.unpack_from("<H", raw)[0]
if clusterOffset < 2 or clusterOffset > 65526:
break
fileOffset = fileOffset + 32
continue
fileSize = parts[3]
self.output.append('"' + str(_id) + '", ' \
+ '"' + directories[directoryOffset] + '", ' \
+ '"' + filename + '", ' \
+ '"' + longFileName + '", ' \
+ '"' + allocated + '", ' \
+ '"' + str(fileSize) + '", ' \
+ '"' + str(accessedYear) + '-' + str(accessedMonth) + '-' + str(accessedDay) + '", ' \
+ '"' + str(modifiedYear) + '-' + str(modifiedMonth) + '-' + str(modifiedDay) + 'T' + str(modifiedHours) + ':' + str(modifiedMinutes) + ':' + str(modifiedSeconds) + '", ' \
+ '"' + str(createdYear) + '-' + str(createdMonth) + '-' + str(createdDay) + 'T' + str(createdHours) + ':' + str(createdMinutes) + ':' + str(createdSeconds) + '", ' \
+ '"' + str(startingCluster) + '"')
# if we don't have a LFN:
if not fileAttributes == 15:
longFileName = ""
_id = _id + 1
fileOffset = fileOffset + 32
#=== FUNCTIONS =================================================================
# This is a private module function only for the other module functions.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this module. :-(
# sphinx-apidoc does ignore it. :-)
def _getargs():
"""Get command line arguments.
Parses the command line arguments and return them.
(Don't forget to check them in the next steps?)
Returns
-------
tuple
A tuple containing the to the image file,
the offset in bytes in the image file calculated from sectors
and the output file.
The default offset is 0.
For example:
( "image.dd", 2048, "output.csv" )
Raises
------
Exits if argparse detects an error.
"""
parser = argparse.ArgumentParser()
parser.add_argument("image",
type=str,
help="raw image file (esp.: image.dd)")
parser.add_argument("-o",
"--offset",
type=int,
default=0,
help="offset in sectors (default=0)")
parser.add_argument("-f",
"--file",
type=str,
default="",
help='output file (default="")')
args = parser.parse_args()
return (args.image, args.offset * 512, args.file)
#-------------------------------------------------------------------------------
# This is a private module function only for the other module functions.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this class. :-(
# sphinx-apidoc does ignore it. :-)
def _checkfile(_file):
"""Check output file.
Check if the output file is not existing and the target directory is writable.
Parameters
----------
_file : str
path to the output file.
Raises
------
Exits if the image does not exist or is not readable.
"""
if os.path.isfile(_file):
sys.stderr.write("Error: output file already exist!\n")
sys.exit(6)
# Check write permissions if we try to write to the file the first time!
#=== MAIN ======================================================================
if __name__ == '__main__':
(IMAGE, OFFSET, FILE) = _getargs()
OBJECT = Fatlister(IMAGE, OFFSET)
if not FILE:
OBJECT.printoutput()
else:
_checkfile(FILE)
OBJECT.file = FILE
OBJECT.writeoutput()
sys.exit(0)

140
fatlister_wrapper.py Executable file
View File

@ -0,0 +1,140 @@
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
"""List file and directory names in a disk image."""
#===============================================================================
#
# FILE:
# ./fatlister_wrapper.py
#
# BASIC USAGE:
# $ ./fatlister_wrapper.py [-h|--help] [-o|--offset OFFSET] [-f|--file FILENAME] image
# OR
# $ python fatlister_wrapper.py [-h|--help] [-o|--offset OFFSET] [-f|--file FILENAME] image
#
# OPTIONS:
# -h,
# --help show help message and exit
# -o OFFSET,
# --offset OFFSET offset in sectors (default=0)
# -f FILENAME, write output to file (default=unset)
# --file FILENAME if unset output goes to stdout
# image raw image file (esp. dd)
#
# EXIT STATES:
# 0 = success
# 1 = Python version not tested/supported
# 2 = image file does not exist
# 33 = file is not readable
# 3 = offset is not a positive integer
# 22 = output file already exist
# 23 = output directory is not writable
# 4 = wrong or missing data in dictionary
# 5 = empty image file
# 6 = image file smaller than offset
# 7 = invalid vbr signatures
#
# REQUIREMENTS:
# python2.7
#
# NOTES:
# Tested on:
# - ArchLinux (64-Bit) + python 2.7.13
# - Raspbian GNU/Linux 8.0 (32-Bit) + python 2.7.9
# - macOS (10.12.3) + python 2.7.10
# - Bash on Ubuntu on Windows 10 (64-Bit) + python 2.7.6
# with:
# - raw images
# - filesystem(s) in partition(s)
# - filesystem without a partition
# - no partition/no filesystem (empty file)
# - invalid filesystem
# - FAT12, FAT16 and FAT32
#
# WARRANTY:
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See the LICENSE file for more details.
#
# HISTORY:
# See the CHANGES file for more details.
#
#===============================================================================
#=== MODULES ===================================================================
import argparse
import sys
import fatlister
#=== INFO ======================================================================
"""@author: Patrick Neumann
@contact: patrick@neumannsland.de
@copyright: Copyright (C) 2017, Patrick Neumann
@license: GNU General Public License 3.0
@date: 2017-05-08
@version: 1.0.0
@status: Development
"""
#=== CHECKS ====================================================================
"""Only tested with Python versions 3.6.x!"""
if sys.version_info < (3, 6, 0):
sys.stderr.write("Sorry, your Python version was not tested but may work?\n")
sys.exit(1)
#=== FUNCTIONS =================================================================
# This is a private module function only for the other module functions.
# Unfortunately, the underscore does not prevent other developers from using
# it directly from outside this module. :-(
# sphinx-apidoc does ignore it. :-)
def _getargs():
"""Get command line arguments.
Parses the command line arguments and return them.
(Don't forget to check them in the next steps?)
Returns
-------
tuple
A tuple containing the to the image file,
the offset in bytes in the image file calculated from sectors
and the output file.
The default offset is 0.
For example:
( "image.dd", 1048576, "/dev/stdout" )
"""
parser = argparse.ArgumentParser()
parser.add_argument("image",
type=str,
help="raw image file (esp.: image.dd)")
parser.add_argument("-o",
"--offset",
type=int,
default=0,
help="offset in sectors (default=0)")
parser.add_argument("-f",
"--file",
type=str,
default="",
help="output file (default=/dev/stdout)")
args = parser.parse_args()
return (args.image, args.offset * 512, args.file)
#=== MAIN ======================================================================
if __name__ == '__main__':
(IMAGE, OFFSET, FILE) = _getargs()
OBJECT = fatlister.Fatlister(IMAGE, OFFSET, FILE)
sys.exit(0)

BIN
images/cf8mbwin.dmg Executable file

Binary file not shown.

0
images/empty.dd Executable file
View File

BIN
images/fat16.dd Executable file

Binary file not shown.

65
images/generate_fat16_image Executable file
View File

@ -0,0 +1,65 @@
#!/usr/bin/env bash
fallocate -l 32M fat16.dd
mkfs.vfat -F 16 -s 2 -n "IMG_4_A2" fat16.dd
mkdir fat16.loop
mount -o loop fat16.dd fat16.loop
cd fat16.loop
echo "Short file name." > SFN.TXT
echo "Short file name with a leading sigma." > X_SIGMA.TXT
echo "Short file name that will be deleted soon." > DELSFN.TXT
echo "Long file name." > Long_file_name.txt
echo "Long file name with spaces." > "LFN with spaces.txt"
echo "Long file name that will be deleted soon." > Del_long_file_name.txt
dd if=/dev/urandom of=BIGFILE.BIN bs=1024 count=1024
mkdir SDN
cd SDN
mkdir SSUBDN
cd SSUBDN
echo "Another short file name." > SFN2.TXT
cd ../..
mkdir Long_directory_name
cd Long_directory_name
mkdir Long_subdirectory_name
cd Long_subdirectory_name
echo "Another long file name." > Long_file_name2.txt
cd ../..
mkdir BIGDIR
cd BIGDIR
for id in {01..30} ; do
echo "I am in the first cluster of the directory." > FILE${id}.TXT
done
echo "I am in the second cluster of the directory." > FILE31.TXT
cd ..
rm DELSFN.TXT
rm Del_long_file_name.txt
cd ..
umount fat16.loop
rmdir fat16.loop
chmod 444 fat16.dd
echo
echo "Do not forget to change the X in X_SIGMA.TXT to \x05 with a hex editor!"
echo
exit 0

BIN
images/invalid.dd Executable file

Binary file not shown.