ONC+ 開発ガイド

XDR ルーチンで必要なメモリ

XDR ルーチンを使用するときは、前もってメモリを割り当てておかなければならない (または、必要なメモリサイズを決定しておかなければならない)場合があります。XDR 変換ルーチンで使用するメモリの割り当てや割り当て解除が必要なときのために、xdr_sizeof() というルーチンが提供されています。xdr_sizeof() は、XDR フィルタルーチン (func()) がデータ (data()) の符号化や復号化で使用するバイト数を返します。xdr_sizeof() が返す値には、RPC ヘッダやレコードマークは含まれていませんので、必要なメモリサイズを正確に求めるには、それらのバイト数も加えなければなりません。エラーが起こった場合、xdr_sizeof() はゼロを返します。

xdr_sizeof(xdrproc_t func, void *data)

xdr_sizeof() は、RPC 環境以外で XDR を使用するアプリケーションでメモリを割り当てるとき、トランスポートプロトコルを選択するとき、下位レベルの RPC を使用してクライアント作成関数やサーバ作成関数を実行するときに特に便利です。

例 A-5例 A-6 で、xdr_sizeof()の 2 通りの使用方法を説明します。


例 A-5 xdr_sizeof() の使用例 1

#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);
	}
}

例 A-6 は、xdr_sizeof() の使用例 2 になります。


例 A-6 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);
}