This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: dd in cygwin vs dd in linux - number of records is always different


On Feb  8 16:30, Morph Ex wrote:
> I'm trying to use "dd" to create a md5 checksum of a dvd.  The problem
> is that the number of records read by "dd" is always different
> depending on the OS used.  For example, using the same command below
> in both cygwin and linux displays the following results.
> 
> dd if=/dev/scd0 bs=2048 iflag=direct | md5sum -b
> 
> Linux (ubuntu 8.10 amd64)
> 28446caccede349759e4e9fed8bce862 
> 3025539+0 records in 
> 3025539+0 records out 
> 6196303872 bytes (6.2 GB) copied, 3347.83 s, 1.9 MB/s 
>  
> Cygwin (windows xp pro)
> 15cab8963c4746eca21c014224adefa3 
> 3025538+0 records in 
> 3025538+0 records out 
> 6196301824 bytes (6.2 GB) copied, 3323.91 s, 1.9 MB/s

Just to let you know that I can reproduce a similar result.  In my test
case it's just not 1 block but 200 blocks.  For some reason the Win32
function ReadFile returns EOF prematurely, in my case on XP as well as
on Server 2008, and I have not the faintest idea why.  I created a
non-Cygwin testcase (attached) which uses only native NT functions to
open/seek/read/close the device and it suffers the exact same problem.
Ii doesn't have anything to do with Cygwin, apparently.

If you want to experiment with the native NT testcase, you can build
it with

  $ gcc -g -o ntreadraw ntreadraw.c -lntdll

(with or without -mno-cygwin) and then you can run it like this:

  $ ./ntreadraw \\Device\\CdRom0 2048 3025530

The output for my testcase looks like this:

  $ ./ntreadraw \\Device\\CdRom0 2048 98990
  partition info: offset 0  length 203044864 (99143 blocks)
  Setting offset to: 202731520
  Current offset: 202731520 (block 98990)
  NtReadFile: pos: 202731520 (block 98990), status 0x00000000, bytes read: 2048
  NtReadFile: pos: 202733568 (block 98991), status 0x00000000, bytes read: 2048
  NtReadFile: pos: 202735616 (block 98992), status 0x00000000, bytes read: 2048
  NtReadFile: pos: 202737664 (block 98993), status 0xc0000011, bytes read: 8
  Final offset: 202737664 (block 98993)

So in my case, the DVD has 99143 blocks and Windows stops to read
after block 98993 all the time with status 0xC0000011, which simply
is the native NT status code for EOF (STATUS_END_OF_FILE).

I guess I'll ask on one of the Microsoft newsgroups if this is a known
effect and especially what I'm doing wrong or what I have to do to
get the desired behaviour.

Btw., if anybody has an idea what's going wrong, please speak up :}


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat
#include <stdio.h>
#include <inttypes.h>
#include <windows.h>
#include <ddk/ntifs.h>
#include <ddk/winddk.h>
#include <ddk/ntdddisk.h>

#if defined (__CYGWIN__) || defined (__MINGW32__)
#define NtDeviceIoControlFile ZwDeviceIoControlFile
#define NtSetInformationFile ZwSetInformationFile
#define NtQueryInformationFile ZwQueryInformationFile
#endif

BOOL NTAPI RtlCreateUnicodeStringFromAsciiz (PUNICODE_STRING, PCSTR);

