Decoded: rm (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 rm command (coreutils)

Summary

rm - remove files or directories

[Source] [Code Walkthrough]

Lines of code: 374
Principal syscall: unlinkat() via gnulib FTS
Support syscalls: None
Options: 19 (7 short, 11 long)

Descended from rm introduced in Version 1 UNIX (1971)
Added to Fileutils in October 1992 [First version]
Number of revisions: 194

The rm utility seems deceptively simple because most of the work is pushed to gnulib, including the fts interface.

Helpers:
  • diagnose_leading_hyphen() - Verifies command line input consistency (files might begin with '-')
  • rm_option_init() - Initializes an rm_options struct
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
  • ngettext() - Processes text for native language support. (from gnulib adapted from the gettext in the GNU Translation Project
  • priv_set_remove_linkdir() - Remove ability to unlink directories (from gnulib)
  • rm() - Wrapped for removing a target using fts

Setup

rm uses several global enums to set behavior options. The most notable is interactive_type, which matches three type values to argments in interactive_types. The values are user responses to handling multiple matches such as 'never', 'once', or 'always' take an action.

main() defines four variables:

  • c - The first character of the next option to process
  • preserve_root - Flag if the utility should preserve root
  • prompt_once - Flag to ask the user for a decision one time
  • rm_options - Struct to hold options for rm (in remove.h)

Parsing

Parsing for rm needs at least one target. The options answer a list of questions about how to handle the targets.

  • Are we preserving root?
  • Are we operating recursively
  • Should we query the user for handling mulitple matches?
  • Should we ignore most problems and continue processing?
  • Only target one file system?

Parsing failures

These failure case is explicitly checked:

  • No target file provided
  • Unable to find root inode
  • Unknown option is used

Failure results in a short error message followed by the usage instructions.

Execution

Very little work is performed directly in rm setting options and behaviors. Control passes to procedures in remove.c

Basic execution looks like this

  • If multiple files are matched, prompt user for handling. (May exit succesfully here)
  • Pass the file and options to rm() (here)
  • Return the status of execution

Failure case:

Exeuction failures are tied closely to performance of the file traversal system. These include inability to open, close, read, or remove any files. The success status is returned back to rm


[Back to Project Main Page]