簡単に言うと:最新バージョンの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] -X
busyboxが提供する他のツールを使用して動作をシミュレートしたり、少なくとも作業する他の方法はありますか?
最も注意深くすべきことは、新しいバイナリを正しい動作で導入/交換することですが、これはさまざまな理由で不可能です(ここでは議論する必要はありません)。
この記事は、主に当面の問題に関連しない詳細に言及することに集中しているようですが、これを防ぐためにここに詳細を示します。XYの問題。
答え1
あなたの質問を正しく理解したら、次のようなリクエストからアップロードされたファイルを抽出したいと思います。
- ダッシュとそれに続く16進数で構成される行です。
- より多くの空白ではない行(タイトル)。
- 空行
- 抽出するコンテンツ
- 改行文字;
- 最初の行を繰り返します。
ここで、改行文字はCRLFシーケンスであり、内容にはすべてのバイトを含めることができますが、ヘッダーにはNULLバイトを含めません。
head
行に依存してtail
解析する代わりに、次の2つの手順でこれを実行できます。
- 抽出するバイト位置の範囲を決定します。
- このバイトを抽出します。
最初のステップでは、ヌルバイトの問題を避けるためにtr
。その後、行ベースのツールを使用して最初の空白行を検出し、最後の行の先頭を検出できます。私は以下でawkを使用しており、ファイル名も抽出する機会を得ています。 awkがなければ、、、、head
...を使用できます。tail
sed
dd
2番目のステップでは、ブロックサイズが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"
答え2
Busyboxは高度に設定可能なので、答えはコンパイルされた項目によって異なります。以下はいくつかのオプションです。
catv -v
ヌル値は「^@」で示されます。
split -l 1
それぞれ1行ずつ含まれるファイルxaa
xab
などが生成されます。