int
main (int argc, char **argv)
{
  UNICODE_STRING upath;
  OBJECT_ATTRIBUTES attr;
  HANDLE h;
  IO_STATUS_BLOCK io;
  NTSTATUS status;
  PARTITION_INFORMATION_EX pix;
  FILE_POSITION_INFORMATION fpi;
  void *buf;

  ULONGLONG blocksize;
  ULONGLONG skip;

  if (argc < 4)
    {
      fprintf (stderr, "usage: %s native_path blocksize #_of_blocks_to_skip\n",
	       argv[0]);
      return 1;
    }
  if (!RtlCreateUnicodeStringFromAsciiz (&upath, argv[1]))
    {
      fprintf (stderr, "RtlCreateUnicodeStringFromAsciiz failed\n");
      return 1;
    }
  blocksize = strtoull (argv[2], NULL, 0);
  skip = strtoull (argv[3], NULL, 0);

  /* Open Device */
  InitializeObjectAttributes (&attr, &upath, 0, NULL, NULL);
  status = NtOpenFile (&h, FILE_GENERIC_READ, &attr, &io,
		       FILE_SHARE_VALID_FLAGS,
		       FILE_SYNCHRONOUS_IO_NONALERT
		       | FILE_OPEN_FOR_BACKUP_INTENT);
  if (!NT_SUCCESS (status))
    {
      fprintf (stderr, "NtOpenFile: 0x%08lx\n", status);
      return 1;
    }

  /* Get size information */
  status = NtDeviceIoControlFile (h, NULL, NULL, NULL, &io,
			    IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0,
			    &pix, sizeof pix);
  if (!NT_SUCCESS (status))
    {
      fprintf (stderr, "NtDeviceIoControlFile: 0x%08lx\n", status);
      goto thats_all_folks;
    }
  printf ("partition info: offset %" PRId64 "  length %" PRId64 " (%" PRId64 " blocks)\n",
	  pix.StartingOffset.QuadPart, pix.PartitionLength.QuadPart,
	  pix.PartitionLength.QuadPart / blocksize);

  /* Skip # of blocks given on the command line */

  fpi.CurrentByteOffset.QuadPart = skip * blocksize;
  printf ("Setting offset to: %" PRId64 "\n", fpi.CurrentByteOffset.QuadPart);
  status = NtSetInformationFile (h, &io, &fpi, sizeof fpi,
				 FilePositionInformation);
  if (!NT_SUCCESS (status))
    {
      fprintf (stderr, "NtSetInformationFile(%" PRId64 "): 0x%08lx\n",
      			fpi.CurrentByteOffset.QuadPart, status);
      goto thats_all_folks;
    }

  /* First a check if we are where we want to be. */

  fpi.CurrentByteOffset.QuadPart = 0;
  status = NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
				   FilePositionInformation);
  if (!NT_SUCCESS (status))
    {
      fprintf (stderr, "NtQueryInformationFile: 0x%08lx\n", status);
      goto thats_all_folks;
    }
  printf ("Current offset: %" PRId64 " (block %" PRId64 ")\n",
	  fpi.CurrentByteOffset.QuadPart,
	  fpi.CurrentByteOffset.QuadPart / blocksize);
  if (fpi.CurrentByteOffset.QuadPart != skip * blocksize)
    goto thats_all_folks;

  /* Now read until EOF or another error occured. */

  buf = alloca (blocksize);
  status = 0;
  while (NT_SUCCESS (status))
    {
      /* Missing status check but who cares? */
      fpi.CurrentByteOffset.QuadPart = 0;
      NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
			      FilePositionInformation);
      status = NtReadFile (h, NULL, NULL, NULL, &io, buf, blocksize,
			   NULL, NULL);
      printf ("NtReadFile: pos: %" PRId64 " (block %" PRId64
	      "), status 0x%08lx, bytes read: %lu\n",
	      fpi.CurrentByteOffset.QuadPart,
	      fpi.CurrentByteOffset.QuadPart / blocksize,
	      status, io.Information);
      Sleep (10L);
    }

  /* Final check for position. */

  fpi.CurrentByteOffset.QuadPart = 0;
  status = NtQueryInformationFile (h, &io, &fpi, sizeof fpi,
				   FilePositionInformation);
  if (!NT_SUCCESS (status))
    {
      fprintf (stderr, "NtQueryInformationFile: 0x%08lx\n", status);
      goto thats_all_folks;
    }
  printf ("Final offset: %" PRId64 " (block %" PRId64 ")\n",
	  fpi.CurrentByteOffset.QuadPart,
	  fpi.CurrentByteOffset.QuadPart / blocksize);

  /* That's all folks. */

thats_all_folks:
  NtClose (h);
  return 0;
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]