xdr.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
  2. /*
  3. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4. * unrestricted use provided that this legend is included on all tape
  5. * media and as a part of the software program in whole or part. Users
  6. * may copy or modify Sun RPC without charge, but are not authorized
  7. * to license or distribute it to anyone else except as part of a product or
  8. * program developed by the user.
  9. *
  10. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13. *
  14. * Sun RPC is provided with no support and without any obligation on the
  15. * part of Sun Microsystems, Inc. to assist in its use, correction,
  16. * modification or enhancement.
  17. *
  18. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20. * OR ANY PART THEREOF.
  21. *
  22. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23. * or profits or other special, indirect and consequential damages, even if
  24. * Sun has been advised of the possibility of such damages.
  25. *
  26. * Sun Microsystems, Inc.
  27. * 2550 Garcia Avenue
  28. * Mountain View, California 94043
  29. */
  30. #if !defined(lint) && defined(SCCSIDS)
  31. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  32. #endif
  33. /*
  34. * xdr.c, Generic XDR routines implementation.
  35. *
  36. * Copyright (C) 1986, Sun Microsystems, Inc.
  37. *
  38. * These are the "generic" xdr routines used to serialize and de-serialize
  39. * most common data items. See xdr.h for more info on the interface to
  40. * xdr.
  41. */
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <rpc/types.h>
  45. #include <rpc/xdr.h>
  46. #include <string.h>
  47. /*
  48. * constants specific to the xdr "protocol"
  49. */
  50. #define XDR_FALSE ((long) 0)
  51. #define XDR_TRUE ((long) 1)
  52. #define LASTUNSIGNED ((unsigned int) 0-1)
  53. /*
  54. * for unit alignment
  55. */
  56. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  57. /*
  58. * Free a data structure using XDR
  59. * Not a filter, but a convenient utility nonetheless
  60. */
  61. void xdr_free(xdrproc_t proc, char* objp)
  62. {
  63. XDR x;
  64. x.x_op = XDR_FREE;
  65. (*proc) (&x, objp);
  66. }
  67. /*
  68. * XDR nothing
  69. */
  70. bool_t xdr_void( /* xdrs, addr */ )
  71. /* XDR *xdrs; */
  72. /* char* addr; */
  73. {
  74. return (TRUE);
  75. }
  76. /*
  77. * XDR integers
  78. */
  79. bool_t xdr_int(XDR* xdrs, int* ip)
  80. {
  81. if (sizeof(int) == sizeof(long)) {
  82. return (xdr_long(xdrs, (long *) ip));
  83. } else if (sizeof(int) < sizeof(long)) {
  84. long l;
  85. switch (xdrs->x_op) {
  86. case XDR_ENCODE:
  87. l = (long) *ip;
  88. return XDR_PUTLONG(xdrs, &l);
  89. case XDR_DECODE:
  90. if (!XDR_GETLONG(xdrs, &l))
  91. return FALSE;
  92. *ip = (int) l;
  93. case XDR_FREE:
  94. return TRUE;
  95. }
  96. return FALSE;
  97. } else {
  98. return (xdr_short(xdrs, (short *) ip));
  99. }
  100. }
  101. /*
  102. * XDR unsigned integers
  103. */
  104. bool_t xdr_u_int(XDR* xdrs, unsigned int* up)
  105. {
  106. if (sizeof(unsigned int) == sizeof(unsigned long)) {
  107. return (xdr_u_long(xdrs, (unsigned long *) up));
  108. } else if (sizeof(unsigned int) < sizeof(unsigned long)) {
  109. unsigned long l;
  110. switch (xdrs->x_op) {
  111. case XDR_ENCODE:
  112. l = (unsigned long) *up;
  113. return XDR_PUTLONG(xdrs, (long*)&l);
  114. case XDR_DECODE:
  115. if (!XDR_GETLONG(xdrs, (long*)&l))
  116. return FALSE;
  117. *up = (unsigned int) l;
  118. case XDR_FREE:
  119. return TRUE;
  120. }
  121. return FALSE;
  122. } else {
  123. return (xdr_short(xdrs, (short *) up));
  124. }
  125. }
  126. /*
  127. * XDR long integers
  128. * same as xdr_u_long - open coded to save a proc call!
  129. */
  130. bool_t xdr_long(XDR* xdrs, long* lp)
  131. {
  132. if (xdrs->x_op == XDR_ENCODE
  133. && (sizeof(int32_t) == sizeof(long)
  134. || (int32_t) *lp == *lp))
  135. return (XDR_PUTLONG(xdrs, lp));
  136. if (xdrs->x_op == XDR_DECODE)
  137. return (XDR_GETLONG(xdrs, lp));
  138. if (xdrs->x_op == XDR_FREE)
  139. return (TRUE);
  140. return (FALSE);
  141. }
  142. /*
  143. * XDR unsigned long integers
  144. * same as xdr_long - open coded to save a proc call!
  145. */
  146. bool_t xdr_u_long(XDR* xdrs, unsigned long* ulp)
  147. {
  148. if (xdrs->x_op == XDR_DECODE) {
  149. long l;
  150. if (XDR_GETLONG(xdrs, &l) == FALSE)
  151. return FALSE;
  152. *ulp = (uint32_t) l;
  153. return TRUE;
  154. }
  155. if (xdrs->x_op == XDR_ENCODE) {
  156. if (sizeof(uint32_t) != sizeof(unsigned long)
  157. && (uint32_t) *ulp != *ulp)
  158. return FALSE;
  159. return (XDR_PUTLONG(xdrs, (long *) ulp));
  160. }
  161. if (xdrs->x_op == XDR_FREE)
  162. return (TRUE);
  163. return (FALSE);
  164. }
  165. /*
  166. * XDR long long integers
  167. */
  168. bool_t xdr_longlong_t (XDR * xdrs, long long* llp)
  169. {
  170. int32_t t1, t2;
  171. switch (xdrs->x_op)
  172. {
  173. case XDR_ENCODE:
  174. t1 = (int32_t) ((*llp) >> 32);
  175. t2 = (int32_t) (*llp);
  176. return (XDR_PUTLONG (xdrs, &t1) && XDR_PUTLONG (xdrs, &t2));
  177. case XDR_DECODE:
  178. if (!XDR_GETLONG (xdrs, &t1) || !XDR_GETLONG (xdrs, &t2))
  179. return FALSE;
  180. *llp = ((int64_t) t1) << 32;
  181. *llp |= (uint32_t) t2;
  182. return TRUE;
  183. case XDR_FREE:
  184. return TRUE;
  185. }
  186. return FALSE;
  187. }
  188. /*
  189. * XDR unsigned long long integers
  190. */
  191. bool_t xdr_u_longlong_t (XDR * xdrs, unsigned long long* ullp)
  192. {
  193. uint32_t t1, t2;
  194. switch (xdrs->x_op)
  195. {
  196. case XDR_ENCODE:
  197. t1 = (uint32_t) ((*ullp) >> 32);
  198. t2 = (uint32_t) (*ullp);
  199. return (XDR_PUTLONG (xdrs, (int32_t *)&t1) &&
  200. XDR_PUTLONG (xdrs, (int32_t *)&t2));
  201. case XDR_DECODE:
  202. if (!XDR_GETLONG (xdrs, (int32_t *)&t1) ||
  203. !XDR_GETLONG (xdrs, (int32_t *)&t2))
  204. return FALSE;
  205. *ullp = ((uint64_t) t1) << 32;
  206. *ullp |= t2;
  207. return TRUE;
  208. case XDR_FREE:
  209. return TRUE;
  210. }
  211. return FALSE;
  212. }
  213. /*
  214. * XDR short integers
  215. */
  216. bool_t xdr_short(XDR* xdrs, short* sp)
  217. {
  218. long l;
  219. switch (xdrs->x_op) {
  220. case XDR_ENCODE:
  221. l = (long) *sp;
  222. return (XDR_PUTLONG(xdrs, &l));
  223. case XDR_DECODE:
  224. if (!XDR_GETLONG(xdrs, &l)) {
  225. return (FALSE);
  226. }
  227. *sp = (short) l;
  228. return (TRUE);
  229. case XDR_FREE:
  230. return (TRUE);
  231. }
  232. return (FALSE);
  233. }
  234. /*
  235. * XDR unsigned short integers
  236. */
  237. bool_t xdr_u_short(XDR* xdrs, unsigned short* usp)
  238. {
  239. unsigned long l;
  240. switch (xdrs->x_op) {
  241. case XDR_ENCODE:
  242. l = (unsigned long) * usp;
  243. return (XDR_PUTLONG(xdrs, (long*)&l));
  244. case XDR_DECODE:
  245. if (!XDR_GETLONG(xdrs, (long*)&l)) {
  246. return (FALSE);
  247. }
  248. *usp = (unsigned short) l;
  249. return (TRUE);
  250. case XDR_FREE:
  251. return (TRUE);
  252. }
  253. return (FALSE);
  254. }
  255. /*
  256. * XDR a char
  257. */
  258. bool_t xdr_char(XDR* xdrs, char* cp)
  259. {
  260. int i;
  261. i = (*cp);
  262. if (!xdr_int(xdrs, &i)) {
  263. return (FALSE);
  264. }
  265. *cp = i;
  266. return (TRUE);
  267. }
  268. /*
  269. * XDR an unsigned char
  270. */
  271. bool_t xdr_u_char(XDR* xdrs, unsigned char* cp)
  272. {
  273. unsigned int u;
  274. u = (*cp);
  275. if (!xdr_u_int(xdrs, &u)) {
  276. return (FALSE);
  277. }
  278. *cp = u;
  279. return (TRUE);
  280. }
  281. /*
  282. * XDR booleans
  283. */
  284. bool_t xdr_bool(XDR *xdrs, bool_t *bp)
  285. {
  286. long lb;
  287. switch (xdrs->x_op) {
  288. case XDR_ENCODE:
  289. lb = *bp ? XDR_TRUE : XDR_FALSE;
  290. return (XDR_PUTLONG(xdrs, &lb));
  291. case XDR_DECODE:
  292. if (!XDR_GETLONG(xdrs, &lb)) {
  293. return (FALSE);
  294. }
  295. *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  296. return (TRUE);
  297. case XDR_FREE:
  298. return (TRUE);
  299. }
  300. return (FALSE);
  301. }
  302. /*
  303. * XDR enumerations
  304. */
  305. bool_t xdr_enum(XDR *xdrs, enum_t *ep)
  306. {
  307. /*
  308. * enums are treated as ints
  309. */
  310. return (xdr_long(xdrs, (long *) ep));
  311. }
  312. /*
  313. * XDR opaque data
  314. * Allows the specification of a fixed size sequence of opaque bytes.
  315. * cp points to the opaque object and cnt gives the byte length.
  316. */
  317. bool_t xdr_opaque(XDR *xdrs, char* cp, unsigned int cnt)
  318. {
  319. register unsigned int rndup;
  320. static char crud[BYTES_PER_XDR_UNIT];
  321. /*
  322. * if no data we are done
  323. */
  324. if (cnt == 0)
  325. return (TRUE);
  326. /*
  327. * round byte count to full xdr units
  328. */
  329. rndup = cnt % BYTES_PER_XDR_UNIT;
  330. if (rndup > 0)
  331. rndup = BYTES_PER_XDR_UNIT - rndup;
  332. if (xdrs->x_op == XDR_DECODE) {
  333. if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  334. return (FALSE);
  335. }
  336. if (rndup == 0)
  337. return (TRUE);
  338. return (XDR_GETBYTES(xdrs, crud, rndup));
  339. }
  340. if (xdrs->x_op == XDR_ENCODE) {
  341. if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  342. return (FALSE);
  343. }
  344. if (rndup == 0)
  345. return (TRUE);
  346. return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  347. }
  348. if (xdrs->x_op == XDR_FREE) {
  349. return (TRUE);
  350. }
  351. return (FALSE);
  352. }
  353. /*
  354. * XDR counted bytes
  355. * *cpp is a pointer to the bytes, *sizep is the count.
  356. * If *cpp is NULL maxsize bytes are allocated
  357. */
  358. bool_t xdr_bytes(XDR *xdrs, char** cpp, unsigned int *sizep, unsigned int maxsize)
  359. {
  360. register char *sp = *cpp; /* sp is the actual string pointer */
  361. register unsigned int nodesize;
  362. /*
  363. * first deal with the length since xdr bytes are counted
  364. */
  365. if (!xdr_u_int(xdrs, sizep)) {
  366. return (FALSE);
  367. }
  368. nodesize = *sizep;
  369. if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  370. return (FALSE);
  371. }
  372. /*
  373. * now deal with the actual bytes
  374. */
  375. switch (xdrs->x_op) {
  376. case XDR_DECODE:
  377. if (nodesize == 0) {
  378. return (TRUE);
  379. }
  380. if (sp == NULL) {
  381. *cpp = sp = (char *) rt_malloc(nodesize);
  382. }
  383. if (sp == NULL) {
  384. rt_kprintf("xdr_bytes: out of memory\n");
  385. return (FALSE);
  386. }
  387. /* fall into ... */
  388. case XDR_ENCODE:
  389. return (xdr_opaque(xdrs, sp, nodesize));
  390. case XDR_FREE:
  391. if (sp != NULL) {
  392. rt_free(sp);
  393. *cpp = NULL;
  394. }
  395. return (TRUE);
  396. }
  397. return (FALSE);
  398. }
  399. /*
  400. * Implemented here due to commonality of the object.
  401. */
  402. bool_t xdr_netobj(XDR *xdrs, struct netobj *np)
  403. {
  404. return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  405. }
  406. /*
  407. * XDR a descriminated union
  408. * Support routine for discriminated unions.
  409. * You create an array of xdrdiscrim structures, terminated with
  410. * an entry with a null procedure pointer. The routine gets
  411. * the discriminant value and then searches the array of xdrdiscrims
  412. * looking for that value. It calls the procedure given in the xdrdiscrim
  413. * to handle the discriminant. If there is no specific routine a default
  414. * routine may be called.
  415. * If there is no specific or default routine an error is returned.
  416. */
  417. bool_t xdr_union(XDR* xdrs, enum_t* dscmp, char* unp, const struct xdr_discrim* choices, xdrproc_t dfault)
  418. {
  419. register enum_t dscm;
  420. /*
  421. * we deal with the discriminator; it's an enum
  422. */
  423. if (!xdr_enum(xdrs, dscmp)) {
  424. return (FALSE);
  425. }
  426. dscm = *dscmp;
  427. /*
  428. * search choices for a value that matches the discriminator.
  429. * if we find one, execute the xdr routine for that value.
  430. */
  431. for (; choices->proc != NULL_xdrproc_t; choices++) {
  432. if (choices->value == dscm)
  433. return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
  434. }
  435. /*
  436. * no match - execute the default xdr routine if there is one
  437. */
  438. return ((dfault == NULL_xdrproc_t) ? FALSE :
  439. (*dfault) (xdrs, unp, LASTUNSIGNED));
  440. }
  441. /*
  442. * Non-portable xdr primitives.
  443. * Care should be taken when moving these routines to new architectures.
  444. */
  445. /*
  446. * XDR null terminated ASCII strings
  447. * xdr_string deals with "C strings" - arrays of bytes that are
  448. * terminated by a NULL character. The parameter cpp references a
  449. * pointer to storage; If the pointer is null, then the necessary
  450. * storage is allocated. The last parameter is the max allowed length
  451. * of the string as specified by a protocol.
  452. */
  453. bool_t xdr_string(XDR *xdrs, char **cpp, unsigned int maxsize)
  454. {
  455. register char *sp = *cpp; /* sp is the actual string pointer */
  456. unsigned int size;
  457. unsigned int nodesize;
  458. /*
  459. * first deal with the length since xdr strings are counted-strings
  460. */
  461. switch (xdrs->x_op) {
  462. case XDR_FREE:
  463. if (sp == NULL) {
  464. return (TRUE); /* already free */
  465. }
  466. /* fall through... */
  467. case XDR_ENCODE:
  468. size = strlen(sp);
  469. break;
  470. }
  471. if (!xdr_u_int(xdrs, &size)) {
  472. return (FALSE);
  473. }
  474. if (size > maxsize) {
  475. return (FALSE);
  476. }
  477. nodesize = size + 1;
  478. /*
  479. * now deal with the actual bytes
  480. */
  481. switch (xdrs->x_op) {
  482. case XDR_DECODE:
  483. if (nodesize == 0) {
  484. return (TRUE);
  485. }
  486. if (sp == NULL)
  487. *cpp = sp = (char *) rt_malloc(nodesize);
  488. if (sp == NULL) {
  489. rt_kprintf("xdr_string: out of memory\n");
  490. return (FALSE);
  491. }
  492. sp[size] = 0;
  493. /* fall into ... */
  494. case XDR_ENCODE:
  495. return (xdr_opaque(xdrs, sp, size));
  496. case XDR_FREE:
  497. rt_free(sp);
  498. *cpp = NULL;
  499. return (TRUE);
  500. }
  501. return (FALSE);
  502. }
  503. /*
  504. * Wrapper for xdr_string that can be called directly from
  505. * routines like clnt_call
  506. */
  507. bool_t xdr_wrapstring(XDR *xdrs, char **cpp)
  508. {
  509. if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
  510. return (TRUE);
  511. }
  512. return (FALSE);
  513. }
  514. /*
  515. * XDR an array of arbitrary elements
  516. * *addrp is a pointer to the array, *sizep is the number of elements.
  517. * If addrp is NULL (*sizep * elsize) bytes are allocated.
  518. * elsize is the size (in bytes) of each element, and elproc is the
  519. * xdr procedure to call to handle each element of the array.
  520. */
  521. bool_t xdr_array(XDR *xdrs, char **addrp, unsigned int *sizep, unsigned int maxsize, unsigned int elsize, xdrproc_t elproc)
  522. {
  523. register unsigned int i;
  524. register char* target = *addrp;
  525. register unsigned int c; /* the actual element count */
  526. register bool_t stat = TRUE;
  527. register unsigned int nodesize;
  528. /* like strings, arrays are really counted arrays */
  529. if (!xdr_u_int(xdrs, sizep)) {
  530. return (FALSE);
  531. }
  532. c = *sizep;
  533. if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
  534. return (FALSE);
  535. }
  536. /* duh, look for integer overflow (fefe) */
  537. {
  538. unsigned int i;
  539. nodesize = 0;
  540. for (i=c; i; --i) {
  541. unsigned int tmp=nodesize+elsize;
  542. if (tmp<nodesize) /* overflow */
  543. return FALSE;
  544. nodesize=tmp;
  545. }
  546. }
  547. /*
  548. * if we are deserializing, we may need to allocate an array.
  549. * We also save time by checking for a null array if we are freeing.
  550. */
  551. if (target == NULL)
  552. switch (xdrs->x_op) {
  553. case XDR_DECODE:
  554. if (c == 0)
  555. return (TRUE);
  556. *addrp = target = rt_malloc(nodesize);
  557. if (target == NULL) {
  558. rt_kprintf("xdr_array: out of memory\n");
  559. return (FALSE);
  560. }
  561. memset(target, 0, nodesize);
  562. break;
  563. case XDR_FREE:
  564. return (TRUE);
  565. }
  566. /*
  567. * now we xdr each element of array
  568. */
  569. for (i = 0; (i < c) && stat; i++) {
  570. stat = (*elproc) (xdrs, target, LASTUNSIGNED);
  571. target += elsize;
  572. }
  573. /*
  574. * the array may need freeing
  575. */
  576. if (xdrs->x_op == XDR_FREE) {
  577. rt_free(*addrp);
  578. *addrp = NULL;
  579. }
  580. return (stat);
  581. }
  582. /*
  583. * xdr_vector():
  584. *
  585. * XDR a fixed length array. Unlike variable-length arrays,
  586. * the storage of fixed length arrays is static and unfreeable.
  587. * > basep: base of the array
  588. * > size: size of the array
  589. * > elemsize: size of each element
  590. * > xdr_elem: routine to XDR each element
  591. */
  592. bool_t xdr_vector(XDR *xdrs, char *basep, unsigned int nelem, unsigned int elemsize, xdrproc_t xdr_elem)
  593. {
  594. register unsigned int i;
  595. register char *elptr;
  596. elptr = basep;
  597. for (i = 0; i < nelem; i++) {
  598. if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) {
  599. return (FALSE);
  600. }
  601. elptr += elemsize;
  602. }
  603. return (TRUE);
  604. }
  605. /*
  606. * XDR an indirect pointer
  607. * xdr_reference is for recursively translating a structure that is
  608. * referenced by a pointer inside the structure that is currently being
  609. * translated. pp references a pointer to storage. If *pp is null
  610. * the necessary storage is allocated.
  611. * size is the sizeof the referneced structure.
  612. * proc is the routine to handle the referenced structure.
  613. */
  614. bool_t xdr_reference(XDR *xdrs, char **pp, unsigned int size, xdrproc_t proc)
  615. {
  616. register char* loc = *pp;
  617. register bool_t stat;
  618. if (loc == NULL)
  619. switch (xdrs->x_op) {
  620. case XDR_FREE:
  621. return (TRUE);
  622. case XDR_DECODE:
  623. *pp = loc = (char*) rt_malloc(size);
  624. if (loc == NULL) {
  625. rt_kprintf("xdr_reference: out of memory\n");
  626. return (FALSE);
  627. }
  628. memset(loc, 0, (int) size);
  629. break;
  630. }
  631. stat = (*proc) (xdrs, loc, LASTUNSIGNED);
  632. if (xdrs->x_op == XDR_FREE) {
  633. rt_free(loc);
  634. *pp = NULL;
  635. }
  636. return (stat);
  637. }
  638. /*
  639. * xdr_pointer():
  640. *
  641. * XDR a pointer to a possibly recursive data structure. This
  642. * differs with xdr_reference in that it can serialize/deserialiaze
  643. * trees correctly.
  644. *
  645. * What's sent is actually a union:
  646. *
  647. * union object_pointer switch (boolean b) {
  648. * case TRUE: object_data data;
  649. * case FALSE: void nothing;
  650. * }
  651. *
  652. * > objpp: Pointer to the pointer to the object.
  653. * > obj_size: size of the object.
  654. * > xdr_obj: routine to XDR an object.
  655. *
  656. */
  657. bool_t xdr_pointer(XDR *xdrs, char **objpp, unsigned int obj_size, xdrproc_t xdr_obj)
  658. {
  659. bool_t more_data;
  660. more_data = (*objpp != NULL);
  661. if (!xdr_bool(xdrs, &more_data)) {
  662. return (FALSE);
  663. }
  664. if (!more_data) {
  665. *objpp = NULL;
  666. return (TRUE);
  667. }
  668. return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
  669. }