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


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed