ddコマンドソースコード・リーディング
(dd.c)
|c| int main (int argc, char **argv) { int i; int exit_status; off_t offset;
install_signal_handlers ();
initialize_main (&argc, &argv); set_program_name (argv[0]); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE);
/* Arrange to close stdout if parse_long_options exits. */ atexit (maybe_close_stdout);
page_size = getpagesize ();
parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version, usage, AUTHORS, (char const *) NULL); close_stdout_required = false;
if (getopt_long (argc, argv, "", NULL, NULL) != -1) usage (EXIT_FAILURE);
/* Initialize translation table to identity translation. */ for (i = 0; i < 256; i++) trans_table[i] = i;
/* Decode arguments. /
scanargs (argc, argv); []
...
if (input_file == NULL)
{
input_file = _("standard input"); []
set_fd_flags (STDIN_FILENO, input_flags, input_file);
}
...
if (output_file == NULL)
{
output_file = _("standard output"); []
set_fd_flags (STDOUT_FILENO, output_flags, output_file);
}
else
{
/* Open the output file with read access only if we might
need to read to satisfy a 'seek=' request. If we can't read
the file, go ahead with write-only access; it might work. /
if ((! seek_records
|| fd_reopen (STDOUT_FILENO, output_file, O_RDWR | opts, perms) < 0)
&& (fd_reopen (STDOUT_FILENO, output_file, O_WRONLY | opts, perms) []
< 0))
error (EXIT_FAILURE, errno, _("failed to open %s"),
quote (output_file));
if (seek_records != 0 && !(conversions_mask & C_NOTRUNC))
{
uintmax_t size = seek_records * output_blocksize + seek_bytes;
if (ftruncate (STDOUT_FILENO, size) != 0) []
{
...
}
}
}
}
exit_status = dd_copy (); []
||<
[]で指定されたオプションの解析を行います。
[],[]では入出力ファイルがオプションで指定されていない場合、標準入出力に切り替えています。
もし出力ファイルが指定されていてかつ-seekが指定されている場合、出力ファイルを一旦[]でread onlyで開いた後、[]でftruncateを実行してseekされた分ファイルのサイズ変更している。
[]のdd_copyがファイルコンバートのメイン処理である。
(dd.c)
|c| static int dd_copy (void) { alloc_ibuf (); alloc_obuf (); while (1) { ... if (translation_needed) translate_buffer (ibuf, n_bytes_read); [*]
if (conversions_mask & C_SWAB)
bufstart = swab_buffer (ibuf, &n_bytes_read); [*]
else
bufstart = ibuf;
if (conversions_mask & C_BLOCK)
copy_with_block (bufstart, n_bytes_read); [*]
else if (conversions_mask & C_UNBLOCK)
copy_with_unblock (bufstart, n_bytes_read); [*]
else
copy_simple (bufstart, n_bytes_read); [*]
} /* If we have a char left as a result of conv=swab, output it. / if (char_is_saved) [] { if (conversions_mask & C_BLOCK) copy_with_block (&saved_char, 1); else if (conversions_mask & C_UNBLOCK) copy_with_unblock (&saved_char, 1); else output_char (saved_char); } ||< [],[],[],[]ではそれぞれconvオプションに(ascii|ebcdic,ibm)変換、swab,block,unblockを指定した場合に、中間bufをそれぞれ変換してobufに出力する処理である。 []は何も指定されていない場合にそのままobufに出力する。 また[]のsaved_charはswabによって奇数文字数の文字を処理した際の一番最後のまだ書き出されていない1文字を格納している。(奇数でこの処理をするのはGNU dd独自らしい)