78d412487154348b4b0ef161b5b4d73fa741b63d
[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 <afs/param.h>
28 #include <afs/afsint.h>
29 #include <afs/vlserver.h>
30 #include <afs/vldbint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include "afscp.h"
35 #include "afscp_internal.h"
36
37 ssize_t afs_pread(const struct afs_venusfid *fid, void *buffer, size_t count, off_t offset) {
38      struct AFSFetchStatus fst;
39      struct AFSVolSync vs;
40      struct AFSCallBack cb;
41      struct AFSFid tf = fid->fid;
42      struct afs_volume *vol;
43      struct afs_server *server;
44
45      struct rx_call *c=NULL;
46      int code,code2;
47      int i,j,bytes,totalbytes;
48      int bytesremaining;
49      char *p;
50
51      vol=afs_volumebyid(fid->cell, fid->fid.Volume);
52      if (!vol) {
53           afs_errno=ENOENT;
54           return -1;
55      }
56      code=ENOENT;
57      for (i=0;i<vol->nservers;i++) {
58           server=afs_serverbyindex(vol->servers[i]);
59           if (server && server->naddrs > 0) {
60                for (j=0;j < server->naddrs;j++) {
61                     c=rx_NewCall(server->conns[j]);
62                     if (c) {
63                          p=buffer;
64                          code=StartRXAFS_FetchData(c, &tf, offset, count);
65                          if (code) {
66                               code=rx_EndCall(c,code);
67                               continue;
68                          }
69                          bytes=rx_Read(c,(char *)&bytesremaining,sizeof(afs_int32));
70                          if (bytes != sizeof(afs_int32)) {
71                               code=rx_EndCall(c,bytes);
72                               continue;
73                          }
74                          bytesremaining=ntohl(bytesremaining);
75                          totalbytes=0;
76                          while (bytesremaining > 0) {
77                               bytes=rx_Read(c, p, bytesremaining);
78                               if (bytes <= 0)
79                                    break;
80                               p+=bytes;
81                               totalbytes+=bytes;
82                               bytesremaining-=bytes;
83                          }
84                          if (bytesremaining == 0) {
85                               code2=EndRXAFS_FetchData(c, &fst, &cb, &vs);
86                               if (code2 == 0)
87                                    AddCallBack(server, &fid->fid, &fst, &cb);
88                          }
89                          code=rx_EndCall(c, code2);
90                     }
91                     if (code == 0)
92                          return totalbytes;
93                }
94           }
95      }
96      afs_errno=code;
97      return -1;
98 }
99
100
101
102 ssize_t afs_pwrite(const struct afs_venusfid *fid, const void *buffer, size_t count, off_t offset) {
103
104      struct AFSFetchStatus fst;
105      struct AFSStoreStatus sst;
106      struct AFSVolSync vs;
107      struct AFSCallBack cb;
108      struct AFSFid tf=fid->fid;
109      struct afs_volume *vol;
110      struct afs_server *server;
111
112      struct rx_call *c=NULL;
113      int code,code2;
114      int i,j,bytes,totalbytes;
115      int bytesremaining;
116      const char *p;
117      size_t filesize;
118      time_t now;
119
120
121      vol=afs_volumebyid(fid->cell, fid->fid.Volume);
122      if (!vol) {
123           afs_errno=ENOENT;
124           return -1;
125      }
126      if (vol->voltype != VOLTYPE_RW) {
127           afs_errno = EROFS;
128           return -1;
129      }
130
131      code=ENOENT;
132      for (i=0;i<vol->nservers;i++) {
133           server=afs_serverbyindex(vol->servers[i]);
134           if (server && server->naddrs > 0) {
135                for (j=0;j < server->naddrs;j++) {
136                     code=RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs);
137                     if (code)
138                          continue;
139                     sst.Mask=AFS_SETMODTIME;
140                     time(&now);
141                     sst.ClientModTime = now;
142                     filesize=fst.Length;
143                     if (offset + count > filesize)
144                          filesize = offset + count;
145                     c=rx_NewCall(server->conns[j]);
146                     if (c) {
147                          p=buffer;
148                          code=StartRXAFS_StoreData(c, &tf, &sst, offset, count, filesize);
149                          if (code) {
150                               code=rx_EndCall(c,code);
151                               continue;
152                          }
153                          bytesremaining=htonl(count);
154                          bytes=rx_Write(c,(char *)&bytesremaining,sizeof(afs_int32));
155                          if (bytes != sizeof(afs_int32)) {
156                               code=rx_EndCall(c,bytes);
157                               continue;
158                          }
159                          bytesremaining=count;
160                          totalbytes=0;
161                          while (bytesremaining > 0) {
162                               bytes=rx_Write(c, (char *)p, bytesremaining);
163                               if (bytes <= 0)
164                                    break;
165                               p+=bytes;
166                               totalbytes+=bytes;
167                               bytesremaining-=bytes;
168                          }
169                          if (bytesremaining == 0) {
170                               code2=EndRXAFS_StoreData(c, &fst, &vs);
171                          }
172                          code=rx_EndCall(c, code2);
173                     }
174                     if (code == 0)
175                          return totalbytes;
176                }
177           }
178      }
179      afs_errno=code;
180      return -1;
181 }
182