source: rtems/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c @ 6b2c3f11

4.104.115
Last change on this file since 6b2c3f11 was 6b2c3f11, checked in by Ralf Corsepius <ralf.corsepius@…>, on 05/29/10 at 04:30:47

2010-05-29 Ralf Corsépius <ralf.corsepius@…>

  • libfs/src/nfsclient/src/xdr_mbuf.c (xdrmbuf_setup): Cast addr to uintptr_t instead of size_t.
  • Property mode set to 100644
File size: 11.2 KB
Line 
1/* $Id$ */
2
3/* xdr_mbuf is derived from xdr_mem */
4
5/* Author (mbuf specifica): Till Straumann <strauman@slac.stanford.edu>, 10/2002 */
6
7/*
8 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
9 * unrestricted use provided that this legend is included on all tape
10 * media and as a part of the software program in whole or part.  Users
11 * may copy or modify Sun RPC without charge, but are not authorized
12 * to license or distribute it to anyone else except as part of a product or
13 * program developed by the user.
14 *
15 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
16 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
18 *
19 * Sun RPC is provided with no support and without any obligation on the
20 * part of Sun Microsystems, Inc. to assist in its use, correction,
21 * modification or enhancement.
22 *
23 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
24 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
25 * OR ANY PART THEREOF.
26 *
27 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
28 * or profits or other special, indirect and consequential damages, even if
29 * Sun has been advised of the possibility of such damages.
30 *
31 * Sun Microsystems, Inc.
32 * 2550 Garcia Avenue
33 * Mountain View, California  94043
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
38/*static char *sccsid = "from: @(#)xdr_mem.c    2.1 88/07/29 4.0 RPCSRC";*/
39static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
40#endif
41
42/*
43 * xdr_mbuf,  XDR implementation using mbuf buffers
44 *
45 * derived from:
46 *
47 * xdr_mem.h, XDR implementation using memory buffers.
48 *
49 * Copyright (C) 1984, Sun Microsystems, Inc.
50 *
51 * The MBUF stream is useful for BSDNET kernel (or RTEMS for that matter)
52 * use.
53 */
54
55#if HAVE_CONFIG_H
56#include "config.h"
57#endif
58
59#include <string.h>
60#include <rpc/types.h>
61#include <rpc/xdr.h>
62#include <netinet/in.h>
63
64#include <stdlib.h>
65
66#define TODO
67
68/* TODO remove: a hack because malloc is redefined */
69#ifdef TODO
70static inline void *
71my_malloc(size_t i)
72{
73        return malloc(i);
74}
75
76static inline void
77my_free(void *p)
78{
79        return free(p);
80}
81#endif
82
83#define DEBUG_ASSERT    (1<<0)
84#define DEBUG_VERB              (1<<1)
85
86#define DEBUG                   DEBUG_ASSERT
87
88#define _KERNEL
89#include <sys/mbuf.h>
90
91#include <assert.h>
92
93#if DEBUG & DEBUG_VERB || defined(TODO)
94#include <stdio.h>
95#endif
96
97static bool_t   xdrmbuf_getlong_aligned(XDR *xdrs, long *lp);
98static bool_t   xdrmbuf_putlong_aligned(XDR *xdrs, const long *lp);
99static bool_t   xdrmbuf_getlong_unaligned(XDR *xdrs, long *lp);
100static bool_t   xdrmbuf_putlong_unaligned(XDR *xdrs, const long *lp);
101static bool_t   xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len);
102static bool_t   xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len);
103static u_int    xdrmbuf_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */
104static bool_t   xdrmbuf_setpos(XDR *xdrs, u_int pos);
105static int32_t *xdrmbuf_inline_aligned(XDR *xdrs, u_int len);
106static int32_t *xdrmbuf_inline_unaligned(XDR *xdrs, u_int len);
107static void     xdrmbuf_destroy(XDR *);
108
109static struct   xdr_ops xdrmbuf_ops_aligned = {
110        xdrmbuf_getlong_aligned,
111        xdrmbuf_putlong_aligned,
112        xdrmbuf_getbytes,
113        xdrmbuf_putbytes,
114        xdrmbuf_getpos,
115        xdrmbuf_setpos,
116        xdrmbuf_inline_aligned,
117        xdrmbuf_destroy
118};
119
120static struct   xdr_ops xdrmbuf_ops_unaligned = {
121        xdrmbuf_getlong_unaligned,
122        xdrmbuf_putlong_unaligned,
123        xdrmbuf_getbytes,
124        xdrmbuf_putbytes,
125        xdrmbuf_getpos,
126        xdrmbuf_setpos,
127        xdrmbuf_inline_unaligned,
128        xdrmbuf_destroy
129};
130
131typedef struct MBPrivateRec_ {
132        struct mbuf             *mchain;
133        struct mbuf             *mcurrent;
134        u_int                   pos;            /* number of bytes contained in all MUBFS ahead
135                                                                 * of mcurrent
136                                                                 */
137} MBPrivateRec, *MBPrivate;
138
139/* NOTE: the stream position helper 'pos'
140 *       must be managed by the caller!
141 */
142static inline void
143xdrmbuf_setup(XDR *xdrs, struct mbuf *m)
144{
145MBPrivate       mbp = (MBPrivate)xdrs->x_base;
146
147                mbp->mcurrent    = m;
148                xdrs->x_private  = mtod(m,caddr_t);
149                xdrs->x_handy    = m->m_len;
150                xdrs->x_ops      = ((uintptr_t)xdrs->x_private & (sizeof(int32_t) - 1))
151                                                                ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
152}
153
154static struct mbuf *
155xdrmbuf_next(XDR *xdrs)
156{
157struct mbuf             *rval;
158MBPrivate               mbp = (MBPrivate)xdrs->x_base;
159
160        if (mbp->mcurrent) {
161                mbp->pos += mbp->mcurrent->m_len;
162                rval      = mbp->mcurrent->m_next;
163        } else {
164                rval      = 0;
165        }
166
167        if (rval) {
168                xdrmbuf_setup(xdrs, rval);
169        }
170#if DEBUG & DEBUG_VERB
171        else {
172                fprintf(stderr,"xdrmbuf: end of chain\n");
173        }
174#endif
175
176        return rval;
177}
178
179/*
180 * The procedure xdrmbuf_create initializes a stream descriptor for a
181 * memory buffer.
182 */
183void
184xdrmbuf_create(XDR *xdrs, struct mbuf *mbuf, enum xdr_op op)
185{
186MBPrivate mbp;
187
188        xdrs->x_op = op;
189        assert( mbp = (MBPrivate)my_malloc(sizeof(*mbp)) );
190        xdrs->x_base  = (caddr_t) mbp;
191
192        mbp->mchain   = mbuf;
193        mbp->pos      = 0;
194
195#if DEBUG & DEBUG_VERB
196        {
197        struct mbuf *mbf;
198        fprintf(stderr,"Dumping chain:\n");
199        for (mbf = mbuf; mbf; mbf=mbf->m_next) {
200                int ii;
201                fprintf(stderr,"MBUF------------");
202                for (ii=0; ii<mbf->m_len; ii++) {
203                        fprintf(stderr,"%02x ",mtod(mbf,char*)[ii]);
204                        if (ii%16==0)
205                                fputc('\n',stderr);
206                }
207                fputc('\n',stderr);
208        }
209        }
210#endif
211
212        xdrmbuf_setup(xdrs, mbuf);
213}
214
215static void
216xdrmbuf_destroy(XDR *xdrs)
217{
218MBPrivate       mbp = (MBPrivate)xdrs->x_base;
219#if 0 /* leave destroying the chain to the user */
220struct mbuf *m = mbp->mchain;
221
222        rtems_bsdnet_semaphore_obtain();
223                m_freem(m);
224        rtems_bsdnet_semaphore_release();
225#endif
226
227        my_free(mbp);
228}
229
230static bool_t
231xdrmbuf_getlong_aligned(register XDR *xdrs, register long *lp)
232{
233        while ( (signed int)(xdrs->x_handy -= sizeof(int32_t)) < 0) {
234                if ((xdrs->x_handy += sizeof(int32_t)) == 0) {
235                        /* handy was 0 on entry; request a new buffer.
236                         * Coded this way, so the most frequently executed
237                         * path needs only one comparison...
238                         */
239                        if (!xdrmbuf_next(xdrs))
240                                return FALSE;
241                } else {
242                        /* uh-oh an aligned long spread over two MBUFS ??
243                         * let the unaligned handler deal with this rare
244                         * situation.
245                         */
246                        return xdrmbuf_getlong_unaligned(xdrs,lp);
247                }
248        }
249        *lp = ntohl(*(int32_t *)(xdrs->x_private));
250        xdrs->x_private += sizeof(int32_t);
251#if DEBUG & DEBUG_VERB
252        fprintf(stderr,"Got aligned long %x\n",*lp);
253#endif
254        return (TRUE);
255}
256
257static bool_t
258xdrmbuf_putlong_aligned(
259        XDR *xdrs,
260        const long *lp)
261{
262fprintf(stderr,"TODO: xdrmbuf_putlong_aligned() is unimplemented\n");
263        return FALSE;
264#if 0
265        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
266                return (FALSE);
267        *(int32_t *)xdrs->x_private = htonl(*lp);
268        xdrs->x_private += sizeof(int32_t);
269        return (TRUE);
270#endif
271}
272
273static bool_t
274xdrmbuf_getlong_unaligned(
275        XDR *xdrs,
276        long *lp)
277{
278union {
279        int32_t l;
280        char    c[sizeof(int32_t)];
281}       u;
282
283register int  i,j;
284register char *cp,*sp;
285
286        i = xdrs->x_handy - sizeof(int32_t);
287
288        /* handle the most common case first */
289        if ( i >= 0 ) {
290
291                xdrs->x_handy   = i;
292                sp                          = (char*)xdrs->x_private;
293                xdrs->x_private = sp + sizeof(int32_t);
294
295#ifdef CANDO_UNALIGNED
296                {
297                        *lp              = ntohl(*(int32_t *)sp);
298#        if DEBUG & DEBUG_VERB
299                        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
300#        endif
301                        return TRUE;
302                }
303#else   /* machine can't do unaligned access */
304                {
305                        u.c[0]          = *sp;
306                        u.c[1]          = *++sp;
307                        u.c[2]          = *++sp;
308                        u.c[3]          = *++sp;
309
310                        goto done;
311                }
312#endif /* CANDO_UNALIGNED */
313        }
314
315        /* here the messy 'crossing buffers' business starts */
316
317
318        j  = sizeof(int32_t);
319
320        cp = u.c-1;
321
322        /* NOTE: on entry to this section,  handy < j holds */
323        do {
324                sp = ((char*)xdrs->x_private)-1;
325
326                if ( (i=xdrs->x_handy) >= j ) {
327                        /* more data in the buffer than we need:
328                         * copy everything we need and goto 'done'
329                         */
330                        xdrs->x_handy    = i-j;
331                        do {
332                                *++cp = *++sp;
333                        } while (--j > 0);
334                        xdrs->x_private  = (caddr_t)++sp;
335
336                        goto done;
337
338                } else {
339                        /* not enough data - copy as much as possible
340                         * then get retrieve the next MBUF and start
341                         * over
342                         */
343                        j-=i;
344                        while (i--)
345                                *++cp = *++sp;
346                        if (!xdrmbuf_next(xdrs))
347                                return FALSE;
348#if DEBUG & DEBUG_VERB
349                        fprintf(stderr,"getlong_unaligned: crossed mbuf boundary\n");
350#endif
351                }
352        } while (j > 0);
353
354done:
355
356        *lp = ntohl(u.l);
357
358#if DEBUG & DEBUG_VERB
359        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
360#endif
361        return (TRUE);
362}
363
364static bool_t
365xdrmbuf_putlong_unaligned(
366        XDR *xdrs,
367        const long *lp )
368{
369
370        fprintf(stderr,"TODO: xdrmbuf_putlong_unaligned() is unimplemented\n");
371        return FALSE;
372#if 0
373        {
374        int32_t l;
375
376        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
377                return (FALSE);
378        l = htonl(*lp);
379        memcpy(xdrs->x_private, &l, sizeof(int32_t));
380        xdrs->x_private += sizeof(int32_t);
381        return (TRUE);
382        }
383#endif
384}
385
386static bool_t
387xdrmbuf_getbytes(
388        XDR *xdrs,
389        caddr_t addr,
390        u_int len)
391{
392#if DEBUG & DEBUG_VERB
393int     olen=len,bufs=0;
394#endif
395
396#if DEBUG & DEBUG_VERB
397        fprintf(stderr,"wanting %i bytes (have %i)\n",olen,xdrs->x_handy);
398#endif
399
400        while (len>0) {
401                if (xdrs->x_handy >= len) {
402                        memcpy(addr, xdrs->x_private, len);
403                        xdrs->x_private += len;
404                        xdrs->x_handy   -= len;
405#if 0 /* save a couple of instructions */
406                        len = 0;
407#else
408                        goto done;
409#endif
410                } else {
411                        if (xdrs->x_handy > 0) {
412                                memcpy(addr, xdrs->x_private, xdrs->x_handy);
413                                len  -= xdrs->x_handy;
414                                addr += xdrs->x_handy;
415                        }
416                        if (!xdrmbuf_next(xdrs))
417                                return FALSE;
418#if DEBUG & DEBUG_VERB
419                        bufs++;
420#endif
421                }
422        }
423done:
424#if DEBUG & DEBUG_VERB
425        fprintf(stderr,"Got %i bytes (out of %i mbufs)\n",olen,bufs);
426#endif
427        return (TRUE);
428}
429
430static bool_t
431xdrmbuf_putbytes(
432        XDR *xdrs,
433        const char *addr,
434        u_int len )
435{
436
437        fprintf(stderr,"TODO: xdrmbuf_putbytes() is unimplemented\n");
438        return FALSE;
439#if 0
440        if ((xdrs->x_handy -= len) < 0)
441                return (FALSE);
442        memcpy(xdrs->x_private, addr, len);
443        xdrs->x_private += len;
444        return (TRUE);
445#endif
446}
447
448static u_int
449xdrmbuf_getpos(
450        XDR *xdrs)
451{
452#if 1
453MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
454struct mbuf *m   = mbp->mcurrent;
455u_int       rval = mbp->pos;
456
457        if (m) {
458                rval += xdrs->x_private - mtod(m, void*);
459        }
460#else
461struct mbuf *m;
462u_int           rval = 0;
463MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
464
465        for ( m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next )
466                rval += m->m_len;
467        if (m) {
468                rval += (u_long)xdrs->x_private - mtod(m, u_long);
469        }
470
471#endif
472        return rval;
473}
474
475static bool_t
476xdrmbuf_setpos(
477        XDR *xdrs,
478        u_int pos)
479{
480struct          mbuf *m;
481MBPrivate       mbp   = (MBPrivate)xdrs->x_base;
482
483        if (pos >= mbp->pos) {
484                pos      -= mbp->pos;
485                m         = mbp->mcurrent;
486        } else {
487                m         = mbp->mchain;
488                mbp->pos  = 0;
489        }
490
491        while ( m && pos >= m->m_len ) {
492                pos      -= m->m_len;
493                mbp->pos += m->m_len;
494                m         = m->m_next;
495        }
496
497        if (m) {
498                xdrmbuf_setup(xdrs, m);
499                xdrs->x_private += pos;
500                return TRUE;
501        }
502
503        return 0 == pos ? TRUE : FALSE;
504}
505
506static int32_t *
507xdrmbuf_inline_aligned(
508        XDR *xdrs,
509        u_int len)
510{
511int32_t *buf = 0;
512
513        if (xdrs->x_handy == 0 && !xdrmbuf_next(xdrs))
514                return 0;
515
516        if (xdrs->x_handy >= len) {
517                xdrs->x_handy -= len;
518                buf = (int32_t *) xdrs->x_private;
519                xdrs->x_private += len;
520#if DEBUG & DEBUG_VERB
521                fprintf(stderr,"Got %i aligned inline bytes at %x\n", len, buf);
522#endif
523        }
524#if DEBUG & DEBUG_VERB
525        else {
526                fprintf(stderr,"Skipped %i aligned inline bytes\n",len);
527        }
528#endif
529        return (buf);
530}
531
532static int32_t *
533xdrmbuf_inline_unaligned(
534        XDR *xdrs,
535        u_int len )
536{
537        return (0);
538}
Note: See TracBrowser for help on using the repository browser.