XDR ルーチンを使用するときは、前もってメモリーを割り当てておかなければならない場合や、必要なメモリーサイズを決定しておかなければならない場合があります。 XDR 変換ルーチン用のメモリーの割り当てと割り当て解除を制御する必要がある場合は、 xdr_sizeof() ルーチンを使用します。このルーチンは XDR フィルタ関数の 1 つ (func()) を使用して、データの符号化と復号化に必要なバイト数を返します。 xdr_sizeof() 関数が返す値には、RPC ヘッダーやレコードマーカーは含まれません。必要なメモリーサイズを正確に計算するにはこれらのバイト数も追加しなければなりません。 エラーが起こった場合、xdr_sizeof() はゼロを返します。
xdr_sizeof(xdrproc_t func, void *data) |
RPC 環境外で XDR を使用するアプリケーションでメモリーを割り当てるときや、通信プロトコルを選択するとき、下位レベルの RPC でクライアント作成関数とサーバー作成関数を実行するときに、xdr_sizeof() を使用してください。
次の 2 つのコーディング例は xdr_sizeof () の 2 つの使用例を示しています。
#include <rpc/rpc.h>
/*
* この関数への入力引数は、CLIENT ハンドル、XDR 関数、XDR 変換を行う
* データへのポインタです。XDR 変換を行うデータが、CLIENT ハンドルに
* 結合しているトランスポートで送信可能な大きさの場合は TRUE、
* 大き過ぎて送信不可能な場合は FALSE を返します。
*/
bool_t
cansend(cl, xdrfunc, xdrdata)
CLIENT *cl;
xdrproc_t xdrfunc;
void *xdrdata;
{
int fd;
struct t_info tinfo;
if (clnt_control(cl, CLGET_FD, &fd) == -1) {
/* ハンドルの clnt_control() エラー */
return (FALSE);
}
if (t_getinfo(fd, &tinfo) == -1) {
/* ハンドルの t_getinfo() エラー */
return (FALSE);
} else {
if (tinfo.servtype == T_CLTS) {
/*
* 現在使用しているのは非接続型トランスポートです。
* xdr_sizeof() を使用して、メモリー要求がこのトランスポートでは
* 大き過ぎないか調べます。
*/
switch(tinfo.tsdu) {
case 0: /* TSDU の概念なし */
case -2: /* 通常データの送信不可能 */
return (FALSE);
break;
case -1: /* TSDU サイズの制限なし */
return (TRUE);
break;
default:
if (tinfo.tsdu < xdr_sizeof(xdrfunc, xdrdata))
return (FALSE);
else
return (TRUE);
}
} else
return (TRUE);
}
}
次は xdr_sizeof() の 2 つめの使用例です。
#include <sys/statvfs.h>
#include <sys/sysmacros.h>
/*
* この関数への入力引数は、ファイル名、XDR 関数、XDR 変換を行うデータへの
* ポインタです。この関数は、ファイルが置かれているファイルシステムに、
* データを XDR 変換するのに必要な空間が残っていれば TRUE を返します。
* ファイルシステムに関して statvfs(2) で得られる情報はブロック数単位
* なので、xdr_sizeof() の戻り値もバイト数からディスクブロック数に
* 変換しなければならないことに注意してください。
*/
bool_t
canwrite(file, xdrfunc, xdrdata)
char *file;
xdrproc_t xdrfunc;
void *xdrdata;
{
struct statvfs s;
if (statvfs(file, &s) == -1) {
/* ハンドルの statvfs() エラー */
return (FALSE);
}
if (s.f_bavail>= btod(xdr_sizeof(xdrfunc, xdrdata)))
return (TRUE);
else
return (FALSE);
}