Decoded: touch (coreutils)

[Back to Project Main Page]

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

Logical flow of touch command (coreutils)

Summary

touch - change file timestamps

[Source] [Code Walkthrough]

Lines of code: 439
Principal syscalls: futimens() via fdutimensat(), open() via fd_reopen()
Support syscalls: close(), stat()
Options: 15 (8 short, 7 long)

Descended from touch introduced in Version 7 UNIX (1979)
Added to Fileutils in October 1992 [First version]
Number of revisions: 187

The primary work behind touch updates file timestamps, although it is often used to create empty files.

Helpers:
  • get_reldate() - Calculates a relative date between two input dates
  • touch() - Performs the touch procedure for one target file
External non-standard helpers:
  • die() - Exit with mandatory non-zero error and message to stderr
  • error() - Outputs error message to standard error with possible process termination
  • get_stat_atime() - Retrieves the access time from a stat structure
  • get_stat_mtime() - Retrieves the modified time from a stat structure
  • gettime() - Gets the system time in a timespec structure
  • posixtime() - Tests if an input date is a POSIX format (from gnulib)

Setup

touch declares several global flags that control execution flow and are defined during parsing:

  • amtime_now - Flag to change both access and modify times
  • change_times - Bitflag for access and modify times
  • newtime[] - Struct array for the access and modify times
  • no_create - Flag to skip file creation if it doesn't exist
  • no_dereference - Flag to prevent following links (update link time, not target time)
  • *ref_file - The path to the reference file
  • use_ref - Flag if a reference file is provided

touch initializes a few local variables in main(), including:

  • c - The first letter of the next option to process
  • date_set - Flag if a date is provided
  • *flex_date - Holds the time input by the user
  • ok - The final return status of the utility

Parsing

Parsing touch considers five questions:

  • Are we only interested in modified or access times?
  • Should we use an alternate timestamp?
  • Is there a reference file providing the timestamp?
  • Should we create non-existent files?
  • If touching a link, should we update the link or the target?

Parsing failures

These failure cases are explicitly checked:

  • Invalid date format
  • Using conflicting time source (reference file and a direct date)
  • Unknown options used

Failures result in a short error message followed by the usage instructions.


Execution

The touch begins by locating the desired times for the target time. This comes from three possible sources: A reference file, discovered via a stat() syscall. From the user directly as input on the cli. Or finally, from the current system time. The requested access/modified times are loaded in to the newtime structure.

Once the desired time is known and available in newtime[] structure, we 'touch' each target file with the requested time. The process is:

  • Open the target file -- this may create the file if it doesn't exist
  • Change the desired times, passing the target and behaviors to fdutimensat() in gnulib
  • Close the target file
  • Check errno and report issues
  • Repeat for the next target file

Failure cases:

  • No access to path or file
  • Cannot change times
  • Cannot close the file
  • No target files provided
  • stat() failed on the reference file

Failures at this stage output an error message to STDERR unless quiet mode was enabled


[Back to Project Main Page]