FATTOOL

NAME
SYNOPSIS
DESCRIPTION
OPTIONS
COMMANDS
FILE NAMES
SIMULATED ERRORS
SEE ALSO

NAME

fattool − several operations on a FAT12/16/32 filesystem

SYNOPSIS

fattool

[-f num] [-l] [-i] [-s] [-n]

[-m] [-c] [-o offset] [-e simerr.txt]
filesystem command args

DESCRIPTION

Perform a number of low-level operations on a FAT filesystem: print some data about them, fix some errors, move clusters, etc.

OPTIONS

-f num

use the specified file allocation table for both reading and writing; usually, num can only be either 0 or 1; the default is to read from the first table that can be read and to write to all (this behavior cannot be specified with -f)

-l

begin by reading the whole first FAT, and exit if that fails; without this option, the program may start making some changes and then have to stop in the middle because a sector in the file allocation table cannot be read

-i

make file lookup case-insensitive; this allows for example to refer to a file with a short name only like EXAMPLE.TXT by the name example.txt

-s

use shortnames instead of long names; this affects both lookups and file creations; beware that ‘~’ may be special to the shell, so use quotes around short names, like:

	\fIfattool /dev/sda1 gettime '/ADIR/SOMENA~1.TXT'\fP

-n

use file names passed to the program without checking their validity and converting them; this allows creating and accessing files with invalid names, and enables the use of CLUSTER:num and cluster:num (se FILE NAMES, below)

-m

show memory usage after closing the filesystem; this is intended for testing memory leaks; it could also be done before closing the filesystem, but it would not tell much since FAT sectors are never deleted from cache

-c

dump the cluster cache at the end of the operation; this is only useful during testing to check whether clusters are correctly deallocated

-o offset

the filesystem is assumed to start at this offset in the device

-e simerr.txt

read simulated errors from file; see SIMULATED ERRORS, below

COMMANDS

summary

print a summary of the filesystem data, such as the number of clusters, etc.

free/used/clusters

print a map of the clusters that tells which are free and which are used

view [path [all]]

recusively show the content of a file or directory, by default ’/’ (see FILE NAMES, below); for directories, each entry is shown on a line; for files, its sequence of cluster numbers is printed; argument "all" makes long name parts to be printed, and if also -s is given then also the deleted directory entries are shown

calls [all]

print the arguments of the calls fatreferenceexecute() performs on the filesystem; this is mainly for helping in development; with argument "all", also deleted entries and long filename parts are shown

fixdot

fix the dot and dotdot files, so that . points to the current directory and .. to its parent

compact

move used clusters at the beginning of the filesystem, in place of the free ones; this is not defragmenting, which also makes the cluster to each file consecutive

defragment

order all clusters in the filesystem so that the root directory is in the first clusters in order, followed by its first entry, etc.; is the same as fattool linear / recur 2; this operation is dangerous: if the program at some point cannot allocate enough memory, the filesystem is left with some clusters moved but the file allocation tables not updated; running fatbackup before is of no use

last [n]

set the last known free cluster indicator on a FAT32 to n; makes the following search for free clusters start at cluster n, by default the first cluster in the filesystem; this is a no-op on FAT12 and FAT16

recompute

count the free clusters in the filesystem; also save this number if the filesystem is FAT32

header

restore the first two entries in all file allocation tables; this allows to run dosfsck(8) on a filesystem that has the boot sector as its only undamaged part

zero

reset the filesystem to its original state; all content is lost

this function deallocates all clusters except the first of the root directory, which is reset to 2 if the filesystem is a FAT32 and re-initalized (filled with zeros); it is useful to avoid reformatting a filesystem that is badly corrupted

unused

mark as unused all unused clusters that are erroneously marked used

delete file

remove a file or directory (see FILE NAMES, below) without reclaiming its clusters; useful if the file or directory is corrupted: its directory entry is marked deleted and nothing else is done; the clusters of files deleted this way can be later reclaimed by fattool filesystem unused or reattached to some other file via fattool filesystem setfirst ... or fattool filesystem setnext ...

link target new

create an hard link; the target is an existing file or directory (see FILE NAMES, below); the new file file will be created with the same attributes and first cluster of the first, so that it looks like a copy of the first

the resulting filesystem is incorrect and does not work for every driver; furthermore, the size of the new file is correct upon creation but is not updated if the source is changed; if the target is a directory and the new file is in different directory, its dotdot file is incorrect

deleting any of the two files with anythigh other than "fattol filesystem delete" makes the resulting filesystem incorrect

