08cab454b571a5f957d7e16243721b97af206a58
[openafs.git] / src / afs / afs_osi_uio.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "../afs/param.h"
12
13 RCSID("$Header$");
14
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* statistics */
18 #include "../afs/afs_cbqueue.h"
19 #include "../afs/nfsclient.h"
20 #include "../afs/afs_osidnlc.h"
21
22
23 /*
24  * UIO routines
25  */
26
27 /* routine to make copy of uio structure in ainuio, using aoutvec for space */
28 afsio_copy(ainuio, aoutuio, aoutvec)
29 struct uio *ainuio, *aoutuio;
30 register struct iovec *aoutvec; {
31     register int i;
32     register struct iovec *tvec;
33
34     AFS_STATCNT(afsio_copy);
35     if (ainuio->afsio_iovcnt > AFS_MAXIOVCNT) return EINVAL;
36     bcopy((char *)ainuio, (char *)aoutuio, sizeof(struct uio));
37     tvec = ainuio->afsio_iov;
38     aoutuio->afsio_iov = aoutvec;
39     for(i=0;i<ainuio->afsio_iovcnt;i++){
40         bcopy((char *)tvec, (char *)aoutvec, sizeof(struct iovec));
41         tvec++;     /* too many compiler bugs to do this as one expr */
42         aoutvec++;
43     }
44     return 0;
45 }
46
47 /* trim the uio structure to the specified size */
48 afsio_trim(auio, asize)
49 register struct uio *auio;
50 register afs_int32 asize; {
51     register int i;
52     register struct iovec *tv;
53
54     AFS_STATCNT(afsio_trim);
55     auio->afsio_resid = asize;
56     tv = auio->afsio_iov;
57     /* It isn't clear that multiple iovecs work ok (hasn't been tested!) */
58     for(i=0;;i++,tv++) {
59         if (i >= auio->afsio_iovcnt || asize <= 0) {
60             /* we're done */
61             auio->afsio_iovcnt = i;
62             break;
63         }
64         if (tv->iov_len <= asize)
65             /* entire iovec is included */
66             asize -= tv->iov_len;   /* this many fewer bytes */
67         else {
68             /* this is the last one */
69             tv->iov_len = asize;
70             auio->afsio_iovcnt = i+1;
71             break;
72         }
73     }
74     return 0;
75 }
76
77 /* skip asize bytes in the current uio structure */
78 afsio_skip(auio, asize)
79 register struct uio *auio;
80 register afs_int32 asize; {
81     register struct iovec *tv;  /* pointer to current iovec */
82     register int cnt;
83
84     AFS_STATCNT(afsio_skip);
85    /* It isn't guaranteed that multiple iovecs work ok (hasn't been tested!) */
86     while (asize > 0 && auio->afsio_resid) {
87         tv = auio->afsio_iov;
88         cnt = tv->iov_len;
89         if (cnt == 0) {
90             auio->afsio_iov++;
91             auio->afsio_iovcnt--;
92             continue;
93         }
94         if (cnt > asize)
95             cnt = asize;
96         tv->iov_base = (char *)(tv->iov_base) + cnt;
97         tv->iov_len -= cnt;
98         auio->uio_resid -= cnt;
99         auio->uio_offset += cnt;
100         asize -= cnt;
101     }
102     return 0;
103 }
104