in reply to Re: problem with sysseek in loop
in thread problem with sysseek in loop

Here you go, its a working script that gets md5 and puts it in a file in "C:\md5.txt"



use Digest::MD5; use File::Path qw(make_path); open (my $infile, '<', 'file') or die "cannot open file: $!"; binmode ($infile); make_path ('./extracted'); my $curpos = ''; my $fileLocation = ''; my $fileSize = ''; my $fileName = ''; my $file =''; my $chunk = ''; my $exit = ''; #GET File Location, File Size, File Name and write to file seek ($infile, 0x10, 0); until ($exit){ $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20); $curpos = tell $infile; if ($fileLocation =~ 'unformatted characters'){ last; } $fileLocation =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileSize =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileName =~ s/\0+$//; if ($fileLocation =~ 'formatted characters'){ last; } #THIS PART ACTUALLY EXTRACTS THE DATA BASED OFF OF OFFSETS open($file, '>', "extracted/$fileName") or die "Cannot open $fileName +$!"; binmode($file); sysseek ($infile, hex($fileLocation), 0); sysread ($infile, $chunk, hex($fileSize)); syswrite ($file, $chunk); $fileLocation = ''; $fileSize = ''; }; #GET MD5 my $dirname = "extracted"; foreach my $file (<$dirname/*>) { next if -d $file; open( my $FILE, $file ); binmode($FILE); open (my $md5, "+>>", "C:/md5") or die "cant open md5.txt: $!"; binmode($md5); $file =~ s{.*/}{}; syswrite $md5, Digest::MD5->new->addfile($FILE)->hexdigest; syswrite $md5, " $file\n"; };


seeing how $fileLocation is the first check, you can also exit with that if you have many many files to extract. but this will extract those files and it will also get the md5 of them in a split sec lol
yall have a good one :)
Any Questions?

Replies are listed 'Best First'.
Re^3: problem with sysseek in loop
by Laurent_R (Canon) on May 07, 2014 at 17:35 UTC
    Hi,

    If I understand correctly what you are doing, you don't need the long series of:

    $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20);
    This would probably be sufficient:
    read ($infile, $fileLocation, 0x08); read ($infile, $fileSize, 0x08); read ($infile, $fileName, 0x20);
    since the read function knows which byte it has last read and which one to read next, so that the calls to seek and tell are most probably not required.

      yes that worked great, to bad im new to perl or i would have caught that. saved me a few lines of code :)

      i am now writing md5 checksums to a md5 file as you see already, but i am having a hard time comparing the md5s that the script gets against the md5 file.
      here is what i have so far when trying to compare them.
      my $dirname = "extracted"; open (my $md5file, '<', "C:/md5"); binmode($md5file); foreach my $file (<$dirname/*>) { next if -d $file; open( my $FILE, $file ); binmode($FILE); $file =~ s{.*/}{}; my $md5hash = Digest::MD5->new->addfile($FILE)->hexdigest; if ($md5hash =~ $md5file){ print "$file MATCH\n"; } else { print "$file NO MATCH!\n"; } }
      I dont understand, it should /just/ work right? I dont open the file over and over and the md5 check is in the foreach loop.
      Ive been at just this one part for over an hour and i am ready to give up for the evening lol.
      $file =~ s{.*/}{}; just strips the path from the filename. it shouldnt have anything to do with comparing the md5's.
      Any help would be appreciated :)
        I think you should really take the habit of indenting your code correctly. This code of yours: should probably be rewritten more or less this way (no code change, just improved formatting):
        my $dirname = "extracted"; open (my $md5file, '<', "C:/md5"); binmode($md5file); foreach my $file (<$dirname/*>) { next if -d $file; open( my $FILE, $file ); binmode($FILE); $file =~ s{.*/}{}; my $md5hash = Digest::MD5->new->addfile($FILE)->hexdigest; if ($md5hash =~ $md5file){ print "$file MATCH\n"; } else { print "$file NO MATCH!\n"; } }
        as this would enable you to better visualize the logical structure and detect possible problems or bugs.

        Concerning subroutines, yes, by all means, learn them, this is quite easy and necessary. The perlsub document tells you more or less everything about them, but it has probably far more details than what you need or want for a start. For an easier introduction to them, read the relevant section (http://perldoc.perl.org/perlintro.html#Writing-subroutines) of the perlintro document, but don't read only the section on subs, reading the full document would probably be very useful to you.

      Figured it out finally, had to do a loop, inside of a loop, which id never done before. I was doing it in a loop, in a loop, in a loop... but i changed it
      I would love to learn how to do sub routines
      Anyway here is the final working code as of now.
      use File::Path (make_path, rmtree); use Digest::MD5; use File::Slurp; rmtree 'extracted'; open (my $infile, '<', $ARGV[0]) or die "cannot open file: $!"; binmode ($infile); make_path ('./extracted');#or die "Failed to create Direcotry: $!"; my $curpos = ''; my $fileLocation = ''; my $fileSize = ''; my $fileName = ''; my $file =''; my $chunk = ''; my $exit = ''; #GET File Location, File Size, File Name and write to file seek ($infile, 0x10, 0); until ($exit){ read ($infile, $fileLocation, 0x08); read ($infile, $fileSize, 0x08); read ($infile, $fileName, 0x20); if ($fileLocation =~ 'SCE'){ last; } $fileLocation =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileSize =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileName =~ s/\0+$//; if ($fileLocation =~ 'ffffffffffffffff'){ last; } open($file, '>', "extracted/$fileName") or die "Cannot open $fileName + $!"; binmode($file); sysseek ($infile, hex($fileLocation), 0); sysread ($infile, $chunk, hex($fileSize)); syswrite ($file, $chunk); $fileLocation = ''; $fileSize = ''; }; my $dirname = "extracted"; open (my $sdk, '<', "extracted/sdk_version") or die "cannot open sdk_v +ersion: $!"; seek ($sdk, 0x00, 0); read ($sdk, $buf, 0x03); # my@fn; # my @hash; my @md5s = read_file 'C:/md5'; chomp @hash; chomp @md5s; # open (my $md5file, '>>', 'C:/md5'); foreach my $file (<$dirname/*>) { next if -d $file; open( my $FILE, $file ); binmode($FILE); $file =~ s{.*/}{}; my $md5 = Digest::MD5->new->addfile($FILE)->hexdigest; push (@hash, $md5); # syswrite $md5file, "$md5\n"; } foreach $md5s (@hash) { foreach $md5table (@md5s) { if($md5s ~~ $md5table) { print "$md5s ", "$buf ", "success\n"; } } }
      file to reference with

      I dont like a few things about the foreach loop that gets the md5 tho because i cannot print the filename with the md5 checksum.
      i will probably end up rewriting this lol.
      thanks for all your help :)
        heres the md5 file to check with
        you can uncomment:
        # open (my $md5file, '>>', 'C:/md5'); # syswrite $md5file, "$md5\n";
        and it would create it for you, but either here is the md5 file, put it in C:\md5 or change the code and put it anywhere you like