Solved

Copying binary files

Posted on 1998-10-15
7
187 Views
Last Modified: 2010-03-05
I am writing a Perl program that runs on NT. I have NFS mounted unix filesystems. I will need to copy binary files from the NT system to the Unux filesystem. I have written a subroutines that accepts two parameters, the full source path including filename, and the destination path. I suspect that I would be opening a filehandle to the destination file and opening another to the source. I guess that I would then simply print one to the other, but I think I need binary mode somewhere.

I hope this is clear enough.
Thanx
Angel
0
Comment
Question by:aleyva
  • 3
  • 2
  • 2
7 Comments
 
LVL 5

Accepted Solution

by:
b2pi earned 200 total points
ID: 1205351
perldoc -f binmode

will tell you what you might be looking for.  However, since you have
file systems nfs mounted, why not just do

system('copy /b src_file_on_nfs_fs dst_file_on_local_storage');

unless you're doing this from the UNIX side, in which case it would be

system('cp src_file_on_remote_NT_storage dst_file_on_unix_fs ');

you might also want to check out using Net::FTP, but you may not have
servers set up.

If you're convinced you want to do it by hand, try (Note that this is
off the top of my head, some clean up may be necessary, your mileage
may vary, offer not valid in the state of Utah)

sub MyCP ( $$ );

sub MyCP ( $$ ) {

    my($src, $dst) = @_;

    my($error) = 0;
    if (!-f "$src") {
       carp "MyCP: Invalid src file '$src'";
       $error ++;
    }
    if (!-f "$dst") {
       carp "MyCP: Invalid dst file '$dst'";
       $error ++;
    }
    return undef if $error;

    open(SRC, "<$src") || $error++;
    if ($error) {
       carp "Unable to open src file '$src' : $!";
       return undef;
    }
    open(DST, ">$dst") || $error++;
    if ($error) {
       carp "Unable to open dst file '$dst' : $!";
       close(SRC);
       return undef;
    }
    binmode SRC;
    binmode DST;

    my($count) = 64*1024;
    my($bcount, $rcount, $wcount, $buffer, $rcount);

    for ($bcount = -s $src; $bcount; $bcount -= $wcount) {
          $rcount = sysread(SRC, $buffer, $count);
      $wcount = undef;
      if (!defined($rcount)) {
         carp "src read failed: $!";
      } else {
          $wcount = syswrite(DST, $buffer, $rcount);
          if (!defined($wcount) || $wcount != $rcount) {
             carp "dst write failed: $!";
          }
      }
      if (!defined($wcount) || $wcount != $rcount) {
          close(SRC);
          close(DST);
          return undef;
        }
    }
    close(SRC);
    close(DST);
    return 1;
}

0
 

Author Comment

by:aleyva
ID: 1205352
b2pi, Why don't you have any real profile data? Anyway,

I have a couple of questions/comments.
First of all, what is the carp () command doing?

Next, I have done the following and it works, so I would simply want to ask why it is or isn't a good idea to do it this way.

      open (SRC,"$source");
      open (DEST,">$destination");
      binmode (SRC);
      binmode (DEST);
      print DEST <SRC>;
      close (SRC);
      close (DEST);

Again, this works because I am able to read the files on the UNIX end.

I tried the system ("copy /b $source $destination"); command, but the files never appeared, this is why I am now trying with perl. Not only that, it makes it more portable.

One more, would it be asking too much to have you comment the code? (You must be rolling your eyes by now with that one).

Appreciated
Angel

PS    I increased the points.
0
 
LVL 5

Expert Comment

by:b2pi
ID: 1205353
1.) Why do I need profile data?
2.) carp issues warnings with a bit of trace info.  I note that I
forgot that at the top of the code there has to be a


use Carp;

line.  Take a look at

perldoc Carp

for more information. (Note that, as with warn, you can defined a
$SIG__WARN__} handler to suppress messages)

3.) There's probably no problem with your code, save for two
bugaboos. First, no error handling, and no way to determine if the
copy worked (or, if it didn't, where, and why not).  Secondly, it will
read the entire file into memory as one chunk.  That could be a bit of
a problem if memory resources are .... constrained.  Suppose you have
a 64M machine, and a 128M file.  Even with virtual memory, you're
going to be waiting a long, long time.

4.) Comment?  It's kind of small, but...

use strict;
use Carp;

## Prototype to put at the top of code
sub MyCP ( $$ );


## Intervening code..., including that which calls MyCP
## like
##
##    die "MyCP failure" if !MyCP($src, $dst)
##

sub MyCP ( $$ ) {
    my($src, $dst) = @_;
    my($error) = 0;
    ## Ensure that the source file exists
    if (!-f "$src") {
        carp "MyCP: Invalid src file '$src'";
        $error ++;
    }
    ## Ensure that the destination file exists
    if (!-f "$dst") {
        carp "MyCP: Invalid dst file '$dst'";
        $error ++;
    }
    return undef if $error;
    ## Open the source file
    open(SRC, "<$src") || $error++;
    if ($error) {
        carp "Unable to open src file '$src' : $!";
        return undef;
    }
    ## Open the destination file
    open(DST, ">$dst") || $error++;
    if ($error) {
        carp "Unable to open dst file '$dst' : $!";
        close(SRC);
        return undef;
    }
    ## Set both source and destination files to binmode
    binmode SRC;
    binmode DST;
    ## Define a constant for maximum read size
    my($count) = 64*1024;
    ## declare some variables (byte count, read count, write count,
    ## a buffer for reads and writes, and bytes remaining)
    my($bcount, $rcount, $wcount, $buffer, $rcount);
    ## Note that -s $src returns the size of the file $src
    for ($bcount = -s $src; $bcount; $bcount -= $wcount) {
      ## Read the data, $rcount is the number of bytes read
        $rcount = sysread(SRC, $buffer, $count);
        $wcount = undef;
      ## Complain on error
        if (!defined($rcount)) {
            carp "src read failed: $!";
        } else {
          ## Write the data, $wcount is the number of bytes written
            $wcount = syswrite(DST, $buffer, $rcount);
          ## Complain on error
            if (!defined($wcount) || $wcount != $rcount) {
                carp "dst write failed: $!";
            }
        }
      ## Complain and return on error
        if (!defined($wcount) || $wcount != $rcount) {
            close(SRC);
            close(DST);
            return undef;
        }
    }
    ## clean up
    close(SRC);
    close(DST);
    # Done
    return 1;
}

0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 84

Expert Comment

by:ozo
ID: 1205354
b2pi, if you're not going to handle partial writes from the sysewrite, it may be safer to use print, which handles all that for you.
0
 

Author Comment

by:aleyva
ID: 1205355
b2pi,

The reason for the profile, is primarily to know your background/experience, and a name, but no big deal.

I implemented your solution, and it works like a champ almost. I don't think that it is your code as much as it might be the file, but I have a postscript file that was saved on a MAC as BINARY Postscript. The programs loops forever trying to write the file even though it is returning 0 values for rcount and wcount. I simply put an check if these values are 0, then exit.

Thanx again,
Angel
0
 
LVL 5

Expert Comment

by:b2pi
ID: 1205356
ozo, I thought I was handling partial results from the write ($wcount
!= $rcount). It is true that I could retry the write, but, really,
I don't think I've ever had a need.

I find it curious that a sysread could return 0 bytes on a proper call...
0
 
LVL 84

Expert Comment

by:ozo
ID: 1205357
You may not have ever had a signal sent to you during a syswrite
(write is different, don't try to mix write and syswrite calls on the same filehandle)
But that doesn't mean you will never have the need.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (http://dilbert.com/strips/comic/2007-08…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now