EN JA
SBUF(9)
SBUF(9) FreeBSD Kernel Developer's Manual SBUF(9)

名称

sbuf, sbuf_new, sbuf_new_auto, sbuf_new_for_sysctl, sbuf_clear, sbuf_setpos, sbuf_bcat, sbuf_bcopyin, sbuf_bcpy, sbuf_cat, sbuf_copyin, sbuf_cpy, sbuf_printf, sbuf_vprintf, sbuf_putc, sbuf_set_drain, sbuf_trim, sbuf_error, sbuf_finish, sbuf_data, sbuf_len, sbuf_done, sbuf_delete, sbuf_start_section, sbuf_end_section安全な文字列の組み立て

書式

#include < sys/types.h>
#include < sys/sbuf.h>

typedef int (
sbuf_drain_func) (
void *arg, const char *data, int len);


struct sbuf *
sbuf_new( struct sbuf *s, char *buf, int length, int flags);

struct sbuf *
sbuf_new_auto();

void
sbuf_clear( struct sbuf *s);

int
sbuf_setpos( struct sbuf *s, int pos);

int
sbuf_bcat( struct sbuf *s, const void *buf, size_t len);

int
sbuf_bcopyin( struct sbuf *s, const void *uaddr, size_t len);

int
sbuf_bcpy( struct sbuf *s, const void *buf, size_t len);

int
sbuf_cat( struct sbuf *s, const char *str);

int
sbuf_copyin( struct sbuf *s, const void *uaddr, size_t len);

int
sbuf_cpy( struct sbuf *s, const char *str);

int
sbuf_printf( struct sbuf *s, const char *fmt, ...);

int
sbuf_vprintf( struct sbuf *s, const char *fmt, va_list ap);

int
sbuf_putc( struct sbuf *s, int c);

void
sbuf_set_drain( struct sbuf *s, sbuf_drain_func *func, void *arg);

int
sbuf_trim( struct sbuf *s);

int
sbuf_error( struct sbuf *s);

int
sbuf_finish( struct sbuf *s);

char *
sbuf_data( struct sbuf *s);

ssize_t
sbuf_len( struct sbuf *s);

int
sbuf_done( struct sbuf *s);

void
sbuf_delete( struct sbuf *s);

void
sbuf_start_section( struct sbuf *s, ssize_t *old_lenp);

ssize_t
sbuf_end_section( struct sbuf *s, ssize_t old_len, size_t pad, int c);

#include < sys/sysctl.h>

struct sbuf *
sbuf_new_for_sysctl( struct sbuf *s, char *buf, int length, struct sysctl_req *req);

解説

sbuf 関数ファミリは、カーネルまたはユーザ空間の文字列を安全に割り付ける、組み立てる、そして解放することができます。

文字の配列の代わりに、これらの関数は、 < sys/sbuf.h> に定義される sbufs と呼ばれる構造体で動作します。

文字列の割り付けまたは組み立ての間に遭遇する任意のエラーは、データ構造体でラッチされ (歯止めがかけられ)、すべてのプロセスの成否を決定するのに十分である組み立ての終わりで単一のエラーをテストをします。

sbuf_new() 関数は、最初の引数によって指される sbuf を初期化します。そのポインタが NULL であるなら、 sbuf_new() は、 malloc(9) を使用して、 struct sbuf を割り付けます。 buf 引数は、実際の文字列を格納するバッファへのポインタです。それが NULL であるなら、 sbuf_new() は、 malloc(9) を使用して、バッファを割り付けます。 length は、記憶域バッファの最初のサイズです。 4 番目の引数 flags は、次のフラグで構成されます:

SBUF_FIXEDLEN
記憶域のバッファは、その最初のサイズに固定されます。このサイズを越えて sbuf を拡張する試みは、オーバフロー状態の結果となります。
SBUF_AUTOEXTEND
これは、リソースが許す限り、追加のデータを保持するために、記憶域のバッファが、必要に応じて拡張されることを示します。

bufNULL でないなら、少なくとも length 文字の配列を指さなければならないことに注意してください。 sbuf によって使用されている間に、その配列に直接アクセスすることの結果は、未定義です。

sbuf_new_auto() 関数は、完全に動的な sbuf を作成するためのショートカット (近道) です。それは、値 NULL, NULL, 0SBUF_AUTOEXTEND をつけて sbuf_new() を呼び出すことと同等です。

sbuf_new_for_sysctl() 関数は、内部のバッファが満杯になるとき、 SYSCTL_OUT() を使用するために drain 関数で sbuf をセットアップします。 sbuf に追加される様々な関数がスリープ不可能なロックが保持されている間に、使用されるなら、ユーザバッファは、 sysctl_wire_old_buffer() を使用して結ばれるべきであることに注意してください。