this command can be used to recreate the . and .. entries in directories (the warning about the resulting filesystem not being correct can then be ignored), like for example:

	fattool filename link AAA/CCC AAA/CCC/.
	fattool filename link AAA AAA/CCC/..

position (n|sector:s|file:name) [file|bvi|recur]

print the position of cluster n in the filesystem; with argument file, also print the name of the file this cluster belongs to (if any) and its chain of clusters; with argument bvi, call bvi(1) to edit the cluster

if the first argument is given in the form sector:s, the cluster is the one containing sector s, if any; otherwise, print whether the sector is reserved or in which file allocation table

the form file:name is for printing the position of all clusters in the file; if the file is a directory and the second argument is recur, also the position of all clusters in all subdirectories and files are printed

read n

dump the content of cluster n

hex n

dump the content of cluster n in hex form

write n [part] [read]

write stdin to cluster n; without any other option, do not write unless enough data to fill a complete cluster is read; option "part" allows writing a partial cluster, with the rest filled with random data; option "read" is similar, but the cluster is first read and then its initial part overwritten with data coming from stdin

getnext n

print the number of the cluster that follows n; may also be EOF, UNUSED or BAD

setnext n m

set the cluster that follows n to be m; other than a cluster number, m may be EOF, UNUSED, BAD

getfirst file

show the first cluster of a file (see FILE NAMES, below)

setfirst file n

set the first cluster of a file to be n (see FILE NAMES, below)

sparse [noread]

fill all unused clusters with zero; this is useful for preparing a filesystem image for sparsification (e.g., cp --sparse=always image newimage); it is not a security wipe because a. clusters are not repeatedly filled with random bytes and b. unused directory entries are not cleared; normally, clusters that are already zero are not overwritten, but noread makes clusters not to be read but just zeroed; this may speed up execution if many clusters are not zero

linear file [recur] [check|test|start|min|free|n]

makes the clusters of file consecutive (see FILE NAMES, below); option recur only matters for directories, making consecutive the clusters of all files and subdirectories; options test and check are equivalent: the operation is not performed, but the number of clusters that would be moved is calculated (if zero, the file or directory is already linear); the other options specify where clusters are moved:

start

starting from where the file originally starts

min

chosen to minimize the number of cluster movements

free

the area free of bad clusters with the maximal number of unused clusters; in most but not all cases, this minimizes the movements of the clusters of the other files

n

the new starting cluster of the file will be n

in all cases, the operation fails if the some of the resulting clusters are bad or outside the filesystem

the default is to try "start", and if that fails try "free"

bad n [m]

mark cluster n as bad, or all clusters between n and m if m is given; if some of them are currently allocated a warning is displayed; if the operation is performed anyway, the resulting filesystem is incorrect; the "hole" operation instead attempts to move the clusters in the area out to free locations

hole (n m|size l)

create an hole of clusters marked bad; the content of the filesystem is not changed: clusters previously in this area are moved outside, and the operation fails if the number of free clusters is insufficient; the area can be specified in two forms:

n m

the area is between cluster n and cluster m

size l

the program looks for the area of size l that contains a minimal number of allocated clusters

 

cutbad

cut the chains of clusters at the ones marked bad (the bad cluster itself is cut out from the chain); if a bad cluster is found in a chain a whole-volume search for unused clusters is then performed to reclaim the clusters that originally followed the bad one in the chain

readfile file [chain]

print the content of file to stdout (see FILE NAMES, below); if "chain" is given, the entire cluster chain is printed, including the data that is over the file size; this allows printing a directory as if it were a regular file; this is done anyway if file is in the form cluster:num

writefile file

copy stdin to file

deletefile file

delete the given file (see FILE NAMES, below)

overwrite file [immediate|test]

write stdin to an existing file; no cluster is deleted or appended to the chain; clusters that already identical to their new content are not written; this command is intended for re-writing a file whose content is corrupted; the argument immediate makes writing to happen immediately, but the default is actually write the clusters only at the end; argument test makes the program run doing everything but writing

getsize file

print the size of an existing file

setsize file num

make the file to be large num bytes; the resulting filesystem is incorrect if the new size it too small or too large for the chain of clusters of the file

directoryclean [test]

delete the directory clusters that only contain deleted entries; also zero all entries following the last that is actually used; this also clean directory entries that over an "end-of-directory" entry, which may cause problems to some implementations (e.g., msdos.ko); with option test, only print what would be done without actually changing anything

countclusters file [recur]

count the clusters a file takes; can be called on a directory, in which case it only counts the clusters taken by the directory itself; the additional parameter "recur" makes the count include all files and subdirectories

