1
0

xdr.c 17 KB

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