[comp.lang.perl] PERL PL28 and reading raw devices

gorpong@uunet.uu.net (09/26/90)

I am writing a perl program which will handle tape copying from remote or
local devices.  The scheme I use for a local source device is to open up
the device via:
	open(SRC_TAPE, "< $SRC_TAPE");
I then open up a pipe to write the remote tape (or pipe to read the remote).
When going remote for the device, I use the 'dd' command to do the reading
and/or writing.  Enough background, now to the question.

When copying a tape which is in boot format, the program tells me that it
has read and written the exact same number of bytes.  When attempting to
boot this tape, it fails every time, on every tape drive.  When forcing
the program to use 'dd' to read the tape and write the tape, it also tells
me that the correct number of bytes have been written.  However, the
copy made with 'dd' on both ends boots correctly.

I am reading the tape with the perl read(SRC_TAPE, $_, $blksize); and
SRC_TAPE is opened either "< device" or "dd if=device |"
The exact same code works when the open is opening up a 'dd' command to
read the device.  Is there something which perl is doing to the bytes
read in from the raw device which it does not do when reading from a pipe?

I should note that when copying things like 'tar' format tapes, it is still
in tar format, and it unarchives correctly.  It really screws up boot 
format tapes.  My question is, why?  It is perl patchlevel 28 on a Sun 3/50
or 3/anything (or 4/anything) running SunOS 4.1.  Any help you may be able
to give me would be greatly appreciated.

		-- Gordon.

-- 
Gordon C. Galligher	9127 Potter Rd. #2E	Des. Plaines, Ill.    60016-4881
     telxon!ping%gorpong@uunet.uu.net (not tested)  (Is this even legal??)
     ...!uunet!telxon!ping!gorpong      (tested)    (And it works!)
"It seems to me, Golan, that the advance of civilization is nothing but an
 exercise in the limiting of privacy." - Janov Pelorat -- _Foundation's Edge_

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (09/27/90)

In article <1990Sep26.122859.18935@uvaarpa.Virginia.EDU> telxon!ping!gorpong@uunet.uu.net writes:
: I am writing a perl program which will handle tape copying from remote or
: local devices.  The scheme I use for a local source device is to open up
: the device via:
: 	open(SRC_TAPE, "< $SRC_TAPE");
: I then open up a pipe to write the remote tape (or pipe to read the remote).
: When going remote for the device, I use the 'dd' command to do the reading
: and/or writing.  Enough background, now to the question.
: 
: When copying a tape which is in boot format, the program tells me that it
: has read and written the exact same number of bytes.  When attempting to
: boot this tape, it fails every time, on every tape drive.  When forcing
: the program to use 'dd' to read the tape and write the tape, it also tells
: me that the correct number of bytes have been written.  However, the
: copy made with 'dd' on both ends boots correctly.
: 
: I am reading the tape with the perl read(SRC_TAPE, $_, $blksize); and
: SRC_TAPE is opened either "< device" or "dd if=device |"
: The exact same code works when the open is opening up a 'dd' command to
: read the device.  Is there something which perl is doing to the bytes
: read in from the raw device which it does not do when reading from a pipe?
: 
: I should note that when copying things like 'tar' format tapes, it is still
: in tar format, and it unarchives correctly.  It really screws up boot 
: format tapes.  My question is, why?  It is perl patchlevel 28 on a Sun 3/50
: or 3/anything (or 4/anything) running SunOS 4.1.  Any help you may be able
: to give me would be greatly appreciated.

The problem is that read is actually a call to standard I/O's fread(), and
how many bytes fread() chooses to read has little relation to how many
bytes you said to read.

For this very reason, Perl 4.0 has a sysread() and a syswrite() function.

For now, you can call a real read() using syscall(), if you have it
available.

Larry

merlyn@iwarp.intel.com (Randal Schwartz) (09/27/90)

In article <1990Sep26.122859.18935@uvaarpa.Virginia.EDU>, telxon!ping!gorpong@uunet writes:
| I am reading the tape with the perl read(SRC_TAPE, $_, $blksize); and
| SRC_TAPE is opened either "< device" or "dd if=device |"
| The exact same code works when the open is opening up a 'dd' command to
| read the device.  Is there something which perl is doing to the bytes
| read in from the raw device which it does not do when reading from a pipe?

Raw devices are sensitive to the *real* number of bytes being passed
to the read(2) system call.  Between Perl's read() and the read(2)
system call sits the standard I/O package, which is free to break up
requests into little teenytiny blocks or big huge blocks at will.  So
the number in the read() has very little to do with the number passed
to read(2).

For now, you can do something like:

	open(DD,"dd if=/dev/rst1 bs=20b |");
	while(read(DD,$_,8192)) { # 8192 is arbitrary
	}

and in the future (Perl 4.0), something like:

	open(TAPE,"/dev/rst1");
	while($err = sysread(TAPE,$_,20*512)) {
	}

or you can use syscall() now if you can figure out what to pass it.

Just remember that the number of bytes read by read() has nothing to
do with the blocking on the tape, but to the bytes transfered from
stdio's buffers to your program.

print (("Just another ", "buffered ", "Perl hacker,")[0,2])
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/