douyong5476 2013-09-27 05:35
浏览 62
已采纳

使用RPM将字节转为整数编码

I am trying to create a go program that can read and create RPM files without the need of librpm and rpmbuild. Most of the reason for this is to get a better understanding of programming in go.

I am parsing an RPM based off the following: https://github.com/jordansissel/fpm/wiki/rpm-internals

I am looking at the header and trying to parse the number of tags + the length, and I have the following code

fi, err := os.Open("golang-1.1-2.fc19.i686.rpm")
...
// header
head := make([]byte, 16)
// read a chunk
_, err = fi.Read(head)
if err != nil && err != io.EOF { panic(err) }

fmt.Printf("Magic number %s
", head[:8])
tags, read := binary.Varint(head[8:12])
fmt.Printf("Tag Count: %d
", tags)
fmt.Printf("Read %d
", read)

length, read := binary.Varint(head[12:16])
fmt.Printf("Length : %d
", length)
fmt.Printf("Read %d
", read)

I get back the following:

Magic number ���
Tag Count: 0
Read 1
Length : 0
Read 1

I printed out the slice and I see this:

Tag bytes: [0 0 0 7]
Length bytes: [0 0 4 132]

I then tried just doing this:

length, read = binary.Varint([]byte{4, 132})

which returns length as 2 and read 1.

Based off what I am reading, the tag and length should be "4 byte 'tag count'", so how would I get the four bytes as one number?

EDIT: Based off the feedback from @nick-craig-wood and @james-henstridge below is my following prototype code that does what Im looking for:

package main

import (
    "io"
    "os"
    "fmt"
    "encoding/binary"
    "bytes"
)    

type Header struct {
    // begin with the 8-byte header magic value: 8D AD E8 01 00 00 00 00
    Magic uint64
    // 4 byte 'tag count'
    Count uint32
    // 4 byte 'data length'
    Length uint32
}

func main() {
    // open input file
    fi, err := os.Open("golang-1.1-2.fc19.i686.rpm")
    if err != nil { panic(err) }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()

    // ignore lead
    fi.Seek(96, 0)

    // header
    head := make([]byte, 16)
    // read a chunk
    _, err = fi.Read(head)
    if err != nil && err != io.EOF { panic(err) }

    fmt.Printf("Magic number %s
", head[:8])
    tags := binary.BigEndian.Uint32(head[8:12])
    fmt.Printf("Count Count: %d
", tags)

    length := binary.BigEndian.Uint32(head[12:16])
    fmt.Printf("Length : %d
", length)

    // read it as a struct
    buf := bytes.NewBuffer(head)
    header := Header{}
    err = binary.Read(buf, binary.BigEndian, &header)
    if err != nil {
        fmt.Println("binary.Read failed:", err)
    }
    fmt.Printf("header = %#v
", header)
    fmt.Printf("Count bytes: %d
", header.Count)
    fmt.Printf("Length bytes: %d
", header.Length)
}
  • 写回答

2条回答 默认 最新

  • duananyu9231 2013-09-27 05:55
    关注

    Firstly don't use Varint - it doesn't do what you think it does!

    Decode like this into a go structure is the most convenient way

    package main
    
    import (
        "bytes"
        "encoding/binary"
        "fmt"
    )
    
    type Header struct {
        // begin with the 8-byte header magic value: 8D AD E8 01 00 00 00 00
        Magic uint64
        // 4 byte 'tag count'
        Count uint32
        // 4 byte 'data length'
        Length uint32
    }
    
    var data = []byte{0x8D, 0xAD, 0xE8, 0x01, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 132}
    
    func main() {
        buf := bytes.NewBuffer(data)
        header := Header{}
        err := binary.Read(buf, binary.BigEndian, &header)
        if err != nil {
            fmt.Println("binary.Read failed:", err)
        }
        fmt.Printf("header = %#v
    ", header)
    
    }
    

    Prints

    header = main.Header{Magic:0x8dade80100000000, Count:0x7, Length:0x484}
    

    Playground link

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 帮我解决一下膳食平衡的线性规划模型的数据实例
  • ¥40 万年历缺少农历,需要和阳历同时显示
  • ¥250 雷电模拟器内存穿透、寻基址和特征码的教学
  • ¥200 比特币ord程序wallet_constructor.rs文件支持一次性铸造1000个代币,并将它们分配到40个UTXO上(每个UTXO上分配25个代币),并设置找零地址
  • ¥15 关于Java的学习问题
  • ¥15 如何使用chatgpt完成文本分类任务?
  • ¥15 已知速度v关于位置s的等式,怎么转化为已知位置求速度v的等式
  • ¥15 我有个餐饮系统,用wampserver把环境配置好了,但是后端的网页却进去,是为什么,能不能帮远程一下?
  • ¥15 R运行没有名称为"species"的插槽对于此对象类"SDMmodelCV"
  • ¥20 基于决策树的数字信号处理,2ask 2psk 2fsk的代码,检查下报错的原因