linux-dont-d-drop-in-revalidate-20010416
[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 "../afs/param.h"       /* Should be always first */
11 #include "../afs/sysincludes.h" /* Standard vendor system headers */
12 #include "../afs/afsincludes.h" /* Afs-based standard headers */
13 #include "../afs/afs_stats.h" /* statistics */
14 #include "../afs/afs_cbqueue.h"
15 #include "../afs/nfsclient.h"
16 #include "../afs/afs_osidnlc.h"
17
18
19 /*
20  * UIO routines
21  */
22
23 /* routine to make copy of uio structure in ainuio, using aoutvec for space */
24 afsio_copy(ainuio, aoutuio, aoutvec)
25 struct uio *ainuio, *aoutuio;
26 register struct iovec *aoutvec; {
27     register int i;
28     register struct iovec *tvec;
29
30     AFS_STATCNT(afsio_copy);
31     if (ainuio->afsio_iovcnt > AFS_MAXIOVCNT) return EINVAL;
32     bcopy((char *)ainuio, (char *)aoutuio, sizeof(struct uio));
33     tvec = ainuio->afsio_iov;
34     aoutuio->afsio_iov = aoutvec;
35     for(i=0;i<ainuio->afsio_iovcnt;i++){
36         bcopy((char *)tvec, (char *)aoutvec, sizeof(struct iovec));
37         tvec++;     /* too many compiler bugs to do this as one expr */
38         aoutvec++;
39     }
40     return 0;
41 }
42
43 /* trim the uio structure to the specified size */
44 afsio_trim(auio, asize)
45 register struct uio *auio;
46 register afs_int32 asize; {
47     register int i;
48     register struct iovec *tv;
49
50     AFS_STATCNT(afsio_trim);
51     auio->afsio_resid = asize;
52     tv = auio->afsio_iov;
53     /* It isn't clear that multiple iovecs work ok (hasn't been tested!) */
54     for(i=0;;i++,tv++) {
55         if (i >= auio->afsio_iovcnt || asize <= 0) {
56             /* we're done */
57             auio->afsio_iovcnt = i;
58             break;
59         }
60         if (tv->iov_len <= asize)
61             /* entire iovec is included */
62             asize -= tv->iov_len;   /* this many fewer bytes */
63         else {
64             /* this is the last one */
65             tv->iov_len = asize;
66             auio->afsio_iovcnt = i+1;
67             break;
68         }
69     }
70     return 0;
71 }
72
73 /* skip asize bytes in the current uio structure */
74 afsio_skip(auio, asize)
75 register struct uio *auio;
76 register afs_int32 asize; {
77     register struct iovec *tv;  /* pointer to current iovec */
78     register int cnt;
79
80     AFS_STATCNT(afsio_skip);
81    /* It isn't guaranteed that multiple iovecs work ok (hasn't been tested!) */
82     while (asize > 0 && auio->afsio_resid) {
83         tv = auio->afsio_iov;
84         cnt = tv->iov_len;
85         if (cnt == 0) {
86             auio->afsio_iov++;
87             auio->afsio_iovcnt--;
88             continue;
89         }
90         if (cnt > asize)
91             cnt = asize;
92         tv->iov_base = (char *)(tv->iov_base) + cnt;
93         tv->iov_len -= cnt;
94         auio->uio_resid -= cnt;
95         auio->uio_offset += cnt;
96         asize -= cnt;
97     }
98     return 0;
99 }
100