sbuf_delete() 関数は、 sbuf をクリアして、そのために割り付けられた全てのメモリを開放します。全ての sbuf_new() への呼び出しのための sbuf_delete() の呼び出しがなければなりません。削除された後の sbuf への全てのアクセスの試みは、失敗します。

sbuf_clear() 関数は、 sbuf の内容を無効にし、位置を 0 にリセットします。

sbuf_setpos() 関数は、 sbuf の終了位置を、0 と格納バッファの大きさよりも 1 小さい値の間の値である pos に設定します。結果として、新しい位置において sbuf の先端を切り捨てることになります。

sbuf_bcat() 関数は、バッファ buf の最初の len バイトを sbuf に追加します。

sbuf_bcopyin() 関数は、明示されたユーザ空間アドレスから sbuflen バイトをコピーします。

sbuf_bcpy() 関数は、 sbuf の内容をバッファ buf の最初の len バイトで置き換えます。

sbuf_cat() 関数は、NUL 文字で終端された文字列 strsbuf の現在位置に追加します。

sbuf_set_drain() 関数は、 sbuf のための drain 関数 func を設定し、コールバックで drain に渡されるポインタ arg を記録します。 sbuf_len が 0 以外である間に、drain 関数を変更することはできません。

登録された drain 関数 sbuf_drain_func は、 sbuf_set_drain() に提供された引数 arg、sbuf の内容であるバイト文字列へのポインタ data とデータの長さの len で呼び出されます。 drain 関数が存在しているなら、sbuf の内部バッファが満杯であるか、または sbuf_finish() の代わりに呼び出されます。 drain 関数は、一部またはすべてのデータを排出 (drain) しますが、少なくとも 1 バイトを排出しなければなりません。 drain 関数からの返り値が、正であるなら、どのくらいのバイトを排出したかを示します。負であるなら、返り値は、これから返される負のエラーコードまたは sbuf_finish() への遅い呼び出しを示します。返された排出された長さは、0 のはずはありません。 drain をバッファリングしないようにするためには、 2 バイトのバッファで sbuf を初期化します。 drain は、sbuf に追加されたあらゆるバイトに対して呼び出されます。 drain がある sbuf で sbuf_bcopyin(), sbuf_copyin(), sbuf_trim() と sbuf_data() 関数を使用することができません。

sbuf_copyin() 関数は、NUL 文字で終端された文字列を明示されたユーザ空間アドレスから sbuf にコピーします。 len 引数が 0 でない場合には、 len 文字を越えない文字 (終端の NUL は、数えません) がコピーされ、そうでない場合には、文字列全体、または sbuf に詰め込むことが出来るだけの文字をコピーします。

sbuf_cpy() 関数は、 sbuf の内容を NUL 文字で終端された文字列 str で置き換えます。これは、新しい sbuf で、または sbuf_clear() か sbuf_setpos() でその位置を 0 にリセットされている sbuf で、 sbuf_cat() を呼び出すことと等価です。

sbuf_printf() 関数は、 fmt によって指されているフォーマット文字列に従ってその引数をフォーマットし、その結果の文字列を sbuf の現在位置に追加します。

sbuf_vprintf() 関数は、 sbuf_printf() と同様に振舞いますが、引数が可変長引数リスト ap から取得されることが違います。

sbuf_putc() 関数は、文字 csbuf の現在位置に追加します。

sbuf_trim() 関数は、末尾の空白を sbuf から除去します。

sbuf_error() 関数は、ドレイン関数から、または sbuf がオーバフローしたなら、ENOMEM のいずれかの、 sbuf が蓄積した任意のエラー値を返します。一般的に、この関数は、必要ではありません、代わりに、 sbuf_finish() からのエラーコードは、sbuf にエラーがあったかどうかを発見するよい方法です。

sbuf_finish() 関数は、 sbuf のすべてのデータがフラッシュされるまで、存在しているなら、アタッチされた drain 関数を呼び出します。アタッチされた drain がないなら、 sbuf_finish() は、 sbuf を NUL で終了します。いずれにしても、 sbuf_clear() が sbuf をリセットするために使用されるまで、もはや sbuf_setpos(), sbuf_cat(), sbuf_cpy(), sbuf_printf() または sbuf_putc() を使用して変更されないことを意味する、終了しているとして sbuf をマークします。

