in reply to Re: Re: Re: Re: Re: Unpack for VMS binary files
in thread Unpack for VMS binary files

Ahh, with the VMS time, I have two parts:
3918795776 9926119 4118795776 9926119 23828480 9926120 223828480 9926120 423828480 9926120
For the subroutine you mentioned, which is considered the low_long and high_long values? Regards, Stacy.

Replies are listed 'Best First'.
Re: Re: Unpack for VMS binary files
by pfaut (Priest) on Feb 19, 2003 at 22:44 UTC

    The first value should be the low part and the second value the high part.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      I've imported your subroutine into my code... However, I'm not getting the what I think I should. If I've got it right, your routine should return the unix time in epoch seconds. However, doing a "gdate '+%s'" on my system shows the epoch seconds = 1045700265... a bit different to what the routine returns (see below). In my case, perhaps the unpack format of the low_long and high_long paramenters in the routine require a little alteration? BTW, reversing the order of $high and $low into &quad_to_epoch didn't help...
      print "$low $high ", &quad_to_epoch("$low $high"), "\n";
      low high &quad_to_epoch 2038398976 10599419 408804118300 2238398976 10599419 408804118300 2438398976 10599419 408804118300 2638398976 10599419 408804118300 2838398976 10599419 408804118300 3038398976 10599419 408804118300 3238398976 10599419 408804118300 3438398976 10599419 408804118300 3638398976 10599419 408804118300
      Regards, Stacy.
        You're calling the routine very wrong there--if nothing else there's a space in the middle of the series of bytes, which'll screw things up a lot, and unless the two variables actually have the exact 4 bytes of the data from the disk file for their fields (not the string value of the 4-byte integer converted to a real int, mind, but the actual 4 bytes from disk) the conversion will go horribly wrong.

        I've appended a version that you might find more useful.

Re: Re: Unpack for VMS binary files
by Elian (Parson) on Feb 20, 2003 at 15:04 UTC
    low_long is the least-significant 32 bits of the quadword date, while high_long is the most significant 32 bits. Make sure that you've unpacked things correctly--the code assumes that a VMS system put the bytes on disk, and in VMS endian-order. If that's not the case, then you'll have problems, of course.

    Also, what are the dates supposed to be? Running the conversion on the first date gives me a date of Wed Dec 22 00:14:00 1993, which might well be correct. (Hard to say there)

      Whilst parsing the VMS binary file, I have unpacked it with the template:
      my $template="V2 v12";
      Where V/v are a long/short in "VAX" (little-endian) order. As I've already unpacked the data, there isn't a need to redo the unpack commands in the subroutine - just pass the low_long and high_long as is into the sub. There is one problem: the data in the binary file starts at 00:00:00 and ends at 23:40:40 for 1-1-2003. Printing out the output from the sub produces 11:00:00 through to 23:40:40 and _then_ 00:00:00 through to 10:59:40 for 2-1-2003! Regards, Stacy.

        Elian's code wants to do the unpacking. Try something like this.

        @vals = unpack("x8 v12",$buf); $timelow = substr($buf,0,4); $timehigh = substr($buf,4,4);

        @vals will contain all the short values. This unpack will skip the first eight bytes (the time field) so the time is no longer returned. Instead, the time is pulled out of the buffer in packed form with substr. You can then pass $timelow and $timehigh to Elian's conversion function.

        --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';