b887c5ac470a901616981ff96c6da5737c2267bc
[openafs.git] / src / libafscp / afscp_file.c
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <afsconfig.h>
28 #include <afs/param.h>
29
30 #include <roken.h>
31
32 #include <afs/vlserver.h>
33 #include <afs/vldbint.h>
34 #include "afscp.h"
35 #include "afscp_internal.h"
36
37 /* this is not yet 64-bit clean */
38 ssize_t
39 afscp_PRead(const struct afscp_venusfid * fid, void *buffer,
40             size_t count, off_t offset)
41 {
42     struct AFSFetchStatus fst;
43     struct AFSVolSync vs;
44     struct AFSCallBack cb;
45     struct AFSFid tf = fid->fid;
46     struct afscp_volume *vol;
47     struct afscp_server *server;
48     struct rx_call *c = NULL;
49     int code;
50     int i, j, bytes, totalbytes = 0;
51     int bytesremaining;
52     char *p;
53     time_t now;
54
55     vol = afscp_VolumeById(fid->cell, fid->fid.Volume);
56     if (vol == NULL) {
57         afscp_errno = ENOENT;
58         return -1;
59     }
60     code = ENOENT;
61     for (i = 0; i < vol->nservers; i++) {
62         server = afscp_ServerByIndex(vol->servers[i]);
63         if (server && server->naddrs > 0) {
64             for (j = 0; j < server->naddrs; j++) {
65                 c = rx_NewCall(server->conns[j]);
66                 if (c != 0) {
67                     p = buffer;
68                     code = StartRXAFS_FetchData(c, &tf, offset, count);
69                     if (code != 0) {
70                         code = rx_EndCall(c, code);
71                         continue;
72                     }
73                     bytes =
74                         rx_Read(c, (char *)&bytesremaining,
75                                 sizeof(afs_int32));
76                     if (bytes != sizeof(afs_int32)) {
77                         code = rx_EndCall(c, RX_PROTOCOL_ERROR);
78                         continue;
79                     }
80                     bytesremaining = ntohl(bytesremaining);
81                     totalbytes = 0;
82                     while (bytesremaining > 0) {
83                         bytes = rx_Read(c, p, bytesremaining);
84                         if (bytes <= 0)
85                             break;
86                         p += bytes;
87                         totalbytes += bytes;
88                         bytesremaining -= bytes;
89                     }
90                     if (bytesremaining == 0) {
91                         time(&now);
92                         code = EndRXAFS_FetchData(c, &fst, &cb, &vs);
93                         if (code == 0)
94                             afscp_AddCallBack(server, &fid->fid, &fst, &cb,
95                                               now);
96                     }
97                     code = rx_EndCall(c, code);
98                 }
99                 if (code == 0) {
100                     return totalbytes;
101                 }
102             }
103         }
104     }
105     afscp_errno = code;
106     return -1;
107 }
108
109 /* this is not yet 64-bit clean */
110 ssize_t
111 afscp_PWrite(const struct afscp_venusfid * fid, const void *buffer,
112              size_t count, off_t offset)
113 {
114     struct AFSFetchStatus fst;
115     struct AFSStoreStatus sst;
116     struct AFSVolSync vs;
117     struct AFSCallBack cb;
118     struct AFSFid tf = fid->fid;
119     struct afscp_volume *vol;
120     struct afscp_server *server;
121     struct rx_call *c = NULL;
122     int code;
123     int i, j, bytes, totalbytes = 0;
124     int bytesremaining;
125     const char *p;
126     off_t filesize;
127     time_t now;
128
129     vol = afscp_VolumeById(fid->cell, fid->fid.Volume);
130     if (vol == NULL) {
131         afscp_errno = ENOENT;
132         return -1;
133     }
134     if (vol->voltype != RWVOL) {
135         afscp_errno = EROFS;
136         return -1;
137     }
138
139     code = ENOENT;
140     for (i = 0; i < vol->nservers; i++) {
141         server = afscp_ServerByIndex(vol->servers[i]);
142         if (server && server->naddrs > 0) {
143             for (j = 0; j < server->naddrs; j++) {
144                 code =
145                     RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs);
146                 if (code != 0)
147                     continue;
148                 sst.Mask = AFS_SETMODTIME;
149                 time(&now);
150                 sst.ClientModTime = now;
151                 filesize = fst.Length;
152                 if (offset + count > filesize)
153                     filesize = offset + count;
154                 c = rx_NewCall(server->conns[j]);
155                 if (c != 0) {
156                     p = buffer;
157                     code =
158                         StartRXAFS_StoreData(c, &tf, &sst, offset, count,
159                                              filesize);
160                     if (code != 0) {
161                         code = rx_EndCall(c, code);
162                         continue;
163                     }
164                     /*
165                      * seems to write file length to beginning of file -- why?
166                      */
167                     /*
168                      * bytesremaining = htonl(count);
169                      * bytes = rx_Write(c, (char *)&bytesremaining,
170                      *                  sizeof(afs_int32));
171                      * if (bytes != sizeof(afs_int32)) {
172                      *  code = rx_EndCall(c, bytes);
173                      *  continue;
174                      * }
175                      */
176                     bytesremaining = count;
177                     totalbytes = 0;
178                     while (bytesremaining > 0) {
179                         bytes = rx_Write(c, (char *)p, bytesremaining);
180                         if (bytes <= 0)
181                             break;
182                         p += bytes;
183                         totalbytes += bytes;
184                         bytesremaining -= bytes;
185                     }
186                     if (bytesremaining == 0) {
187                         code = EndRXAFS_StoreData(c, &fst, &vs);
188                     }
189                     code = rx_EndCall(c, code);
190                 }
191                 if (code == 0) {
192                     return totalbytes;
193                 }
194             }
195         }
196     }
197     afscp_errno = code;
198     return -1;
199 }