Decoded: base64 (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] [No FreeBSD support]

Logical flow of base64 command (coreutils)

Summary

base64 - transform data into printable data

[Source] [Code Walkthrough]

Lines of code: 351
Principal syscall: write() with buffering via fwrite()
Support syscalls: fadvise()
Options: 8 (3 short, 5 long)

Number of revisions: Unknown (utility has undergone several name changes recently to basenc.c)

base64 is an encoder/decoder which reads a block of input to a buffer, transforms it, and writes it out. The code in the source file is interchangable between base32 and base64 depending on macro definitions.

Helpers:
  • wrap_write() - Handles word wrap by inserting newlines when appropriate (-w option)
  • do_decode() - The decoder function wrapper for base64_decode_ctx() (in gnulib)
  • do_encode() - The encoder function wrapper for base64_encode() (in gnulib)
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
External macros:
  • BASE32_LENGTH - Determines the I/O buffer size base32 (from gnulib)
  • BASE64_LENGTH - Determines the I/O buffer size base64 (from gnulib)

  • Setup

    Preliminary checks to verify appropriate block sizes, for base64, this means checking that BLOCKSIZE is a multiple of 5 and 8. Buffers must be properly sized to include padding.

    Local variables defined in main() include:

    • decode - Flag to toggle encode/decode mode
    • ignore_garbage - Flag to ignore characters not part of base64 decoding
    • *infile - The input file name
    • *input_fh - The input file handle
    • optc - The next command line option to parse
    • wrap_column - The line length to wrap output

    Parsing

    Parsing base64 considers three questions:

    • Are we encoding or decoding (default encoding)?
    • How long are the lines before wrapping (default 76 chars)?
    • Should we ignore characters that aren't usually printed?

    Parsing failures

    These failure cases are explicitly checked:

    • Unusual line wrap sizes (negative, too large, etc)
    • More than one input provided

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


    Execution

    The utility reads source data into a buffer, transforms it to/from base64, then outputs the data. The transformation function is outsourced to gnulib, leaving the utility with managing data transfer in and out of the buffer. The process is this:

    • Open the input, either STDIN or target file
    • Call either the encode or decode procedure as requested:
    • Properly size the I/O buffers
    • Read in a block of data
    • Pass the I/O buffers to gnulib: (base64_encode() or base64_decode_ctx())
    • Repeat read and code until the input is finished
    • Close the input
    • Return success

    Failure may occur at mose points along the way. Completing execution implies successful execution

    Failure cases:

    • Unable to read or write to I/O files
    • Unable to open input file
    • Unable to close the input (file or STDIN)

    [Back to Project Main Page]