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