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

Summary

mknod - make block or character special files

[Source] [Code Walkthrough]

Lines of code: 276
Principal syscall: mknod(), mkfifo() (BSD)
Support syscalls: fchmodat() via lchmod() for links
Options: 6 (2 short, 4 long)

Descended from mknod introduced in Version 6 UNIX (1975)
Added to Fileutils in October 1992 [First version]
Number of revisions: 143 [Code Evolution]

The mknod utility wraps the syscall of the same name. It may parse major/minor numbers and handle the security context.

Helpers:
  • None
External non-standard helpers:
  • defaultcon() - Gets the security context label of the input
  • die() - Exit with mandatory non-zero error and message to stderr
  • error() - Outputs error message to standard error with possible process termination
  • makedev() - Produces a device ID from a major and minor number
  • setfscreatecon() - Sets the context for a new filesystem object
  • smack_set_label_for_self() - Sets security label for the current process

Setup

mknod initializes local variables in main(), including:

  • newmode - A file mode in UGO format
  • *specified_mode - A file mode as input by the user
  • exit_status - Utility exit status (EXIT_*)
  • optc - The next option to process
  • *scontext - The user specified security context
  • set_security_context - Flag to check security context labels in SELinux

Parsing

Parsing mknod performs a bit more work than a typical utility because the user provides a more input than options and targets. This requires a more robust sanity checking phase than simply verifying options and boundaries. First, parsing collects options to answer questions, including:

  • What access mode is the named pipe?
  • Are there security considerations? (SELinux / Smack)

Parsing failures

These failure cases are explicitly checked:

  • Permission type is invalid
  • The operand counts must make sense:
    • Including a major and minor device number for a fifo
    • Not including a major and minor device number for a special file

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


Execution

The utility has some work to do to properly parse the input arguments in to a form usable by the mknod() syscall. The syscall has this prototype:

int mknod(const char *path, mode_t mode, dev_t dev);

While the user passes this to the utility:

mknod [option]… name type [major minor]

You can see the relationship between 'name', and the path. Combine that with the type and we can derive the mode (permissions). Finally the 'major' and 'minor' components lead to a 'dev'.

The mknod utility execution sequence looks like this:

  • If the user specified a security context, attempt to set the next context
  • For block and character devices:
    • Parse the major and minor numbers
    • Call makedev() (alias for gnu_dev_makedev() in libc) for a device_id
    • Set the security context
    • Call mknod() using the target, mode, and device
  • For Pipes/FIFOs:
    • Set the security context
    • Call mkfifo() using the target and mode
  • Return exit status (any failure forces EXIT_FAILURE)

mknod execution may fail in several cases:

  • Invalid major and minor numbers
  • Invalid device specified
  • makedev() or mknod() fails
  • Unable to set permissions
  • System specified special files not supported
  • Unable to set security context

[Back to Project Main Page]