Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / afs_osi_uio.c
CommitLineData
805e021f
CE
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
14#include "afs/sysincludes.h" /* Standard vendor system headers */
15#include "afsincludes.h" /* Afs-based standard headers */
16#include "afs/afs_stats.h" /* statistics */
17#include "afs/afs_cbqueue.h"
18#include "afs/nfsclient.h"
19#include "afs/afs_osidnlc.h"
20
21
22/*
23 * UIO routines
24 */
25
26#ifndef AFS_DARWIN80_ENV
27/* routine to make copy of uio structure in ainuio, using aoutvec for space */
28int
29afsio_copy(struct uio *ainuio, struct uio *aoutuio,
30 struct iovec *aoutvec)
31{
32 int i;
33 struct iovec *tvec;
34
35 AFS_STATCNT(afsio_copy);
36 if (ainuio->afsio_iovcnt > AFS_MAXIOVCNT)
37 return EINVAL;
38 memcpy((char *)aoutuio, (char *)ainuio, sizeof(struct uio));
39 tvec = ainuio->afsio_iov;
40 aoutuio->afsio_iov = aoutvec;
41 for (i = 0; i < ainuio->afsio_iovcnt; i++) {
42 memcpy((char *)aoutvec, (char *)tvec, sizeof(struct iovec));
43 tvec++; /* too many compiler bugs to do this as one expr */
44 aoutvec++;
45 }
46 return 0;
47}
48
49/* trim the uio structure to the specified size */
50int
51afsio_trim(struct uio *auio, afs_int32 asize)
52{
53 int i;
54 struct iovec *tv;
55
56 AFS_STATCNT(afsio_trim);
57 auio->afsio_resid = asize;
58 tv = auio->afsio_iov;
59 /* It isn't clear that multiple iovecs work ok (hasn't been tested!) */
60 for (i = 0;; i++, tv++) {
61 if (i >= auio->afsio_iovcnt || asize <= 0) {
62 /* we're done */
63 auio->afsio_iovcnt = i;
64 break;
65 }
66 if (tv->iov_len <= asize)
67 /* entire iovec is included */
68 asize -= tv->iov_len; /* this many fewer bytes */
69 else {
70 /* this is the last one */
71 tv->iov_len = asize;
72 auio->afsio_iovcnt = i + 1;
73 break;
74 }
75 }
76 return 0;
77}
78
79/* Allocate space for, then partially copy, over an existing iovec up to the
80 * length given in len.
81 *
82 * This requires that SmallSpace can alloc space big enough to hold a struct
83 * UIO, plus 16 iovecs
84 */
85
86struct uio *
87afsio_partialcopy(struct uio *auio, size_t len) {
88 char *space;
89 struct uio *newuio;
90 struct iovec *newvec;
91 size_t space_len = sizeof(struct uio) +
92 sizeof(struct iovec) * AFS_MAXIOVCNT;
93
94 /* Allocate a block that can contain both the UIO and the iovec */
95 space = osi_AllocSmallSpace(space_len);
96 memset(space, 0, space_len);
97
98 newuio = (struct uio *) space;
99 newvec = (struct iovec *) (space + sizeof(struct uio));
100
101 afsio_copy(auio, newuio, newvec);
102 afsio_trim(newuio, len);
103
104 return newuio;
105}
106
107void
108afsio_free(struct uio *uio) {
109 osi_FreeSmallSpace(uio);
110}
111#endif
112
113/* skip asize bytes in the current uio structure */
114int
115afsio_skip(struct uio *auio, afs_int32 asize)
116{
117 struct iovec *tv; /* pointer to current iovec */
118 int cnt;
119
120 AFS_STATCNT(afsio_skip);
121#ifdef AFS_DARWIN80_ENV
122 uio_update(auio, asize);
123#else
124 /* It isn't guaranteed that multiple iovecs work ok (hasn't been tested!) */
125 while (asize > 0 && auio->afsio_resid) {
126 tv = auio->afsio_iov;
127 cnt = tv->iov_len;
128 if (cnt == 0) {
129 auio->afsio_iov++;
130 auio->afsio_iovcnt--;
131 continue;
132 }
133 if (cnt > asize)
134 cnt = asize;
135 tv->iov_base = (char *)(tv->iov_base) + cnt;
136 tv->iov_len -= cnt;
137 auio->uio_resid -= cnt;
138 auio->afsio_offset += cnt;
139 asize -= cnt;
140 }
141#endif
142 return 0;
143}