[GNU Manual] [No POSIX requirement] [Linux man] [FreeBSD man]
Summary
truncate - shrink or extend the size of a file
Lines of code: 400
Principal syscalls: ftruncate()
Support syscalls: fstat()
Options: 10 (4 short, 6 long)
Added to Coreutils in June 2008 [First version]
Number of revisions: 53 [Code Evolution]
The truncate utility is primarily a wrapper for the ftruncate()
syscall with extra features and input checking
do_ftruncate()
- Computes required sizes and invokesftruncate()
for a single target. Returns success/fail
Setup
truncate sets up a few important types and flags before executing. First, there is a rel_mode_t
enum used to hold the logical size relations (less than, at most, etc). Global flags include:
block_mode
- Flag to prevent file creation (-c option)no_create
- Flag to trigger block mode instead of byte mode (-o option)ref_file
- Holds the name of the reference file provided by -r
main()
initializes a few local variables needed for parsing and execution.
c
- The first character of the next option to processerrors
- Flag to hold return status ofdo_ftruncate
fd
- The file descriptor for the target filefname
- The name of the target filegot_size
- Flag if the desired file size is knownoflags
- Access permissions for the target filerel_mode
- The sizing mode to applyrsize
- The reference file sizesize
- The target size input by the user
Parsing
Parsing truncate is typical of most coreutils with exception of the --size option. Parsing answers the following questions:
- Should we create the target if it doesn't exist?
- Are we handling blocks or bytes?
- Is there a reference file to use for sizing
- What is the size of the target file?
The --size option needs extra processing to support both relative comparisons (<,<=, etc) and basis multiples (kilo,mega,giga, etc). This requires extra steps in checking for white space and relation symbols. Multiples are handled by the xdectoimax()
macro
The relation rules require more sanity checks than most other coreutils
Parsing failures
These failure cases are explicitly checked:
- Specifying more than one relative modifier
- Specifying an invalid or unparsable size
- Rounding to a size of 0
- Not including a size or a reference file
- Not using a relative size with a reference file
- Using block mode without a size
- Not specifying a target file
Execution
truncate follows this logic:
- Get the desired size from a reference file (if provided)
- Set access flags: Non-blocking, write-only with possible creation
- For open each target file and...
- Get the currrent file size
- Compute change required to meet the desired size, converting blocks to bytes as needed)
- Read from input to the input buffer
- Invoke the
ftruncate()
syscall - Close the file
- Repeat above for all targets
Execution could fail in several ways:
Failure cases:
- Unable to open or close target file
- Unable to
fstat()
target - File size conversion is too large
- Unable to size reference file
- Unable to round or extend file due to overflow
ftruncate()
fails for any reason