xdr.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  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(xdrs, bp)
  285. register XDR *xdrs;
  286. bool_t *bp;
  287. {
  288. long lb;
  289. switch (xdrs->x_op) {
  290. case XDR_ENCODE:
  291. lb = *bp ? XDR_TRUE : XDR_FALSE;
  292. return (XDR_PUTLONG(xdrs, &lb));
  293. case XDR_DECODE:
  294. if (!XDR_GETLONG(xdrs, &lb)) {
  295. return (FALSE);
  296. }
  297. *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  298. return (TRUE);
  299. case XDR_FREE:
  300. return (TRUE);
  301. }
  302. return (FALSE);
  303. }
  304. /*
  305. * XDR enumerations
  306. */
  307. bool_t xdr_enum(xdrs, ep)
  308. XDR *xdrs;
  309. enum_t *ep;
  310. {
  311. long lp;
  312. lp = *ep;
  313. /*
  314. * enums are treated as ints
  315. */
  316. return (xdr_long(xdrs, (long *) ep));
  317. }
  318. /*
  319. * XDR opaque data
  320. * Allows the specification of a fixed size sequence of opaque bytes.
  321. * cp points to the opaque object and cnt gives the byte length.
  322. */
  323. bool_t xdr_opaque(xdrs, cp, cnt)
  324. register XDR *xdrs;
  325. char* cp;
  326. register unsigned int cnt;
  327. {
  328. register unsigned int rndup;
  329. static char crud[BYTES_PER_XDR_UNIT];
  330. /*
  331. * if no data we are done
  332. */
  333. if (cnt == 0)
  334. return (TRUE);
  335. /*
  336. * round byte count to full xdr units
  337. */
  338. rndup = cnt % BYTES_PER_XDR_UNIT;
  339. if (rndup > 0)
  340. rndup = BYTES_PER_XDR_UNIT - rndup;
  341. if (xdrs->x_op == XDR_DECODE) {
  342. if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  343. return (FALSE);
  344. }
  345. if (rndup == 0)
  346. return (TRUE);
  347. return (XDR_GETBYTES(xdrs, crud, rndup));
  348. }
  349. if (xdrs->x_op == XDR_ENCODE) {
  350. if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  351. return (FALSE);
  352. }
  353. if (rndup == 0)
  354. return (TRUE);
  355. return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  356. }
  357. if (xdrs->x_op == XDR_FREE) {
  358. return (TRUE);
  359. }
  360. return (FALSE);
  361. }
  362. /*
  363. * XDR counted bytes
  364. * *cpp is a pointer to the bytes, *sizep is the count.
  365. * If *cpp is NULL maxsize bytes are allocated
  366. */
  367. bool_t xdr_bytes(xdrs, cpp, sizep, maxsize)
  368. register XDR *xdrs;
  369. char **cpp;
  370. register unsigned int *sizep;
  371. unsigned int maxsize;
  372. {
  373. register char *sp = *cpp; /* sp is the actual string pointer */
  374. register unsigned int nodesize;
  375. /*
  376. * first deal with the length since xdr bytes are counted
  377. */
  378. if (!xdr_u_int(xdrs, sizep)) {
  379. return (FALSE);
  380. }
  381. nodesize = *sizep;
  382. if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  383. return (FALSE);
  384. }
  385. /*
  386. * now deal with the actual bytes
  387. */
  388. switch (xdrs->x_op) {
  389. case XDR_DECODE:
  390. if (nodesize == 0) {
  391. return (TRUE);
  392. }
  393. if (sp == NULL) {
  394. *cpp = sp = (char *) rt_malloc(nodesize);
  395. }
  396. if (sp == NULL) {
  397. rt_kprintf("xdr_bytes: out of memory\n");
  398. return (FALSE);
  399. }
  400. /* fall into ... */
  401. case XDR_ENCODE:
  402. return (xdr_opaque(xdrs, sp, nodesize));
  403. case XDR_FREE:
  404. if (sp != NULL) {
  405. rt_free(sp);
  406. *cpp = NULL;
  407. }
  408. return (TRUE);
  409. }
  410. return (FALSE);
  411. }
  412. /*
  413. * Implemented here due to commonality of the object.
  414. */
  415. bool_t xdr_netobj(xdrs, np)
  416. XDR *xdrs;
  417. struct netobj *np;
  418. {
  419. return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  420. }
  421. /*
  422. * XDR a descriminated union
  423. * Support routine for discriminated unions.
  424. * You create an array of xdrdiscrim structures, terminated with
  425. * an entry with a null procedure pointer. The routine gets
  426. * the discriminant value and then searches the array of xdrdiscrims
  427. * looking for that value. It calls the procedure given in the xdrdiscrim
  428. * to handle the discriminant. If there is no specific routine a default
  429. * routine may be called.
  430. * If there is no specific or default routine an error is returned.
  431. */
  432. bool_t xdr_union(XDR* xdrs, enum_t* dscmp, char* unp, const struct xdr_discrim* choices, xdrproc_t dfault)
  433. {
  434. register enum_t dscm;
  435. /*
  436. * we deal with the discriminator; it's an enum
  437. */
  438. if (!xdr_enum(xdrs, dscmp)) {
  439. return (FALSE);
  440. }
  441. dscm = *dscmp;
  442. /*
  443. * search choices for a value that matches the discriminator.
  444. * if we find one, execute the xdr routine for that value.
  445. */
  446. for (; choices->proc != NULL_xdrproc_t; choices++) {
  447. if (choices->value == dscm)
  448. return ((*(choices->proc)) (xdrs, unp, LASTUNSIGNED));
  449. }
  450. /*
  451. * no match - execute the default xdr routine if there is one
  452. */
  453. return ((dfault == NULL_xdrproc_t) ? FALSE :
  454. (*dfault) (xdrs, unp, LASTUNSIGNED));
  455. }
  456. /*
  457. * Non-portable xdr primitives.
  458. * Care should be taken when moving these routines to new architectures.
  459. */
  460. /*
  461. * XDR null terminated ASCII strings
  462. * xdr_string deals with "C strings" - arrays of bytes that are
  463. * terminated by a NULL character. The parameter cpp references a
  464. * pointer to storage; If the pointer is null, then the necessary
  465. * storage is allocated. The last parameter is the max allowed length
  466. * of the string as specified by a protocol.
  467. */
  468. bool_t xdr_string(xdrs, cpp, maxsize)
  469. register XDR *xdrs;
  470. char **cpp;
  471. unsigned int maxsize;
  472. {
  473. register char *sp = *cpp; /* sp is the actual string pointer */
  474. unsigned int size;
  475. unsigned int nodesize;
  476. /*
  477. * first deal with the length since xdr strings are counted-strings
  478. */
  479. switch (xdrs->x_op) {
  480. case XDR_FREE:
  481. if (sp == NULL) {
  482. return (TRUE); /* already free */
  483. }
  484. /* fall through... */
  485. case XDR_ENCODE:
  486. size = strlen(sp);
  487. break;
  488. }
  489. if (!xdr_u_int(xdrs, &size)) {
  490. return (FALSE);
  491. }
  492. if (size > maxsize) {
  493. return (FALSE);
  494. }
  495. nodesize = size + 1;
  496. /*
  497. * now deal with the actual bytes
  498. */
  499. switch (xdrs->x_op) {
  500. case XDR_DECODE:
  501. if (nodesize == 0) {
  502. return (TRUE);
  503. }
  504. if (sp == NULL)
  505. *cpp = sp = (char *) rt_malloc(nodesize);
  506. if (sp == NULL) {
  507. rt_kprintf("xdr_string: out of memory\n");
  508. return (FALSE);
  509. }
  510. sp[size] = 0;
  511. /* fall into ... */
  512. case XDR_ENCODE:
  513. return (xdr_opaque(xdrs, sp, size));
  514. case XDR_FREE:
  515. rt_free(sp);
  516. *cpp = NULL;
  517. return (TRUE);
  518. }
  519. return (FALSE);
  520. }
  521. /*
  522. * Wrapper for xdr_string that can be called directly from
  523. * routines like clnt_call
  524. */
  525. bool_t xdr_wrapstring(xdrs, cpp)
  526. XDR *xdrs;
  527. char **cpp;
  528. {
  529. if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
  530. return (TRUE);
  531. }
  532. return (FALSE);
  533. }
  534. /*
  535. * XDR an array of arbitrary elements
  536. * *addrp is a pointer to the array, *sizep is the number of elements.
  537. * If addrp is NULL (*sizep * elsize) bytes are allocated.
  538. * elsize is the size (in bytes) of each element, and elproc is the
  539. * xdr procedure to call to handle each element of the array.
  540. */
  541. bool_t xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
  542. register XDR *xdrs;
  543. char* *addrp; /* array pointer */
  544. unsigned int *sizep; /* number of elements */
  545. unsigned int maxsize; /* max numberof elements */
  546. unsigned int elsize; /* size in bytes of each element */
  547. xdrproc_t elproc; /* xdr routine to handle each element */
  548. {
  549. register unsigned int i;
  550. register char* target = *addrp;
  551. register unsigned int c; /* the actual element count */
  552. register bool_t stat = TRUE;
  553. register unsigned int nodesize;
  554. /* like strings, arrays are really counted arrays */
  555. if (!xdr_u_int(xdrs, sizep)) {
  556. return (FALSE);
  557. }
  558. c = *sizep;
  559. if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
  560. return (FALSE);
  561. }
  562. /* duh, look for integer overflow (fefe) */
  563. {
  564. unsigned int i;
  565. nodesize = 0;
  566. for (i=c; i; --i) {
  567. unsigned int tmp=nodesize+elsize;
  568. if (tmp<nodesize) /* overflow */
  569. return FALSE;
  570. nodesize=tmp;
  571. }
  572. }
  573. /*
  574. * if we are deserializing, we may need to allocate an array.
  575. * We also save time by checking for a null array if we are freeing.
  576. */
  577. if (target == NULL)
  578. switch (xdrs->x_op) {
  579. case XDR_DECODE:
  580. if (c == 0)
  581. return (TRUE);
  582. *addrp = target = rt_malloc(nodesize);
  583. if (target == NULL) {
  584. rt_kprintf("xdr_array: out of memory\n");
  585. return (FALSE);
  586. }
  587. memset(target, 0, nodesize);
  588. break;
  589. case XDR_FREE:
  590. return (TRUE);
  591. }
  592. /*
  593. * now we xdr each element of array
  594. */
  595. for (i = 0; (i < c) && stat; i++) {
  596. stat = (*elproc) (xdrs, target, LASTUNSIGNED);
  597. target += elsize;
  598. }
  599. /*
  600. * the array may need freeing
  601. */
  602. if (xdrs->x_op == XDR_FREE) {
  603. rt_free(*addrp);
  604. *addrp = NULL;
  605. }
  606. return (stat);
  607. }
  608. /*
  609. * xdr_vector():
  610. *
  611. * XDR a fixed length array. Unlike variable-length arrays,
  612. * the storage of fixed length arrays is static and unfreeable.
  613. * > basep: base of the array
  614. * > size: size of the array
  615. * > elemsize: size of each element
  616. * > xdr_elem: routine to XDR each element
  617. */
  618. bool_t xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
  619. register XDR *xdrs;
  620. register char *basep;
  621. register unsigned int nelem;
  622. register unsigned int elemsize;
  623. register xdrproc_t xdr_elem;
  624. {
  625. register unsigned int i;
  626. register char *elptr;
  627. elptr = basep;
  628. for (i = 0; i < nelem; i++) {
  629. if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) {
  630. return (FALSE);
  631. }
  632. elptr += elemsize;
  633. }
  634. return (TRUE);
  635. }
  636. /*
  637. * XDR an indirect pointer
  638. * xdr_reference is for recursively translating a structure that is
  639. * referenced by a pointer inside the structure that is currently being
  640. * translated. pp references a pointer to storage. If *pp is null
  641. * the necessary storage is allocated.
  642. * size is the sizeof the referneced structure.
  643. * proc is the routine to handle the referenced structure.
  644. */
  645. bool_t xdr_reference(xdrs, pp, size, proc)
  646. register XDR *xdrs;
  647. char* *pp; /* the pointer to work on */
  648. unsigned int size; /* size of the object pointed to */
  649. xdrproc_t proc; /* xdr routine to handle the object */
  650. {
  651. register char* loc = *pp;
  652. register bool_t stat;
  653. if (loc == NULL)
  654. switch (xdrs->x_op) {
  655. case XDR_FREE:
  656. return (TRUE);
  657. case XDR_DECODE:
  658. *pp = loc = (char*) rt_malloc(size);
  659. if (loc == NULL) {
  660. rt_kprintf("xdr_reference: out of memory\n");
  661. return (FALSE);
  662. }
  663. memset(loc, 0, (int) size);
  664. break;
  665. }
  666. stat = (*proc) (xdrs, loc, LASTUNSIGNED);
  667. if (xdrs->x_op == XDR_FREE) {
  668. rt_free(loc);
  669. *pp = NULL;
  670. }
  671. return (stat);
  672. }
  673. /*
  674. * xdr_pointer():
  675. *
  676. * XDR a pointer to a possibly recursive data structure. This
  677. * differs with xdr_reference in that it can serialize/deserialiaze
  678. * trees correctly.
  679. *
  680. * What's sent is actually a union:
  681. *
  682. * union object_pointer switch (boolean b) {
  683. * case TRUE: object_data data;
  684. * case FALSE: void nothing;
  685. * }
  686. *
  687. * > objpp: Pointer to the pointer to the object.
  688. * > obj_size: size of the object.
  689. * > xdr_obj: routine to XDR an object.
  690. *
  691. */
  692. bool_t xdr_pointer(xdrs, objpp, obj_size, xdr_obj)
  693. register XDR *xdrs;
  694. char **objpp;
  695. unsigned int obj_size;
  696. xdrproc_t xdr_obj;
  697. {
  698. bool_t more_data;
  699. more_data = (*objpp != NULL);
  700. if (!xdr_bool(xdrs, &more_data)) {
  701. return (FALSE);
  702. }
  703. if (!more_data) {
  704. *objpp = NULL;
  705. return (TRUE);
  706. }
  707. return (xdr_reference(xdrs, objpp, obj_size, xdr_obj));
  708. }