rem: r_full++;
add: { r_full++; partread = 0; }
context: dd_copy (void){  char *ibuf, *bufstart;	/* Input buffer. */  char *real_buf;		/* real buffer address before alignment */  char *real_obuf;  size_t nread;			/* Bytes read in the current block. */  int exit_status = 0;  size_t page_size = getpagesize ();  size_t n_bytes_read;  /* Leave at least one extra byte at the beginning and end of `ibuf'     for conv=swab, but keep the buffer address even.  But some peculiar     device drivers work only with word-aligned buffers, so leave an     extra two bytes.  */  /* Some devices require alignment on a sector or page boundary     (e.g. character disk devices).  Align the input buffer to a     page boundary to cover all bases.  Note that due to the swab     algorithm, we must have at least one byte in the page before     the input buffer;  thus we allocate 2 pages of slop in the     real buffer.  8k above the blocksize shouldn't bother anyone.     The page alignment is necessary on any linux system that supports     either the SGI raw I/O patch or Steven Tweedies raw I/O patch.     It is necessary when accessing raw (i.e. character special) disk     devices on Unixware or other SVR4-derived system.  */  real_buf = xmalloc (input_blocksize		      + 2 * SWAB_ALIGN_OFFSET		      + 2 * page_size - 1);  ibuf = real_buf;  ibuf += SWAB_ALIGN_OFFSET;	/* allow space for swab */  ibuf = PTR_ALIGN (ibuf, page_size);  if (conversions_mask & C_TWOBUFS)    {      /* Page-align the output buffer, too.  */      real_obuf = xmalloc (output_blocksize + page_size - 1);      obuf = PTR_ALIGN (real_obuf, page_size);    }  else    {      real_obuf = NULL;      obuf = ibuf;    }  if (skip_records != 0)    skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);  if (seek_records != 0)    {      /* FIXME: this loses for	 % ./dd if=dd seek=1 |:	 ./dd: standard output: Bad file descriptor	 0+0 records in	 0+0 records out	 */      skip (STDOUT_FILENO, output_file, seek_records, output_blocksize, obuf);    }  if (max_records == 0)    quit (exit_status);  while (1)    {      if (r_partial + r_full >= max_records)	break;      /* Zero the buffer before reading, so that if we get a read error,	 whatever data we are able to read is followed by zeros.	 This minimizes data loss. */      if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))	memset (ibuf,		(conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',		input_blocksize);      nread = safe_read (STDIN_FILENO, ibuf, input_blocksize);      if (nread == 0)	break;			/* EOF.  */      if (nread == SAFE_READ_ERROR)	{	  error (0, errno, _("reading %s"), quote (input_file));	  if (conversions_mask & C_NOERROR)	    {	      print_stats ();	      /* Seek past the bad block if possible. */	      lseek (STDIN_FILENO, (off_t) input_blocksize, SEEK_CUR);	      if (conversions_mask & C_SYNC)		/* Replace the missing input with null bytes and		   proceed normally.  */		nread = 0;	      else		continue;	    }	  else	    {	      /* Write any partial block. */	      exit_status = 2;	      break;	    }	}      n_bytes_read = nread;      if (n_bytes_read < input_blocksize)	{	  r_partial++;	  if (conversions_mask & C_SYNC)	    {	      if (!(conversions_mask & C_NOERROR))		/* If C_NOERROR, we zeroed the block before reading. */		memset (ibuf + n_bytes_read,			(conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',			input_blocksize - n_bytes_read);	      n_bytes_read = input_blocksize;	    }	}      else	r_full++;      if (ibuf == obuf)		/* If not C_TWOBUFS. */	{	  size_t nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);	  if (nwritten != n_bytes_read)	    {	      error (0, errno, _("writing %s"), quote (output_file));	      quit (1);	    }	  else if (n_bytes_read == input_blocksize)	    w_full++;	  else	    w_partial++;	  continue;	}      /* Do any translations on the whole buffer at once.  */      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);    }  if ((conversions_mask & C_BLOCK) && col > 0)    {      /* If the final input line didn't end with a '\n', pad	 the output block to `conversion_blocksize' chars.  */      size_t i;      for (i = col; i < conversion_blocksize; i++)	output_char (space_character);    }  if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)    /* Add a final '\n' if there are exactly `conversion_blocksize'       characters in the final record. */    output_char (newline_character);  /* Write out the last block. */  if (oc != 0)    {      size_t nwritten = full_write (STDOUT_FILENO, obuf, oc);      if (nwritten != 0)	w_partial++;      if (nwritten != oc)	{	  error (0, errno, _("writing %s"), quote (output_file));	  quit (1);	}    }  free (real_buf);  if (real_obuf)    free (real_obuf);  return exit_status;}