sbuf_data() 関数は、実際の文字列を返します。 sbuf_data() は、終了した sbuf でのみ動作します。 sbuf_len() 関数は、文字列の長さを返します。アタッチされた drain がある sbuf に関して、 sbuf_len() は、排出されていないデータの長さを返します。 sbuf_done() は、 sbuf が終了しているなら、0 以外を返します。

sbuf_start_section() と sbuf_end_section() 関数は、自動的なセクションの整列のために使用されます。引数 padc は、詰め物のために使用される詰め物のサイズと文字を指定します。引数 old_lenpold_len は、入れ子にされたセクションが使用されるとき、現在のセクションの長さを保存して復旧するためのものです。トップレベルのセクションに対して、それぞれ、 old_lenpold_len のために NULL と-1 を指定することができます。

操作が sbuf をオーバフローさせるなら、 sbuf が、 sbuf_finish() を使用してい終了されるか、または sbuf_clear() 使用してリセットするか、またはその位置が、 sbuf_setpos() を使用して、その記憶域のバッファのサイズ未満の 0 と 1 の間の値にリセットされるか、または sbuf_cpy() を使用して十分に短い文字列に再初期化されるまで、sbuf でのほとんどの続く操作は、失敗します。

ユーザ空間の drain は、示されるように常に機能するというわけではありません。 drain 関数がオーバフローのときに sbuf_putc, sbuf_bcat, sbuf_cat 関数からただちに呼び出されている間に、 sbuf_printfsbuf_vprintf は、現在、オーバフロー起こった後まで、オーバフローがあるかを決定する方法がなく、書式の文字列の部分的な拡張ができません。したがって、libsbuf を使用するとき、バッファは、たとえ drain がアタッチされていても、単一の printf の呼び出しの完了を許可するために拡張されるかもしれません、

戻り値

sbuf_new() 関数は、記憶域のバッファを割り付けることに失敗したなら、 NULL を返し、そうでなければ、新しい sbuf へのポインタを返します。

sbuf_setpos() 関数は、 pos が不正であったなら、-1 を返し、そうでなければ、0 を返します。

sbuf_cat(), sbuf_cpy(), sbuf_printf(), sbuf_putc() と sbuf_trim() 関数は、すべて、バッファがオーバフローしたなら、-1 を返し、そうでなければ、0 を返します。

sbuf_error() 関数は、バッファがオーバフローするか、または drain エラーがあるなら、 0 以外の値を返し、そうでなければ、0 を返します。

sbuf_len() 関数は、バッファがオーバフローしたなら、-1 を返します。

sbuf_copyin() 関数は、ユーザランドから文字列をコピーすることが失敗したなら、-1 を返し、そうでなければ、コピーされたバイト数を返します。

sbuf_end_section() 関数は、セクションの長さを返し、バッファにエラーがあるなら、-1 を返します。

(カーネルバージョンの) sbuf_finish( 9) 関数は、終わる前に、sbuf がオーバフローしたなら、 ENOMEM を返し、アタッチされているなら、drain からエラーコードを返します。

(ユーザランドバージョンの) sbuf_finish( 3) 関数は、成功すれば、0 を返し、エラーであるなら、-1 を返し errno を設定します。

使用例

#include <sys/sbuf.h> 
 
struct sbuf *sb; 
 
sb = sbuf_new_auto(); 
sbuf_cat(sb, "Customers found:\n"); 
TAILQ_FOREACH(foo, &foolist, list) { 
 sbuf_printf(sb, "   %4d %s\n", foo->index, foo->name); 
 sbuf_printf(sb, "      Address: %s\n", foo->address); 
 sbuf_printf(sb, "      Zip: %s\n", foo->zipcode); 
} 
if (sbuf_finish(sb) != 0) /* ありとあらゆるエラーをチェックする */ 
 err(1, "Could not generate message"); 
transmit_msg(sbuf_data(sb), sbuf_len(sb)); 
sbuf_delete(sb);

歴史

sbuf 関数ファミリは、 FreeBSD 4.4 ではじめて登場しました。

作者

sbuf 関数ファミリは、 Poul-Henning Kamp <phk@FreeBSD.org>によって設計され、 Dag-Erling Smørgrav <des@FreeBSD.org>によって実装されました。追加の改良は、 Justin T. Gibbs <gibbs@FreeBSD.org>によって提案されました。自動拡張のサポートは、 Kelly Yancey <kbyanc@FreeBSD.org>によって追加されました。 drain 機能は、 Matthew Fleming <mdf@FreeBSD.org>によって追加されました。

このマニュアルページは、 Dag-Erling Smørgrav <des@FreeBSD.org>によって書かれました。

April 11, 2013 FreeBSD