xxdr.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
  2. See the COPYRIGHT file for more information. */
  3. /*
  4. * Copyright (c) 2009, Sun Microsystems, Inc.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * - Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * - Neither the name of Sun Microsystems, Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * from: @(#)xdr.h 1.19 87/04/22 SMI
  31. * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
  32. * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $
  33. * $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $
  34. */
  35. /* Define our own implementation of the needed
  36. elements of XDR. Assumes read-only
  37. */
  38. #undef XXDRTRACE
  39. #include "config.h"
  40. #include <stdlib.h>
  41. #include <stdio.h>
  42. #include <assert.h>
  43. #include <string.h>
  44. #include <stdarg.h>
  45. #ifdef HAVE_UNISTD_H
  46. #include <unistd.h>
  47. #endif
  48. #include "xxdr.h"
  49. int xxdr_network_order; /* network order is big endian */
  50. static int xxdr_big_endian; /* what is this machine? */
  51. #ifdef XXDRTRACE
  52. static void
  53. xxdrtrace(XXDR* xdr, char* where, off_t arg)
  54. {
  55. fprintf(stderr,"xxdr: %s: arg=%ld ; pos=%ld len=%ld\n",
  56. where,arg,(long)xdr->pos,(long)xdr->length);
  57. fflush(stderr);
  58. }
  59. #else
  60. #define xxdrtrace(x,y,z)
  61. #endif
  62. /* Read-only operations */
  63. int xxdr_getbytes(XXDR* xdrs, char* memory, off_t count)
  64. {
  65. if(!memory) return 0;
  66. if(!xdrs->getbytes(xdrs,memory,count))
  67. return 0;
  68. return 1;
  69. }
  70. /* get a unsigned int from underlying stream*/
  71. int
  72. xxdr_uint(XXDR* xdr, unsigned int* ip)
  73. {
  74. if(!ip) return 0;
  75. if(!xdr->getbytes(xdr,(char*)ip,sizeof(*ip)))
  76. return 0;
  77. /*convert from network order*/
  78. if(!xxdr_network_order) {
  79. swapinline32(ip);
  80. }
  81. return 1;
  82. }
  83. /* get a long long from underlying stream*/
  84. int
  85. xxdr_ulonglong(XXDR* xdr, unsigned long* llp)
  86. {
  87. /* Pull two units */
  88. if(!llp) return 0;
  89. if(!xdr->getbytes(xdr,(char*)llp,sizeof(*llp)))
  90. return 0;
  91. /* Convert to signed/unsigned */
  92. /*convert from network order*/
  93. if(!xxdr_network_order) {
  94. swapinline64(llp);
  95. }
  96. return 1;
  97. }
  98. /* get some bytes from underlying stream;
  99. will move xdrs pointer to next XDRUNIT boundary*/
  100. int
  101. xxdr_opaque(XXDR* xdr, char* mem, off_t count)
  102. {
  103. off_t pos,rounded;
  104. if(!xdr->getbytes(xdr,mem,count))
  105. return 0;
  106. pos = xxdr_getpos(xdr);
  107. rounded = RNDUP(pos);
  108. return xxdr_skip(xdr,(rounded - pos));
  109. }
  110. /* get counted string from underlying stream*/
  111. int
  112. xxdr_string(XXDR* xdrs, char** sp, off_t* lenp)
  113. {
  114. char* s;
  115. unsigned int len;
  116. if(!xxdr_uint(xdrs,&len)) return 0;
  117. s = (char*)malloc((off_t)len+1);
  118. if(s == NULL) return 0;
  119. if(!xxdr_opaque(xdrs,s,len)) {
  120. free((void*)s);
  121. return 0;
  122. }
  123. s[len] = '\0'; /* make sure it is null terminated */
  124. if(sp) *sp = s;
  125. if(lenp) *lenp = len;
  126. /* xxdr_opaque will have skippped any trailing bytes */
  127. return 1;
  128. }
  129. /* returns bytes off from beginning*/
  130. off_t
  131. xxdr_getpos(XXDR* xdr)
  132. {
  133. return xdr->getpos(xdr);
  134. }
  135. /* reposition the stream*/
  136. int
  137. xxdr_setpos(XXDR* xdr, off_t pos)
  138. {
  139. return xdr->setpos(xdr,pos);
  140. }
  141. /* returns total available starting at current position */
  142. off_t
  143. xxdr_getavail(XXDR* xdr)
  144. {
  145. return xdr->getavail(xdr);
  146. }
  147. /* free up XXDR structure */
  148. void
  149. xxdr_free(XXDR* xdr)
  150. {
  151. xdr->free(xdr);
  152. }
  153. /***********************************/
  154. /* Skip exacly "len" bytes in the input; any rounding must be done by the caller*/
  155. int
  156. xxdr_skip(XXDR* xdrs, off_t len)
  157. {
  158. unsigned int pos;
  159. pos = xxdr_getpos(xdrs);
  160. pos = (pos + len);
  161. if(pos < 0) pos = 0;
  162. return xxdr_setpos(xdrs,pos);
  163. }
  164. /* skip "n" string/bytestring instances in the input*/
  165. int
  166. xxdr_skip_strings(XXDR* xdrs, off_t n)
  167. {
  168. while(n-- > 0) {
  169. unsigned int slen;
  170. if(!xxdr_uint(xdrs,&slen)) return 0;
  171. slen = RNDUP(slen);
  172. if(xxdr_skip(xdrs,slen)) return 0;
  173. }
  174. return 1;
  175. }
  176. unsigned int
  177. xdr_roundup(unsigned int n)
  178. {
  179. unsigned int rounded;
  180. rounded = RNDUP(n);
  181. return rounded;
  182. }
  183. unsigned int
  184. ocbyteswap(unsigned int i)
  185. {
  186. unsigned int swap,b0,b1,b2,b3;
  187. b0 = (i>>24) & 0x000000ff;
  188. b1 = (i>>16) & 0x000000ff;
  189. b2 = (i>>8) & 0x000000ff;
  190. b3 = (i) & 0x000000ff;
  191. swap = (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
  192. return swap;
  193. }
  194. /**************************************************/
  195. /* File based xdr */
  196. static void
  197. xxdr_filefree(XXDR* xdrs)
  198. {
  199. if(xdrs != NULL) {
  200. (void)fflush((FILE *)xdrs->data);
  201. free(xdrs);
  202. }
  203. }
  204. static int
  205. xxdr_filegetbytes(XXDR* xdrs, char* addr, off_t len)
  206. {
  207. int ok = 1;
  208. int count;
  209. xxdrtrace(xdrs,"getbytes",len);
  210. if(len < 0) len = 0;
  211. if(!xdrs->valid)
  212. {
  213. if(fseek((FILE *)xdrs->data, xdrs->pos + xdrs->base, 0) != 0) {
  214. ok=0;
  215. goto done;
  216. }
  217. xdrs->valid = 1;
  218. }
  219. if(xdrs->pos + len > xdrs->length)
  220. return 0;
  221. if(len > 0) {
  222. count = fread(addr, len, 1, (FILE*)xdrs->data);
  223. if(count <= 0) {
  224. ok=0;
  225. goto done;
  226. }
  227. }
  228. xdrs->pos += len;
  229. done:
  230. return ok;
  231. }
  232. static off_t
  233. xxdr_filegetpos(XXDR* xdrs)
  234. {
  235. xxdrtrace(xdrs,"getpos",0);
  236. return xdrs->pos;
  237. }
  238. static off_t
  239. xxdr_filegetavail(XXDR* xdrs)
  240. {
  241. xxdrtrace(xdrs,"getavail",0);
  242. return (xdrs->length - xdrs->pos);
  243. }
  244. static int
  245. xxdr_filesetpos(XXDR* xdrs, off_t pos)
  246. {
  247. int ok = 1;
  248. xxdrtrace(xdrs,"setpos",pos);
  249. if(pos == xdrs->pos) goto done;
  250. if(pos < 0) pos = 0;
  251. if(pos > xdrs->length) {ok=0;goto done;}
  252. xdrs->pos = pos;
  253. xdrs->valid = 0;
  254. done:
  255. return ok;
  256. }
  257. /*
  258. Modified to track the current position to avoid the file io
  259. operation. Not sure if this worth the effort because I
  260. don't actually know the cost to doing an fseek
  261. */
  262. /*
  263. * Initialize a stdio xdr stream.
  264. * Sets the xdr stream handle xdrs for use on the stream file.
  265. * Operation flag is set to op.
  266. */
  267. XXDR*
  268. xxdr_filecreate(FILE* file, off_t base)
  269. {
  270. XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
  271. if(xdrs != NULL) {
  272. xdrs->data = (void*)file;
  273. xdrs->base = base;
  274. xdrs->pos = 0;
  275. xdrs->valid = 0;
  276. if(fseek(file,0L,SEEK_END)) return NULL;
  277. xdrs->length = (off_t)ftell(file);
  278. xdrs->length -= xdrs->base;
  279. xdrs->getbytes = xxdr_filegetbytes;
  280. xdrs->setpos = xxdr_filesetpos;
  281. xdrs->getpos = xxdr_filegetpos;
  282. xdrs->getavail = xxdr_filegetavail;
  283. xdrs->free = xxdr_filefree;
  284. }
  285. xxdrtrace(xdrs,"create",base);
  286. return xdrs;
  287. }
  288. /**************************************************/
  289. /* memory based xdr */
  290. static void
  291. xxdr_memfree(XXDR* xdrs)
  292. {
  293. if(xdrs != NULL) {
  294. free(xdrs);
  295. }
  296. }
  297. static int
  298. xxdr_memgetbytes(XXDR* xdrs, char* addr, off_t len)
  299. {
  300. int ok = 1;
  301. xxdrtrace(xdrs,"getbytes",len);
  302. if(len < 0) len = 0;
  303. if(xdrs->pos+len > xdrs->length) {ok=0; goto done;}
  304. if(len > 0) {
  305. memcpy(addr,(char*)xdrs->data+xdrs->base+xdrs->pos, len);
  306. }
  307. xdrs->pos += len;
  308. done:
  309. return ok;
  310. }
  311. static off_t
  312. xxdr_memgetpos(XXDR* xdrs)
  313. {
  314. xxdrtrace(xdrs,"getpos",0);
  315. return xdrs->pos;
  316. }
  317. static off_t
  318. xxdr_memgetavail(XXDR* xdrs)
  319. {
  320. xxdrtrace(xdrs,"getavail",0);
  321. return (xdrs->length - xdrs->pos);
  322. }
  323. static int
  324. xxdr_memsetpos(XXDR* xdrs, off_t pos)
  325. {
  326. int ok = 1;
  327. xxdrtrace(xdrs,"setpos",pos);
  328. if(pos == xdrs->pos) goto done;
  329. if(pos > xdrs->length) {ok=0; goto done;}
  330. xdrs->pos = pos;
  331. done:
  332. return ok;
  333. }
  334. /*
  335. Modified to track the current position to avoid the file io
  336. operation. Not sure if this worth the effort because I
  337. don't actually know the cost to doing an fseek
  338. */
  339. /*
  340. * Initialize a stdio xdr stream.
  341. * Sets the xdr stream handle xdrs for use on the
  342. * given memory starting at base offset.
  343. */
  344. XXDR*
  345. xxdr_memcreate(char* mem, off_t memsize, off_t base)
  346. {
  347. XXDR* xdrs = (XXDR*)calloc(1,sizeof(XXDR));
  348. if(xdrs != NULL) {
  349. /* zero base memory */
  350. xdrs->data = (void*)(mem + base);
  351. xdrs->base = 0;
  352. xdrs->length = memsize - base;
  353. xdrs->pos = 0;
  354. xdrs->getbytes = xxdr_memgetbytes;
  355. xdrs->setpos = xxdr_memsetpos;
  356. xdrs->getpos = xxdr_memgetpos;
  357. xdrs->getavail = xxdr_memgetavail;
  358. xdrs->free = xxdr_memfree;
  359. }
  360. xxdrtrace(xdrs,"create",base);
  361. return xdrs;
  362. }
  363. /* Float utility types */
  364. /* get a float from underlying stream*/
  365. int
  366. xxdr_float(XXDR* xdr, float* fp)
  367. {
  368. int status = 0;
  369. float f;
  370. unsigned int* data = (unsigned int*)&f;
  371. /* Pull one unit directly into a float */
  372. status = xxdr_uint(xdr,data);
  373. if(status && fp)
  374. *fp = f;
  375. return status;
  376. }
  377. /* Get a double from underlying stream */
  378. int
  379. xxdr_double(XXDR* xdr, double* dp)
  380. {
  381. int status = 0;
  382. char data[2*XDRUNIT];
  383. /* Pull two units */
  384. status = xxdr_opaque(xdr,data,2*XDRUNIT);
  385. if(status && dp) {
  386. xxdrntohdouble(data,dp);
  387. }
  388. return status;
  389. }
  390. /* Double needs special handling */
  391. void
  392. xxdrntohdouble(char* c8, double* dp)
  393. {
  394. unsigned int ii[2];
  395. memcpy(ii,c8,2*XDRUNIT);
  396. if(!xxdr_big_endian) {
  397. unsigned int tmp;
  398. /* reverse byte order */
  399. swapinline32(&ii[0]);
  400. swapinline32(&ii[1]);
  401. /* interchange ii[0] and ii[1] */
  402. tmp = ii[0];
  403. ii[0] = ii[1];
  404. ii[1] = tmp;
  405. }
  406. if(dp) *dp = *(double*)ii;
  407. }
  408. void
  409. xxdr_init()
  410. {
  411. /* Compute if we are same as network order v-a-v xdr */
  412. int testint = 0x00000001;
  413. char *byte = (char *)&testint;
  414. xxdr_big_endian = (byte[0] == 0 ? 1 : 0);
  415. xxdr_network_order = xxdr_big_endian;
  416. }