Decoded: truncate (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [No POSIX requirement] [Linux man] [FreeBSD man]

Logical flow of truncate command (coreutils)

Summary

truncate - shrink or extend the size of a file

[Source] [Code Walkthrough]

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

Helpers:
  • do_ftruncate() - Computes required sizes and invokes ftruncate() 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 process
  • errors - Flag to hold return status of do_ftruncate
  • fd - The file descriptor for the target file
  • fname - The name of the target file
  • got_size - Flag if the desired file size is known
  • oflags - Access permissions for the target file
  • rel_mode - The sizing mode to apply
  • rsize - The reference file size
  • size - 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

[Back to Project Main Page]