データからNULを削除するbusyboxヘッダーのソリューション

データからNULを削除するbusyboxヘッダーのソリューション

簡単に言うと:最新バージョンのbusybox(1.23.2)にはhead問題があり、提供されたデータからNUL文字を喜んで削除します。バイナリを交換することはオプションではありません。私のスクリプトでこれを使用していますhead -[nc] -X。 busyboxが提供する他のツールを使ってシミュレートする方法はありますか?


ファイルのアップロードやbusybox httpdがこれを処理する方法に慣れていない人は、読んでみたいかもしれません。これ続行する前に。

Busyboxがインストールされている組み込みシステムでCGIスクリプトで受信したデータのアップロードを処理しようとしています。送信されるデータは次のとおりです。

$ hexdump -C foo.bin
00000000  03 15 20 00 00 00 75 73  74 61 72 30 30 30 2e 30  |.. ...ustar000.0|
00000010  00 11 00                                          |...|
00000013

POST要求を介して送信されると、データを処理するCGIスクリプトは次のデータを受け取ります。

$ hexdump -C 24593.tmp 
00000000  2d 2d 2d 2d 2d 2d 2d 2d  2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000010  2d 2d 2d 2d 2d 2d 2d 2d  2d 2d 30 65 34 32 32 64  |----------0e422d|
00000020  63 39 65 64 65 32 34 36  34 30 0d 0a 43 6f 6e 74  |c9ede24640..Cont|
00000030  65 6e 74 2d 44 69 73 70  6f 73 69 74 69 6f 6e 3a  |ent-Disposition:|
00000040  20 66 6f 72 6d 2d 64 61  74 61 3b 20 6e 61 6d 65  | form-data; name|
00000050  3d 22 66 69 6c 65 22 3b  20 66 69 6c 65 6e 61 6d  |="file"; filenam|
00000060  65 3d 22 66 6f 6f 2e 62  69 6e 22 0d 0a 43 6f 6e  |e="foo.bin"..Con|
00000070  74 65 6e 74 2d 54 79 70  65 3a 20 61 70 70 6c 69  |tent-Type: appli|
00000080  63 61 74 69 6f 6e 2f 6f  63 74 65 74 2d 73 74 72  |cation/octet-str|
00000090  65 61 6d 0d 0a 0d 0a 03  15 20 00 00 00 75 73 74  |eam...... ...ust|
000000a0  61 72 30 30 30 2e 30 00  11 00 0d 0a 2d 2d 2d 2d  |ar000.0.....----|
000000b0  2d 2d 2d 2d 2d 2d 2d 2d  2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000000c0  2d 2d 2d 2d 2d 2d 30 65  34 32 32 64 63 39 65 64  |------0e422dc9ed|
000000d0  65 32 34 36 34 30 2d 2d  0d 0a                    |e24640--..|
000000da

上記から生データを取得するのは簡単です。

$ tail -n +5 24593.tmp | head -n -1 | head -c -2 | hexdump -C
00000000  03 15 20 00 00 00 75 73  74 61 72 30 30 30 2e 30  |.. ...ustar000.0|
00000010  00 11 00                                          |...|
00000013

しかし、busyboxには欠点がありますhead。データのすべてのNUL文字が削除されます。

$ /firmware/system/xbin/tail -n +5 24593.tmp | /firmware/system/xbin/head -n -1 | /firmware/system/xbin/head -c -2 | hexdump -C
00000000  03 15 20 75 73 74 61 72  30 30 30 2e 30 11        |.. ustar000.0.|
0000000e

head -[nc] -Xbusyboxが提供する他のツールを使用して動作をシミュレートしたり、少なくとも作業する他の方法はありますか?


最も注意深くすべきことは、新しいバイナリを正しい動作で導入/交換することですが、これはさまざまな理由で不可能です(ここでは議論する必要はありません)。

この記事は、主に当面の問題に関連しない詳細に言及することに集中しているようですが、これを防ぐためにここに詳細を示します。XYの問題

ベストアンサー1

あなたの質問を正しく理解したら、次のようなリクエストからアップロードされたファイルを抽出したいと思います。

  • ダッシュとそれに続く16進数で構成される行です。
  • より多くの空白ではない行(タイトル)。
  • 空行
  • 抽出するコンテンツ
  • 改行文字;
  • 最初の行を繰り返します。

ここで、改行文字はCRLFシーケンスであり、内容にはすべてのバイトを含めることができますが、ヘッダーにはNULLバイトを含めません。

head行に依存してtail解析する代わりに、次の2つの手順でこれを実行できます。

  1. 抽出するバイト位置の範囲を決定します。
  2. このバイトを抽出します。

最初のステップでは、ヌルバイトの問題を避けるためにtr。その後、行ベースのツールを使用して最初の空白行を検出し、最後の行の先頭を検出できます。私は以下でawkを使用しており、ファイル名も抽出する機会を得ています。 awkがなければ、、、、head...を使用できます。tailsed

dd2番目のステップでは、ブロックサイズが1のブロックを使用できます。遅いが安定しています。

upload=24593.tmp
filename=$(<"$upload" tr '\0' _ | awk '
    {line_start = line_end; line_end += length($0)+1}
    !content_start && /^Content-Disposition:.*filename="/ {
        sub(/.*filename="/, ""); sub(/".*/, "");
        filename = $0
    }
    !content_start && $0=="\r" {content_start=line_end}
    END {print content_start, line_start-2-content_start, filename}
')
skip=${filename%% *}; filename=${filename#* }
count=${filename%% *}; filename=${filename#* }
if [ -z "$filename" ]; then filename=$(mktemp); fi
<$upload dd bs=1 skip="$skip" count="$count" >"$filename"

おすすめ記事