filldeleted directory

fill the unused entries in a directory with deleted files entries; this is part of creating cyclic directories

gettime file [write|create|read]

get the date and time of a file; depending on the second argument, the date and time of the last write (default), the date and time of creation or the date of the last read (the time of last read is not recorded in the filesystem)

settime file (write|create|read) (date|now)

set the date and time of a file; depending on the second argument, the date and time of the last write, the date and time of the last read or the date of the last read; date and time are parsed by strptime(3) with format "%Y-%m-%d %H:%M"; time is required even when setting the date of the last read, where the time is not recorded in the filesystem; the current time/date is used if the last argument is "now"

inverse

check whether an inverse FAT for this filesystem can be created; this is not possible if some directory clusters cannot be read due to IO errors, or memory is insufficient for holding the entire inverse FAT and all directory clusters

dirty [[UNCLEAN][,][IOERROR]|NONE]

show, set or clean the dirty bits in the filesystem

dotcase

clean the case byte in the directory entries of the dot (.) and dotdot (..) files; mtools(1) may set these to something different than zero, causing dosfsck(8) not to recognize them and to signal their names as erroneous

dir [directory [start|all|over]]

list the entries in the given directory; if start is also given, the start point of each long file name is also printed; with option -s, long part names are printed individually, deleted entries are also printed with all and entries over the end of the directory with over

valid path

check whether path is a valid path (the filesystem argument is irrelevant to this operation)

dirfind [num]

try to detect which clusters are used for directories; the intended usage is to attempt recovering files from a damaged filesystem: after finding the clusters that may be used for directories, these can be printed by fattool -n filesystem dir cluster:... and the files in them copied out by fattool -n filesystem readfile cluster:.../filename; this operation uses an heuristic score of clusters, so it may return both false positives and false negatives; if a number is also given, the score of that cluster is printed (this is inteded for testing the heuristic)

boot [sectorsize [sectors]]

Try to locate the boot sector. This is useful for images of partitioned devices and on partitioned devices where the master boot record is lost but the filesystem may still be there. The defaults for the size of sectors and the number of sectors tried are 512 and 10000, respectively. An estimate for each sector is printed, and the first of the best candidates is also printed at the end. If this number is for example 63, the filesystem may be then operated using fattool -o $((63 * 512)) ..., and may be mounted via losetup(8):

	modprobe loop
	losetup -o $((63 * 512)) /dev/loop0 devicename
	mount /dev/loop0 somedirectory

format (sectors|"") (sectorspercluster|"") (maxentries|"")

Create a filesystem or evaluate whether it can be created and how. The first parameter sectors is the number of sectors in the filesystem; if omitted or specified as "", it is derived from the size of the device or file and the offset; therefore, it is required if the device or file does not exist. The second parameter sectorspercluster is the size of each cluster, expressed in number of sectors; allowed values are the powers of two from 1 to 128; if omitted or specified as "", the program tests every allowed value and shows whether the filesystem could be created, and of which type, but does not actually create it. The third parameter maxentries is the maximal number of entries in the root directory; a value is allowed only if maxentries * 32 is a multiple of the sector size (512); default is 256; this value is silently ignored if the filesystem turns out to be a FAT32.

FILE NAMES

Files can be specified either as path or as a pair cluster,index.

The path is always relative to the root of the filesystem. The special form cluster:num at the beginning makes the operation relative to the directory of first cluster num. Since ‘:’ is invalid in a file name, this requires -n. This form can also be given as the file name for some operations (like reading a file, where the size is taken to be given by the length of the chain).

The pair cluster,index is number of cluster where the directory entry of the file is, and its progressive number within it. This specification can only be given for existing files and directories other than /. The root directory and a file to be created can only be specified by path.

SIMULATED ERRORS

Option -e simerr.txt allows simulating IO errors when seeking, reading and writing to the device. Each line of the file, unless empty or starting with #, represents an error that will be simulated by the library. For example:

READ 12
WRITE 5
READ|WRITE 37
SEEK 51

Every attempt to read cluster 12 results in an IO error, so does writing to cluster 5, accessing cluster 37 either way and seeking to cluster 51. Every line may have two further optional arguments: the first is 0 to mean sector (instead of cluster, the default 1); the second is -1 for simulating a failed operation and a number greater than 0 to simulate a short read or write.

This is intended only for testing the robustness of the programs and the library to IO errors. It is of no use outside this.

SEE ALSO

fatview(1), fatbackup(1), fatshrink(1), fat_lib(3)